@xortex/xcode 3.0.5 → 3.1.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/INSTALLATION.md +285 -0
- package/QUICKSTART.md +151 -0
- package/SYSTEM_PROMPT.md +583 -0
- package/SYSTEM_PROMPT_EXTRACTED.md +1 -0
- package/Untitled +1 -0
- package/bin/xcode +69 -120
- package/bootstrap/state.ts +1758 -0
- package/bun-bundle-hook.js +38 -17
- package/bun-bundle-shim.ts +12 -0
- package/bun.lock +645 -0
- package/context/QueuedMessageContext.tsx +63 -0
- package/context/fpsMetrics.tsx +30 -0
- package/context/mailbox.tsx +38 -0
- package/context/modalContext.tsx +58 -0
- package/context/notifications.tsx +240 -0
- package/context/overlayContext.tsx +151 -0
- package/context/promptOverlayContext.tsx +125 -0
- package/context/stats.tsx +220 -0
- package/context/voice.tsx +88 -0
- package/coordinator/coordinatorMode.ts +369 -0
- package/costHook.ts +22 -0
- package/dialogLaunchers.tsx +133 -0
- package/entrypoints/cli.tsx +1 -1
- package/extract_prompt.ts +304 -0
- package/ink.ts +85 -0
- package/install.sh +221 -0
- package/interactiveHelpers.tsx +366 -0
- package/macro.ts +1 -1
- package/memdir/findRelevantMemories.ts +141 -0
- package/memdir/memdir.ts +511 -0
- package/memdir/memoryAge.ts +53 -0
- package/memdir/memoryScan.ts +94 -0
- package/memdir/memoryTypes.ts +271 -0
- package/memdir/paths.ts +291 -0
- package/memdir/teamMemPaths.ts +292 -0
- package/memdir/teamMemPrompts.ts +100 -0
- package/moreright/useMoreRight.tsx +26 -0
- package/native-ts/color-diff/index.ts +999 -0
- package/native-ts/file-index/index.ts +370 -0
- package/native-ts/yoga-layout/enums.ts +134 -0
- package/native-ts/yoga-layout/index.ts +2578 -0
- package/outputStyles/loadOutputStylesDir.ts +98 -0
- package/package.json +5 -42
- package/plugins/builtinPlugins.ts +159 -0
- package/plugins/bundled/index.ts +23 -0
- package/projectOnboardingState.ts +83 -0
- package/public/claude-files.png +0 -0
- package/public/leak-tweet.png +0 -0
- package/query/config.ts +46 -0
- package/query/deps.ts +40 -0
- package/query/stopHooks.ts +470 -0
- package/query/tokenBudget.ts +93 -0
- package/replLauncher.tsx +27 -0
- package/schemas/hooks.ts +222 -0
- package/screens/Doctor.tsx +575 -0
- package/screens/REPL.tsx +7107 -0
- package/screens/ResumeConversation.tsx +399 -0
- package/scripts/postinstall.js +90 -0
- package/server/createDirectConnectSession.ts +88 -0
- package/server/directConnectManager.ts +213 -0
- package/server/types.ts +57 -0
- package/setup.ts +477 -0
- package/stub_types.sh +13 -0
- package/tasks.ts +39 -0
- package/tools.ts +396 -0
- package/tsconfig.json +16 -0
- package/upstreamproxy/relay.ts +455 -0
- package/upstreamproxy/upstreamproxy.ts +285 -0
- package/vim/motions.ts +82 -0
- package/vim/operators.ts +556 -0
- package/vim/textObjects.ts +186 -0
- package/vim/transitions.ts +490 -0
- package/vim/types.ts +199 -0
- package/voice/voiceModeEnabled.ts +54 -0
- package/utils/bunBundleCompat.ts +0 -44
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { c as _c } from "react/compiler-runtime";
|
|
2
|
+
import * as React from 'react';
|
|
3
|
+
import { Box } from '../ink.js';
|
|
4
|
+
type QueuedMessageContextValue = {
|
|
5
|
+
isQueued: boolean;
|
|
6
|
+
isFirst: boolean;
|
|
7
|
+
/** Width reduction for container padding (e.g., 4 for paddingX={2}) */
|
|
8
|
+
paddingWidth: number;
|
|
9
|
+
};
|
|
10
|
+
const QueuedMessageContext = React.createContext<QueuedMessageContextValue | undefined>(undefined);
|
|
11
|
+
export function useQueuedMessage() {
|
|
12
|
+
return React.useContext(QueuedMessageContext);
|
|
13
|
+
}
|
|
14
|
+
const PADDING_X = 2;
|
|
15
|
+
type Props = {
|
|
16
|
+
isFirst: boolean;
|
|
17
|
+
useBriefLayout?: boolean;
|
|
18
|
+
children: React.ReactNode;
|
|
19
|
+
};
|
|
20
|
+
export function QueuedMessageProvider(t0) {
|
|
21
|
+
const $ = _c(9);
|
|
22
|
+
const {
|
|
23
|
+
isFirst,
|
|
24
|
+
useBriefLayout,
|
|
25
|
+
children
|
|
26
|
+
} = t0;
|
|
27
|
+
const padding = useBriefLayout ? 0 : PADDING_X;
|
|
28
|
+
const t1 = padding * 2;
|
|
29
|
+
let t2;
|
|
30
|
+
if ($[0] !== isFirst || $[1] !== t1) {
|
|
31
|
+
t2 = {
|
|
32
|
+
isQueued: true,
|
|
33
|
+
isFirst,
|
|
34
|
+
paddingWidth: t1
|
|
35
|
+
};
|
|
36
|
+
$[0] = isFirst;
|
|
37
|
+
$[1] = t1;
|
|
38
|
+
$[2] = t2;
|
|
39
|
+
} else {
|
|
40
|
+
t2 = $[2];
|
|
41
|
+
}
|
|
42
|
+
const value = t2;
|
|
43
|
+
let t3;
|
|
44
|
+
if ($[3] !== children || $[4] !== padding) {
|
|
45
|
+
t3 = <Box paddingX={padding}>{children}</Box>;
|
|
46
|
+
$[3] = children;
|
|
47
|
+
$[4] = padding;
|
|
48
|
+
$[5] = t3;
|
|
49
|
+
} else {
|
|
50
|
+
t3 = $[5];
|
|
51
|
+
}
|
|
52
|
+
let t4;
|
|
53
|
+
if ($[6] !== t3 || $[7] !== value) {
|
|
54
|
+
t4 = <QueuedMessageContext.Provider value={value}>{t3}</QueuedMessageContext.Provider>;
|
|
55
|
+
$[6] = t3;
|
|
56
|
+
$[7] = value;
|
|
57
|
+
$[8] = t4;
|
|
58
|
+
} else {
|
|
59
|
+
t4 = $[8];
|
|
60
|
+
}
|
|
61
|
+
return t4;
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsIkJveCIsIlF1ZXVlZE1lc3NhZ2VDb250ZXh0VmFsdWUiLCJpc1F1ZXVlZCIsImlzRmlyc3QiLCJwYWRkaW5nV2lkdGgiLCJRdWV1ZWRNZXNzYWdlQ29udGV4dCIsImNyZWF0ZUNvbnRleHQiLCJ1bmRlZmluZWQiLCJ1c2VRdWV1ZWRNZXNzYWdlIiwidXNlQ29udGV4dCIsIlBBRERJTkdfWCIsIlByb3BzIiwidXNlQnJpZWZMYXlvdXQiLCJjaGlsZHJlbiIsIlJlYWN0Tm9kZSIsIlF1ZXVlZE1lc3NhZ2VQcm92aWRlciIsInQwIiwiJCIsIl9jIiwicGFkZGluZyIsInQxIiwidDIiLCJ2YWx1ZSIsInQzIiwidDQiXSwic291cmNlcyI6WyJRdWV1ZWRNZXNzYWdlQ29udGV4dC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgUmVhY3QgZnJvbSAncmVhY3QnXG5pbXBvcnQgeyBCb3ggfSBmcm9tICcuLi9pbmsuanMnXG5cbnR5cGUgUXVldWVkTWVzc2FnZUNvbnRleHRWYWx1ZSA9IHtcbiAgaXNRdWV1ZWQ6IGJvb2xlYW5cbiAgaXNGaXJzdDogYm9vbGVhblxuICAvKiogV2lkdGggcmVkdWN0aW9uIGZvciBjb250YWluZXIgcGFkZGluZyAoZS5nLiwgNCBmb3IgcGFkZGluZ1g9ezJ9KSAqL1xuICBwYWRkaW5nV2lkdGg6IG51bWJlclxufVxuXG5jb25zdCBRdWV1ZWRNZXNzYWdlQ29udGV4dCA9IFJlYWN0LmNyZWF0ZUNvbnRleHQ8XG4gIFF1ZXVlZE1lc3NhZ2VDb250ZXh0VmFsdWUgfCB1bmRlZmluZWRcbj4odW5kZWZpbmVkKVxuXG5leHBvcnQgZnVuY3Rpb24gdXNlUXVldWVkTWVzc2FnZSgpOiBRdWV1ZWRNZXNzYWdlQ29udGV4dFZhbHVlIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIFJlYWN0LnVzZUNvbnRleHQoUXVldWVkTWVzc2FnZUNvbnRleHQpXG59XG5cbmNvbnN0IFBBRERJTkdfWCA9IDJcblxudHlwZSBQcm9wcyA9IHtcbiAgaXNGaXJzdDogYm9vbGVhblxuICB1c2VCcmllZkxheW91dD86IGJvb2xlYW5cbiAgY2hpbGRyZW46IFJlYWN0LlJlYWN0Tm9kZVxufVxuXG5leHBvcnQgZnVuY3Rpb24gUXVldWVkTWVzc2FnZVByb3ZpZGVyKHtcbiAgaXNGaXJzdCxcbiAgdXNlQnJpZWZMYXlvdXQsXG4gIGNoaWxkcmVuLFxufTogUHJvcHMpOiBSZWFjdC5SZWFjdE5vZGUge1xuICAvLyBCcmllZiBtb2RlIGFscmVhZHkgaW5kZW50cyB2aWEgcGFkZGluZ0xlZnQgaW4gSGlnaGxpZ2h0ZWRUaGlua2luZ1RleHQgL1xuICAvLyBCcmllZlRvb2wgVUkg4oCUIGFkZGluZyBwYWRkaW5nWCBoZXJlIHdvdWxkIGRvdWJsZS1pbmRlbnQgdGhlIHF1ZXVlLlxuICBjb25zdCBwYWRkaW5nID0gdXNlQnJpZWZMYXlvdXQgPyAwIDogUEFERElOR19YXG4gIGNvbnN0IHZhbHVlID0gUmVhY3QudXNlTWVtbyhcbiAgICAoKSA9PiAoeyBpc1F1ZXVlZDogdHJ1ZSwgaXNGaXJzdCwgcGFkZGluZ1dpZHRoOiBwYWRkaW5nICogMiB9KSxcbiAgICBbaXNGaXJzdCwgcGFkZGluZ10sXG4gIClcblxuICByZXR1cm4gKFxuICAgIDxRdWV1ZWRNZXNzYWdlQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17dmFsdWV9PlxuICAgICAgPEJveCBwYWRkaW5nWD17cGFkZGluZ30+e2NoaWxkcmVufTwvQm94PlxuICAgIDwvUXVldWVkTWVzc2FnZUNvbnRleHQuUHJvdmlkZXI+XG4gIClcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUFBLE9BQU8sS0FBS0EsS0FBSyxNQUFNLE9BQU87QUFDOUIsU0FBU0MsR0FBRyxRQUFRLFdBQVc7QUFFL0IsS0FBS0MseUJBQXlCLEdBQUc7RUFDL0JDLFFBQVEsRUFBRSxPQUFPO0VBQ2pCQyxPQUFPLEVBQUUsT0FBTztFQUNoQjtFQUNBQyxZQUFZLEVBQUUsTUFBTTtBQUN0QixDQUFDO0FBRUQsTUFBTUMsb0JBQW9CLEdBQUdOLEtBQUssQ0FBQ08sYUFBYSxDQUM5Q0wseUJBQXlCLEdBQUcsU0FBUyxDQUN0QyxDQUFDTSxTQUFTLENBQUM7QUFFWixPQUFPLFNBQUFDLGlCQUFBO0VBQUEsT0FDRVQsS0FBSyxDQUFBVSxVQUFXLENBQUNKLG9CQUFvQixDQUFDO0FBQUE7QUFHL0MsTUFBTUssU0FBUyxHQUFHLENBQUM7QUFFbkIsS0FBS0MsS0FBSyxHQUFHO0VBQ1hSLE9BQU8sRUFBRSxPQUFPO0VBQ2hCUyxjQUFjLENBQUMsRUFBRSxPQUFPO0VBQ3hCQyxRQUFRLEVBQUVkLEtBQUssQ0FBQ2UsU0FBUztBQUMzQixDQUFDO0FBRUQsT0FBTyxTQUFBQyxzQkFBQUMsRUFBQTtFQUFBLE1BQUFDLENBQUEsR0FBQUMsRUFBQTtFQUErQjtJQUFBZixPQUFBO0lBQUFTLGNBQUE7SUFBQUM7RUFBQSxJQUFBRyxFQUk5QjtFQUdOLE1BQUFHLE9BQUEsR0FBZ0JQLGNBQWMsR0FBZCxDQUE4QixHQUE5QkYsU0FBOEI7RUFFSSxNQUFBVSxFQUFBLEdBQUFELE9BQU8sR0FBRyxDQUFDO0VBQUEsSUFBQUUsRUFBQTtFQUFBLElBQUFKLENBQUEsUUFBQWQsT0FBQSxJQUFBYyxDQUFBLFFBQUFHLEVBQUE7SUFBcERDLEVBQUE7TUFBQW5CLFFBQUEsRUFBWSxJQUFJO01BQUFDLE9BQUE7TUFBQUMsWUFBQSxFQUF5QmdCO0lBQVksQ0FBQztJQUFBSCxDQUFBLE1BQUFkLE9BQUE7SUFBQWMsQ0FBQSxNQUFBRyxFQUFBO0lBQUFILENBQUEsTUFBQUksRUFBQTtFQUFBO0lBQUFBLEVBQUEsR0FBQUosQ0FBQTtFQUFBO0VBRC9ELE1BQUFLLEtBQUEsR0FDU0QsRUFBc0Q7RUFFOUQsSUFBQUUsRUFBQTtFQUFBLElBQUFOLENBQUEsUUFBQUosUUFBQSxJQUFBSSxDQUFBLFFBQUFFLE9BQUE7SUFJR0ksRUFBQSxJQUFDLEdBQUcsQ0FBV0osUUFBTyxDQUFQQSxRQUFNLENBQUMsQ0FBR04sU0FBTyxDQUFFLEVBQWpDLEdBQUcsQ0FBb0M7SUFBQUksQ0FBQSxNQUFBSixRQUFBO0lBQUFJLENBQUEsTUFBQUUsT0FBQTtJQUFBRixDQUFBLE1BQUFNLEVBQUE7RUFBQTtJQUFBQSxFQUFBLEdBQUFOLENBQUE7RUFBQTtFQUFBLElBQUFPLEVBQUE7RUFBQSxJQUFBUCxDQUFBLFFBQUFNLEVBQUEsSUFBQU4sQ0FBQSxRQUFBSyxLQUFBO0lBRDFDRSxFQUFBLGtDQUFzQ0YsS0FBSyxDQUFMQSxNQUFJLENBQUMsQ0FDekMsQ0FBQUMsRUFBdUMsQ0FDekMsZ0NBQWdDO0lBQUFOLENBQUEsTUFBQU0sRUFBQTtJQUFBTixDQUFBLE1BQUFLLEtBQUE7SUFBQUwsQ0FBQSxNQUFBTyxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBUCxDQUFBO0VBQUE7RUFBQSxPQUZoQ08sRUFFZ0M7QUFBQSIsImlnbm9yZUxpc3QiOltdfQ==
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { c as _c } from "react/compiler-runtime";
|
|
2
|
+
import React, { createContext, useContext } from 'react';
|
|
3
|
+
import type { FpsMetrics } from '../utils/fpsTracker.js';
|
|
4
|
+
type FpsMetricsGetter = () => FpsMetrics | undefined;
|
|
5
|
+
const FpsMetricsContext = createContext<FpsMetricsGetter | undefined>(undefined);
|
|
6
|
+
type Props = {
|
|
7
|
+
getFpsMetrics: FpsMetricsGetter;
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
};
|
|
10
|
+
export function FpsMetricsProvider(t0) {
|
|
11
|
+
const $ = _c(3);
|
|
12
|
+
const {
|
|
13
|
+
getFpsMetrics,
|
|
14
|
+
children
|
|
15
|
+
} = t0;
|
|
16
|
+
let t1;
|
|
17
|
+
if ($[0] !== children || $[1] !== getFpsMetrics) {
|
|
18
|
+
t1 = <FpsMetricsContext.Provider value={getFpsMetrics}>{children}</FpsMetricsContext.Provider>;
|
|
19
|
+
$[0] = children;
|
|
20
|
+
$[1] = getFpsMetrics;
|
|
21
|
+
$[2] = t1;
|
|
22
|
+
} else {
|
|
23
|
+
t1 = $[2];
|
|
24
|
+
}
|
|
25
|
+
return t1;
|
|
26
|
+
}
|
|
27
|
+
export function useFpsMetrics() {
|
|
28
|
+
return useContext(FpsMetricsContext);
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsImNyZWF0ZUNvbnRleHQiLCJ1c2VDb250ZXh0IiwiRnBzTWV0cmljcyIsIkZwc01ldHJpY3NHZXR0ZXIiLCJGcHNNZXRyaWNzQ29udGV4dCIsInVuZGVmaW5lZCIsIlByb3BzIiwiZ2V0RnBzTWV0cmljcyIsImNoaWxkcmVuIiwiUmVhY3ROb2RlIiwiRnBzTWV0cmljc1Byb3ZpZGVyIiwidDAiLCIkIiwiX2MiLCJ0MSIsInVzZUZwc01ldHJpY3MiXSwic291cmNlcyI6WyJmcHNNZXRyaWNzLnRzeCJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgUmVhY3QsIHsgY3JlYXRlQ29udGV4dCwgdXNlQ29udGV4dCB9IGZyb20gJ3JlYWN0J1xuaW1wb3J0IHR5cGUgeyBGcHNNZXRyaWNzIH0gZnJvbSAnLi4vdXRpbHMvZnBzVHJhY2tlci5qcydcblxudHlwZSBGcHNNZXRyaWNzR2V0dGVyID0gKCkgPT4gRnBzTWV0cmljcyB8IHVuZGVmaW5lZFxuXG5jb25zdCBGcHNNZXRyaWNzQ29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8RnBzTWV0cmljc0dldHRlciB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKVxuXG50eXBlIFByb3BzID0ge1xuICBnZXRGcHNNZXRyaWNzOiBGcHNNZXRyaWNzR2V0dGVyXG4gIGNoaWxkcmVuOiBSZWFjdC5SZWFjdE5vZGVcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIEZwc01ldHJpY3NQcm92aWRlcih7XG4gIGdldEZwc01ldHJpY3MsXG4gIGNoaWxkcmVuLFxufTogUHJvcHMpOiBSZWFjdC5SZWFjdE5vZGUge1xuICByZXR1cm4gKFxuICAgIDxGcHNNZXRyaWNzQ29udGV4dC5Qcm92aWRlciB2YWx1ZT17Z2V0RnBzTWV0cmljc30+XG4gICAgICB7Y2hpbGRyZW59XG4gICAgPC9GcHNNZXRyaWNzQ29udGV4dC5Qcm92aWRlcj5cbiAgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdXNlRnBzTWV0cmljcygpOiBGcHNNZXRyaWNzR2V0dGVyIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIHVzZUNvbnRleHQoRnBzTWV0cmljc0NvbnRleHQpXG59XG4iXSwibWFwcGluZ3MiOiI7QUFBQSxPQUFPQSxLQUFLLElBQUlDLGFBQWEsRUFBRUMsVUFBVSxRQUFRLE9BQU87QUFDeEQsY0FBY0MsVUFBVSxRQUFRLHdCQUF3QjtBQUV4RCxLQUFLQyxnQkFBZ0IsR0FBRyxHQUFHLEdBQUdELFVBQVUsR0FBRyxTQUFTO0FBRXBELE1BQU1FLGlCQUFpQixHQUFHSixhQUFhLENBQUNHLGdCQUFnQixHQUFHLFNBQVMsQ0FBQyxDQUFDRSxTQUFTLENBQUM7QUFFaEYsS0FBS0MsS0FBSyxHQUFHO0VBQ1hDLGFBQWEsRUFBRUosZ0JBQWdCO0VBQy9CSyxRQUFRLEVBQUVULEtBQUssQ0FBQ1UsU0FBUztBQUMzQixDQUFDO0FBRUQsT0FBTyxTQUFBQyxtQkFBQUMsRUFBQTtFQUFBLE1BQUFDLENBQUEsR0FBQUMsRUFBQTtFQUE0QjtJQUFBTixhQUFBO0lBQUFDO0VBQUEsSUFBQUcsRUFHM0I7RUFBQSxJQUFBRyxFQUFBO0VBQUEsSUFBQUYsQ0FBQSxRQUFBSixRQUFBLElBQUFJLENBQUEsUUFBQUwsYUFBQTtJQUVKTyxFQUFBLCtCQUFtQ1AsS0FBYSxDQUFiQSxjQUFZLENBQUMsQ0FDN0NDLFNBQU8sQ0FDViw2QkFBNkI7SUFBQUksQ0FBQSxNQUFBSixRQUFBO0lBQUFJLENBQUEsTUFBQUwsYUFBQTtJQUFBSyxDQUFBLE1BQUFFLEVBQUE7RUFBQTtJQUFBQSxFQUFBLEdBQUFGLENBQUE7RUFBQTtFQUFBLE9BRjdCRSxFQUU2QjtBQUFBO0FBSWpDLE9BQU8sU0FBQUMsY0FBQTtFQUFBLE9BQ0VkLFVBQVUsQ0FBQ0csaUJBQWlCLENBQUM7QUFBQSIsImlnbm9yZUxpc3QiOltdfQ==
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { c as _c } from "react/compiler-runtime";
|
|
2
|
+
import React, { createContext, useContext, useMemo } from 'react';
|
|
3
|
+
import { Mailbox } from '../utils/mailbox.js';
|
|
4
|
+
const MailboxContext = createContext<Mailbox | undefined>(undefined);
|
|
5
|
+
type Props = {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
};
|
|
8
|
+
export function MailboxProvider(t0) {
|
|
9
|
+
const $ = _c(3);
|
|
10
|
+
const {
|
|
11
|
+
children
|
|
12
|
+
} = t0;
|
|
13
|
+
let t1;
|
|
14
|
+
if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
|
|
15
|
+
t1 = new Mailbox();
|
|
16
|
+
$[0] = t1;
|
|
17
|
+
} else {
|
|
18
|
+
t1 = $[0];
|
|
19
|
+
}
|
|
20
|
+
const mailbox = t1;
|
|
21
|
+
let t2;
|
|
22
|
+
if ($[1] !== children) {
|
|
23
|
+
t2 = <MailboxContext.Provider value={mailbox}>{children}</MailboxContext.Provider>;
|
|
24
|
+
$[1] = children;
|
|
25
|
+
$[2] = t2;
|
|
26
|
+
} else {
|
|
27
|
+
t2 = $[2];
|
|
28
|
+
}
|
|
29
|
+
return t2;
|
|
30
|
+
}
|
|
31
|
+
export function useMailbox() {
|
|
32
|
+
const mailbox = useContext(MailboxContext);
|
|
33
|
+
if (!mailbox) {
|
|
34
|
+
throw new Error("useMailbox must be used within a MailboxProvider");
|
|
35
|
+
}
|
|
36
|
+
return mailbox;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsImNyZWF0ZUNvbnRleHQiLCJ1c2VDb250ZXh0IiwidXNlTWVtbyIsIk1haWxib3giLCJNYWlsYm94Q29udGV4dCIsInVuZGVmaW5lZCIsIlByb3BzIiwiY2hpbGRyZW4iLCJSZWFjdE5vZGUiLCJNYWlsYm94UHJvdmlkZXIiLCJ0MCIsIiQiLCJfYyIsInQxIiwiU3ltYm9sIiwiZm9yIiwibWFpbGJveCIsInQyIiwidXNlTWFpbGJveCIsIkVycm9yIl0sInNvdXJjZXMiOlsibWFpbGJveC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IFJlYWN0LCB7IGNyZWF0ZUNvbnRleHQsIHVzZUNvbnRleHQsIHVzZU1lbW8gfSBmcm9tICdyZWFjdCdcbmltcG9ydCB7IE1haWxib3ggfSBmcm9tICcuLi91dGlscy9tYWlsYm94LmpzJ1xuXG5jb25zdCBNYWlsYm94Q29udGV4dCA9IGNyZWF0ZUNvbnRleHQ8TWFpbGJveCB8IHVuZGVmaW5lZD4odW5kZWZpbmVkKVxuXG50eXBlIFByb3BzID0ge1xuICBjaGlsZHJlbjogUmVhY3QuUmVhY3ROb2RlXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBNYWlsYm94UHJvdmlkZXIoeyBjaGlsZHJlbiB9OiBQcm9wcyk6IFJlYWN0LlJlYWN0Tm9kZSB7XG4gIGNvbnN0IG1haWxib3ggPSB1c2VNZW1vKCgpID0+IG5ldyBNYWlsYm94KCksIFtdKVxuICByZXR1cm4gKFxuICAgIDxNYWlsYm94Q29udGV4dC5Qcm92aWRlciB2YWx1ZT17bWFpbGJveH0+XG4gICAgICB7Y2hpbGRyZW59XG4gICAgPC9NYWlsYm94Q29udGV4dC5Qcm92aWRlcj5cbiAgKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdXNlTWFpbGJveCgpOiBNYWlsYm94IHtcbiAgY29uc3QgbWFpbGJveCA9IHVzZUNvbnRleHQoTWFpbGJveENvbnRleHQpXG4gIGlmICghbWFpbGJveCkge1xuICAgIHRocm93IG5ldyBFcnJvcigndXNlTWFpbGJveCBtdXN0IGJlIHVzZWQgd2l0aGluIGEgTWFpbGJveFByb3ZpZGVyJylcbiAgfVxuICByZXR1cm4gbWFpbGJveFxufVxuIl0sIm1hcHBpbmdzIjoiO0FBQUEsT0FBT0EsS0FBSyxJQUFJQyxhQUFhLEVBQUVDLFVBQVUsRUFBRUMsT0FBTyxRQUFRLE9BQU87QUFDakUsU0FBU0MsT0FBTyxRQUFRLHFCQUFxQjtBQUU3QyxNQUFNQyxjQUFjLEdBQUdKLGFBQWEsQ0FBQ0csT0FBTyxHQUFHLFNBQVMsQ0FBQyxDQUFDRSxTQUFTLENBQUM7QUFFcEUsS0FBS0MsS0FBSyxHQUFHO0VBQ1hDLFFBQVEsRUFBRVIsS0FBSyxDQUFDUyxTQUFTO0FBQzNCLENBQUM7QUFFRCxPQUFPLFNBQUFDLGdCQUFBQyxFQUFBO0VBQUEsTUFBQUMsQ0FBQSxHQUFBQyxFQUFBO0VBQXlCO0lBQUFMO0VBQUEsSUFBQUcsRUFBbUI7RUFBQSxJQUFBRyxFQUFBO0VBQUEsSUFBQUYsQ0FBQSxRQUFBRyxNQUFBLENBQUFDLEdBQUE7SUFDbkJGLEVBQUEsT0FBSVYsT0FBTyxDQUFDLENBQUM7SUFBQVEsQ0FBQSxNQUFBRSxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBRixDQUFBO0VBQUE7RUFBM0MsTUFBQUssT0FBQSxHQUE4QkgsRUFBYTtFQUFLLElBQUFJLEVBQUE7RUFBQSxJQUFBTixDQUFBLFFBQUFKLFFBQUE7SUFFOUNVLEVBQUEsNEJBQWdDRCxLQUFPLENBQVBBLFFBQU0sQ0FBQyxDQUNwQ1QsU0FBTyxDQUNWLDBCQUEwQjtJQUFBSSxDQUFBLE1BQUFKLFFBQUE7SUFBQUksQ0FBQSxNQUFBTSxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBTixDQUFBO0VBQUE7RUFBQSxPQUYxQk0sRUFFMEI7QUFBQTtBQUk5QixPQUFPLFNBQUFDLFdBQUE7RUFDTCxNQUFBRixPQUFBLEdBQWdCZixVQUFVLENBQUNHLGNBQWMsQ0FBQztFQUMxQyxJQUFJLENBQUNZLE9BQU87SUFDVixNQUFNLElBQUlHLEtBQUssQ0FBQyxrREFBa0QsQ0FBQztFQUFBO0VBQ3BFLE9BQ01ILE9BQU87QUFBQSIsImlnbm9yZUxpc3QiOltdfQ==
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { c as _c } from "react/compiler-runtime";
|
|
2
|
+
import { createContext, type RefObject, useContext } from 'react';
|
|
3
|
+
import type { ScrollBoxHandle } from '../ink/components/ScrollBox.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Set by FullscreenLayout when rendering content in its `modal` slot —
|
|
7
|
+
* the absolute-positioned bottom-anchored pane for slash-command dialogs.
|
|
8
|
+
* Consumers use this to:
|
|
9
|
+
*
|
|
10
|
+
* - Suppress top-level framing — `Pane` skips its full-terminal-width
|
|
11
|
+
* `Divider` (FullscreenLayout already draws the ▔ divider).
|
|
12
|
+
* - Size Select pagination to the available rows — the modal's inner
|
|
13
|
+
* area is smaller than the terminal (rows minus transcript peek minus
|
|
14
|
+
* divider), so components that cap their visible option count from
|
|
15
|
+
* `useTerminalSize().rows` would overflow without this context.
|
|
16
|
+
* - Reset scroll on tab switch — Tabs keys its ScrollBox by
|
|
17
|
+
* `selectedTabIndex`, remounting on tab switch so scrollTop resets to 0
|
|
18
|
+
* without scrollTo() timing games.
|
|
19
|
+
*
|
|
20
|
+
* null = not inside the modal slot.
|
|
21
|
+
*/
|
|
22
|
+
type ModalCtx = {
|
|
23
|
+
rows: number;
|
|
24
|
+
columns: number;
|
|
25
|
+
scrollRef: RefObject<ScrollBoxHandle | null> | null;
|
|
26
|
+
};
|
|
27
|
+
export const ModalContext = createContext<ModalCtx | null>(null);
|
|
28
|
+
export function useIsInsideModal() {
|
|
29
|
+
return useContext(ModalContext) !== null;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Available content rows/columns when inside a Modal, else falls back to
|
|
34
|
+
* the provided terminal size. Use instead of `useTerminalSize()` when a
|
|
35
|
+
* component caps its visible content height — the modal's inner area is
|
|
36
|
+
* smaller than the terminal.
|
|
37
|
+
*/
|
|
38
|
+
export function useModalOrTerminalSize(fallback) {
|
|
39
|
+
const $ = _c(3);
|
|
40
|
+
const ctx = useContext(ModalContext);
|
|
41
|
+
let t0;
|
|
42
|
+
if ($[0] !== ctx || $[1] !== fallback) {
|
|
43
|
+
t0 = ctx ? {
|
|
44
|
+
rows: ctx.rows,
|
|
45
|
+
columns: ctx.columns
|
|
46
|
+
} : fallback;
|
|
47
|
+
$[0] = ctx;
|
|
48
|
+
$[1] = fallback;
|
|
49
|
+
$[2] = t0;
|
|
50
|
+
} else {
|
|
51
|
+
t0 = $[2];
|
|
52
|
+
}
|
|
53
|
+
return t0;
|
|
54
|
+
}
|
|
55
|
+
export function useModalScrollRef() {
|
|
56
|
+
return useContext(ModalContext)?.scrollRef ?? null;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJjcmVhdGVDb250ZXh0IiwiUmVmT2JqZWN0IiwidXNlQ29udGV4dCIsIlNjcm9sbEJveEhhbmRsZSIsIk1vZGFsQ3R4Iiwicm93cyIsImNvbHVtbnMiLCJzY3JvbGxSZWYiLCJNb2RhbENvbnRleHQiLCJ1c2VJc0luc2lkZU1vZGFsIiwidXNlTW9kYWxPclRlcm1pbmFsU2l6ZSIsImZhbGxiYWNrIiwiJCIsIl9jIiwiY3R4IiwidDAiLCJ1c2VNb2RhbFNjcm9sbFJlZiJdLCJzb3VyY2VzIjpbIm1vZGFsQ29udGV4dC50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY3JlYXRlQ29udGV4dCwgdHlwZSBSZWZPYmplY3QsIHVzZUNvbnRleHQgfSBmcm9tICdyZWFjdCdcbmltcG9ydCB0eXBlIHsgU2Nyb2xsQm94SGFuZGxlIH0gZnJvbSAnLi4vaW5rL2NvbXBvbmVudHMvU2Nyb2xsQm94LmpzJ1xuXG4vKipcbiAqIFNldCBieSBGdWxsc2NyZWVuTGF5b3V0IHdoZW4gcmVuZGVyaW5nIGNvbnRlbnQgaW4gaXRzIGBtb2RhbGAgc2xvdCDigJRcbiAqIHRoZSBhYnNvbHV0ZS1wb3NpdGlvbmVkIGJvdHRvbS1hbmNob3JlZCBwYW5lIGZvciBzbGFzaC1jb21tYW5kIGRpYWxvZ3MuXG4gKiBDb25zdW1lcnMgdXNlIHRoaXMgdG86XG4gKlxuICogLSBTdXBwcmVzcyB0b3AtbGV2ZWwgZnJhbWluZyDigJQgYFBhbmVgIHNraXBzIGl0cyBmdWxsLXRlcm1pbmFsLXdpZHRoXG4gKiAgIGBEaXZpZGVyYCAoRnVsbHNjcmVlbkxheW91dCBhbHJlYWR5IGRyYXdzIHRoZSDilpQgZGl2aWRlcikuXG4gKiAtIFNpemUgU2VsZWN0IHBhZ2luYXRpb24gdG8gdGhlIGF2YWlsYWJsZSByb3dzIOKAlCB0aGUgbW9kYWwncyBpbm5lclxuICogICBhcmVhIGlzIHNtYWxsZXIgdGhhbiB0aGUgdGVybWluYWwgKHJvd3MgbWludXMgdHJhbnNjcmlwdCBwZWVrIG1pbnVzXG4gKiAgIGRpdmlkZXIpLCBzbyBjb21wb25lbnRzIHRoYXQgY2FwIHRoZWlyIHZpc2libGUgb3B0aW9uIGNvdW50IGZyb21cbiAqICAgYHVzZVRlcm1pbmFsU2l6ZSgpLnJvd3NgIHdvdWxkIG92ZXJmbG93IHdpdGhvdXQgdGhpcyBjb250ZXh0LlxuICogLSBSZXNldCBzY3JvbGwgb24gdGFiIHN3aXRjaCDigJQgVGFicyBrZXlzIGl0cyBTY3JvbGxCb3ggYnlcbiAqICAgYHNlbGVjdGVkVGFiSW5kZXhgLCByZW1vdW50aW5nIG9uIHRhYiBzd2l0Y2ggc28gc2Nyb2xsVG9wIHJlc2V0cyB0byAwXG4gKiAgIHdpdGhvdXQgc2Nyb2xsVG8oKSB0aW1pbmcgZ2FtZXMuXG4gKlxuICogbnVsbCA9IG5vdCBpbnNpZGUgdGhlIG1vZGFsIHNsb3QuXG4gKi9cbnR5cGUgTW9kYWxDdHggPSB7XG4gIHJvd3M6IG51bWJlclxuICBjb2x1bW5zOiBudW1iZXJcbiAgc2Nyb2xsUmVmOiBSZWZPYmplY3Q8U2Nyb2xsQm94SGFuZGxlIHwgbnVsbD4gfCBudWxsXG59XG5leHBvcnQgY29uc3QgTW9kYWxDb250ZXh0ID0gY3JlYXRlQ29udGV4dDxNb2RhbEN0eCB8IG51bGw+KG51bGwpXG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VJc0luc2lkZU1vZGFsKCk6IGJvb2xlYW4ge1xuICByZXR1cm4gdXNlQ29udGV4dChNb2RhbENvbnRleHQpICE9PSBudWxsXG59XG5cbi8qKlxuICogQXZhaWxhYmxlIGNvbnRlbnQgcm93cy9jb2x1bW5zIHdoZW4gaW5zaWRlIGEgTW9kYWwsIGVsc2UgZmFsbHMgYmFjayB0b1xuICogdGhlIHByb3ZpZGVkIHRlcm1pbmFsIHNpemUuIFVzZSBpbnN0ZWFkIG9mIGB1c2VUZXJtaW5hbFNpemUoKWAgd2hlbiBhXG4gKiBjb21wb25lbnQgY2FwcyBpdHMgdmlzaWJsZSBjb250ZW50IGhlaWdodCDigJQgdGhlIG1vZGFsJ3MgaW5uZXIgYXJlYSBpc1xuICogc21hbGxlciB0aGFuIHRoZSB0ZXJtaW5hbC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHVzZU1vZGFsT3JUZXJtaW5hbFNpemUoZmFsbGJhY2s6IHtcbiAgcm93czogbnVtYmVyXG4gIGNvbHVtbnM6IG51bWJlclxufSk6IHsgcm93czogbnVtYmVyOyBjb2x1bW5zOiBudW1iZXIgfSB7XG4gIGNvbnN0IGN0eCA9IHVzZUNvbnRleHQoTW9kYWxDb250ZXh0KVxuICByZXR1cm4gY3R4ID8geyByb3dzOiBjdHgucm93cywgY29sdW1uczogY3R4LmNvbHVtbnMgfSA6IGZhbGxiYWNrXG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VNb2RhbFNjcm9sbFJlZigpOiBSZWZPYmplY3Q8U2Nyb2xsQm94SGFuZGxlIHwgbnVsbD4gfCBudWxsIHtcbiAgcmV0dXJuIHVzZUNvbnRleHQoTW9kYWxDb250ZXh0KT8uc2Nyb2xsUmVmID8/IG51bGxcbn1cbiJdLCJtYXBwaW5ncyI6IjtBQUFBLFNBQVNBLGFBQWEsRUFBRSxLQUFLQyxTQUFTLEVBQUVDLFVBQVUsUUFBUSxPQUFPO0FBQ2pFLGNBQWNDLGVBQWUsUUFBUSxnQ0FBZ0M7O0FBRXJFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLQyxRQUFRLEdBQUc7RUFDZEMsSUFBSSxFQUFFLE1BQU07RUFDWkMsT0FBTyxFQUFFLE1BQU07RUFDZkMsU0FBUyxFQUFFTixTQUFTLENBQUNFLGVBQWUsR0FBRyxJQUFJLENBQUMsR0FBRyxJQUFJO0FBQ3JELENBQUM7QUFDRCxPQUFPLE1BQU1LLFlBQVksR0FBR1IsYUFBYSxDQUFDSSxRQUFRLEdBQUcsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDO0FBRWhFLE9BQU8sU0FBQUssaUJBQUE7RUFBQSxPQUNFUCxVQUFVLENBQUNNLFlBQVksQ0FBQyxLQUFLLElBQUk7QUFBQTs7QUFHMUM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTyxTQUFBRSx1QkFBQUMsUUFBQTtFQUFBLE1BQUFDLENBQUEsR0FBQUMsRUFBQTtFQUlMLE1BQUFDLEdBQUEsR0FBWVosVUFBVSxDQUFDTSxZQUFZLENBQUM7RUFBQSxJQUFBTyxFQUFBO0VBQUEsSUFBQUgsQ0FBQSxRQUFBRSxHQUFBLElBQUFGLENBQUEsUUFBQUQsUUFBQTtJQUM3QkksRUFBQSxHQUFBRCxHQUFHLEdBQUg7TUFBQVQsSUFBQSxFQUFjUyxHQUFHLENBQUFULElBQUs7TUFBQUMsT0FBQSxFQUFXUSxHQUFHLENBQUFSO0lBQW9CLENBQUMsR0FBekRLLFFBQXlEO0lBQUFDLENBQUEsTUFBQUUsR0FBQTtJQUFBRixDQUFBLE1BQUFELFFBQUE7SUFBQUMsQ0FBQSxNQUFBRyxFQUFBO0VBQUE7SUFBQUEsRUFBQSxHQUFBSCxDQUFBO0VBQUE7RUFBQSxPQUF6REcsRUFBeUQ7QUFBQTtBQUdsRSxPQUFPLFNBQUFDLGtCQUFBO0VBQUEsT0FDRWQsVUFBVSxDQUFDTSxZQUF1QixDQUFDLEVBQUFELFNBQVEsSUFBM0MsSUFBMkM7QUFBQSIsImlnbm9yZUxpc3QiOltdfQ==
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
import type * as React from 'react';
|
|
2
|
+
import { useCallback, useEffect } from 'react';
|
|
3
|
+
import { useAppStateStore, useSetAppState } from 'src/state/AppState.js';
|
|
4
|
+
import type { Theme } from '../utils/theme.js';
|
|
5
|
+
type Priority = 'low' | 'medium' | 'high' | 'immediate';
|
|
6
|
+
type BaseNotification = {
|
|
7
|
+
key: string;
|
|
8
|
+
/**
|
|
9
|
+
* Keys of notifications that this notification invalidates.
|
|
10
|
+
* If a notification is invalidated, it will be removed from the queue
|
|
11
|
+
* and, if currently displayed, cleared immediately.
|
|
12
|
+
*/
|
|
13
|
+
invalidates?: string[];
|
|
14
|
+
priority: Priority;
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Combine notifications with the same key, like Array.reduce().
|
|
18
|
+
* Called as fold(accumulator, incoming) when a notification with a matching
|
|
19
|
+
* key already exists in the queue or is currently displayed.
|
|
20
|
+
* Returns the merged notification (should carry fold forward for future merges).
|
|
21
|
+
*/
|
|
22
|
+
fold?: (accumulator: Notification, incoming: Notification) => Notification;
|
|
23
|
+
};
|
|
24
|
+
type TextNotification = BaseNotification & {
|
|
25
|
+
text: string;
|
|
26
|
+
color?: keyof Theme;
|
|
27
|
+
};
|
|
28
|
+
type JSXNotification = BaseNotification & {
|
|
29
|
+
jsx: React.ReactNode;
|
|
30
|
+
};
|
|
31
|
+
type AddNotificationFn = (content: Notification) => void;
|
|
32
|
+
type RemoveNotificationFn = (key: string) => void;
|
|
33
|
+
export type Notification = TextNotification | JSXNotification;
|
|
34
|
+
const DEFAULT_TIMEOUT_MS = 8000;
|
|
35
|
+
|
|
36
|
+
// Track current timeout to clear it when immediate notifications arrive
|
|
37
|
+
let currentTimeoutId: NodeJS.Timeout | null = null;
|
|
38
|
+
export function useNotifications(): {
|
|
39
|
+
addNotification: AddNotificationFn;
|
|
40
|
+
removeNotification: RemoveNotificationFn;
|
|
41
|
+
} {
|
|
42
|
+
const store = useAppStateStore();
|
|
43
|
+
const setAppState = useSetAppState();
|
|
44
|
+
|
|
45
|
+
// Process queue when current notification finishes or queue changes
|
|
46
|
+
const processQueue = useCallback(() => {
|
|
47
|
+
setAppState(prev => {
|
|
48
|
+
const next = getNext(prev.notifications.queue);
|
|
49
|
+
if (prev.notifications.current !== null || !next) {
|
|
50
|
+
return prev;
|
|
51
|
+
}
|
|
52
|
+
currentTimeoutId = setTimeout((setAppState, nextKey, processQueue) => {
|
|
53
|
+
currentTimeoutId = null;
|
|
54
|
+
setAppState(prev => {
|
|
55
|
+
// Compare by key instead of reference to handle re-created notifications
|
|
56
|
+
if (prev.notifications.current?.key !== nextKey) {
|
|
57
|
+
return prev;
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
...prev,
|
|
61
|
+
notifications: {
|
|
62
|
+
queue: prev.notifications.queue,
|
|
63
|
+
current: null
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
});
|
|
67
|
+
processQueue();
|
|
68
|
+
}, next.timeoutMs ?? DEFAULT_TIMEOUT_MS, setAppState, next.key, processQueue);
|
|
69
|
+
return {
|
|
70
|
+
...prev,
|
|
71
|
+
notifications: {
|
|
72
|
+
queue: prev.notifications.queue.filter(_ => _ !== next),
|
|
73
|
+
current: next
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
});
|
|
77
|
+
}, [setAppState]);
|
|
78
|
+
const addNotification = useCallback<AddNotificationFn>((notif: Notification) => {
|
|
79
|
+
// Handle immediate priority notifications
|
|
80
|
+
if (notif.priority === 'immediate') {
|
|
81
|
+
// Clear any existing timeout since we're showing a new immediate notification
|
|
82
|
+
if (currentTimeoutId) {
|
|
83
|
+
clearTimeout(currentTimeoutId);
|
|
84
|
+
currentTimeoutId = null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Set up timeout for the immediate notification
|
|
88
|
+
currentTimeoutId = setTimeout((setAppState, notif, processQueue) => {
|
|
89
|
+
currentTimeoutId = null;
|
|
90
|
+
setAppState(prev => {
|
|
91
|
+
// Compare by key instead of reference to handle re-created notifications
|
|
92
|
+
if (prev.notifications.current?.key !== notif.key) {
|
|
93
|
+
return prev;
|
|
94
|
+
}
|
|
95
|
+
return {
|
|
96
|
+
...prev,
|
|
97
|
+
notifications: {
|
|
98
|
+
queue: prev.notifications.queue.filter(_ => !notif.invalidates?.includes(_.key)),
|
|
99
|
+
current: null
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
});
|
|
103
|
+
processQueue();
|
|
104
|
+
}, notif.timeoutMs ?? DEFAULT_TIMEOUT_MS, setAppState, notif, processQueue);
|
|
105
|
+
|
|
106
|
+
// Show the immediate notification right away
|
|
107
|
+
setAppState(prev => ({
|
|
108
|
+
...prev,
|
|
109
|
+
notifications: {
|
|
110
|
+
current: notif,
|
|
111
|
+
queue:
|
|
112
|
+
// Only re-queue the current notification if it's not immediate
|
|
113
|
+
[...(prev.notifications.current ? [prev.notifications.current] : []), ...prev.notifications.queue].filter(_ => _.priority !== 'immediate' && !notif.invalidates?.includes(_.key))
|
|
114
|
+
}
|
|
115
|
+
}));
|
|
116
|
+
return; // IMPORTANT: Exit addNotification for immediate notifications
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Handle non-immediate notifications
|
|
120
|
+
setAppState(prev => {
|
|
121
|
+
// Check if we can fold into an existing notification with the same key
|
|
122
|
+
if (notif.fold) {
|
|
123
|
+
// Fold into current notification if keys match
|
|
124
|
+
if (prev.notifications.current?.key === notif.key) {
|
|
125
|
+
const folded = notif.fold(prev.notifications.current, notif);
|
|
126
|
+
// Reset timeout for the folded notification
|
|
127
|
+
if (currentTimeoutId) {
|
|
128
|
+
clearTimeout(currentTimeoutId);
|
|
129
|
+
currentTimeoutId = null;
|
|
130
|
+
}
|
|
131
|
+
currentTimeoutId = setTimeout((setAppState, foldedKey, processQueue) => {
|
|
132
|
+
currentTimeoutId = null;
|
|
133
|
+
setAppState(p => {
|
|
134
|
+
if (p.notifications.current?.key !== foldedKey) {
|
|
135
|
+
return p;
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
...p,
|
|
139
|
+
notifications: {
|
|
140
|
+
queue: p.notifications.queue,
|
|
141
|
+
current: null
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
});
|
|
145
|
+
processQueue();
|
|
146
|
+
}, folded.timeoutMs ?? DEFAULT_TIMEOUT_MS, setAppState, folded.key, processQueue);
|
|
147
|
+
return {
|
|
148
|
+
...prev,
|
|
149
|
+
notifications: {
|
|
150
|
+
current: folded,
|
|
151
|
+
queue: prev.notifications.queue
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// Fold into queued notification if keys match
|
|
157
|
+
const queueIdx = prev.notifications.queue.findIndex(_ => _.key === notif.key);
|
|
158
|
+
if (queueIdx !== -1) {
|
|
159
|
+
const folded = notif.fold(prev.notifications.queue[queueIdx]!, notif);
|
|
160
|
+
const newQueue = [...prev.notifications.queue];
|
|
161
|
+
newQueue[queueIdx] = folded;
|
|
162
|
+
return {
|
|
163
|
+
...prev,
|
|
164
|
+
notifications: {
|
|
165
|
+
current: prev.notifications.current,
|
|
166
|
+
queue: newQueue
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Only add to queue if not already present (prevent duplicates)
|
|
173
|
+
const queuedKeys = new Set(prev.notifications.queue.map(_ => _.key));
|
|
174
|
+
const shouldAdd = !queuedKeys.has(notif.key) && prev.notifications.current?.key !== notif.key;
|
|
175
|
+
if (!shouldAdd) return prev;
|
|
176
|
+
const invalidatesCurrent = prev.notifications.current !== null && notif.invalidates?.includes(prev.notifications.current.key);
|
|
177
|
+
if (invalidatesCurrent && currentTimeoutId) {
|
|
178
|
+
clearTimeout(currentTimeoutId);
|
|
179
|
+
currentTimeoutId = null;
|
|
180
|
+
}
|
|
181
|
+
return {
|
|
182
|
+
...prev,
|
|
183
|
+
notifications: {
|
|
184
|
+
current: invalidatesCurrent ? null : prev.notifications.current,
|
|
185
|
+
queue: [...prev.notifications.queue.filter(_ => _.priority !== 'immediate' && !notif.invalidates?.includes(_.key)), notif]
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
// Process queue after adding the notification
|
|
191
|
+
processQueue();
|
|
192
|
+
}, [setAppState, processQueue]);
|
|
193
|
+
const removeNotification = useCallback<RemoveNotificationFn>((key: string) => {
|
|
194
|
+
setAppState(prev => {
|
|
195
|
+
const isCurrent = prev.notifications.current?.key === key;
|
|
196
|
+
const inQueue = prev.notifications.queue.some(n => n.key === key);
|
|
197
|
+
if (!isCurrent && !inQueue) {
|
|
198
|
+
return prev;
|
|
199
|
+
}
|
|
200
|
+
if (isCurrent && currentTimeoutId) {
|
|
201
|
+
clearTimeout(currentTimeoutId);
|
|
202
|
+
currentTimeoutId = null;
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
...prev,
|
|
206
|
+
notifications: {
|
|
207
|
+
current: isCurrent ? null : prev.notifications.current,
|
|
208
|
+
queue: prev.notifications.queue.filter(n => n.key !== key)
|
|
209
|
+
}
|
|
210
|
+
};
|
|
211
|
+
});
|
|
212
|
+
processQueue();
|
|
213
|
+
}, [setAppState, processQueue]);
|
|
214
|
+
|
|
215
|
+
// Process queue on mount if there are notifications in the initial state.
|
|
216
|
+
// Imperative read (not useAppState) — a subscription in a mount-only
|
|
217
|
+
// effect would be vestigial and make every caller re-render on queue changes.
|
|
218
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
219
|
+
// biome-ignore lint/correctness/useExhaustiveDependencies: mount-only effect, store is a stable context ref
|
|
220
|
+
useEffect(() => {
|
|
221
|
+
if (store.getState().notifications.queue.length > 0) {
|
|
222
|
+
processQueue();
|
|
223
|
+
}
|
|
224
|
+
}, []);
|
|
225
|
+
return {
|
|
226
|
+
addNotification,
|
|
227
|
+
removeNotification
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
const PRIORITIES: Record<Priority, number> = {
|
|
231
|
+
immediate: 0,
|
|
232
|
+
high: 1,
|
|
233
|
+
medium: 2,
|
|
234
|
+
low: 3
|
|
235
|
+
};
|
|
236
|
+
export function getNext(queue: Notification[]): Notification | undefined {
|
|
237
|
+
if (queue.length === 0) return undefined;
|
|
238
|
+
return queue.reduce((min, n) => PRIORITIES[n.priority] < PRIORITIES[min.priority] ? n : min);
|
|
239
|
+
}
|
|
240
|
+
//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJuYW1lcyI6WyJSZWFjdCIsInVzZUNhbGxiYWNrIiwidXNlRWZmZWN0IiwidXNlQXBwU3RhdGVTdG9yZSIsInVzZVNldEFwcFN0YXRlIiwiVGhlbWUiLCJQcmlvcml0eSIsIkJhc2VOb3RpZmljYXRpb24iLCJrZXkiLCJpbnZhbGlkYXRlcyIsInByaW9yaXR5IiwidGltZW91dE1zIiwiZm9sZCIsImFjY3VtdWxhdG9yIiwiTm90aWZpY2F0aW9uIiwiaW5jb21pbmciLCJUZXh0Tm90aWZpY2F0aW9uIiwidGV4dCIsImNvbG9yIiwiSlNYTm90aWZpY2F0aW9uIiwianN4IiwiUmVhY3ROb2RlIiwiQWRkTm90aWZpY2F0aW9uRm4iLCJjb250ZW50IiwiUmVtb3ZlTm90aWZpY2F0aW9uRm4iLCJERUZBVUxUX1RJTUVPVVRfTVMiLCJjdXJyZW50VGltZW91dElkIiwiTm9kZUpTIiwiVGltZW91dCIsInVzZU5vdGlmaWNhdGlvbnMiLCJhZGROb3RpZmljYXRpb24iLCJyZW1vdmVOb3RpZmljYXRpb24iLCJzdG9yZSIsInNldEFwcFN0YXRlIiwicHJvY2Vzc1F1ZXVlIiwicHJldiIsIm5leHQiLCJnZXROZXh0Iiwibm90aWZpY2F0aW9ucyIsInF1ZXVlIiwiY3VycmVudCIsInNldFRpbWVvdXQiLCJuZXh0S2V5IiwiZmlsdGVyIiwiXyIsIm5vdGlmIiwiY2xlYXJUaW1lb3V0IiwiaW5jbHVkZXMiLCJmb2xkZWQiLCJmb2xkZWRLZXkiLCJwIiwicXVldWVJZHgiLCJmaW5kSW5kZXgiLCJuZXdRdWV1ZSIsInF1ZXVlZEtleXMiLCJTZXQiLCJtYXAiLCJzaG91bGRBZGQiLCJoYXMiLCJpbnZhbGlkYXRlc0N1cnJlbnQiLCJpc0N1cnJlbnQiLCJpblF1ZXVlIiwic29tZSIsIm4iLCJnZXRTdGF0ZSIsImxlbmd0aCIsIlBSSU9SSVRJRVMiLCJSZWNvcmQiLCJpbW1lZGlhdGUiLCJoaWdoIiwibWVkaXVtIiwibG93IiwidW5kZWZpbmVkIiwicmVkdWNlIiwibWluIl0sInNvdXJjZXMiOlsibm90aWZpY2F0aW9ucy50c3giXSwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgKiBhcyBSZWFjdCBmcm9tICdyZWFjdCdcbmltcG9ydCB7IHVzZUNhbGxiYWNrLCB1c2VFZmZlY3QgfSBmcm9tICdyZWFjdCdcbmltcG9ydCB7IHVzZUFwcFN0YXRlU3RvcmUsIHVzZVNldEFwcFN0YXRlIH0gZnJvbSAnc3JjL3N0YXRlL0FwcFN0YXRlLmpzJ1xuaW1wb3J0IHR5cGUgeyBUaGVtZSB9IGZyb20gJy4uL3V0aWxzL3RoZW1lLmpzJ1xuXG50eXBlIFByaW9yaXR5ID0gJ2xvdycgfCAnbWVkaXVtJyB8ICdoaWdoJyB8ICdpbW1lZGlhdGUnXG5cbnR5cGUgQmFzZU5vdGlmaWNhdGlvbiA9IHtcbiAga2V5OiBzdHJpbmdcbiAgLyoqXG4gICAqIEtleXMgb2Ygbm90aWZpY2F0aW9ucyB0aGF0IHRoaXMgbm90aWZpY2F0aW9uIGludmFsaWRhdGVzLlxuICAgKiBJZiBhIG5vdGlmaWNhdGlvbiBpcyBpbnZhbGlkYXRlZCwgaXQgd2lsbCBiZSByZW1vdmVkIGZyb20gdGhlIHF1ZXVlXG4gICAqIGFuZCwgaWYgY3VycmVudGx5IGRpc3BsYXllZCwgY2xlYXJlZCBpbW1lZGlhdGVseS5cbiAgICovXG4gIGludmFsaWRhdGVzPzogc3RyaW5nW11cbiAgcHJpb3JpdHk6IFByaW9yaXR5XG4gIHRpbWVvdXRNcz86IG51bWJlclxuICAvKipcbiAgICogQ29tYmluZSBub3RpZmljYXRpb25zIHdpdGggdGhlIHNhbWUga2V5LCBsaWtlIEFycmF5LnJlZHVjZSgpLlxuICAgKiBDYWxsZWQgYXMgZm9sZChhY2N1bXVsYXRvciwgaW5jb21pbmcpIHdoZW4gYSBub3RpZmljYXRpb24gd2l0aCBhIG1hdGNoaW5nXG4gICAqIGtleSBhbHJlYWR5IGV4aXN0cyBpbiB0aGUgcXVldWUgb3IgaXMgY3VycmVudGx5IGRpc3BsYXllZC5cbiAgICogUmV0dXJucyB0aGUgbWVyZ2VkIG5vdGlmaWNhdGlvbiAoc2hvdWxkIGNhcnJ5IGZvbGQgZm9yd2FyZCBmb3IgZnV0dXJlIG1lcmdlcykuXG4gICAqL1xuICBmb2xkPzogKGFjY3VtdWxhdG9yOiBOb3RpZmljYXRpb24sIGluY29taW5nOiBOb3RpZmljYXRpb24pID0+IE5vdGlmaWNhdGlvblxufVxuXG50eXBlIFRleHROb3RpZmljYXRpb24gPSBCYXNlTm90aWZpY2F0aW9uICYge1xuICB0ZXh0OiBzdHJpbmdcbiAgY29sb3I/OiBrZXlvZiBUaGVtZVxufVxuXG50eXBlIEpTWE5vdGlmaWNhdGlvbiA9IEJhc2VOb3RpZmljYXRpb24gJiB7XG4gIGpzeDogUmVhY3QuUmVhY3ROb2RlXG59XG5cbnR5cGUgQWRkTm90aWZpY2F0aW9uRm4gPSAoY29udGVudDogTm90aWZpY2F0aW9uKSA9PiB2b2lkXG50eXBlIFJlbW92ZU5vdGlmaWNhdGlvbkZuID0gKGtleTogc3RyaW5nKSA9PiB2b2lkXG5cbmV4cG9ydCB0eXBlIE5vdGlmaWNhdGlvbiA9IFRleHROb3RpZmljYXRpb24gfCBKU1hOb3RpZmljYXRpb25cblxuY29uc3QgREVGQVVMVF9USU1FT1VUX01TID0gODAwMFxuXG4vLyBUcmFjayBjdXJyZW50IHRpbWVvdXQgdG8gY2xlYXIgaXQgd2hlbiBpbW1lZGlhdGUgbm90aWZpY2F0aW9ucyBhcnJpdmVcbmxldCBjdXJyZW50VGltZW91dElkOiBOb2RlSlMuVGltZW91dCB8IG51bGwgPSBudWxsXG5cbmV4cG9ydCBmdW5jdGlvbiB1c2VOb3RpZmljYXRpb25zKCk6IHtcbiAgYWRkTm90aWZpY2F0aW9uOiBBZGROb3RpZmljYXRpb25GblxuICByZW1vdmVOb3RpZmljYXRpb246IFJlbW92ZU5vdGlmaWNhdGlvbkZuXG59IHtcbiAgY29uc3Qgc3RvcmUgPSB1c2VBcHBTdGF0ZVN0b3JlKClcbiAgY29uc3Qgc2V0QXBwU3RhdGUgPSB1c2VTZXRBcHBTdGF0ZSgpXG5cbiAgLy8gUHJvY2VzcyBxdWV1ZSB3aGVuIGN1cnJlbnQgbm90aWZpY2F0aW9uIGZpbmlzaGVzIG9yIHF1ZXVlIGNoYW5nZXNcbiAgY29uc3QgcHJvY2Vzc1F1ZXVlID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIHNldEFwcFN0YXRlKHByZXYgPT4ge1xuICAgICAgY29uc3QgbmV4dCA9IGdldE5leHQocHJldi5ub3RpZmljYXRpb25zLnF1ZXVlKVxuICAgICAgaWYgKHByZXYubm90aWZpY2F0aW9ucy5jdXJyZW50ICE9PSBudWxsIHx8ICFuZXh0KSB7XG4gICAgICAgIHJldHVybiBwcmV2XG4gICAgICB9XG5cbiAgICAgIGN1cnJlbnRUaW1lb3V0SWQgPSBzZXRUaW1lb3V0KFxuICAgICAgICAoc2V0QXBwU3RhdGUsIG5leHRLZXksIHByb2Nlc3NRdWV1ZSkgPT4ge1xuICAgICAgICAgIGN1cnJlbnRUaW1lb3V0SWQgPSBudWxsXG4gICAgICAgICAgc2V0QXBwU3RhdGUocHJldiA9PiB7XG4gICAgICAgICAgICAvLyBDb21wYXJlIGJ5IGtleSBpbnN0ZWFkIG9mIHJlZmVyZW5jZSB0byBoYW5kbGUgcmUtY3JlYXRlZCBub3RpZmljYXRpb25zXG4gICAgICAgICAgICBpZiAocHJldi5ub3RpZmljYXRpb25zLmN1cnJlbnQ/LmtleSAhPT0gbmV4dEtleSkge1xuICAgICAgICAgICAgICByZXR1cm4gcHJldlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgLi4ucHJldixcbiAgICAgICAgICAgICAgbm90aWZpY2F0aW9uczoge1xuICAgICAgICAgICAgICAgIHF1ZXVlOiBwcmV2Lm5vdGlmaWNhdGlvbnMucXVldWUsXG4gICAgICAgICAgICAgICAgY3VycmVudDogbnVsbCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9KVxuICAgICAgICAgIHByb2Nlc3NRdWV1ZSgpXG4gICAgICAgIH0sXG4gICAgICAgIG5leHQudGltZW91dE1zID8/IERFRkFVTFRfVElNRU9VVF9NUyxcbiAgICAgICAgc2V0QXBwU3RhdGUsXG4gICAgICAgIG5leHQua2V5LFxuICAgICAgICBwcm9jZXNzUXVldWUsXG4gICAgICApXG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnByZXYsXG4gICAgICAgIG5vdGlmaWNhdGlvbnM6IHtcbiAgICAgICAgICBxdWV1ZTogcHJldi5ub3RpZmljYXRpb25zLnF1ZXVlLmZpbHRlcihfID0+IF8gIT09IG5leHQpLFxuICAgICAgICAgIGN1cnJlbnQ6IG5leHQsXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgfSlcbiAgfSwgW3NldEFwcFN0YXRlXSlcblxuICBjb25zdCBhZGROb3RpZmljYXRpb24gPSB1c2VDYWxsYmFjazxBZGROb3RpZmljYXRpb25Gbj4oXG4gICAgKG5vdGlmOiBOb3RpZmljYXRpb24pID0+IHtcbiAgICAgIC8vIEhhbmRsZSBpbW1lZGlhdGUgcHJpb3JpdHkgbm90aWZpY2F0aW9uc1xuICAgICAgaWYgKG5vdGlmLnByaW9yaXR5ID09PSAnaW1tZWRpYXRlJykge1xuICAgICAgICAvLyBDbGVhciBhbnkgZXhpc3RpbmcgdGltZW91dCBzaW5jZSB3ZSdyZSBzaG93aW5nIGEgbmV3IGltbWVkaWF0ZSBub3RpZmljYXRpb25cbiAgICAgICAgaWYgKGN1cnJlbnRUaW1lb3V0SWQpIHtcbiAgICAgICAgICBjbGVhclRpbWVvdXQoY3VycmVudFRpbWVvdXRJZClcbiAgICAgICAgICBjdXJyZW50VGltZW91dElkID0gbnVsbFxuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2V0IHVwIHRpbWVvdXQgZm9yIHRoZSBpbW1lZGlhdGUgbm90aWZpY2F0aW9uXG4gICAgICAgIGN1cnJlbnRUaW1lb3V0SWQgPSBzZXRUaW1lb3V0KFxuICAgICAgICAgIChzZXRBcHBTdGF0ZSwgbm90aWYsIHByb2Nlc3NRdWV1ZSkgPT4ge1xuICAgICAgICAgICAgY3VycmVudFRpbWVvdXRJZCA9IG51bGxcbiAgICAgICAgICAgIHNldEFwcFN0YXRlKHByZXYgPT4ge1xuICAgICAgICAgICAgICAvLyBDb21wYXJlIGJ5IGtleSBpbnN0ZWFkIG9mIHJlZmVyZW5jZSB0byBoYW5kbGUgcmUtY3JlYXRlZCBub3RpZmljYXRpb25zXG4gICAgICAgICAgICAgIGlmIChwcmV2Lm5vdGlmaWNhdGlvbnMuY3VycmVudD8ua2V5ICE9PSBub3RpZi5rZXkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gcHJldlxuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgICAgLi4ucHJldixcbiAgICAgICAgICAgICAgICBub3RpZmljYXRpb25zOiB7XG4gICAgICAgICAgICAgICAgICBxdWV1ZTogcHJldi5ub3RpZmljYXRpb25zLnF1ZXVlLmZpbHRlcihcbiAgICAgICAgICAgICAgICAgICAgXyA9PiAhbm90aWYuaW52YWxpZGF0ZXM/LmluY2x1ZGVzKF8ua2V5KSxcbiAgICAgICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgICAgICBjdXJyZW50OiBudWxsLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICBwcm9jZXNzUXVldWUoKVxuICAgICAgICAgIH0sXG4gICAgICAgICAgbm90aWYudGltZW91dE1zID8/IERFRkFVTFRfVElNRU9VVF9NUyxcbiAgICAgICAgICBzZXRBcHBTdGF0ZSxcbiAgICAgICAgICBub3RpZixcbiAgICAgICAgICBwcm9jZXNzUXVldWUsXG4gICAgICAgIClcblxuICAgICAgICAvLyBTaG93IHRoZSBpbW1lZGlhdGUgbm90aWZpY2F0aW9uIHJpZ2h0IGF3YXlcbiAgICAgICAgc2V0QXBwU3RhdGUocHJldiA9PiAoe1xuICAgICAgICAgIC4uLnByZXYsXG4gICAgICAgICAgbm90aWZpY2F0aW9uczoge1xuICAgICAgICAgICAgY3VycmVudDogbm90aWYsXG4gICAgICAgICAgICBxdWV1ZTpcbiAgICAgICAgICAgICAgLy8gT25seSByZS1xdWV1ZSB0aGUgY3VycmVudCBub3RpZmljYXRpb24gaWYgaXQncyBub3QgaW1tZWRpYXRlXG4gICAgICAgICAgICAgIFtcbiAgICAgICAgICAgICAgICAuLi4ocHJldi5ub3RpZmljYXRpb25zLmN1cnJlbnRcbiAgICAgICAgICAgICAgICAgID8gW3ByZXYubm90aWZpY2F0aW9ucy5jdXJyZW50XVxuICAgICAgICAgICAgICAgICAgOiBbXSksXG4gICAgICAgICAgICAgICAgLi4ucHJldi5ub3RpZmljYXRpb25zLnF1ZXVlLFxuICAgICAgICAgICAgICBdLmZpbHRlcihcbiAgICAgICAgICAgICAgICBfID0+XG4gICAgICAgICAgICAgICAgICBfLnByaW9yaXR5ICE9PSAnaW1tZWRpYXRlJyAmJlxuICAgICAgICAgICAgICAgICAgIW5vdGlmLmludmFsaWRhdGVzPy5pbmNsdWRlcyhfLmtleSksXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgfSxcbiAgICAgICAgfSkpXG4gICAgICAgIHJldHVybiAvLyBJTVBPUlRBTlQ6IEV4aXQgYWRkTm90aWZpY2F0aW9uIGZvciBpbW1lZGlhdGUgbm90aWZpY2F0aW9uc1xuICAgICAgfVxuXG4gICAgICAvLyBIYW5kbGUgbm9uLWltbWVkaWF0ZSBub3RpZmljYXRpb25zXG4gICAgICBzZXRBcHBTdGF0ZShwcmV2ID0+IHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgd2UgY2FuIGZvbGQgaW50byBhbiBleGlzdGluZyBub3RpZmljYXRpb24gd2l0aCB0aGUgc2FtZSBrZXlcbiAgICAgICAgaWYgKG5vdGlmLmZvbGQpIHtcbiAgICAgICAgICAvLyBGb2xkIGludG8gY3VycmVudCBub3RpZmljYXRpb24gaWYga2V5cyBtYXRjaFxuICAgICAgICAgIGlmIChwcmV2Lm5vdGlmaWNhdGlvbnMuY3VycmVudD8ua2V5ID09PSBub3RpZi5rZXkpIHtcbiAgICAgICAgICAgIGNvbnN0IGZvbGRlZCA9IG5vdGlmLmZvbGQocHJldi5ub3RpZmljYXRpb25zLmN1cnJlbnQsIG5vdGlmKVxuICAgICAgICAgICAgLy8gUmVzZXQgdGltZW91dCBmb3IgdGhlIGZvbGRlZCBub3RpZmljYXRpb25cbiAgICAgICAgICAgIGlmIChjdXJyZW50VGltZW91dElkKSB7XG4gICAgICAgICAgICAgIGNsZWFyVGltZW91dChjdXJyZW50VGltZW91dElkKVxuICAgICAgICAgICAgICBjdXJyZW50VGltZW91dElkID0gbnVsbFxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY3VycmVudFRpbWVvdXRJZCA9IHNldFRpbWVvdXQoXG4gICAgICAgICAgICAgIChzZXRBcHBTdGF0ZSwgZm9sZGVkS2V5LCBwcm9jZXNzUXVldWUpID0+IHtcbiAgICAgICAgICAgICAgICBjdXJyZW50VGltZW91dElkID0gbnVsbFxuICAgICAgICAgICAgICAgIHNldEFwcFN0YXRlKHAgPT4ge1xuICAgICAgICAgICAgICAgICAgaWYgKHAubm90aWZpY2F0aW9ucy5jdXJyZW50Py5rZXkgIT09IGZvbGRlZEtleSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcFxuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICAgICAgLi4ucCxcbiAgICAgICAgICAgICAgICAgICAgbm90aWZpY2F0aW9uczoge1xuICAgICAgICAgICAgICAgICAgICAgIHF1ZXVlOiBwLm5vdGlmaWNhdGlvbnMucXVldWUsXG4gICAgICAgICAgICAgICAgICAgICAgY3VycmVudDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9KVxuICAgICAgICAgICAgICAgIHByb2Nlc3NRdWV1ZSgpXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIGZvbGRlZC50aW1lb3V0TXMgPz8gREVGQVVMVF9USU1FT1VUX01TLFxuICAgICAgICAgICAgICBzZXRBcHBTdGF0ZSxcbiAgICAgICAgICAgICAgZm9sZGVkLmtleSxcbiAgICAgICAgICAgICAgcHJvY2Vzc1F1ZXVlLFxuICAgICAgICAgICAgKVxuXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAuLi5wcmV2LFxuICAgICAgICAgICAgICBub3RpZmljYXRpb25zOiB7XG4gICAgICAgICAgICAgICAgY3VycmVudDogZm9sZGVkLFxuICAgICAgICAgICAgICAgIHF1ZXVlOiBwcmV2Lm5vdGlmaWNhdGlvbnMucXVldWUsXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgLy8gRm9sZCBpbnRvIHF1ZXVlZCBub3RpZmljYXRpb24gaWYga2V5cyBtYXRjaFxuICAgICAgICAgIGNvbnN0IHF1ZXVlSWR4ID0gcHJldi5ub3RpZmljYXRpb25zLnF1ZXVlLmZpbmRJbmRleChcbiAgICAgICAgICAgIF8gPT4gXy5rZXkgPT09IG5vdGlmLmtleSxcbiAgICAgICAgICApXG4gICAgICAgICAgaWYgKHF1ZXVlSWR4ICE9PSAtMSkge1xuICAgICAgICAgICAgY29uc3QgZm9sZGVkID0gbm90aWYuZm9sZChcbiAgICAgICAgICAgICAgcHJldi5ub3RpZmljYXRpb25zLnF1ZXVlW3F1ZXVlSWR4XSEsXG4gICAgICAgICAgICAgIG5vdGlmLFxuICAgICAgICAgICAgKVxuICAgICAgICAgICAgY29uc3QgbmV3UXVldWUgPSBbLi4ucHJldi5ub3RpZmljYXRpb25zLnF1ZXVlXVxuICAgICAgICAgICAgbmV3UXVldWVbcXVldWVJZHhdID0gZm9sZGVkXG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAuLi5wcmV2LFxuICAgICAgICAgICAgICBub3RpZmljYXRpb25zOiB7XG4gICAgICAgICAgICAgICAgY3VycmVudDogcHJldi5ub3RpZmljYXRpb25zLmN1cnJlbnQsXG4gICAgICAgICAgICAgICAgcXVldWU6IG5ld1F1ZXVlLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE9ubHkgYWRkIHRvIHF1ZXVlIGlmIG5vdCBhbHJlYWR5IHByZXNlbnQgKHByZXZlbnQgZHVwbGljYXRlcylcbiAgICAgICAgY29uc3QgcXVldWVkS2V5cyA9IG5ldyBTZXQocHJldi5ub3RpZmljYXRpb25zLnF1ZXVlLm1hcChfID0+IF8ua2V5KSlcbiAgICAgICAgY29uc3Qgc2hvdWxkQWRkID1cbiAgICAgICAgICAhcXVldWVkS2V5cy5oYXMobm90aWYua2V5KSAmJlxuICAgICAgICAgIHByZXYubm90aWZpY2F0aW9ucy5jdXJyZW50Py5rZXkgIT09IG5vdGlmLmtleVxuXG4gICAgICAgIGlmICghc2hvdWxkQWRkKSByZXR1cm4gcHJldlxuXG4gICAgICAgIGNvbnN0IGludmFsaWRhdGVzQ3VycmVudCA9XG4gICAgICAgICAgcHJldi5ub3RpZmljYXRpb25zLmN1cnJlbnQgIT09IG51bGwgJiZcbiAgICAgICAgICBub3RpZi5pbnZhbGlkYXRlcz8uaW5jbHVkZXMocHJldi5ub3RpZmljYXRpb25zLmN1cnJlbnQua2V5KVxuXG4gICAgICAgIGlmIChpbnZhbGlkYXRlc0N1cnJlbnQgJiYgY3VycmVudFRpbWVvdXRJZCkge1xuICAgICAgICAgIGNsZWFyVGltZW91dChjdXJyZW50VGltZW91dElkKVxuICAgICAgICAgIGN1cnJlbnRUaW1lb3V0SWQgPSBudWxsXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLnByZXYsXG4gICAgICAgICAgbm90aWZpY2F0aW9uczoge1xuICAgICAgICAgICAgY3VycmVudDogaW52YWxpZGF0ZXNDdXJyZW50ID8gbnVsbCA6IHByZXYubm90aWZpY2F0aW9ucy5jdXJyZW50LFxuICAgICAgICAgICAgcXVldWU6IFtcbiAgICAgICAgICAgICAgLi4ucHJldi5ub3RpZmljYXRpb25zLnF1ZXVlLmZpbHRlcihcbiAgICAgICAgICAgICAgICBfID0+XG4gICAgICAgICAgICAgICAgICBfLnByaW9yaXR5ICE9PSAnaW1tZWRpYXRlJyAmJlxuICAgICAgICAgICAgICAgICAgIW5vdGlmLmludmFsaWRhdGVzPy5pbmNsdWRlcyhfLmtleSksXG4gICAgICAgICAgICAgICksXG4gICAgICAgICAgICAgIG5vdGlmLFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICB9LFxuICAgICAgICB9XG4gICAgICB9KVxuXG4gICAgICAvLyBQcm9jZXNzIHF1ZXVlIGFmdGVyIGFkZGluZyB0aGUgbm90aWZpY2F0aW9uXG4gICAgICBwcm9jZXNzUXVldWUoKVxuICAgIH0sXG4gICAgW3NldEFwcFN0YXRlLCBwcm9jZXNzUXVldWVdLFxuICApXG5cbiAgY29uc3QgcmVtb3ZlTm90aWZpY2F0aW9uID0gdXNlQ2FsbGJhY2s8UmVtb3ZlTm90aWZpY2F0aW9uRm4+KFxuICAgIChrZXk6IHN0cmluZykgPT4ge1xuICAgICAgc2V0QXBwU3RhdGUocHJldiA9PiB7XG4gICAgICAgIGNvbnN0IGlzQ3VycmVudCA9IHByZXYubm90aWZpY2F0aW9ucy5jdXJyZW50Py5rZXkgPT09IGtleVxuICAgICAgICBjb25zdCBpblF1ZXVlID0gcHJldi5ub3RpZmljYXRpb25zLnF1ZXVlLnNvbWUobiA9PiBuLmtleSA9PT0ga2V5KVxuXG4gICAgICAgIGlmICghaXNDdXJyZW50ICYmICFpblF1ZXVlKSB7XG4gICAgICAgICAgcmV0dXJuIHByZXZcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc0N1cnJlbnQgJiYgY3VycmVudFRpbWVvdXRJZCkge1xuICAgICAgICAgIGNsZWFyVGltZW91dChjdXJyZW50VGltZW91dElkKVxuICAgICAgICAgIGN1cnJlbnRUaW1lb3V0SWQgPSBudWxsXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIC4uLnByZXYsXG4gICAgICAgICAgbm90aWZpY2F0aW9uczoge1xuICAgICAgICAgICAgY3VycmVudDogaXNDdXJyZW50ID8gbnVsbCA6IHByZXYubm90aWZpY2F0aW9ucy5jdXJyZW50LFxuICAgICAgICAgICAgcXVldWU6IHByZXYubm90aWZpY2F0aW9ucy5xdWV1ZS5maWx0ZXIobiA9PiBuLmtleSAhPT0ga2V5KSxcbiAgICAgICAgICB9LFxuICAgICAgICB9XG4gICAgICB9KVxuXG4gICAgICBwcm9jZXNzUXVldWUoKVxuICAgIH0sXG4gICAgW3NldEFwcFN0YXRlLCBwcm9jZXNzUXVldWVdLFxuICApXG5cbiAgLy8gUHJvY2VzcyBxdWV1ZSBvbiBtb3VudCBpZiB0aGVyZSBhcmUgbm90aWZpY2F0aW9ucyBpbiB0aGUgaW5pdGlhbCBzdGF0ZS5cbiAgLy8gSW1wZXJhdGl2ZSByZWFkIChub3QgdXNlQXBwU3RhdGUpIOKAlCBhIHN1YnNjcmlwdGlvbiBpbiBhIG1vdW50LW9ubHlcbiAgLy8gZWZmZWN0IHdvdWxkIGJlIHZlc3RpZ2lhbCBhbmQgbWFrZSBldmVyeSBjYWxsZXIgcmUtcmVuZGVyIG9uIHF1ZXVlIGNoYW5nZXMuXG4gIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSByZWFjdC1ob29rcy9leGhhdXN0aXZlLWRlcHNcbiAgLy8gYmlvbWUtaWdub3JlIGxpbnQvY29ycmVjdG5lc3MvdXNlRXhoYXVzdGl2ZURlcGVuZGVuY2llczogbW91bnQtb25seSBlZmZlY3QsIHN0b3JlIGlzIGEgc3RhYmxlIGNvbnRleHQgcmVmXG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKHN0b3JlLmdldFN0YXRlKCkubm90aWZpY2F0aW9ucy5xdWV1ZS5sZW5ndGggPiAwKSB7XG4gICAgICBwcm9jZXNzUXVldWUoKVxuICAgIH1cbiAgfSwgW10pXG5cbiAgcmV0dXJuIHsgYWRkTm90aWZpY2F0aW9uLCByZW1vdmVOb3RpZmljYXRpb24gfVxufVxuXG5jb25zdCBQUklPUklUSUVTOiBSZWNvcmQ8UHJpb3JpdHksIG51bWJlcj4gPSB7XG4gIGltbWVkaWF0ZTogMCxcbiAgaGlnaDogMSxcbiAgbWVkaXVtOiAyLFxuICBsb3c6IDMsXG59XG5leHBvcnQgZnVuY3Rpb24gZ2V0TmV4dChxdWV1ZTogTm90aWZpY2F0aW9uW10pOiBOb3RpZmljYXRpb24gfCB1bmRlZmluZWQge1xuICBpZiAocXVldWUubGVuZ3RoID09PSAwKSByZXR1cm4gdW5kZWZpbmVkXG4gIHJldHVybiBxdWV1ZS5yZWR1Y2UoKG1pbiwgbikgPT5cbiAgICBQUklPUklUSUVTW24ucHJpb3JpdHldIDwgUFJJT1JJVElFU1ttaW4ucHJpb3JpdHldID8gbiA6IG1pbixcbiAgKVxufVxuIl0sIm1hcHBpbmdzIjoiQUFBQSxZQUFZLEtBQUtBLEtBQUssTUFBTSxPQUFPO0FBQ25DLFNBQVNDLFdBQVcsRUFBRUMsU0FBUyxRQUFRLE9BQU87QUFDOUMsU0FBU0MsZ0JBQWdCLEVBQUVDLGNBQWMsUUFBUSx1QkFBdUI7QUFDeEUsY0FBY0MsS0FBSyxRQUFRLG1CQUFtQjtBQUU5QyxLQUFLQyxRQUFRLEdBQUcsS0FBSyxHQUFHLFFBQVEsR0FBRyxNQUFNLEdBQUcsV0FBVztBQUV2RCxLQUFLQyxnQkFBZ0IsR0FBRztFQUN0QkMsR0FBRyxFQUFFLE1BQU07RUFDWDtBQUNGO0FBQ0E7QUFDQTtBQUNBO0VBQ0VDLFdBQVcsQ0FBQyxFQUFFLE1BQU0sRUFBRTtFQUN0QkMsUUFBUSxFQUFFSixRQUFRO0VBQ2xCSyxTQUFTLENBQUMsRUFBRSxNQUFNO0VBQ2xCO0FBQ0Y7QUFDQTtBQUNBO0FBQ0E7QUFDQTtFQUNFQyxJQUFJLENBQUMsRUFBRSxDQUFDQyxXQUFXLEVBQUVDLFlBQVksRUFBRUMsUUFBUSxFQUFFRCxZQUFZLEVBQUUsR0FBR0EsWUFBWTtBQUM1RSxDQUFDO0FBRUQsS0FBS0UsZ0JBQWdCLEdBQUdULGdCQUFnQixHQUFHO0VBQ3pDVSxJQUFJLEVBQUUsTUFBTTtFQUNaQyxLQUFLLENBQUMsRUFBRSxNQUFNYixLQUFLO0FBQ3JCLENBQUM7QUFFRCxLQUFLYyxlQUFlLEdBQUdaLGdCQUFnQixHQUFHO0VBQ3hDYSxHQUFHLEVBQUVwQixLQUFLLENBQUNxQixTQUFTO0FBQ3RCLENBQUM7QUFFRCxLQUFLQyxpQkFBaUIsR0FBRyxDQUFDQyxPQUFPLEVBQUVULFlBQVksRUFBRSxHQUFHLElB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
|