@devaccel-labs/app-comments-toolbar 1.0.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +152 -18
- package/dist/react.js +516 -61
- package/dist/server.js +342 -14
- package/dist/types/capture/api.d.ts +30 -0
- package/dist/types/capture/editor.d.ts +10 -0
- package/dist/types/capture/ignore.d.ts +19 -0
- package/dist/types/capture/index.d.ts +1 -0
- package/dist/types/capture/picker.d.ts +9 -0
- package/dist/types/capture/picture.d.ts +29 -0
- package/dist/types/capture/surface.d.ts +39 -0
- package/dist/types/core/index.d.ts +2 -2
- package/dist/types/core/resolve.d.ts +2 -1
- package/dist/types/core/types.d.ts +11 -0
- package/dist/types/debug-context.d.ts +7 -0
- package/dist/types/dictation.d.ts +9 -0
- package/dist/types/embed/controller.d.ts +61 -0
- package/dist/types/embed/index.d.ts +1 -0
- package/dist/types/embed/options.d.ts +35 -0
- package/dist/types/help/index.d.ts +1 -0
- package/dist/types/help/panel-index.d.ts +1 -0
- package/dist/types/help/panel-styles.d.ts +1 -0
- package/dist/types/help/panel.d.ts +4 -0
- package/dist/types/help/pill-styles.d.ts +11 -0
- package/dist/types/help/pill.d.ts +44 -0
- package/dist/types/help/react.d.ts +12 -0
- package/dist/types/help/requests.d.ts +2 -0
- package/dist/types/help/types.d.ts +119 -0
- package/dist/types/help/wire.d.ts +61 -0
- package/dist/types/native-wire.d.ts +63 -0
- package/dist/types/native.d.ts +43 -0
- package/dist/types/react.d.ts +8 -1
- package/dist/types/replay.d.ts +6 -0
- package/dist/types/runtime/api.d.ts +250 -0
- package/dist/types/runtime/attachment-model.d.ts +16 -0
- package/dist/types/runtime/attachments.d.ts +43 -7
- package/dist/types/runtime/boot.d.ts +39 -0
- package/dist/types/runtime/browser-label.d.ts +5 -0
- package/dist/types/runtime/build-id.d.ts +7 -0
- package/dist/types/runtime/capture-ui.d.ts +45 -21
- package/dist/types/runtime/clarity-model.d.ts +260 -0
- package/dist/types/runtime/clarity-ui.d.ts +62 -0
- package/dist/types/runtime/client.d.ts +6 -197
- package/dist/types/runtime/composer-size.d.ts +30 -0
- package/dist/types/runtime/dashboard.d.ts +17 -2
- package/dist/types/runtime/debug-context-core.d.ts +88 -0
- package/dist/types/runtime/debug-context-host.d.ts +39 -0
- package/dist/types/runtime/debug-context-model.d.ts +352 -0
- package/dist/types/runtime/debug-context-redact.d.ts +48 -0
- package/dist/types/runtime/debug-context.d.ts +36 -0
- package/dist/types/runtime/details-model.d.ts +7 -0
- package/dist/types/runtime/details.d.ts +7 -5
- package/dist/types/runtime/dictation-engine.d.ts +98 -0
- package/dist/types/runtime/dictation-model.d.ts +28 -0
- package/dist/types/runtime/dictation-ui.d.ts +56 -0
- package/dist/types/runtime/dictation.d.ts +66 -0
- package/dist/types/runtime/draft-dock.d.ts +32 -0
- package/dist/types/runtime/draft-model.d.ts +104 -0
- package/dist/types/runtime/draft-store.d.ts +15 -0
- package/dist/types/runtime/edits.d.ts +1 -1
- package/dist/types/runtime/font.d.ts +16 -0
- package/dist/types/runtime/format.d.ts +30 -1
- package/dist/types/runtime/host-watch.d.ts +20 -0
- package/dist/types/runtime/icons.d.ts +16 -2
- package/dist/types/runtime/index.d.ts +3 -1
- package/dist/types/runtime/ink.d.ts +8 -0
- package/dist/types/runtime/kind-model.d.ts +14 -0
- package/dist/types/runtime/live-model.d.ts +25 -0
- package/dist/types/runtime/loader.d.ts +5 -11
- package/dist/types/runtime/markup-editor.d.ts +54 -0
- package/dist/types/runtime/markup-model.d.ts +126 -0
- package/dist/types/runtime/markup.d.ts +69 -0
- package/dist/types/runtime/mention-parse.d.ts +18 -0
- package/dist/types/runtime/mentions.d.ts +4 -4
- package/dist/types/runtime/page-background.d.ts +9 -0
- package/dist/types/runtime/page-image.d.ts +123 -0
- package/dist/types/runtime/placement.d.ts +6 -3
- package/dist/types/runtime/record.d.ts +18 -2
- package/dist/types/runtime/related.d.ts +1 -1
- package/dist/types/runtime/replay-model.d.ts +80 -0
- package/dist/types/runtime/replay.d.ts +5 -38
- package/dist/types/runtime/runtime.d.ts +6 -0
- package/dist/types/runtime/screen.d.ts +47 -0
- package/dist/types/runtime/screenshot.d.ts +60 -6
- package/dist/types/runtime/session-source.d.ts +45 -0
- package/dist/types/runtime/session.d.ts +20 -18
- package/dist/types/runtime/shield.d.ts +9 -0
- package/dist/types/runtime/shot.d.ts +45 -0
- package/dist/types/runtime/sketch.d.ts +26 -0
- package/dist/types/runtime/styles.d.ts +1 -1
- package/dist/types/runtime/sync.d.ts +1 -0
- package/dist/types/runtime/thread-model.d.ts +18 -0
- package/dist/types/runtime/ticket-form-model.d.ts +57 -0
- package/dist/types/runtime/ticket-form.d.ts +9 -0
- package/dist/types/runtime/toolbar.d.ts +37 -1
- package/dist/types/runtime/ui-scale.d.ts +17 -0
- package/dist/types/runtime/update.d.ts +37 -0
- package/dist/types/runtime/use-debug-context.d.ts +27 -0
- package/dist/types/server/index.d.ts +22 -0
- package/dist/types/server/support.d.ts +20 -0
- package/dist/types/server.d.ts +2 -0
- package/dist/types/vite/plugin.d.ts +15 -0
- package/dist/vite.js +121 -41
- package/package.json +26 -13
- package/src/capture/api.ts +128 -0
- package/src/capture/editor.tsx +178 -0
- package/src/capture/ignore.ts +38 -0
- package/src/capture/index.ts +27 -0
- package/src/capture/picker.tsx +171 -0
- package/src/capture/picture.ts +90 -0
- package/src/capture/surface.tsx +185 -0
- package/src/compiler/annotate.ts +202 -0
- package/src/compiler/babel.d.ts +11 -0
- package/src/compiler/enabled.ts +55 -0
- package/src/compiler/index.ts +2 -0
- package/src/core/index.ts +8 -0
- package/src/core/resolve.ts +307 -0
- package/src/core/types.ts +58 -0
- package/src/debug-context.ts +47 -0
- package/src/dictation.ts +17 -0
- package/src/embed/controller.ts +215 -0
- package/src/embed/index.ts +68 -0
- package/src/embed/options.ts +100 -0
- package/src/help/index.ts +38 -0
- package/src/help/panel-index.ts +17 -0
- package/src/help/panel-styles.ts +123 -0
- package/src/help/panel.ts +840 -0
- package/src/help/pill-styles.ts +75 -0
- package/src/help/pill.ts +338 -0
- package/src/help/react.tsx +143 -0
- package/src/help/requests.ts +111 -0
- package/src/help/types.ts +124 -0
- package/src/help/wire.ts +55 -0
- package/src/native-wire.ts +124 -0
- package/src/native.ts +282 -0
- package/src/react.ts +27 -0
- package/src/replay.ts +13 -0
- package/src/runtime/api.ts +531 -0
- package/src/runtime/attachment-model.ts +42 -0
- package/src/runtime/attachments.tsx +1260 -0
- package/src/runtime/boot.ts +95 -0
- package/src/runtime/browser-label.ts +31 -0
- package/src/runtime/build-id.ts +10 -0
- package/src/runtime/capture-ui.tsx +306 -0
- package/src/runtime/capture.ts +508 -0
- package/src/runtime/clarity-model.ts +634 -0
- package/src/runtime/clarity-ui.tsx +454 -0
- package/src/runtime/client.ts +151 -0
- package/src/runtime/composer-size.tsx +146 -0
- package/src/runtime/dashboard.tsx +1130 -0
- package/src/runtime/debug-context-core.ts +681 -0
- package/src/runtime/debug-context-host.ts +56 -0
- package/src/runtime/debug-context-model.ts +1319 -0
- package/src/runtime/debug-context-redact.ts +259 -0
- package/src/runtime/debug-context.ts +613 -0
- package/src/runtime/details-model.ts +30 -0
- package/src/runtime/details.tsx +395 -0
- package/src/runtime/dictation-engine.ts +616 -0
- package/src/runtime/dictation-model.ts +79 -0
- package/src/runtime/dictation-ui.tsx +363 -0
- package/src/runtime/dictation.ts +271 -0
- package/src/runtime/dock.ts +108 -0
- package/src/runtime/draft-dock.tsx +124 -0
- package/src/runtime/draft-model.ts +251 -0
- package/src/runtime/draft-store.ts +149 -0
- package/src/runtime/edits.tsx +165 -0
- package/src/runtime/font.ts +42 -0
- package/src/runtime/format.ts +129 -0
- package/src/runtime/freshness.ts +23 -0
- package/src/runtime/handoff.ts +76 -0
- package/src/runtime/host-watch.ts +64 -0
- package/src/runtime/icons.tsx +295 -0
- package/src/runtime/idle.ts +20 -0
- package/src/runtime/index.ts +11 -0
- package/src/runtime/ink.ts +6 -0
- package/src/runtime/kind-model.ts +20 -0
- package/src/runtime/live-model.ts +32 -0
- package/src/runtime/loader.tsx +87 -0
- package/src/runtime/markup-editor.tsx +1333 -0
- package/src/runtime/markup-model.ts +485 -0
- package/src/runtime/markup.ts +382 -0
- package/src/runtime/members.ts +58 -0
- package/src/runtime/mention-parse.ts +56 -0
- package/src/runtime/mentions.tsx +205 -0
- package/src/runtime/page-background.ts +51 -0
- package/src/runtime/page-image.ts +1592 -0
- package/src/runtime/placement.ts +336 -0
- package/src/runtime/record.ts +402 -0
- package/src/runtime/redact.ts +30 -0
- package/src/runtime/related.ts +34 -0
- package/src/runtime/render-page.ts +2 -0
- package/src/runtime/replay-model.ts +232 -0
- package/src/runtime/replay.ts +173 -0
- package/src/runtime/runtime-version.ts +7 -0
- package/src/runtime/runtime.tsx +51 -0
- package/src/runtime/screen.ts +182 -0
- package/src/runtime/screenshot.ts +260 -0
- package/src/runtime/session-source.ts +112 -0
- package/src/runtime/session.ts +108 -0
- package/src/runtime/shield.ts +34 -0
- package/src/runtime/shot.tsx +422 -0
- package/src/runtime/sketch.ts +139 -0
- package/src/runtime/styles.ts +1541 -0
- package/src/runtime/sync.ts +300 -0
- package/src/runtime/thread-model.ts +71 -0
- package/src/runtime/ticket-form-model.ts +128 -0
- package/src/runtime/ticket-form.tsx +342 -0
- package/src/runtime/toolbar.tsx +4427 -0
- package/src/runtime/ui-scale.ts +75 -0
- package/src/runtime/update.ts +98 -0
- package/src/runtime/use-debug-context.ts +81 -0
- package/src/server/index.ts +133 -0
- package/src/server/support.ts +499 -0
- package/src/server.ts +4 -0
- package/src/vite/plugin.ts +102 -0
- package/src/vite.ts +1 -0
- package/dist/chunks/chunk-CSKXLF33.js +0 -153
- package/dist/chunks/chunk-HUM5FQII.js +0 -160
- package/dist/chunks/render-page-76MLIT6M.js +0 -1421
- package/dist/chunks/runtime-JX75TKER.js +0 -9267
- package/dist/chunks/screenshot-66ARTBGR.js +0 -12
package/dist/react.js
CHANGED
|
@@ -1,91 +1,546 @@
|
|
|
1
|
-
import {
|
|
2
|
-
captureHandoff,
|
|
3
|
-
runtimeVersion,
|
|
4
|
-
sessionFor,
|
|
5
|
-
whenIdle
|
|
6
|
-
} from "./chunks/chunk-CSKXLF33.js";
|
|
7
|
-
|
|
8
1
|
// src/runtime/loader.tsx
|
|
9
2
|
import { useEffect, useRef } from "react";
|
|
3
|
+
|
|
4
|
+
// src/runtime/idle.ts
|
|
5
|
+
var FALLBACK_SLICE_MS = 8;
|
|
6
|
+
function whenIdle(task, timeout) {
|
|
7
|
+
if (typeof requestIdleCallback === "function") {
|
|
8
|
+
const id2 = requestIdleCallback(task, { timeout });
|
|
9
|
+
return () => cancelIdleCallback(id2);
|
|
10
|
+
}
|
|
11
|
+
const id = setTimeout(
|
|
12
|
+
() => {
|
|
13
|
+
const end = performance.now() + FALLBACK_SLICE_MS;
|
|
14
|
+
task({ didTimeout: false, timeRemaining: () => Math.max(0, end - performance.now()) });
|
|
15
|
+
},
|
|
16
|
+
Math.min(timeout, 200)
|
|
17
|
+
);
|
|
18
|
+
return () => clearTimeout(id);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// src/runtime/runtime-version.ts
|
|
22
|
+
var runtimeVersion = 1;
|
|
23
|
+
|
|
24
|
+
// src/runtime/boot.ts
|
|
10
25
|
var IDLE_TIMEOUT_MS = 3e3;
|
|
11
|
-
|
|
12
|
-
var
|
|
13
|
-
|
|
14
|
-
|
|
26
|
+
var untilIdle = (task) => whenIdle(task, IDLE_TIMEOUT_MS);
|
|
27
|
+
var importModule = (url) => import(
|
|
28
|
+
/* @vite-ignore */
|
|
29
|
+
/* webpackIgnore: true */
|
|
30
|
+
url
|
|
31
|
+
);
|
|
32
|
+
async function loadRuntime(apiUrl, load = importModule) {
|
|
15
33
|
const url = `${apiUrl.replace(/\/+$/, "")}/v1/toolbar/${runtimeVersion}.js`;
|
|
34
|
+
const remote = await load(url);
|
|
35
|
+
if (typeof remote.mount === "function") return remote;
|
|
36
|
+
throw new Error(`${url} has no mount export`);
|
|
37
|
+
}
|
|
38
|
+
function bootToolbar(boot) {
|
|
39
|
+
let cancelled = false;
|
|
40
|
+
let mounted = null;
|
|
41
|
+
let container = null;
|
|
42
|
+
const start = async () => {
|
|
43
|
+
const session = await boot.getSession().catch(() => null);
|
|
44
|
+
if (!session || cancelled) return;
|
|
45
|
+
const runtime = await (boot.load ?? loadRuntime)(session.apiUrl);
|
|
46
|
+
if (cancelled) return;
|
|
47
|
+
container = document.createElement("div");
|
|
48
|
+
container.setAttribute("data-cs-runtime", "latest");
|
|
49
|
+
container.style.display = "contents";
|
|
50
|
+
document.body.appendChild(container);
|
|
51
|
+
mounted = runtime.mount(container, boot.props());
|
|
52
|
+
boot.onMount?.(mounted, container);
|
|
53
|
+
};
|
|
54
|
+
const cancelWait = (boot.wait ?? untilIdle)(() => {
|
|
55
|
+
start().catch((error) => console.warn("[comment-service] The toolbar could not start.", error)).finally(() => boot.onSettled?.());
|
|
56
|
+
});
|
|
57
|
+
return () => {
|
|
58
|
+
cancelled = true;
|
|
59
|
+
cancelWait();
|
|
60
|
+
queueMicrotask(() => {
|
|
61
|
+
mounted?.unmount();
|
|
62
|
+
container?.remove();
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/runtime/handoff.ts
|
|
68
|
+
var key = "devaccel.comment.handoff";
|
|
69
|
+
var ttl = 30 * 60 * 1e3;
|
|
70
|
+
function readHandoff() {
|
|
71
|
+
try {
|
|
72
|
+
const value = JSON.parse(sessionStorage.getItem(key) ?? "null");
|
|
73
|
+
return value && Date.now() - value.at < ttl ? value : null;
|
|
74
|
+
} catch {
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function write(value) {
|
|
16
79
|
try {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
)
|
|
29
|
-
|
|
80
|
+
if (value.invite || value.thread) sessionStorage.setItem(key, JSON.stringify(value));
|
|
81
|
+
else sessionStorage.removeItem(key);
|
|
82
|
+
} catch {
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function linkParams() {
|
|
86
|
+
const url = new URL(window.location.href);
|
|
87
|
+
const hash = new URLSearchParams(url.hash.slice(1));
|
|
88
|
+
return {
|
|
89
|
+
url,
|
|
90
|
+
hash,
|
|
91
|
+
invite: url.searchParams.get("cs-invite") ?? hash.get("cs-invite"),
|
|
92
|
+
thread: url.searchParams.get("cs-thread") ?? hash.get("cs-thread")
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function captureHandoff() {
|
|
96
|
+
if (typeof window === "undefined") return;
|
|
97
|
+
const { invite, thread } = linkParams();
|
|
98
|
+
if (!invite && !thread) return;
|
|
99
|
+
write({
|
|
100
|
+
...readHandoff(),
|
|
101
|
+
...invite ? { invite } : {},
|
|
102
|
+
...thread ? { thread } : {},
|
|
103
|
+
at: Date.now()
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// src/runtime/host-watch.ts
|
|
108
|
+
var HOST_CHECK_GAP_MS = 1e4;
|
|
109
|
+
var NAVIGATED = "cs-nav";
|
|
110
|
+
var HISTORY_FLAG = "__devaccelCommentHistory";
|
|
111
|
+
function announceNavigation() {
|
|
112
|
+
if (Reflect.get(window, HISTORY_FLAG)) return;
|
|
113
|
+
Reflect.set(window, HISTORY_FLAG, true);
|
|
114
|
+
for (const name of ["pushState", "replaceState"]) {
|
|
115
|
+
const original = history[name].bind(history);
|
|
116
|
+
history[name] = (...args) => {
|
|
117
|
+
original(...args);
|
|
118
|
+
window.dispatchEvent(new Event(NAVIGATED));
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function watchHost(check, gap = HOST_CHECK_GAP_MS) {
|
|
123
|
+
announceNavigation();
|
|
124
|
+
const listening = new AbortController();
|
|
125
|
+
let last = Date.now();
|
|
126
|
+
let timer = 0;
|
|
127
|
+
const run = () => {
|
|
128
|
+
window.clearTimeout(timer);
|
|
129
|
+
timer = 0;
|
|
130
|
+
last = Date.now();
|
|
131
|
+
check();
|
|
132
|
+
};
|
|
133
|
+
const soon = (event) => {
|
|
134
|
+
if (timer || document.visibilityState === "hidden") return;
|
|
135
|
+
if (event.type === "pageshow" && !event.persisted) return;
|
|
136
|
+
const wait = last + gap - Date.now();
|
|
137
|
+
if (wait <= 0) run();
|
|
138
|
+
else timer = window.setTimeout(run, wait);
|
|
139
|
+
};
|
|
140
|
+
for (const type of ["focus", "popstate", "hashchange", "pageshow", NAVIGATED])
|
|
141
|
+
window.addEventListener(type, soon, { signal: listening.signal });
|
|
142
|
+
document.addEventListener("visibilitychange", soon, { signal: listening.signal });
|
|
143
|
+
return {
|
|
144
|
+
now: run,
|
|
145
|
+
stop() {
|
|
146
|
+
window.clearTimeout(timer);
|
|
147
|
+
listening.abort();
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// src/runtime/session-source.ts
|
|
153
|
+
var EXPIRY_MARGIN_MS = 6e4;
|
|
154
|
+
var UNKNOWN_EXPIRY_MS = 5 * 6e4;
|
|
155
|
+
function readJwt(token) {
|
|
156
|
+
try {
|
|
157
|
+
const part = token.split(".")[1];
|
|
158
|
+
if (!part) return null;
|
|
159
|
+
const pad = part.length % 4 === 0 ? "" : "=".repeat(4 - part.length % 4);
|
|
160
|
+
return JSON.parse(atob(part.replaceAll("-", "+").replaceAll("_", "/") + pad));
|
|
161
|
+
} catch {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
function sessionFrom(payload) {
|
|
166
|
+
const value = payload;
|
|
167
|
+
if (!value?.enabled || !value.apiUrl || !value.project || !value.environment || !value.hostToken)
|
|
168
|
+
return null;
|
|
169
|
+
return {
|
|
170
|
+
apiUrl: value.apiUrl,
|
|
171
|
+
project: value.project,
|
|
172
|
+
environment: value.environment,
|
|
173
|
+
hostToken: value.hostToken,
|
|
174
|
+
...typeof value.loaderOrigin === "string" ? { loaderOrigin: value.loaderOrigin } : {}
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
var SessionOff = class extends Error {
|
|
178
|
+
};
|
|
179
|
+
function sessionSource(path, load, now2 = Date.now) {
|
|
180
|
+
let kept = null;
|
|
181
|
+
let pending = null;
|
|
182
|
+
return ({ refresh = false } = {}) => {
|
|
183
|
+
if (!refresh && kept && now2() < kept.until) return Promise.resolve(kept.session);
|
|
184
|
+
if (pending) return pending;
|
|
185
|
+
pending = load(path).then((payload) => {
|
|
186
|
+
const failed = payload;
|
|
187
|
+
if (failed && failed.enabled === false && failed.error) {
|
|
188
|
+
throw new SessionOff(
|
|
189
|
+
typeof failed.error === "string" ? failed.error : "Comment service is unreachable."
|
|
190
|
+
);
|
|
191
|
+
}
|
|
192
|
+
const session = sessionFrom(payload);
|
|
193
|
+
const expires = session ? readJwt(session.hostToken)?.exp : void 0;
|
|
194
|
+
const until = !session ? Infinity : expires ? expires * 1e3 - EXPIRY_MARGIN_MS : now2() + UNKNOWN_EXPIRY_MS;
|
|
195
|
+
kept = { session, until };
|
|
196
|
+
return session;
|
|
197
|
+
}).finally(() => {
|
|
198
|
+
pending = null;
|
|
199
|
+
});
|
|
200
|
+
return pending;
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// src/runtime/session.ts
|
|
205
|
+
var SIGN_IN_PREFIX = "devaccel.comment.http";
|
|
206
|
+
function forgetSignIns(storage = localStorage) {
|
|
207
|
+
try {
|
|
208
|
+
for (let index = storage.length - 1; index >= 0; index--) {
|
|
209
|
+
const key2 = storage.key(index);
|
|
210
|
+
if (key2?.startsWith(SIGN_IN_PREFIX)) storage.removeItem(key2);
|
|
211
|
+
}
|
|
212
|
+
} catch {
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
var reported = /* @__PURE__ */ new Set();
|
|
216
|
+
function report(path, status, error, failed) {
|
|
217
|
+
const said = typeof error === "string" ? `: ${error}` : failed ? "." : " with comments off.";
|
|
218
|
+
const line = `[comment-service] ${path} answered ${status}${said}`;
|
|
219
|
+
if (reported.has(line)) return;
|
|
220
|
+
reported.add(line);
|
|
221
|
+
if (failed) console.warn(line);
|
|
222
|
+
else console.info(line);
|
|
223
|
+
}
|
|
224
|
+
async function fetchSession(path) {
|
|
225
|
+
const response = await fetch(path, {
|
|
226
|
+
headers: { accept: "application/json", "x-comment-service-origin": window.location.origin },
|
|
227
|
+
cache: "no-store"
|
|
228
|
+
});
|
|
229
|
+
const payload = await response.json().catch(() => null);
|
|
230
|
+
const off = response.status === 401 || response.status === 403;
|
|
231
|
+
if (!response.ok && !off) {
|
|
232
|
+
report(path, response.status, payload?.error, true);
|
|
233
|
+
throw new Error(`The session route answered ${response.status}.`);
|
|
234
|
+
}
|
|
235
|
+
if (off || payload?.enabled !== true) {
|
|
236
|
+
report(path, response.status, payload?.error, false);
|
|
237
|
+
forgetSignIns();
|
|
238
|
+
return { enabled: false };
|
|
30
239
|
}
|
|
240
|
+
return payload;
|
|
31
241
|
}
|
|
242
|
+
function sessionSource2(path, load = fetchSession, now2 = Date.now) {
|
|
243
|
+
return sessionSource(path, load, now2);
|
|
244
|
+
}
|
|
245
|
+
var sources = /* @__PURE__ */ new Map();
|
|
246
|
+
function sessionFor(path) {
|
|
247
|
+
let source = sources.get(path);
|
|
248
|
+
if (!source) {
|
|
249
|
+
source = sessionSource2(path);
|
|
250
|
+
sources.set(path, source);
|
|
251
|
+
}
|
|
252
|
+
return source;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// src/runtime/loader.tsx
|
|
256
|
+
var stampedBuild = typeof __COMMENT_TOOL_HOST_BUILD__ === "object" ? __COMMENT_TOOL_HOST_BUILD__ : void 0;
|
|
257
|
+
function withStampedBuild(config) {
|
|
258
|
+
if (!config || !stampedBuild) return config;
|
|
259
|
+
const options = config === true ? {} : config;
|
|
260
|
+
return options.build ? config : { ...options, build: stampedBuild };
|
|
261
|
+
}
|
|
262
|
+
captureHandoff();
|
|
263
|
+
var now = (task) => {
|
|
264
|
+
task();
|
|
265
|
+
return () => {
|
|
266
|
+
};
|
|
267
|
+
};
|
|
32
268
|
function CommentToolbar({
|
|
33
|
-
source = "latest",
|
|
34
269
|
sessionPath = "/api/comment-service/session",
|
|
35
270
|
pollMs,
|
|
36
271
|
position,
|
|
37
272
|
theme,
|
|
38
|
-
navigate
|
|
273
|
+
navigate,
|
|
274
|
+
screen,
|
|
275
|
+
debugContext
|
|
39
276
|
}) {
|
|
40
277
|
const handle = useRef(null);
|
|
41
278
|
const navigateRef = useRef(navigate);
|
|
42
|
-
|
|
43
|
-
const hasNavigate = Boolean(navigate);
|
|
44
|
-
const props = useRef({});
|
|
45
|
-
props.current = {
|
|
46
|
-
sessionPath,
|
|
47
|
-
pollMs,
|
|
48
|
-
position,
|
|
49
|
-
theme,
|
|
50
|
-
navigate: hasNavigate ? (href) => navigateRef.current?.(href) : void 0,
|
|
51
|
-
getSession: sessionFor(sessionPath)
|
|
52
|
-
};
|
|
279
|
+
const propsRef = useRef({});
|
|
53
280
|
useEffect(() => {
|
|
281
|
+
navigateRef.current = navigate;
|
|
282
|
+
propsRef.current = {
|
|
283
|
+
sessionPath,
|
|
284
|
+
pollMs,
|
|
285
|
+
position,
|
|
286
|
+
theme,
|
|
287
|
+
navigate: navigate ? (href) => navigateRef.current?.(href) : void 0,
|
|
288
|
+
screen,
|
|
289
|
+
debugContext: withStampedBuild(debugContext),
|
|
290
|
+
getSession: sessionFor(sessionPath)
|
|
291
|
+
};
|
|
292
|
+
handle.current?.update(propsRef.current);
|
|
293
|
+
}, [debugContext, navigate, pollMs, position, screen, sessionPath, theme]);
|
|
294
|
+
useEffect(() => {
|
|
295
|
+
const boot = (refresh, wait) => bootToolbar({
|
|
296
|
+
getSession: () => sessionFor(sessionPath)({ refresh }),
|
|
297
|
+
props: () => propsRef.current,
|
|
298
|
+
onMount: (mounted) => {
|
|
299
|
+
handle.current = mounted;
|
|
300
|
+
},
|
|
301
|
+
...wait ? { wait } : {}
|
|
302
|
+
});
|
|
303
|
+
let stop = boot(false);
|
|
304
|
+
const watch = watchHost(() => {
|
|
305
|
+
if (handle.current) return;
|
|
306
|
+
stop();
|
|
307
|
+
stop = boot(true, now);
|
|
308
|
+
});
|
|
309
|
+
return () => {
|
|
310
|
+
watch.stop();
|
|
311
|
+
handle.current = null;
|
|
312
|
+
stop();
|
|
313
|
+
};
|
|
314
|
+
}, [sessionPath]);
|
|
315
|
+
return null;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// src/runtime/debug-context-host.ts
|
|
319
|
+
var DEBUG_ERROR_EVENT = "comment-tool:error";
|
|
320
|
+
function reportToolbarError(error, componentStack) {
|
|
321
|
+
if (typeof window === "undefined" || typeof CustomEvent !== "function") return;
|
|
322
|
+
window.dispatchEvent(
|
|
323
|
+
new CustomEvent(DEBUG_ERROR_EVENT, {
|
|
324
|
+
detail: { error, componentStack: componentStack ?? null }
|
|
325
|
+
})
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
function queryCacheSummary(client, max = 50) {
|
|
329
|
+
return client.getQueryCache().getAll().slice(-max).map((query) => ({
|
|
330
|
+
key: query.queryKey,
|
|
331
|
+
status: query.state.status,
|
|
332
|
+
fetchStatus: query.state.fetchStatus,
|
|
333
|
+
error: query.state.error ?? void 0,
|
|
334
|
+
updatedAt: query.state.dataUpdatedAt,
|
|
335
|
+
observers: query.getObserversCount?.()
|
|
336
|
+
}));
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
// src/help/react.tsx
|
|
340
|
+
import { useEffect as useEffect2, useRef as useRef2 } from "react";
|
|
341
|
+
var loading = /* @__PURE__ */ new Map();
|
|
342
|
+
function loadHelp(serviceUrl) {
|
|
343
|
+
const page = window;
|
|
344
|
+
const there = () => typeof page.CommentToolHelp?.mount === "function" ? page.CommentToolHelp : null;
|
|
345
|
+
const ready = there();
|
|
346
|
+
if (ready) return Promise.resolve(ready);
|
|
347
|
+
const url = `${serviceUrl.replace(/\/+$/, "")}/v1/toolbar/help.js`;
|
|
348
|
+
let kept = loading.get(url);
|
|
349
|
+
if (!kept) {
|
|
350
|
+
kept = new Promise((resolve, reject) => {
|
|
351
|
+
const tag = document.createElement("script");
|
|
352
|
+
tag.src = url;
|
|
353
|
+
tag.async = true;
|
|
354
|
+
tag.onload = () => {
|
|
355
|
+
const api = there();
|
|
356
|
+
if (api) resolve(api);
|
|
357
|
+
else reject(new Error(`${url} defined no CommentToolHelp.`));
|
|
358
|
+
};
|
|
359
|
+
tag.onerror = () => {
|
|
360
|
+
tag.remove();
|
|
361
|
+
reject(new Error(`${url} did not load.`));
|
|
362
|
+
};
|
|
363
|
+
document.head.appendChild(tag);
|
|
364
|
+
});
|
|
365
|
+
kept.catch(() => loading.delete(url));
|
|
366
|
+
loading.set(url, kept);
|
|
367
|
+
}
|
|
368
|
+
return kept;
|
|
369
|
+
}
|
|
370
|
+
function HelpPill(props) {
|
|
371
|
+
const {
|
|
372
|
+
serviceUrl,
|
|
373
|
+
sessionPath = "/api/comment-service/session",
|
|
374
|
+
label,
|
|
375
|
+
position,
|
|
376
|
+
theme
|
|
377
|
+
} = props;
|
|
378
|
+
const hasList = typeof props.list === "function";
|
|
379
|
+
const hasMore = typeof props.moreOptions === "function";
|
|
380
|
+
const latest = useRef2(props);
|
|
381
|
+
const mounted = useRef2(null);
|
|
382
|
+
const options = useRef2(() => {
|
|
383
|
+
const now2 = latest.current;
|
|
384
|
+
return {
|
|
385
|
+
submit: (request) => latest.current.submit(request),
|
|
386
|
+
...typeof now2.list === "function" ? {
|
|
387
|
+
list: () => {
|
|
388
|
+
const list = latest.current.list;
|
|
389
|
+
return list ? list() : Promise.resolve([]);
|
|
390
|
+
}
|
|
391
|
+
} : {},
|
|
392
|
+
label: now2.label,
|
|
393
|
+
position: now2.position,
|
|
394
|
+
theme: now2.theme,
|
|
395
|
+
captures: () => {
|
|
396
|
+
const captures = latest.current.captures;
|
|
397
|
+
return typeof captures === "function" ? captures() : captures !== false;
|
|
398
|
+
},
|
|
399
|
+
...typeof now2.moreOptions === "function" ? { moreOptions: (draft) => latest.current.moreOptions?.(draft) } : {}
|
|
400
|
+
};
|
|
401
|
+
});
|
|
402
|
+
useEffect2(() => {
|
|
403
|
+
latest.current = props;
|
|
404
|
+
});
|
|
405
|
+
useEffect2(() => {
|
|
54
406
|
let cancelled = false;
|
|
55
|
-
let mounted = null;
|
|
56
|
-
let container = null;
|
|
57
407
|
const start = async () => {
|
|
58
|
-
const
|
|
59
|
-
if (
|
|
60
|
-
|
|
408
|
+
const address = serviceUrl ?? (await sessionFor(sessionPath)().catch(() => null))?.apiUrl ?? null;
|
|
409
|
+
if (cancelled) return;
|
|
410
|
+
if (!address) {
|
|
411
|
+
console.info(
|
|
412
|
+
`[comment-service] <HelpPill> is not shown: ${sessionPath} names no service for this person. Pass serviceUrl to show it to everyone.`
|
|
413
|
+
);
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
const api = await loadHelp(address);
|
|
61
417
|
if (cancelled) return;
|
|
62
|
-
|
|
63
|
-
container.setAttribute("data-cs-runtime", source);
|
|
64
|
-
container.style.display = "contents";
|
|
65
|
-
document.body.append(container);
|
|
66
|
-
mounted = runtime.mount(container, props.current);
|
|
67
|
-
handle.current = mounted;
|
|
418
|
+
mounted.current = { api, handle: api.mount(options.current()) };
|
|
68
419
|
};
|
|
69
|
-
const
|
|
420
|
+
const cancelWait = whenIdle(() => {
|
|
70
421
|
start().catch(
|
|
71
|
-
(error) => console.warn("[comment-service] The
|
|
422
|
+
(error) => console.warn("[comment-service] The help pill could not start.", error)
|
|
72
423
|
);
|
|
73
424
|
}, IDLE_TIMEOUT_MS);
|
|
74
425
|
return () => {
|
|
75
426
|
cancelled = true;
|
|
76
|
-
|
|
77
|
-
handle.
|
|
78
|
-
|
|
79
|
-
mounted?.unmount();
|
|
80
|
-
container?.remove();
|
|
81
|
-
});
|
|
427
|
+
cancelWait();
|
|
428
|
+
mounted.current?.handle.unmount();
|
|
429
|
+
mounted.current = null;
|
|
82
430
|
};
|
|
83
|
-
}, [
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
431
|
+
}, [serviceUrl, sessionPath]);
|
|
432
|
+
useEffect2(() => {
|
|
433
|
+
const now2 = mounted.current;
|
|
434
|
+
if (now2) now2.handle = now2.api.mount(options.current());
|
|
435
|
+
}, [label, position, theme, hasList, hasMore]);
|
|
87
436
|
return null;
|
|
88
437
|
}
|
|
438
|
+
|
|
439
|
+
// src/help/wire.ts
|
|
440
|
+
var HELP_LIMITS = {
|
|
441
|
+
/** A request's own id: letters, digits, `.`, `_`, `:` and `-`. */
|
|
442
|
+
id: 100,
|
|
443
|
+
message: 4e3,
|
|
444
|
+
images: 3,
|
|
445
|
+
/** One picture, before base64. */
|
|
446
|
+
imageBytes: 5 * 1024 * 1024,
|
|
447
|
+
name: 200,
|
|
448
|
+
label: 200,
|
|
449
|
+
url: 1e3,
|
|
450
|
+
/** "Your requests" shows at most this many. */
|
|
451
|
+
listed: 50
|
|
452
|
+
};
|
|
453
|
+
var HELP_BODY_BYTES = Math.ceil(HELP_LIMITS.images * HELP_LIMITS.imageBytes * 4 / 3) + 256 * 1024;
|
|
454
|
+
|
|
455
|
+
// src/help/types.ts
|
|
456
|
+
var HelpError = class extends Error {
|
|
457
|
+
name = "HelpError";
|
|
458
|
+
};
|
|
459
|
+
|
|
460
|
+
// src/help/requests.ts
|
|
461
|
+
var NOT_SENT = "That did not send. Check your connection and try again.";
|
|
462
|
+
var NOT_READ = "Your requests could not be loaded.";
|
|
463
|
+
async function base64Of(blob) {
|
|
464
|
+
const bytes = new Uint8Array(await blob.arrayBuffer());
|
|
465
|
+
let binary = "";
|
|
466
|
+
const chunk = 32768;
|
|
467
|
+
for (let index = 0; index < bytes.length; index += chunk) {
|
|
468
|
+
binary += String.fromCharCode(...bytes.subarray(index, index + chunk));
|
|
469
|
+
}
|
|
470
|
+
return btoa(binary);
|
|
471
|
+
}
|
|
472
|
+
async function imageWire(image) {
|
|
473
|
+
if (image.blob.size > HELP_LIMITS.imageBytes) {
|
|
474
|
+
throw new HelpError("A picture is too large to send. Remove it and try again.");
|
|
475
|
+
}
|
|
476
|
+
return {
|
|
477
|
+
name: image.name,
|
|
478
|
+
contentType: image.blob.type,
|
|
479
|
+
width: image.width,
|
|
480
|
+
height: image.height,
|
|
481
|
+
markedUp: image.markedUp,
|
|
482
|
+
data: await base64Of(image.blob)
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
async function sentenceOf(response) {
|
|
486
|
+
const payload = await response.json().catch(() => null);
|
|
487
|
+
return typeof payload?.error === "string" && payload.error.trim() ? payload.error : null;
|
|
488
|
+
}
|
|
489
|
+
function supportRequestsAt(url) {
|
|
490
|
+
return {
|
|
491
|
+
async submit(request) {
|
|
492
|
+
const body = {
|
|
493
|
+
id: request.id,
|
|
494
|
+
message: request.message,
|
|
495
|
+
pageUrl: request.pageUrl,
|
|
496
|
+
route: request.route,
|
|
497
|
+
pointed: request.pointed,
|
|
498
|
+
images: await Promise.all(request.images.map(imageWire)),
|
|
499
|
+
client: request.client
|
|
500
|
+
};
|
|
501
|
+
let response;
|
|
502
|
+
try {
|
|
503
|
+
response = await fetch(url, {
|
|
504
|
+
method: "POST",
|
|
505
|
+
headers: { accept: "application/json", "content-type": "application/json" },
|
|
506
|
+
credentials: "same-origin",
|
|
507
|
+
cache: "no-store",
|
|
508
|
+
body: JSON.stringify(body)
|
|
509
|
+
});
|
|
510
|
+
} catch {
|
|
511
|
+
throw new HelpError(NOT_SENT);
|
|
512
|
+
}
|
|
513
|
+
if (!response.ok) throw new HelpError(await sentenceOf(response) ?? NOT_SENT);
|
|
514
|
+
const receipt = await response.json().catch(() => null);
|
|
515
|
+
return {
|
|
516
|
+
...typeof receipt?.reference === "string" ? { reference: receipt.reference } : {},
|
|
517
|
+
...typeof receipt?.url === "string" ? { url: receipt.url } : {},
|
|
518
|
+
...typeof receipt?.note === "string" ? { note: receipt.note } : {}
|
|
519
|
+
};
|
|
520
|
+
},
|
|
521
|
+
async list() {
|
|
522
|
+
let response;
|
|
523
|
+
try {
|
|
524
|
+
response = await fetch(url, {
|
|
525
|
+
headers: { accept: "application/json" },
|
|
526
|
+
credentials: "same-origin",
|
|
527
|
+
cache: "no-store"
|
|
528
|
+
});
|
|
529
|
+
} catch {
|
|
530
|
+
throw new HelpError(NOT_READ);
|
|
531
|
+
}
|
|
532
|
+
if (!response.ok) throw new HelpError(await sentenceOf(response) ?? NOT_READ);
|
|
533
|
+
const payload = await response.json().catch(() => null);
|
|
534
|
+
if (!Array.isArray(payload?.requests)) throw new HelpError(NOT_READ);
|
|
535
|
+
return payload.requests;
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
}
|
|
89
539
|
export {
|
|
90
|
-
CommentToolbar
|
|
540
|
+
CommentToolbar,
|
|
541
|
+
HelpError,
|
|
542
|
+
HelpPill,
|
|
543
|
+
queryCacheSummary,
|
|
544
|
+
reportToolbarError,
|
|
545
|
+
supportRequestsAt
|
|
91
546
|
};
|