dsh-token-gauge 0.1.9 → 0.1.10
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/lib/client.mjs +58 -19
- package/package.json +1 -1
- package/src/client.ts +74 -29
package/lib/client.mjs
CHANGED
|
@@ -32,7 +32,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
32
32
|
var client_exports = {};
|
|
33
33
|
__export(client_exports, {
|
|
34
34
|
apply: () => apply,
|
|
35
|
-
inject: () => inject,
|
|
36
35
|
name: () => name
|
|
37
36
|
});
|
|
38
37
|
module.exports = __toCommonJS(client_exports);
|
|
@@ -1006,25 +1005,49 @@ var GaugeIcon = (size) => {
|
|
|
1006
1005
|
};
|
|
1007
1006
|
var TAB_ORDER = 90;
|
|
1008
1007
|
var name = PLUGIN_ID;
|
|
1009
|
-
|
|
1008
|
+
function findOurTab(snap) {
|
|
1009
|
+
if (!snap) return null;
|
|
1010
|
+
const trees = [snap.splits, snap.bottomSplits];
|
|
1011
|
+
for (const tree of trees) {
|
|
1012
|
+
if (!tree) continue;
|
|
1013
|
+
const stack = [tree];
|
|
1014
|
+
while (stack.length) {
|
|
1015
|
+
const node = stack.pop();
|
|
1016
|
+
if (!node) continue;
|
|
1017
|
+
if (Array.isArray(node.tabs)) {
|
|
1018
|
+
for (const t2 of node.tabs) if (t2 && t2.type === PLUGIN_ID) return t2;
|
|
1019
|
+
}
|
|
1020
|
+
if (Array.isArray(node.children)) stack.push(...node.children);
|
|
1021
|
+
if (node.splits) stack.push(node.splits);
|
|
1022
|
+
if (node.bottomSplits) stack.push(node.bottomSplits);
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
return null;
|
|
1026
|
+
}
|
|
1010
1027
|
function apply(ctx) {
|
|
1011
1028
|
let unregisterTab = null;
|
|
1012
|
-
let
|
|
1013
|
-
let
|
|
1029
|
+
let mountedOverlay = false;
|
|
1030
|
+
let slotsService = null;
|
|
1014
1031
|
let fallbackTimer = void 0;
|
|
1015
|
-
|
|
1016
|
-
|
|
1032
|
+
let openTimer = null;
|
|
1033
|
+
const stopSlots = ctx.inject(["slots"], (slotsCtx) => {
|
|
1034
|
+
slotsService = slotsCtx.slots;
|
|
1035
|
+
});
|
|
1036
|
+
const mountOverlay = (reason) => {
|
|
1037
|
+
if (mountedOverlay || unregisterTab) return;
|
|
1038
|
+
if (!slotsService || typeof slotsService.register !== "function") return;
|
|
1017
1039
|
console.warn(`[dsh-token-gauge] ${reason}\uFF0C\u4EEA\u8868\u76D8\u6539\u4E3A\u53F3\u4E0B\u89D2\u6D6E\u5C42\u663E\u793A\uFF08\u4ECD\u53EF\u7528\uFF09\u3002`);
|
|
1018
1040
|
try {
|
|
1019
|
-
|
|
1041
|
+
const d = slotsService.register(
|
|
1020
1042
|
{ name: "shell.overlay", id: PLUGIN_ID, order: 100, label: "Token \u4EEA\u8868\u76D8" },
|
|
1021
1043
|
() => import_react.default.createElement(GaugePanel)
|
|
1022
1044
|
);
|
|
1045
|
+
if (typeof d === "function") mountedOverlay = true;
|
|
1023
1046
|
} catch (e) {
|
|
1024
1047
|
console.error("[dsh-token-gauge] \u6D6E\u5C42\u515C\u5E95\u4E5F\u5931\u8D25", e);
|
|
1025
1048
|
}
|
|
1026
1049
|
};
|
|
1027
|
-
const
|
|
1050
|
+
const stopSidebar = ctx.inject(["betterSidebar"], (sidebarCtx) => {
|
|
1028
1051
|
const sidebar = sidebarCtx.betterSidebar;
|
|
1029
1052
|
if (!sidebar || typeof sidebar.registerTab !== "function") return;
|
|
1030
1053
|
unregisterTab = sidebar.registerTab({
|
|
@@ -1035,25 +1058,41 @@ function apply(ctx) {
|
|
|
1035
1058
|
icon: GaugeIcon,
|
|
1036
1059
|
component: () => import_react.default.createElement(GaugeTab)
|
|
1037
1060
|
});
|
|
1038
|
-
registeredViaBetter = true;
|
|
1039
1061
|
if (typeof fallbackTimer !== "undefined") clearTimeout(fallbackTimer);
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1062
|
+
let attempts = 0;
|
|
1063
|
+
openTimer = setInterval(() => {
|
|
1064
|
+
attempts++;
|
|
1065
|
+
const snap = sidebar.getSnapshot?.();
|
|
1066
|
+
const sid = snap?.sessionId;
|
|
1067
|
+
if (sid !== void 0 && typeof sidebar.openTab === "function") {
|
|
1068
|
+
try {
|
|
1069
|
+
sidebar.openTab({ type: PLUGIN_ID });
|
|
1070
|
+
} catch {
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
if (sid !== void 0 && findOurTab(snap)) {
|
|
1074
|
+
clearInterval(openTimer);
|
|
1075
|
+
openTimer = null;
|
|
1076
|
+
return;
|
|
1077
|
+
}
|
|
1078
|
+
if (attempts >= 45) {
|
|
1079
|
+
clearInterval(openTimer);
|
|
1080
|
+
openTimer = null;
|
|
1081
|
+
mountOverlay("better-sidebar \u5DF2\u6CE8\u518C\u4F46\u4F1A\u8BDD\u59CB\u7EC8\u672A\u5C31\u7EEA");
|
|
1082
|
+
}
|
|
1083
|
+
}, 800);
|
|
1044
1084
|
return () => {
|
|
1045
1085
|
if (unregisterTab) unregisterTab();
|
|
1046
1086
|
};
|
|
1047
1087
|
});
|
|
1048
1088
|
fallbackTimer = setTimeout(() => {
|
|
1049
|
-
if (!
|
|
1050
|
-
|
|
1051
|
-
}
|
|
1052
|
-
}, 3e4);
|
|
1089
|
+
if (!unregisterTab) mountOverlay("\u672A\u53D6\u5F97 dsh-better-sidebar \u670D\u52A1\uFF08\u8BF7\u786E\u8BA4\u5176\u5DF2\u5B89\u88C5\u5E76\u542F\u7528\uFF09");
|
|
1090
|
+
}, 8e3);
|
|
1053
1091
|
return () => {
|
|
1054
1092
|
if (typeof fallbackTimer !== "undefined") clearTimeout(fallbackTimer);
|
|
1055
|
-
if (
|
|
1056
|
-
if (typeof
|
|
1093
|
+
if (openTimer) clearInterval(openTimer);
|
|
1094
|
+
if (typeof stopSidebar === "function") stopSidebar();
|
|
1095
|
+
if (typeof stopSlots === "function") stopSlots();
|
|
1057
1096
|
};
|
|
1058
1097
|
}
|
|
1059
1098
|
; return module.exports; } });
|
package/package.json
CHANGED
package/src/client.ts
CHANGED
|
@@ -4,8 +4,9 @@
|
|
|
4
4
|
// 通过同域 HTTP 与 Host 半边通信:
|
|
5
5
|
// GET /plugins/dsh-token-gauge/state -> 完整 State(JSON)
|
|
6
6
|
// POST /plugins/dsh-token-gauge/cmd -> {type,payload} -> 更新后 State
|
|
7
|
-
// 优先把仪表盘注册到 dsh-better-sidebar 的右侧工作台 Tab
|
|
8
|
-
//
|
|
7
|
+
// 优先把仪表盘注册到 dsh-better-sidebar 的右侧工作台 Tab(停靠侧边栏),注册后轮询
|
|
8
|
+
// openTab 直到会话就绪并自动打开激活(解决“已挂载却未显示”:session 未就绪时 openTab
|
|
9
|
+
// 会静默 no-op);若 better-sidebar 始终不可用,回退到官方 shell.overlay 浮层兜底。
|
|
9
10
|
// 为避免与运行时 React 产生双实例 hook 冲突,本组件不调用任何 hook,
|
|
10
11
|
// 仅在 ref 回调里挂载一次原生 DOM 仪表盘,并自行轮询刷新。
|
|
11
12
|
// ============================================================================
|
|
@@ -275,34 +276,61 @@ const TAB_ORDER = 90
|
|
|
275
276
|
|
|
276
277
|
export const name = PLUGIN_ID
|
|
277
278
|
|
|
278
|
-
//
|
|
279
|
-
//
|
|
280
|
-
|
|
281
|
-
|
|
279
|
+
// 不声明顶层 inject(避免 pending 导致插件加载失败)。better-sidebar(兄弟 bundle 服务)
|
|
280
|
+
// 与 slots(框架级浮层服务)都用 apply 内的 ctx.inject 软注入回调按需获取。
|
|
281
|
+
|
|
282
|
+
// 在 better-sidebar 快照里查找我们的 Tab 是否已打开(按 type 判定,single 单例)。
|
|
283
|
+
function findOurTab(snap: any): any {
|
|
284
|
+
if (!snap) return null
|
|
285
|
+
const trees = [snap.splits, snap.bottomSplits]
|
|
286
|
+
for (const tree of trees) {
|
|
287
|
+
if (!tree) continue
|
|
288
|
+
const stack: any[] = [tree]
|
|
289
|
+
while (stack.length) {
|
|
290
|
+
const node = stack.pop()
|
|
291
|
+
if (!node) continue
|
|
292
|
+
if (Array.isArray(node.tabs)) {
|
|
293
|
+
for (const t of node.tabs) if (t && t.type === PLUGIN_ID) return t
|
|
294
|
+
}
|
|
295
|
+
if (Array.isArray(node.children)) stack.push(...node.children)
|
|
296
|
+
if (node.splits) stack.push(node.splits)
|
|
297
|
+
if (node.bottomSplits) stack.push(node.bottomSplits)
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return null
|
|
301
|
+
}
|
|
282
302
|
|
|
283
303
|
export function apply(ctx: any): (() => void) | void {
|
|
284
304
|
let unregisterTab: (() => void) | null = null
|
|
285
|
-
let
|
|
286
|
-
let
|
|
305
|
+
let mountedOverlay = false
|
|
306
|
+
let slotsService: any = null
|
|
287
307
|
let fallbackTimer: any = void 0
|
|
308
|
+
let openTimer: any = null
|
|
309
|
+
|
|
310
|
+
// 取得框架级 slots(仅用于浮层兜底)。若平台不提供 slots,浮层兜底不可用,但侧边栏主路径不受影响。
|
|
311
|
+
const stopSlots = ctx.inject(['slots'], (slotsCtx: any) => {
|
|
312
|
+
slotsService = slotsCtx.slots
|
|
313
|
+
})
|
|
288
314
|
|
|
289
|
-
// 浮层兜底:把仪表盘挂到官方 shell.overlay
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
if (
|
|
315
|
+
// 浮层兜底:把仪表盘挂到官方 shell.overlay(右下角 33vh),仅当 better-sidebar 不可用或会话始终未就绪时。
|
|
316
|
+
const mountOverlay = (reason: string): void => {
|
|
317
|
+
if (mountedOverlay || unregisterTab) return // 已注册到侧边栏则不再叠加浮层
|
|
318
|
+
if (!slotsService || typeof slotsService.register !== 'function') return
|
|
293
319
|
console.warn(`[dsh-token-gauge] ${reason},仪表盘改为右下角浮层显示(仍可用)。`)
|
|
294
320
|
try {
|
|
295
|
-
|
|
321
|
+
const d = slotsService.register(
|
|
296
322
|
{ name: 'shell.overlay', id: PLUGIN_ID, order: 100, label: 'Token 仪表盘' },
|
|
297
323
|
() => React.createElement(GaugePanel),
|
|
298
324
|
)
|
|
325
|
+
if (typeof d === 'function') mountedOverlay = true
|
|
299
326
|
} catch (e) {
|
|
300
327
|
console.error('[dsh-token-gauge] 浮层兜底也失败', e)
|
|
301
328
|
}
|
|
302
329
|
}
|
|
303
330
|
|
|
304
|
-
// 主路径:注册到 better-sidebar 右侧工作台 Tab
|
|
305
|
-
|
|
331
|
+
// 主路径:注册到 better-sidebar 右侧工作台 Tab(停靠侧边栏),并轮询 openTab 直到会话就绪,
|
|
332
|
+
// 让仪表盘自动打开并成为当前可见页(“已挂载但未显示”的根因是 session 未就绪时 openTab 静默 no-op)。
|
|
333
|
+
const stopSidebar = ctx.inject(['betterSidebar'], (sidebarCtx: any) => {
|
|
306
334
|
const sidebar = sidebarCtx.betterSidebar
|
|
307
335
|
if (!sidebar || typeof sidebar.registerTab !== 'function') return
|
|
308
336
|
unregisterTab = sidebar.registerTab({
|
|
@@ -313,29 +341,46 @@ export function apply(ctx: any): (() => void) | void {
|
|
|
313
341
|
icon: GaugeIcon,
|
|
314
342
|
component: () => React.createElement(GaugeTab),
|
|
315
343
|
})
|
|
316
|
-
registeredViaBetter = true
|
|
317
344
|
if (typeof fallbackTimer !== 'undefined') clearTimeout(fallbackTimer)
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
345
|
+
let attempts = 0
|
|
346
|
+
openTimer = setInterval(() => {
|
|
347
|
+
attempts++
|
|
348
|
+
const snap = sidebar.getSnapshot?.()
|
|
349
|
+
const sid = snap?.sessionId
|
|
350
|
+
// session 已就绪才尝试打开(未就绪时 openTab 会静默 no-op)
|
|
351
|
+
if (sid !== undefined && typeof sidebar.openTab === 'function') {
|
|
352
|
+
try {
|
|
353
|
+
sidebar.openTab({ type: PLUGIN_ID })
|
|
354
|
+
} catch {
|
|
355
|
+
/* ignore */
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
if (sid !== undefined && findOurTab(snap)) {
|
|
359
|
+
clearInterval(openTimer)
|
|
360
|
+
openTimer = null
|
|
361
|
+
return
|
|
362
|
+
}
|
|
363
|
+
if (attempts >= 45) {
|
|
364
|
+
// 约 36s 仍未打开(极端:会话始终未建立)→ 浮层兜底,保证可见
|
|
365
|
+
clearInterval(openTimer)
|
|
366
|
+
openTimer = null
|
|
367
|
+
mountOverlay('better-sidebar 已注册但会话始终未就绪')
|
|
368
|
+
}
|
|
369
|
+
}, 800)
|
|
324
370
|
return () => {
|
|
325
371
|
if (unregisterTab) unregisterTab()
|
|
326
372
|
}
|
|
327
373
|
})
|
|
328
374
|
|
|
329
|
-
// 兜底:
|
|
375
|
+
// 兜底:8s 内 better-sidebar 仍未就绪 → 浮层
|
|
330
376
|
fallbackTimer = setTimeout(() => {
|
|
331
|
-
if (!
|
|
332
|
-
|
|
333
|
-
}
|
|
334
|
-
}, 30000)
|
|
377
|
+
if (!unregisterTab) mountOverlay('未取得 dsh-better-sidebar 服务(请确认其已安装并启用)')
|
|
378
|
+
}, 8000)
|
|
335
379
|
|
|
336
380
|
return () => {
|
|
337
381
|
if (typeof fallbackTimer !== 'undefined') clearTimeout(fallbackTimer)
|
|
338
|
-
if (
|
|
339
|
-
if (typeof
|
|
382
|
+
if (openTimer) clearInterval(openTimer)
|
|
383
|
+
if (typeof stopSidebar === 'function') stopSidebar()
|
|
384
|
+
if (typeof stopSlots === 'function') stopSlots()
|
|
340
385
|
}
|
|
341
386
|
}
|