@shivaedev/work-board 0.14.2 → 0.16.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/CHANGELOG.md +26 -0
- package/README.md +1 -1
- package/assets/agent.js +1 -1
- package/assets/native.js +25 -25
- package/assets/react.css +1 -1
- package/assets/react.js +37 -36
- package/dist/browser/diagnostics/schema.d.ts +15 -12
- package/dist/browser/diagnostics/schema.d.ts.map +1 -1
- package/dist/browser/diagnostics/schema.js +12 -2
- package/dist/browser/diagnostics/schema.js.map +1 -1
- package/dist/browser/views/remaining.d.ts +20 -12
- package/dist/browser/views/remaining.d.ts.map +1 -1
- package/dist/client/client.d.ts +1 -0
- package/dist/client/client.d.ts.map +1 -1
- package/dist/client/client.js +1 -1
- package/dist/client/client.js.map +1 -1
- package/dist/client/document/Mermaid.d.ts.map +1 -1
- package/dist/client/document/Mermaid.js +4 -10
- package/dist/client/document/Mermaid.js.map +1 -1
- package/dist/client/document/View.js +1 -1
- package/dist/client/document/View.js.map +1 -1
- package/dist/client/formStatus.d.ts +12 -0
- package/dist/client/formStatus.d.ts.map +1 -0
- package/dist/client/formStatus.js +27 -0
- package/dist/client/formStatus.js.map +1 -0
- package/dist/client/react/BoardShell.d.ts.map +1 -1
- package/dist/client/react/BoardShell.js +36 -37
- package/dist/client/react/BoardShell.js.map +1 -1
- package/dist/client/react/DocumentContext.d.ts.map +1 -1
- package/dist/client/react/DocumentContext.js +12 -7
- package/dist/client/react/DocumentContext.js.map +1 -1
- package/dist/client/react/FormContext.d.ts +5 -0
- package/dist/client/react/FormContext.d.ts.map +1 -0
- package/dist/client/react/FormContext.js +10 -0
- package/dist/client/react/FormContext.js.map +1 -0
- package/dist/client/react/LiveControls.d.ts +4 -3
- package/dist/client/react/LiveControls.d.ts.map +1 -1
- package/dist/client/react/LiveControls.js +5 -24
- package/dist/client/react/LiveControls.js.map +1 -1
- package/dist/client/react/MainLocationContext.d.ts +3 -0
- package/dist/client/react/MainLocationContext.d.ts.map +1 -0
- package/dist/client/react/MainLocationContext.js +7 -0
- package/dist/client/react/MainLocationContext.js.map +1 -0
- package/dist/client/react/PhoneNavigation.d.ts +3 -1
- package/dist/client/react/PhoneNavigation.d.ts.map +1 -1
- package/dist/client/react/PhoneNavigation.js +8 -13
- package/dist/client/react/PhoneNavigation.js.map +1 -1
- package/dist/client/react/ProjectionFrame.d.ts +1 -2
- package/dist/client/react/ProjectionFrame.d.ts.map +1 -1
- package/dist/client/react/ProjectionFrame.js +10 -4
- package/dist/client/react/ProjectionFrame.js.map +1 -1
- package/dist/client/react/ReadingLibrary.d.ts.map +1 -1
- package/dist/client/react/ReadingLibrary.js +9 -14
- package/dist/client/react/ReadingLibrary.js.map +1 -1
- package/dist/client/react/ReadingReadyContext.d.ts +6 -0
- package/dist/client/react/ReadingReadyContext.d.ts.map +1 -0
- package/dist/client/react/ReadingReadyContext.js +7 -0
- package/dist/client/react/ReadingReadyContext.js.map +1 -0
- package/dist/client/react/SessionContext.d.ts +3 -0
- package/dist/client/react/SessionContext.d.ts.map +1 -0
- package/dist/client/react/SessionContext.js +3 -0
- package/dist/client/react/SessionContext.js.map +1 -0
- package/dist/client/react/SystemMain.d.ts.map +1 -1
- package/dist/client/react/SystemMain.js +3 -1
- package/dist/client/react/SystemMain.js.map +1 -1
- package/dist/client/react/SystemPage.d.ts.map +1 -1
- package/dist/client/react/SystemPage.js +2 -1
- package/dist/client/react/SystemPage.js.map +1 -1
- package/dist/client/react/ThemeContext.d.ts +2 -0
- package/dist/client/react/ThemeContext.d.ts.map +1 -0
- package/dist/client/react/ThemeContext.js +3 -0
- package/dist/client/react/ThemeContext.js.map +1 -0
- package/dist/client/react/TodayOptions.d.ts.map +1 -1
- package/dist/client/react/TodayOptions.js +23 -14
- package/dist/client/react/TodayOptions.js.map +1 -1
- package/dist/client/react/VisualViewer.d.ts.map +1 -1
- package/dist/client/react/VisualViewer.js +6 -5
- package/dist/client/react/VisualViewer.js.map +1 -1
- package/dist/client/react/boardRouter.d.ts +3 -2
- package/dist/client/react/boardRouter.d.ts.map +1 -1
- package/dist/client/react/boardRouter.js +2 -1
- package/dist/client/react/boardRouter.js.map +1 -1
- package/dist/client/react/createResponse.d.ts +32 -4
- package/dist/client/react/createResponse.d.ts.map +1 -1
- package/dist/client/react/createResponse.js +7 -28
- package/dist/client/react/createResponse.js.map +1 -1
- package/dist/client/react/diagnosticsValues.d.ts.map +1 -1
- package/dist/client/react/diagnosticsValues.js +5 -7
- package/dist/client/react/diagnosticsValues.js.map +1 -1
- package/dist/client/react/entry.d.ts.map +1 -1
- package/dist/client/react/entry.js +2 -34
- package/dist/client/react/entry.js.map +1 -1
- package/dist/client/react/githubLimited.d.ts +3 -0
- package/dist/client/react/githubLimited.d.ts.map +1 -0
- package/dist/client/react/githubLimited.js +4 -0
- package/dist/client/react/githubLimited.js.map +1 -0
- package/dist/client/react/loadProjection.d.ts +135 -135
- package/dist/client/react/loadRemaining.d.ts +20 -12
- package/dist/client/react/loadRemaining.d.ts.map +1 -1
- package/dist/client/react/mainLocation.d.ts +4 -2
- package/dist/client/react/mainLocation.d.ts.map +1 -1
- package/dist/client/react/mainLocation.js +1 -8
- package/dist/client/react/mainLocation.js.map +1 -1
- package/dist/client/react/mountBoard.d.ts +3 -0
- package/dist/client/react/mountBoard.d.ts.map +1 -0
- package/dist/client/react/mountBoard.js +45 -0
- package/dist/client/react/mountBoard.js.map +1 -0
- package/dist/client/react/navigationLocation.d.ts +3 -1
- package/dist/client/react/navigationLocation.d.ts.map +1 -1
- package/dist/client/react/navigationLocation.js +11 -1
- package/dist/client/react/navigationLocation.js.map +1 -1
- package/dist/client/react/retryPage.d.ts +2 -1
- package/dist/client/react/retryPage.d.ts.map +1 -1
- package/dist/client/react/retryPage.js +3 -4
- package/dist/client/react/retryPage.js.map +1 -1
- package/dist/client/react/scheduleReading.d.ts.map +1 -1
- package/dist/client/react/scheduleReading.js +1 -10
- package/dist/client/react/scheduleReading.js.map +1 -1
- package/dist/client/react/useAppearance.d.ts +2 -1
- package/dist/client/react/useAppearance.d.ts.map +1 -1
- package/dist/client/react/useAppearance.js +1 -2
- package/dist/client/react/useAppearance.js.map +1 -1
- package/dist/client/react/useBoardNavigation.d.ts +1 -1
- package/dist/client/react/useBoardNavigation.d.ts.map +1 -1
- package/dist/client/react/useBoardNavigation.js +28 -22
- package/dist/client/react/useBoardNavigation.js.map +1 -1
- package/dist/client/react/useDiagnosticsPolling.d.ts +4 -1
- package/dist/client/react/useDiagnosticsPolling.d.ts.map +1 -1
- package/dist/client/react/useDiagnosticsPolling.js +9 -7
- package/dist/client/react/useDiagnosticsPolling.js.map +1 -1
- package/dist/client/react/useDocumentPage.d.ts +1 -1
- package/dist/client/react/useDocumentPage.d.ts.map +1 -1
- package/dist/client/react/useDocumentPage.js +9 -6
- package/dist/client/react/useDocumentPage.js.map +1 -1
- package/dist/client/react/useHandoffForm.d.ts +56 -30
- package/dist/client/react/useHandoffForm.d.ts.map +1 -1
- package/dist/client/react/useHandoffForm.js +19 -30
- package/dist/client/react/useHandoffForm.js.map +1 -1
- package/dist/client/react/useResponseForm.d.ts +72 -43
- package/dist/client/react/useResponseForm.d.ts.map +1 -1
- package/dist/client/react/useResponseForm.js +20 -17
- package/dist/client/react/useResponseForm.js.map +1 -1
- package/dist/client/react/useSidebar.d.ts.map +1 -1
- package/dist/client/react/useSidebar.js +5 -3
- package/dist/client/react/useSidebar.js.map +1 -1
- package/dist/client/react/visualSources.d.ts.map +1 -1
- package/dist/client/react/visualSources.js +10 -8
- package/dist/client/react/visualSources.js.map +1 -1
- package/dist/client/saveFailure.d.ts +8 -0
- package/dist/client/saveFailure.d.ts.map +1 -0
- package/dist/client/saveFailure.js +8 -0
- package/dist/client/saveFailure.js.map +1 -0
- package/dist/diagnostics/daemonContract.d.ts +65 -38
- package/dist/diagnostics/daemonContract.d.ts.map +1 -1
- package/dist/diagnostics/daemonContract.js +2 -1
- package/dist/diagnostics/daemonContract.js.map +1 -1
- package/dist/diagnostics/health.d.ts +10 -0
- package/dist/diagnostics/health.d.ts.map +1 -1
- package/dist/diagnostics/health.js +2 -0
- package/dist/diagnostics/health.js.map +1 -1
- package/dist/diagnostics/source.d.ts +55 -36
- package/dist/diagnostics/source.d.ts.map +1 -1
- package/dist/diagnostics/source.js +1 -2
- package/dist/diagnostics/source.js.map +1 -1
- package/dist/render/{failed.d.ts → Failed.d.ts} +1 -1
- package/dist/render/Failed.d.ts.map +1 -0
- package/dist/render/{failed.js → Failed.js} +1 -1
- package/dist/render/Failed.js.map +1 -0
- package/dist/render/code.d.ts +2 -2
- package/dist/render/code.d.ts.map +1 -1
- package/dist/render/code.js +15 -13
- package/dist/render/code.js.map +1 -1
- package/dist/render/footnoteIds.d.ts +3 -0
- package/dist/render/footnoteIds.d.ts.map +1 -0
- package/dist/render/{footnotes.js → footnoteIds.js} +11 -9
- package/dist/render/footnoteIds.js.map +1 -0
- package/dist/rpc/contract.d.ts +2346 -2322
- package/dist/rpc/contract.d.ts.map +1 -1
- package/dist/rpc/handoffContract.d.ts +33 -33
- package/dist/rpc/responseContract.d.ts +56 -56
- package/dist/server/board.d.ts +1 -1
- package/dist/server/diagnostics/daemon.d.ts +41 -25
- package/dist/server/diagnostics/daemon.d.ts.map +1 -1
- package/dist/server/diagnostics/fleetHealth.d.ts +10 -0
- package/dist/server/diagnostics/fleetHealth.d.ts.map +1 -1
- package/dist/server/diagnostics/githubLimits.d.ts +12 -13
- package/dist/server/diagnostics/githubLimits.d.ts.map +1 -1
- package/dist/server/diagnostics/githubLimits.js +6 -6
- package/dist/server/diagnostics/githubLimits.js.map +1 -1
- package/dist/server/integration/diagnostics.d.ts +74 -38
- package/dist/server/integration/diagnostics.d.ts.map +1 -1
- package/dist/server/mcp/client.d.ts +1155 -1147
- package/dist/server/mcp/client.d.ts.map +1 -1
- package/dist/server/mcp/queries.d.ts +60 -36
- package/dist/server/mcp/queries.d.ts.map +1 -1
- package/dist/server/metadata/fields.js +1 -1
- package/dist/server/metadata/fields.js.map +1 -1
- package/dist/server/packageInfo.d.ts +1 -1
- package/dist/server/packageInfo.js +1 -1
- package/dist/server/render/Highlighter.d.ts +1 -1
- package/dist/server/render/Highlighter.js +1 -1
- package/dist/server/render/markdown.d.ts +1 -1
- package/dist/server/render/markdown.js +2 -2
- package/dist/server/render/markdown.js.map +1 -1
- package/dist/server/serve.d.ts +1 -1
- package/dist/server/views/remainingQueries.d.ts +20 -12
- package/dist/server/views/remainingQueries.d.ts.map +1 -1
- package/package.json +9 -39
- package/src/browser/diagnostics/schema.ts +12 -2
- package/src/client/client.ts +2 -1
- package/src/client/document/Mermaid.ts +4 -10
- package/src/client/document/View.ts +1 -1
- package/src/client/formStatus.ts +35 -0
- package/src/client/react/BoardShell.tsx +49 -43
- package/src/client/react/DocumentContext.tsx +12 -7
- package/src/client/react/FormContext.ts +13 -0
- package/src/client/react/LiveControls.tsx +5 -38
- package/src/client/react/MainLocationContext.ts +8 -0
- package/src/client/react/PhoneNavigation.tsx +20 -15
- package/src/client/react/ProjectionFrame.tsx +13 -5
- package/src/client/react/ReadingLibrary.tsx +9 -14
- package/src/client/react/ReadingReadyContext.ts +11 -0
- package/src/client/react/SessionContext.ts +4 -0
- package/src/client/react/SystemMain.tsx +3 -1
- package/src/client/react/SystemPage.tsx +2 -1
- package/src/client/react/ThemeContext.ts +3 -0
- package/src/client/react/TodayOptions.tsx +40 -33
- package/src/client/react/VisualViewer.tsx +6 -6
- package/src/client/react/boardRouter.ts +3 -2
- package/src/client/react/createResponse.ts +10 -35
- package/src/client/react/diagnosticsValues.tsx +20 -12
- package/src/client/react/entry.tsx +2 -37
- package/src/client/react/githubLimited.ts +5 -0
- package/src/client/react/mainLocation.ts +5 -8
- package/src/client/react/mountBoard.tsx +49 -0
- package/src/client/react/navigationLocation.ts +14 -2
- package/src/client/react/retryPage.ts +4 -4
- package/src/client/react/scheduleReading.ts +1 -10
- package/src/client/react/useAppearance.ts +2 -3
- package/src/client/react/useBoardNavigation.ts +30 -23
- package/src/client/react/useDiagnosticsPolling.ts +14 -7
- package/src/client/react/useDocumentPage.ts +12 -6
- package/src/client/react/useHandoffForm.ts +25 -33
- package/src/client/react/useResponseForm.ts +20 -18
- package/src/client/react/useSidebar.ts +5 -3
- package/src/client/react/visualSources.ts +10 -8
- package/src/client/saveFailure.ts +14 -0
- package/src/diagnostics/daemonContract.ts +2 -1
- package/src/diagnostics/health.ts +2 -0
- package/src/diagnostics/source.ts +1 -2
- package/src/render/code.ts +3 -4
- package/src/render/{footnotes.ts → footnoteIds.ts} +12 -10
- package/src/server/board.ts +1 -1
- package/src/server/diagnostics/githubLimits.ts +9 -11
- package/src/server/metadata/fields.ts +1 -1
- package/src/server/packageInfo.ts +1 -1
- package/src/server/render/Highlighter.ts +1 -1
- package/src/server/render/markdown.ts +2 -2
- package/dist/client/handoffs/failureStatus.d.ts +0 -2
- package/dist/client/handoffs/failureStatus.d.ts.map +0 -1
- package/dist/client/handoffs/failureStatus.js +0 -7
- package/dist/client/handoffs/failureStatus.js.map +0 -1
- package/dist/client/responses/failure.d.ts +0 -5
- package/dist/client/responses/failure.d.ts.map +0 -1
- package/dist/client/responses/failure.js +0 -13
- package/dist/client/responses/failure.js.map +0 -1
- package/dist/render/failed.d.ts.map +0 -1
- package/dist/render/failed.js.map +0 -1
- package/dist/render/footnotes.d.ts +0 -3
- package/dist/render/footnotes.d.ts.map +0 -1
- package/dist/render/footnotes.js.map +0 -1
- package/dist/server/diagnostics/readCommand.d.ts +0 -4
- package/dist/server/diagnostics/readCommand.d.ts.map +0 -1
- package/dist/server/diagnostics/readCommand.js +0 -20
- package/dist/server/diagnostics/readCommand.js.map +0 -1
- package/src/client/handoffs/failureStatus.ts +0 -6
- package/src/client/responses/failure.ts +0 -13
- package/src/server/diagnostics/readCommand.ts +0 -24
- /package/src/render/{failed.ts → Failed.ts} +0 -0
|
@@ -1,11 +1,14 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from "react";
|
|
2
2
|
import { KeyboardHints } from "./KeyboardHints.tsx";
|
|
3
|
+
import { useMainLocation } from "./MainLocationContext.ts";
|
|
3
4
|
import { shellIds } from "./shellIds.ts";
|
|
4
5
|
import { VisualControls } from "./VisualControls.tsx";
|
|
5
6
|
import { graphicWidth, visualFilename } from "./visualDimensions.ts";
|
|
6
7
|
import type { VisualSelection } from "./visualSources.ts";
|
|
7
8
|
|
|
8
9
|
export function VisualViewer({ selection, close }: { readonly selection: VisualSelection; readonly close: () => void }) {
|
|
10
|
+
const page = useMainLocation();
|
|
11
|
+
const openedPageRef = useRef(page);
|
|
9
12
|
const [selected, setSelected] = useState(selection.selected);
|
|
10
13
|
const [scale, setScale] = useState(100);
|
|
11
14
|
const [baseWidth, setBaseWidth] = useState(0);
|
|
@@ -27,13 +30,11 @@ export function VisualViewer({ selection, close }: { readonly selection: VisualS
|
|
|
27
30
|
return () => URL.revokeObjectURL(url);
|
|
28
31
|
}, [selection.drawing]);
|
|
29
32
|
useEffect(() => {
|
|
30
|
-
|
|
33
|
+
if (page !== openedPageRef.current) {
|
|
31
34
|
setStale(true);
|
|
32
35
|
setStatus("Source updated. This preview is the drawing/image opened earlier; close and reopen to inspect or save the latest source.");
|
|
33
36
|
}
|
|
34
|
-
|
|
35
|
-
return () => document.removeEventListener("board-page", changed);
|
|
36
|
-
}, []);
|
|
37
|
+
}, [page]);
|
|
37
38
|
function handleFitVisual() {
|
|
38
39
|
setBaseWidth(0);
|
|
39
40
|
setScale(100);
|
|
@@ -114,8 +115,7 @@ export function VisualViewer({ selection, close }: { readonly selection: VisualS
|
|
|
114
115
|
</button>
|
|
115
116
|
</div>
|
|
116
117
|
<p id={shellIds.visualContext}>
|
|
117
|
-
{image ? `${image.alt || "Local image"} · ${selected + 1} of ${selection.images.length} · ${image.local}` : "Mermaid diagram"} ·{
|
|
118
|
-
{document.getElementById("doc")?.dataset.file}
|
|
118
|
+
{image ? `${image.alt || "Local image"} · ${selected + 1} of ${selection.images.length} · ${image.local}` : "Mermaid diagram"} · {page.file}
|
|
119
119
|
{image ? "" : " · Current drawing"}
|
|
120
120
|
</p>
|
|
121
121
|
<VisualControls
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { createRootRouteWithContext, createRoute, createRouter } from "@tanstack/react-router";
|
|
1
|
+
import { createRootRouteWithContext, createRoute, createRouter, type RouterHistory } from "@tanstack/react-router";
|
|
2
2
|
import { createElement } from "react";
|
|
3
3
|
import { BoardShell } from "./BoardShell.tsx";
|
|
4
4
|
import { loadBoardPage, type RouterShell } from "./loadBoardPage.ts";
|
|
5
|
-
export function boardRouter(options?: RouterShell) {
|
|
5
|
+
export function boardRouter(options?: RouterShell, history?: RouterHistory) {
|
|
6
6
|
const root = createRootRouteWithContext<{ readonly shell?: RouterShell }>()({
|
|
7
7
|
component: () => {
|
|
8
8
|
const { shell } = root.useRouteContext();
|
|
@@ -24,6 +24,7 @@ export function boardRouter(options?: RouterShell) {
|
|
|
24
24
|
path: "$",
|
|
25
25
|
});
|
|
26
26
|
return createRouter({
|
|
27
|
+
...(history ? { history } : {}),
|
|
27
28
|
context: options ? { shell: options } : {},
|
|
28
29
|
defaultPendingMs: Number.POSITIVE_INFINITY,
|
|
29
30
|
defaultPreloadStaleTime: 0,
|
|
@@ -1,40 +1,15 @@
|
|
|
1
|
-
import { Effect
|
|
1
|
+
import { Effect } from "effect";
|
|
2
2
|
import type { QuestionPreview } from "#browser/responses/schema.ts";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import type { ResponseInput, ResponseSubmission } from "#client/responses/formSchema.ts";
|
|
3
|
+
import type { ResponseSubmission } from "#client/responses/formSchema.ts";
|
|
4
|
+
import type { FormClient } from "./FormContext.ts";
|
|
6
5
|
|
|
7
|
-
export
|
|
6
|
+
export const createResponse = Effect.fn("Board.createResponse")(function* (
|
|
7
|
+
client: FormClient,
|
|
8
8
|
source: QuestionPreview,
|
|
9
9
|
submission: ResponseSubmission,
|
|
10
|
-
current: () => ResponseInput | undefined,
|
|
11
|
-
setOutcome: (outcome: string) => void,
|
|
12
|
-
setStatus: (status: string) => void,
|
|
13
10
|
) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
setStatus("Pending: registering reviewed context, then recording response…");
|
|
20
|
-
try {
|
|
21
|
-
const question = await native.mutate(
|
|
22
|
-
native.responses.registerQuestion.run({ item: source.item, request: source.request, revision: submission.revision }),
|
|
23
|
-
);
|
|
24
|
-
const { answerContext: _answerContext, recovery: _recovery, ...input } = submission;
|
|
25
|
-
await native.mutate(native.responses.recordResponse.run({ ...input, question: question.id }));
|
|
26
|
-
const newer = !Equal.equals(current(), submission);
|
|
27
|
-
setOutcome("saved");
|
|
28
|
-
setStatus(
|
|
29
|
-
`Saved: responses/${submission.id}.md. This records feedback, not acceptance.${newer ? " Your current draft remains unsaved." : ""}`,
|
|
30
|
-
);
|
|
31
|
-
return submission;
|
|
32
|
-
} catch (error) {
|
|
33
|
-
const failure = responseFailure(error);
|
|
34
|
-
setOutcome(failure.outcome);
|
|
35
|
-
setStatus(failure.text);
|
|
36
|
-
throw error;
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
});
|
|
40
|
-
}
|
|
11
|
+
const question = yield* client.responses.registerQuestion.run({ item: source.item, request: source.request, revision: submission.revision });
|
|
12
|
+
const { answerContext: _answerContext, recovery: _recovery, ...input } = submission;
|
|
13
|
+
yield* client.responses.recordResponse.run({ ...input, question: question.id });
|
|
14
|
+
return submission;
|
|
15
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CodexLimits, GithubLimits, UsageWindow } from "#browser/diagnostics/schema.ts";
|
|
1
|
+
import type { CodexLimits, GithubLimits, GithubWindow, UsageWindow } from "#browser/diagnostics/schema.ts";
|
|
2
2
|
import { resetLabel } from "#diagnostics/resetLabel.ts";
|
|
3
3
|
export function ObservedTime({ at }: { readonly at: number | null }) {
|
|
4
4
|
return at === null ? (
|
|
@@ -71,33 +71,41 @@ export function DiagnosticsWindows({ value, now }: { readonly value: CodexLimits
|
|
|
71
71
|
</ul>
|
|
72
72
|
);
|
|
73
73
|
}
|
|
74
|
+
const GITHUB_RESOURCES: Readonly<Record<string, string>> = { core: "REST", graphql: "GraphQL", search: "Search" };
|
|
75
|
+
const GITHUB_PAUSES = { "rate-limit": "Rate-limited", reserve: "GitHub paused below the 20% reserve" } as const;
|
|
74
76
|
export function DiagnosticsGithub({ value, now }: { readonly value: GithubLimits; readonly now: number }) {
|
|
75
|
-
const windows = (
|
|
76
|
-
[
|
|
77
|
-
["REST", value.core],
|
|
78
|
-
["GraphQL", value.graphql],
|
|
79
|
-
] as const
|
|
80
|
-
).map(([name, window]) => <GithubWindow key={name} name={name} now={now} window={window} />);
|
|
81
77
|
return (
|
|
82
78
|
<>
|
|
83
|
-
<dl className="grid gap-4 text-sm [&_dt]:text-muted-foreground">
|
|
84
|
-
|
|
79
|
+
<dl className="grid gap-4 text-sm [&_dt]:text-muted-foreground">
|
|
80
|
+
{value.map((window) => (
|
|
81
|
+
<GithubResource key={window.resource} now={now} window={window} />
|
|
82
|
+
))}
|
|
83
|
+
</dl>
|
|
84
|
+
<p className="text-muted-foreground text-xs">Recorded from the rate-limit headers of Fleet's own GitHub responses.</p>
|
|
85
85
|
</>
|
|
86
86
|
);
|
|
87
87
|
}
|
|
88
|
-
function
|
|
88
|
+
function GithubResource({ window, now }: { readonly window: GithubWindow; readonly now: number }) {
|
|
89
89
|
return (
|
|
90
|
-
<div>
|
|
91
|
-
<dt>{
|
|
90
|
+
<div data-resource={window.resource}>
|
|
91
|
+
<dt>{GITHUB_RESOURCES[window.resource] ?? window.resource}</dt>
|
|
92
92
|
<dd>
|
|
93
93
|
<strong>
|
|
94
94
|
{window.remaining} / {window.limit}
|
|
95
95
|
</strong>{" "}
|
|
96
96
|
remaining
|
|
97
97
|
</dd>
|
|
98
|
+
{window.limitedUntil !== null && window.limitedUntil > now ? (
|
|
99
|
+
<dd>
|
|
100
|
+
<strong>{GITHUB_PAUSES[window.limitedBy ?? "rate-limit"]}</strong> until <Reset at={window.limitedUntil} now={now} />
|
|
101
|
+
</dd>
|
|
102
|
+
) : null}
|
|
98
103
|
<dd>
|
|
99
104
|
Resets <Reset at={window.reset * 1000} now={now} />
|
|
100
105
|
</dd>
|
|
106
|
+
<dd>
|
|
107
|
+
Observed <time dateTime={new Date(window.observedAt).toISOString()}>{resetLabel(window.observedAt, now)}</time>
|
|
108
|
+
</dd>
|
|
101
109
|
</div>
|
|
102
110
|
);
|
|
103
111
|
}
|
|
@@ -1,43 +1,8 @@
|
|
|
1
|
-
import { RegistryContext } from "@effect/atom-react";
|
|
2
|
-
import { RouterProvider } from "@tanstack/react-router";
|
|
3
|
-
import { createRoot } from "react-dom/client";
|
|
4
1
|
import { session } from "#client/entry.ts";
|
|
5
|
-
import {
|
|
2
|
+
import { mountBoard } from "./mountBoard.tsx";
|
|
6
3
|
import "#client/react/entry.css";
|
|
7
4
|
|
|
8
5
|
const container = document.querySelector("[data-board-react-root]");
|
|
9
6
|
if (container) {
|
|
10
|
-
|
|
11
|
-
let native = session(window);
|
|
12
|
-
let started = false;
|
|
13
|
-
function ready() {
|
|
14
|
-
if (started) {
|
|
15
|
-
return;
|
|
16
|
-
}
|
|
17
|
-
started = true;
|
|
18
|
-
document.documentElement.dataset.boardReady = "true";
|
|
19
|
-
document.documentElement.dataset.js = "true";
|
|
20
|
-
}
|
|
21
|
-
const reading = history.state?.workBoard;
|
|
22
|
-
const router = boardRouter({ api: native.api, client: native, reading, ready, registry: native.registry });
|
|
23
|
-
if (reading) {
|
|
24
|
-
history.replaceState({ ...history.state, workBoard: reading }, "");
|
|
25
|
-
}
|
|
26
|
-
function render() {
|
|
27
|
-
root.render(
|
|
28
|
-
<RegistryContext.Provider value={native.registry}>
|
|
29
|
-
<RouterProvider router={router} />
|
|
30
|
-
</RegistryContext.Provider>,
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
render();
|
|
34
|
-
window.addEventListener("pageshow", (event) => {
|
|
35
|
-
if (!event.persisted) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
native = session(window);
|
|
39
|
-
router.update({ context: { shell: { api: native.api, client: native, reading, ready, registry: native.registry } } });
|
|
40
|
-
void router.invalidate();
|
|
41
|
-
render();
|
|
42
|
-
});
|
|
7
|
+
mountBoard(container, () => session(window));
|
|
43
8
|
}
|
|
@@ -1,13 +1,10 @@
|
|
|
1
1
|
export interface MainLocation {
|
|
2
2
|
readonly file: string;
|
|
3
|
+
readonly projection: string;
|
|
4
|
+
readonly route: string;
|
|
5
|
+
readonly status: number;
|
|
3
6
|
readonly title?: string | undefined;
|
|
4
7
|
readonly view: string;
|
|
5
8
|
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const title = main?.querySelector("h1")?.textContent?.trim();
|
|
9
|
-
return { file, title, view: main?.dataset.view ?? "" };
|
|
10
|
-
}
|
|
11
|
-
export function sameMainLocation(previous: MainLocation, next: MainLocation) {
|
|
12
|
-
return previous.file === next.file && previous.view === next.view && previous.title === next.title;
|
|
13
|
-
}
|
|
9
|
+
|
|
10
|
+
export const emptyMainLocation: MainLocation = { file: "", projection: "document", route: "", status: 200, view: "" };
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { RegistryContext } from "@effect/atom-react";
|
|
2
|
+
import { RouterProvider } from "@tanstack/react-router";
|
|
3
|
+
import { createRoot } from "react-dom/client";
|
|
4
|
+
import type { BrowserClient } from "#client/client.ts";
|
|
5
|
+
import { boardRouter } from "./boardRouter.ts";
|
|
6
|
+
|
|
7
|
+
export function mountBoard(container: Element, readSession: () => BrowserClient) {
|
|
8
|
+
const root = createRoot(container);
|
|
9
|
+
let native = readSession();
|
|
10
|
+
let generation = 0;
|
|
11
|
+
let started = false;
|
|
12
|
+
function ready() {
|
|
13
|
+
if (started) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
started = true;
|
|
17
|
+
document.documentElement.dataset.boardReady = "true";
|
|
18
|
+
document.documentElement.dataset.js = "true";
|
|
19
|
+
}
|
|
20
|
+
const reading = history.state?.workBoard;
|
|
21
|
+
let router = boardRouter({ api: native.api, client: native, reading, ready, registry: native.registry });
|
|
22
|
+
const navigation = router.history;
|
|
23
|
+
if (reading) {
|
|
24
|
+
history.replaceState({ ...history.state, workBoard: reading }, "");
|
|
25
|
+
}
|
|
26
|
+
function render() {
|
|
27
|
+
root.render(
|
|
28
|
+
<RegistryContext.Provider key={generation} value={native.registry}>
|
|
29
|
+
<RouterProvider router={router} />
|
|
30
|
+
</RegistryContext.Provider>,
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
render();
|
|
34
|
+
function restore(event: PageTransitionEvent) {
|
|
35
|
+
if (!event.persisted) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
native = readSession();
|
|
39
|
+
generation += 1;
|
|
40
|
+
router = boardRouter({ api: native.api, client: native, reading, ready, registry: native.registry }, navigation);
|
|
41
|
+
render();
|
|
42
|
+
}
|
|
43
|
+
window.addEventListener("pageshow", restore);
|
|
44
|
+
return () => {
|
|
45
|
+
window.removeEventListener("pageshow", restore);
|
|
46
|
+
root.unmount();
|
|
47
|
+
navigation.destroy();
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
import type { AnyRouter } from "@tanstack/react-router";
|
|
1
2
|
import { readingEntry } from "#client/react/storedReadings.ts";
|
|
2
3
|
|
|
3
|
-
export function navigationFailure(status:
|
|
4
|
-
const code =
|
|
4
|
+
export function navigationFailure(status: number) {
|
|
5
|
+
const code = status;
|
|
5
6
|
if (code < 400) {
|
|
6
7
|
return "";
|
|
7
8
|
}
|
|
@@ -25,3 +26,14 @@ export function sameReadingLocation(
|
|
|
25
26
|
) {
|
|
26
27
|
return previous.route === next.route && previous.id === next.id && previous.hash === next.hash;
|
|
27
28
|
}
|
|
29
|
+
|
|
30
|
+
export function recordEntry(router: AnyRouter, route: string, id: string, native: boolean) {
|
|
31
|
+
if (!native) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
router.history.flush?.();
|
|
35
|
+
if (window.location.pathname + window.location.search !== route || window.history.state?.workBoard?.id === id) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
window.history.replaceState({ ...window.history.state, workBoard: { id } }, "");
|
|
39
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type * as AtomRegistry from "effect/reactivity/AtomRegistry";
|
|
2
|
+
import type { MainLocation } from "./mainLocation.ts";
|
|
2
3
|
import { pageQueries } from "./pageQueries.ts";
|
|
3
4
|
import type { ShellApi } from "./ShellApi.ts";
|
|
4
5
|
|
|
5
|
-
export function retryPage(api: ShellApi, registry: AtomRegistry.AtomRegistry,
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
if (Number(doc?.dataset.status ?? 200) < 400 && !queries.some((query) => registry.get(query)._tag === "Failure")) {
|
|
6
|
+
export function retryPage(api: ShellApi, registry: AtomRegistry.AtomRegistry, page: MainLocation) {
|
|
7
|
+
const queries = pageQueries(api, page.projection, page.route);
|
|
8
|
+
if (page.status < 400 && !queries.some((query) => registry.get(query)._tag === "Failure")) {
|
|
9
9
|
return false;
|
|
10
10
|
}
|
|
11
11
|
for (const query of queries) {
|
|
@@ -9,18 +9,10 @@ export function scheduleReading(
|
|
|
9
9
|
setStatus: (status: string) => void,
|
|
10
10
|
focus: boolean,
|
|
11
11
|
) {
|
|
12
|
-
let restored = false;
|
|
13
12
|
function restore() {
|
|
14
|
-
if (
|
|
15
|
-
document.removeEventListener("board-reading-ready", restore);
|
|
13
|
+
if (!active()) {
|
|
16
14
|
return;
|
|
17
15
|
}
|
|
18
|
-
const context = doc.querySelector<HTMLElement>(".item-context");
|
|
19
|
-
if (context && context.dataset.readingReady !== "true") {
|
|
20
|
-
return;
|
|
21
|
-
}
|
|
22
|
-
restored = true;
|
|
23
|
-
document.removeEventListener("board-reading-ready", restore);
|
|
24
16
|
if (focus && !document.activeElement?.closest("[data-response-form], #response-form, #handoff-form")) {
|
|
25
17
|
doc.focus({ preventScroll: true });
|
|
26
18
|
}
|
|
@@ -41,6 +33,5 @@ export function scheduleReading(
|
|
|
41
33
|
}
|
|
42
34
|
});
|
|
43
35
|
}
|
|
44
|
-
document.addEventListener("board-reading-ready", restore);
|
|
45
36
|
requestAnimationFrame(restore);
|
|
46
37
|
}
|
|
@@ -37,7 +37,6 @@ export function useAppearance() {
|
|
|
37
37
|
if (doc) {
|
|
38
38
|
doc.dataset.scheme = scheme;
|
|
39
39
|
}
|
|
40
|
-
document.dispatchEvent(new Event("board-theme"));
|
|
41
40
|
}, [value.theme, value.density, scheme]);
|
|
42
41
|
function change(next: Partial<Pick<typeof value, "closed" | "density" | "theme">>) {
|
|
43
42
|
const appearance = { closed: valueRef.current.closed, density: valueRef.current.density, theme: valueRef.current.theme, ...next };
|
|
@@ -50,6 +49,6 @@ export function useAppearance() {
|
|
|
50
49
|
valueRef.current = { ...appearance, notice };
|
|
51
50
|
setValue(valueRef.current);
|
|
52
51
|
}
|
|
53
|
-
return { ...value, change };
|
|
52
|
+
return { ...value, change, scheme };
|
|
54
53
|
}
|
|
55
|
-
export type AppearanceControls = ReturnType<typeof useAppearance>;
|
|
54
|
+
export type AppearanceControls = Omit<ReturnType<typeof useAppearance>, "scheme">;
|
|
@@ -1,15 +1,27 @@
|
|
|
1
1
|
import { useRouter } from "@tanstack/react-router";
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
2
|
+
import { useContext, useEffect, useRef, useState } from "react";
|
|
3
3
|
import type { RouterShell } from "#client/react/loadBoardPage.ts";
|
|
4
|
-
import {
|
|
4
|
+
import { useMainLocation } from "#client/react/MainLocationContext.ts";
|
|
5
|
+
import { currentEntry, navigationFailure, readingKey, recordEntry, sameReadingLocation } from "#client/react/navigationLocation.ts";
|
|
6
|
+
import { ReadingReadyContext, readingReady } from "#client/react/ReadingReadyContext.ts";
|
|
5
7
|
import { readerLink } from "#client/react/readerLink.ts";
|
|
6
8
|
import { captureReading } from "#client/react/readingState.ts";
|
|
7
9
|
import { retryPage } from "#client/react/retryPage.ts";
|
|
8
10
|
import { scheduleReading } from "#client/react/scheduleReading.ts";
|
|
9
11
|
import { readingEntry, storedReadings } from "#client/react/storedReadings.ts";
|
|
10
12
|
|
|
11
|
-
export function useBoardNavigation(shell: RouterShell) {
|
|
13
|
+
export function useBoardNavigation(shell: RouterShell, onCurrentDestination?: () => void) {
|
|
12
14
|
const router = useRouter();
|
|
15
|
+
const main = useMainLocation();
|
|
16
|
+
const { element } = useContext(ReadingReadyContext);
|
|
17
|
+
const readyRef = useRef(element);
|
|
18
|
+
const mainRef = useRef(main);
|
|
19
|
+
const pageRef = useRef<(() => void) | undefined>(undefined);
|
|
20
|
+
useEffect(() => {
|
|
21
|
+
mainRef.current = main;
|
|
22
|
+
readyRef.current = element;
|
|
23
|
+
pageRef.current?.();
|
|
24
|
+
}, [main, element]);
|
|
13
25
|
const [status, setStatus] = useState("");
|
|
14
26
|
useEffect(() => {
|
|
15
27
|
const readings = storedReadings();
|
|
@@ -21,7 +33,7 @@ export function useBoardNavigation(shell: RouterShell) {
|
|
|
21
33
|
let failure = "";
|
|
22
34
|
let interrupted = false;
|
|
23
35
|
function save() {
|
|
24
|
-
if (!displayed ||
|
|
36
|
+
if (!displayed || mainRef.current.route !== route || router.state.location.pathname + router.state.location.searchStr !== route) {
|
|
25
37
|
interrupted ||= displayed !== "";
|
|
26
38
|
return;
|
|
27
39
|
}
|
|
@@ -34,11 +46,11 @@ export function useBoardNavigation(shell: RouterShell) {
|
|
|
34
46
|
const location = router.state.resolvedLocation ?? router.state.location;
|
|
35
47
|
const nextRoute = location.pathname + location.searchStr;
|
|
36
48
|
const doc = document.getElementById("doc");
|
|
37
|
-
if (doc
|
|
49
|
+
if (!doc || mainRef.current.route !== nextRoute || !readingReady(doc, readyRef.current)) {
|
|
38
50
|
return;
|
|
39
51
|
}
|
|
40
52
|
const previousFailure = failure;
|
|
41
|
-
failure = navigationFailure(
|
|
53
|
+
failure = navigationFailure(mainRef.current.status);
|
|
42
54
|
if (failure) {
|
|
43
55
|
setStatus(failure);
|
|
44
56
|
return;
|
|
@@ -57,13 +69,19 @@ export function useBoardNavigation(shell: RouterShell) {
|
|
|
57
69
|
route = nextRoute;
|
|
58
70
|
hash = location.hash;
|
|
59
71
|
recordEntry(router, nextRoute, id, shell.client !== undefined);
|
|
60
|
-
scheduleReading(doc, reading, hash, () => displayed === id &&
|
|
72
|
+
scheduleReading(doc, reading, hash, () => displayed === id && mainRef.current.route === nextRoute && doc.isConnected, setStatus, focus);
|
|
61
73
|
}
|
|
62
74
|
async function open(target: URL) {
|
|
63
75
|
save();
|
|
64
|
-
document.dispatchEvent(new Event("board-navigate"));
|
|
65
76
|
const url = target.pathname + target.search + target.hash;
|
|
66
|
-
if (url === router.state.location.href
|
|
77
|
+
if (url === router.state.location.href) {
|
|
78
|
+
onCurrentDestination?.();
|
|
79
|
+
}
|
|
80
|
+
if (
|
|
81
|
+
url === router.state.location.href
|
|
82
|
+
&& mainRef.current.route === target.pathname + target.search
|
|
83
|
+
&& retryPage(shell.api, shell.registry, mainRef.current)
|
|
84
|
+
) {
|
|
67
85
|
await router.invalidate();
|
|
68
86
|
} else if (url !== router.state.location.href) {
|
|
69
87
|
await router.navigate({ to: url });
|
|
@@ -107,7 +125,7 @@ export function useBoardNavigation(shell: RouterShell) {
|
|
|
107
125
|
const resolved = router.subscribe("onResolved", page);
|
|
108
126
|
window.history.scrollRestoration = "manual";
|
|
109
127
|
document.addEventListener("click", click);
|
|
110
|
-
|
|
128
|
+
pageRef.current = page;
|
|
111
129
|
window.addEventListener("pagehide", save);
|
|
112
130
|
page();
|
|
113
131
|
return () => {
|
|
@@ -115,20 +133,9 @@ export function useBoardNavigation(shell: RouterShell) {
|
|
|
115
133
|
resolved();
|
|
116
134
|
document.removeEventListener("submit", submit);
|
|
117
135
|
document.removeEventListener("click", click);
|
|
118
|
-
|
|
136
|
+
pageRef.current = undefined;
|
|
119
137
|
window.removeEventListener("pagehide", save);
|
|
120
138
|
};
|
|
121
|
-
}, [router, shell.api, shell.registry, shell.reading, shell.client]);
|
|
139
|
+
}, [router, shell.api, shell.registry, shell.reading, shell.client, onCurrentDestination]);
|
|
122
140
|
return status;
|
|
123
141
|
}
|
|
124
|
-
|
|
125
|
-
function recordEntry(router: ReturnType<typeof useRouter>, route: string, id: string, native: boolean) {
|
|
126
|
-
if (!native) {
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
router.history.flush?.();
|
|
130
|
-
if (window.location.pathname + window.location.search !== route || window.history.state?.workBoard?.id === id) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
window.history.replaceState({ ...window.history.state, workBoard: { id } }, "");
|
|
134
|
-
}
|
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
import { RegistryContext } from "@effect/atom-react";
|
|
2
2
|
import type * as Atom from "effect/reactivity/Atom";
|
|
3
3
|
import { useContext, useEffect } from "react";
|
|
4
|
-
import {
|
|
4
|
+
import type { BrowserClient } from "#client/client.ts";
|
|
5
5
|
|
|
6
|
-
export function useDiagnosticsPolling<A, TFleet>(
|
|
6
|
+
export function useDiagnosticsPolling<A, TFleet>(
|
|
7
|
+
client: (Pick<BrowserClient, "registry"> & { readonly updates: Pick<BrowserClient["updates"], "paused"> }) | undefined,
|
|
8
|
+
atom: Atom.Atom<A>,
|
|
9
|
+
fleet?: Atom.Atom<TFleet>,
|
|
10
|
+
) {
|
|
7
11
|
const registry = useContext(RegistryContext);
|
|
8
12
|
useEffect(() => {
|
|
9
13
|
function refresh() {
|
|
10
|
-
|
|
11
|
-
if (!(document.hidden || native.registry.get(native.updates.paused))) {
|
|
14
|
+
if (!(document.hidden || client?.registry.get(client.updates.paused))) {
|
|
12
15
|
registry.refresh(atom);
|
|
13
16
|
if (fleet) {
|
|
14
17
|
registry.refresh(fleet);
|
|
@@ -16,12 +19,16 @@ export function useDiagnosticsPolling<A, TFleet>(atom: Atom.Atom<A>, fleet?: Ato
|
|
|
16
19
|
}
|
|
17
20
|
}
|
|
18
21
|
const timer = setInterval(refresh, 15_000);
|
|
19
|
-
|
|
22
|
+
const resumed = client?.registry.subscribe(client.updates.paused, (paused) => {
|
|
23
|
+
if (!paused) {
|
|
24
|
+
refresh();
|
|
25
|
+
}
|
|
26
|
+
});
|
|
20
27
|
document.addEventListener("visibilitychange", refresh);
|
|
21
28
|
return () => {
|
|
22
29
|
clearInterval(timer);
|
|
23
|
-
|
|
30
|
+
resumed?.();
|
|
24
31
|
document.removeEventListener("visibilitychange", refresh);
|
|
25
32
|
};
|
|
26
|
-
}, [atom, fleet, registry]);
|
|
33
|
+
}, [atom, fleet, registry, client]);
|
|
27
34
|
}
|
|
@@ -3,7 +3,7 @@ import { flushSync } from "react-dom";
|
|
|
3
3
|
import type { Document } from "#browser/document/schema.ts";
|
|
4
4
|
import { documentSourceId } from "#client/document/layout.ts";
|
|
5
5
|
import { fileUrl } from "#files/url.ts";
|
|
6
|
-
import {
|
|
6
|
+
import type { MainLocation } from "./mainLocation.ts";
|
|
7
7
|
export function useDocumentPage({
|
|
8
8
|
data,
|
|
9
9
|
pending,
|
|
@@ -25,9 +25,7 @@ export function useDocumentPage({
|
|
|
25
25
|
}
|
|
26
26
|
const main = element;
|
|
27
27
|
main.dataset.scheme = document.documentElement.dataset.scheme ?? "";
|
|
28
|
-
|
|
29
|
-
delete main.dataset.route;
|
|
30
|
-
}
|
|
28
|
+
delete main.dataset.route;
|
|
31
29
|
let active = true;
|
|
32
30
|
let scheduled = false;
|
|
33
31
|
function announce() {
|
|
@@ -72,10 +70,18 @@ function publishPage(main: HTMLElement, data: Document | undefined, status: stri
|
|
|
72
70
|
} else {
|
|
73
71
|
delete main.dataset.identity;
|
|
74
72
|
}
|
|
75
|
-
flushSync(() => onPage(displayedLocation(main)));
|
|
76
73
|
main.dataset.route = url;
|
|
77
74
|
main.dataset.status = status;
|
|
78
|
-
|
|
75
|
+
flushSync(() =>
|
|
76
|
+
onPage({
|
|
77
|
+
file: data?.file ?? "",
|
|
78
|
+
projection: "document",
|
|
79
|
+
route: url,
|
|
80
|
+
status: Number(status),
|
|
81
|
+
title: main.querySelector("h1")?.textContent?.trim(),
|
|
82
|
+
view: "",
|
|
83
|
+
}),
|
|
84
|
+
);
|
|
79
85
|
}
|
|
80
86
|
function affectsDocument(record: MutationRecord) {
|
|
81
87
|
const element = record.target instanceof Element ? record.target : record.target.parentElement;
|