Mercurial
annotate mrjunejune/src/jrpg/jrpg.js @ 261:b401627fc49e
Add JRPG mock flows and interactive previews
Add scripted mock SSE commands, custom event forwarding, animated chat turns, full-height message navigation, and a cyberpunk resume dossier.
Co-authored-by: Copilot <[email protected]>
| author | MrJuneJune <mrjunejune@users.noreply.github.com> |
|---|---|
| date | Wed, 05 Aug 2026 20:38:32 -0700 |
| parents | 1f9877b637e9 |
| children | 0f45474c1b1a |
| 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 type: "Profile", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
22 url: "/resume", |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
23 works: [ |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
24 { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
25 detail: "Agentic execution", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
26 label: "Copilot Tasks", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
27 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
|
28 }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
29 { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
30 detail: "AI platform", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
31 label: "Copilot SuperApp", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
32 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
|
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: "Build 2026", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
36 label: "Code", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
37 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
|
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: "Personal agent", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
41 label: "Autopilot", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
42 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
|
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: "Ads systems", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
46 label: "Meta", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
47 url: "https://www.meta.com/", |
|
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: "Workspace platform", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
51 label: "Google", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
52 url: "https://www.google.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 ], |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
55 }, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
56 tools: { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
57 copy: "Small, focused utilities for writing, media, and experimentation.", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
58 kicker: "ITEM INVENTORY", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
59 title: "Tools", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
60 type: "Utilities", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
61 url: "/tools", |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
62 works: [ |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
63 { 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
|
64 { 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
|
65 { 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
|
66 ], |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
67 }, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
68 blog: { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
69 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
|
70 kicker: "QUEST ARCHIVE", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
71 title: "Blogs", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
72 type: "Writing", |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
73 url: "/blog", |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
74 works: [ |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
75 { 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
|
76 ], |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
77 }, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
78 }); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
79 |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
80 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
|
81 const TYPING_INTERVAL_MS = 18; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
82 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
83 class StreamingTextAnimator { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
84 constructor(render) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
85 this._render = render; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
86 this._displayed = ""; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
87 this._target = ""; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
88 this._timer = 0; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
89 this._waiters = []; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
90 this._reduceMotion = window.matchMedia( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
91 "(prefers-reduced-motion: reduce)", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
92 ).matches; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
93 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
94 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
95 append(text) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
96 if (typeof text !== "string" || !text) return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
97 this._target += text; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
98 this._schedule(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
99 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
100 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
101 complete(text) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
102 if (typeof text === "string") { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
103 this._target = text; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
104 if (!this._target.startsWith(this._displayed)) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
105 let shared = 0; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
106 while ( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
107 shared < this._target.length && |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
108 shared < this._displayed.length && |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
109 this._target[shared] === this._displayed[shared] |
|
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 shared++; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
112 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
113 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
|
114 this._render(this._displayed); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
115 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
116 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
117 this._schedule(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
118 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
119 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
120 waitForIdle() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
121 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
|
122 return Promise.resolve(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
123 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
124 return new Promise(resolve => { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
125 this._waiters.push(resolve); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
126 }); |
|
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 cancel() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
130 window.clearTimeout(this._timer); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
131 this._timer = 0; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
132 this._target = this._displayed; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
133 this._settle(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
134 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
135 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
136 _schedule() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
137 if (this._reduceMotion) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
138 this._displayed = this._target; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
139 this._render(this._displayed); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
140 this._settle(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
141 return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
142 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
143 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
|
144 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
|
145 } |
|
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 _tick() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
148 this._timer = 0; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
149 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
|
150 if (remaining <= 0) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
151 this._settle(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
152 return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
153 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
154 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
|
155 this._displayed = this._target.slice( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
156 0, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
157 this._displayed.length + amount, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
158 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
159 this._render(this._displayed); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
160 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
|
161 else this._schedule(); |
|
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 _settle() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
165 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
|
166 const waiters = this._waiters.splice(0); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
167 for (const resolve of waiters) resolve(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
168 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
169 } |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
170 |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
171 class MjjJrpgCharacter extends HTMLElement { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
172 static get observedAttributes() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
173 return ["state"]; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
174 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
175 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
176 connectedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
177 this.render(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
178 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
179 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
180 attributeChangedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
181 if (this.isConnected) this.render(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
182 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
183 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
184 render() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
185 const image = this.querySelector("[data-character]"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
186 if (!image) return; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
187 const state = CHARACTER_STATES[this.getAttribute("state")] || |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
188 CHARACTER_STATES.default; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
189 image.src = state.src; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
190 image.alt = state.alt; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
191 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
192 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
193 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
194 class MjjJrpgChat extends HTMLElement { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
195 connectedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
196 this._messages = this.querySelector("[data-messages]"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
197 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
|
198 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
|
199 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
|
200 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
|
201 this._initialMessages = [...(this._messages?.children || [])].map( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
202 item => item.cloneNode(true), |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
203 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
204 this._turnSequence = 0; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
205 this._activeGroup = null; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
206 this._onNavigationClick = event => { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
207 const button = event.target.closest("button"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
208 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
|
209 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
|
210 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
|
211 }; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
212 this.addEventListener("click", this._onNavigationClick); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
213 this._refreshTurnGroups("start"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
214 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
215 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
216 disconnectedCallback() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
217 this.removeEventListener("click", this._onNavigationClick); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
218 } |
|
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 appendMessage(speaker, text) { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
221 let group = this._activeGroup || "start"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
222 if (speaker === "June") { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
223 this._turnSequence++; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
224 group = `turn-${this._turnSequence}`; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
225 this._activeGroup = group; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
226 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
227 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
|
228 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
229 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
230 _createMessage(speaker, text, group, select) { |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
231 if (!this._messages) return; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
232 const item = document.createElement("li"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
233 const name = document.createElement("strong"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
234 const copy = document.createElement("p"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
235 item.className = "jrpg-message"; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
236 item.dataset.speaker = speaker; |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
237 item.dataset.turnGroup = group; |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
238 name.textContent = speaker; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
239 copy.textContent = text; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
240 item.append(name, copy); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
241 this._messages.append(item); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
242 this._refreshTurnGroups(select ? group : this._currentGroup); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
243 return item; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
244 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
245 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
246 replaceMessages(turns) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
247 if (!this._messages) return; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
248 this._messages.replaceChildren(); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
249 this._turnSequence = 0; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
250 this._activeGroup = null; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
251 const visibleTurns = turns.filter(turn => |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
252 ["user", "assistant"].includes(turn.role) |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
253 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
254 if (!visibleTurns.length) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
255 this._messages.append( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
256 ...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
|
257 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
258 this._refreshTurnGroups("start"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
259 return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
260 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
261 let group = null; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
262 for (const turn of visibleTurns) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
263 if (turn.role === "user" || !group) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
264 this._turnSequence++; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
265 group = `turn-${this._turnSequence}`; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
266 this._activeGroup = group; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
267 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
268 this._createMessage( |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
269 turn.role === "user" ? "June" : "Epi", |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
270 turn.content || |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
271 (turn.status === "aborted" |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
272 ? "Quest cancelled." |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
273 : turn.status === "failed" |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
274 ? "The quest failed." |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
275 : ""), |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
276 group, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
277 false, |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
278 ); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
279 } |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
280 this._refreshTurnGroups(group); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
281 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
282 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
283 startAssistantMessage() { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
284 return this.appendMessage("Epi", ""); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
285 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
286 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
287 setMessageText(item, text) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
288 const copy = item?.querySelector("p"); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
289 if (copy) copy.textContent = text; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
290 this.scrollEnd(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
291 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
292 |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
293 setMessageStreaming(item, streaming) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
294 if (!item) return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
295 if (streaming) item.dataset.streaming = "true"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
296 else delete item.dataset.streaming; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
297 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
|
298 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
299 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
300 _refreshTurnGroups(preferredGroup) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
301 const groups = []; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
302 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
|
303 const group = item.dataset.turnGroup || "start"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
304 item.dataset.turnGroup = group; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
305 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
|
306 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
307 this._turnGroups = groups; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
308 const preferredIndex = groups.indexOf(preferredGroup); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
309 const currentIndex = groups.indexOf(this._currentGroup); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
310 this._turnIndex = preferredIndex >= 0 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
311 ? preferredIndex |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
312 : currentIndex >= 0 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
313 ? currentIndex |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
314 : Math.max(0, groups.length - 1); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
315 this._showTurn(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
316 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
317 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
318 _moveTurn(offset) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
319 const nextIndex = Math.max( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
320 0, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
321 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
|
322 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
323 if (nextIndex === this._turnIndex) return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
324 this._turnIndex = nextIndex; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
325 this._showTurn(); |
|
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 _showTurn() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
329 const group = this._turnGroups?.[this._turnIndex]; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
330 this._currentGroup = group; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
331 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
|
332 item.hidden = item.dataset.turnGroup !== group; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
333 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
334 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
|
335 if (this._nextButton) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
336 this._nextButton.disabled = |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
337 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
|
338 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
339 if (this._position) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
340 if (group === "start") { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
341 this._position.textContent = "START"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
342 } else { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
343 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
|
344 this._position.textContent = |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
345 `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
|
346 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
347 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
348 this.scrollEnd(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
349 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
350 |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
351 scrollEnd() { |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
352 requestAnimationFrame(() => { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
353 if (this._viewport) { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
354 this._viewport.scrollTop = this._viewport.scrollHeight; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
355 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
356 }); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
357 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
358 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
359 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
360 class MjjJrpgComposer extends HTMLElement { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
361 connectedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
362 this._form = this.querySelector("[data-composer]"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
363 this._textarea = this.querySelector("textarea"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
364 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
|
365 this._cancel = this.querySelector("[data-cancel]"); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
366 this._cancelControl = this.querySelector("[data-cancel-control]"); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
367 this._onSubmit = event => { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
368 event.preventDefault(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
369 const message = this._textarea?.value.trim(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
370 if (!message || this._button?.disabled) return; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
371 this.dispatchEvent(new CustomEvent("mjj-jrpg-submit", { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
372 bubbles: true, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
373 detail: { message }, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
374 })); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
375 this._form.reset(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
376 }; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
377 this._onKeydown = event => { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
378 if (event.key !== "Enter" || event.shiftKey || event.isComposing) return; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
379 event.preventDefault(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
380 this._form?.requestSubmit(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
381 }; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
382 this._form?.addEventListener("submit", this._onSubmit); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
383 this._textarea?.addEventListener("keydown", this._onKeydown); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
384 this._onCancel = () => { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
385 this.dispatchEvent(new CustomEvent("mjj-jrpg-cancel", { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
386 bubbles: true, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
387 })); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
388 }; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
389 this._cancel?.addEventListener("click", this._onCancel); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
390 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
391 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
392 disconnectedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
393 this._form?.removeEventListener("submit", this._onSubmit); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
394 this._textarea?.removeEventListener("keydown", this._onKeydown); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
395 this._cancel?.removeEventListener("click", this._onCancel); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
396 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
397 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
398 setBusy(busy) { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
399 if (this._textarea) this._textarea.disabled = busy; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
400 if (this._button) { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
401 this._button.disabled = busy; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
402 this._button.setAttribute("aria-busy", String(busy)); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
403 } |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
404 if (this._cancelControl) this._cancelControl.hidden = !busy; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
405 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
406 |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
407 setCancellable(cancellable) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
408 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
|
409 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
410 |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
411 setDisabled(disabled) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
412 if (this._textarea) this._textarea.disabled = disabled; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
413 if (this._button) this._button.disabled = disabled; |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
414 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
415 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
416 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
417 class MjjJrpgMenu extends HTMLElement { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
418 connectedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
419 this._onClick = event => { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
420 const button = event.target.closest("button[data-preview]"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
421 if (!button || !this.contains(button)) return; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
422 for (const item of this.querySelectorAll("button[data-preview]")) { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
423 item.setAttribute("aria-pressed", String(item === button)); |
|
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 this.dispatchEvent(new CustomEvent("mjj-jrpg-preview-change", { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
426 bubbles: true, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
427 detail: { selection: button.dataset.preview }, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
428 })); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
429 }; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
430 this.addEventListener("click", this._onClick); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
431 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
432 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
433 disconnectedCallback() { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
434 this.removeEventListener("click", this._onClick); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
435 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
436 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
437 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
438 class MjjJrpgPreview extends HTMLElement { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
439 connectedCallback() { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
440 this._onClick = event => { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
441 if ( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
442 event.target.closest("[data-zen-trigger]") && |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
443 this.dataset.selection === "resume" |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
444 ) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
445 void this.loadResume(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
446 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
447 }; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
448 this.addEventListener("click", this._onClick); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
449 this.show(this.dataset.selection || "resume"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
450 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
451 |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
452 disconnectedCallback() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
453 this.removeEventListener("click", this._onClick); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
454 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
455 |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
456 show(selection) { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
457 const preview = PREVIEWS[selection] || PREVIEWS.resume; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
458 this.dataset.selection = selection; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
459 this.querySelector("[data-preview-kicker]").textContent = preview.kicker; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
460 this.querySelector("[data-preview-title]").textContent = preview.title; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
461 this.querySelector("[data-preview-copy]").textContent = preview.copy; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
462 this.querySelector("[data-preview-type]").textContent = preview.type; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
463 this.querySelector("[data-dialog-title]").textContent = preview.title; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
464 this.querySelector("[data-dialog-copy]").textContent = preview.copy; |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
465 const showcase = this.querySelector("[data-work-showcase]"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
466 showcase.replaceChildren(...preview.works.map(work => { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
467 const item = document.createElement("li"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
468 const link = document.createElement("a"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
469 const label = document.createElement("span"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
470 const detail = document.createElement("small"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
471 link.href = work.url; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
472 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
|
473 link.target = "_blank"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
474 link.rel = "noreferrer"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
475 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
476 label.textContent = work.label; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
477 detail.textContent = work.detail; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
478 link.append(label, detail); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
479 item.append(link); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
480 return item; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
481 })); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
482 const link = this.querySelector("[data-preview-link]"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
483 link.href = preview.url; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
484 link.setAttribute("aria-label", `Open ${preview.title}`); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
485 const resumeDossier = this.querySelector("[data-resume-dossier]"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
486 const resumeDownload = this.querySelector("[data-resume-download]"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
487 const isResume = selection === "resume"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
488 resumeDossier.hidden = !isResume; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
489 resumeDownload.hidden = !isResume; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
490 this.querySelector("[data-dialog-copy]").hidden = isResume; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
491 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
492 |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
493 async loadResume() { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
494 if (this._resumeLoaded || this._resumeLoading) return; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
495 this._resumeLoading = true; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
496 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
|
497 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
|
498 try { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
499 const response = await fetch("/resume", { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
500 headers: { Accept: "text/html" }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
501 }); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
502 if (!response.ok) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
503 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
|
504 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
505 const documentCopy = new DOMParser().parseFromString( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
506 await response.text(), |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
507 "text/html", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
508 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
509 const resume = documentCopy.querySelector("main"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
510 if (!resume) throw new Error("Resume content is unavailable"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
511 for (const unsafe of resume.querySelectorAll( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
512 "embed, iframe, object, script, style, svg", |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
513 )) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
514 unsafe.remove(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
515 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
516 for (const element of resume.querySelectorAll("*")) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
517 for (const attribute of [...element.attributes]) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
518 if (attribute.name.toLowerCase().startsWith("on")) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
519 element.removeAttribute(attribute.name); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
520 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
521 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
522 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
523 for (const anchor of resume.querySelectorAll("a")) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
524 const target = new URL(anchor.href, window.location.href); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
525 if (target.origin !== window.location.origin) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
526 anchor.target = "_blank"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
527 anchor.rel = "noreferrer"; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
528 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
529 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
530 content.replaceChildren(...resume.childNodes); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
531 status.hidden = true; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
532 this._resumeLoaded = true; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
533 } catch (error) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
534 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
|
535 } finally { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
536 this._resumeLoading = false; |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
537 } |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
538 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
539 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
540 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
541 class MjjJrpgShell extends HTMLElement {} |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
542 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
543 for (const [name, constructor] of Object.entries({ |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
544 "mjj-jrpg-character": MjjJrpgCharacter, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
545 "mjj-jrpg-chat": MjjJrpgChat, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
546 "mjj-jrpg-composer": MjjJrpgComposer, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
547 "mjj-jrpg-menu": MjjJrpgMenu, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
548 "mjj-jrpg-preview": MjjJrpgPreview, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
549 "mjj-jrpg-shell": MjjJrpgShell, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
550 })) { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
551 if (!customElements.get(name)) customElements.define(name, constructor); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
552 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
553 |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
554 async function requestJson(url, options = {}) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
555 const response = await fetch(url, { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
556 ...options, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
557 headers: { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
558 "Content-Type": "application/json", |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
559 ...options.headers, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
560 }, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
561 }); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
562 if (!response.ok) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
563 let message = `Request failed (${response.status})`; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
564 try { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
565 const body = await response.json(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
566 message = body.error?.message || message; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
567 } catch { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
568 // Preserve the status-derived message. |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
569 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
570 throw new Error(message); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
571 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
572 return response.status === 204 ? null : response.json(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
573 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
574 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
575 async function consumeSse(response, onEvent) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
576 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
|
577 const reader = response.body.getReader(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
578 const decoder = new TextDecoder(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
579 let buffer = ""; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
580 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
581 const dispatch = block => { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
582 let eventName = "message"; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
583 const data = []; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
584 for (const line of block.split("\n")) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
585 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
|
586 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
|
587 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
588 if (!data.length) return; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
589 onEvent(eventName, JSON.parse(data.join("\n"))); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
590 }; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
591 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
592 while (true) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
593 const { done, value } = await reader.read(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
594 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
|
595 buffer = buffer.replaceAll("\r\n", "\n"); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
596 let boundary; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
597 while ((boundary = buffer.indexOf("\n\n")) >= 0) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
598 const block = buffer.slice(0, boundary); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
599 buffer = buffer.slice(boundary + 2); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
600 if (block.trim()) dispatch(block); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
601 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
602 if (done) break; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
603 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
604 if (buffer.trim()) dispatch(buffer); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
605 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
606 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
607 async function initializeJrpgPage() { |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
608 const colorProbe = document.createElement("span"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
609 colorProbe.style.background = "var(--zenbu-sys-color-surface-page)"; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
610 document.body.append(colorProbe); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
611 const themeColor = getComputedStyle(colorProbe).backgroundColor; |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
612 colorProbe.remove(); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
613 for (const meta of document.querySelectorAll('meta[name="theme-color"]')) { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
614 meta.setAttribute("content", themeColor); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
615 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
616 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
617 const shell = document.querySelector("mjj-jrpg-shell"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
618 const character = shell?.querySelector("mjj-jrpg-character"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
619 const chat = shell?.querySelector("mjj-jrpg-chat"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
620 const composer = shell?.querySelector("mjj-jrpg-composer"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
621 const preview = shell?.querySelector("mjj-jrpg-preview"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
622 let characterTimer = 0; |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
623 let conversationId = sessionStorage.getItem(CONVERSATION_STORAGE_KEY); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
624 let activeController = null; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
625 composer?.setDisabled(true); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
626 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
627 if (conversationId) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
628 try { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
629 const conversation = await requestJson( |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
630 `/api/conversations/${encodeURIComponent(conversationId)}`, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
631 { headers: {} }, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
632 ); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
633 chat?.replaceMessages(conversation.turns); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
634 } catch { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
635 sessionStorage.removeItem(CONVERSATION_STORAGE_KEY); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
636 conversationId = null; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
637 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
638 } |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
639 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
640 shell?.addEventListener("mjj-jrpg-preview-change", event => { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
641 preview?.show(event.detail.selection); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
642 character?.setAttribute("state", "thinking"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
643 window.clearTimeout(characterTimer); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
644 characterTimer = window.setTimeout(() => { |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
645 character?.setAttribute("state", "default"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
646 }, 650); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
647 }); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
648 |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
649 shell?.addEventListener("mjj-jrpg-cancel", () => { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
650 activeController?.abort(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
651 }); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
652 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
653 shell?.addEventListener("mjj-jrpg-submit", async event => { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
654 if (activeController) return; |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
655 chat?.appendMessage("June", event.detail.message); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
656 composer?.setBusy(true); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
657 character?.setAttribute("state", "thinking"); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
658 window.clearTimeout(characterTimer); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
659 const assistantItem = chat?.startAssistantMessage(); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
660 chat?.setMessageStreaming(assistantItem, true); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
661 const assistantText = new StreamingTextAnimator(text => { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
662 chat?.setMessageText(assistantItem, text); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
663 }); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
664 let turnFinished = false; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
665 activeController = new AbortController(); |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
666 activeController.signal.addEventListener("abort", () => { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
667 assistantText.cancel(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
668 }, { once: true }); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
669 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
670 try { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
671 const createConversation = async () => { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
672 const conversation = await requestJson("/api/conversations", { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
673 method: "POST", |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
674 body: JSON.stringify({ title: "Shiba Quest" }), |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
675 }); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
676 conversationId = conversation.id; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
677 sessionStorage.setItem(CONVERSATION_STORAGE_KEY, conversationId); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
678 }; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
679 if (!conversationId) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
680 await createConversation(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
681 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
682 |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
683 const postTurn = () => fetch( |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
684 `/api/conversations/${encodeURIComponent(conversationId)}/turns`, { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
685 method: "POST", |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
686 headers: { "Content-Type": "application/json" }, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
687 body: JSON.stringify({ prompt: event.detail.message }), |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
688 signal: activeController.signal, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
689 }, |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
690 ); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
691 let response = await postTurn(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
692 if (response.status === 404) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
693 sessionStorage.removeItem(CONVERSATION_STORAGE_KEY); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
694 conversationId = null; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
695 await createConversation(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
696 response = await postTurn(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
697 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
698 if (!response.ok) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
699 let message = `Turn failed (${response.status})`; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
700 try { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
701 const body = await response.json(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
702 message = body.error?.message || message; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
703 } catch { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
704 // Preserve the status-derived message. |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
705 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
706 throw new Error(message); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
707 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
708 await consumeSse(response, (eventName, data) => { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
709 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
|
710 bubbles: true, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
711 detail: { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
712 data, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
713 type: eventName, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
714 }, |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
715 })); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
716 if (eventName === "assistant.delta") { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
717 assistantText.append(data.delta || ""); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
718 } else if (eventName === "assistant.completed") { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
719 assistantText.complete(data.content); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
720 } else if (eventName === "turn.error") { |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
721 throw new Error( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
722 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
|
723 ); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
724 } else if (eventName === "turn.done") { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
725 turnFinished = true; |
|
261
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
726 composer?.setCancellable(false); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
727 if (data.failed || data.aborted) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
728 throw new Error( |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
729 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
|
730 ); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
731 } |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
732 } |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
733 }); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
734 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
|
735 await assistantText.waitForIdle(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
736 if (activeController.signal.aborted) { |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
737 throw new DOMException("Quest cancelled", "AbortError"); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
738 } |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
739 chat?.setMessageStreaming(assistantItem, false); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
740 character?.setAttribute("state", "default"); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
741 } catch (error) { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
742 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
|
743 assistantText.cancel(); |
|
b401627fc49e
Add JRPG mock flows and interactive previews
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
260
diff
changeset
|
744 chat?.setMessageStreaming(assistantItem, false); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
745 chat?.setMessageText( |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
746 assistantItem, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
747 aborted ? "Quest cancelled." : `System error: ${error.message}`, |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
748 ); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
749 character?.setAttribute("state", "sad"); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
750 } finally { |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
751 composer?.setBusy(false); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
752 composer?.querySelector("textarea")?.focus(); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
753 activeController = null; |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
754 } |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
755 }); |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
756 composer?.setDisabled(false); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
757 } |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
758 |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
759 if (document.readyState === "loading") { |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
760 document.addEventListener("DOMContentLoaded", () => { |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
761 void initializeJrpgPage(); |
|
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
762 }, { |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
763 once: true, |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
764 }); |
|
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
765 } else { |
|
260
1f9877b637e9
Add Copilot-powered cyberpunk JRPG chat
MrJuneJune <mrjunejune@users.noreply.github.com>
parents:
259
diff
changeset
|
766 void initializeJrpgPage(); |
|
259
667156fcd3e3
Add dev-only cyberpunk JRPG page
MrJuneJune <me@mrjunejune.com>
parents:
diff
changeset
|
767 } |