dsh-token-gauge 0.1.5 → 0.1.6

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 CHANGED
@@ -946,23 +946,82 @@ var gaugeRef = (el) => {
946
946
  function GaugeTab() {
947
947
  return import_react.default.createElement("div", { ref: gaugeRef, className: "tg-tab-root" });
948
948
  }
949
+ var GaugeIcon = (size) => {
950
+ const s = typeof size === "number" && size > 0 ? size : 16;
951
+ const svgProps = {
952
+ width: s,
953
+ height: s,
954
+ viewBox: "0 0 16 16",
955
+ fill: "none",
956
+ xmlns: "http://www.w3.org/2000/svg",
957
+ "aria-hidden": "true"
958
+ };
959
+ const arc = import_react.default.createElement("path", {
960
+ d: "M2.6 11.6a5.6 5.6 0 1 1 10.8 0",
961
+ stroke: "currentColor",
962
+ strokeWidth: 1.5,
963
+ strokeLinecap: "round"
964
+ });
965
+ const needle = import_react.default.createElement("path", {
966
+ d: "M8 11.6 10.4 7.2",
967
+ stroke: "currentColor",
968
+ strokeWidth: 1.5,
969
+ strokeLinecap: "round"
970
+ });
971
+ return import_react.default.createElement("svg", svgProps, arc, needle);
972
+ };
973
+ var TAB_ORDER = 90;
949
974
  var name = PLUGIN_ID;
950
975
  function apply(ctx) {
951
- const disposeSidebar = ctx.inject(["betterSidebar"], (sidebarCtx) => {
952
- const sidebar = sidebarCtx.betterSidebar;
953
- if (!sidebar || typeof sidebar.registerTab !== "function") return;
954
- const unregister = sidebar.registerTab({
955
- id: PLUGIN_ID,
956
- title: "Token \u4EEA\u8868\u76D8",
957
- single: true,
958
- component: GaugeTab
976
+ let registered = false;
977
+ let unregister = void 0;
978
+ const register = (sidebar) => {
979
+ if (registered || !sidebar || typeof sidebar.registerTab !== "function") return;
980
+ registered = true;
981
+ try {
982
+ unregister = sidebar.registerTab({
983
+ id: PLUGIN_ID,
984
+ title: "Token \u4EEA\u8868\u76D8",
985
+ single: true,
986
+ order: TAB_ORDER,
987
+ icon: GaugeIcon,
988
+ component: GaugeTab
989
+ });
990
+ } catch (e) {
991
+ registered = false;
992
+ }
993
+ };
994
+ let disposeInject = void 0;
995
+ try {
996
+ disposeInject = ctx.inject(["betterSidebar"], (sidebarCtx) => {
997
+ register(sidebarCtx && sidebarCtx.betterSidebar);
959
998
  });
960
- return () => {
961
- if (typeof unregister === "function") unregister();
962
- };
963
- });
999
+ } catch (e) {
1000
+ }
1001
+ const tryRead = () => {
1002
+ if (registered) return;
1003
+ try {
1004
+ const s = typeof ctx.get === "function" ? ctx.get("betterSidebar") : ctx.betterSidebar;
1005
+ register(s);
1006
+ } catch (e) {
1007
+ }
1008
+ };
1009
+ tryRead();
1010
+ let timer = void 0;
1011
+ if (!registered) {
1012
+ timer = setInterval(() => {
1013
+ tryRead();
1014
+ if (registered && timer !== void 0) clearInterval(timer);
1015
+ }, 500);
1016
+ }
1017
+ const stop = setTimeout(() => {
1018
+ if (timer !== void 0) clearInterval(timer);
1019
+ }, 3e4);
964
1020
  return () => {
965
- if (typeof disposeSidebar === "function") disposeSidebar();
1021
+ if (timer !== void 0) clearInterval(timer);
1022
+ clearTimeout(stop);
1023
+ if (typeof unregister === "function") unregister();
1024
+ if (typeof disposeInject === "function") disposeInject();
966
1025
  };
967
1026
  }
968
1027
  ; return module.exports; } });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-token-gauge",
3
- "version": "0.1.5",
3
+ "version": "0.1.6",
4
4
  "description": "DSH 机车风格 Token 用量/费用仪表盘侧边栏插件(稳定版 0.1.1-rc.x 兼容)",
5
5
  "type": "module",
6
6
  "main": "lib/index.mjs",
package/src/client.ts CHANGED
@@ -203,6 +203,39 @@ function GaugeTab(): React.ReactElement {
203
203
  return React.createElement('div', { ref: gaugeRef, className: 'tg-tab-root' })
204
204
  }
205
205
 
206
+ // 侧边栏图标:better-sidebar 以 `icon(size)` 形式调用(见其内置 tab:
207
+ // `icon: (size) => jsx(Icon, { size })`),故这里接收数字尺寸。用 currentColor
208
+ // 着色以自适应明暗主题,纯 SVG 零依赖。
209
+ const GaugeIcon = (size?: number): any => {
210
+ const s = typeof size === 'number' && size > 0 ? size : 16
211
+ const svgProps: any = {
212
+ width: s,
213
+ height: s,
214
+ viewBox: '0 0 16 16',
215
+ fill: 'none',
216
+ xmlns: 'http://www.w3.org/2000/svg',
217
+ 'aria-hidden': 'true',
218
+ }
219
+ // 仪表盘弧 + 指针
220
+ const arc = React.createElement('path', {
221
+ d: 'M2.6 11.6a5.6 5.6 0 1 1 10.8 0',
222
+ stroke: 'currentColor',
223
+ strokeWidth: 1.5,
224
+ strokeLinecap: 'round',
225
+ })
226
+ const needle = React.createElement('path', {
227
+ d: 'M8 11.6 10.4 7.2',
228
+ stroke: 'currentColor',
229
+ strokeWidth: 1.5,
230
+ strokeLinecap: 'round',
231
+ })
232
+ return React.createElement('svg', svgProps, arc, needle)
233
+ }
234
+
235
+ // 在「+ 新建 Tab」菜单里的排序位。内置 tab 用 20/91/110 等,order 缺省为 100
236
+ // 会排到菜单最底部不易发现,这里显式给一个偏前的值。
237
+ const TAB_ORDER = 90
238
+
206
239
  export const name = PLUGIN_ID
207
240
 
208
241
  // 兄弟 bundle 提供的服务(betterSidebar)在本机这个 cordis 里两种读法都不行,必须用
@@ -221,22 +254,66 @@ export const name = PLUGIN_ID
221
254
  // 合法属性,读它不触发守卫;且注册被延迟到服务就绪那一刻(兄弟 bundle 提供得早或晚
222
255
  // 都能注册上)。生态插件 @linxin666/dsh-client-ui-aionui-panel 用的正是这个模式。
223
256
  export function apply(ctx: any): (() => void) | void {
224
- const disposeSidebar = ctx.inject(['betterSidebar'], (sidebarCtx: any) => {
225
- const sidebar = sidebarCtx.betterSidebar
226
- if (!sidebar || typeof sidebar.registerTab !== 'function') return
227
- const unregister = sidebar.registerTab({
228
- id: PLUGIN_ID,
229
- title: 'Token 仪表盘',
230
- single: true,
231
- component: GaugeTab,
257
+ let registered = false
258
+ let unregister: unknown = void 0
259
+
260
+ // 注册一次即止(registerTab 对重复 id 会抛 "already registered")
261
+ const register = (sidebar: any): void => {
262
+ if (registered || !sidebar || typeof sidebar.registerTab !== 'function') return
263
+ registered = true
264
+ try {
265
+ unregister = sidebar.registerTab({
266
+ id: PLUGIN_ID,
267
+ title: 'Token 仪表盘',
268
+ single: true,
269
+ order: TAB_ORDER,
270
+ icon: GaugeIcon,
271
+ component: GaugeTab,
272
+ })
273
+ } catch (e) {
274
+ registered = false // 失败则允许后续重试
275
+ }
276
+ }
277
+
278
+ // 主路径:ctx.inject 回调——服务就绪时触发,回调内读 sidebarCtx.betterSidebar 合法
279
+ let disposeInject: unknown = void 0
280
+ try {
281
+ disposeInject = ctx.inject(['betterSidebar'], (sidebarCtx: any) => {
282
+ register(sidebarCtx && sidebarCtx.betterSidebar)
232
283
  })
233
- return () => {
234
- if (typeof unregister === 'function') unregister()
284
+ } catch (e) {
285
+ /* 运行时无 ctx.inject:交由下面的轮询兜底 */
286
+ }
287
+
288
+ // 兜底:轮询读取。0811 严格注入下未声明 inject 时 ctx.get('betterSidebar')
289
+ // 会「抛异常」(而非返回 undefined),所以必须用 try/catch 包住读取。
290
+ const tryRead = (): void => {
291
+ if (registered) return
292
+ try {
293
+ const s = typeof ctx.get === 'function' ? ctx.get('betterSidebar') : ctx.betterSidebar
294
+ register(s)
295
+ } catch (e) {
296
+ /* 服务此刻不可达,下一轮再试 */
235
297
  }
236
- })
298
+ }
299
+ tryRead()
300
+
301
+ let timer: unknown = void 0
302
+ if (!registered) {
303
+ timer = setInterval(() => {
304
+ tryRead()
305
+ if (registered && timer !== void 0) clearInterval(timer as number)
306
+ }, 500)
307
+ }
308
+ const stop = setTimeout(() => {
309
+ if (timer !== void 0) clearInterval(timer as number)
310
+ }, 30000)
237
311
 
238
- // 返回插件级 disposer:卸载时一并撤掉未完成的注入
312
+ // 插件级 disposer
239
313
  return () => {
240
- if (typeof disposeSidebar === 'function') disposeSidebar()
314
+ if (timer !== void 0) clearInterval(timer as number)
315
+ clearTimeout(stop)
316
+ if (typeof unregister === 'function') (unregister as () => void)()
317
+ if (typeof disposeInject === 'function') (disposeInject as () => void)()
241
318
  }
242
319
  }