dsh-later 1.2.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/CHANGELOG.md +10 -0
- package/README.en.md +42 -3
- package/README.md +42 -3
- package/lib/client.js +565 -255
- package/lib/commands.js +486 -51
- package/lib/index.js +20 -2
- package/lib/ownership-store.js +50 -3
- package/lib/runtime.js +39 -5
- package/lib/smart-window.js +28 -3
- package/lib/types/commands.d.ts +60 -16
- package/lib/types/index.d.ts +2 -0
- package/lib/types/ownership-store.d.ts +30 -1
- package/lib/types/runtime.d.ts +10 -1
- package/lib/types/user-tools.d.ts +9 -1
- package/lib/user-tools.js +13 -4
- package/package.json +5 -4
package/lib/client.js
CHANGED
|
@@ -4,9 +4,11 @@ window.__ModuleLoader__.load({
|
|
|
4
4
|
var module = { exports: {} };
|
|
5
5
|
var exports = module.exports;
|
|
6
6
|
"use strict";
|
|
7
|
+
var __create = Object.create;
|
|
7
8
|
var __defProp = Object.defineProperty;
|
|
8
9
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
9
10
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
11
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
10
12
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
13
|
var __export = (target, all) => {
|
|
12
14
|
for (var name2 in all)
|
|
@@ -20,6 +22,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
20
22
|
}
|
|
21
23
|
return to;
|
|
22
24
|
};
|
|
25
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
26
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
27
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
28
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
29
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
30
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
31
|
+
mod
|
|
32
|
+
));
|
|
23
33
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
24
34
|
|
|
25
35
|
// src/client/index.tsx
|
|
@@ -78,25 +88,27 @@ var COMPONENTS = [
|
|
|
78
88
|
" margin: 0 auto calc(0px - var(--dsh-composer-stack-gap) - 3px);",
|
|
79
89
|
" padding: 0 var(--dsh-composer-dock-inset);",
|
|
80
90
|
"}",
|
|
81
|
-
"/* \u9762\u677F\u4E0E QueueDock .panel \u4E00\u81F4\uFF1Abg
|
|
91
|
+
"/* \u9762\u677F\u4E0E QueueDock .panel \u4E00\u81F4\uFF1Abg menu + backdrop-filter\u3001\u9876\u90E8\u5706\u89D2\u3001::before \u753B\u63CF\u8FB9\uFF08\u7559\u5E95\u8FB9\u5F00\u53E3\uFF09\u3002 */",
|
|
82
92
|
".ss-dock-body {",
|
|
83
93
|
" position: relative; overflow: hidden; width: 100%; padding: 2px 0;",
|
|
84
|
-
"
|
|
85
|
-
" border-radius:
|
|
94
|
+
" isolation: isolate;",
|
|
95
|
+
" border-radius: var(--dsw-radius-lg) var(--dsw-radius-lg) 0 0;",
|
|
86
96
|
" --dsh-scrollbar-thumb: var(--dsw-alias-scrollbar-bg-l2);",
|
|
87
97
|
" --dsh-scrollbar-thumb-hover: var(--dsw-alias-scrollbar-hover-l2);",
|
|
88
98
|
"}",
|
|
89
|
-
".ss-dock-body::
|
|
90
|
-
"
|
|
91
|
-
"
|
|
99
|
+
".ss-dock-body::before {",
|
|
100
|
+
" z-index: -1; border-radius: inherit; background: var(--dsw-specific-menu);",
|
|
101
|
+
" backdrop-filter: var(--dsw-menu-backdrop-filter); content: '';",
|
|
102
|
+
" position: absolute; inset: 0; pointer-events: none;",
|
|
103
|
+
" border: 1px solid var(--dsw-alias-border-l1); border-bottom: none;",
|
|
92
104
|
"}",
|
|
93
105
|
".ss-dock-header {",
|
|
94
106
|
" box-sizing: border-box; display: flex; align-items: center; gap: 10px;",
|
|
95
107
|
" width: 100%; height: 36px; padding: 4px 12px;",
|
|
96
|
-
" background: none; border: none; border-radius:
|
|
108
|
+
" background: none; border: none; border-radius: var(--dsw-radius-md); cursor: pointer; text-align: left;",
|
|
97
109
|
" color: var(--dsw-alias-label-primary);",
|
|
98
110
|
"}",
|
|
99
|
-
".ss-dock-header:focus-visible { outline:
|
|
111
|
+
".ss-dock-header:focus-visible { outline: var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); outline-offset: -2px; }",
|
|
100
112
|
".ss-dock-lead { display: grid; place-items: center; color: var(--dsw-alias-label-tertiary); flex: none; }",
|
|
101
113
|
".ss-dock-count {",
|
|
102
114
|
" flex: auto; min-width: 0;",
|
|
@@ -189,13 +201,30 @@ var COMPONENTS = [
|
|
|
189
201
|
" background-repeat: no-repeat;",
|
|
190
202
|
"}",
|
|
191
203
|
".ss-dock-actions { display: flex; align-items: center; gap: 10px; flex: none; }",
|
|
204
|
+
"/* DockTip\uFF1A\u9010\u5B57\u5BF9\u9F50\u5B98\u65B9 Tooltip.module.css .bubble\uFF08portal: true \u5C42\uFF09\u3002 */",
|
|
205
|
+
".ss-dock-tip-anchor { display: inline-grid; flex: none; }",
|
|
206
|
+
".ss-dock-tip {",
|
|
207
|
+
" position: fixed; z-index: 1100;",
|
|
208
|
+
" display: inline-flex; align-items: center; gap: 8px;",
|
|
209
|
+
" width: max-content; max-width: 50vw;",
|
|
210
|
+
" padding: 3px 7px; border-radius: var(--dsw-radius-sm);",
|
|
211
|
+
" background: var(--dsw-alias-tooltip-bg); color: var(--dsw-static-neutral-bluish-00);",
|
|
212
|
+
" font-size: 13px; line-height: 20px;",
|
|
213
|
+
" white-space: pre-line; overflow-wrap: break-word;",
|
|
214
|
+
" pointer-events: none;",
|
|
215
|
+
" transform: translateX(-50%);",
|
|
216
|
+
" animation: ss-dock-tip-in 150ms var(--ds-ease-in-out);",
|
|
217
|
+
"}",
|
|
218
|
+
'.ss-dock-tip[data-side="top"] { transform: translate(-50%, -100%); }',
|
|
219
|
+
"@keyframes ss-dock-tip-in { from { opacity: 0; } }",
|
|
220
|
+
"@media (prefers-reduced-motion: reduce) { .ss-dock-tip { animation: none; } }",
|
|
192
221
|
".ss-dock-action {",
|
|
193
222
|
" display: grid; place-items: center; width: 28px; height: 28px; padding: 0; flex: none;",
|
|
194
223
|
" border: none; border-radius: 999px; background: none; cursor: pointer;",
|
|
195
224
|
" color: var(--dsw-alias-label-tertiary);",
|
|
196
225
|
"}",
|
|
197
226
|
".ss-dock-action:hover:not(:disabled) { background: var(--dsw-alias-interactive-bg-hover); }",
|
|
198
|
-
".ss-dock-action:focus-visible { outline:
|
|
227
|
+
".ss-dock-action:focus-visible { outline: var(--dsw-focus-ring-width) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary)); outline-offset: -2px; }",
|
|
199
228
|
".ss-dock-action:disabled { cursor: default; opacity: 0.45; }",
|
|
200
229
|
"/* \u63D2\u8BDD\u5B8C\u6210\u6001\uFF1AQueueDock \u65E0\u6B64\u6001\uFF0C\u7528\u6210\u529F\u8272\u505A\u8F7B\u63D0\u793A\uFF08\u53E0\u52A0 disabled \u534A\u900F\u660E\uFF09\u3002 */",
|
|
201
230
|
".ss-dock-action-steer.ss-done { color: var(--dsw-alias-state-success-primary); }",
|
|
@@ -245,19 +274,40 @@ var COMPONENTS = [
|
|
|
245
274
|
".ss-dock-editing { flex-wrap: wrap; }",
|
|
246
275
|
"",
|
|
247
276
|
"/* ==================== \u9762\u677F ==================== */",
|
|
248
|
-
"/*
|
|
277
|
+
"/*",
|
|
278
|
+
" * \u62AC\u5347\u9762\u9010\u9879\u5BF9\u9F50\u5B98\u65B9 PickerPopover\uFF08@deepseek-ai/dsh-client-ui-schedule \u7684",
|
|
279
|
+
" * PickerPopover.module.css + primitives MenuSurface.module.css\uFF09\uFF1A",
|
|
280
|
+
" * \u80CC\u666F --dsw-menu-surface-fill\uFF08\u5E26\u900F\u660E\u5EA6\u7684\u83DC\u5355\u9762\uFF09+ blur(40px) \u6BDB\u73BB\u7483",
|
|
281
|
+
" * \u63CF\u8FB9\u8D70\u4E3B\u9898\u7684 --dsw-elevation-stroke\uFF080 0 0 .5px\uFF09\uFF0C\u800C\u4E0D\u662F\u624B\u5199 1px \u2014\u2014",
|
|
282
|
+
" * 0.5px \u63CF\u8FB9\u662F\u9AD8\u5206\u5C4F\u4E0B\u7684\u6B63\u786E\u7EC6\u7EBF\uFF0C1px \u5728 1x \u4E0A\u8FC7\u91CD\u3001\u5728 2x \u4E0A\u53C8\u53D1\u865A\u3002",
|
|
283
|
+
" * \u9634\u5F71 --dsw-elevation-prominent\uFF08\u542B\u63CF\u8FB9\u5C42\uFF0C\u4E0D\u662F\u7B2C\u4E8C\u5957\u9634\u5F71\uFF09\u3002",
|
|
284
|
+
" * \u5706\u89D2 16px = --dsw-radius-lg\uFF08\u5B98\u65B9\u9762\u677F\u540C\u4E00\u6863\uFF1B\u65E7\u7684 12px \u662F --dsw-radius-md\uFF09\u3002",
|
|
285
|
+
" * z-index 1100 = \u5B98\u65B9\u6D6E\u5C42\u6863\uFF08\u65E7\u7684 101 \u662F\u81EA\u9020\u503C\uFF0C\u6392\u5728 dock \u4E4B\u4E0B\uFF09\u3002",
|
|
286
|
+
" *",
|
|
287
|
+
" * \u26A0\uFE0F \u52FF\u518D\u5F15\u5165 --dsw-shadow-lv3 / --dsw-alias-border-inverted\uFF1A\u90A3\u662F\u66F4\u65E9\u8BBE\u8BA1\u4EE3\u6B21\u7684",
|
|
288
|
+
" * token\uFF0C\u6DF7\u7528\u4F1A\u8BA9\u9762\u677F\u5728\u6D45\u8272/\u6DF1\u8272\u4E0B\u90FD\u504F\u79BB\u5B98\u65B9\u89C2\u611F\uFF08issue #24\uFF09\u3002",
|
|
289
|
+
" */",
|
|
249
290
|
".ss-backdrop {",
|
|
250
|
-
" position: fixed; inset: 0; z-index:
|
|
291
|
+
" position: fixed; inset: 0; z-index: 1099; background: transparent;",
|
|
251
292
|
"}",
|
|
252
293
|
".ss-panel {",
|
|
253
|
-
" position: fixed; z-index:
|
|
294
|
+
" position: fixed; top: auto; left: auto; z-index: 1100;",
|
|
295
|
+
" box-sizing: border-box; display: flex; flex-direction: column;",
|
|
254
296
|
" width: min(340px, calc(100vw - 24px));",
|
|
255
|
-
"
|
|
297
|
+
" padding: 12px;",
|
|
298
|
+
" background: var(--dsw-menu-surface-fill);",
|
|
299
|
+
" backdrop-filter: var(--dsw-menu-backdrop-filter);",
|
|
300
|
+
" -webkit-backdrop-filter: var(--dsw-menu-backdrop-filter);",
|
|
301
|
+
" border: 0; border-radius: var(--dsw-radius-lg);",
|
|
302
|
+
" box-shadow: var(--dsw-elevation-prominent);",
|
|
303
|
+
" /* \u63CF\u8FB9\u4E0E\u9634\u5F71\u540C\u53D8\u91CF\uFF1A--dsw-elevation-prominent \u81EA\u8EAB\u542B --dsw-elevation-stroke\uFF0C",
|
|
304
|
+
" \u8FD9\u91CC\u53EA\u9700\u7ED9 stroke \u989C\u8272\u3002\u5B98\u65B9 schedule/input-trigger/subagent \u4E09\u4E2A\u5305\u4E00\u81F4\u53D6 l1\u3002 */",
|
|
305
|
+
" --dsw-elevation-stroke-color: var(--dsw-alias-border-l1);",
|
|
256
306
|
" color: var(--dsw-alias-label-secondary);",
|
|
257
|
-
" border: 1px solid var(--dsw-alias-border-inverted); border-radius: 12px;",
|
|
258
|
-
" box-shadow: var(--dsw-shadow-lv3); padding: 12px; box-sizing: border-box;",
|
|
259
307
|
" font-size: 12px; line-height: 20px; font-family: var(--dsw-font-family);",
|
|
260
308
|
"}",
|
|
309
|
+
/* 兜底定位分支(无官方 useAnchoredPosition 的旧代次宿主)才用 bottom,
|
|
310
|
+
有官方锚定时 left/top 由 hook 注入,这里只兜住首帧测量前的 top:auto。 */
|
|
261
311
|
".ss-panel-header {",
|
|
262
312
|
" display: flex; align-items: center; justify-content: space-between; margin-bottom: 8px;",
|
|
263
313
|
"}",
|
|
@@ -635,7 +685,8 @@ function injectStyles() {
|
|
|
635
685
|
}
|
|
636
686
|
|
|
637
687
|
// src/client/components/SchedButton.tsx
|
|
638
|
-
var
|
|
688
|
+
var import_react7 = require("react");
|
|
689
|
+
var import_dsh_client_ui_primitives3 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
639
690
|
|
|
640
691
|
// src/time-utils.ts
|
|
641
692
|
function detectTimeZone() {
|
|
@@ -879,7 +930,9 @@ function useSchedT(locale) {
|
|
|
879
930
|
}
|
|
880
931
|
|
|
881
932
|
// src/client/components/SchedPanel.tsx
|
|
882
|
-
var
|
|
933
|
+
var import_react4 = require("react");
|
|
934
|
+
var import_react_dom = require("react-dom");
|
|
935
|
+
var import_dsh_client_ui_primitives2 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
883
936
|
|
|
884
937
|
// src/smart-window.ts
|
|
885
938
|
var DEFAULT_SMART_WINDOW = Object.freeze({
|
|
@@ -894,13 +947,13 @@ function isValidHhmm(value) {
|
|
|
894
947
|
return typeof value === "string" && HHMM_RE.test(value);
|
|
895
948
|
}
|
|
896
949
|
function sanitizeSmartWindowConfig(raw) {
|
|
897
|
-
const
|
|
950
|
+
const pick2 = (key, fallback) => isValidHhmm(raw?.[key]) ? raw[key] : fallback;
|
|
898
951
|
return {
|
|
899
|
-
workStart:
|
|
900
|
-
workEnd:
|
|
901
|
-
lunchStart:
|
|
902
|
-
lunchEnd:
|
|
903
|
-
eveningEnd:
|
|
952
|
+
workStart: pick2("workStart", DEFAULT_SMART_WINDOW.workStart),
|
|
953
|
+
workEnd: pick2("workEnd", DEFAULT_SMART_WINDOW.workEnd),
|
|
954
|
+
lunchStart: pick2("lunchStart", DEFAULT_SMART_WINDOW.lunchStart),
|
|
955
|
+
lunchEnd: pick2("lunchEnd", DEFAULT_SMART_WINDOW.lunchEnd),
|
|
956
|
+
eveningEnd: pick2("eveningEnd", DEFAULT_SMART_WINDOW.eveningEnd)
|
|
904
957
|
};
|
|
905
958
|
}
|
|
906
959
|
var SMART_MIN_DELAY_MS = 2 * 60 * 1e3;
|
|
@@ -1035,8 +1088,21 @@ function epochFromLocal(date, time, timeZone) {
|
|
|
1035
1088
|
if (hour > 23 || minute > 59 || second > 59 || month < 1 || month > 12 || day < 1 || day > 31) {
|
|
1036
1089
|
return void 0;
|
|
1037
1090
|
}
|
|
1038
|
-
const
|
|
1039
|
-
|
|
1091
|
+
const localEpoch = Date.UTC(year, month - 1, day, hour, minute, second, 0);
|
|
1092
|
+
const offsets = /* @__PURE__ */ new Set();
|
|
1093
|
+
for (let delta = -2; delta <= 2; delta += 1) {
|
|
1094
|
+
offsets.add(offsetOf(localEpoch + delta * DAY_MS2, timeZone));
|
|
1095
|
+
}
|
|
1096
|
+
const candidates = [];
|
|
1097
|
+
for (const offset of offsets) {
|
|
1098
|
+
const candidate = localEpoch - offset;
|
|
1099
|
+
const f = localFieldsOf(candidate, timeZone);
|
|
1100
|
+
if (f.year === year && f.month === month && f.day === day && f.hour === hour && f.minute === minute && f.second === second) {
|
|
1101
|
+
candidates.push(candidate);
|
|
1102
|
+
}
|
|
1103
|
+
}
|
|
1104
|
+
candidates.sort((a, b) => a - b);
|
|
1105
|
+
return candidates[0];
|
|
1040
1106
|
}
|
|
1041
1107
|
function nextSmartAt(now, timeZone, window2 = DEFAULT_SMART_WINDOW) {
|
|
1042
1108
|
let target;
|
|
@@ -1062,6 +1128,7 @@ function nextSmartAt(now, timeZone, window2 = DEFAULT_SMART_WINDOW) {
|
|
|
1062
1128
|
}
|
|
1063
1129
|
|
|
1064
1130
|
// src/client/components/TaskList.tsx
|
|
1131
|
+
var import_dsh_client_ui_primitives = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
1065
1132
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1066
1133
|
function scheduleStateOf(item, now) {
|
|
1067
1134
|
return Date.parse(item.scheduled_at) <= now ? "overdue" : "scheduled";
|
|
@@ -1095,7 +1162,7 @@ function TaskList({ items, now, deliveredIds, cancellingIds, onDelete, timeZone,
|
|
|
1095
1162
|
event.stopPropagation();
|
|
1096
1163
|
onDelete(item.id);
|
|
1097
1164
|
},
|
|
1098
|
-
children:
|
|
1165
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_dsh_client_ui_primitives.IconCloseOutlineRegular, { size: 14 })
|
|
1099
1166
|
}
|
|
1100
1167
|
)
|
|
1101
1168
|
] }, item.id);
|
|
@@ -1113,6 +1180,96 @@ function useNow(intervalMs = 1e3) {
|
|
|
1113
1180
|
return now;
|
|
1114
1181
|
}
|
|
1115
1182
|
|
|
1183
|
+
// src/client/primitives-compat.ts
|
|
1184
|
+
var import_react3 = require("react");
|
|
1185
|
+
var primitives = __toESM(require("@deepseek-ai/dsh-client-ui-primitives"), 1);
|
|
1186
|
+
function pick(name2) {
|
|
1187
|
+
return primitives[name2];
|
|
1188
|
+
}
|
|
1189
|
+
var hostUseAnchoredPosition = pick("useAnchoredPosition");
|
|
1190
|
+
var hostUseDismissOnOutsidePointer = pick("useDismissOnOutsidePointer");
|
|
1191
|
+
function useLegacyAnchoredPosition({
|
|
1192
|
+
open,
|
|
1193
|
+
anchorRef,
|
|
1194
|
+
panelRef,
|
|
1195
|
+
side = "bottom",
|
|
1196
|
+
align = "start",
|
|
1197
|
+
gap,
|
|
1198
|
+
margin
|
|
1199
|
+
}) {
|
|
1200
|
+
const [position, setPosition] = (0, import_react3.useState)(null);
|
|
1201
|
+
(0, import_react3.useLayoutEffect)(() => {
|
|
1202
|
+
if (!open) {
|
|
1203
|
+
setPosition(null);
|
|
1204
|
+
return void 0;
|
|
1205
|
+
}
|
|
1206
|
+
const measure = () => {
|
|
1207
|
+
const anchor = anchorRef.current;
|
|
1208
|
+
const panel2 = panelRef.current;
|
|
1209
|
+
if (anchor === null || panel2 === null) return;
|
|
1210
|
+
const rect = anchor.getBoundingClientRect();
|
|
1211
|
+
const panelWidth = panel2.offsetWidth;
|
|
1212
|
+
const panelHeight = panel2.offsetHeight;
|
|
1213
|
+
const viewportWidth = window.innerWidth;
|
|
1214
|
+
const viewportHeight = window.innerHeight;
|
|
1215
|
+
const left = align === "end" ? rect.right - panelWidth : rect.left;
|
|
1216
|
+
const rawTop = side === "top" ? rect.top - panelHeight - gap : rect.bottom + gap;
|
|
1217
|
+
const clampedLeft = Math.min(
|
|
1218
|
+
Math.max(margin, left),
|
|
1219
|
+
Math.max(margin, viewportWidth - panelWidth - margin)
|
|
1220
|
+
);
|
|
1221
|
+
const overflowsTop = rawTop < margin;
|
|
1222
|
+
const overflowsBottom = rawTop + panelHeight > viewportHeight - margin;
|
|
1223
|
+
const top = overflowsTop && !overflowsBottom ? rect.bottom + gap : overflowsBottom && !overflowsTop ? rect.top - panelHeight - gap : rawTop;
|
|
1224
|
+
setPosition({
|
|
1225
|
+
left: `${Math.round(clampedLeft)}px`,
|
|
1226
|
+
top: `${Math.round(Math.max(margin, Math.min(top, viewportHeight - panelHeight - margin)))}px`
|
|
1227
|
+
});
|
|
1228
|
+
};
|
|
1229
|
+
measure();
|
|
1230
|
+
window.addEventListener("scroll", measure, true);
|
|
1231
|
+
window.addEventListener("resize", measure);
|
|
1232
|
+
const panel = panelRef.current;
|
|
1233
|
+
const observer = typeof ResizeObserver === "undefined" || panel === null ? void 0 : new ResizeObserver(measure);
|
|
1234
|
+
if (observer !== void 0 && panel !== null) observer.observe(panel);
|
|
1235
|
+
return () => {
|
|
1236
|
+
window.removeEventListener("scroll", measure, true);
|
|
1237
|
+
window.removeEventListener("resize", measure);
|
|
1238
|
+
observer?.disconnect();
|
|
1239
|
+
};
|
|
1240
|
+
}, [open, anchorRef, panelRef, side, align, gap, margin]);
|
|
1241
|
+
return position;
|
|
1242
|
+
}
|
|
1243
|
+
function noopDismiss() {
|
|
1244
|
+
}
|
|
1245
|
+
var anchorImpl = hostUseAnchoredPosition ?? useLegacyAnchoredPosition;
|
|
1246
|
+
var dismissImpl = hostUseDismissOnOutsidePointer ?? noopDismiss;
|
|
1247
|
+
var hasOfficialOutsideDismiss = hostUseDismissOnOutsidePointer !== void 0;
|
|
1248
|
+
var hasOfficialAnchoredPosition = hostUseAnchoredPosition !== void 0;
|
|
1249
|
+
function usePanelAnchorPosition(options) {
|
|
1250
|
+
return anchorImpl(options);
|
|
1251
|
+
}
|
|
1252
|
+
function usePanelOutsideDismiss(root, open, setOpen, portal) {
|
|
1253
|
+
return dismissImpl(root, open, setOpen, portal);
|
|
1254
|
+
}
|
|
1255
|
+
var PANEL_MEASURE_STYLE = {
|
|
1256
|
+
visibility: "hidden",
|
|
1257
|
+
left: 0,
|
|
1258
|
+
top: 0
|
|
1259
|
+
};
|
|
1260
|
+
function useEscapeToClose(open, setOpen) {
|
|
1261
|
+
const setOpenRef = (0, import_react3.useRef)(setOpen);
|
|
1262
|
+
setOpenRef.current = setOpen;
|
|
1263
|
+
(0, import_react3.useEffect)(() => {
|
|
1264
|
+
if (!open) return void 0;
|
|
1265
|
+
const onKey = (event) => {
|
|
1266
|
+
if (event.key === "Escape") setOpenRef.current(false);
|
|
1267
|
+
};
|
|
1268
|
+
window.addEventListener("keydown", onKey, true);
|
|
1269
|
+
return () => window.removeEventListener("keydown", onKey, true);
|
|
1270
|
+
}, [open]);
|
|
1271
|
+
}
|
|
1272
|
+
|
|
1116
1273
|
// src/client/components/SchedPanel.tsx
|
|
1117
1274
|
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
1118
1275
|
function atOnDay(dayOffset, hhmm, timeZone, now) {
|
|
@@ -1135,22 +1292,36 @@ function SchedPanel({
|
|
|
1135
1292
|
onCreate,
|
|
1136
1293
|
onDelete,
|
|
1137
1294
|
bottom,
|
|
1295
|
+
anchorRef,
|
|
1296
|
+
panelRef: externalPanelRef,
|
|
1138
1297
|
smartWindow = DEFAULT_SMART_WINDOW,
|
|
1139
1298
|
promptLimits
|
|
1140
1299
|
}) {
|
|
1141
1300
|
const now = useNow(1e3);
|
|
1142
|
-
const
|
|
1143
|
-
const
|
|
1301
|
+
const localPanelRef = (0, import_react4.useRef)(null);
|
|
1302
|
+
const panelRef = externalPanelRef ?? localPanelRef;
|
|
1303
|
+
const anchored = usePanelAnchorPosition({
|
|
1304
|
+
open: true,
|
|
1305
|
+
anchorRef: anchorRef ?? { current: null },
|
|
1306
|
+
panelRef,
|
|
1307
|
+
side: "top",
|
|
1308
|
+
align: "start",
|
|
1309
|
+
gap: 4,
|
|
1310
|
+
margin: 12
|
|
1311
|
+
});
|
|
1312
|
+
const panelStyle = hasOfficialAnchoredPosition ? anchored ?? PANEL_MEASURE_STYLE : { bottom };
|
|
1313
|
+
const [selected, setSelected] = (0, import_react4.useState)("after-600");
|
|
1314
|
+
const [customDate, setCustomDate] = (0, import_react4.useState)(() => {
|
|
1144
1315
|
const f = localFieldsOf(Date.now(), timeZone);
|
|
1145
1316
|
return `${String(f.year).padStart(4, "0")}-${String(f.month).padStart(2, "0")}-${String(f.day).padStart(2, "0")}`;
|
|
1146
1317
|
});
|
|
1147
|
-
const [customTime, setCustomTime] = (0,
|
|
1148
|
-
const [error, setError] = (0,
|
|
1149
|
-
const [cancelling, setCancelling] = (0,
|
|
1150
|
-
const [delivered, setDelivered] = (0,
|
|
1151
|
-
const deliveredTimers = (0,
|
|
1152
|
-
const prevIds = (0,
|
|
1153
|
-
(0,
|
|
1318
|
+
const [customTime, setCustomTime] = (0, import_react4.useState)("18:00");
|
|
1319
|
+
const [error, setError] = (0, import_react4.useState)(null);
|
|
1320
|
+
const [cancelling, setCancelling] = (0, import_react4.useState)(/* @__PURE__ */ new Set());
|
|
1321
|
+
const [delivered, setDelivered] = (0, import_react4.useState)(/* @__PURE__ */ new Set());
|
|
1322
|
+
const deliveredTimers = (0, import_react4.useRef)([]);
|
|
1323
|
+
const prevIds = (0, import_react4.useRef)(null);
|
|
1324
|
+
(0, import_react4.useEffect)(() => {
|
|
1154
1325
|
const currentIds = new Set(schedules.map((item) => item.id));
|
|
1155
1326
|
const previous = prevIds.current;
|
|
1156
1327
|
prevIds.current = currentIds;
|
|
@@ -1169,13 +1340,13 @@ function SchedPanel({
|
|
|
1169
1340
|
deliveredTimers.current.push(timer);
|
|
1170
1341
|
}
|
|
1171
1342
|
}, [schedules, cancelling]);
|
|
1172
|
-
(0,
|
|
1343
|
+
(0, import_react4.useEffect)(
|
|
1173
1344
|
() => () => {
|
|
1174
1345
|
for (const timer of deliveredTimers.current) window.clearTimeout(timer);
|
|
1175
1346
|
},
|
|
1176
1347
|
[]
|
|
1177
1348
|
);
|
|
1178
|
-
const quickOptions = (0,
|
|
1349
|
+
const quickOptions = (0, import_react4.useMemo)(() => {
|
|
1179
1350
|
const options = [
|
|
1180
1351
|
{ kind: "after", seconds: 600, label: t.quick10m },
|
|
1181
1352
|
{ kind: "after", seconds: 3600, label: t.quick1h }
|
|
@@ -1200,7 +1371,7 @@ function SchedPanel({
|
|
|
1200
1371
|
options.push({ kind: "custom", label: t.quickCustom });
|
|
1201
1372
|
return options;
|
|
1202
1373
|
}, [timeZone, now, t, smartWindow]);
|
|
1203
|
-
const target = (0,
|
|
1374
|
+
const target = (0, import_react4.useMemo)(() => {
|
|
1204
1375
|
if (selected === "custom") {
|
|
1205
1376
|
const match = /^(\d{2}):(\d{2})$/.exec(customTime);
|
|
1206
1377
|
if (match === null) return null;
|
|
@@ -1213,7 +1384,7 @@ function SchedPanel({
|
|
|
1213
1384
|
if (option.kind === "after") return { after_seconds: option.seconds, epoch: now + option.seconds * 1e3 };
|
|
1214
1385
|
return { at: option.at, epoch: option.epoch };
|
|
1215
1386
|
}, [selected, customDate, customTime, timeZone, now, quickOptions]);
|
|
1216
|
-
const targetLabel = (0,
|
|
1387
|
+
const targetLabel = (0, import_react4.useMemo)(() => {
|
|
1217
1388
|
if (target === void 0 || target === null) return null;
|
|
1218
1389
|
return `${formatAbsolute(target.epoch, timeZone, lang)} \xB7 ${formatRelative(target.epoch, now, lang)}`;
|
|
1219
1390
|
}, [target, timeZone, now]);
|
|
@@ -1261,87 +1432,101 @@ function SchedPanel({
|
|
|
1261
1432
|
};
|
|
1262
1433
|
const promptEmpty = defaultPrompt.trim().length === 0;
|
|
1263
1434
|
const canConfirm = !busy && !promptEmpty && target !== null;
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
"aria-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1435
|
+
const panel = /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
1436
|
+
"div",
|
|
1437
|
+
{
|
|
1438
|
+
ref: panelRef,
|
|
1439
|
+
className: "ss-panel",
|
|
1440
|
+
"data-ss-panel": "",
|
|
1441
|
+
role: "dialog",
|
|
1442
|
+
"aria-label": t.panelTitle,
|
|
1443
|
+
style: panelStyle,
|
|
1444
|
+
onClick: (event) => event.stopPropagation(),
|
|
1445
|
+
children: [
|
|
1446
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "ss-panel-header", children: [
|
|
1447
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "ss-panel-title", children: t.panelTitle }),
|
|
1448
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("button", { type: "button", className: "ss-panel-close", "aria-label": t.close, onClick: onClose, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_dsh_client_ui_primitives2.IconCloseOutlineRegular, { size: 14 }) })
|
|
1449
|
+
] }),
|
|
1450
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "ss-quick-grid", role: "radiogroup", "aria-label": t.panelTitle, children: quickOptions.map((option) => {
|
|
1451
|
+
const key = keyOf(option);
|
|
1452
|
+
const active = selected === key || option.kind === "custom" && selected === "custom";
|
|
1453
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1454
|
+
"button",
|
|
1455
|
+
{
|
|
1456
|
+
type: "button",
|
|
1457
|
+
role: "radio",
|
|
1458
|
+
"aria-checked": active,
|
|
1459
|
+
className: active ? "ss-quick-chip ss-active" : "ss-quick-chip",
|
|
1460
|
+
onClick: () => {
|
|
1461
|
+
setSelected(key);
|
|
1462
|
+
setError(null);
|
|
1463
|
+
},
|
|
1464
|
+
children: option.label
|
|
1465
|
+
},
|
|
1466
|
+
key
|
|
1467
|
+
);
|
|
1468
|
+
}) }),
|
|
1469
|
+
selected === "custom" && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "ss-custom-row", children: [
|
|
1470
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1471
|
+
"input",
|
|
1472
|
+
{
|
|
1473
|
+
type: "date",
|
|
1474
|
+
className: "ss-input",
|
|
1475
|
+
"aria-label": t.dateLabel,
|
|
1476
|
+
value: customDate,
|
|
1477
|
+
onChange: (event) => {
|
|
1478
|
+
if (event.target.value) setCustomDate(event.target.value);
|
|
1479
|
+
}
|
|
1480
|
+
}
|
|
1481
|
+
),
|
|
1482
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1483
|
+
"input",
|
|
1484
|
+
{
|
|
1485
|
+
type: "time",
|
|
1486
|
+
className: "ss-input",
|
|
1487
|
+
"aria-label": t.timeLabel,
|
|
1488
|
+
value: customTime,
|
|
1489
|
+
onChange: (event) => {
|
|
1490
|
+
if (event.target.value) setCustomTime(event.target.value);
|
|
1491
|
+
}
|
|
1492
|
+
}
|
|
1493
|
+
)
|
|
1494
|
+
] }),
|
|
1495
|
+
target !== null && targetLabel !== null && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "ss-hint", style: { margin: "6px 0 0" }, children: targetLabel }),
|
|
1496
|
+
error !== null && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "ss-error", role: "alert", style: { marginTop: 6 }, children: error }),
|
|
1497
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "ss-tasklist-head", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "ss-hint", children: [
|
|
1498
|
+
t.taskListTitle,
|
|
1499
|
+
schedules.length > 0 ? ` (${schedules.length})` : ""
|
|
1500
|
+
] }) }),
|
|
1501
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1502
|
+
TaskList,
|
|
1503
|
+
{
|
|
1504
|
+
items: schedules,
|
|
1505
|
+
now,
|
|
1506
|
+
deliveredIds: delivered,
|
|
1507
|
+
cancellingIds: cancelling,
|
|
1508
|
+
onDelete: handleDelete,
|
|
1509
|
+
timeZone,
|
|
1510
|
+
t,
|
|
1511
|
+
lang
|
|
1298
1512
|
}
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
onChange: (event) => {
|
|
1309
|
-
if (event.target.value) setCustomTime(event.target.value);
|
|
1513
|
+
),
|
|
1514
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "ss-footer", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1515
|
+
"button",
|
|
1516
|
+
{
|
|
1517
|
+
type: "button",
|
|
1518
|
+
className: "ss-confirm",
|
|
1519
|
+
disabled: !canConfirm,
|
|
1520
|
+
onClick: () => void handleConfirm(),
|
|
1521
|
+
children: busy ? t.sending : target !== null ? format(t.confirmAdd, { time: formatAbsolute(target.epoch, timeZone, lang) }) : t.confirmAddNoTime
|
|
1310
1522
|
}
|
|
1311
|
-
}
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
schedules.length > 0 ? ` (${schedules.length})` : ""
|
|
1319
|
-
] }) }),
|
|
1320
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1321
|
-
TaskList,
|
|
1322
|
-
{
|
|
1323
|
-
items: schedules,
|
|
1324
|
-
now,
|
|
1325
|
-
deliveredIds: delivered,
|
|
1326
|
-
cancellingIds: cancelling,
|
|
1327
|
-
onDelete: handleDelete,
|
|
1328
|
-
timeZone,
|
|
1329
|
-
t,
|
|
1330
|
-
lang
|
|
1331
|
-
}
|
|
1332
|
-
),
|
|
1333
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "ss-footer", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1334
|
-
"button",
|
|
1335
|
-
{
|
|
1336
|
-
type: "button",
|
|
1337
|
-
className: "ss-confirm",
|
|
1338
|
-
disabled: !canConfirm,
|
|
1339
|
-
onClick: () => void handleConfirm(),
|
|
1340
|
-
children: busy ? t.sending : target !== null ? format(t.confirmAdd, { time: formatAbsolute(target.epoch, timeZone, lang) }) : t.confirmAddNoTime
|
|
1341
|
-
}
|
|
1342
|
-
) }),
|
|
1343
|
-
promptEmpty && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "ss-hint", style: { marginTop: 6 }, children: t.promptFromDraft })
|
|
1344
|
-
] });
|
|
1523
|
+
) }),
|
|
1524
|
+
promptEmpty && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "ss-hint", style: { marginTop: 6 }, children: t.promptFromDraft })
|
|
1525
|
+
]
|
|
1526
|
+
}
|
|
1527
|
+
);
|
|
1528
|
+
if (typeof document === "undefined") return panel;
|
|
1529
|
+
return (0, import_react_dom.createPortal)(panel, document.body);
|
|
1345
1530
|
}
|
|
1346
1531
|
function keyOf(option) {
|
|
1347
1532
|
switch (option.kind) {
|
|
@@ -1357,7 +1542,7 @@ function keyOf(option) {
|
|
|
1357
1542
|
}
|
|
1358
1543
|
|
|
1359
1544
|
// src/client/hooks/useSchedules.ts
|
|
1360
|
-
var
|
|
1545
|
+
var import_react5 = require("react");
|
|
1361
1546
|
|
|
1362
1547
|
// src/client/local-store.ts
|
|
1363
1548
|
var STORAGE_KEY = "dsh-later:pending";
|
|
@@ -1410,28 +1595,28 @@ var createLine = (input) => {
|
|
|
1410
1595
|
var deleteLine = (id) => `/user-schedule-delete ${JSON.stringify({ id })}`;
|
|
1411
1596
|
function useSchedules(inject2) {
|
|
1412
1597
|
const { callCommand, sessionId, inputActions, input, useProjection, useInput } = inject2;
|
|
1413
|
-
const [busy, setBusy] = (0,
|
|
1414
|
-
const [anchorBottom, setAnchorBottom] = (0,
|
|
1415
|
-
const [pendingSync, setPendingSync] = (0,
|
|
1416
|
-
const rowRef = (0,
|
|
1598
|
+
const [busy, setBusy] = (0, import_react5.useState)(false);
|
|
1599
|
+
const [anchorBottom, setAnchorBottom] = (0, import_react5.useState)(80);
|
|
1600
|
+
const [pendingSync, setPendingSync] = (0, import_react5.useState)(() => readPending());
|
|
1601
|
+
const rowRef = (0, import_react5.useRef)(null);
|
|
1417
1602
|
const now = useNow(1e3);
|
|
1418
1603
|
const draft = input?.draft ?? (typeof useInput === "function" ? useInput((s) => s.draft) : "") ?? "";
|
|
1419
1604
|
const projection = typeof useProjection === "function" ? useProjection("userSchedules") : void 0;
|
|
1420
|
-
const schedules = (0,
|
|
1421
|
-
const nextEpoch = (0,
|
|
1605
|
+
const schedules = (0, import_react5.useMemo)(() => schedulesOf(projection), [projection]);
|
|
1606
|
+
const nextEpoch = (0, import_react5.useMemo)(() => {
|
|
1422
1607
|
return schedules.map((item) => Date.parse(item.scheduled_at)).filter((value) => !Number.isNaN(value)).sort((a, b) => a - b)[0];
|
|
1423
1608
|
}, [schedules]);
|
|
1424
1609
|
const enabled = draft.trim().length > 0 || schedules.length > 0;
|
|
1425
|
-
const reposition = (0,
|
|
1610
|
+
const reposition = (0, import_react5.useCallback)(() => {
|
|
1426
1611
|
const el = rowRef.current;
|
|
1427
1612
|
if (el === null) return;
|
|
1428
1613
|
const rect = el.getBoundingClientRect();
|
|
1429
1614
|
setAnchorBottom(Math.max(12, window.innerHeight - rect.top + 10));
|
|
1430
1615
|
}, []);
|
|
1431
|
-
const syncedPrompts = (0,
|
|
1616
|
+
const syncedPrompts = (0, import_react5.useMemo)(() => {
|
|
1432
1617
|
return new Set(schedules.map((item) => item.prompt));
|
|
1433
1618
|
}, [schedules]);
|
|
1434
|
-
(0,
|
|
1619
|
+
(0, import_react5.useEffect)(() => {
|
|
1435
1620
|
if (pendingSync.length === 0) return;
|
|
1436
1621
|
const remaining = pendingSync.filter((item) => !syncedPrompts.has(item.payload.prompt));
|
|
1437
1622
|
if (remaining.length !== pendingSync.length) {
|
|
@@ -1439,7 +1624,7 @@ function useSchedules(inject2) {
|
|
|
1439
1624
|
writePendingLocal(remaining);
|
|
1440
1625
|
}
|
|
1441
1626
|
}, [syncedPrompts, pendingSync]);
|
|
1442
|
-
(0,
|
|
1627
|
+
(0, import_react5.useEffect)(() => {
|
|
1443
1628
|
if (pendingSync.length === 0 || !sessionId) return;
|
|
1444
1629
|
let cancelled = false;
|
|
1445
1630
|
const syncAll = async () => {
|
|
@@ -1467,7 +1652,7 @@ function useSchedules(inject2) {
|
|
|
1467
1652
|
window.removeEventListener("online", onOnline);
|
|
1468
1653
|
};
|
|
1469
1654
|
}, [pendingSync, sessionId, callCommand]);
|
|
1470
|
-
const handleCreate = (0,
|
|
1655
|
+
const handleCreate = (0, import_react5.useCallback)(async (inputPayload) => {
|
|
1471
1656
|
if (!sessionId) {
|
|
1472
1657
|
throw new Error(CLIENT_ERR.NO_SESSION);
|
|
1473
1658
|
}
|
|
@@ -1483,15 +1668,15 @@ function useSchedules(inject2) {
|
|
|
1483
1668
|
setBusy(false);
|
|
1484
1669
|
}
|
|
1485
1670
|
}, [sessionId, callCommand]);
|
|
1486
|
-
const handleDelete = (0,
|
|
1671
|
+
const handleDelete = (0, import_react5.useCallback)(async (id) => {
|
|
1487
1672
|
if (!sessionId) return;
|
|
1488
1673
|
await callCommand(sessionId, deleteLine(id));
|
|
1489
1674
|
}, [sessionId, callCommand]);
|
|
1490
|
-
const handleCancelAll = (0,
|
|
1675
|
+
const handleCancelAll = (0, import_react5.useCallback)(async () => {
|
|
1491
1676
|
if (!sessionId) return;
|
|
1492
1677
|
await Promise.all(schedules.map((item) => callCommand(sessionId, deleteLine(item.id))));
|
|
1493
1678
|
}, [sessionId, schedules, callCommand]);
|
|
1494
|
-
const handleClearDraft = (0,
|
|
1679
|
+
const handleClearDraft = (0, import_react5.useCallback)(() => {
|
|
1495
1680
|
inputActions?.setDraft("");
|
|
1496
1681
|
}, [inputActions]);
|
|
1497
1682
|
return {
|
|
@@ -1519,7 +1704,7 @@ function writePendingLocal(pending) {
|
|
|
1519
1704
|
}
|
|
1520
1705
|
|
|
1521
1706
|
// src/client/hooks/useSchedulerSettings.ts
|
|
1522
|
-
var
|
|
1707
|
+
var import_react6 = require("react");
|
|
1523
1708
|
var CLIENT_DEFAULT_MAX_PROMPT_CHARS = 1e3;
|
|
1524
1709
|
var FALLBACK_PROMPT = {
|
|
1525
1710
|
allowLong: false,
|
|
@@ -1563,16 +1748,16 @@ function resolveFromSnapshot(snap) {
|
|
|
1563
1748
|
var NOOP_SUBSCRIBE = () => () => void 0;
|
|
1564
1749
|
var EMPTY_SNAPSHOT = { status: "unavailable" };
|
|
1565
1750
|
function useSchedulerSettings(scope) {
|
|
1566
|
-
const getSnapshot = (0,
|
|
1751
|
+
const getSnapshot = (0, import_react6.useCallback)(
|
|
1567
1752
|
() => scope === void 0 ? EMPTY_SNAPSHOT : scope.getSnapshot(),
|
|
1568
1753
|
[scope]
|
|
1569
1754
|
);
|
|
1570
|
-
const subscribe = (0,
|
|
1755
|
+
const subscribe = (0, import_react6.useCallback)(
|
|
1571
1756
|
(onStoreChange) => scope === void 0 ? NOOP_SUBSCRIBE() : scope.subscribe(onStoreChange),
|
|
1572
1757
|
[scope]
|
|
1573
1758
|
);
|
|
1574
|
-
const raw = (0,
|
|
1575
|
-
return (0,
|
|
1759
|
+
const raw = (0, import_react6.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
1760
|
+
return (0, import_react6.useMemo)(() => resolveFromSnapshot(raw), [raw]);
|
|
1576
1761
|
}
|
|
1577
1762
|
|
|
1578
1763
|
// src/client/components/SchedButton.tsx
|
|
@@ -1581,7 +1766,7 @@ function SchedButton(props) {
|
|
|
1581
1766
|
const { callCommand, sessionId, inputActions, input, useProjection, useInput, locale, schedulerScope } = props;
|
|
1582
1767
|
const { lang, t } = useSchedT(locale);
|
|
1583
1768
|
const { smartWindow, promptLimits, showButton } = useSchedulerSettings(schedulerScope);
|
|
1584
|
-
const [open, setOpen] = (0,
|
|
1769
|
+
const [open, setOpen] = (0, import_react7.useState)(false);
|
|
1585
1770
|
const {
|
|
1586
1771
|
draft,
|
|
1587
1772
|
schedules,
|
|
@@ -1600,19 +1785,15 @@ function SchedButton(props) {
|
|
|
1600
1785
|
useProjection,
|
|
1601
1786
|
useInput
|
|
1602
1787
|
});
|
|
1603
|
-
(
|
|
1604
|
-
|
|
1788
|
+
useEscapeToClose(open, setOpen);
|
|
1789
|
+
(0, import_react7.useEffect)(() => {
|
|
1790
|
+
if (!open) return void 0;
|
|
1605
1791
|
reposition();
|
|
1606
1792
|
window.addEventListener("resize", reposition);
|
|
1607
|
-
|
|
1608
|
-
if (event.key === "Escape") setOpen(false);
|
|
1609
|
-
};
|
|
1610
|
-
window.addEventListener("keydown", onKey, true);
|
|
1611
|
-
return () => {
|
|
1612
|
-
window.removeEventListener("resize", reposition);
|
|
1613
|
-
window.removeEventListener("keydown", onKey, true);
|
|
1614
|
-
};
|
|
1793
|
+
return () => window.removeEventListener("resize", reposition);
|
|
1615
1794
|
}, [open, reposition]);
|
|
1795
|
+
const panelRef = (0, import_react7.useRef)(null);
|
|
1796
|
+
usePanelOutsideDismiss(rowRef, open, setOpen, panelRef);
|
|
1616
1797
|
if (!showButton) return null;
|
|
1617
1798
|
const handleCreateWithErrorBoundary = async (inputPayload) => {
|
|
1618
1799
|
try {
|
|
@@ -1633,14 +1814,11 @@ function SchedButton(props) {
|
|
|
1633
1814
|
"aria-expanded": open,
|
|
1634
1815
|
disabled: !enabled,
|
|
1635
1816
|
onClick: () => setOpen((value) => !value),
|
|
1636
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime3.
|
|
1637
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("circle", { cx: "12", cy: "12", r: "10" }),
|
|
1638
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("polyline", { points: "12 6 12 12 16 14" })
|
|
1639
|
-
] })
|
|
1817
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_dsh_client_ui_primitives3.IconClockOutlineRegular, { size: 16 })
|
|
1640
1818
|
}
|
|
1641
1819
|
),
|
|
1642
1820
|
open && /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
|
|
1643
|
-
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "ss-backdrop", onClick: () => setOpen(false), "aria-hidden": "true" }),
|
|
1821
|
+
!hasOfficialOutsideDismiss && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className: "ss-backdrop", onClick: () => setOpen(false), "aria-hidden": "true" }),
|
|
1644
1822
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
1645
1823
|
SchedPanel,
|
|
1646
1824
|
{
|
|
@@ -1654,6 +1832,8 @@ function SchedButton(props) {
|
|
|
1654
1832
|
onCreate: handleCreateWithErrorBoundary,
|
|
1655
1833
|
onDelete: (id) => void handleDelete(id),
|
|
1656
1834
|
bottom: anchorBottom,
|
|
1835
|
+
anchorRef: rowRef,
|
|
1836
|
+
panelRef,
|
|
1657
1837
|
smartWindow,
|
|
1658
1838
|
promptLimits
|
|
1659
1839
|
}
|
|
@@ -1663,7 +1843,9 @@ function SchedButton(props) {
|
|
|
1663
1843
|
}
|
|
1664
1844
|
|
|
1665
1845
|
// src/client/components/ScheduleDock.tsx
|
|
1666
|
-
var
|
|
1846
|
+
var import_react8 = require("react");
|
|
1847
|
+
var import_react_dom2 = require("react-dom");
|
|
1848
|
+
var import_dsh_client_ui_primitives4 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
1667
1849
|
|
|
1668
1850
|
// src/bar-geometry.ts
|
|
1669
1851
|
var BAR_UNIT_MS = 36e5;
|
|
@@ -1774,8 +1956,8 @@ function ScheduleDock({ callCommand, sessionId, useProjection, locale }) {
|
|
|
1774
1956
|
const now = useNow(1e3);
|
|
1775
1957
|
const { t } = useSchedT(locale);
|
|
1776
1958
|
const projection = typeof useProjection === "function" ? useProjection("userSchedules") : void 0;
|
|
1777
|
-
const [dismissedPaused, setDismissedPaused] = (0,
|
|
1778
|
-
(0,
|
|
1959
|
+
const [dismissedPaused, setDismissedPaused] = (0, import_react8.useState)(/* @__PURE__ */ new Set());
|
|
1960
|
+
(0, import_react8.useEffect)(() => {
|
|
1779
1961
|
const live = projection?.schedules;
|
|
1780
1962
|
if (live === void 0) return;
|
|
1781
1963
|
setDismissedPaused((current) => {
|
|
@@ -1788,8 +1970,8 @@ function ScheduleDock({ callCommand, sessionId, useProjection, locale }) {
|
|
|
1788
1970
|
return changed ? nextSet : current;
|
|
1789
1971
|
});
|
|
1790
1972
|
}, [projection]);
|
|
1791
|
-
const [promptOverrides, setPromptOverrides] = (0,
|
|
1792
|
-
(0,
|
|
1973
|
+
const [promptOverrides, setPromptOverrides] = (0, import_react8.useState)(/* @__PURE__ */ new Map());
|
|
1974
|
+
(0, import_react8.useEffect)(() => {
|
|
1793
1975
|
const live = projection?.schedules;
|
|
1794
1976
|
if (live === void 0 || promptOverrides.size === 0) return;
|
|
1795
1977
|
setPromptOverrides((current) => {
|
|
@@ -1806,7 +1988,7 @@ function ScheduleDock({ callCommand, sessionId, useProjection, locale }) {
|
|
|
1806
1988
|
return changed ? nextMap : current;
|
|
1807
1989
|
});
|
|
1808
1990
|
}, [projection, promptOverrides]);
|
|
1809
|
-
const schedules = (0,
|
|
1991
|
+
const schedules = (0, import_react8.useMemo)(
|
|
1810
1992
|
() => (projection?.schedules ?? []).filter((item) => !(item.status === "paused" && dismissedPaused.has(item.id))).map((item) => {
|
|
1811
1993
|
const override = promptOverrides.get(item.id);
|
|
1812
1994
|
return override === void 0 ? item : { ...item, prompt: override };
|
|
@@ -1815,17 +1997,17 @@ function ScheduleDock({ callCommand, sessionId, useProjection, locale }) {
|
|
|
1815
1997
|
),
|
|
1816
1998
|
[projection, dismissedPaused, promptOverrides]
|
|
1817
1999
|
);
|
|
1818
|
-
const [collapsed, setCollapsed] = (0,
|
|
1819
|
-
const [cancelling, setCancelling] = (0,
|
|
1820
|
-
const [editingId, setEditingId] = (0,
|
|
1821
|
-
const [editingText, setEditingText] = (0,
|
|
1822
|
-
const [editErr, setEditErr] = (0,
|
|
1823
|
-
const [saving, setSaving] = (0,
|
|
1824
|
-
const [steering, setSteering] = (0,
|
|
1825
|
-
const [steerDone, setSteerDone] = (0,
|
|
1826
|
-
const [steerErr, setSteerErr] = (0,
|
|
1827
|
-
const [steerUnconfirmed, setSteerUnconfirmed] = (0,
|
|
1828
|
-
(0,
|
|
2000
|
+
const [collapsed, setCollapsed] = (0, import_react8.useState)(true);
|
|
2001
|
+
const [cancelling, setCancelling] = (0, import_react8.useState)(/* @__PURE__ */ new Set());
|
|
2002
|
+
const [editingId, setEditingId] = (0, import_react8.useState)(null);
|
|
2003
|
+
const [editingText, setEditingText] = (0, import_react8.useState)("");
|
|
2004
|
+
const [editErr, setEditErr] = (0, import_react8.useState)(null);
|
|
2005
|
+
const [saving, setSaving] = (0, import_react8.useState)(false);
|
|
2006
|
+
const [steering, setSteering] = (0, import_react8.useState)(/* @__PURE__ */ new Set());
|
|
2007
|
+
const [steerDone, setSteerDone] = (0, import_react8.useState)(/* @__PURE__ */ new Set());
|
|
2008
|
+
const [steerErr, setSteerErr] = (0, import_react8.useState)(/* @__PURE__ */ new Map());
|
|
2009
|
+
const [steerUnconfirmed, setSteerUnconfirmed] = (0, import_react8.useState)(/* @__PURE__ */ new Set());
|
|
2010
|
+
(0, import_react8.useEffect)(() => {
|
|
1829
2011
|
const live = projection?.schedules;
|
|
1830
2012
|
if (live === void 0) return;
|
|
1831
2013
|
const present = new Set(live.filter((item) => item.status !== "paused").map((item) => item.id));
|
|
@@ -1842,7 +2024,7 @@ function ScheduleDock({ callCommand, sessionId, useProjection, locale }) {
|
|
|
1842
2024
|
return changed ? next2 : current;
|
|
1843
2025
|
});
|
|
1844
2026
|
}, [projection]);
|
|
1845
|
-
(0,
|
|
2027
|
+
(0, import_react8.useEffect)(() => {
|
|
1846
2028
|
if (steerDone.size === 0) return void 0;
|
|
1847
2029
|
const timer = window.setTimeout(() => {
|
|
1848
2030
|
const live = projection?.schedules;
|
|
@@ -1863,11 +2045,11 @@ function ScheduleDock({ callCommand, sessionId, useProjection, locale }) {
|
|
|
1863
2045
|
}, STEER_CONFIRM_WINDOW_MS);
|
|
1864
2046
|
return () => window.clearTimeout(timer);
|
|
1865
2047
|
}, [steerDone, projection]);
|
|
1866
|
-
const [pausing, setPausing] = (0,
|
|
1867
|
-
const [resuming, setResuming] = (0,
|
|
1868
|
-
const [pauseErr, setPauseErr] = (0,
|
|
1869
|
-
const firstSeenRef = (0,
|
|
1870
|
-
const lastActiveAtRef = (0,
|
|
2048
|
+
const [pausing, setPausing] = (0, import_react8.useState)(/* @__PURE__ */ new Set());
|
|
2049
|
+
const [resuming, setResuming] = (0, import_react8.useState)(/* @__PURE__ */ new Set());
|
|
2050
|
+
const [pauseErr, setPauseErr] = (0, import_react8.useState)(/* @__PURE__ */ new Map());
|
|
2051
|
+
const firstSeenRef = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
|
|
2052
|
+
const lastActiveAtRef = (0, import_react8.useRef)(/* @__PURE__ */ new Map());
|
|
1871
2053
|
const wallClock = Date.now();
|
|
1872
2054
|
{
|
|
1873
2055
|
const next2 = new Map(lastActiveAtRef.current);
|
|
@@ -1888,8 +2070,8 @@ function ScheduleDock({ callCommand, sessionId, useProjection, locale }) {
|
|
|
1888
2070
|
}
|
|
1889
2071
|
if (changed) lastActiveAtRef.current = next2;
|
|
1890
2072
|
}
|
|
1891
|
-
const byId = (0,
|
|
1892
|
-
(0,
|
|
2073
|
+
const byId = (0, import_react8.useMemo)(() => new Map(schedules.map((item) => [item.id, item])), [schedules]);
|
|
2074
|
+
(0, import_react8.useEffect)(() => {
|
|
1893
2075
|
let changed = false;
|
|
1894
2076
|
const next2 = new Map(firstSeenRef.current);
|
|
1895
2077
|
for (const [id] of byId) {
|
|
@@ -1906,7 +2088,7 @@ function ScheduleDock({ callCommand, sessionId, useProjection, locale }) {
|
|
|
1906
2088
|
}
|
|
1907
2089
|
if (changed) firstSeenRef.current = next2;
|
|
1908
2090
|
}, [byId]);
|
|
1909
|
-
(0,
|
|
2091
|
+
(0, import_react8.useEffect)(() => {
|
|
1910
2092
|
if (schedules.length <= 1) setCollapsed(true);
|
|
1911
2093
|
}, [schedules.length]);
|
|
1912
2094
|
if (schedules.length === 0 || sessionId === void 0) return null;
|
|
@@ -2088,7 +2270,7 @@ function ScheduleDock({ callCommand, sessionId, useProjection, locale }) {
|
|
|
2088
2270
|
children: saving ? "\u2026" : t.editSave
|
|
2089
2271
|
}
|
|
2090
2272
|
),
|
|
2091
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "ss-dock-action", onClick: cancelEdit, "aria-label": t.editCancel, children:
|
|
2273
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("button", { type: "button", className: "ss-dock-action", onClick: cancelEdit, "aria-label": t.editCancel, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.IconCloseOutlineRegular, { size: 14 }) }),
|
|
2092
2274
|
editErr !== null && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "ss-dock-edit-err", children: editErr })
|
|
2093
2275
|
] }, item.id);
|
|
2094
2276
|
}
|
|
@@ -2115,63 +2297,58 @@ function ScheduleDock({ callCommand, sessionId, useProjection, locale }) {
|
|
|
2115
2297
|
] })
|
|
2116
2298
|
] }),
|
|
2117
2299
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "ss-dock-actions", children: [
|
|
2118
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2300
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DockTip, { label: t.editTask, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2119
2301
|
"button",
|
|
2120
2302
|
{
|
|
2121
2303
|
type: "button",
|
|
2122
2304
|
className: "ss-dock-action",
|
|
2123
|
-
title: t.editTask,
|
|
2124
2305
|
"aria-label": t.editTask,
|
|
2125
2306
|
onClick: () => startEdit(item),
|
|
2126
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2307
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.IconEditOutlineRegular, { size: 14 })
|
|
2127
2308
|
}
|
|
2128
|
-
),
|
|
2129
|
-
isPaused ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2309
|
+
) }),
|
|
2310
|
+
isPaused ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DockTip, { label: t.resumeTask, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2130
2311
|
"button",
|
|
2131
2312
|
{
|
|
2132
2313
|
type: "button",
|
|
2133
2314
|
className: `ss-dock-action ss-paused-active${resuming.has(item.id) ? " ss-pending" : ""}`,
|
|
2134
|
-
title: t.resumeTask,
|
|
2135
2315
|
"aria-label": t.resumeTask,
|
|
2136
2316
|
disabled: resuming.has(item.id),
|
|
2137
2317
|
onClick: () => handleResume(item),
|
|
2138
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2318
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.IconPlayOutlineRegular, { size: 16 })
|
|
2139
2319
|
}
|
|
2140
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2320
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DockTip, { label: canPause(item, now) ? t.pauseTask : t.pauseUnsupportedKind, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2141
2321
|
"button",
|
|
2142
2322
|
{
|
|
2143
2323
|
type: "button",
|
|
2144
2324
|
className: `ss-dock-action${pausing.has(item.id) ? " ss-pending" : ""}`,
|
|
2145
|
-
title: canPause(item, now) ? t.pauseTask : t.pauseUnsupportedKind,
|
|
2146
2325
|
"aria-label": canPause(item, now) ? t.pauseTask : t.pauseUnsupportedKind,
|
|
2147
2326
|
disabled: !canPause(item, now) || pausing.has(item.id),
|
|
2148
2327
|
onClick: () => handlePause(item),
|
|
2149
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2328
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.IconPauseOutlineRegular, { size: 16 })
|
|
2150
2329
|
}
|
|
2151
|
-
),
|
|
2152
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2330
|
+
) }),
|
|
2331
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DockTip, { label: t.deleteTask, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2153
2332
|
"button",
|
|
2154
2333
|
{
|
|
2155
2334
|
type: "button",
|
|
2156
2335
|
className: "ss-dock-action",
|
|
2157
|
-
title: t.deleteTask,
|
|
2158
2336
|
"aria-label": t.deleteTask,
|
|
2159
2337
|
onClick: () => handleCancel(item.id, isPaused ? "paused" : "active"),
|
|
2160
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2338
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.IconTrashOutlineRegular, { size: 14 })
|
|
2161
2339
|
}
|
|
2162
|
-
),
|
|
2163
|
-
item.kind !== "every" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2340
|
+
) }),
|
|
2341
|
+
item.kind !== "every" && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(DockTip, { label: steerDone.has(item.id) ? t.steerAlreadySent : t.steerTask, children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2164
2342
|
"button",
|
|
2165
2343
|
{
|
|
2166
2344
|
type: "button",
|
|
2167
2345
|
className: `ss-dock-action ss-dock-action-steer${steering.has(item.id) ? " ss-pending" : ""}${steerDone.has(item.id) ? " ss-done" : ""}`,
|
|
2168
|
-
title: steerDone.has(item.id) ? t.steerAlreadySent : t.steerTask,
|
|
2169
2346
|
"aria-label": steerDone.has(item.id) ? t.steerAlreadySent : t.steerTask,
|
|
2170
2347
|
disabled: steering.has(item.id) || steerDone.has(item.id),
|
|
2171
2348
|
onClick: () => handleSteer(item),
|
|
2172
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2349
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.IconSendOutlineRegular, { size: 16 })
|
|
2173
2350
|
}
|
|
2174
|
-
)
|
|
2351
|
+
) })
|
|
2175
2352
|
] })
|
|
2176
2353
|
]
|
|
2177
2354
|
},
|
|
@@ -2187,9 +2364,9 @@ function ScheduleDock({ callCommand, sessionId, useProjection, locale }) {
|
|
|
2187
2364
|
"aria-expanded": !collapsed,
|
|
2188
2365
|
onClick: () => setCollapsed((value) => !value),
|
|
2189
2366
|
children: [
|
|
2190
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "ss-dock-lead", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2367
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "ss-dock-lead", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.IconClockOutlineRegular, { size: 16 }) }),
|
|
2191
2368
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "ss-dock-count", children: format(t.panelCount, { n: schedules.length }) }),
|
|
2192
|
-
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: expanded ? "ss-dock-chevron ss-open" : "ss-dock-chevron", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2369
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: expanded ? "ss-dock-chevron ss-open" : "ss-dock-chevron", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_dsh_client_ui_primitives4.IconChevronDownOutlineRegular, { size: 14 }) })
|
|
2193
2370
|
]
|
|
2194
2371
|
}
|
|
2195
2372
|
),
|
|
@@ -2208,7 +2385,7 @@ function MultiBar({
|
|
|
2208
2385
|
const frozenSeg = frozen ? frozenBarSegments(item, frozenLeftMs ?? 0, firstSeen, renderedAt) : void 0;
|
|
2209
2386
|
const activeSeg = frozen ? void 0 : barSegments(item, now, firstSeen);
|
|
2210
2387
|
const { totalRatio, count } = frozenSeg ?? activeSeg ?? { totalRatio: 0, count: 1 };
|
|
2211
|
-
const phaseAtRef = (0,
|
|
2388
|
+
const phaseAtRef = (0, import_react8.useRef)(null);
|
|
2212
2389
|
if (frozen || prefersReducedMotion()) {
|
|
2213
2390
|
phaseAtRef.current = null;
|
|
2214
2391
|
} else if (phaseAtRef.current === null) {
|
|
@@ -2252,33 +2429,76 @@ function MultiBar({
|
|
|
2252
2429
|
}
|
|
2253
2430
|
);
|
|
2254
2431
|
}
|
|
2255
|
-
function
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2432
|
+
function DockTip({ label, children }) {
|
|
2433
|
+
const anchorRef = (0, import_react8.useRef)(null);
|
|
2434
|
+
const bubbleRef = (0, import_react8.useRef)(null);
|
|
2435
|
+
const [pos, setPos] = (0, import_react8.useState)(null);
|
|
2436
|
+
const timerRef = (0, import_react8.useRef)(null);
|
|
2437
|
+
const cancel = () => {
|
|
2438
|
+
if (timerRef.current !== null) {
|
|
2439
|
+
window.clearTimeout(timerRef.current);
|
|
2440
|
+
timerRef.current = null;
|
|
2441
|
+
}
|
|
2442
|
+
};
|
|
2443
|
+
const show = () => {
|
|
2444
|
+
const el = anchorRef.current;
|
|
2445
|
+
if (!el) return;
|
|
2446
|
+
const r = el.getBoundingClientRect();
|
|
2447
|
+
setPos({ left: r.left + r.width / 2, top: r.bottom + 8, side: "bottom" });
|
|
2448
|
+
};
|
|
2449
|
+
const enter = () => {
|
|
2450
|
+
cancel();
|
|
2451
|
+
timerRef.current = window.setTimeout(show, 500);
|
|
2452
|
+
};
|
|
2453
|
+
const leave = () => {
|
|
2454
|
+
cancel();
|
|
2455
|
+
setPos(null);
|
|
2456
|
+
};
|
|
2457
|
+
(0, import_react8.useEffect)(() => cancel, []);
|
|
2458
|
+
(0, import_react8.useLayoutEffect)(() => {
|
|
2459
|
+
if (!pos || !bubbleRef.current) return;
|
|
2460
|
+
const b = bubbleRef.current;
|
|
2461
|
+
const w = b.offsetWidth;
|
|
2462
|
+
const h = b.offsetHeight;
|
|
2463
|
+
const edge = 12;
|
|
2464
|
+
let left = pos.left;
|
|
2465
|
+
let top = pos.top;
|
|
2466
|
+
let side = pos.side;
|
|
2467
|
+
left = Math.max(edge + w / 2, Math.min(left, window.innerWidth - edge - w / 2));
|
|
2468
|
+
if (side === "bottom" && top + h > window.innerHeight - edge) {
|
|
2469
|
+
const anchorEl = anchorRef.current;
|
|
2470
|
+
const r = anchorEl.getBoundingClientRect();
|
|
2471
|
+
top = r.top - 8;
|
|
2472
|
+
side = "top";
|
|
2473
|
+
}
|
|
2474
|
+
b.style.left = `${left}px`;
|
|
2475
|
+
b.style.top = `${top}px`;
|
|
2476
|
+
b.dataset.side = side;
|
|
2477
|
+
b.style.visibility = "visible";
|
|
2478
|
+
}, [pos]);
|
|
2479
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(import_jsx_runtime4.Fragment, { children: [
|
|
2480
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
2481
|
+
"span",
|
|
2482
|
+
{
|
|
2483
|
+
ref: anchorRef,
|
|
2484
|
+
className: "ss-dock-tip-anchor",
|
|
2485
|
+
onPointerEnter: enter,
|
|
2486
|
+
onPointerLeave: leave,
|
|
2487
|
+
onFocus: enter,
|
|
2488
|
+
onBlur: leave,
|
|
2489
|
+
children
|
|
2490
|
+
}
|
|
2491
|
+
),
|
|
2492
|
+
pos && typeof document !== "undefined" && (0, import_react_dom2.createPortal)(
|
|
2493
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { ref: bubbleRef, className: "ss-dock-tip", style: { left: pos.left, top: pos.top, visibility: "hidden" }, children: label }),
|
|
2494
|
+
document.body
|
|
2495
|
+
)
|
|
2274
2496
|
] });
|
|
2275
2497
|
}
|
|
2276
|
-
function QueueResumeIcon() {
|
|
2277
|
-
return /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "none", xmlns: "http://www.w3.org/2000/svg", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("path", { d: "M4.4 2.9c0-.6.66-1 1.18-.68l7.1 4.1c.52.3.52 1.06 0 1.36l-7.1 4.1A.8.8 0 0 1 4.4 11.1V2.9Z", fill: "currentColor" }) });
|
|
2278
|
-
}
|
|
2279
2498
|
|
|
2280
2499
|
// src/client/components/SchedulerSettingsCard.tsx
|
|
2281
|
-
var
|
|
2500
|
+
var import_react9 = require("react");
|
|
2501
|
+
var import_dsh_client_ui_primitives5 = require("@deepseek-ai/dsh-client-ui-primitives");
|
|
2282
2502
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
2283
2503
|
var SECTIONS = [
|
|
2284
2504
|
{
|
|
@@ -2345,22 +2565,50 @@ var SECTIONS = [
|
|
|
2345
2565
|
defaultValue: "keep"
|
|
2346
2566
|
}
|
|
2347
2567
|
]
|
|
2568
|
+
},
|
|
2569
|
+
{
|
|
2570
|
+
id: "advanced",
|
|
2571
|
+
titleKey: "sectionAdvanced",
|
|
2572
|
+
layout: "stack",
|
|
2573
|
+
beta: true,
|
|
2574
|
+
fields: [
|
|
2575
|
+
{
|
|
2576
|
+
kind: "boolean",
|
|
2577
|
+
key: "advancedSyntax",
|
|
2578
|
+
labelKey: "advancedSyntaxLabel",
|
|
2579
|
+
hintKey: "advancedSyntaxHint",
|
|
2580
|
+
defaultValue: true
|
|
2581
|
+
}
|
|
2582
|
+
]
|
|
2348
2583
|
}
|
|
2349
2584
|
];
|
|
2350
2585
|
var FIELDS = SECTIONS.flatMap((s) => s.fields);
|
|
2351
|
-
function SchedulerSettingsCard({ scope, t }) {
|
|
2352
|
-
const [snapshot, setSnapshot] = (0,
|
|
2353
|
-
const [pending, setPending] = (0,
|
|
2354
|
-
const [saving, setSaving] = (0,
|
|
2355
|
-
const [failed, setFailed] = (0,
|
|
2356
|
-
const [helpOpen, setHelpOpen] = (0,
|
|
2357
|
-
|
|
2586
|
+
function SchedulerSettingsCard({ scope, t, surface }) {
|
|
2587
|
+
const [snapshot, setSnapshot] = (0, import_react9.useState)(() => scope.getSnapshot());
|
|
2588
|
+
const [pending, setPending] = (0, import_react9.useState)({});
|
|
2589
|
+
const [saving, setSaving] = (0, import_react9.useState)(false);
|
|
2590
|
+
const [failed, setFailed] = (0, import_react9.useState)(false);
|
|
2591
|
+
const [helpOpen, setHelpOpen] = (0, import_react9.useState)({});
|
|
2592
|
+
const SHOW_SETTINGS_KEY = "dsh-later:show-settings-section";
|
|
2593
|
+
const [showSettings, setShowSettings] = (0, import_react9.useState)(() => {
|
|
2594
|
+
if (typeof localStorage === "undefined") return false;
|
|
2595
|
+
return localStorage.getItem(SHOW_SETTINGS_KEY) === "true";
|
|
2596
|
+
});
|
|
2597
|
+
const toggleShowSettings = () => {
|
|
2598
|
+
const next = !showSettings;
|
|
2599
|
+
setShowSettings(next);
|
|
2600
|
+
if (typeof localStorage !== "undefined") {
|
|
2601
|
+
if (next) localStorage.setItem(SHOW_SETTINGS_KEY, "true");
|
|
2602
|
+
else localStorage.removeItem(SHOW_SETTINGS_KEY);
|
|
2603
|
+
}
|
|
2604
|
+
};
|
|
2605
|
+
(0, import_react9.useEffect)(() => {
|
|
2358
2606
|
const initial = scope.getSnapshot();
|
|
2359
2607
|
setSnapshot(initial);
|
|
2360
2608
|
setPending({});
|
|
2361
2609
|
if (initial.status === "ready") setFailed(false);
|
|
2362
2610
|
}, [scope]);
|
|
2363
|
-
(0,
|
|
2611
|
+
(0, import_react9.useEffect)(() => {
|
|
2364
2612
|
return scope.subscribe(() => {
|
|
2365
2613
|
const snap = scope.getSnapshot();
|
|
2366
2614
|
setSnapshot(snap);
|
|
@@ -2438,11 +2686,11 @@ function SchedulerSettingsCard({ scope, t }) {
|
|
|
2438
2686
|
setFieldPending(field.key, baselineValue(field), true);
|
|
2439
2687
|
setFailed(false);
|
|
2440
2688
|
};
|
|
2441
|
-
const handleDiscard = (0,
|
|
2689
|
+
const handleDiscard = (0, import_react9.useCallback)(() => {
|
|
2442
2690
|
setPending({});
|
|
2443
2691
|
setFailed(false);
|
|
2444
2692
|
}, []);
|
|
2445
|
-
const handleSave = (0,
|
|
2693
|
+
const handleSave = (0, import_react9.useCallback)(async () => {
|
|
2446
2694
|
if (!dirty || saving || !writable) return;
|
|
2447
2695
|
setSaving(true);
|
|
2448
2696
|
setFailed(false);
|
|
@@ -2478,8 +2726,32 @@ function SchedulerSettingsCard({ scope, t }) {
|
|
|
2478
2726
|
const confirmEnabled = (pending.confirmDelivery?.value ?? (value.confirmDelivery === false ? "false" : "true")) !== "false";
|
|
2479
2727
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "ss-settings-form", children: [
|
|
2480
2728
|
!writable && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "ss-hint", role: "status", children: t("readOnly") }),
|
|
2729
|
+
surface === "detail" && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "ss-section", "aria-labelledby": "ss-section-display-toggle", children: [
|
|
2730
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h3", { className: "ss-section-heading", id: "ss-section-display-toggle", children: t("sectionDisplayToggle") }),
|
|
2731
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "ss-section-fields", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "ss-field ss-fieldToggle", children: [
|
|
2732
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "ss-toggle-row", children: [
|
|
2733
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "ss-label-group", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("label", { className: "ss-toggle-label", htmlFor: "ss-show-settings", children: t("showInSettings") }) }),
|
|
2734
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
2735
|
+
"button",
|
|
2736
|
+
{
|
|
2737
|
+
type: "button",
|
|
2738
|
+
id: "ss-show-settings",
|
|
2739
|
+
role: "switch",
|
|
2740
|
+
"aria-checked": showSettings,
|
|
2741
|
+
"aria-label": t("showInSettings"),
|
|
2742
|
+
className: "ss-toggle-switch",
|
|
2743
|
+
onClick: toggleShowSettings
|
|
2744
|
+
}
|
|
2745
|
+
)
|
|
2746
|
+
] }),
|
|
2747
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "ss-toggle-description", children: t("showInSettingsHint") })
|
|
2748
|
+
] }) })
|
|
2749
|
+
] }),
|
|
2481
2750
|
SECTIONS.map((section) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("section", { className: "ss-section", "aria-labelledby": `ss-section-${section.id}`, children: [
|
|
2482
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.
|
|
2751
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("h3", { className: "ss-section-heading", id: `ss-section-${section.id}`, children: [
|
|
2752
|
+
t(section.titleKey),
|
|
2753
|
+
section.beta === true ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "ss-section-beta", "aria-label": t("betaBadgeAria"), children: t("betaBadge") }) : null
|
|
2754
|
+
] }),
|
|
2483
2755
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: section.layout === "grid" ? "ss-section-fields ss-section-fieldsGrid" : "ss-section-fields", children: section.fields.map((field) => {
|
|
2484
2756
|
const invalid = invalidField(field);
|
|
2485
2757
|
const isTime = field.kind === "time";
|
|
@@ -2538,11 +2810,7 @@ function SchedulerSettingsCard({ scope, t }) {
|
|
|
2538
2810
|
"aria-expanded": helpOpen[field.key] === true,
|
|
2539
2811
|
"aria-controls": `ss-help-${field.key}`,
|
|
2540
2812
|
onClick: () => setHelpOpen((prev) => ({ ...prev, [field.key]: !prev[field.key] })),
|
|
2541
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime5.
|
|
2542
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M12.5757 7.00012C12.5757 3.92085 10.0794 1.42463 7.00012 1.42456C3.9208 1.42456 1.42456 3.9208 1.42456 7.00012C1.42463 10.0794 3.92085 12.5757 7.00012 12.5757C10.0793 12.5756 12.5756 10.0793 12.5757 7.00012ZM13.8002 7.00012C13.8001 10.7559 10.7559 13.8001 7.00012 13.8002C3.2443 13.8002 0.199291 10.7559 0.199219 7.00012C0.199219 3.24426 3.24426 0.199219 7.00012 0.199219C10.7559 0.199291 13.8002 3.2443 13.8002 7.00012Z", fill: "currentColor" }),
|
|
2543
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M7.6127 3.18921V4.55986H6.38735V3.18921H7.6127Z", fill: "currentColor" }),
|
|
2544
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("path", { d: "M7.6127 5.68921V10.8109H6.38735V5.68921H7.6127Z", fill: "currentColor" })
|
|
2545
|
-
] })
|
|
2813
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_dsh_client_ui_primitives5.IconInfoOutlineRegular, { size: 12 })
|
|
2546
2814
|
}
|
|
2547
2815
|
)
|
|
2548
2816
|
] }),
|
|
@@ -3056,23 +3324,23 @@ function subscribeScheduleSummaryStore(listener) {
|
|
|
3056
3324
|
}
|
|
3057
3325
|
|
|
3058
3326
|
// src/client/useScheduleSummary.ts
|
|
3059
|
-
var
|
|
3327
|
+
var import_react10 = require("react");
|
|
3060
3328
|
var EMPTY_SUMMARY = /* @__PURE__ */ new Map();
|
|
3061
3329
|
var noopSubscribe2 = () => () => void 0;
|
|
3062
3330
|
var emptySnapshot = () => EMPTY_SUMMARY;
|
|
3063
3331
|
var missingSnapshot = () => void 0;
|
|
3064
3332
|
function useScheduleSummary(store) {
|
|
3065
|
-
const registered = (0,
|
|
3333
|
+
const registered = (0, import_react10.useSyncExternalStore)(subscribeScheduleSummaryStore, getScheduleSummaryStore, missingSnapshot);
|
|
3066
3334
|
const target = store ?? registered;
|
|
3067
|
-
const subscribe = (0,
|
|
3335
|
+
const subscribe = (0, import_react10.useMemo)(
|
|
3068
3336
|
() => target === void 0 ? noopSubscribe2 : (listener) => target.subscribe(listener),
|
|
3069
3337
|
[target]
|
|
3070
3338
|
);
|
|
3071
|
-
const getSnapshot = (0,
|
|
3339
|
+
const getSnapshot = (0, import_react10.useMemo)(
|
|
3072
3340
|
() => target === void 0 ? emptySnapshot : () => target.getSnapshot(),
|
|
3073
3341
|
[target]
|
|
3074
3342
|
);
|
|
3075
|
-
return (0,
|
|
3343
|
+
return (0, import_react10.useSyncExternalStore)(subscribe, getSnapshot, emptySnapshot);
|
|
3076
3344
|
}
|
|
3077
3345
|
|
|
3078
3346
|
// src/client/index.tsx
|
|
@@ -3122,6 +3390,11 @@ function apply(ctx) {
|
|
|
3122
3390
|
sectionDisplay: "\u663E\u793A\u8BBE\u7F6E",
|
|
3123
3391
|
sectionTime: "\u65F6\u95F4\u8BBE\u7F6E",
|
|
3124
3392
|
sectionDelivery: "\u6295\u9012\u8BBE\u7F6E",
|
|
3393
|
+
sectionAdvanced: "\u9AD8\u7EA7\u8BED\u6CD5",
|
|
3394
|
+
betaBadge: "Beta",
|
|
3395
|
+
betaBadgeAria: "Beta \u529F\u80FD\uFF0C\u884C\u4E3A\u53EF\u80FD\u968F\u7248\u672C\u8C03\u6574",
|
|
3396
|
+
advancedSyntaxLabel: "\u542F\u7528\u591A\u6B21\u5199\u6CD5\uFF08+1h*3 / 15:32+16:32\uFF09",
|
|
3397
|
+
advancedSyntaxHint: "\u8BA9 /later \u4E0E /schedule \u652F\u6301\u4E00\u6B21\u5199\u591A\u6761\uFF1A+1h*3\uFF08\u7B49\u95F4\u9694 3 \u6B21\uFF09\u3001+1h+1h+0.5h\uFF08\u76F8\u5BF9\u5E8F\u5217\uFF09\u300115:32+16:32 \u4E0E 9:00+1d\uFF08\u951A\u70B9\u5E8F\u5217\uFF0C\u6309\u5899\u949F\u63A8\u8FDB\uFF0C\u8DE8\u590F\u4EE4\u65F6\u4E0D\u6F02\uFF09\u3002\u6BCF\u6761\u90FD\u662F\u72EC\u7ACB\u4EFB\u52A1\uFF0C\u53EF\u5355\u72EC\u53D6\u6D88\u6216\u7F16\u8F91\uFF1B\u5355\u6B21\u6700\u591A 10 \u6761\u3002\u6807\u8BB0\u4E3A Beta\uFF1A\u5C55\u5F00\u540E\u7684\u89C2\u611F\u4E0E\u6761\u6570\u4E0A\u9650\u4ECD\u9700\u89C2\u5BDF\u3002",
|
|
3125
3398
|
showButtonLabel: "\u663E\u793A\u5B9A\u65F6\u6309\u94AE",
|
|
3126
3399
|
showButtonHint: "\u5173\u95ED\u540E\u8F93\u5165\u6846\u53F3\u4FA7\u4E0D\u518D\u663E\u793A\u65F6\u949F\u6309\u94AE\uFF1B\u5DF2\u521B\u5EFA\u7684\u63D0\u9192\u4ECD\u4F1A\u7167\u5E38\u89E6\u53D1\uFF0C\u5E76\u5728\u8F93\u5165\u6846\u4E0B\u65B9\u7684\u5F85\u53D1\u9001\u5217\u8868\u4E2D\u663E\u793A\u3002",
|
|
3127
3400
|
maxSchedulesLabel: "\u5355\u4F1A\u8BDD\u4EFB\u52A1\u4E0A\u9650",
|
|
@@ -3159,7 +3432,10 @@ function apply(ctx) {
|
|
|
3159
3432
|
discard: "\u653E\u5F03\u4FEE\u6539",
|
|
3160
3433
|
saveFailed: "\u4FDD\u5B58\u5931\u8D25\uFF0C\u8BF7\u91CD\u8BD5\u3002",
|
|
3161
3434
|
loading: "\u52A0\u8F7D\u4E2D\u2026",
|
|
3162
|
-
unavailable: "\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002"
|
|
3435
|
+
unavailable: "\u8BBE\u7F6E\u6682\u4E0D\u53EF\u7528\u3002",
|
|
3436
|
+
sectionDisplayToggle: "\u663E\u793A\u8BBE\u7F6E",
|
|
3437
|
+
showInSettings: "\u5728\u8BBE\u7F6E\u4E2D\u663E\u793A",
|
|
3438
|
+
showInSettingsHint: "\u5728\u8BBE\u7F6E\u5BF9\u8BDD\u6846\u4E2D\u663E\u793A\u672C\u63D2\u4EF6\u7684\u8BBE\u7F6E\u9875\uFF08\u5237\u65B0\u9875\u9762\u540E\u751F\u6548\uFF09"
|
|
3163
3439
|
},
|
|
3164
3440
|
en: {
|
|
3165
3441
|
title: "Session Scheduler",
|
|
@@ -3171,6 +3447,11 @@ function apply(ctx) {
|
|
|
3171
3447
|
sectionDisplay: "Display",
|
|
3172
3448
|
sectionTime: "Time windows",
|
|
3173
3449
|
sectionDelivery: "Delivery",
|
|
3450
|
+
sectionAdvanced: "Advanced syntax",
|
|
3451
|
+
betaBadge: "Beta",
|
|
3452
|
+
betaBadgeAria: "Beta feature; behaviour may change between versions",
|
|
3453
|
+
advancedSyntaxLabel: "Multi-shot syntax (+1h*3 / 15:32+16:32)",
|
|
3454
|
+
advancedSyntaxHint: "Let /later and /schedule create several tasks at once: +1h*3 (same interval N times), +1h+1h+0.5h (relative chain), 15:32+16:32 and 9:00+1d (anchored on a wall clock \u2014 it keeps the clock time across DST). Each occurrence is an independent task you can cancel or edit on its own; up to 10 per command. Marked Beta: the expanded result and the 10-task cap still need real-world observation.",
|
|
3174
3455
|
showButtonLabel: "Show schedule button",
|
|
3175
3456
|
showButtonHint: "Hide the clock button on the input bar. Existing reminders keep firing and stay visible in the dock below the composer.",
|
|
3176
3457
|
maxSchedulesLabel: "Max schedules per session",
|
|
@@ -3208,7 +3489,10 @@ function apply(ctx) {
|
|
|
3208
3489
|
discard: "Discard",
|
|
3209
3490
|
saveFailed: "Save failed, please try again.",
|
|
3210
3491
|
loading: "Loading\u2026",
|
|
3211
|
-
unavailable: "Settings unavailable."
|
|
3492
|
+
unavailable: "Settings unavailable.",
|
|
3493
|
+
sectionDisplayToggle: "Display",
|
|
3494
|
+
showInSettings: "Show in settings",
|
|
3495
|
+
showInSettingsHint: "Show this plugin's settings page in the settings dialog (refresh to take effect)"
|
|
3212
3496
|
}
|
|
3213
3497
|
}), "dsh-later: locale");
|
|
3214
3498
|
}
|
|
@@ -3253,11 +3537,17 @@ function apply(ctx) {
|
|
|
3253
3537
|
);
|
|
3254
3538
|
};
|
|
3255
3539
|
const cardT = locale === void 0 ? void 0 : locale.bind(NS);
|
|
3256
|
-
const cardDeclaration = (slot, scope) => ({
|
|
3540
|
+
const cardDeclaration = (slot, scope, surface = "detail") => ({
|
|
3257
3541
|
name: slot,
|
|
3542
|
+
id: SETTINGS_NS,
|
|
3543
|
+
order: 30,
|
|
3258
3544
|
key: SETTINGS_NS,
|
|
3259
3545
|
locale: NS,
|
|
3260
|
-
|
|
3546
|
+
label: () => {
|
|
3547
|
+
const active = locale === void 0 ? "zh" : locale.getSnapshot().active;
|
|
3548
|
+
return active === "en" ? "Session Scheduler" : "\u5B9A\u65F6\u63D0\u9192";
|
|
3549
|
+
},
|
|
3550
|
+
inject: () => ({ scope, t: cardT, surface })
|
|
3261
3551
|
});
|
|
3262
3552
|
ctx.inject(["settingsScope"], () => {
|
|
3263
3553
|
const binder = ctx.get("settingsScope");
|
|
@@ -3273,10 +3563,18 @@ function apply(ctx) {
|
|
|
3273
3563
|
};
|
|
3274
3564
|
mountComposer(scope);
|
|
3275
3565
|
if (cardT === void 0) return;
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3566
|
+
const SHOW_SETTINGS_KEY = "dsh-later:show-settings-section";
|
|
3567
|
+
const showSettingsSection = typeof localStorage !== "undefined" && localStorage.getItem(SHOW_SETTINGS_KEY) === "true";
|
|
3568
|
+
if (!showSettingsSection) return;
|
|
3569
|
+
const disposeSection = ctx.slots.inject(
|
|
3570
|
+
"settings.section",
|
|
3571
|
+
() => ctx.slots.register(cardDeclaration("settings.section", scope, "settings"), SchedulerSettingsCard)
|
|
3279
3572
|
);
|
|
3573
|
+
if (typeof disposeSection === "function") {
|
|
3574
|
+
ctx.effect(() => () => {
|
|
3575
|
+
disposeSection();
|
|
3576
|
+
});
|
|
3577
|
+
}
|
|
3280
3578
|
});
|
|
3281
3579
|
ctx.inject(["configForms"], () => {
|
|
3282
3580
|
const forms = ctx.get("configForms");
|
|
@@ -3297,11 +3595,23 @@ function apply(ctx) {
|
|
|
3297
3595
|
[ENTRY_ID],
|
|
3298
3596
|
() => ctx.slots.inject(
|
|
3299
3597
|
"plugins.bundle.config",
|
|
3300
|
-
() => ctx.slots.register(cardDeclaration("plugins.bundle.config", scope), SchedulerSettingsCard)
|
|
3598
|
+
() => ctx.slots.register(cardDeclaration("plugins.bundle.config", scope, "detail"), SchedulerSettingsCard)
|
|
3301
3599
|
)
|
|
3302
3600
|
),
|
|
3303
3601
|
"dsh-later: plugins-page card"
|
|
3304
3602
|
);
|
|
3603
|
+
const SHOW_SETTINGS_KEY = "dsh-later:show-settings-section";
|
|
3604
|
+
const showSettingsSection = typeof localStorage !== "undefined" && localStorage.getItem(SHOW_SETTINGS_KEY) === "true";
|
|
3605
|
+
if (!showSettingsSection) return;
|
|
3606
|
+
const disposeSection = ctx.slots.inject(
|
|
3607
|
+
"settings.section",
|
|
3608
|
+
() => ctx.slots.register(cardDeclaration("settings.section", scope, "settings"), SchedulerSettingsCard)
|
|
3609
|
+
);
|
|
3610
|
+
if (typeof disposeSection === "function") {
|
|
3611
|
+
ctx.effect(() => () => {
|
|
3612
|
+
disposeSection();
|
|
3613
|
+
});
|
|
3614
|
+
}
|
|
3305
3615
|
});
|
|
3306
3616
|
}
|
|
3307
3617
|
|