Mercurial
annotate mrjunejune/src/jrpg/jrpg.js @ 263:ee04e4e69fed
Add functional JRPG frame and tools
Add full-screen background_2 apertures, functional frame chrome, card-driven details, dual-window tools, live conversion workflows, and bounded cleanup for generated downloads.
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <mrjunejune@users.noreply.github.com> |
|---|---|
| date | Thu, 06 Aug 2026 11:31:30 -0700 |
| parents | 0f45474c1b1a |
| children | 04fee26ecce0 |
| rev | line source |
|---|---|
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1 const CHARACTER_STATES = Object.freeze({ |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
2 default: { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
3 alt: "Epi the Shiba Inu standing happily", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
4 src: "/public/jrpg/shiba-default.webp", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
5 }, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
6 sad: { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
7 alt: "Epi the Shiba Inu sitting sadly", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
8 src: "/public/jrpg/shiba-sad.webp", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
9 }, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
10 thinking: { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
11 alt: "Epi the Shiba Inu tilting her head in thought", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
12 src: "/public/jrpg/shiba-thinking.webp", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
13 }, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
14 }); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
15 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
16 const PREVIEWS = Object.freeze({ |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
17 resume: { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
18 copy: "Experience, projects, and the systems I have helped build.", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
19 kicker: "CHARACTER RECORD", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
20 title: "Resume", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
21 url: "/resume", |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
22 works: [ |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
23 { |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
24 detail: "Career dossier", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
25 label: "Full resume", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
26 modal: "resume", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
27 url: "/resume", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
28 }, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
29 { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
30 detail: "Agentic execution", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
31 label: "Copilot Tasks", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
32 url: "https://www.microsoft.com/en-us/microsoft-copilot/blog/2026/02/26/copilot-tasks-from-answers-to-actions/", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
33 }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
34 { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
35 detail: "AI platform", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
36 label: "Copilot SuperApp", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
37 url: "https://www.cio.com/article/3977098/microsoft-doubles-down-on-multi-model-ai-as-it-builds-a-copilot-super-app.html", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
38 }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
39 { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
40 detail: "Build 2026", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
41 label: "Code", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
42 url: "https://news.microsoft.com/build-2026/", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
43 }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
44 { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
45 detail: "Personal agent", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
46 label: "Autopilot", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
47 url: "https://www.microsoft.com/en-us/microsoft-365/blog/2026/06/02/introducing-microsoft-scout-your-always-on-personal-agent/", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
48 }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
49 { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
50 detail: "Ads systems", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
51 label: "Meta", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
52 url: "https://www.meta.com/", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
53 }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
54 { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
55 detail: "Workspace platform", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
56 label: "Google", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
57 url: "https://www.google.com/", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
58 }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
59 ], |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
60 }, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
61 tools: { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
62 copy: "Small, focused utilities for writing, media, and experimentation.", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
63 kicker: "ITEM INVENTORY", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
64 title: "Tools", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
65 url: "/tools", |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
66 works: [ |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
67 { detail: "Writing", label: "Markdown", url: "/tools/markdown_to_html" }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
68 { detail: "Media", label: "Converter", url: "/tools/file_converter" }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
69 { detail: "Streaming", label: "HLS Player", url: "/tools/hls_player" }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
70 ], |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
71 }, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
72 blog: { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
73 copy: "Notes from building systems, games, web tools, and curious prototypes.", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
74 kicker: "QUEST ARCHIVE", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
75 title: "Blogs", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
76 url: "/blog", |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
77 works: [ |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
78 { detail: "Archive", label: "All posts", url: "/blog" }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
79 ], |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
80 }, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
81 }); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
82 |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
83 const CONVERSATION_STORAGE_KEY = "mjj-jrpg-conversation-id"; |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
84 const TYPING_INTERVAL_MS = 18; |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
85 const SCRIPT_LOADS = new Map(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
86 const TOOL_ICON_NAMES = Object.freeze({ |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
87 "/notes": "repository", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
88 "/tools/file_converter": "retry", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
89 "/tools/hls_player": "play", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
90 "/tools/latex_editor": "file", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
91 "/tools/markdown_to_html": "code", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
92 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
93 |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
94 function loadScript(source) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
95 if (SCRIPT_LOADS.has(source)) return SCRIPT_LOADS.get(source); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
96 const loading = new Promise((resolve, reject) => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
97 const script = document.createElement("script"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
98 script.src = source; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
99 script.addEventListener("load", resolve, { once: true }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
100 script.addEventListener("error", () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
101 SCRIPT_LOADS.delete(source); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
102 script.remove(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
103 reject(new Error(`Unable to load ${source}`)); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
104 }, { once: true }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
105 document.head.append(script); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
106 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
107 SCRIPT_LOADS.set(source, loading); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
108 return loading; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
109 } |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
110 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
111 class StreamingTextAnimator { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
112 constructor(render) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
113 this._render = render; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
114 this._displayed = ""; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
115 this._target = ""; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
116 this._timer = 0; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
117 this._waiters = []; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
118 this._reduceMotion = window.matchMedia( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
119 "(prefers-reduced-motion: reduce)", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
120 ).matches; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
121 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
122 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
123 append(text) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
124 if (typeof text !== "string" || !text) return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
125 this._target += text; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
126 this._schedule(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
127 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
128 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
129 complete(text) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
130 if (typeof text === "string") { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
131 this._target = text; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
132 if (!this._target.startsWith(this._displayed)) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
133 let shared = 0; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
134 while ( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
135 shared < this._target.length && |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
136 shared < this._displayed.length && |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
137 this._target[shared] === this._displayed[shared] |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
138 ) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
139 shared++; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
140 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
141 this._displayed = this._displayed.slice(0, shared); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
142 this._render(this._displayed); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
143 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
144 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
145 this._schedule(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
146 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
147 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
148 waitForIdle() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
149 if (!this._timer && this._displayed === this._target) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
150 return Promise.resolve(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
151 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
152 return new Promise(resolve => { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
153 this._waiters.push(resolve); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
154 }); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
155 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
156 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
157 cancel() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
158 window.clearTimeout(this._timer); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
159 this._timer = 0; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
160 this._target = this._displayed; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
161 this._settle(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
162 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
163 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
164 _schedule() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
165 if (this._reduceMotion) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
166 this._displayed = this._target; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
167 this._render(this._displayed); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
168 this._settle(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
169 return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
170 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
171 if (this._timer || this._displayed === this._target) return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
172 this._timer = window.setTimeout(() => this._tick(), TYPING_INTERVAL_MS); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
173 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
174 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
175 _tick() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
176 this._timer = 0; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
177 const remaining = this._target.length - this._displayed.length; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
178 if (remaining <= 0) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
179 this._settle(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
180 return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
181 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
182 const amount = Math.max(1, Math.ceil(remaining / 80)); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
183 this._displayed = this._target.slice( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
184 0, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
185 this._displayed.length + amount, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
186 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
187 this._render(this._displayed); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
188 if (this._displayed === this._target) this._settle(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
189 else this._schedule(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
190 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
191 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
192 _settle() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
193 if (this._timer || this._displayed !== this._target) return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
194 const waiters = this._waiters.splice(0); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
195 for (const resolve of waiters) resolve(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
196 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
197 } |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
198 |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
199 class MjjJrpgCharacter extends HTMLElement { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
200 static get observedAttributes() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
201 return ["state"]; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
202 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
203 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
204 connectedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
205 this.render(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
206 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
207 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
208 attributeChangedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
209 if (this.isConnected) this.render(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
210 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
211 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
212 render() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
213 const image = this.querySelector("[data-character]"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
214 if (!image) return; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
215 const state = CHARACTER_STATES[this.getAttribute("state")] || |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
216 CHARACTER_STATES.default; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
217 image.src = state.src; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
218 image.alt = state.alt; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
219 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
220 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
221 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
222 class MjjJrpgChat extends HTMLElement { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
223 connectedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
224 this._messages = this.querySelector("[data-messages]"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
225 this._viewport = this.querySelector("[data-zen-viewport]"); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
226 this._previousButton = this.querySelector("[data-turn-previous]"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
227 this._nextButton = this.querySelector("[data-turn-next]"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
228 this._position = this.querySelector("[data-turn-position]"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
229 this._initialMessages = [...(this._messages?.children || [])].map( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
230 item => item.cloneNode(true), |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
231 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
232 this._turnSequence = 0; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
233 this._activeGroup = null; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
234 this._onNavigationClick = event => { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
235 const button = event.target.closest("button"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
236 if (!button || !this.contains(button) || button.disabled) return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
237 if (button === this._previousButton) this._moveTurn(-1); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
238 else if (button === this._nextButton) this._moveTurn(1); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
239 }; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
240 this.addEventListener("click", this._onNavigationClick); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
241 this._refreshTurnGroups("start"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
242 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
243 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
244 disconnectedCallback() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
245 this.removeEventListener("click", this._onNavigationClick); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
246 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
247 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
248 appendMessage(speaker, text) { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
249 let group = this._activeGroup || "start"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
250 if (speaker === "June") { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
251 this._turnSequence++; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
252 group = `turn-${this._turnSequence}`; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
253 this._activeGroup = group; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
254 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
255 return this._createMessage(speaker, text, group, true); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
256 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
257 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
258 _createMessage(speaker, text, group, select) { |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
259 if (!this._messages) return; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
260 const item = document.createElement("li"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
261 const name = document.createElement("strong"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
262 const copy = document.createElement("p"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
263 item.className = "jrpg-message"; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
264 item.dataset.speaker = speaker; |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
265 item.dataset.turnGroup = group; |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
266 name.textContent = speaker; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
267 copy.textContent = text; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
268 item.append(name, copy); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
269 this._messages.append(item); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
270 this._refreshTurnGroups(select ? group : this._currentGroup); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
271 return item; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
272 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
273 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
274 replaceMessages(turns) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
275 if (!this._messages) return; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
276 this._messages.replaceChildren(); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
277 this._turnSequence = 0; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
278 this._activeGroup = null; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
279 const visibleTurns = turns.filter(turn => |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
280 ["user", "assistant"].includes(turn.role) |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
281 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
282 if (!visibleTurns.length) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
283 this._messages.append( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
284 ...this._initialMessages.map(item => item.cloneNode(true)), |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
285 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
286 this._refreshTurnGroups("start"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
287 return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
288 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
289 let group = null; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
290 for (const turn of visibleTurns) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
291 if (turn.role === "user" || !group) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
292 this._turnSequence++; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
293 group = `turn-${this._turnSequence}`; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
294 this._activeGroup = group; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
295 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
296 this._createMessage( |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
297 turn.role === "user" ? "June" : "Epi", |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
298 turn.content || |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
299 (turn.status === "aborted" |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
300 ? "Quest cancelled." |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
301 : turn.status === "failed" |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
302 ? "The quest failed." |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
303 : ""), |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
304 group, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
305 false, |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
306 ); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
307 } |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
308 this._refreshTurnGroups(group); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
309 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
310 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
311 startAssistantMessage() { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
312 return this.appendMessage("Epi", ""); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
313 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
314 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
315 setMessageText(item, text) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
316 const copy = item?.querySelector("p"); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
317 if (copy) copy.textContent = text; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
318 this.scrollEnd(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
319 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
320 |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
321 setMessageStreaming(item, streaming) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
322 if (!item) return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
323 if (streaming) item.dataset.streaming = "true"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
324 else delete item.dataset.streaming; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
325 this._viewport?.setAttribute("aria-busy", String(streaming)); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
326 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
327 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
328 _refreshTurnGroups(preferredGroup) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
329 const groups = []; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
330 for (const item of this._messages?.children || []) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
331 const group = item.dataset.turnGroup || "start"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
332 item.dataset.turnGroup = group; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
333 if (!groups.includes(group)) groups.push(group); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
334 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
335 this._turnGroups = groups; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
336 const preferredIndex = groups.indexOf(preferredGroup); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
337 const currentIndex = groups.indexOf(this._currentGroup); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
338 this._turnIndex = preferredIndex >= 0 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
339 ? preferredIndex |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
340 : currentIndex >= 0 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
341 ? currentIndex |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
342 : Math.max(0, groups.length - 1); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
343 this._showTurn(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
344 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
345 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
346 _moveTurn(offset) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
347 const nextIndex = Math.max( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
348 0, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
349 Math.min(this._turnGroups.length - 1, this._turnIndex + offset), |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
350 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
351 if (nextIndex === this._turnIndex) return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
352 this._turnIndex = nextIndex; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
353 this._showTurn(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
354 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
355 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
356 _showTurn() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
357 const group = this._turnGroups?.[this._turnIndex]; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
358 this._currentGroup = group; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
359 for (const item of this._messages?.children || []) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
360 item.hidden = item.dataset.turnGroup !== group; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
361 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
362 if (this._previousButton) this._previousButton.disabled = this._turnIndex <= 0; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
363 if (this._nextButton) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
364 this._nextButton.disabled = |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
365 this._turnIndex >= (this._turnGroups?.length || 0) - 1; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
366 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
367 if (this._position) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
368 if (group === "start") { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
369 this._position.textContent = "START"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
370 } else { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
371 const turns = this._turnGroups.filter(item => item !== "start"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
372 this._position.textContent = |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
373 `TURN ${turns.indexOf(group) + 1} / ${turns.length}`; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
374 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
375 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
376 this.scrollEnd(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
377 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
378 |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
379 scrollEnd() { |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
380 requestAnimationFrame(() => { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
381 if (this._viewport) { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
382 this._viewport.scrollTop = this._viewport.scrollHeight; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
383 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
384 }); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
385 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
386 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
387 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
388 class MjjJrpgComposer extends HTMLElement { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
389 connectedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
390 this._form = this.querySelector("[data-composer]"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
391 this._textarea = this.querySelector("textarea"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
392 this._button = this.querySelector('button[type="submit"]'); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
393 this._cancel = this.querySelector("[data-cancel]"); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
394 this._cancelControl = this.querySelector("[data-cancel-control]"); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
395 this._onSubmit = event => { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
396 event.preventDefault(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
397 const message = this._textarea?.value.trim(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
398 if (!message || this._button?.disabled) return; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
399 this.dispatchEvent(new CustomEvent("mjj-jrpg-submit", { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
400 bubbles: true, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
401 detail: { message }, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
402 })); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
403 this._form.reset(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
404 }; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
405 this._onKeydown = event => { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
406 if (event.key !== "Enter" || event.shiftKey || event.isComposing) return; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
407 event.preventDefault(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
408 this._form?.requestSubmit(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
409 }; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
410 this._form?.addEventListener("submit", this._onSubmit); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
411 this._textarea?.addEventListener("keydown", this._onKeydown); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
412 this._onCancel = () => { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
413 this.dispatchEvent(new CustomEvent("mjj-jrpg-cancel", { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
414 bubbles: true, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
415 })); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
416 }; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
417 this._cancel?.addEventListener("click", this._onCancel); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
418 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
419 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
420 disconnectedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
421 this._form?.removeEventListener("submit", this._onSubmit); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
422 this._textarea?.removeEventListener("keydown", this._onKeydown); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
423 this._cancel?.removeEventListener("click", this._onCancel); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
424 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
425 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
426 setBusy(busy) { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
427 if (this._textarea) this._textarea.disabled = busy; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
428 if (this._button) { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
429 this._button.disabled = busy; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
430 this._button.setAttribute("aria-busy", String(busy)); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
431 } |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
432 if (this._cancelControl) this._cancelControl.hidden = !busy; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
433 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
434 |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
435 setCancellable(cancellable) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
436 if (this._cancelControl) this._cancelControl.hidden = !cancellable; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
437 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
438 |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
439 setDisabled(disabled) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
440 if (this._textarea) this._textarea.disabled = disabled; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
441 if (this._button) this._button.disabled = disabled; |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
442 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
443 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
444 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
445 class MjjJrpgMenu extends HTMLElement { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
446 connectedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
447 this._onClick = event => { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
448 const button = event.target.closest("button[data-preview]"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
449 if (!button || !this.contains(button)) return; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
450 for (const item of this.querySelectorAll("button[data-preview]")) { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
451 item.setAttribute("aria-pressed", String(item === button)); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
452 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
453 this.dispatchEvent(new CustomEvent("mjj-jrpg-preview-change", { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
454 bubbles: true, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
455 detail: { selection: button.dataset.preview }, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
456 })); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
457 }; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
458 this.addEventListener("click", this._onClick); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
459 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
460 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
461 disconnectedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
462 this.removeEventListener("click", this._onClick); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
463 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
464 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
465 |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
466 function sanitizeFetchedMain(main) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
467 for (const unsafe of main.querySelectorAll( |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
468 "embed, form, iframe, object, script, style, svg", |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
469 )) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
470 unsafe.remove(); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
471 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
472 for (const element of main.querySelectorAll("*")) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
473 for (const attribute of [...element.attributes]) { |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
474 const name = attribute.name.toLowerCase(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
475 if (name.startsWith("on") || name === "id" || name === "style") { |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
476 element.removeAttribute(attribute.name); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
477 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
478 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
479 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
480 for (const anchor of main.querySelectorAll("a")) { |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
481 const href = anchor.getAttribute("href"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
482 if (!href || anchor.getAttribute("aria-disabled") === "true") { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
483 anchor.remove(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
484 continue; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
485 } |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
486 const target = new URL( |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
487 href, |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
488 window.location.href, |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
489 ); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
490 anchor.href = target.href; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
491 if (target.origin !== window.location.origin) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
492 anchor.target = "_blank"; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
493 anchor.rel = "noreferrer"; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
494 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
495 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
496 for (const image of main.querySelectorAll("img")) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
497 const source = image.getAttribute("src") || ""; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
498 if (source.startsWith("/public/") && source.endsWith(".png")) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
499 image.src = source.replace(/\.png$/i, ".webp"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
500 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
501 image.loading = "lazy"; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
502 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
503 return main; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
504 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
505 |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
506 function sanitizeToolDetail(main) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
507 sanitizeFetchedMain(main); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
508 for (const textarea of main.querySelectorAll("textarea")) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
509 const sample = document.createElement("pre"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
510 sample.className = "jrpg-tool-source-sample"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
511 sample.textContent = textarea.value || textarea.textContent; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
512 textarea.replaceWith(sample); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
513 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
514 for (const inactive of main.querySelectorAll( |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
515 "button, canvas, dialog, input, select, video, [hidden]", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
516 )) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
517 inactive.remove(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
518 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
519 for (const owner of main.querySelectorAll( |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
520 "zen-button, zen-checkbox, zen-field, zen-input, zen-textarea", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
521 )) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
522 owner.replaceWith(...owner.childNodes); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
523 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
524 for (const label of main.querySelectorAll("label[for]")) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
525 label.removeAttribute("for"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
526 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
527 return main; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
528 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
529 |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
530 class MjjJrpgPreview extends HTMLElement { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
531 connectedCallback() { |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
532 this._dialog = this.querySelector("dialog"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
533 this._onDialogClose = () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
534 this._toolRequest = (this._toolRequest || 0) + 1; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
535 this.cleanupTool(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
536 }; |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
537 this._onClick = event => { |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
538 const trigger = event.target.closest("[data-zen-trigger]"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
539 if (trigger) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
540 if (this.dataset.selection === "resume") void this.loadResume(); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
541 if (this.dataset.selection === "blog") { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
542 this.show("blog"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
543 void this.loadBlogs(); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
544 } |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
545 if (this.dataset.selection === "tools") { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
546 this.show("tools"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
547 void this.openToolWorkspace(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
548 } |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
549 return; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
550 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
551 const blogEntry = event.target.closest("[data-blog-entry]"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
552 if (blogEntry) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
553 void this.loadBlogDetail(blogEntry.dataset.blogUrl); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
554 return; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
555 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
556 const latestBlog = event.target.closest("[data-latest-blog]"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
557 if (latestBlog && !event.metaKey && !event.ctrlKey && !event.shiftKey) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
558 event.preventDefault(); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
559 this.querySelector("zen-dialog").open(); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
560 void this.loadBlogDetail(latestBlog.dataset.blogUrl); |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
561 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
562 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
563 const blogArchive = event.target.closest("[data-blog-archive]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
564 if (blogArchive) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
565 event.preventDefault(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
566 this.querySelector("zen-dialog").open(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
567 this.show("blog"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
568 void this.loadBlogs(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
569 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
570 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
571 const resumeModal = event.target.closest("[data-resume-modal]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
572 if (resumeModal) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
573 event.preventDefault(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
574 this.querySelector("zen-dialog").open(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
575 this.show("resume"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
576 void this.loadResume(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
577 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
578 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
579 const latestTool = event.target.closest("[data-latest-tool]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
580 if (latestTool && !event.metaKey && !event.ctrlKey && !event.shiftKey) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
581 event.preventDefault(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
582 this.querySelector("zen-dialog").open(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
583 void this.loadToolDetail(latestTool.dataset.toolUrl); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
584 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
585 }; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
586 this.addEventListener("click", this._onClick); |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
587 this._dialog.addEventListener("close", this._onDialogClose); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
588 this.show(this.dataset.selection || "resume"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
589 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
590 |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
591 disconnectedCallback() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
592 this.removeEventListener("click", this._onClick); |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
593 this._dialog?.removeEventListener("close", this._onDialogClose); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
594 this.cleanupTool(); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
595 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
596 |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
597 show(selection) { |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
598 this.cleanupTool(); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
599 const preview = PREVIEWS[selection] || PREVIEWS.resume; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
600 this.dataset.selection = selection; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
601 this.querySelector("[data-preview-kicker]").textContent = preview.kicker; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
602 this.querySelector("[data-preview-title]").textContent = preview.title; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
603 this.querySelector("[data-preview-copy]").textContent = preview.copy; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
604 this.querySelector("[data-dialog-title]").textContent = preview.title; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
605 this.querySelector("[data-dialog-copy]").textContent = preview.copy; |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
606 this.renderShowcase(preview.works); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
607 const link = this.querySelector("[data-preview-link]"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
608 link.href = preview.url; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
609 link.setAttribute("aria-label", `Open ${preview.title}`); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
610 const resumeDossier = this.querySelector("[data-resume-dossier]"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
611 const resumeDownload = this.querySelector("[data-resume-download]"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
612 const blogBrowser = this.querySelector("[data-blog-browser]"); |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
613 const toolBrowser = this.querySelector("[data-tool-browser]"); |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
614 const isResume = selection === "resume"; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
615 const isBlog = selection === "blog"; |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
616 const isTools = selection === "tools"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
617 this._dialog.dataset.detailMode = isTools ? "tools" : "content"; |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
618 resumeDossier.hidden = !isResume; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
619 resumeDownload.hidden = !isResume; |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
620 this.querySelector("[data-dialog-actions]").hidden = !isResume; |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
621 blogBrowser.hidden = !isBlog; |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
622 toolBrowser.hidden = !isTools; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
623 this.querySelector("[data-dialog-copy]").hidden = |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
624 isResume || isBlog || isTools; |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
625 if (!isBlog) this._blogRequest = (this._blogRequest || 0) + 1; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
626 if (isBlog) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
627 const status = this.querySelector("[data-blog-status]"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
628 status.hidden = false; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
629 status.textContent = "Select a blog to inspect."; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
630 this.querySelector("[data-blog-content]").replaceChildren(); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
631 for (const button of this.querySelectorAll("[data-blog-entry]")) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
632 button.setAttribute("aria-pressed", "false"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
633 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
634 void this.loadBlogs(); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
635 } |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
636 if (!isTools) this._toolRequest = (this._toolRequest || 0) + 1; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
637 if (isTools) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
638 const status = this.querySelector("[data-tool-status]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
639 status.hidden = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
640 status.textContent = "Select a tool to inspect."; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
641 this.querySelector("[data-tool-content]").replaceChildren(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
642 void this.loadTools(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
643 } |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
644 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
645 |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
646 renderShowcase(works, latestBlogs = false, latestKind = null) { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
647 const showcase = this.querySelector("[data-work-showcase]"); |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
648 showcase.replaceChildren(...works.map(work => { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
649 const item = document.createElement("li"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
650 const link = document.createElement("a"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
651 const label = document.createElement("span"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
652 const detail = document.createElement("small"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
653 link.href = work.url; |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
654 if (latestBlogs) { |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
655 if (work.modal === "blog") { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
656 link.dataset.blogArchive = ""; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
657 } else { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
658 link.dataset.latestBlog = ""; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
659 link.dataset.blogUrl = work.url; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
660 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
661 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
662 if (work.modal === "resume") link.dataset.resumeModal = ""; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
663 if (latestKind === "tool") { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
664 link.dataset.latestTool = ""; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
665 link.dataset.toolUrl = work.url; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
666 const icon = document.createElement("zen-icon"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
667 icon.setAttribute("name", TOOL_ICON_NAMES[work.url] || "settings"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
668 link.prepend(icon); |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
669 } |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
670 if (new URL(work.url, window.location.href).origin !== window.location.origin) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
671 link.target = "_blank"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
672 link.rel = "noreferrer"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
673 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
674 label.textContent = work.label; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
675 detail.textContent = work.detail; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
676 link.append(label, detail); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
677 item.append(link); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
678 return item; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
679 })); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
680 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
681 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
682 async loadResume() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
683 if (this._resumeLoaded || this._resumeLoading) return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
684 this._resumeLoading = true; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
685 const status = this.querySelector("[data-resume-status]"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
686 const content = this.querySelector("[data-resume-content]"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
687 try { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
688 const response = await fetch("/resume", { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
689 headers: { Accept: "text/html" }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
690 }); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
691 if (!response.ok) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
692 throw new Error(`Resume request failed (${response.status})`); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
693 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
694 const documentCopy = new DOMParser().parseFromString( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
695 await response.text(), |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
696 "text/html", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
697 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
698 const resume = documentCopy.querySelector("main"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
699 if (!resume) throw new Error("Resume content is unavailable"); |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
700 sanitizeFetchedMain(resume); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
701 content.replaceChildren(...resume.childNodes); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
702 status.hidden = true; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
703 this._resumeLoaded = true; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
704 } catch (error) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
705 status.textContent = `Unable to load resume: ${error.message}`; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
706 } finally { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
707 this._resumeLoading = false; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
708 } |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
709 } |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
710 |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
711 async loadBlogs() { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
712 if (this._blogs) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
713 if (this.dataset.selection === "blog") { |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
714 this.renderShowcase([ |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
715 ...this._blogs.slice(0, 4), |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
716 { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
717 detail: "Full archive", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
718 label: "All blogs", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
719 modal: "blog", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
720 url: "/blog", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
721 }, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
722 ], true); |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
723 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
724 return true; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
725 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
726 if (this._blogsLoading) return this._blogsLoading; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
727 const list = this.querySelector("[data-blog-list]"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
728 this._blogsLoading = (async () => { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
729 const response = await fetch("/blog", { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
730 headers: { Accept: "text/html" }, |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
731 }); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
732 if (!response.ok) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
733 throw new Error(`Blog archive request failed (${response.status})`); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
734 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
735 const documentCopy = new DOMParser().parseFromString( |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
736 await response.text(), |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
737 "text/html", |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
738 ); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
739 this._blogs = [...documentCopy.querySelectorAll( |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
740 'main li a[href^="/blog/"]', |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
741 )].map(anchor => ({ |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
742 date: anchor.closest("li")?.querySelector("span")?.textContent.trim() || |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
743 "Archive", |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
744 detail: anchor.closest("li")?.querySelector("span")?.textContent.trim() || |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
745 "Archive", |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
746 label: anchor.textContent.trim(), |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
747 url: anchor.getAttribute("href"), |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
748 })); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
749 if (!this._blogs.length) throw new Error("No blog entries were found"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
750 this.renderBlogList(); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
751 if (this.dataset.selection === "blog") { |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
752 this.renderShowcase([ |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
753 ...this._blogs.slice(0, 4), |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
754 { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
755 detail: "Full archive", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
756 label: "All blogs", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
757 modal: "blog", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
758 url: "/blog", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
759 }, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
760 ], true); |
|
262
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
761 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
762 return true; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
763 })().catch(error => { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
764 list.replaceChildren(); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
765 const item = document.createElement("li"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
766 item.textContent = `Unable to load blogs: ${error.message}`; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
767 list.append(item); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
768 return false; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
769 }).finally(() => { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
770 this._blogsLoading = null; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
771 }); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
772 return this._blogsLoading; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
773 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
774 |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
775 renderBlogList() { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
776 const list = this.querySelector("[data-blog-list]"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
777 list.replaceChildren(...this._blogs.map(blog => { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
778 const item = document.createElement("li"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
779 const owner = document.createElement("zen-button"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
780 const button = document.createElement("button"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
781 const title = document.createElement("span"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
782 const date = document.createElement("small"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
783 owner.setAttribute("appearance", "plain"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
784 owner.setAttribute("size", "sm"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
785 button.type = "button"; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
786 button.dataset.blogEntry = ""; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
787 button.dataset.blogUrl = blog.url; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
788 title.textContent = blog.label; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
789 date.textContent = blog.date; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
790 button.append(title, date); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
791 owner.append(button); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
792 item.append(owner); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
793 return item; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
794 })); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
795 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
796 |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
797 async loadBlogDetail(url) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
798 if (!await this.loadBlogs()) return; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
799 const blog = this._blogs.find(item => item.url === url); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
800 const status = this.querySelector("[data-blog-status]"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
801 const content = this.querySelector("[data-blog-content]"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
802 if (!blog) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
803 status.hidden = false; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
804 status.textContent = "Unable to load blog: unknown entry."; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
805 return; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
806 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
807 const request = (this._blogRequest || 0) + 1; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
808 this._blogRequest = request; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
809 status.hidden = false; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
810 status.textContent = `Loading ${blog.label}...`; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
811 content.replaceChildren(); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
812 this.querySelector("[data-dialog-title]").textContent = blog.label; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
813 const fullPage = this.querySelector("[data-preview-link]"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
814 fullPage.href = blog.url; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
815 fullPage.setAttribute("aria-label", `Open ${blog.label}`); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
816 for (const button of this.querySelectorAll("[data-blog-entry]")) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
817 button.setAttribute( |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
818 "aria-pressed", |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
819 String(button.dataset.blogUrl === blog.url), |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
820 ); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
821 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
822 try { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
823 const response = await fetch(blog.url, { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
824 headers: { Accept: "text/html" }, |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
825 }); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
826 if (!response.ok) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
827 throw new Error(`Blog request failed (${response.status})`); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
828 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
829 const documentCopy = new DOMParser().parseFromString( |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
830 await response.text(), |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
831 "text/html", |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
832 ); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
833 const article = documentCopy.querySelector("main"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
834 if (!article) throw new Error("Blog content is unavailable"); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
835 sanitizeFetchedMain(article); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
836 if (request !== this._blogRequest || this.dataset.selection !== "blog") { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
837 return; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
838 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
839 content.replaceChildren(...article.childNodes); |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
840 status.hidden = true; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
841 } catch (error) { |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
842 if (request !== this._blogRequest) return; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
843 status.hidden = false; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
844 status.textContent = `Unable to load blog: ${error.message}`; |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
845 } |
|
0f45474c1b1a
Add cyberpunk JRPG blog browser
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
261
diff
changeset
|
846 } |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
847 |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
848 async loadTools() { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
849 if (this._tools) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
850 if (this.dataset.selection === "tools") { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
851 this.renderShowcase(this._tools, false, "tool"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
852 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
853 return true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
854 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
855 if (this._toolsLoading) return this._toolsLoading; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
856 this._toolsLoading = (async () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
857 const response = await fetch("/tools", { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
858 headers: { Accept: "text/html" }, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
859 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
860 if (!response.ok) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
861 throw new Error(`Tools request failed (${response.status})`); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
862 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
863 const documentCopy = new DOMParser().parseFromString( |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
864 await response.text(), |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
865 "text/html", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
866 ); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
867 this._tools = [...documentCopy.querySelectorAll("main li a[href]")].map( |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
868 anchor => ({ |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
869 detail: anchor.getAttribute("href").startsWith("/notes") |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
870 ? "Writing" |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
871 : "Utility", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
872 label: anchor.textContent.trim(), |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
873 url: anchor.getAttribute("href"), |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
874 }), |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
875 ); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
876 if (!this._tools.length) throw new Error("No tools were found"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
877 if (this.dataset.selection === "tools") { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
878 this.renderShowcase(this._tools, false, "tool"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
879 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
880 return true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
881 })().catch(error => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
882 const status = this.querySelector("[data-tool-status]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
883 status.hidden = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
884 status.textContent = `Unable to load tools: ${error.message}`; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
885 return false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
886 }).finally(() => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
887 this._toolsLoading = null; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
888 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
889 return this._toolsLoading; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
890 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
891 |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
892 async openToolWorkspace() { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
893 if (!await this.loadTools() || this.dataset.selection !== "tools") return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
894 await this.loadToolDetail(this._activeToolUrl || this._tools[0].url); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
895 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
896 |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
897 async loadToolDetail(url) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
898 const request = (this._toolRequest || 0) + 1; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
899 this._toolRequest = request; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
900 if (!await this.loadTools()) return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
901 if (request !== this._toolRequest || this.dataset.selection !== "tools") { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
902 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
903 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
904 const tool = this._tools.find(item => item.url === url); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
905 const status = this.querySelector("[data-tool-status]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
906 const content = this.querySelector("[data-tool-content]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
907 if (!tool) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
908 status.hidden = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
909 status.textContent = "Unable to load tool: unknown entry."; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
910 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
911 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
912 this._activeToolUrl = tool.url; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
913 status.hidden = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
914 status.textContent = `Loading ${tool.label}...`; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
915 this.cleanupTool(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
916 content.replaceChildren(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
917 this.querySelector("[data-dialog-title]").textContent = tool.label; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
918 const fullPage = this.querySelector("[data-preview-link]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
919 fullPage.href = tool.url; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
920 fullPage.setAttribute("aria-label", `Open ${tool.label}`); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
921 if (tool.url === "/tools/markdown_to_html") { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
922 await this.renderMarkdownTool(content, status, request); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
923 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
924 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
925 if (tool.url === "/tools/file_converter") { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
926 this.renderFileConverterTool(content, status); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
927 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
928 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
929 if (tool.url === "/tools/hls_player") { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
930 await this.renderHlsTool(content, status, request); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
931 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
932 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
933 if (tool.url === "/tools/latex_editor") { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
934 this.renderLatexTool(content, status); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
935 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
936 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
937 if (tool.url === "/notes") { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
938 const heading = document.createElement("h1"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
939 const description = document.createElement("p"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
940 const privacy = document.createElement("p"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
941 heading.textContent = "Personal Notes"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
942 description.textContent = |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
943 "A private browser-based writing workspace with rich-text editing and server-backed persistence."; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
944 privacy.textContent = |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
945 "The interactive editor and authentication flow are available on the full Notes page."; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
946 content.replaceChildren( |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
947 this.createReadonlyToolNote(), |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
948 heading, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
949 description, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
950 privacy, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
951 ); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
952 status.hidden = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
953 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
954 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
955 try { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
956 const response = await fetch(tool.url, { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
957 headers: { Accept: "text/html" }, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
958 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
959 if (!response.ok) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
960 throw new Error(`Tool request failed (${response.status})`); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
961 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
962 const documentCopy = new DOMParser().parseFromString( |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
963 await response.text(), |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
964 "text/html", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
965 ); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
966 const detail = documentCopy.querySelector("main, .container") || |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
967 documentCopy.body; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
968 if (!detail) throw new Error("Tool content is unavailable"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
969 sanitizeToolDetail(detail); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
970 if (request !== this._toolRequest || this.dataset.selection !== "tools") { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
971 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
972 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
973 content.replaceChildren( |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
974 this.createReadonlyToolNote(), |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
975 ...detail.childNodes, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
976 ); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
977 status.hidden = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
978 } catch (error) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
979 if (request !== this._toolRequest) return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
980 status.hidden = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
981 status.textContent = `Unable to load tool: ${error.message}`; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
982 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
983 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
984 |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
985 async renderMarkdownTool(content, status, request) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
986 content.innerHTML = ` |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
987 <section class="jrpg-functional-tool" data-functional-tool="markdown"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
988 <div class="jrpg-tool-panes"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
989 <section class="jrpg-tool-pane jrpg-tool-window"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
990 <h2><zen-icon name="code"></zen-icon> Markdown source</h2> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
991 <zen-field appearance="plain" size="md"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
992 <label for="jrpgMarkdownSource">Markdown</label> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
993 <textarea id="jrpgMarkdownSource" data-markdown-source></textarea> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
994 </zen-field> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
995 </section> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
996 <section class="jrpg-tool-pane jrpg-tool-window"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
997 <h2><zen-icon name="check"></zen-icon> Converted HTML</h2> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
998 <div class="jrpg-markdown-output" data-markdown-output></div> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
999 </section> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1000 </div> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1001 </section> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1002 `; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1003 const source = content.querySelector("[data-markdown-source]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1004 const output = content.querySelector("[data-markdown-output]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1005 source.value = [ |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1006 "# JRPG Markdown", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1007 "", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1008 "Edit this **Markdown** to update the converted panel.", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1009 "", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1010 "- Bazel-built WASM", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1011 "- Sanitized HTML output", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1012 ].join("\n"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1013 status.hidden = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1014 status.textContent = "Loading the Markdown converter..."; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1015 try { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1016 this._markdownModule ||= import("/markdown_to_html_bin.js") |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1017 .then(module => module.default()); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1018 const module = await this._markdownModule; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1019 if (request !== this._toolRequest || !source.isConnected) return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1020 const convertMarkdown = module.cwrap( |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1021 "markdown_to_html", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1022 "number", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1023 ["string"], |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1024 ); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1025 const freeMarkdown = module.cwrap("markdown_free", null, ["number"]); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1026 const convert = () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1027 const pointer = convertMarkdown(source.value); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1028 const html = module.UTF8ToString(pointer); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1029 freeMarkdown(pointer); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1030 const documentCopy = new DOMParser().parseFromString(html, "text/html"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1031 sanitizeFetchedMain(documentCopy.body); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1032 output.replaceChildren(...documentCopy.body.childNodes); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1033 }; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1034 source.addEventListener("input", convert); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1035 convert(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1036 status.hidden = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1037 } catch (error) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1038 this._markdownModule = null; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1039 if (request !== this._toolRequest) return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1040 status.hidden = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1041 status.textContent = `Unable to start Markdown: ${error.message}`; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1042 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1043 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1044 |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1045 renderFileConverterTool(content, status) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1046 content.innerHTML = ` |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1047 <section class="jrpg-functional-tool" data-functional-tool="converter"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1048 <p class="jrpg-tool-status" data-converter-status> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1049 Choose a file in either panel. |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1050 </p> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1051 <div class="jrpg-tool-panes"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1052 <section class="jrpg-tool-pane jrpg-tool-window"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1053 <h2><zen-icon name="file"></zen-icon> Image to WebP</h2> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1054 <zen-field appearance="plain" size="md"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1055 <label for="jrpgImageInput">Image file</label> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1056 <input id="jrpgImageInput" data-converter-input="image" type="file" accept="image/*"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1057 </zen-field> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1058 <zen-button appearance="plain" size="md"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1059 <button type="button" data-convert-kind="image"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1060 Convert image <zen-icon name="arrow-right"></zen-icon> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1061 </button> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1062 </zen-button> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1063 <a data-converter-download="image" hidden>Download WebP</a> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1064 </section> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1065 <section class="jrpg-tool-pane jrpg-tool-window"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1066 <h2><zen-icon name="play"></zen-icon> Video to MP4</h2> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1067 <zen-field appearance="plain" size="md"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1068 <label for="jrpgVideoInput">Video file</label> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1069 <input id="jrpgVideoInput" data-converter-input="video" type="file" accept="video/*"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1070 </zen-field> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1071 <zen-button appearance="plain" size="md"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1072 <button type="button" data-convert-kind="video"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1073 Convert video <zen-icon name="arrow-right"></zen-icon> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1074 </button> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1075 </zen-button> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1076 <a data-converter-download="video" hidden>Download MP4</a> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1077 </section> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1078 </div> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1079 </section> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1080 `; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1081 const toolStatus = content.querySelector("[data-converter-status]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1082 let disposed = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1083 const downloads = new Set(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1084 const discardDownload = url => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1085 if (!url) return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1086 downloads.delete(url); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1087 void fetch(url, { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1088 method: "DELETE", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1089 keepalive: true, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1090 }).then(response => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1091 if (!response.ok && response.status !== 404) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1092 console.warn(`Unable to discard converted file (${response.status})`); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1093 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1094 }).catch(error => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1095 console.warn(`Unable to discard converted file: ${error.message}`); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1096 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1097 }; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1098 const convert = async kind => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1099 const input = content.querySelector(`[data-converter-input="${kind}"]`); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1100 const button = content.querySelector(`[data-convert-kind="${kind}"]`); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1101 const download = content.querySelector( |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1102 `[data-converter-download="${kind}"]`, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1103 ); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1104 const file = input.files?.[0]; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1105 if (!file) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1106 toolStatus.textContent = `Choose a ${kind} file first.`; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1107 toolStatus.dataset.state = "error"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1108 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1109 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1110 button.disabled = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1111 discardDownload(download.dataset.cleanupUrl); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1112 delete download.dataset.cleanupUrl; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1113 download.removeAttribute("href"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1114 download.hidden = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1115 toolStatus.textContent = `Converting ${file.name}...`; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1116 toolStatus.dataset.state = "working"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1117 try { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1118 const endpoint = kind === "image" |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1119 ? "/api/convert/image-to-webp" |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1120 : "/api/convert/video-to-mp4"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1121 const response = await fetch(endpoint, { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1122 method: "POST", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1123 body: file, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1124 headers: { "Content-Type": file.type || "application/octet-stream" }, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1125 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1126 if (!response.ok) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1127 throw new Error(await response.text() || `Conversion failed (${response.status})`); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1128 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1129 const result = await response.json(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1130 if (disposed || !download.isConnected) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1131 discardDownload(result.download_url); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1132 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1133 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1134 download.href = result.download_url; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1135 download.dataset.cleanupUrl = result.download_url; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1136 downloads.add(result.download_url); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1137 download.download = file.name.replace(/\.[^/.]+$/, "") + |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1138 (kind === "image" ? ".webp" : ".mp4"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1139 download.hidden = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1140 toolStatus.textContent = "Conversion complete."; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1141 toolStatus.dataset.state = "ready"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1142 } catch (error) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1143 if (!disposed) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1144 toolStatus.textContent = `Conversion failed: ${error.message}`; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1145 toolStatus.dataset.state = "error"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1146 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1147 } finally { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1148 if (button.isConnected) button.disabled = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1149 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1150 }; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1151 for (const button of content.querySelectorAll("[data-convert-kind]")) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1152 button.addEventListener("click", () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1153 void convert(button.dataset.convertKind); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1154 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1155 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1156 for (const download of content.querySelectorAll("[data-converter-download]")) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1157 download.addEventListener("click", () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1158 downloads.delete(download.dataset.cleanupUrl); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1159 delete download.dataset.cleanupUrl; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1160 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1161 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1162 this._toolCleanup = () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1163 disposed = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1164 for (const download of [...downloads]) discardDownload(download); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1165 }; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1166 status.hidden = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1167 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1168 |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1169 async renderHlsTool(content, status, request) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1170 content.innerHTML = ` |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1171 <section class="jrpg-functional-tool" data-functional-tool="hls"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1172 <div class="jrpg-tool-panes"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1173 <section class="jrpg-tool-pane jrpg-tool-window"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1174 <h2><zen-icon name="file"></zen-icon> HLS source</h2> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1175 <zen-field appearance="plain" size="md"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1176 <label for="jrpgHlsUrl">Playlist URL</label> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1177 <input |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1178 id="jrpgHlsUrl" |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1179 data-hls-url |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1180 type="url" |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1181 value="/public/hls-sample/h264-ts-stream.m3u8" |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1182 > |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1183 </zen-field> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1184 <div class="jrpg-tool-actions"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1185 <zen-button appearance="plain" size="md"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1186 <button type="button" data-hls-load> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1187 Load URL <zen-icon name="arrow-right"></zen-icon> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1188 </button> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1189 </zen-button> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1190 <zen-button appearance="plain" size="md"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1191 <button type="button" data-hls-sample> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1192 Load sample <zen-icon name="play"></zen-icon> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1193 </button> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1194 </zen-button> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1195 </div> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1196 <p class="jrpg-tool-status" data-hls-status>Loading player engine...</p> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1197 </section> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1198 <section class="jrpg-tool-pane jrpg-tool-window"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1199 <h2><zen-icon name="play"></zen-icon> Playback</h2> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1200 <video data-hls-video controls playsinline preload="metadata"></video> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1201 <dl class="jrpg-tool-details" data-hls-details hidden> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1202 <div><dt>Playback</dt><dd data-detail="mode">-</dd></div> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1203 <div><dt>Segments</dt><dd data-detail="segments">-</dd></div> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1204 <div><dt>Duration</dt><dd data-detail="duration">-</dd></div> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1205 <div><dt>Codec</dt><dd data-detail="codecs">-</dd></div> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1206 </dl> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1207 </section> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1208 </div> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1209 </section> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1210 `; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1211 try { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1212 await loadScript("/public/hls.min.js"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1213 await loadScript("/tools/hls_player/hls-player.js"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1214 if (request !== this._toolRequest || !content.isConnected) return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1215 const video = content.querySelector("[data-hls-video]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1216 const playerStatus = content.querySelector("[data-hls-status]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1217 const details = content.querySelector("[data-hls-details]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1218 const url = content.querySelector("[data-hls-url]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1219 const player = new window.HlsPlayerModule.HlsPlayer(video, { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1220 statusElement: playerStatus, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1221 detailsElement: details, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1222 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1223 const load = () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1224 void player.load(url.value.trim()).catch(() => {}); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1225 }; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1226 content.querySelector("[data-hls-load]").addEventListener("click", load); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1227 content.querySelector("[data-hls-sample]").addEventListener("click", () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1228 url.value = "/public/hls-sample/h264-ts-stream.m3u8"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1229 load(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1230 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1231 playerStatus.textContent = "Ready to load a playlist."; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1232 playerStatus.dataset.state = "ready"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1233 this._toolCleanup = () => player.destroy(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1234 status.hidden = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1235 } catch (error) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1236 if (request !== this._toolRequest) return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1237 status.hidden = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1238 status.textContent = `Unable to start HLS: ${error.message}`; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1239 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1240 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1241 |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1242 renderLatexTool(content, status) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1243 content.innerHTML = ` |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1244 <section class="jrpg-functional-tool" data-functional-tool="latex"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1245 <p class="jrpg-tool-status" data-latex-status> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1246 Edit the source, then compile the PDF. |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1247 </p> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1248 <div class="jrpg-tool-panes"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1249 <section class="jrpg-tool-pane jrpg-tool-window"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1250 <div class="jrpg-tool-pane-heading"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1251 <h2><zen-icon name="code"></zen-icon> LaTeX source</h2> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1252 <span data-latex-size></span> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1253 </div> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1254 <zen-field appearance="plain" size="md"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1255 <label for="jrpgLatexSource">document.tex</label> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1256 <textarea id="jrpgLatexSource" data-latex-source></textarea> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1257 </zen-field> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1258 <div class="jrpg-tool-actions"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1259 <zen-button appearance="plain" size="md"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1260 <button type="button" data-latex-compile> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1261 Compile PDF <zen-icon name="file"></zen-icon> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1262 </button> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1263 </zen-button> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1264 <zen-button appearance="plain" size="md" data-latex-download hidden> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1265 <a download="document.pdf"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1266 Download PDF <zen-icon name="download"></zen-icon> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1267 </a> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1268 </zen-button> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1269 </div> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1270 </section> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1271 <section class="jrpg-tool-pane jrpg-tool-window"> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1272 <h2><zen-icon name="file"></zen-icon> PDF preview</h2> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1273 <iframe data-latex-preview title="Compiled LaTeX PDF preview"></iframe> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1274 <pre data-latex-diagnostics hidden></pre> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1275 </section> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1276 </div> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1277 </section> |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1278 `; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1279 const source = content.querySelector("[data-latex-source]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1280 const compileButton = content.querySelector("[data-latex-compile]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1281 const toolStatus = content.querySelector("[data-latex-status]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1282 const size = content.querySelector("[data-latex-size]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1283 const preview = content.querySelector("[data-latex-preview]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1284 const diagnostics = content.querySelector("[data-latex-diagnostics]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1285 const downloadOwner = content.querySelector("[data-latex-download]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1286 const download = downloadOwner.querySelector("a"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1287 source.value = String.raw`\documentclass[11pt]{article} |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1288 \usepackage[margin=1in]{geometry} |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1289 \title{JRPG LaTeX} |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1290 \author{MrJuneJune} |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1291 \begin{document} |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1292 \maketitle |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1293 This PDF was compiled from the cyberpunk tool modal. |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1294 \end{document}`; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1295 let controller = null; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1296 let pdfUrl = null; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1297 let compileGeneration = 0; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1298 const clearPdf = () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1299 if (pdfUrl) URL.revokeObjectURL(pdfUrl); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1300 pdfUrl = null; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1301 preview.src = "about:blank"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1302 preview.hidden = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1303 diagnostics.hidden = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1304 download.removeAttribute("href"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1305 downloadOwner.hidden = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1306 }; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1307 const updateSize = () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1308 const bytes = new TextEncoder().encode(source.value).byteLength; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1309 size.textContent = `${bytes.toLocaleString()} / 65,536 bytes`; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1310 return bytes; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1311 }; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1312 const compile = async () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1313 const generation = ++compileGeneration; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1314 clearPdf(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1315 const bytes = updateSize(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1316 if (!source.value.trim() || bytes > 64 * 1024) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1317 toolStatus.textContent = bytes > 64 * 1024 |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1318 ? "Source exceeds 64 KiB." |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1319 : "Write LaTeX before compiling."; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1320 toolStatus.dataset.state = "error"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1321 return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1322 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1323 controller?.abort(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1324 const requestController = new AbortController(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1325 controller = requestController; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1326 compileButton.disabled = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1327 toolStatus.textContent = "Compiling on the server..."; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1328 toolStatus.dataset.state = "working"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1329 try { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1330 const response = await fetch("/api/latex/render", { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1331 method: "POST", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1332 headers: { "Content-Type": "text/plain; charset=utf-8" }, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1333 body: source.value, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1334 cache: "no-store", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1335 signal: requestController.signal, |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1336 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1337 if (generation !== compileGeneration) return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1338 if (!response.ok) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1339 throw new Error(await response.text() || `Compilation failed (${response.status})`); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1340 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1341 const blob = await response.blob(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1342 if (generation !== compileGeneration) return; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1343 if (blob.type !== "application/pdf" || blob.size < 5) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1344 throw new Error("The server returned an invalid PDF."); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1345 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1346 if (pdfUrl) URL.revokeObjectURL(pdfUrl); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1347 pdfUrl = URL.createObjectURL(blob); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1348 preview.src = pdfUrl; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1349 preview.hidden = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1350 diagnostics.hidden = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1351 download.href = pdfUrl; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1352 downloadOwner.hidden = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1353 toolStatus.textContent = `PDF ready (${Math.ceil(blob.size / 1024)} KiB).`; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1354 toolStatus.dataset.state = "ready"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1355 } catch (error) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1356 if (error.name !== "AbortError" && generation === compileGeneration) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1357 diagnostics.textContent = error.message; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1358 diagnostics.hidden = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1359 preview.hidden = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1360 toolStatus.textContent = "Compilation failed."; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1361 toolStatus.dataset.state = "error"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1362 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1363 } finally { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1364 if (controller === requestController) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1365 controller = null; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1366 compileButton.disabled = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1367 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1368 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1369 }; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1370 source.addEventListener("input", () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1371 compileGeneration++; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1372 controller?.abort(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1373 controller = null; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1374 compileButton.disabled = false; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1375 clearPdf(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1376 updateSize(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1377 toolStatus.textContent = "Changes ready to compile."; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1378 toolStatus.dataset.state = "working"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1379 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1380 compileButton.addEventListener("click", () => void compile()); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1381 updateSize(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1382 this._toolCleanup = () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1383 compileGeneration++; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1384 controller?.abort(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1385 clearPdf(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1386 }; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1387 status.hidden = true; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1388 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1389 |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1390 cleanupTool() { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1391 this._toolCleanup?.(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1392 this._toolCleanup = null; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1393 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1394 |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1395 createReadonlyToolNote() { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1396 const introduction = document.createElement("p"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1397 introduction.className = "jrpg-tool-readonly-note"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1398 introduction.textContent = |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1399 "Read-only preview. Open the full page to use this tool."; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1400 return introduction; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1401 } |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1402 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1403 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1404 class MjjJrpgShell extends HTMLElement {} |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1405 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1406 for (const [name, constructor] of Object.entries({ |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1407 "mjj-jrpg-character": MjjJrpgCharacter, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1408 "mjj-jrpg-chat": MjjJrpgChat, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1409 "mjj-jrpg-composer": MjjJrpgComposer, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1410 "mjj-jrpg-menu": MjjJrpgMenu, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1411 "mjj-jrpg-preview": MjjJrpgPreview, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1412 "mjj-jrpg-shell": MjjJrpgShell, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1413 })) { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1414 if (!customElements.get(name)) customElements.define(name, constructor); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1415 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1416 |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1417 async function requestJson(url, options = {}) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1418 const response = await fetch(url, { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1419 ...options, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1420 headers: { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1421 "Content-Type": "application/json", |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1422 ...options.headers, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1423 }, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1424 }); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1425 if (!response.ok) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1426 let message = `Request failed (${response.status})`; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1427 try { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1428 const body = await response.json(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1429 message = body.error?.message || message; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1430 } catch { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1431 // Preserve the status-derived message. |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1432 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1433 throw new Error(message); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1434 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1435 return response.status === 204 ? null : response.json(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1436 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1437 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1438 async function consumeSse(response, onEvent) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1439 if (!response.body) throw new Error("Streaming response body is unavailable"); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1440 const reader = response.body.getReader(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1441 const decoder = new TextDecoder(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1442 let buffer = ""; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1443 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1444 const dispatch = block => { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1445 let eventName = "message"; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1446 const data = []; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1447 for (const line of block.split("\n")) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1448 if (line.startsWith("event:")) eventName = line.slice(6).trim(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1449 else if (line.startsWith("data:")) data.push(line.slice(5).trimStart()); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1450 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1451 if (!data.length) return; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1452 onEvent(eventName, JSON.parse(data.join("\n"))); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1453 }; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1454 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1455 while (true) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1456 const { done, value } = await reader.read(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1457 buffer += decoder.decode(value || new Uint8Array(), { stream: !done }); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1458 buffer = buffer.replaceAll("\r\n", "\n"); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1459 let boundary; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1460 while ((boundary = buffer.indexOf("\n\n")) >= 0) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1461 const block = buffer.slice(0, boundary); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1462 buffer = buffer.slice(boundary + 2); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1463 if (block.trim()) dispatch(block); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1464 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1465 if (done) break; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1466 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1467 if (buffer.trim()) dispatch(buffer); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1468 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1469 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1470 async function initializeJrpgPage() { |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1471 const colorProbe = document.createElement("span"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1472 colorProbe.style.background = "var(--zenbu-sys-color-surface-page)"; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1473 document.body.append(colorProbe); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1474 const themeColor = getComputedStyle(colorProbe).backgroundColor; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1475 colorProbe.remove(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1476 for (const meta of document.querySelectorAll('meta[name="theme-color"]')) { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1477 meta.setAttribute("content", themeColor); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1478 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1479 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1480 const shell = document.querySelector("mjj-jrpg-shell"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1481 const character = shell?.querySelector("mjj-jrpg-character"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1482 const chat = shell?.querySelector("mjj-jrpg-chat"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1483 const composer = shell?.querySelector("mjj-jrpg-composer"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1484 const preview = shell?.querySelector("mjj-jrpg-preview"); |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1485 const frameNetwork = shell?.querySelector("[data-frame-network]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1486 const frameUptime = shell?.querySelector("[data-frame-uptime]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1487 const minimizeButton = shell?.querySelector("[data-frame-minimize]"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1488 const fullscreenButton = shell?.querySelector("[data-frame-fullscreen]"); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1489 let characterTimer = 0; |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1490 let conversationId = sessionStorage.getItem(CONVERSATION_STORAGE_KEY); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1491 let activeController = null; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1492 composer?.setDisabled(true); |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1493 const setFrameStatus = (label, state, title = "") => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1494 if (frameNetwork) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1495 frameNetwork.textContent = label; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1496 frameNetwork.setAttribute("aria-label", `Status ${label.toLowerCase()}`); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1497 frameNetwork.dataset.state = state; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1498 frameNetwork.title = title; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1499 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1500 }; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1501 setFrameStatus("ONLINE", "online"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1502 const startedAt = Date.now(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1503 const updateUptime = () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1504 const elapsed = Math.floor((Date.now() - startedAt) / 1000); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1505 const hours = String(Math.floor(elapsed / 3600)).padStart(2, "0"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1506 const minutes = String(Math.floor((elapsed % 3600) / 60)).padStart(2, "0"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1507 const seconds = String(elapsed % 60).padStart(2, "0"); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1508 if (frameUptime) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1509 frameUptime.textContent = `${hours}:${minutes}:${seconds}`; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1510 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1511 }; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1512 updateUptime(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1513 window.setInterval(updateUptime, 1000); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1514 |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1515 minimizeButton?.addEventListener("click", () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1516 const minimized = shell.dataset.minimized !== "true"; |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1517 shell.dataset.minimized = String(minimized); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1518 minimizeButton.setAttribute("aria-pressed", String(minimized)); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1519 minimizeButton.setAttribute( |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1520 "aria-label", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1521 minimized ? "Restore interface" : "Minimize interface", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1522 ); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1523 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1524 fullscreenButton?.addEventListener("click", async () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1525 try { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1526 if (document.fullscreenElement) await document.exitFullscreen(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1527 else await shell.requestFullscreen(); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1528 } catch (error) { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1529 setFrameStatus("DENIED", "offline", error.message); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1530 } |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1531 }); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1532 document.addEventListener("fullscreenchange", () => { |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1533 fullscreenButton?.setAttribute( |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1534 "aria-pressed", |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1535 String(Boolean(document.fullscreenElement)), |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1536 ); |
|
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1537 }); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1538 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1539 if (conversationId) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1540 try { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1541 const conversation = await requestJson( |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1542 `/api/conversations/${encodeURIComponent(conversationId)}`, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1543 { headers: {} }, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1544 ); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1545 chat?.replaceMessages(conversation.turns); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1546 } catch { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1547 sessionStorage.removeItem(CONVERSATION_STORAGE_KEY); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1548 conversationId = null; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1549 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1550 } |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1551 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1552 shell?.addEventListener("mjj-jrpg-preview-change", event => { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1553 preview?.show(event.detail.selection); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1554 character?.setAttribute("state", "thinking"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1555 window.clearTimeout(characterTimer); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1556 characterTimer = window.setTimeout(() => { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1557 character?.setAttribute("state", "default"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1558 }, 650); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1559 }); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1560 |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1561 shell?.addEventListener("mjj-jrpg-cancel", () => { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1562 activeController?.abort(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1563 }); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1564 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1565 shell?.addEventListener("mjj-jrpg-submit", async event => { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1566 if (activeController) return; |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1567 chat?.appendMessage("June", event.detail.message); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1568 composer?.setBusy(true); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1569 character?.setAttribute("state", "thinking"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1570 window.clearTimeout(characterTimer); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1571 const assistantItem = chat?.startAssistantMessage(); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1572 chat?.setMessageStreaming(assistantItem, true); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1573 const assistantText = new StreamingTextAnimator(text => { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1574 chat?.setMessageText(assistantItem, text); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1575 }); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1576 let turnFinished = false; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1577 activeController = new AbortController(); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1578 activeController.signal.addEventListener("abort", () => { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1579 assistantText.cancel(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1580 }, { once: true }); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1581 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1582 try { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1583 const createConversation = async () => { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1584 const conversation = await requestJson("/api/conversations", { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1585 method: "POST", |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1586 body: JSON.stringify({ title: "Shiba Quest" }), |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1587 }); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1588 conversationId = conversation.id; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1589 sessionStorage.setItem(CONVERSATION_STORAGE_KEY, conversationId); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1590 }; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1591 if (!conversationId) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1592 await createConversation(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1593 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1594 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1595 const postTurn = () => fetch( |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1596 `/api/conversations/${encodeURIComponent(conversationId)}/turns`, { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1597 method: "POST", |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1598 headers: { "Content-Type": "application/json" }, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1599 body: JSON.stringify({ prompt: event.detail.message }), |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1600 signal: activeController.signal, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1601 }, |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1602 ); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1603 let response = await postTurn(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1604 if (response.status === 404) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1605 sessionStorage.removeItem(CONVERSATION_STORAGE_KEY); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1606 conversationId = null; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1607 await createConversation(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1608 response = await postTurn(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1609 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1610 if (!response.ok) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1611 let message = `Turn failed (${response.status})`; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1612 try { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1613 const body = await response.json(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1614 message = body.error?.message || message; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1615 } catch { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1616 // Preserve the status-derived message. |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1617 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1618 throw new Error(message); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1619 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1620 await consumeSse(response, (eventName, data) => { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1621 shell?.dispatchEvent(new CustomEvent("mjj-jrpg-stream-event", { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1622 bubbles: true, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1623 detail: { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1624 data, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1625 type: eventName, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1626 }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1627 })); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1628 if (eventName === "assistant.delta") { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1629 assistantText.append(data.delta || ""); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1630 } else if (eventName === "assistant.completed") { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1631 assistantText.complete(data.content); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1632 } else if (eventName === "turn.error") { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1633 throw new Error( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1634 data.error?.message || data.message || "Inference turn failed", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1635 ); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1636 } else if (eventName === "turn.done") { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1637 turnFinished = true; |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1638 composer?.setCancellable(false); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1639 if (data.failed || data.aborted) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1640 throw new Error( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1641 data.aborted ? "Inference turn aborted" : "Inference turn failed", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1642 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1643 } |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1644 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1645 }); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1646 if (!turnFinished) throw new Error("Inference stream ended unexpectedly"); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1647 await assistantText.waitForIdle(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1648 if (activeController.signal.aborted) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1649 throw new DOMException("Quest cancelled", "AbortError"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1650 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1651 chat?.setMessageStreaming(assistantItem, false); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1652 character?.setAttribute("state", "default"); |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1653 setFrameStatus("ONLINE", "online"); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1654 } catch (error) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1655 const aborted = error instanceof DOMException && error.name === "AbortError"; |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1656 assistantText.cancel(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
1657 chat?.setMessageStreaming(assistantItem, false); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1658 chat?.setMessageText( |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1659 assistantItem, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1660 aborted ? "Quest cancelled." : `System error: ${error.message}`, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1661 ); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1662 character?.setAttribute("state", "sad"); |
|
263
ee04e4e69fed
Add functional JRPG frame and tools
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
262
diff
changeset
|
1663 if (!aborted) setFrameStatus("OFFLINE", "offline"); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1664 } finally { |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1665 composer?.setBusy(false); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1666 composer?.querySelector("textarea")?.focus(); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1667 activeController = null; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1668 } |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1669 }); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1670 composer?.setDisabled(false); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1671 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1672 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1673 if (document.readyState === "loading") { |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1674 document.addEventListener("DOMContentLoaded", () => { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1675 void initializeJrpgPage(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1676 }, { |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1677 once: true, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1678 }); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1679 } else { |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
1680 void initializeJrpgPage(); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
1681 } |