diff --git a/zenno/src/lib/umadump/talk.ts b/zenno/src/lib/umadump/talk.ts new file mode 100644 index 0000000..8ae6594 --- /dev/null +++ b/zenno/src/lib/umadump/talk.ts @@ -0,0 +1,14 @@ +import * as z from 'zod'; + +const Entry = z.strictObject({ + home_story_trigger_id: z.int32(), + new_flag: z.literal(0).or(z.literal(1)), +}); + +export type Entry = z.infer; + +export const Gallery = z.object({ + talk_gallery_list: z.array(Entry), +}); + +export type Gallery = z.infer; diff --git a/zenno/src/routes/chara/convo/+page.svelte b/zenno/src/routes/chara/convo/+page.svelte index 57440b4..66049f0 100644 --- a/zenno/src/routes/chara/convo/+page.svelte +++ b/zenno/src/routes/chara/convo/+page.svelte @@ -9,25 +9,51 @@ requiredCharas, convoCharas, } from '$lib/data/convo'; + import * as talk from '$lib/umadump/talk'; import CharaPick from '$lib/CharaPick.svelte'; import { onMount } from 'svelte'; import CharaIcon from '$lib/CharaIcon.svelte'; + import { SvelteSet } from 'svelte/reactivity'; - let conversations: Conversation[] = $state([]); - const convoMap = $derived(byChara(conversations)); - const popular = $derived(groupPopulars(conversations)); + let allConvos: Conversation[] = $state([]); + const popular = $derived(groupPopulars(allConvos)); let characters: Character[] = $state([]); - const selCharas = $derived(characters.filter((c) => convoMap.has(c.chara_id))); const names = $derived(charaNames(characters)); const minSuggest = 8; onMount(async () => { - [conversations, characters] = await Promise.all([conversation(), character()]); + [allConvos, characters] = await Promise.all([conversation(), character()]); }); let chara: Character | undefined = $state(); let convo = $state(1); + let talkFiles: FileList | undefined = $state(); + let readIDs = new SvelteSet(); + let talkFileInvalid = $state(false); + async function setRead(f: FileList) { + talkFiles = f; + readIDs.clear(); + talkFileInvalid = false; + if (talkFiles == null || talkFiles.length === 0) { + return; + } + const t = await talkFiles[0].text(); + const d = JSON.parse(t); + const g = talk.Gallery.safeDecode(d); + if (!g.success) { + talkFileInvalid = true; + console.warn(g.error); + return; + } + for (const e of g.data.talk_gallery_list) { + readIDs.add(e.home_story_trigger_id); + } + } + const conversations = $derived(allConvos.filter((c) => !readIDs.has(c.id))); + const convoMap = $derived(byChara(conversations)); + const selCharas = $derived(characters.filter((c) => convoMap.has(c.chara_id))); + const options = $derived(convoMap.get(chara?.chara_id ?? 0) ?? []); const cur = $derived(options.find((c) => c.number === convo)); const charaIDs = $derived(cur != null ? convoCharas(cur) : []); @@ -47,12 +73,12 @@

Lobby Conversations

-
-
+
+
-
+
+
+ + talkFiles ?? new DataTransfer().files, setRead} + /> + +
+ {#if talkFileInvalid} +
Invalid File
+ {/if}
{#if cur}