@jxgame2020/dsh-token-quota 0.1.30 → 0.1.32

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.js CHANGED
@@ -37,6 +37,7 @@ window.__ModuleLoader__.load({
37
37
  onFull: "stop",
38
38
  checkUpdates: true,
39
39
  dimWhenIdle: false,
40
+ order: [],
40
41
  musicEnabled: false,
41
42
  musicVolume: .5,
42
43
  musicStyle: "pentatonic",
@@ -82,6 +83,9 @@ window.__ModuleLoader__.load({
82
83
  setDimWhenIdle: (d, dimWhenIdle) => {
83
84
  d.dimWhenIdle = dimWhenIdle;
84
85
  },
86
+ setOrder: (d, order) => {
87
+ d.order = order;
88
+ },
85
89
  setMusicEnabled: (d, enabled) => {
86
90
  d.musicEnabled = enabled;
87
91
  },
@@ -95,7 +99,7 @@ window.__ModuleLoader__.load({
95
99
  d.musicOnlyCurrentSession = only;
96
100
  },
97
101
  setUpgrade: (d, upgrade) => {
98
- const normalized = upgrade !== null && upgrade.latestVersion !== "" && upgrade.latestVersion !== "0.1.30" ? upgrade : null;
102
+ const normalized = upgrade !== null && upgrade.latestVersion !== "" && upgrade.latestVersion !== "0.1.32" ? upgrade : null;
99
103
  if (d.upgrade === null || d.upgrade.latestVersion !== normalized?.latestVersion) d.upgradeDismissed = false;
100
104
  d.upgrade = normalized;
101
105
  },
@@ -157,9 +161,11 @@ window.__ModuleLoader__.load({
157
161
  * @param groups - advisory provider groups of the current session.
158
162
  * @param snapshot - latest quota snapshot, or null before the first one.
159
163
  * @param current - current model selection reported by the Host.
160
- * @returns rows sorted by key.
164
+ * @param order - user's drag-to-reorder preference (model keys); listed keys
165
+ * come first in that exact order, the rest follow in catalog order.
166
+ * @returns rows in display order.
161
167
  */
162
- function mergeModelRows(groups, snapshot, current) {
168
+ function mergeModelRows(groups, snapshot, current, order = []) {
163
169
  const entryByKey = new Map((snapshot?.entries ?? []).map((entry) => [entry.key, entry]));
164
170
  const rows = /* @__PURE__ */ new Map();
165
171
  for (const group of groups) for (const model of group.models) {
@@ -187,11 +193,33 @@ window.__ModuleLoader__.load({
187
193
  current: current !== null && current.provider === entry.provider && current.model === entry.model
188
194
  });
189
195
  }
190
- return [...rows.values()].sort((left, right) => left.key.localeCompare(right.key));
196
+ const rank = new Map(order.map((key, index) => [key, index]));
197
+ return [...rows.values()].sort((left, right) => {
198
+ const leftRank = rank.get(left.key);
199
+ const rightRank = rank.get(right.key);
200
+ if (leftRank !== void 0 && rightRank !== void 0) return leftRank - rightRank;
201
+ if (leftRank !== void 0) return -1;
202
+ if (rightRank !== void 0) return 1;
203
+ return left.key.localeCompare(right.key);
204
+ });
205
+ }
206
+ /**
207
+ * Move one key to another key's position, returning the full reordered key
208
+ * list (the shape persisted in the settings document's `order`).
209
+ */
210
+ function reorderKeys(keys, from, to) {
211
+ const next = [...keys];
212
+ const fromIndex = next.indexOf(from);
213
+ const toIndex = next.indexOf(to);
214
+ if (fromIndex < 0 || toIndex < 0 || fromIndex === toIndex) return next;
215
+ const [moved] = next.splice(fromIndex, 1);
216
+ if (moved === void 0) return next;
217
+ next.splice(toIndex, 0, moved);
218
+ return next;
191
219
  }
192
220
  //#endregion
193
221
  //#region \0dsh-css:/Users/jxgame/Desktop/works/deepseek-harness-package/dsh-token-quota/packages/token-quota/src/client/TokenQuotaPanel.module.css.mjs
194
- const css = ".NPLLIq_panel{box-sizing:border-box;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);pointer-events:auto;z-index:40;opacity:1;border-radius:12px;flex-direction:column;width:320px;max-height:min(72vh,560px);transition:opacity .18s;display:flex;position:fixed;top:56px;right:12px;overflow:hidden;box-shadow:0 8px 28px #0000002e}.NPLLIq_panelDim{opacity:.55}.NPLLIq_panelDimStrong{opacity:.3}.NPLLIq_header{border-bottom:1px solid var(--dsw-alias-border-l1);cursor:grab;user-select:none;touch-action:none;justify-content:space-between;align-items:flex-start;gap:8px;padding:10px 12px;display:flex}.NPLLIq_header:active{cursor:grabbing}.NPLLIq_headerText{flex-direction:column;gap:2px;min-width:0;display:flex}.NPLLIq_title{color:var(--dsw-alias-label-primary);align-items:baseline;gap:6px;font-size:13px;font-weight:600;display:flex}.NPLLIq_version{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:10px;font-weight:500}.NPLLIq_versionNew{color:var(--dsw-alias-status-warning-foreground,#b56900);background:var(--dsw-alias-status-warning-background,#fff6d7);cursor:default;border-radius:4px;padding:1px 6px}.NPLLIq_subtitle{color:var(--dsw-alias-label-secondary);font-size:11px}.NPLLIq_collapse{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;flex:none;padding:2px 6px;font-size:11px}.NPLLIq_collapse:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_body{padding:4px 0;overflow-y:auto}.NPLLIq_row{border-bottom:1px solid var(--dsw-alias-border-l1);flex-direction:column;gap:6px;padding:8px 12px;display:flex}.NPLLIq_rowHeader{justify-content:space-between;align-items:center;gap:8px;display:flex}.NPLLIq_rowName{color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;align-items:center;gap:6px;font-size:12px;font-weight:500;display:inline-flex;overflow:hidden}.NPLLIq_currentBadge{color:var(--dsw-alias-state-success-primary);border:1px solid var(--dsw-alias-state-success-primary);border-radius:8px;flex:none;padding:1px 6px;font-size:10px}.NPLLIq_rowMeta{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;font-size:11px}.NPLLIq_bar{background:var(--dsw-alias-bg-layer-1);border-radius:3px;height:6px;overflow:hidden}.NPLLIq_fillIdle{background:var(--dsw-alias-brand-primary);height:100%;transition:width .2s}.NPLLIq_fillWarn{background:var(--dsw-alias-state-warn-primary);height:100%;transition:width .2s}.NPLLIq_fillOver{background:var(--dsw-alias-state-error-primary);height:100%;transition:width .2s}.NPLLIq_controls{align-items:center;gap:6px;display:flex}.NPLLIq_input{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;color:var(--dsw-alias-label-primary);border-radius:6px;flex:1;padding:4px 8px;font-size:11px}.NPLLIq_input::placeholder{color:var(--dsw-alias-label-secondary)}.NPLLIq_save,.NPLLIq_switch{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;flex:none;padding:4px 10px;font-size:11px}.NPLLIq_save:hover,.NPLLIq_switch:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2)}.NPLLIq_switch:disabled{opacity:.5;cursor:default}.NPLLIq_notice,.NPLLIq_noticeError{color:var(--dsw-alias-label-secondary);padding:10px 12px;font-size:12px}.NPLLIq_noticeError{color:var(--dsw-alias-state-error-primary)}.NPLLIq_tab{background:var(--dsw-alias-brand-primary);border:1px solid var(--dsw-alias-brand-primary);color:var(--dsw-alias-bg-overlay);pointer-events:auto;cursor:pointer;z-index:90;border-radius:10px;align-items:center;gap:6px;padding:9px 14px;font-size:12px;font-weight:600;display:inline-flex;position:fixed;top:56px;right:12px;box-shadow:0 6px 20px #00000040}.NPLLIq_tab:hover{filter:brightness(1.08)}.NPLLIq_tabIcon{font-size:12px;line-height:1}.NPLLIq_tabLabel{white-space:nowrap}.NPLLIq_headerActions{flex:none;align-items:center;gap:4px;display:flex}.NPLLIq_settingsBtn{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;flex:none;padding:2px 6px;font-size:11px}.NPLLIq_settingsBtn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_settingsBtnActive{color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-2,#0000000f);box-shadow:inset 0 0 0 1px var(--dsw-alias-brand-primary);font-weight:700}.NPLLIq_selectBtn{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-brand-primary);cursor:pointer;background:0 0;border-radius:6px;flex:none;padding:1px 6px;font-size:10px}.NPLLIq_selectBtn:hover{background:var(--dsw-alias-bg-layer-1)}.NPLLIq_gearBtn{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;flex:none;margin-left:6px;padding:0 2px;font-size:12px;line-height:1}.NPLLIq_gearBtn:hover{color:var(--dsw-alias-label-primary)}.NPLLIq_fullNotice{color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-state-error-primary);border-radius:8px;margin:6px 12px;padding:8px 10px;font-size:12px}.NPLLIq_upgradeBanner{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-divider-1,#0000001a);border-radius:8px;margin:6px 12px;padding:10px 30px 10px 10px;font-size:12px;position:relative}@keyframes NPLLIq_upgradeBannerFlash{0%,to{border-color:var(--dsw-alias-divider-1,#0000001a);box-shadow:0 0 #f0a02000}50%{border-color:var(--dsw-alias-status-warning-foreground,#b56900);box-shadow:0 0 0 5px #f0a02073}}.NPLLIq_upgradeBannerFlash{border-color:var(--dsw-alias-status-warning-foreground,#b56900);animation:.6s ease-in-out 4 NPLLIq_upgradeBannerFlash}.NPLLIq_upgradeBannerText{margin-bottom:6px;font-weight:600}.NPLLIq_upgradeCommands{flex-direction:column;gap:4px;display:flex}.NPLLIq_upgradeCommandRow{align-items:center;gap:6px;display:flex}.NPLLIq_upgradeCommand{background:var(--dsw-alias-bg-layer-2,#0000000a);white-space:nowrap;border-radius:4px;flex:1;min-width:0;padding:4px 6px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;overflow-x:auto}.NPLLIq_copyBtn{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-2,#0000000a);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:4px;flex:none;padding:3px 8px;font-size:11px;transition:transform 80ms,background .12s,color .12s}.NPLLIq_copyBtn:hover{background:var(--dsw-alias-bg-layer-3,#00000014)}.NPLLIq_copyBtn:active{transform:scale(.92)}.NPLLIq_copyBtnDone{background:var(--dsw-alias-status-success-background,#14963c1f);border-color:var(--dsw-alias-status-success-foreground,#0a7d32);color:var(--dsw-alias-status-success-foreground,#0a7d32);font-weight:600}.NPLLIq_upgradeHint{color:var(--dsw-alias-label-secondary);margin-top:6px;font-size:11px}.NPLLIq_upgradeClose{width:20px;height:20px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;font-size:16px;line-height:1;position:absolute;top:4px;right:6px}.NPLLIq_upgradeClose:hover{background:var(--dsw-alias-bg-layer-2,#0000000a);color:var(--dsw-alias-label-primary)}.NPLLIq_checkUpdatesRow{justify-content:space-between;align-items:center;gap:12px;display:flex}.NPLLIq_checkUpdatesLabel{color:var(--dsw-alias-label-primary);cursor:pointer;align-items:center;gap:6px;font-size:12px;display:flex}.NPLLIq_checkUpdatesLabel input{margin:0}.NPLLIq_checkUpdatesLabel input[type=range]{min-width:90px;accent-color:var(--dsw-alias-brand-primary);flex:1}.NPLLIq_checkUpdatesLabel select{background:var(--dsw-alias-bg-layer-2,#0000000a);min-width:90px;color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-divider-1,#00000026);border-radius:4px;flex:1;padding:2px 4px;font-size:12px}.NPLLIq_checkBtn{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-2,#0000000a);color:var(--dsw-alias-label-primary);cursor:pointer;white-space:nowrap;text-align:center;border-radius:4px;flex:none;min-width:72px;padding:4px 10px;font-size:12px}.NPLLIq_checkBtn:hover:not(:disabled){background:var(--dsw-alias-bg-layer-3,#00000014)}.NPLLIq_checkBtn:disabled{opacity:.6;cursor:default}.NPLLIq_checkErrorHint{color:var(--dsw-alias-state-error-primary,#c00);background:var(--dsw-alias-state-error-background,#ff00000f);border:1px solid var(--dsw-alias-state-error-border,#b4000040);word-break:break-all;border-radius:6px;margin-top:8px;padding:6px 8px;font-size:11px;line-height:1.4}.NPLLIq_dialog{z-index:100;box-sizing:border-box;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;flex-direction:column;gap:12px;width:430px;max-width:94vw;max-height:80vh;padding:14px;display:flex;position:fixed;top:50%;left:50%;overflow-y:auto;transform:translate(-50%,-50%);box-shadow:0 8px 28px #00000040}.NPLLIq_dialogTabs{border-bottom:1px solid var(--dsw-alias-divider-1,#00000014);gap:2px;margin:-6px -14px 0;padding:0 14px;display:flex}.NPLLIq_dialogTab{appearance:none;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;padding:6px 12px 8px;font-size:12px}.NPLLIq_dialogTab:hover{color:var(--dsw-alias-label-primary)}.NPLLIq_dialogTabActive{color:var(--dsw-alias-brand-primary);border-bottom-color:var(--dsw-alias-brand-primary);font-weight:600}.NPLLIq_dialogTitle{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600}.NPLLIq_dialogSection{flex-direction:column;gap:6px;display:flex}.NPLLIq_dialogLabel{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:500}.NPLLIq_monitorHint{color:var(--dsw-alias-label-secondary);font-size:11px}.NPLLIq_dialogHint{color:var(--dsw-alias-label-secondary);margin-top:4px;font-size:11px;line-height:1.4}.NPLLIq_monitorList{flex-direction:column;gap:2px;max-height:180px;display:flex;overflow-y:auto}.NPLLIq_monitorRow{color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;align-items:center;gap:6px;padding:2px 4px;font-size:12px;display:flex}.NPLLIq_monitorRow:hover{background:var(--dsw-alias-bg-layer-1)}.NPLLIq_monitorName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.NPLLIq_radioRow{color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;align-items:center;gap:6px;padding:3px 4px;font-size:12px;display:flex}.NPLLIq_radioRow:hover{background:var(--dsw-alias-bg-layer-1)}.NPLLIq_dialogActions{justify-content:flex-end;gap:6px;display:flex}.NPLLIq_dialogBtn,.NPLLIq_dialogBtnPrimary{border:1px solid var(--dsw-alias-border-l1);cursor:pointer;border-radius:6px;padding:4px 12px;font-size:11px}.NPLLIq_dialogBtn{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}.NPLLIq_dialogBtnPrimary{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-bg-overlay)}.NPLLIq_dialogHeader{z-index:2;background:var(--dsw-alias-bg-overlay);cursor:grab;user-select:none;touch-action:none;justify-content:space-between;align-items:center;gap:8px;margin:-14px -14px 0;padding:14px 14px 8px;display:flex;position:sticky;top:-14px}.NPLLIq_dialogHeader:active{cursor:grabbing}.NPLLIq_dialogClose{width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px;flex:none;justify-content:center;align-items:center;font-size:18px;line-height:1;display:flex}.NPLLIq_dialogClose:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_resetRow{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.NPLLIq_resetSelect{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:6px;padding:3px 6px;font-size:12px}.NPLLIq_logTable{border-collapse:collapse;width:100%;font-size:11px}.NPLLIq_logTable th{text-align:left;color:var(--dsw-alias-label-secondary);border-bottom:1px solid var(--dsw-alias-border-l1);padding:4px 6px;font-weight:500}.NPLLIq_logTable td{color:var(--dsw-alias-label-primary);border-bottom:1px solid var(--dsw-alias-border-l1);font-variant-numeric:tabular-nums;padding:4px 6px}.NPLLIq_logDayCol{white-space:nowrap;color:var(--dsw-alias-label-secondary)}.NPLLIq_logModelCol{text-overflow:ellipsis;white-space:nowrap;max-width:160px;overflow:hidden}.NPLLIq_logUsedCol{text-align:right}.NPLLIq_logDialog{gap:0;width:380px;max-height:min(72vh,480px);padding:0}.NPLLIq_logHeader{background:var(--dsw-alias-bg-overlay);cursor:grab;user-select:none;touch-action:none;flex:none;justify-content:space-between;align-items:center;gap:8px;padding:14px 14px 8px;display:flex}.NPLLIq_logHeader:active{cursor:grabbing}.NPLLIq_logScroll{flex:1;min-height:0;padding:0 14px 14px;overflow:auto}.NPLLIq_logToolbar{flex:1;align-items:center;gap:6px;display:flex}.NPLLIq_logSearch{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);min-width:0;color:var(--dsw-alias-label-primary);border-radius:4px;flex:1;padding:3px 6px;font-size:11px}.NPLLIq_logSearch:focus{border-color:var(--dsw-alias-accent-1,#4a9eff);outline:none}.NPLLIq_logClearBtn{border:1px solid var(--dsw-alias-state-error-border,#b400004d);color:var(--dsw-alias-state-error-primary,#c00);cursor:pointer;white-space:nowrap;background:0 0;border-radius:4px;flex:none;padding:3px 8px;font-size:11px}.NPLLIq_logClearBtn:hover{background:var(--dsw-alias-state-error-background,#ff00000f)}.NPLLIq_logPager{border-top:1px solid var(--dsw-alias-divider-1,#00000014);background:var(--dsw-alias-bg-overlay);color:var(--dsw-alias-label-secondary);flex:none;justify-content:space-between;align-items:center;gap:8px;padding:6px 14px;font-size:11px;display:flex}.NPLLIq_logPagerInfo{white-space:nowrap}.NPLLIq_logPagerControls{align-items:center;gap:4px;display:flex}.NPLLIq_logPagerBtn{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);width:24px;height:24px;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:4px;font-size:13px;line-height:1}.NPLLIq_logPagerBtn:disabled{opacity:.4;cursor:default}.NPLLIq_logPagerPages{text-align:center;min-width:50px;color:var(--dsw-alias-label-secondary)}.NPLLIq_logPageSizeSelect{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:4px;padding:2px 4px;font-size:11px}.NPLLIq_dialogOverlay{z-index:100001;background:#0000004d;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.NPLLIq_logClearDialog{gap:0;width:320px;padding:16px}.NPLLIq_dialogBody{color:var(--dsw-alias-label-secondary);margin:6px 0 10px;font-size:12px;line-height:1.5}.NPLLIq_logClearDate{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);width:100%;color:var(--dsw-alias-label-primary);border-radius:6px;margin-bottom:12px;padding:6px 8px;font-size:13px}.NPLLIq_logClearDate:focus{border-color:var(--dsw-alias-accent-1,#4a9eff);outline:none}";
222
+ const css = ".NPLLIq_panel{box-sizing:border-box;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);pointer-events:auto;z-index:40;opacity:1;border-radius:12px;flex-direction:column;width:320px;max-height:min(72vh,560px);transition:opacity .18s;display:flex;position:fixed;top:56px;right:12px;overflow:hidden;box-shadow:0 8px 28px #0000002e}.NPLLIq_panelDim{opacity:.55}.NPLLIq_panelDimStrong{opacity:.3}.NPLLIq_header{border-bottom:1px solid var(--dsw-alias-border-l1);cursor:grab;user-select:none;touch-action:none;justify-content:space-between;align-items:flex-start;gap:8px;padding:10px 12px;display:flex}.NPLLIq_header:active{cursor:grabbing}.NPLLIq_headerText{flex-direction:column;gap:2px;min-width:0;display:flex}.NPLLIq_title{color:var(--dsw-alias-label-primary);align-items:baseline;gap:6px;font-size:13px;font-weight:600;display:flex}.NPLLIq_version{color:var(--dsw-alias-label-secondary);white-space:nowrap;font-size:10px;font-weight:500}.NPLLIq_versionNew{color:var(--dsw-alias-status-warning-foreground,#b56900);background:var(--dsw-alias-status-warning-background,#fff6d7);cursor:default;border-radius:4px;padding:1px 6px}.NPLLIq_subtitle{color:var(--dsw-alias-label-secondary);font-size:11px}.NPLLIq_collapse{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;flex:none;padding:2px 6px;font-size:11px}.NPLLIq_collapse:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_body{padding:4px 0;overflow-y:auto}.NPLLIq_row{border-bottom:1px solid var(--dsw-alias-border-l1);flex-direction:column;gap:6px;padding:8px 12px;display:flex}.NPLLIq_rowHeader{justify-content:space-between;align-items:center;gap:8px;display:flex}.NPLLIq_rowDrag{cursor:grab;color:var(--dsw-alias-label-secondary);user-select:none;border-radius:4px;flex:none;margin-right:2px;padding:2px 3px;font-size:11px;line-height:1}.NPLLIq_rowDrag:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_rowDrag:active{cursor:grabbing}.NPLLIq_rowDragging{opacity:.45}.NPLLIq_rowDropTarget{box-shadow:inset 0 2px 0 var(--dsw-alias-brand-primary)}.NPLLIq_rowName{min-width:0;color:var(--dsw-alias-label-primary);text-overflow:ellipsis;white-space:nowrap;flex:1;align-items:center;gap:6px;font-size:12px;font-weight:500;display:inline-flex;overflow:hidden}.NPLLIq_currentBadge{color:var(--dsw-alias-state-success-primary);border:1px solid var(--dsw-alias-state-success-primary);border-radius:8px;flex:none;padding:1px 6px;font-size:10px}.NPLLIq_rowMeta{color:var(--dsw-alias-label-secondary);font-variant-numeric:tabular-nums;flex:none;font-size:11px}.NPLLIq_bar{background:var(--dsw-alias-bg-layer-1);border-radius:3px;height:6px;overflow:hidden}.NPLLIq_fillIdle{background:var(--dsw-alias-brand-primary);height:100%;transition:width .2s}.NPLLIq_fillWarn{background:var(--dsw-alias-state-warn-primary);height:100%;transition:width .2s}.NPLLIq_fillOver{background:var(--dsw-alias-state-error-primary);height:100%;transition:width .2s}.NPLLIq_controls{align-items:center;gap:6px;display:flex}.NPLLIq_input{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);min-width:0;color:var(--dsw-alias-label-primary);border-radius:6px;flex:1;padding:4px 8px;font-size:11px}.NPLLIq_input::placeholder{color:var(--dsw-alias-label-secondary)}.NPLLIq_save,.NPLLIq_switch{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;flex:none;padding:4px 10px;font-size:11px}.NPLLIq_save:hover,.NPLLIq_switch:hover:not(:disabled){background:var(--dsw-alias-bg-layer-2)}.NPLLIq_switch:disabled{opacity:.5;cursor:default}.NPLLIq_notice,.NPLLIq_noticeError{color:var(--dsw-alias-label-secondary);padding:10px 12px;font-size:12px}.NPLLIq_noticeError{color:var(--dsw-alias-state-error-primary)}.NPLLIq_tab{background:var(--dsw-alias-brand-primary);border:1px solid var(--dsw-alias-brand-primary);color:var(--dsw-alias-bg-overlay);pointer-events:auto;cursor:pointer;z-index:90;border-radius:10px;align-items:center;gap:6px;padding:9px 14px;font-size:12px;font-weight:600;display:inline-flex;position:fixed;top:56px;right:12px;box-shadow:0 6px 20px #00000040}.NPLLIq_tab:hover{filter:brightness(1.08)}.NPLLIq_tabIcon{font-size:12px;line-height:1}.NPLLIq_tabLabel{white-space:nowrap}.NPLLIq_headerActions{flex:none;align-items:center;gap:4px;display:flex}.NPLLIq_settingsBtn{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:6px;flex:none;padding:2px 6px;font-size:11px}.NPLLIq_settingsBtn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_settingsBtnActive{color:var(--dsw-alias-brand-primary);background:var(--dsw-alias-bg-layer-2,#0000000f);box-shadow:inset 0 0 0 1px var(--dsw-alias-brand-primary);font-weight:700}.NPLLIq_selectBtn{border:1px solid var(--dsw-alias-border-l1);color:var(--dsw-alias-brand-primary);cursor:pointer;background:0 0;border-radius:6px;flex:none;padding:1px 6px;font-size:10px}.NPLLIq_selectBtn:hover{background:var(--dsw-alias-bg-layer-1)}.NPLLIq_gearBtn{color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;flex:none;margin-left:6px;padding:0 2px;font-size:12px;line-height:1}.NPLLIq_gearBtn:hover{color:var(--dsw-alias-label-primary)}.NPLLIq_fullNotice{color:var(--dsw-alias-state-error-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-state-error-primary);border-radius:8px;margin:6px 12px;padding:8px 10px;font-size:12px}.NPLLIq_upgradeBanner{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-divider-1,#0000001a);border-radius:8px;margin:6px 12px;padding:10px 30px 10px 10px;font-size:12px;position:relative}@keyframes NPLLIq_upgradeBannerFlash{0%,to{border-color:var(--dsw-alias-divider-1,#0000001a);box-shadow:0 0 #f0a02000}50%{border-color:var(--dsw-alias-status-warning-foreground,#b56900);box-shadow:0 0 0 5px #f0a02073}}.NPLLIq_upgradeBannerFlash{border-color:var(--dsw-alias-status-warning-foreground,#b56900);animation:.6s ease-in-out 4 NPLLIq_upgradeBannerFlash}.NPLLIq_upgradeBannerText{margin-bottom:6px;font-weight:600}.NPLLIq_upgradeCommands{flex-direction:column;gap:4px;display:flex}.NPLLIq_upgradeCommandRow{align-items:center;gap:6px;display:flex}.NPLLIq_upgradeCommand{background:var(--dsw-alias-bg-layer-2,#0000000a);white-space:nowrap;border-radius:4px;flex:1;min-width:0;padding:4px 6px;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:11px;overflow-x:auto}.NPLLIq_copyBtn{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-2,#0000000a);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:4px;flex:none;padding:3px 8px;font-size:11px;transition:transform 80ms,background .12s,color .12s}.NPLLIq_copyBtn:hover{background:var(--dsw-alias-bg-layer-3,#00000014)}.NPLLIq_copyBtn:active{transform:scale(.92)}.NPLLIq_copyBtnDone{background:var(--dsw-alias-status-success-background,#14963c1f);border-color:var(--dsw-alias-status-success-foreground,#0a7d32);color:var(--dsw-alias-status-success-foreground,#0a7d32);font-weight:600}.NPLLIq_upgradeHint{color:var(--dsw-alias-label-secondary);margin-top:6px;font-size:11px}.NPLLIq_upgradeClose{width:20px;height:20px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;font-size:16px;line-height:1;position:absolute;top:4px;right:6px}.NPLLIq_upgradeClose:hover{background:var(--dsw-alias-bg-layer-2,#0000000a);color:var(--dsw-alias-label-primary)}.NPLLIq_checkUpdatesRow{justify-content:space-between;align-items:center;gap:12px;display:flex}.NPLLIq_checkUpdatesLabel{color:var(--dsw-alias-label-primary);cursor:pointer;align-items:center;gap:6px;font-size:12px;display:flex}.NPLLIq_checkUpdatesLabel input{margin:0}.NPLLIq_checkUpdatesLabel input[type=range]{min-width:90px;accent-color:var(--dsw-alias-brand-primary);flex:1}.NPLLIq_checkUpdatesLabel select{background:var(--dsw-alias-bg-layer-2,#0000000a);min-width:90px;color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-divider-1,#00000026);border-radius:4px;flex:1;padding:2px 4px;font-size:12px}.NPLLIq_checkBtn{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-2,#0000000a);color:var(--dsw-alias-label-primary);cursor:pointer;white-space:nowrap;text-align:center;border-radius:4px;flex:none;min-width:72px;padding:4px 10px;font-size:12px}.NPLLIq_checkBtn:hover:not(:disabled){background:var(--dsw-alias-bg-layer-3,#00000014)}.NPLLIq_checkBtn:disabled{opacity:.6;cursor:default}.NPLLIq_checkErrorHint{color:var(--dsw-alias-state-error-primary,#c00);background:var(--dsw-alias-state-error-background,#ff00000f);border:1px solid var(--dsw-alias-state-error-border,#b4000040);word-break:break-all;border-radius:6px;margin-top:8px;padding:6px 8px;font-size:11px;line-height:1.4}.NPLLIq_dialog{z-index:100;box-sizing:border-box;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);border-radius:12px;flex-direction:column;gap:12px;width:430px;max-width:94vw;max-height:80vh;padding:14px;display:flex;position:fixed;top:50%;left:50%;overflow-y:auto;transform:translate(-50%,-50%);box-shadow:0 8px 28px #00000040}.NPLLIq_dialogTabs{border-bottom:1px solid var(--dsw-alias-divider-1,#00000014);gap:2px;margin:-6px -14px 0;padding:0 14px;display:flex}.NPLLIq_dialogTab{appearance:none;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-bottom:2px solid #0000;padding:6px 12px 8px;font-size:12px}.NPLLIq_dialogTab:hover{color:var(--dsw-alias-label-primary)}.NPLLIq_dialogTabActive{color:var(--dsw-alias-brand-primary);border-bottom-color:var(--dsw-alias-brand-primary);font-weight:600}.NPLLIq_settingsDialog{height:min(560px,80vh)}.NPLLIq_dialogTitle{color:var(--dsw-alias-label-primary);font-size:13px;font-weight:600}.NPLLIq_dialogSection{flex-direction:column;gap:6px;display:flex}.NPLLIq_dialogLabel{color:var(--dsw-alias-label-primary);font-size:12px;font-weight:500}.NPLLIq_monitorHint{color:var(--dsw-alias-label-secondary);font-size:11px}.NPLLIq_dialogHint{color:var(--dsw-alias-label-secondary);margin-top:4px;font-size:11px;line-height:1.4}.NPLLIq_monitorList{flex-direction:column;gap:2px;max-height:180px;display:flex;overflow-y:auto}.NPLLIq_monitorRow{color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;align-items:center;gap:6px;padding:2px 4px;font-size:12px;display:flex}.NPLLIq_monitorRow:hover{background:var(--dsw-alias-bg-layer-1)}.NPLLIq_monitorName{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.NPLLIq_radioRow{color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:6px;align-items:center;gap:6px;padding:3px 4px;font-size:12px;display:flex}.NPLLIq_radioRow:hover{background:var(--dsw-alias-bg-layer-1)}.NPLLIq_dialogActions{justify-content:flex-end;gap:6px;display:flex}.NPLLIq_dialogBtn,.NPLLIq_dialogBtnPrimary{border:1px solid var(--dsw-alias-border-l1);cursor:pointer;border-radius:6px;padding:4px 12px;font-size:11px}.NPLLIq_dialogBtn{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}.NPLLIq_dialogBtnPrimary{background:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary);color:var(--dsw-alias-bg-overlay)}.NPLLIq_dialogHeader{z-index:2;background:var(--dsw-alias-bg-overlay);cursor:grab;user-select:none;touch-action:none;justify-content:space-between;align-items:center;gap:8px;margin:-14px -14px 0;padding:14px 14px 8px;display:flex;position:sticky;top:-14px}.NPLLIq_dialogHeader:active{cursor:grabbing}.NPLLIq_dialogClose{width:28px;height:28px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:8px;flex:none;justify-content:center;align-items:center;font-size:18px;line-height:1;display:flex}.NPLLIq_dialogClose:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-1)}.NPLLIq_resetRow{flex-wrap:wrap;align-items:center;gap:6px;display:flex}.NPLLIq_resetSelect{border:1px solid var(--dsw-alias-border-l1);background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary);border-radius:6px;padding:3px 6px;font-size:12px}.NPLLIq_logTable{border-collapse:collapse;width:100%;font-size:11px}.NPLLIq_logTable th{text-align:left;color:var(--dsw-alias-label-secondary);border-bottom:1px solid var(--dsw-alias-border-l1);padding:4px 6px;font-weight:500}.NPLLIq_logTable td{color:var(--dsw-alias-label-primary);border-bottom:1px solid var(--dsw-alias-border-l1);font-variant-numeric:tabular-nums;padding:4px 6px}.NPLLIq_logDayCol{white-space:nowrap;color:var(--dsw-alias-label-secondary)}.NPLLIq_logModelCol{text-overflow:ellipsis;white-space:nowrap;max-width:160px;overflow:hidden}.NPLLIq_logUsedCol{text-align:right}.NPLLIq_logDialog{gap:0;width:380px;max-height:min(72vh,480px);padding:0}.NPLLIq_logHeader{background:var(--dsw-alias-bg-overlay);cursor:grab;user-select:none;touch-action:none;flex:none;justify-content:space-between;align-items:center;gap:8px;padding:14px 14px 8px;display:flex}.NPLLIq_logHeader:active{cursor:grabbing}.NPLLIq_logScroll{flex:1;min-height:0;padding:0 14px 14px;overflow:auto}.NPLLIq_logToolbar{flex:1;align-items:center;gap:6px;display:flex}.NPLLIq_logSearch{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);min-width:0;color:var(--dsw-alias-label-primary);border-radius:4px;flex:1;padding:3px 6px;font-size:11px}.NPLLIq_logSearch:focus{border-color:var(--dsw-alias-accent-1,#4a9eff);outline:none}.NPLLIq_logClearBtn{border:1px solid var(--dsw-alias-state-error-border,#b400004d);color:var(--dsw-alias-state-error-primary,#c00);cursor:pointer;white-space:nowrap;background:0 0;border-radius:4px;flex:none;padding:3px 8px;font-size:11px}.NPLLIq_logClearBtn:hover{background:var(--dsw-alias-state-error-background,#ff00000f)}.NPLLIq_logPager{border-top:1px solid var(--dsw-alias-divider-1,#00000014);background:var(--dsw-alias-bg-overlay);color:var(--dsw-alias-label-secondary);flex:none;justify-content:space-between;align-items:center;gap:8px;padding:6px 14px;font-size:11px;display:flex}.NPLLIq_logPagerInfo{white-space:nowrap}.NPLLIq_logPagerControls{align-items:center;gap:4px;display:flex}.NPLLIq_logPagerBtn{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);width:24px;height:24px;color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:4px;font-size:13px;line-height:1}.NPLLIq_logPagerBtn:disabled{opacity:.4;cursor:default}.NPLLIq_logPagerPages{text-align:center;min-width:50px;color:var(--dsw-alias-label-secondary)}.NPLLIq_logPageSizeSelect{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);color:var(--dsw-alias-label-primary);cursor:pointer;border-radius:4px;padding:2px 4px;font-size:11px}.NPLLIq_dialogOverlay{z-index:100001;background:#0000004d;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.NPLLIq_logClearDialog{gap:0;width:320px;padding:16px}.NPLLIq_dialogBody{color:var(--dsw-alias-label-secondary);margin:6px 0 10px;font-size:12px;line-height:1.5}.NPLLIq_logClearDate{border:1px solid var(--dsw-alias-divider-1,#00000026);background:var(--dsw-alias-bg-layer-1,#0000000a);width:100%;color:var(--dsw-alias-label-primary);border-radius:6px;margin-bottom:12px;padding:6px 8px;font-size:13px}.NPLLIq_logClearDate:focus{border-color:var(--dsw-alias-accent-1,#4a9eff);outline:none}";
195
223
  const tagId = "@jxgame2020/dsh-token-quota/TokenQuotaPanel.module.css";
196
224
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
197
225
  const tag = document.createElement("style");
@@ -201,95 +229,99 @@ window.__ModuleLoader__.load({
201
229
  document.head.appendChild(tag);
202
230
  }
203
231
  var TokenQuotaPanel_module_css_default = {
204
- "controls": "NPLLIq_controls",
205
- "logHeader": "NPLLIq_logHeader",
206
- "logModelCol": "NPLLIq_logModelCol",
207
- "gearBtn": "NPLLIq_gearBtn",
208
- "monitorHint": "NPLLIq_monitorHint",
232
+ "subtitle": "NPLLIq_subtitle",
233
+ "headerActions": "NPLLIq_headerActions",
209
234
  "bar": "NPLLIq_bar",
235
+ "collapse": "NPLLIq_collapse",
236
+ "tabLabel": "NPLLIq_tabLabel",
237
+ "rowMeta": "NPLLIq_rowMeta",
238
+ "dialog": "NPLLIq_dialog",
239
+ "panelDimStrong": "NPLLIq_panelDimStrong",
240
+ "settingsBtn": "NPLLIq_settingsBtn",
241
+ "settingsDialog": "NPLLIq_settingsDialog",
242
+ "controls": "NPLLIq_controls",
243
+ "resetRow": "NPLLIq_resetRow",
244
+ "fillOver": "NPLLIq_fillOver",
245
+ "upgradeBannerFlash": "NPLLIq_upgradeBannerFlash",
246
+ "radioRow": "NPLLIq_radioRow",
247
+ "rowHeader": "NPLLIq_rowHeader",
248
+ "fillIdle": "NPLLIq_fillIdle",
249
+ "logTable": "NPLLIq_logTable",
250
+ "fullNotice": "NPLLIq_fullNotice",
251
+ "rowDragging": "NPLLIq_rowDragging",
252
+ "dialogBody": "NPLLIq_dialogBody",
253
+ "logDialog": "NPLLIq_logDialog",
254
+ "rowDropTarget": "NPLLIq_rowDropTarget",
255
+ "checkUpdatesLabel": "NPLLIq_checkUpdatesLabel",
256
+ "dialogTabs": "NPLLIq_dialogTabs",
210
257
  "resetSelect": "NPLLIq_resetSelect",
258
+ "logUsedCol": "NPLLIq_logUsedCol",
259
+ "fillWarn": "NPLLIq_fillWarn",
260
+ "selectBtn": "NPLLIq_selectBtn",
261
+ "versionNew": "NPLLIq_versionNew",
211
262
  "dialogTab": "NPLLIq_dialogTab",
212
- "dialogTabActive": "NPLLIq_dialogTabActive",
263
+ "dialogTitle": "NPLLIq_dialogTitle",
264
+ "dialogBtnPrimary": "NPLLIq_dialogBtnPrimary",
265
+ "logHeader": "NPLLIq_logHeader",
266
+ "rowDrag": "NPLLIq_rowDrag",
267
+ "monitorHint": "NPLLIq_monitorHint",
268
+ "body": "NPLLIq_body",
269
+ "rowName": "NPLLIq_rowName",
270
+ "noticeError": "NPLLIq_noticeError",
271
+ "upgradeCommandRow": "NPLLIq_upgradeCommandRow",
272
+ "dialogHeader": "NPLLIq_dialogHeader",
273
+ "logClearBtn": "NPLLIq_logClearBtn",
213
274
  "logPagerInfo": "NPLLIq_logPagerInfo",
214
- "radioRow": "NPLLIq_radioRow",
275
+ "checkUpdatesRow": "NPLLIq_checkUpdatesRow",
276
+ "dialogLabel": "NPLLIq_dialogLabel",
215
277
  "header": "NPLLIq_header",
216
- "rowHeader": "NPLLIq_rowHeader",
278
+ "logPager": "NPLLIq_logPager",
279
+ "copyBtn": "NPLLIq_copyBtn",
217
280
  "input": "NPLLIq_input",
218
- "settingsBtnActive": "NPLLIq_settingsBtnActive",
219
- "settingsBtn": "NPLLIq_settingsBtn",
220
- "subtitle": "NPLLIq_subtitle",
221
- "copyBtnDone": "NPLLIq_copyBtnDone",
222
- "checkBtn": "NPLLIq_checkBtn",
223
- "dialogTitle": "NPLLIq_dialogTitle",
224
- "monitorRow": "NPLLIq_monitorRow",
225
- "logScroll": "NPLLIq_logScroll",
226
- "dialogTabs": "NPLLIq_dialogTabs",
227
- "logPageSizeSelect": "NPLLIq_logPageSizeSelect",
228
- "checkErrorHint": "NPLLIq_checkErrorHint",
281
+ "logClearDialog": "NPLLIq_logClearDialog",
229
282
  "logClearDate": "NPLLIq_logClearDate",
283
+ "upgradeClose": "NPLLIq_upgradeClose",
230
284
  "dialogBtn": "NPLLIq_dialogBtn",
231
- "upgradeCommand": "NPLLIq_upgradeCommand",
232
- "logDayCol": "NPLLIq_logDayCol",
233
- "resetRow": "NPLLIq_resetRow",
234
- "logPager": "NPLLIq_logPager",
235
- "collapse": "NPLLIq_collapse",
285
+ "logPageSizeSelect": "NPLLIq_logPageSizeSelect",
286
+ "logScroll": "NPLLIq_logScroll",
236
287
  "upgradeHint": "NPLLIq_upgradeHint",
237
- "logClearBtn": "NPLLIq_logClearBtn",
238
- "version": "NPLLIq_version",
239
- "upgradeCommands": "NPLLIq_upgradeCommands",
240
- "notice": "NPLLIq_notice",
288
+ "logModelCol": "NPLLIq_logModelCol",
289
+ "gearBtn": "NPLLIq_gearBtn",
290
+ "monitorName": "NPLLIq_monitorName",
291
+ "dialogOverlay": "NPLLIq_dialogOverlay",
292
+ "currentBadge": "NPLLIq_currentBadge",
241
293
  "upgradeBannerText": "NPLLIq_upgradeBannerText",
242
- "monitorList": "NPLLIq_monitorList",
243
- "logClearDialog": "NPLLIq_logClearDialog",
244
- "headerText": "NPLLIq_headerText",
245
- "fullNotice": "NPLLIq_fullNotice",
246
- "dialogActions": "NPLLIq_dialogActions",
247
- "row": "NPLLIq_row",
248
- "dialogHeader": "NPLLIq_dialogHeader",
249
- "title": "NPLLIq_title",
250
- "selectBtn": "NPLLIq_selectBtn",
251
- "tabIcon": "NPLLIq_tabIcon",
252
- "fillWarn": "NPLLIq_fillWarn",
253
- "checkUpdatesLabel": "NPLLIq_checkUpdatesLabel",
254
- "dialogLabel": "NPLLIq_dialogLabel",
255
- "panelDimStrong": "NPLLIq_panelDimStrong",
256
- "dialogClose": "NPLLIq_dialogClose",
257
294
  "switch": "NPLLIq_switch",
258
295
  "logToolbar": "NPLLIq_logToolbar",
259
- "dialog": "NPLLIq_dialog",
260
- "tabLabel": "NPLLIq_tabLabel",
261
- "currentBadge": "NPLLIq_currentBadge",
262
- "copyBtn": "NPLLIq_copyBtn",
263
- "logDialog": "NPLLIq_logDialog",
264
296
  "logSearch": "NPLLIq_logSearch",
265
- "dialogOverlay": "NPLLIq_dialogOverlay",
266
- "noticeError": "NPLLIq_noticeError",
267
- "headerActions": "NPLLIq_headerActions",
268
- "panelDim": "NPLLIq_panelDim",
297
+ "logDayCol": "NPLLIq_logDayCol",
298
+ "dialogTabActive": "NPLLIq_dialogTabActive",
299
+ "row": "NPLLIq_row",
300
+ "upgradeBanner": "NPLLIq_upgradeBanner",
301
+ "headerText": "NPLLIq_headerText",
302
+ "title": "NPLLIq_title",
303
+ "dialogSection": "NPLLIq_dialogSection",
304
+ "logPagerControls": "NPLLIq_logPagerControls",
305
+ "settingsBtnActive": "NPLLIq_settingsBtnActive",
306
+ "version": "NPLLIq_version",
269
307
  "tab": "NPLLIq_tab",
270
- "upgradeCommandRow": "NPLLIq_upgradeCommandRow",
271
- "checkUpdatesRow": "NPLLIq_checkUpdatesRow",
272
308
  "dialogHint": "NPLLIq_dialogHint",
309
+ "dialogClose": "NPLLIq_dialogClose",
310
+ "panel": "NPLLIq_panel",
311
+ "tabIcon": "NPLLIq_tabIcon",
273
312
  "logPagerPages": "NPLLIq_logPagerPages",
274
- "versionNew": "NPLLIq_versionNew",
275
- "body": "NPLLIq_body",
276
- "rowMeta": "NPLLIq_rowMeta",
277
- "dialogSection": "NPLLIq_dialogSection",
278
- "logUsedCol": "NPLLIq_logUsedCol",
279
- "logPagerControls": "NPLLIq_logPagerControls",
280
- "fillIdle": "NPLLIq_fillIdle",
281
- "save": "NPLLIq_save",
282
- "upgradeBanner": "NPLLIq_upgradeBanner",
313
+ "panelDim": "NPLLIq_panelDim",
314
+ "copyBtnDone": "NPLLIq_copyBtnDone",
315
+ "monitorList": "NPLLIq_monitorList",
283
316
  "logPagerBtn": "NPLLIq_logPagerBtn",
284
- "monitorName": "NPLLIq_monitorName",
285
- "rowName": "NPLLIq_rowName",
286
- "upgradeBannerFlash": "NPLLIq_upgradeBannerFlash",
287
- "panel": "NPLLIq_panel",
288
- "dialogBody": "NPLLIq_dialogBody",
289
- "fillOver": "NPLLIq_fillOver",
290
- "dialogBtnPrimary": "NPLLIq_dialogBtnPrimary",
291
- "logTable": "NPLLIq_logTable",
292
- "upgradeClose": "NPLLIq_upgradeClose"
317
+ "monitorRow": "NPLLIq_monitorRow",
318
+ "dialogActions": "NPLLIq_dialogActions",
319
+ "notice": "NPLLIq_notice",
320
+ "upgradeCommand": "NPLLIq_upgradeCommand",
321
+ "checkErrorHint": "NPLLIq_checkErrorHint",
322
+ "checkBtn": "NPLLIq_checkBtn",
323
+ "upgradeCommands": "NPLLIq_upgradeCommands",
324
+ "save": "NPLLIq_save"
293
325
  };
294
326
  //#endregion
295
327
  //#region lib/types/client/TokenQuotaPanel.js
@@ -376,13 +408,15 @@ window.__ModuleLoader__.load({
376
408
  * @param props - composed slot props.
377
409
  * @returns the panel element tree.
378
410
  */
379
- function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, useStore, actions, useSessions }) {
411
+ function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setModelOrder, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, useStore, actions, useSessions }) {
380
412
  const [collapsed, setCollapsed] = (0, react.useState)(false);
381
413
  const [drafts, setDrafts] = (0, react.useState)({});
382
414
  const [editingKey, setEditingKey] = (0, react.useState)(null);
383
415
  const [hovered, setHovered] = (0, react.useState)(false);
384
416
  const [inputActive, setInputActive] = (0, react.useState)(false);
385
417
  const [settingsTab, setSettingsTab] = (0, react.useState)("quota");
418
+ const [dragKey, setDragKey] = (0, react.useState)(null);
419
+ const [dropKey, setDropKey] = (0, react.useState)(null);
386
420
  const [copiedCmd, setCopiedCmd] = (0, react.useState)(null);
387
421
  const copyTimerRef = (0, react.useRef)(null);
388
422
  const [upgradeFlash, setUpgradeFlash] = (0, react.useState)(false);
@@ -408,6 +442,7 @@ window.__ModuleLoader__.load({
408
442
  const onFull = useStore((s) => s.onFull);
409
443
  const checkUpdates = useStore((s) => s.checkUpdates);
410
444
  const dimWhenIdle = useStore((s) => s.dimWhenIdle);
445
+ const order = useStore((s) => s.order);
411
446
  const musicEnabled = useStore((s) => s.musicEnabled);
412
447
  const musicVolume = useStore((s) => s.musicVolume);
413
448
  const musicStyle = useStore((s) => s.musicStyle);
@@ -463,15 +498,27 @@ window.__ModuleLoader__.load({
463
498
  if (copyTimerRef.current !== null) clearTimeout(copyTimerRef.current);
464
499
  };
465
500
  }, []);
466
- const rows = (0, react.useMemo)(() => mergeModelRows(groups, snapshot, current), [
501
+ const rows = (0, react.useMemo)(() => mergeModelRows(groups, snapshot, current, order), [
467
502
  groups,
468
503
  snapshot,
469
- current
504
+ current,
505
+ order
470
506
  ]);
471
- const allModels = (0, react.useMemo)(() => groups.flatMap((group) => group.models.map((model) => ({
472
- key: `${group.id}/${model.id}`,
473
- name: model.name
474
- }))).sort((a, b) => a.key.localeCompare(b.key)), [groups]);
507
+ const allModels = (0, react.useMemo)(() => {
508
+ const list = groups.flatMap((group) => group.models.map((model) => ({
509
+ key: `${group.id}/${model.id}`,
510
+ name: model.name
511
+ })));
512
+ const rank = new Map(order.map((key, index) => [key, index]));
513
+ return list.sort((left, right) => {
514
+ const leftRank = rank.get(left.key);
515
+ const rightRank = rank.get(right.key);
516
+ if (leftRank !== void 0 && rightRank !== void 0) return leftRank - rightRank;
517
+ if (leftRank !== void 0) return -1;
518
+ if (rightRank !== void 0) return 1;
519
+ return left.key.localeCompare(right.key);
520
+ });
521
+ }, [groups, order]);
475
522
  const isMonitoredKey = (key) => monitored === null || monitored.includes(key);
476
523
  const filteredLogEntries = (0, react.useMemo)(() => {
477
524
  if (log === null) return [];
@@ -596,13 +643,13 @@ window.__ModuleLoader__.load({
596
643
  title: t("upgradeAvailableHint"),
597
644
  children: [
598
645
  "v",
599
- "0.1.30",
646
+ "0.1.32",
600
647
  " → v",
601
648
  upgrade.latestVersion
602
649
  ]
603
650
  }) : (0, react_jsx_runtime.jsxs)("span", {
604
651
  className: TokenQuotaPanel_module_css_default.version,
605
- children: ["v", "0.1.30"]
652
+ children: ["v", "0.1.32"]
606
653
  })]
607
654
  }), (0, react_jsx_runtime.jsx)("div", {
608
655
  className: TokenQuotaPanel_module_css_default.subtitle,
@@ -715,40 +762,69 @@ window.__ModuleLoader__.load({
715
762
  const barClass = state === "over" ? TokenQuotaPanel_module_css_default.fillOver : state === "warn" ? TokenQuotaPanel_module_css_default.fillWarn : TokenQuotaPanel_module_css_default.fillIdle;
716
763
  const editing = editingKey === row.key;
717
764
  return (0, react_jsx_runtime.jsxs)("div", {
718
- className: TokenQuotaPanel_module_css_default.row,
765
+ className: `${TokenQuotaPanel_module_css_default.row}${dragKey === row.key ? ` ${TokenQuotaPanel_module_css_default.rowDragging}` : ""}${dropKey === row.key && dragKey !== row.key ? ` ${TokenQuotaPanel_module_css_default.rowDropTarget}` : ""}`,
766
+ onDragOver: (event) => {
767
+ if (dragKey === null || dragKey === row.key) return;
768
+ event.preventDefault();
769
+ setDropKey(row.key);
770
+ },
771
+ onDrop: (event) => {
772
+ event.preventDefault();
773
+ if (dragKey !== null && dragKey !== row.key) setModelOrder(reorderKeys(rows.map((r) => r.key), dragKey, row.key));
774
+ setDragKey(null);
775
+ setDropKey(null);
776
+ },
777
+ onDragEnd: () => {
778
+ setDragKey(null);
779
+ setDropKey(null);
780
+ },
719
781
  children: [
720
782
  (0, react_jsx_runtime.jsxs)("div", {
721
783
  className: TokenQuotaPanel_module_css_default.rowHeader,
722
- children: [(0, react_jsx_runtime.jsxs)("span", {
723
- className: TokenQuotaPanel_module_css_default.rowName,
724
- title: row.key,
725
- children: [
726
- row.name,
727
- row.current && (0, react_jsx_runtime.jsx)("span", {
728
- className: TokenQuotaPanel_module_css_default.currentBadge,
729
- children: t("current")
730
- }),
731
- sessionId !== void 0 && !row.current && (0, react_jsx_runtime.jsx)("button", {
784
+ children: [
785
+ (0, react_jsx_runtime.jsx)("span", {
786
+ className: TokenQuotaPanel_module_css_default.rowDrag,
787
+ draggable: true,
788
+ title: t("reorderHint"),
789
+ onDragStart: (event) => {
790
+ setDragKey(row.key);
791
+ event.dataTransfer.effectAllowed = "move";
792
+ event.dataTransfer.setData("text/plain", row.key);
793
+ },
794
+ children: "⠿"
795
+ }),
796
+ (0, react_jsx_runtime.jsxs)("span", {
797
+ className: TokenQuotaPanel_module_css_default.rowName,
798
+ title: row.key,
799
+ children: [
800
+ row.name,
801
+ row.current && (0, react_jsx_runtime.jsx)("span", {
802
+ className: TokenQuotaPanel_module_css_default.currentBadge,
803
+ children: t("current")
804
+ }),
805
+ sessionId !== void 0 && !row.current && (0, react_jsx_runtime.jsx)("button", {
806
+ type: "button",
807
+ className: TokenQuotaPanel_module_css_default.selectBtn,
808
+ onClick: () => {
809
+ selectModel(sessionId, row.provider, row.model);
810
+ },
811
+ children: t("select")
812
+ })
813
+ ]
814
+ }),
815
+ (0, react_jsx_runtime.jsxs)("span", {
816
+ className: TokenQuotaPanel_module_css_default.rowMeta,
817
+ children: [row.limit > 0 ? `${formatTokens(row.used)} / ${formatTokens(row.limit)}` : `${formatTokens(row.used)} · ${t("unlimited")}`, (0, react_jsx_runtime.jsx)("button", {
732
818
  type: "button",
733
- className: TokenQuotaPanel_module_css_default.selectBtn,
819
+ className: TokenQuotaPanel_module_css_default.gearBtn,
820
+ title: t("setLimitHint"),
734
821
  onClick: () => {
735
- selectModel(sessionId, row.provider, row.model);
822
+ setEditingKey(editing ? null : row.key);
736
823
  },
737
- children: t("select")
738
- })
739
- ]
740
- }), (0, react_jsx_runtime.jsxs)("span", {
741
- className: TokenQuotaPanel_module_css_default.rowMeta,
742
- children: [row.limit > 0 ? `${formatTokens(row.used)} / ${formatTokens(row.limit)}` : `${formatTokens(row.used)} · ${t("unlimited")}`, (0, react_jsx_runtime.jsx)("button", {
743
- type: "button",
744
- className: TokenQuotaPanel_module_css_default.gearBtn,
745
- title: t("setLimitHint"),
746
- onClick: () => {
747
- setEditingKey(editing ? null : row.key);
748
- },
749
- children: "⚙"
750
- })]
751
- })]
824
+ children: "⚙"
825
+ })]
826
+ })
827
+ ]
752
828
  }),
753
829
  (0, react_jsx_runtime.jsx)("div", {
754
830
  className: TokenQuotaPanel_module_css_default.bar,
@@ -791,7 +867,7 @@ window.__ModuleLoader__.load({
791
867
  }),
792
868
  dialogOpen && (0, react_jsx_runtime.jsxs)("div", {
793
869
  ref: settingsRef,
794
- className: TokenQuotaPanel_module_css_default.dialog,
870
+ className: `${TokenQuotaPanel_module_css_default.dialog} ${TokenQuotaPanel_module_css_default.settingsDialog}`,
795
871
  style: settingsPos !== null ? {
796
872
  left: settingsPos.x,
797
873
  top: settingsPos.y,
@@ -822,230 +898,238 @@ window.__ModuleLoader__.load({
822
898
  (0, react_jsx_runtime.jsxs)("div", {
823
899
  className: TokenQuotaPanel_module_css_default.dialogTabs,
824
900
  role: "tablist",
825
- children: [(0, react_jsx_runtime.jsx)("button", {
826
- type: "button",
827
- role: "tab",
828
- "aria-selected": settingsTab === "quota",
829
- className: `${TokenQuotaPanel_module_css_default.dialogTab}${settingsTab === "quota" ? ` ${TokenQuotaPanel_module_css_default.dialogTabActive}` : ""}`,
830
- onClick: () => {
831
- setSettingsTab("quota");
832
- },
833
- children: t("settingsTabQuota")
834
- }), (0, react_jsx_runtime.jsx)("button", {
835
- type: "button",
836
- role: "tab",
837
- "aria-selected": settingsTab === "music",
838
- className: `${TokenQuotaPanel_module_css_default.dialogTab}${settingsTab === "music" ? ` ${TokenQuotaPanel_module_css_default.dialogTabActive}` : ""}`,
839
- onClick: () => {
840
- setSettingsTab("music");
841
- },
842
- children: t("settingsTabMusic")
843
- })]
901
+ children: [
902
+ (0, react_jsx_runtime.jsx)("button", {
903
+ type: "button",
904
+ role: "tab",
905
+ "aria-selected": settingsTab === "quota",
906
+ className: `${TokenQuotaPanel_module_css_default.dialogTab}${settingsTab === "quota" ? ` ${TokenQuotaPanel_module_css_default.dialogTabActive}` : ""}`,
907
+ onClick: () => {
908
+ setSettingsTab("quota");
909
+ },
910
+ children: t("settingsTabQuota")
911
+ }),
912
+ (0, react_jsx_runtime.jsx)("button", {
913
+ type: "button",
914
+ role: "tab",
915
+ "aria-selected": settingsTab === "music",
916
+ className: `${TokenQuotaPanel_module_css_default.dialogTab}${settingsTab === "music" ? ` ${TokenQuotaPanel_module_css_default.dialogTabActive}` : ""}`,
917
+ onClick: () => {
918
+ setSettingsTab("music");
919
+ },
920
+ children: t("settingsTabMusic")
921
+ }),
922
+ (0, react_jsx_runtime.jsx)("button", {
923
+ type: "button",
924
+ role: "tab",
925
+ "aria-selected": settingsTab === "other",
926
+ className: `${TokenQuotaPanel_module_css_default.dialogTab}${settingsTab === "other" ? ` ${TokenQuotaPanel_module_css_default.dialogTabActive}` : ""}`,
927
+ onClick: () => {
928
+ setSettingsTab("other");
929
+ },
930
+ children: t("settingsTabOther")
931
+ })
932
+ ]
844
933
  }),
845
- settingsTab === "quota" && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
846
- (0, react_jsx_runtime.jsxs)("div", {
847
- className: TokenQuotaPanel_module_css_default.dialogSection,
848
- children: [
849
- (0, react_jsx_runtime.jsx)("div", {
850
- className: TokenQuotaPanel_module_css_default.dialogLabel,
851
- children: t("monitorLabel")
852
- }),
853
- (0, react_jsx_runtime.jsx)("div", {
854
- className: TokenQuotaPanel_module_css_default.monitorHint,
855
- children: t("monitorHint")
856
- }),
857
- (0, react_jsx_runtime.jsx)("div", {
858
- className: TokenQuotaPanel_module_css_default.monitorList,
859
- children: allModels.map((model) => (0, react_jsx_runtime.jsxs)("label", {
860
- className: TokenQuotaPanel_module_css_default.monitorRow,
861
- children: [(0, react_jsx_runtime.jsx)("input", {
862
- type: "checkbox",
863
- checked: monitored === null || monitored.includes(model.key),
864
- onChange: (event) => {
865
- const base = monitored === null ? allModels.map((m) => m.key) : monitored;
866
- const next = new Set(base);
867
- if (event.target.checked) next.add(model.key);
868
- else next.delete(model.key);
869
- setMonitored(next.size === allModels.length ? null : [...next]);
870
- }
871
- }), (0, react_jsx_runtime.jsx)("span", {
872
- className: TokenQuotaPanel_module_css_default.monitorName,
873
- title: model.key,
874
- children: model.name
875
- })]
876
- }, model.key))
877
- })
878
- ]
879
- }),
880
- (0, react_jsx_runtime.jsxs)("div", {
881
- className: TokenQuotaPanel_module_css_default.dialogSection,
882
- children: [(0, react_jsx_runtime.jsx)("div", {
934
+ settingsTab === "quota" && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
935
+ className: TokenQuotaPanel_module_css_default.dialogSection,
936
+ children: [
937
+ (0, react_jsx_runtime.jsx)("div", {
883
938
  className: TokenQuotaPanel_module_css_default.dialogLabel,
884
- children: t("fullActionLabel")
885
- }), FULL_ACTIONS.map((action) => (0, react_jsx_runtime.jsxs)("label", {
886
- className: TokenQuotaPanel_module_css_default.radioRow,
887
- children: [(0, react_jsx_runtime.jsx)("input", {
888
- type: "radio",
889
- name: "token-quota-onfull",
890
- checked: onFull === action.value,
891
- onChange: () => {
892
- setOnFull(action.value);
939
+ children: t("monitorLabel")
940
+ }),
941
+ (0, react_jsx_runtime.jsx)("div", {
942
+ className: TokenQuotaPanel_module_css_default.monitorHint,
943
+ children: t("monitorHint")
944
+ }),
945
+ (0, react_jsx_runtime.jsx)("div", {
946
+ className: TokenQuotaPanel_module_css_default.monitorList,
947
+ children: allModels.map((model) => (0, react_jsx_runtime.jsxs)("label", {
948
+ className: TokenQuotaPanel_module_css_default.monitorRow,
949
+ children: [(0, react_jsx_runtime.jsx)("input", {
950
+ type: "checkbox",
951
+ checked: monitored === null || monitored.includes(model.key),
952
+ onChange: (event) => {
953
+ const base = monitored === null ? allModels.map((m) => m.key) : monitored;
954
+ const next = new Set(base);
955
+ if (event.target.checked) next.add(model.key);
956
+ else next.delete(model.key);
957
+ setMonitored(next.size === allModels.length ? null : [...next]);
958
+ }
959
+ }), (0, react_jsx_runtime.jsx)("span", {
960
+ className: TokenQuotaPanel_module_css_default.monitorName,
961
+ title: model.key,
962
+ children: model.name
963
+ })]
964
+ }, model.key))
965
+ })
966
+ ]
967
+ }), (0, react_jsx_runtime.jsxs)("div", {
968
+ className: TokenQuotaPanel_module_css_default.dialogSection,
969
+ children: [(0, react_jsx_runtime.jsx)("div", {
970
+ className: TokenQuotaPanel_module_css_default.dialogLabel,
971
+ children: t("fullActionLabel")
972
+ }), FULL_ACTIONS.map((action) => (0, react_jsx_runtime.jsxs)("label", {
973
+ className: TokenQuotaPanel_module_css_default.radioRow,
974
+ children: [(0, react_jsx_runtime.jsx)("input", {
975
+ type: "radio",
976
+ name: "token-quota-onfull",
977
+ checked: onFull === action.value,
978
+ onChange: () => {
979
+ setOnFull(action.value);
980
+ }
981
+ }), (0, react_jsx_runtime.jsx)("span", { children: t(action.labelKey) })]
982
+ }, action.value))]
983
+ })] }),
984
+ settingsTab === "other" && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
985
+ className: TokenQuotaPanel_module_css_default.dialogSection,
986
+ children: [
987
+ (0, react_jsx_runtime.jsx)("div", {
988
+ className: TokenQuotaPanel_module_css_default.dialogLabel,
989
+ children: t("resetLabel")
990
+ }),
991
+ (0, react_jsx_runtime.jsx)("div", {
992
+ className: TokenQuotaPanel_module_css_default.monitorHint,
993
+ children: t("resetHint")
994
+ }),
995
+ (0, react_jsx_runtime.jsxs)("div", {
996
+ className: TokenQuotaPanel_module_css_default.resetRow,
997
+ children: [
998
+ (0, react_jsx_runtime.jsx)("select", {
999
+ className: TokenQuotaPanel_module_css_default.resetSelect,
1000
+ value: reset?.offsetHours ?? -(/* @__PURE__ */ new Date()).getTimezoneOffset() / 60,
1001
+ onChange: (event) => {
1002
+ setReset({
1003
+ offsetHours: Number(event.target.value),
1004
+ hour: reset?.hour ?? 0,
1005
+ minute: reset?.minute ?? 0
1006
+ });
1007
+ },
1008
+ children: Array.from({ length: 27 }, (_, i) => i - 12).map((offset) => (0, react_jsx_runtime.jsxs)("option", {
1009
+ value: offset,
1010
+ children: ["UTC", offset >= 0 ? `+${offset}` : offset]
1011
+ }, offset))
1012
+ }),
1013
+ (0, react_jsx_runtime.jsx)("select", {
1014
+ className: TokenQuotaPanel_module_css_default.resetSelect,
1015
+ value: reset?.hour ?? 0,
1016
+ onChange: (event) => {
1017
+ setReset({
1018
+ offsetHours: reset?.offsetHours ?? -(/* @__PURE__ */ new Date()).getTimezoneOffset() / 60,
1019
+ hour: Number(event.target.value),
1020
+ minute: reset?.minute ?? 0
1021
+ });
1022
+ },
1023
+ children: Array.from({ length: 24 }, (_, i) => i).map((hour) => (0, react_jsx_runtime.jsxs)("option", {
1024
+ value: hour,
1025
+ children: [String(hour).padStart(2, "0"), " 时"]
1026
+ }, hour))
1027
+ }),
1028
+ (0, react_jsx_runtime.jsx)("select", {
1029
+ className: TokenQuotaPanel_module_css_default.resetSelect,
1030
+ value: reset?.minute ?? 0,
1031
+ onChange: (event) => {
1032
+ setReset({
1033
+ offsetHours: reset?.offsetHours ?? -(/* @__PURE__ */ new Date()).getTimezoneOffset() / 60,
1034
+ hour: reset?.hour ?? 0,
1035
+ minute: Number(event.target.value)
1036
+ });
1037
+ },
1038
+ children: Array.from({ length: 12 }, (_, i) => i * 5).map((minute) => (0, react_jsx_runtime.jsxs)("option", {
1039
+ value: minute,
1040
+ children: [String(minute).padStart(2, "0"), " 分"]
1041
+ }, minute))
1042
+ })
1043
+ ]
1044
+ })
1045
+ ]
1046
+ }), (0, react_jsx_runtime.jsxs)("div", {
1047
+ className: TokenQuotaPanel_module_css_default.dialogSection,
1048
+ children: [(0, react_jsx_runtime.jsxs)("label", {
1049
+ className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1050
+ children: [(0, react_jsx_runtime.jsx)("input", {
1051
+ type: "checkbox",
1052
+ checked: dimWhenIdle,
1053
+ onChange: (event) => {
1054
+ setDimWhenIdle(event.target.checked);
1055
+ }
1056
+ }), (0, react_jsx_runtime.jsx)("span", { children: t("dimWhenIdleLabel") })]
1057
+ }), (0, react_jsx_runtime.jsx)("div", {
1058
+ className: TokenQuotaPanel_module_css_default.dialogHint,
1059
+ children: t("dimWhenIdleHint")
1060
+ })]
1061
+ })] }),
1062
+ settingsTab === "music" && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
1063
+ className: TokenQuotaPanel_module_css_default.dialogSection,
1064
+ children: [(0, react_jsx_runtime.jsxs)("label", {
1065
+ className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1066
+ children: [(0, react_jsx_runtime.jsx)("input", {
1067
+ type: "checkbox",
1068
+ checked: musicEnabled,
1069
+ onChange: (event) => {
1070
+ setMusicEnabled(event.target.checked);
1071
+ }
1072
+ }), (0, react_jsx_runtime.jsx)("span", { children: t("musicLabel") })]
1073
+ }), (0, react_jsx_runtime.jsx)("div", {
1074
+ className: TokenQuotaPanel_module_css_default.dialogHint,
1075
+ children: t("musicHint")
1076
+ })]
1077
+ }), musicEnabled && (0, react_jsx_runtime.jsxs)("div", {
1078
+ className: TokenQuotaPanel_module_css_default.dialogSection,
1079
+ children: [
1080
+ (0, react_jsx_runtime.jsxs)("label", {
1081
+ className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1082
+ children: [(0, react_jsx_runtime.jsx)("span", { children: t("musicVolume") }), (0, react_jsx_runtime.jsx)("input", {
1083
+ type: "range",
1084
+ min: 0,
1085
+ max: 1,
1086
+ step: .05,
1087
+ value: musicVolume,
1088
+ onChange: (event) => {
1089
+ setMusicVolume(Number(event.target.value));
893
1090
  }
894
- }), (0, react_jsx_runtime.jsx)("span", { children: t(action.labelKey) })]
895
- }, action.value))]
896
- }),
897
- (0, react_jsx_runtime.jsxs)("div", {
898
- className: TokenQuotaPanel_module_css_default.dialogSection,
899
- children: [
900
- (0, react_jsx_runtime.jsx)("div", {
901
- className: TokenQuotaPanel_module_css_default.dialogLabel,
902
- children: t("resetLabel")
903
- }),
904
- (0, react_jsx_runtime.jsx)("div", {
905
- className: TokenQuotaPanel_module_css_default.monitorHint,
906
- children: t("resetHint")
907
- }),
908
- (0, react_jsx_runtime.jsxs)("div", {
909
- className: TokenQuotaPanel_module_css_default.resetRow,
1091
+ })]
1092
+ }),
1093
+ (0, react_jsx_runtime.jsxs)("label", {
1094
+ className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1095
+ children: [(0, react_jsx_runtime.jsx)("span", { children: t("musicStyle") }), (0, react_jsx_runtime.jsxs)("select", {
1096
+ value: musicStyle,
1097
+ onChange: (event) => {
1098
+ setMusicStyle(event.target.value);
1099
+ },
910
1100
  children: [
911
- (0, react_jsx_runtime.jsx)("select", {
912
- className: TokenQuotaPanel_module_css_default.resetSelect,
913
- value: reset?.offsetHours ?? -(/* @__PURE__ */ new Date()).getTimezoneOffset() / 60,
914
- onChange: (event) => {
915
- setReset({
916
- offsetHours: Number(event.target.value),
917
- hour: reset?.hour ?? 0,
918
- minute: reset?.minute ?? 0
919
- });
920
- },
921
- children: Array.from({ length: 27 }, (_, i) => i - 12).map((offset) => (0, react_jsx_runtime.jsxs)("option", {
922
- value: offset,
923
- children: ["UTC", offset >= 0 ? `+${offset}` : offset]
924
- }, offset))
1101
+ (0, react_jsx_runtime.jsx)("option", {
1102
+ value: "major",
1103
+ children: t("musicStyleMajor")
925
1104
  }),
926
- (0, react_jsx_runtime.jsx)("select", {
927
- className: TokenQuotaPanel_module_css_default.resetSelect,
928
- value: reset?.hour ?? 0,
929
- onChange: (event) => {
930
- setReset({
931
- offsetHours: reset?.offsetHours ?? -(/* @__PURE__ */ new Date()).getTimezoneOffset() / 60,
932
- hour: Number(event.target.value),
933
- minute: reset?.minute ?? 0
934
- });
935
- },
936
- children: Array.from({ length: 24 }, (_, i) => i).map((hour) => (0, react_jsx_runtime.jsxs)("option", {
937
- value: hour,
938
- children: [String(hour).padStart(2, "0"), " 时"]
939
- }, hour))
1105
+ (0, react_jsx_runtime.jsx)("option", {
1106
+ value: "minor",
1107
+ children: t("musicStyleMinor")
940
1108
  }),
941
- (0, react_jsx_runtime.jsx)("select", {
942
- className: TokenQuotaPanel_module_css_default.resetSelect,
943
- value: reset?.minute ?? 0,
944
- onChange: (event) => {
945
- setReset({
946
- offsetHours: reset?.offsetHours ?? -(/* @__PURE__ */ new Date()).getTimezoneOffset() / 60,
947
- hour: reset?.hour ?? 0,
948
- minute: Number(event.target.value)
949
- });
950
- },
951
- children: Array.from({ length: 12 }, (_, i) => i * 5).map((minute) => (0, react_jsx_runtime.jsxs)("option", {
952
- value: minute,
953
- children: [String(minute).padStart(2, "0"), " 分"]
954
- }, minute))
1109
+ (0, react_jsx_runtime.jsx)("option", {
1110
+ value: "pentatonic",
1111
+ children: t("musicStylePentatonic")
955
1112
  })
956
1113
  ]
957
- })
958
- ]
959
- }),
960
- (0, react_jsx_runtime.jsxs)("div", {
961
- className: TokenQuotaPanel_module_css_default.dialogSection,
962
- children: [(0, react_jsx_runtime.jsxs)("label", {
963
- className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
964
- children: [(0, react_jsx_runtime.jsx)("input", {
965
- type: "checkbox",
966
- checked: dimWhenIdle,
967
- onChange: (event) => {
968
- setDimWhenIdle(event.target.checked);
969
- }
970
- }), (0, react_jsx_runtime.jsx)("span", { children: t("dimWhenIdleLabel") })]
971
- }), (0, react_jsx_runtime.jsx)("div", {
972
- className: TokenQuotaPanel_module_css_default.dialogHint,
973
- children: t("dimWhenIdleHint")
974
- })]
975
- })
976
- ] }),
977
- settingsTab === "music" && (0, react_jsx_runtime.jsxs)("div", {
978
- className: TokenQuotaPanel_module_css_default.dialogSection,
979
- children: [
1114
+ })]
1115
+ }),
980
1116
  (0, react_jsx_runtime.jsxs)("label", {
981
1117
  className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
982
1118
  children: [(0, react_jsx_runtime.jsx)("input", {
983
1119
  type: "checkbox",
984
- checked: musicEnabled,
1120
+ checked: musicOnlyCurrentSession,
985
1121
  onChange: (event) => {
986
- setMusicEnabled(event.target.checked);
1122
+ setMusicOnlyCurrentSession(event.target.checked);
987
1123
  }
988
- }), (0, react_jsx_runtime.jsx)("span", { children: t("musicLabel") })]
1124
+ }), (0, react_jsx_runtime.jsx)("span", { children: t("musicOnlyCurrentSessionLabel") })]
989
1125
  }),
990
1126
  (0, react_jsx_runtime.jsx)("div", {
991
1127
  className: TokenQuotaPanel_module_css_default.dialogHint,
992
- children: t("musicHint")
993
- }),
994
- musicEnabled && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
995
- (0, react_jsx_runtime.jsxs)("label", {
996
- className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
997
- children: [(0, react_jsx_runtime.jsx)("span", { children: t("musicVolume") }), (0, react_jsx_runtime.jsx)("input", {
998
- type: "range",
999
- min: 0,
1000
- max: 1,
1001
- step: .05,
1002
- value: musicVolume,
1003
- onChange: (event) => {
1004
- setMusicVolume(Number(event.target.value));
1005
- }
1006
- })]
1007
- }),
1008
- (0, react_jsx_runtime.jsxs)("label", {
1009
- className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1010
- children: [(0, react_jsx_runtime.jsx)("span", { children: t("musicStyle") }), (0, react_jsx_runtime.jsxs)("select", {
1011
- value: musicStyle,
1012
- onChange: (event) => {
1013
- setMusicStyle(event.target.value);
1014
- },
1015
- children: [
1016
- (0, react_jsx_runtime.jsx)("option", {
1017
- value: "major",
1018
- children: t("musicStyleMajor")
1019
- }),
1020
- (0, react_jsx_runtime.jsx)("option", {
1021
- value: "minor",
1022
- children: t("musicStyleMinor")
1023
- }),
1024
- (0, react_jsx_runtime.jsx)("option", {
1025
- value: "pentatonic",
1026
- children: t("musicStylePentatonic")
1027
- })
1028
- ]
1029
- })]
1030
- }),
1031
- (0, react_jsx_runtime.jsxs)("label", {
1032
- className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1033
- children: [(0, react_jsx_runtime.jsx)("input", {
1034
- type: "checkbox",
1035
- checked: musicOnlyCurrentSession,
1036
- onChange: (event) => {
1037
- setMusicOnlyCurrentSession(event.target.checked);
1038
- }
1039
- }), (0, react_jsx_runtime.jsx)("span", { children: t("musicOnlyCurrentSessionLabel") })]
1040
- }),
1041
- (0, react_jsx_runtime.jsx)("div", {
1042
- className: TokenQuotaPanel_module_css_default.dialogHint,
1043
- children: t("musicOnlyCurrentSessionHint")
1044
- })
1045
- ] })
1128
+ children: t("musicOnlyCurrentSessionHint")
1129
+ })
1046
1130
  ]
1047
- }),
1048
- settingsTab === "quota" && (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: (0, react_jsx_runtime.jsxs)("div", {
1131
+ })] }),
1132
+ settingsTab === "other" && (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: (0, react_jsx_runtime.jsxs)("div", {
1049
1133
  className: TokenQuotaPanel_module_css_default.dialogSection,
1050
1134
  children: [(0, react_jsx_runtime.jsxs)("div", {
1051
1135
  className: TokenQuotaPanel_module_css_default.checkUpdatesRow,
@@ -1541,6 +1625,10 @@ window.__ModuleLoader__.load({
1541
1625
  get started() {
1542
1626
  return this.audio !== null;
1543
1627
  }
1628
+ /** True when the master switch is on (mirrors the settings document). */
1629
+ get isEnabled() {
1630
+ return this.enabled;
1631
+ }
1544
1632
  /**
1545
1633
  * Start the audio context and probe for a MIDI output (once). Must be
1546
1634
  * called inside a user gesture so the AudioContext can resume.
@@ -1904,6 +1992,8 @@ window.__ModuleLoader__.load({
1904
1992
  settingsTitle: "设置",
1905
1993
  settingsTabQuota: "限额设置",
1906
1994
  settingsTabMusic: "音乐设置",
1995
+ settingsTabOther: "其它",
1996
+ reorderHint: "拖动排序",
1907
1997
  monitorLabel: "监控模型",
1908
1998
  monitorHint: "未勾选的模型不显示、不计入用量、不受限额限制",
1909
1999
  monitorAll: "全部",
@@ -1984,6 +2074,8 @@ window.__ModuleLoader__.load({
1984
2074
  settingsTitle: "Settings",
1985
2075
  settingsTabQuota: "Quota",
1986
2076
  settingsTabMusic: "Music",
2077
+ settingsTabOther: "Other",
2078
+ reorderHint: "Drag to reorder",
1987
2079
  monitorLabel: "Monitored models",
1988
2080
  monitorHint: "Unchecked models are hidden, not metered, and never capped",
1989
2081
  monitorAll: "All",
@@ -2102,6 +2194,24 @@ window.__ModuleLoader__.load({
2102
2194
  ctx.effect(() => () => {
2103
2195
  sse.close();
2104
2196
  }, "token-quota-ui: music SSE");
2197
+ const autoStartMusic = () => {
2198
+ if (!music.isEnabled || music.started) {
2199
+ if (music.started) {
2200
+ window.removeEventListener("pointerdown", autoStartMusic);
2201
+ window.removeEventListener("keydown", autoStartMusic);
2202
+ }
2203
+ return;
2204
+ }
2205
+ music.ensureStarted();
2206
+ window.removeEventListener("pointerdown", autoStartMusic);
2207
+ window.removeEventListener("keydown", autoStartMusic);
2208
+ };
2209
+ window.addEventListener("pointerdown", autoStartMusic);
2210
+ window.addEventListener("keydown", autoStartMusic);
2211
+ ctx.effect(() => () => {
2212
+ window.removeEventListener("pointerdown", autoStartMusic);
2213
+ window.removeEventListener("keydown", autoStartMusic);
2214
+ }, "token-quota-ui: music autostart gestures");
2105
2215
  /** Build a writable music-settings clone with defaults applied. */
2106
2216
  const musicDefaults = (raw) => ({
2107
2217
  enabled: raw?.enabled ?? false,
@@ -2217,6 +2327,7 @@ window.__ModuleLoader__.load({
2217
2327
  bound?.setSettings(lastMonitored, lastOnFull);
2218
2328
  bound?.setCheckUpdates(doc?.checkUpdates ?? true);
2219
2329
  bound?.setDimWhenIdle(doc?.dimWhenIdle ?? false);
2330
+ bound?.setOrder(Array.isArray(doc?.order) ? doc.order : []);
2220
2331
  bound?.setReset(lastReset);
2221
2332
  const musicSettings = musicDefaults(doc?.music);
2222
2333
  lastOnlyCurrentSession = musicSettings.onlyCurrentSession;
@@ -2297,6 +2408,11 @@ window.__ModuleLoader__.load({
2297
2408
  bound?.setDimWhenIdle(enabled);
2298
2409
  scope.set("dimWhenIdle", enabled);
2299
2410
  };
2411
+ /** Persist the drag-to-reorder display order of model rows. */
2412
+ const setModelOrder = (order) => {
2413
+ bound?.setOrder(order);
2414
+ scope.set("order", order);
2415
+ };
2300
2416
  const setMusicEnabled = (enabled) => {
2301
2417
  const doc = scope.getSnapshot().value;
2302
2418
  const current = musicDefaults(doc?.music);
@@ -2409,7 +2525,8 @@ window.__ModuleLoader__.load({
2409
2525
  setMusicEnabled,
2410
2526
  setMusicVolume,
2411
2527
  setMusicStyle,
2412
- setMusicOnlyCurrentSession
2528
+ setMusicOnlyCurrentSession,
2529
+ setModelOrder
2413
2530
  };
2414
2531
  };
2415
2532
  ctx.slots.inject("shell.overlay", () => ctx.slots.register({