@jxgame2020/dsh-token-quota 0.1.32 → 0.1.33

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
@@ -38,6 +38,8 @@ window.__ModuleLoader__.load({
38
38
  checkUpdates: true,
39
39
  dimWhenIdle: false,
40
40
  order: [],
41
+ notes: [],
42
+ notesLoaded: false,
41
43
  musicEnabled: false,
42
44
  musicVolume: .5,
43
45
  musicStyle: "pentatonic",
@@ -86,6 +88,10 @@ window.__ModuleLoader__.load({
86
88
  setOrder: (d, order) => {
87
89
  d.order = order;
88
90
  },
91
+ setNotes: (d, notes) => {
92
+ d.notes = notes;
93
+ d.notesLoaded = true;
94
+ },
89
95
  setMusicEnabled: (d, enabled) => {
90
96
  d.musicEnabled = enabled;
91
97
  },
@@ -99,7 +105,7 @@ window.__ModuleLoader__.load({
99
105
  d.musicOnlyCurrentSession = only;
100
106
  },
101
107
  setUpgrade: (d, upgrade) => {
102
- const normalized = upgrade !== null && upgrade.latestVersion !== "" && upgrade.latestVersion !== "0.1.32" ? upgrade : null;
108
+ const normalized = upgrade !== null && upgrade.latestVersion !== "" && upgrade.latestVersion !== "0.1.33" ? upgrade : null;
103
109
  if (d.upgrade === null || d.upgrade.latestVersion !== normalized?.latestVersion) d.upgradeDismissed = false;
104
110
  d.upgrade = normalized;
105
111
  },
@@ -219,7 +225,7 @@ window.__ModuleLoader__.load({
219
225
  }
220
226
  //#endregion
221
227
  //#region \0dsh-css:/Users/jxgame/Desktop/works/deepseek-harness-package/dsh-token-quota/packages/token-quota/src/client/TokenQuotaPanel.module.css.mjs
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}";
228
+ 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_notesBar{flex-wrap:wrap;align-items:center;gap:4px;margin-top:4px;display:flex}.NPLLIq_noteChip{width:20px;height:20px;color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l1);cursor:pointer;border-radius:5px;flex:none;justify-content:center;align-items:center;padding:0;font-size:11px;line-height:1;transition:color .12s,border-color .12s;display:inline-flex}.NPLLIq_noteChip:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2)}.NPLLIq_noteChipOpen{color:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}.NPLLIq_noteNew{width:22px;height:20px;color:var(--dsw-alias-label-secondary);border:1px dashed var(--dsw-alias-border-l2);cursor:pointer;background:0 0;border-radius:5px;flex:none;justify-content:center;align-items:center;padding:0;transition:color .12s,border-color .12s;display:inline-flex;position:relative}.NPLLIq_noteNew:hover:not(:disabled){color:var(--dsw-alias-brand-primary);border-color:var(--dsw-alias-brand-primary)}.NPLLIq_noteNew:disabled{opacity:.4;cursor:not-allowed}.NPLLIq_noteNewPlus{color:inherit;font-size:10px;font-weight:700;line-height:1;position:absolute;bottom:-2px;right:-1px}.NPLLIq_noteWin{z-index:60;pointer-events:auto;box-sizing:border-box;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);border-radius:10px;flex-direction:column;display:flex;position:fixed;overflow:hidden;box-shadow:0 8px 24px #00000038}.NPLLIq_noteWinCollapsed{height:auto!important}.NPLLIq_noteWinBar{background:var(--dsw-alias-bg-layer-1);border-bottom:1px solid var(--dsw-alias-border-l1);cursor:grab;user-select:none;flex:none;align-items:center;gap:4px;padding:4px 6px;display:flex}.NPLLIq_noteWinBar:active{cursor:grabbing}.NPLLIq_noteWinGripBar{color:var(--dsw-alias-label-secondary);opacity:.7;flex:none;font-size:10px}.NPLLIq_noteWinTitle{min-width:0;color:var(--dsw-alias-label-primary);background:0 0;border:1px solid #0000;border-radius:4px;outline:none;flex:1;padding:1px 2px;font-size:11px;font-weight:600}.NPLLIq_noteWinTitle:hover{border-color:var(--dsw-alias-border-l1)}.NPLLIq_noteWinTitle:focus{background:var(--dsw-alias-bg-overlay);border-color:var(--dsw-alias-brand-primary)}.NPLLIq_noteWinBtn{width:18px;height:18px;color:var(--dsw-alias-label-secondary);cursor:pointer;background:0 0;border:none;border-radius:4px;flex:none;justify-content:center;align-items:center;padding:0;font-size:12px;line-height:1;display:inline-flex}.NPLLIq_noteWinBtn:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}.NPLLIq_noteWinText{box-sizing:border-box;width:100%;min-height:0;color:var(--dsw-alias-label-primary);resize:none;background:0 0;border:none;outline:none;flex:1;padding:6px 8px;font-family:inherit;font-size:11px;line-height:1.5}.NPLLIq_noteWinResize{cursor:nwse-resize;background:linear-gradient(135deg, transparent 0 45%, var(--dsw-alias-border-l2) 45% 55%, transparent 55% 70%, var(--dsw-alias-border-l2) 70% 80%, transparent 80%);width:14px;height:14px;position:absolute;bottom:0;right:0}.NPLLIq_noteMenuBackdrop{z-index:100;pointer-events:auto;position:fixed;inset:0}.NPLLIq_noteMenu{z-index:101;pointer-events:auto;background:var(--dsw-alias-bg-overlay);border:1px solid var(--dsw-alias-border-l1);border-radius:8px;flex-direction:column;min-width:96px;padding:4px;display:flex;position:fixed;box-shadow:0 8px 24px #0000003d}.NPLLIq_noteMenuItem{text-align:left;color:var(--dsw-alias-label-primary);cursor:pointer;background:0 0;border:none;border-radius:5px;padding:5px 8px;font-size:11px}.NPLLIq_noteMenuItem:hover{background:var(--dsw-alias-bg-layer-2)}.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;pointer-events:auto;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;pointer-events:auto;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}";
223
229
  const tagId = "@jxgame2020/dsh-token-quota/TokenQuotaPanel.module.css";
224
230
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId) + "]") === null) {
225
231
  const tag = document.createElement("style");
@@ -229,99 +235,115 @@ window.__ModuleLoader__.load({
229
235
  document.head.appendChild(tag);
230
236
  }
231
237
  var TokenQuotaPanel_module_css_default = {
232
- "subtitle": "NPLLIq_subtitle",
233
- "headerActions": "NPLLIq_headerActions",
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",
238
+ "dialogSection": "NPLLIq_dialogSection",
243
239
  "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",
240
+ "noteWinBtn": "NPLLIq_noteWinBtn",
241
+ "input": "NPLLIq_input",
242
+ "dialogLabel": "NPLLIq_dialogLabel",
243
+ "dialogClose": "NPLLIq_dialogClose",
244
+ "logPagerInfo": "NPLLIq_logPagerInfo",
245
+ "monitorName": "NPLLIq_monitorName",
246
+ "noteWin": "NPLLIq_noteWin",
247
+ "gearBtn": "NPLLIq_gearBtn",
248
+ "logPagerBtn": "NPLLIq_logPagerBtn",
249
+ "logClearDialog": "NPLLIq_logClearDialog",
251
250
  "rowDragging": "NPLLIq_rowDragging",
252
- "dialogBody": "NPLLIq_dialogBody",
253
- "logDialog": "NPLLIq_logDialog",
254
- "rowDropTarget": "NPLLIq_rowDropTarget",
251
+ "checkErrorHint": "NPLLIq_checkErrorHint",
252
+ "dialogTabActive": "NPLLIq_dialogTabActive",
253
+ "logTable": "NPLLIq_logTable",
254
+ "selectBtn": "NPLLIq_selectBtn",
255
+ "rowName": "NPLLIq_rowName",
256
+ "logToolbar": "NPLLIq_logToolbar",
257
+ "settingsDialog": "NPLLIq_settingsDialog",
255
258
  "checkUpdatesLabel": "NPLLIq_checkUpdatesLabel",
256
- "dialogTabs": "NPLLIq_dialogTabs",
257
- "resetSelect": "NPLLIq_resetSelect",
258
- "logUsedCol": "NPLLIq_logUsedCol",
259
+ "header": "NPLLIq_header",
260
+ "noteChip": "NPLLIq_noteChip",
261
+ "subtitle": "NPLLIq_subtitle",
262
+ "noteChipOpen": "NPLLIq_noteChipOpen",
263
+ "noteWinResize": "NPLLIq_noteWinResize",
264
+ "rowMeta": "NPLLIq_rowMeta",
265
+ "save": "NPLLIq_save",
266
+ "headerActions": "NPLLIq_headerActions",
267
+ "fullNotice": "NPLLIq_fullNotice",
268
+ "rowHeader": "NPLLIq_rowHeader",
269
+ "noteWinCollapsed": "NPLLIq_noteWinCollapsed",
259
270
  "fillWarn": "NPLLIq_fillWarn",
260
- "selectBtn": "NPLLIq_selectBtn",
261
- "versionNew": "NPLLIq_versionNew",
262
271
  "dialogTab": "NPLLIq_dialogTab",
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
+ "logDialog": "NPLLIq_logDialog",
272
273
  "dialogHeader": "NPLLIq_dialogHeader",
274
+ "logSearch": "NPLLIq_logSearch",
275
+ "noteWinBar": "NPLLIq_noteWinBar",
273
276
  "logClearBtn": "NPLLIq_logClearBtn",
274
- "logPagerInfo": "NPLLIq_logPagerInfo",
275
- "checkUpdatesRow": "NPLLIq_checkUpdatesRow",
276
- "dialogLabel": "NPLLIq_dialogLabel",
277
- "header": "NPLLIq_header",
278
- "logPager": "NPLLIq_logPager",
277
+ "noteNew": "NPLLIq_noteNew",
278
+ "monitorRow": "NPLLIq_monitorRow",
279
+ "settingsBtn": "NPLLIq_settingsBtn",
280
+ "fillIdle": "NPLLIq_fillIdle",
281
+ "noticeError": "NPLLIq_noticeError",
279
282
  "copyBtn": "NPLLIq_copyBtn",
280
- "input": "NPLLIq_input",
281
- "logClearDialog": "NPLLIq_logClearDialog",
282
- "logClearDate": "NPLLIq_logClearDate",
283
- "upgradeClose": "NPLLIq_upgradeClose",
284
- "dialogBtn": "NPLLIq_dialogBtn",
285
- "logPageSizeSelect": "NPLLIq_logPageSizeSelect",
286
- "logScroll": "NPLLIq_logScroll",
287
- "upgradeHint": "NPLLIq_upgradeHint",
288
- "logModelCol": "NPLLIq_logModelCol",
289
- "gearBtn": "NPLLIq_gearBtn",
290
- "monitorName": "NPLLIq_monitorName",
291
- "dialogOverlay": "NPLLIq_dialogOverlay",
292
- "currentBadge": "NPLLIq_currentBadge",
293
- "upgradeBannerText": "NPLLIq_upgradeBannerText",
294
- "switch": "NPLLIq_switch",
295
- "logToolbar": "NPLLIq_logToolbar",
296
- "logSearch": "NPLLIq_logSearch",
283
+ "tabIcon": "NPLLIq_tabIcon",
284
+ "radioRow": "NPLLIq_radioRow",
285
+ "dialogBtnPrimary": "NPLLIq_dialogBtnPrimary",
286
+ "checkUpdatesRow": "NPLLIq_checkUpdatesRow",
297
287
  "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",
288
+ "noteMenuItem": "NPLLIq_noteMenuItem",
304
289
  "logPagerControls": "NPLLIq_logPagerControls",
305
- "settingsBtnActive": "NPLLIq_settingsBtnActive",
306
- "version": "NPLLIq_version",
290
+ "dialogOverlay": "NPLLIq_dialogOverlay",
291
+ "bar": "NPLLIq_bar",
292
+ "noteWinGripBar": "NPLLIq_noteWinGripBar",
293
+ "monitorList": "NPLLIq_monitorList",
294
+ "logUsedCol": "NPLLIq_logUsedCol",
295
+ "noteWinText": "NPLLIq_noteWinText",
296
+ "headerText": "NPLLIq_headerText",
297
+ "notesBar": "NPLLIq_notesBar",
298
+ "upgradeCommands": "NPLLIq_upgradeCommands",
299
+ "rowDrag": "NPLLIq_rowDrag",
307
300
  "tab": "NPLLIq_tab",
301
+ "checkBtn": "NPLLIq_checkBtn",
302
+ "noteNewPlus": "NPLLIq_noteNewPlus",
308
303
  "dialogHint": "NPLLIq_dialogHint",
309
- "dialogClose": "NPLLIq_dialogClose",
310
- "panel": "NPLLIq_panel",
311
- "tabIcon": "NPLLIq_tabIcon",
312
- "logPagerPages": "NPLLIq_logPagerPages",
313
- "panelDim": "NPLLIq_panelDim",
304
+ "dialogTabs": "NPLLIq_dialogTabs",
314
305
  "copyBtnDone": "NPLLIq_copyBtnDone",
315
- "monitorList": "NPLLIq_monitorList",
316
- "logPagerBtn": "NPLLIq_logPagerBtn",
317
- "monitorRow": "NPLLIq_monitorRow",
318
- "dialogActions": "NPLLIq_dialogActions",
306
+ "dialogTitle": "NPLLIq_dialogTitle",
319
307
  "notice": "NPLLIq_notice",
308
+ "currentBadge": "NPLLIq_currentBadge",
309
+ "settingsBtnActive": "NPLLIq_settingsBtnActive",
310
+ "version": "NPLLIq_version",
320
311
  "upgradeCommand": "NPLLIq_upgradeCommand",
321
- "checkErrorHint": "NPLLIq_checkErrorHint",
322
- "checkBtn": "NPLLIq_checkBtn",
323
- "upgradeCommands": "NPLLIq_upgradeCommands",
324
- "save": "NPLLIq_save"
312
+ "collapse": "NPLLIq_collapse",
313
+ "dialogBtn": "NPLLIq_dialogBtn",
314
+ "resetSelect": "NPLLIq_resetSelect",
315
+ "title": "NPLLIq_title",
316
+ "logModelCol": "NPLLIq_logModelCol",
317
+ "tabLabel": "NPLLIq_tabLabel",
318
+ "controls": "NPLLIq_controls",
319
+ "upgradeBanner": "NPLLIq_upgradeBanner",
320
+ "switch": "NPLLIq_switch",
321
+ "dialogActions": "NPLLIq_dialogActions",
322
+ "logHeader": "NPLLIq_logHeader",
323
+ "upgradeBannerText": "NPLLIq_upgradeBannerText",
324
+ "logClearDate": "NPLLIq_logClearDate",
325
+ "dialogBody": "NPLLIq_dialogBody",
326
+ "versionNew": "NPLLIq_versionNew",
327
+ "noteMenuBackdrop": "NPLLIq_noteMenuBackdrop",
328
+ "dialog": "NPLLIq_dialog",
329
+ "upgradeBannerFlash": "NPLLIq_upgradeBannerFlash",
330
+ "upgradeClose": "NPLLIq_upgradeClose",
331
+ "noteWinTitle": "NPLLIq_noteWinTitle",
332
+ "logPageSizeSelect": "NPLLIq_logPageSizeSelect",
333
+ "logPagerPages": "NPLLIq_logPagerPages",
334
+ "logScroll": "NPLLIq_logScroll",
335
+ "panel": "NPLLIq_panel",
336
+ "panelDim": "NPLLIq_panelDim",
337
+ "panelDimStrong": "NPLLIq_panelDimStrong",
338
+ "body": "NPLLIq_body",
339
+ "rowDropTarget": "NPLLIq_rowDropTarget",
340
+ "fillOver": "NPLLIq_fillOver",
341
+ "logPager": "NPLLIq_logPager",
342
+ "row": "NPLLIq_row",
343
+ "noteMenu": "NPLLIq_noteMenu",
344
+ "monitorHint": "NPLLIq_monitorHint",
345
+ "upgradeCommandRow": "NPLLIq_upgradeCommandRow",
346
+ "upgradeHint": "NPLLIq_upgradeHint"
325
347
  };
326
348
  //#endregion
327
349
  //#region lib/types/client/TokenQuotaPanel.js
@@ -392,6 +414,44 @@ window.__ModuleLoader__.load({
392
414
  window.addEventListener("pointerup", onUp);
393
415
  window.addEventListener("pointercancel", onUp);
394
416
  }
417
+ /**
418
+ * Pointer-driven resize of a note window from its bottom-right grip. Sizes are
419
+ * absolute pixels derived from the element's rect at grab time, so the window
420
+ * keeps its top-left anchor while the pointer moves. A floor keeps a window
421
+ * from collapsing to nothing.
422
+ */
423
+ function beginResize(event, el, apply) {
424
+ if (el === null) return;
425
+ event.preventDefault();
426
+ event.stopPropagation();
427
+ const startX = event.clientX;
428
+ const startY = event.clientY;
429
+ const rect = el.getBoundingClientRect();
430
+ const onMove = (ev) => {
431
+ apply({
432
+ width: Math.max(NOTE_MIN_WIDTH, Math.round(rect.width + (ev.clientX - startX))),
433
+ height: Math.max(NOTE_MIN_HEIGHT, Math.round(rect.height + (ev.clientY - startY)))
434
+ });
435
+ };
436
+ const onUp = () => {
437
+ window.removeEventListener("pointermove", onMove);
438
+ window.removeEventListener("pointerup", onUp);
439
+ window.removeEventListener("pointercancel", onUp);
440
+ };
441
+ window.addEventListener("pointermove", onMove);
442
+ window.addEventListener("pointerup", onUp);
443
+ window.addEventListener("pointercancel", onUp);
444
+ }
445
+ /** First visible character of a note title, for its header chip. */
446
+ function noteInitial(title) {
447
+ const trimmed = title.trim();
448
+ if (trimmed === "") return "·";
449
+ return Array.from(trimmed)[0] ?? "·";
450
+ }
451
+ /** Default geometry of a new note; later notes cascade so they don't stack. */
452
+ const NOTE_DEFAULT_SIZE = 220;
453
+ const NOTE_MIN_WIDTH = 150;
454
+ const NOTE_MIN_HEIGHT = 70;
395
455
  /** Persisted panel placement so a dragged position survives reloads. */
396
456
  const PANEL_POS_KEY = "dsh-token-quota:panel-pos";
397
457
  function loadPanelPos() {
@@ -408,7 +468,7 @@ window.__ModuleLoader__.load({
408
468
  * @param props - composed slot props.
409
469
  * @returns the panel element tree.
410
470
  */
411
- function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setModelOrder, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, useStore, actions, useSessions }) {
471
+ function TokenQuotaPanel({ t, load, setLimit, selectModel, setMonitored, setOnFull, setReset, setCheckUpdates, checkUpdatesNow, clearLogBefore, setDimWhenIdle, setModelOrder, saveNotes, setMusicEnabled, setMusicVolume, setMusicStyle, setMusicOnlyCurrentSession, useStore, actions, useSessions }) {
412
472
  const [collapsed, setCollapsed] = (0, react.useState)(false);
413
473
  const [drafts, setDrafts] = (0, react.useState)({});
414
474
  const [editingKey, setEditingKey] = (0, react.useState)(null);
@@ -417,6 +477,121 @@ window.__ModuleLoader__.load({
417
477
  const [settingsTab, setSettingsTab] = (0, react.useState)("quota");
418
478
  const [dragKey, setDragKey] = (0, react.useState)(null);
419
479
  const [dropKey, setDropKey] = (0, react.useState)(null);
480
+ const storedNotes = useStore((s) => s.notes);
481
+ const storedNotesLoaded = useStore((s) => s.notesLoaded);
482
+ const [notes, setNotes] = (0, react.useState)([]);
483
+ const notesSeeded = (0, react.useRef)(false);
484
+ const notesTimer = (0, react.useRef)(null);
485
+ const notesPending = (0, react.useRef)(null);
486
+ const [noteMenu, setNoteMenu] = (0, react.useState)(null);
487
+ const [activeNote, setActiveNote] = (0, react.useState)(null);
488
+ (0, react.useEffect)(() => {
489
+ if (!storedNotesLoaded || notesSeeded.current) return;
490
+ notesSeeded.current = true;
491
+ setNotes(storedNotes);
492
+ }, [storedNotesLoaded, storedNotes]);
493
+ (0, react.useEffect)(() => () => {
494
+ if (notesTimer.current !== null) window.clearTimeout(notesTimer.current);
495
+ const pending = notesPending.current;
496
+ if (pending !== null) {
497
+ notesPending.current = null;
498
+ saveNotes(pending);
499
+ }
500
+ }, []);
501
+ /**
502
+ * Apply a note change locally and persist it. Structural changes (create,
503
+ * close, collapse, drop) write straight through; free-form edits (typing,
504
+ * dragging, resizing) are debounced so a keystroke doesn't hit the Host.
505
+ */
506
+ const commitNotes = (next, immediate = true) => {
507
+ setNotes(next);
508
+ if (notesTimer.current !== null) window.clearTimeout(notesTimer.current);
509
+ if (immediate) {
510
+ notesPending.current = null;
511
+ saveNotes(next);
512
+ return;
513
+ }
514
+ notesPending.current = next;
515
+ notesTimer.current = window.setTimeout(() => {
516
+ notesTimer.current = null;
517
+ const pending = notesPending.current;
518
+ notesPending.current = null;
519
+ if (pending !== null) saveNotes(pending);
520
+ }, 400);
521
+ };
522
+ const patchNote = (id, patch, immediate = true) => {
523
+ commitNotes(notes.map((note) => note.id === id ? {
524
+ ...note,
525
+ ...patch
526
+ } : note), immediate);
527
+ };
528
+ /** Create a note, auto-titled 新建N with the lowest unused number. */
529
+ const createNote = () => {
530
+ if (notes.length >= 5) return;
531
+ let index = 1;
532
+ const used = new Set(notes.map((note) => /^新建(\d+)$/.exec(note.title.trim())?.[1]).filter(Boolean));
533
+ while (used.has(String(index))) index += 1;
534
+ const step = notes.length * 28;
535
+ commitNotes([...notes, {
536
+ id: `note-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 7)}`,
537
+ title: `新建${index}`,
538
+ text: "",
539
+ x: 120 + step,
540
+ y: 140 + step,
541
+ width: NOTE_DEFAULT_SIZE,
542
+ height: NOTE_DEFAULT_SIZE,
543
+ collapsed: false,
544
+ visible: true
545
+ }]);
546
+ };
547
+ const closeNote = (id) => {
548
+ patchNote(id, { visible: false });
549
+ };
550
+ const removeNote = (id) => {
551
+ commitNotes(notes.filter((note) => note.id !== id));
552
+ setNoteMenu(null);
553
+ };
554
+ /**
555
+ * Title-bar drag with a click/drag threshold: moving the pointer past a few
556
+ * pixels drags the window, while a plain click focuses the title input for
557
+ * editing. A title that is already being edited keeps native text behaviour
558
+ * (selection, caret placement) instead of turning into a window drag.
559
+ */
560
+ const beginNoteBarDrag = (event, id) => {
561
+ const win = event.currentTarget.parentElement;
562
+ if (win === null) return;
563
+ if (event.target.closest("button") !== null) return;
564
+ const input = event.target.closest("input");
565
+ if (input !== null && document.activeElement === input) return;
566
+ event.preventDefault();
567
+ const startX = event.clientX;
568
+ const startY = event.clientY;
569
+ const rect = win.getBoundingClientRect();
570
+ let dragging = false;
571
+ const onMove = (ev) => {
572
+ if (!dragging) {
573
+ if (Math.abs(ev.clientX - startX) < 3 && Math.abs(ev.clientY - startY) < 3) return;
574
+ dragging = true;
575
+ const active = document.activeElement;
576
+ if (active instanceof HTMLElement) active.blur();
577
+ }
578
+ patchNote(id, {
579
+ x: Math.round(rect.left + (ev.clientX - startX)),
580
+ y: Math.round(rect.top + (ev.clientY - startY))
581
+ }, false);
582
+ };
583
+ const onUp = () => {
584
+ window.removeEventListener("pointermove", onMove);
585
+ window.removeEventListener("pointerup", onUp);
586
+ window.removeEventListener("pointercancel", onUp);
587
+ if (dragging) return;
588
+ const title = win.querySelector("input");
589
+ if (title instanceof HTMLInputElement) title.focus();
590
+ };
591
+ window.addEventListener("pointermove", onMove);
592
+ window.addEventListener("pointerup", onUp);
593
+ window.addEventListener("pointercancel", onUp);
594
+ };
420
595
  const [copiedCmd, setCopiedCmd] = (0, react.useState)(null);
421
596
  const copyTimerRef = (0, react.useRef)(null);
422
597
  const [upgradeFlash, setUpgradeFlash] = (0, react.useState)(false);
@@ -614,22 +789,22 @@ window.__ModuleLoader__.load({
614
789
  };
615
790
  const visibleRows = rows.filter((row) => isMonitoredKey(row.key) || row.current);
616
791
  const panelDimClass = dimWhenIdle ? hovered || upgradeFlash ? "" : inputActive ? TokenQuotaPanel_module_css_default.panelDimStrong : TokenQuotaPanel_module_css_default.panelDim : "";
617
- return (0, react_jsx_runtime.jsxs)("div", {
618
- ref: panelRef,
619
- className: `${TokenQuotaPanel_module_css_default.panel}${panelDimClass !== "" ? ` ${panelDimClass}` : ""}`,
620
- style: panelPos !== null ? {
621
- left: panelPos.x,
622
- top: panelPos.y,
623
- right: "auto"
624
- } : void 0,
625
- onPointerEnter: () => {
626
- setHovered(true);
627
- },
628
- onPointerLeave: () => {
629
- setHovered(false);
630
- },
631
- children: [
632
- (0, react_jsx_runtime.jsxs)("div", {
792
+ return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
793
+ (0, react_jsx_runtime.jsxs)("div", {
794
+ ref: panelRef,
795
+ className: `${TokenQuotaPanel_module_css_default.panel}${panelDimClass !== "" ? ` ${panelDimClass}` : ""}`,
796
+ style: panelPos !== null ? {
797
+ left: panelPos.x,
798
+ top: panelPos.y,
799
+ right: "auto"
800
+ } : void 0,
801
+ onPointerEnter: () => {
802
+ setHovered(true);
803
+ },
804
+ onPointerLeave: () => {
805
+ setHovered(false);
806
+ },
807
+ children: [(0, react_jsx_runtime.jsxs)("div", {
633
808
  className: TokenQuotaPanel_module_css_default.header,
634
809
  onPointerDown: (event) => {
635
810
  beginDrag(event, panelRef.current, applyPanelPos);
@@ -643,17 +818,70 @@ window.__ModuleLoader__.load({
643
818
  title: t("upgradeAvailableHint"),
644
819
  children: [
645
820
  "v",
646
- "0.1.32",
821
+ "0.1.33",
647
822
  " → v",
648
823
  upgrade.latestVersion
649
824
  ]
650
825
  }) : (0, react_jsx_runtime.jsxs)("span", {
651
826
  className: TokenQuotaPanel_module_css_default.version,
652
- children: ["v", "0.1.32"]
827
+ children: ["v", "0.1.33"]
828
+ })]
829
+ }), (0, react_jsx_runtime.jsxs)("div", {
830
+ className: TokenQuotaPanel_module_css_default.notesBar,
831
+ onPointerDown: (event) => {
832
+ event.stopPropagation();
833
+ },
834
+ children: [notes.map((note) => {
835
+ const open = note.visible && !note.collapsed;
836
+ return (0, react_jsx_runtime.jsx)("button", {
837
+ type: "button",
838
+ className: `${TokenQuotaPanel_module_css_default.noteChip}${open ? ` ${TokenQuotaPanel_module_css_default.noteChipOpen}` : ""}`,
839
+ title: note.title.trim() === "" ? t("noteUntitled") : note.title,
840
+ onClick: () => {
841
+ patchNote(note.id, {
842
+ visible: true,
843
+ collapsed: false
844
+ });
845
+ },
846
+ onContextMenu: (event) => {
847
+ event.preventDefault();
848
+ setNoteMenu({
849
+ id: note.id,
850
+ x: event.clientX,
851
+ y: event.clientY
852
+ });
853
+ },
854
+ children: noteInitial(note.title)
855
+ }, note.id);
856
+ }), (0, react_jsx_runtime.jsxs)("button", {
857
+ type: "button",
858
+ className: TokenQuotaPanel_module_css_default.noteNew,
859
+ disabled: notes.length >= 5,
860
+ title: notes.length >= 5 ? t("noteMaxHint") : t("noteNewHint"),
861
+ onClick: createNote,
862
+ children: [(0, react_jsx_runtime.jsxs)("svg", {
863
+ viewBox: "0 0 16 16",
864
+ width: "13",
865
+ height: "13",
866
+ "aria-hidden": "true",
867
+ children: [(0, react_jsx_runtime.jsx)("path", {
868
+ d: "M4 1.6h4.6L12.4 5.4v9H4z",
869
+ fill: "none",
870
+ stroke: "currentColor",
871
+ strokeWidth: "1.2",
872
+ strokeLinejoin: "round"
873
+ }), (0, react_jsx_runtime.jsx)("path", {
874
+ d: "M8.4 1.6v3.9h4",
875
+ fill: "none",
876
+ stroke: "currentColor",
877
+ strokeWidth: "1.2",
878
+ strokeLinejoin: "round"
879
+ })]
880
+ }), (0, react_jsx_runtime.jsx)("span", {
881
+ className: TokenQuotaPanel_module_css_default.noteNewPlus,
882
+ children: "+"
883
+ })]
653
884
  })]
654
- }), (0, react_jsx_runtime.jsx)("div", {
655
- className: TokenQuotaPanel_module_css_default.subtitle,
656
- children: t("subtitle")
657
885
  })]
658
886
  }), (0, react_jsx_runtime.jsxs)("div", {
659
887
  className: TokenQuotaPanel_module_css_default.headerActions,
@@ -695,8 +923,7 @@ window.__ModuleLoader__.load({
695
923
  })
696
924
  ]
697
925
  })]
698
- }),
699
- (0, react_jsx_runtime.jsxs)("div", {
926
+ }), (0, react_jsx_runtime.jsxs)("div", {
700
927
  className: TokenQuotaPanel_module_css_default.body,
701
928
  children: [
702
929
  loading && (0, react_jsx_runtime.jsx)("div", {
@@ -864,484 +1091,588 @@ window.__ModuleLoader__.load({
864
1091
  }, row.key);
865
1092
  })
866
1093
  ]
867
- }),
868
- dialogOpen && (0, react_jsx_runtime.jsxs)("div", {
869
- ref: settingsRef,
870
- className: `${TokenQuotaPanel_module_css_default.dialog} ${TokenQuotaPanel_module_css_default.settingsDialog}`,
871
- style: settingsPos !== null ? {
872
- left: settingsPos.x,
873
- top: settingsPos.y,
874
- transform: "none"
875
- } : void 0,
876
- children: [
877
- (0, react_jsx_runtime.jsxs)("div", {
878
- className: TokenQuotaPanel_module_css_default.dialogHeader,
1094
+ })]
1095
+ }),
1096
+ dialogOpen && (0, react_jsx_runtime.jsxs)("div", {
1097
+ ref: settingsRef,
1098
+ className: `${TokenQuotaPanel_module_css_default.dialog} ${TokenQuotaPanel_module_css_default.settingsDialog}`,
1099
+ style: settingsPos !== null ? {
1100
+ left: settingsPos.x,
1101
+ top: settingsPos.y,
1102
+ transform: "none"
1103
+ } : void 0,
1104
+ children: [
1105
+ (0, react_jsx_runtime.jsxs)("div", {
1106
+ className: TokenQuotaPanel_module_css_default.dialogHeader,
1107
+ onPointerDown: (event) => {
1108
+ beginDrag(event, settingsRef.current, setSettingsPos);
1109
+ },
1110
+ children: [(0, react_jsx_runtime.jsx)("div", {
1111
+ className: TokenQuotaPanel_module_css_default.dialogTitle,
1112
+ children: t("settingsTitle")
1113
+ }), (0, react_jsx_runtime.jsx)("button", {
1114
+ type: "button",
1115
+ className: TokenQuotaPanel_module_css_default.dialogClose,
1116
+ title: t("close"),
1117
+ onClick: () => {
1118
+ actions.setDialogOpen(false);
1119
+ },
879
1120
  onPointerDown: (event) => {
880
- beginDrag(event, settingsRef.current, setSettingsPos);
1121
+ event.stopPropagation();
881
1122
  },
882
- children: [(0, react_jsx_runtime.jsx)("div", {
883
- className: TokenQuotaPanel_module_css_default.dialogTitle,
884
- children: t("settingsTitle")
885
- }), (0, react_jsx_runtime.jsx)("button", {
1123
+ children: "×"
1124
+ })]
1125
+ }),
1126
+ (0, react_jsx_runtime.jsxs)("div", {
1127
+ className: TokenQuotaPanel_module_css_default.dialogTabs,
1128
+ role: "tablist",
1129
+ children: [
1130
+ (0, react_jsx_runtime.jsx)("button", {
886
1131
  type: "button",
887
- className: TokenQuotaPanel_module_css_default.dialogClose,
888
- title: t("close"),
1132
+ role: "tab",
1133
+ "aria-selected": settingsTab === "quota",
1134
+ className: `${TokenQuotaPanel_module_css_default.dialogTab}${settingsTab === "quota" ? ` ${TokenQuotaPanel_module_css_default.dialogTabActive}` : ""}`,
889
1135
  onClick: () => {
890
- actions.setDialogOpen(false);
1136
+ setSettingsTab("quota");
891
1137
  },
892
- onPointerDown: (event) => {
893
- event.stopPropagation();
1138
+ children: t("settingsTabQuota")
1139
+ }),
1140
+ (0, react_jsx_runtime.jsx)("button", {
1141
+ type: "button",
1142
+ role: "tab",
1143
+ "aria-selected": settingsTab === "music",
1144
+ className: `${TokenQuotaPanel_module_css_default.dialogTab}${settingsTab === "music" ? ` ${TokenQuotaPanel_module_css_default.dialogTabActive}` : ""}`,
1145
+ onClick: () => {
1146
+ setSettingsTab("music");
894
1147
  },
895
- children: "×"
896
- })]
897
- }),
898
- (0, react_jsx_runtime.jsxs)("div", {
899
- className: TokenQuotaPanel_module_css_default.dialogTabs,
900
- role: "tablist",
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
- ]
933
- }),
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", {
938
- className: TokenQuotaPanel_module_css_default.dialogLabel,
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", {
1148
+ children: t("settingsTabMusic")
1149
+ }),
1150
+ (0, react_jsx_runtime.jsx)("button", {
1151
+ type: "button",
1152
+ role: "tab",
1153
+ "aria-selected": settingsTab === "other",
1154
+ className: `${TokenQuotaPanel_module_css_default.dialogTab}${settingsTab === "other" ? ` ${TokenQuotaPanel_module_css_default.dialogTabActive}` : ""}`,
1155
+ onClick: () => {
1156
+ setSettingsTab("other");
1157
+ },
1158
+ children: t("settingsTabOther")
1159
+ })
1160
+ ]
1161
+ }),
1162
+ settingsTab === "quota" && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
1163
+ className: TokenQuotaPanel_module_css_default.dialogSection,
1164
+ children: [
1165
+ (0, react_jsx_runtime.jsx)("div", {
970
1166
  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);
1167
+ children: t("monitorLabel")
1168
+ }),
1169
+ (0, react_jsx_runtime.jsx)("div", {
1170
+ className: TokenQuotaPanel_module_css_default.monitorHint,
1171
+ children: t("monitorHint")
1172
+ }),
1173
+ (0, react_jsx_runtime.jsx)("div", {
1174
+ className: TokenQuotaPanel_module_css_default.monitorList,
1175
+ children: allModels.map((model) => (0, react_jsx_runtime.jsxs)("label", {
1176
+ className: TokenQuotaPanel_module_css_default.monitorRow,
1177
+ children: [(0, react_jsx_runtime.jsx)("input", {
1178
+ type: "checkbox",
1179
+ checked: monitored === null || monitored.includes(model.key),
1180
+ onChange: (event) => {
1181
+ const base = monitored === null ? allModels.map((m) => m.key) : monitored;
1182
+ const next = new Set(base);
1183
+ if (event.target.checked) next.add(model.key);
1184
+ else next.delete(model.key);
1185
+ setMonitored(next.size === allModels.length ? null : [...next]);
1186
+ }
1187
+ }), (0, react_jsx_runtime.jsx)("span", {
1188
+ className: TokenQuotaPanel_module_css_default.monitorName,
1189
+ title: model.key,
1190
+ children: model.name
1191
+ })]
1192
+ }, model.key))
1193
+ })
1194
+ ]
1195
+ }), (0, react_jsx_runtime.jsxs)("div", {
1196
+ className: TokenQuotaPanel_module_css_default.dialogSection,
1197
+ children: [(0, react_jsx_runtime.jsx)("div", {
1198
+ className: TokenQuotaPanel_module_css_default.dialogLabel,
1199
+ children: t("fullActionLabel")
1200
+ }), FULL_ACTIONS.map((action) => (0, react_jsx_runtime.jsxs)("label", {
1201
+ className: TokenQuotaPanel_module_css_default.radioRow,
1202
+ children: [(0, react_jsx_runtime.jsx)("input", {
1203
+ type: "radio",
1204
+ name: "token-quota-onfull",
1205
+ checked: onFull === action.value,
1206
+ onChange: () => {
1207
+ setOnFull(action.value);
1208
+ }
1209
+ }), (0, react_jsx_runtime.jsx)("span", { children: t(action.labelKey) })]
1210
+ }, action.value))]
1211
+ })] }),
1212
+ settingsTab === "other" && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
1213
+ className: TokenQuotaPanel_module_css_default.dialogSection,
1214
+ children: [
1215
+ (0, react_jsx_runtime.jsx)("div", {
1216
+ className: TokenQuotaPanel_module_css_default.dialogLabel,
1217
+ children: t("resetLabel")
1218
+ }),
1219
+ (0, react_jsx_runtime.jsx)("div", {
1220
+ className: TokenQuotaPanel_module_css_default.monitorHint,
1221
+ children: t("resetHint")
1222
+ }),
1223
+ (0, react_jsx_runtime.jsxs)("div", {
1224
+ className: TokenQuotaPanel_module_css_default.resetRow,
1225
+ children: [
1226
+ (0, react_jsx_runtime.jsx)("select", {
1227
+ className: TokenQuotaPanel_module_css_default.resetSelect,
1228
+ value: reset?.offsetHours ?? -(/* @__PURE__ */ new Date()).getTimezoneOffset() / 60,
1229
+ onChange: (event) => {
1230
+ setReset({
1231
+ offsetHours: Number(event.target.value),
1232
+ hour: reset?.hour ?? 0,
1233
+ minute: reset?.minute ?? 0
1234
+ });
1235
+ },
1236
+ children: Array.from({ length: 27 }, (_, i) => i - 12).map((offset) => (0, react_jsx_runtime.jsxs)("option", {
1237
+ value: offset,
1238
+ children: ["UTC", offset >= 0 ? `+${offset}` : offset]
1239
+ }, offset))
1240
+ }),
1241
+ (0, react_jsx_runtime.jsx)("select", {
1242
+ className: TokenQuotaPanel_module_css_default.resetSelect,
1243
+ value: reset?.hour ?? 0,
1244
+ onChange: (event) => {
1245
+ setReset({
1246
+ offsetHours: reset?.offsetHours ?? -(/* @__PURE__ */ new Date()).getTimezoneOffset() / 60,
1247
+ hour: Number(event.target.value),
1248
+ minute: reset?.minute ?? 0
1249
+ });
1250
+ },
1251
+ children: Array.from({ length: 24 }, (_, i) => i).map((hour) => (0, react_jsx_runtime.jsxs)("option", {
1252
+ value: hour,
1253
+ children: [String(hour).padStart(2, "0"), " 时"]
1254
+ }, hour))
1255
+ }),
1256
+ (0, react_jsx_runtime.jsx)("select", {
1257
+ className: TokenQuotaPanel_module_css_default.resetSelect,
1258
+ value: reset?.minute ?? 0,
1259
+ onChange: (event) => {
1260
+ setReset({
1261
+ offsetHours: reset?.offsetHours ?? -(/* @__PURE__ */ new Date()).getTimezoneOffset() / 60,
1262
+ hour: reset?.hour ?? 0,
1263
+ minute: Number(event.target.value)
1264
+ });
1265
+ },
1266
+ children: Array.from({ length: 12 }, (_, i) => i * 5).map((minute) => (0, react_jsx_runtime.jsxs)("option", {
1267
+ value: minute,
1268
+ children: [String(minute).padStart(2, "0"), " 分"]
1269
+ }, minute))
1270
+ })
1271
+ ]
1272
+ })
1273
+ ]
1274
+ }), (0, react_jsx_runtime.jsxs)("div", {
1275
+ className: TokenQuotaPanel_module_css_default.dialogSection,
1276
+ children: [(0, react_jsx_runtime.jsxs)("label", {
1277
+ className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1278
+ children: [(0, react_jsx_runtime.jsx)("input", {
1279
+ type: "checkbox",
1280
+ checked: dimWhenIdle,
1281
+ onChange: (event) => {
1282
+ setDimWhenIdle(event.target.checked);
1283
+ }
1284
+ }), (0, react_jsx_runtime.jsx)("span", { children: t("dimWhenIdleLabel") })]
1285
+ }), (0, react_jsx_runtime.jsx)("div", {
1286
+ className: TokenQuotaPanel_module_css_default.dialogHint,
1287
+ children: t("dimWhenIdleHint")
1288
+ })]
1289
+ })] }),
1290
+ settingsTab === "music" && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("div", {
1291
+ className: TokenQuotaPanel_module_css_default.dialogSection,
1292
+ children: [(0, react_jsx_runtime.jsxs)("label", {
1293
+ className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1294
+ children: [(0, react_jsx_runtime.jsx)("input", {
1295
+ type: "checkbox",
1296
+ checked: musicEnabled,
1297
+ onChange: (event) => {
1298
+ setMusicEnabled(event.target.checked);
1299
+ }
1300
+ }), (0, react_jsx_runtime.jsx)("span", { children: t("musicLabel") })]
1301
+ }), (0, react_jsx_runtime.jsx)("div", {
1302
+ className: TokenQuotaPanel_module_css_default.dialogHint,
1303
+ children: t("musicHint")
1304
+ })]
1305
+ }), musicEnabled && (0, react_jsx_runtime.jsxs)("div", {
1306
+ className: TokenQuotaPanel_module_css_default.dialogSection,
1307
+ children: [
1308
+ (0, react_jsx_runtime.jsxs)("label", {
1309
+ className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1310
+ children: [(0, react_jsx_runtime.jsx)("span", { children: t("musicVolume") }), (0, react_jsx_runtime.jsx)("input", {
1311
+ type: "range",
1312
+ min: 0,
1313
+ max: 1,
1314
+ step: .05,
1315
+ value: musicVolume,
1316
+ onChange: (event) => {
1317
+ setMusicVolume(Number(event.target.value));
980
1318
  }
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,
1319
+ })]
1320
+ }),
1321
+ (0, react_jsx_runtime.jsxs)("label", {
1322
+ className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1323
+ children: [(0, react_jsx_runtime.jsx)("span", { children: t("musicStyle") }), (0, react_jsx_runtime.jsxs)("select", {
1324
+ value: musicStyle,
1325
+ onChange: (event) => {
1326
+ setMusicStyle(event.target.value);
1327
+ },
997
1328
  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))
1329
+ (0, react_jsx_runtime.jsx)("option", {
1330
+ value: "major",
1331
+ children: t("musicStyleMajor")
1012
1332
  }),
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))
1333
+ (0, react_jsx_runtime.jsx)("option", {
1334
+ value: "minor",
1335
+ children: t("musicStyleMinor")
1027
1336
  }),
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))
1337
+ (0, react_jsx_runtime.jsx)("option", {
1338
+ value: "pentatonic",
1339
+ children: t("musicStylePentatonic")
1042
1340
  })
1043
1341
  ]
1044
- })
1045
- ]
1046
- }), (0, react_jsx_runtime.jsxs)("div", {
1047
- className: TokenQuotaPanel_module_css_default.dialogSection,
1048
- children: [(0, react_jsx_runtime.jsxs)("label", {
1342
+ })]
1343
+ }),
1344
+ (0, react_jsx_runtime.jsxs)("label", {
1049
1345
  className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1050
1346
  children: [(0, react_jsx_runtime.jsx)("input", {
1051
1347
  type: "checkbox",
1052
- checked: dimWhenIdle,
1348
+ checked: musicOnlyCurrentSession,
1053
1349
  onChange: (event) => {
1054
- setDimWhenIdle(event.target.checked);
1350
+ setMusicOnlyCurrentSession(event.target.checked);
1055
1351
  }
1056
- }), (0, react_jsx_runtime.jsx)("span", { children: t("dimWhenIdleLabel") })]
1057
- }), (0, react_jsx_runtime.jsx)("div", {
1352
+ }), (0, react_jsx_runtime.jsx)("span", { children: t("musicOnlyCurrentSessionLabel") })]
1353
+ }),
1354
+ (0, react_jsx_runtime.jsx)("div", {
1058
1355
  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,
1356
+ children: t("musicOnlyCurrentSessionHint")
1357
+ })
1358
+ ]
1359
+ })] }),
1360
+ settingsTab === "other" && (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: (0, react_jsx_runtime.jsxs)("div", {
1361
+ className: TokenQuotaPanel_module_css_default.dialogSection,
1362
+ children: [(0, react_jsx_runtime.jsxs)("div", {
1363
+ className: TokenQuotaPanel_module_css_default.checkUpdatesRow,
1064
1364
  children: [(0, react_jsx_runtime.jsxs)("label", {
1065
1365
  className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1066
1366
  children: [(0, react_jsx_runtime.jsx)("input", {
1067
1367
  type: "checkbox",
1068
- checked: musicEnabled,
1368
+ checked: checkUpdates,
1069
1369
  onChange: (event) => {
1070
- setMusicEnabled(event.target.checked);
1370
+ setCheckUpdates(event.target.checked);
1071
1371
  }
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")
1372
+ }), (0, react_jsx_runtime.jsx)("span", { children: t("checkUpdatesLabel") })]
1373
+ }), (0, react_jsx_runtime.jsx)("button", {
1374
+ type: "button",
1375
+ className: TokenQuotaPanel_module_css_default.checkBtn,
1376
+ disabled: checkingUpdates,
1377
+ onClick: checkUpdatesNow,
1378
+ children: checkingUpdates ? t("checkingUpdates") : lastCheckResult === "up-to-date" ? t("checkUpToDate") : lastCheckResult === "error" ? t("checkFailed") : t("checkUpdatesNow")
1076
1379
  })]
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));
1090
- }
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
- },
1100
- children: [
1101
- (0, react_jsx_runtime.jsx)("option", {
1102
- value: "major",
1103
- children: t("musicStyleMajor")
1104
- }),
1105
- (0, react_jsx_runtime.jsx)("option", {
1106
- value: "minor",
1107
- children: t("musicStyleMinor")
1108
- }),
1109
- (0, react_jsx_runtime.jsx)("option", {
1110
- value: "pentatonic",
1111
- children: t("musicStylePentatonic")
1112
- })
1113
- ]
1114
- })]
1115
- }),
1116
- (0, react_jsx_runtime.jsxs)("label", {
1117
- className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1118
- children: [(0, react_jsx_runtime.jsx)("input", {
1119
- type: "checkbox",
1120
- checked: musicOnlyCurrentSession,
1121
- onChange: (event) => {
1122
- setMusicOnlyCurrentSession(event.target.checked);
1123
- }
1124
- }), (0, react_jsx_runtime.jsx)("span", { children: t("musicOnlyCurrentSessionLabel") })]
1125
- }),
1126
- (0, react_jsx_runtime.jsx)("div", {
1127
- className: TokenQuotaPanel_module_css_default.dialogHint,
1128
- children: t("musicOnlyCurrentSessionHint")
1129
- })
1130
- ]
1131
- })] }),
1132
- settingsTab === "other" && (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: (0, react_jsx_runtime.jsxs)("div", {
1133
- className: TokenQuotaPanel_module_css_default.dialogSection,
1134
- children: [(0, react_jsx_runtime.jsxs)("div", {
1135
- className: TokenQuotaPanel_module_css_default.checkUpdatesRow,
1136
- children: [(0, react_jsx_runtime.jsxs)("label", {
1137
- className: TokenQuotaPanel_module_css_default.checkUpdatesLabel,
1138
- children: [(0, react_jsx_runtime.jsx)("input", {
1139
- type: "checkbox",
1140
- checked: checkUpdates,
1141
- onChange: (event) => {
1142
- setCheckUpdates(event.target.checked);
1143
- }
1144
- }), (0, react_jsx_runtime.jsx)("span", { children: t("checkUpdatesLabel") })]
1380
+ }), lastCheckResult === "error" && upgradeError !== null && (0, react_jsx_runtime.jsx)("div", {
1381
+ className: TokenQuotaPanel_module_css_default.checkErrorHint,
1382
+ role: "alert",
1383
+ children: upgradeError
1384
+ })]
1385
+ }) })
1386
+ ]
1387
+ }),
1388
+ logOpen && (0, react_jsx_runtime.jsxs)("div", {
1389
+ ref: logRef,
1390
+ className: `${TokenQuotaPanel_module_css_default.dialog} ${TokenQuotaPanel_module_css_default.logDialog}`,
1391
+ style: logPos !== null ? {
1392
+ left: logPos.x,
1393
+ top: logPos.y,
1394
+ transform: "none"
1395
+ } : void 0,
1396
+ children: [
1397
+ (0, react_jsx_runtime.jsxs)("div", {
1398
+ className: TokenQuotaPanel_module_css_default.logHeader,
1399
+ onPointerDown: (event) => {
1400
+ beginDrag(event, logRef.current, setLogPos);
1401
+ },
1402
+ children: [
1403
+ (0, react_jsx_runtime.jsx)("div", {
1404
+ className: TokenQuotaPanel_module_css_default.dialogTitle,
1405
+ children: t("logsTitle")
1406
+ }),
1407
+ (0, react_jsx_runtime.jsxs)("div", {
1408
+ className: TokenQuotaPanel_module_css_default.logToolbar,
1409
+ onPointerDown: (event) => {
1410
+ event.stopPropagation();
1411
+ },
1412
+ children: [(0, react_jsx_runtime.jsx)("input", {
1413
+ type: "search",
1414
+ className: TokenQuotaPanel_module_css_default.logSearch,
1415
+ placeholder: t("logSearchPlaceholder"),
1416
+ value: logSearch,
1417
+ onChange: (event) => {
1418
+ actions.setLogSearch(event.target.value);
1419
+ }
1145
1420
  }), (0, react_jsx_runtime.jsx)("button", {
1146
1421
  type: "button",
1147
- className: TokenQuotaPanel_module_css_default.checkBtn,
1148
- disabled: checkingUpdates,
1149
- onClick: checkUpdatesNow,
1150
- children: checkingUpdates ? t("checkingUpdates") : lastCheckResult === "up-to-date" ? t("checkUpToDate") : lastCheckResult === "error" ? t("checkFailed") : t("checkUpdatesNow")
1422
+ className: TokenQuotaPanel_module_css_default.logClearBtn,
1423
+ onClick: () => {
1424
+ actions.setLogClearOpen(true);
1425
+ },
1426
+ children: t("logClear")
1151
1427
  })]
1152
- }), lastCheckResult === "error" && upgradeError !== null && (0, react_jsx_runtime.jsx)("div", {
1153
- className: TokenQuotaPanel_module_css_default.checkErrorHint,
1154
- role: "alert",
1155
- children: upgradeError
1156
- })]
1157
- }) })
1158
- ]
1159
- }),
1160
- logOpen && (0, react_jsx_runtime.jsxs)("div", {
1161
- ref: logRef,
1162
- className: `${TokenQuotaPanel_module_css_default.dialog} ${TokenQuotaPanel_module_css_default.logDialog}`,
1163
- style: logPos !== null ? {
1164
- left: logPos.x,
1165
- top: logPos.y,
1166
- transform: "none"
1167
- } : void 0,
1168
- children: [
1169
- (0, react_jsx_runtime.jsxs)("div", {
1170
- className: TokenQuotaPanel_module_css_default.logHeader,
1171
- onPointerDown: (event) => {
1172
- beginDrag(event, logRef.current, setLogPos);
1173
- },
1174
- children: [
1175
- (0, react_jsx_runtime.jsx)("div", {
1176
- className: TokenQuotaPanel_module_css_default.dialogTitle,
1177
- children: t("logsTitle")
1428
+ }),
1429
+ (0, react_jsx_runtime.jsx)("button", {
1430
+ type: "button",
1431
+ className: TokenQuotaPanel_module_css_default.dialogClose,
1432
+ title: t("close"),
1433
+ onClick: () => {
1434
+ actions.setLogOpen(false);
1435
+ },
1436
+ children: "×"
1437
+ })
1438
+ ]
1439
+ }),
1440
+ log !== null && filteredLogEntries.length === 0 && (0, react_jsx_runtime.jsx)("div", {
1441
+ className: TokenQuotaPanel_module_css_default.notice,
1442
+ children: logSearch.trim() !== "" ? t("logNoMatch") : t("logEmpty")
1443
+ }),
1444
+ (0, react_jsx_runtime.jsx)("div", {
1445
+ className: TokenQuotaPanel_module_css_default.logScroll,
1446
+ children: (0, react_jsx_runtime.jsxs)("table", {
1447
+ className: TokenQuotaPanel_module_css_default.logTable,
1448
+ children: [(0, react_jsx_runtime.jsx)("thead", { children: (0, react_jsx_runtime.jsxs)("tr", { children: [
1449
+ (0, react_jsx_runtime.jsx)("th", { children: t("logDay") }),
1450
+ (0, react_jsx_runtime.jsx)("th", { children: t("logModel") }),
1451
+ (0, react_jsx_runtime.jsx)("th", {
1452
+ className: TokenQuotaPanel_module_css_default.logUsedCol,
1453
+ children: t("logUsed")
1454
+ })
1455
+ ] }) }), (0, react_jsx_runtime.jsx)("tbody", { children: logPageEntries.map((entry) => (0, react_jsx_runtime.jsxs)("tr", { children: [
1456
+ (0, react_jsx_runtime.jsx)("td", {
1457
+ className: TokenQuotaPanel_module_css_default.logDayCol,
1458
+ children: entry.day
1459
+ }),
1460
+ (0, react_jsx_runtime.jsx)("td", {
1461
+ className: TokenQuotaPanel_module_css_default.logModelCol,
1462
+ title: entry.key,
1463
+ children: entry.key
1178
1464
  }),
1179
- (0, react_jsx_runtime.jsxs)("div", {
1180
- className: TokenQuotaPanel_module_css_default.logToolbar,
1181
- onPointerDown: (event) => {
1182
- event.stopPropagation();
1465
+ (0, react_jsx_runtime.jsx)("td", {
1466
+ className: TokenQuotaPanel_module_css_default.logUsedCol,
1467
+ children: formatTokens(entry.used)
1468
+ })
1469
+ ] }, `${entry.day}/${entry.key}`)) })]
1470
+ })
1471
+ }),
1472
+ (0, react_jsx_runtime.jsxs)("div", {
1473
+ className: TokenQuotaPanel_module_css_default.logPager,
1474
+ children: [(0, react_jsx_runtime.jsx)("span", {
1475
+ className: TokenQuotaPanel_module_css_default.logPagerInfo,
1476
+ children: t("logPagerInfo").replace("{from}", String(logCurrentPage * logPageSize + 1)).replace("{to}", String(Math.min((logCurrentPage + 1) * logPageSize, filteredLogEntries.length))).replace("{total}", String(filteredLogEntries.length))
1477
+ }), (0, react_jsx_runtime.jsxs)("div", {
1478
+ className: TokenQuotaPanel_module_css_default.logPagerControls,
1479
+ children: [
1480
+ (0, react_jsx_runtime.jsx)("button", {
1481
+ type: "button",
1482
+ className: TokenQuotaPanel_module_css_default.logPagerBtn,
1483
+ disabled: logCurrentPage <= 0,
1484
+ onClick: () => {
1485
+ actions.setLogPage(logCurrentPage - 1);
1183
1486
  },
1184
- children: [(0, react_jsx_runtime.jsx)("input", {
1185
- type: "search",
1186
- className: TokenQuotaPanel_module_css_default.logSearch,
1187
- placeholder: t("logSearchPlaceholder"),
1188
- value: logSearch,
1189
- onChange: (event) => {
1190
- actions.setLogSearch(event.target.value);
1191
- }
1192
- }), (0, react_jsx_runtime.jsx)("button", {
1193
- type: "button",
1194
- className: TokenQuotaPanel_module_css_default.logClearBtn,
1195
- onClick: () => {
1196
- actions.setLogClearOpen(true);
1197
- },
1198
- children: t("logClear")
1199
- })]
1487
+ children: "‹"
1488
+ }),
1489
+ (0, react_jsx_runtime.jsxs)("span", {
1490
+ className: TokenQuotaPanel_module_css_default.logPagerPages,
1491
+ children: [
1492
+ logCurrentPage + 1,
1493
+ " / ",
1494
+ logTotalPages
1495
+ ]
1200
1496
  }),
1201
1497
  (0, react_jsx_runtime.jsx)("button", {
1202
1498
  type: "button",
1203
- className: TokenQuotaPanel_module_css_default.dialogClose,
1204
- title: t("close"),
1499
+ className: TokenQuotaPanel_module_css_default.logPagerBtn,
1500
+ disabled: logCurrentPage >= logTotalPages - 1,
1205
1501
  onClick: () => {
1206
- actions.setLogOpen(false);
1502
+ actions.setLogPage(logCurrentPage + 1);
1207
1503
  },
1208
- children: "×"
1504
+ children: "›"
1505
+ }),
1506
+ (0, react_jsx_runtime.jsx)("select", {
1507
+ className: TokenQuotaPanel_module_css_default.logPageSizeSelect,
1508
+ value: logPageSize,
1509
+ onChange: (event) => {
1510
+ actions.setLogPageSize(Number(event.target.value));
1511
+ },
1512
+ children: [
1513
+ 10,
1514
+ 15,
1515
+ 20,
1516
+ 50,
1517
+ 100
1518
+ ].map((size) => (0, react_jsx_runtime.jsxs)("option", {
1519
+ value: size,
1520
+ children: [size, t("logPerPage")]
1521
+ }, size))
1209
1522
  })
1210
1523
  ]
1211
- }),
1212
- log !== null && filteredLogEntries.length === 0 && (0, react_jsx_runtime.jsx)("div", {
1213
- className: TokenQuotaPanel_module_css_default.notice,
1214
- children: logSearch.trim() !== "" ? t("logNoMatch") : t("logEmpty")
1524
+ })]
1525
+ })
1526
+ ]
1527
+ }),
1528
+ logClearOpen && (0, react_jsx_runtime.jsx)("div", {
1529
+ className: TokenQuotaPanel_module_css_default.dialogOverlay,
1530
+ children: (0, react_jsx_runtime.jsxs)("div", {
1531
+ className: `${TokenQuotaPanel_module_css_default.dialog} ${TokenQuotaPanel_module_css_default.logClearDialog}`,
1532
+ children: [
1533
+ (0, react_jsx_runtime.jsx)("div", {
1534
+ className: TokenQuotaPanel_module_css_default.dialogTitle,
1535
+ children: t("logClearTitle")
1215
1536
  }),
1216
1537
  (0, react_jsx_runtime.jsx)("div", {
1217
- className: TokenQuotaPanel_module_css_default.logScroll,
1218
- children: (0, react_jsx_runtime.jsxs)("table", {
1219
- className: TokenQuotaPanel_module_css_default.logTable,
1220
- children: [(0, react_jsx_runtime.jsx)("thead", { children: (0, react_jsx_runtime.jsxs)("tr", { children: [
1221
- (0, react_jsx_runtime.jsx)("th", { children: t("logDay") }),
1222
- (0, react_jsx_runtime.jsx)("th", { children: t("logModel") }),
1223
- (0, react_jsx_runtime.jsx)("th", {
1224
- className: TokenQuotaPanel_module_css_default.logUsedCol,
1225
- children: t("logUsed")
1226
- })
1227
- ] }) }), (0, react_jsx_runtime.jsx)("tbody", { children: logPageEntries.map((entry) => (0, react_jsx_runtime.jsxs)("tr", { children: [
1228
- (0, react_jsx_runtime.jsx)("td", {
1229
- className: TokenQuotaPanel_module_css_default.logDayCol,
1230
- children: entry.day
1231
- }),
1232
- (0, react_jsx_runtime.jsx)("td", {
1233
- className: TokenQuotaPanel_module_css_default.logModelCol,
1234
- title: entry.key,
1235
- children: entry.key
1236
- }),
1237
- (0, react_jsx_runtime.jsx)("td", {
1238
- className: TokenQuotaPanel_module_css_default.logUsedCol,
1239
- children: formatTokens(entry.used)
1240
- })
1241
- ] }, `${entry.day}/${entry.key}`)) })]
1242
- })
1538
+ className: TokenQuotaPanel_module_css_default.dialogBody,
1539
+ children: t("logClearHint")
1540
+ }),
1541
+ (0, react_jsx_runtime.jsx)("input", {
1542
+ type: "date",
1543
+ className: TokenQuotaPanel_module_css_default.logClearDate,
1544
+ value: logClearBefore,
1545
+ onChange: (event) => {
1546
+ actions.setLogClearBefore(event.target.value);
1547
+ }
1243
1548
  }),
1244
1549
  (0, react_jsx_runtime.jsxs)("div", {
1245
- className: TokenQuotaPanel_module_css_default.logPager,
1246
- children: [(0, react_jsx_runtime.jsx)("span", {
1247
- className: TokenQuotaPanel_module_css_default.logPagerInfo,
1248
- children: t("logPagerInfo").replace("{from}", String(logCurrentPage * logPageSize + 1)).replace("{to}", String(Math.min((logCurrentPage + 1) * logPageSize, filteredLogEntries.length))).replace("{total}", String(filteredLogEntries.length))
1249
- }), (0, react_jsx_runtime.jsxs)("div", {
1250
- className: TokenQuotaPanel_module_css_default.logPagerControls,
1251
- children: [
1252
- (0, react_jsx_runtime.jsx)("button", {
1253
- type: "button",
1254
- className: TokenQuotaPanel_module_css_default.logPagerBtn,
1255
- disabled: logCurrentPage <= 0,
1256
- onClick: () => {
1257
- actions.setLogPage(logCurrentPage - 1);
1258
- },
1259
- children: "‹"
1260
- }),
1261
- (0, react_jsx_runtime.jsxs)("span", {
1262
- className: TokenQuotaPanel_module_css_default.logPagerPages,
1263
- children: [
1264
- logCurrentPage + 1,
1265
- " / ",
1266
- logTotalPages
1267
- ]
1268
- }),
1269
- (0, react_jsx_runtime.jsx)("button", {
1270
- type: "button",
1271
- className: TokenQuotaPanel_module_css_default.logPagerBtn,
1272
- disabled: logCurrentPage >= logTotalPages - 1,
1273
- onClick: () => {
1274
- actions.setLogPage(logCurrentPage + 1);
1275
- },
1276
- children: "›"
1277
- }),
1278
- (0, react_jsx_runtime.jsx)("select", {
1279
- className: TokenQuotaPanel_module_css_default.logPageSizeSelect,
1280
- value: logPageSize,
1281
- onChange: (event) => {
1282
- actions.setLogPageSize(Number(event.target.value));
1283
- },
1284
- children: [
1285
- 10,
1286
- 15,
1287
- 20,
1288
- 50,
1289
- 100
1290
- ].map((size) => (0, react_jsx_runtime.jsxs)("option", {
1291
- value: size,
1292
- children: [size, t("logPerPage")]
1293
- }, size))
1294
- })
1295
- ]
1550
+ className: TokenQuotaPanel_module_css_default.dialogActions,
1551
+ children: [(0, react_jsx_runtime.jsx)("button", {
1552
+ type: "button",
1553
+ className: TokenQuotaPanel_module_css_default.checkBtn,
1554
+ disabled: logClearBefore === "" || logClearing,
1555
+ onClick: () => {
1556
+ clearLogBefore(logClearBefore);
1557
+ },
1558
+ children: logClearing ? t("logClearing") : t("logClearConfirm")
1559
+ }), (0, react_jsx_runtime.jsx)("button", {
1560
+ type: "button",
1561
+ className: TokenQuotaPanel_module_css_default.checkBtn,
1562
+ onClick: () => {
1563
+ actions.setLogClearOpen(false);
1564
+ },
1565
+ children: t("logClearCancel")
1296
1566
  })]
1297
1567
  })
1298
1568
  ]
1299
- }),
1300
- logClearOpen && (0, react_jsx_runtime.jsx)("div", {
1301
- className: TokenQuotaPanel_module_css_default.dialogOverlay,
1302
- children: (0, react_jsx_runtime.jsxs)("div", {
1303
- className: `${TokenQuotaPanel_module_css_default.dialog} ${TokenQuotaPanel_module_css_default.logClearDialog}`,
1304
- children: [
1305
- (0, react_jsx_runtime.jsx)("div", {
1306
- className: TokenQuotaPanel_module_css_default.dialogTitle,
1307
- children: t("logClearTitle")
1308
- }),
1309
- (0, react_jsx_runtime.jsx)("div", {
1310
- className: TokenQuotaPanel_module_css_default.dialogBody,
1311
- children: t("logClearHint")
1312
- }),
1313
- (0, react_jsx_runtime.jsx)("input", {
1314
- type: "date",
1315
- className: TokenQuotaPanel_module_css_default.logClearDate,
1316
- value: logClearBefore,
1317
- onChange: (event) => {
1318
- actions.setLogClearBefore(event.target.value);
1319
- }
1320
- }),
1321
- (0, react_jsx_runtime.jsxs)("div", {
1322
- className: TokenQuotaPanel_module_css_default.dialogActions,
1323
- children: [(0, react_jsx_runtime.jsx)("button", {
1324
- type: "button",
1325
- className: TokenQuotaPanel_module_css_default.checkBtn,
1326
- disabled: logClearBefore === "" || logClearing,
1327
- onClick: () => {
1328
- clearLogBefore(logClearBefore);
1329
- },
1330
- children: logClearing ? t("logClearing") : t("logClearConfirm")
1331
- }), (0, react_jsx_runtime.jsx)("button", {
1332
- type: "button",
1333
- className: TokenQuotaPanel_module_css_default.checkBtn,
1334
- onClick: () => {
1335
- actions.setLogClearOpen(false);
1336
- },
1337
- children: t("logClearCancel")
1338
- })]
1339
- })
1340
- ]
1341
- })
1342
1569
  })
1343
- ]
1344
- });
1570
+ }),
1571
+ notes.filter((note) => note.visible).map((note) => (0, react_jsx_runtime.jsxs)("div", {
1572
+ className: `${TokenQuotaPanel_module_css_default.noteWin}${note.collapsed ? ` ${TokenQuotaPanel_module_css_default.noteWinCollapsed}` : ""}`,
1573
+ style: {
1574
+ left: `${note.x}px`,
1575
+ top: `${note.y}px`,
1576
+ width: `${note.width}px`,
1577
+ zIndex: activeNote === note.id ? 62 : 60,
1578
+ ...note.collapsed ? {} : { height: `${note.height}px` }
1579
+ },
1580
+ onPointerDown: () => {
1581
+ setActiveNote(note.id);
1582
+ },
1583
+ children: [(0, react_jsx_runtime.jsxs)("div", {
1584
+ className: TokenQuotaPanel_module_css_default.noteWinBar,
1585
+ onPointerDown: (event) => {
1586
+ beginNoteBarDrag(event, note.id);
1587
+ },
1588
+ children: [
1589
+ (0, react_jsx_runtime.jsx)("span", {
1590
+ className: TokenQuotaPanel_module_css_default.noteWinGripBar,
1591
+ "aria-hidden": "true",
1592
+ children: "⠿"
1593
+ }),
1594
+ (0, react_jsx_runtime.jsx)("input", {
1595
+ className: TokenQuotaPanel_module_css_default.noteWinTitle,
1596
+ value: note.title,
1597
+ placeholder: t("noteUntitled"),
1598
+ title: t("noteRenameHint"),
1599
+ onChange: (event) => {
1600
+ patchNote(note.id, { title: event.target.value }, false);
1601
+ },
1602
+ onKeyDown: (event) => {
1603
+ if (event.key === "Enter") event.currentTarget.blur();
1604
+ }
1605
+ }),
1606
+ (0, react_jsx_runtime.jsx)("button", {
1607
+ type: "button",
1608
+ className: TokenQuotaPanel_module_css_default.noteWinBtn,
1609
+ title: note.collapsed ? t("noteExpand") : t("noteCollapse"),
1610
+ onClick: () => {
1611
+ patchNote(note.id, { collapsed: !note.collapsed });
1612
+ },
1613
+ children: note.collapsed ? "▸" : "▾"
1614
+ }),
1615
+ (0, react_jsx_runtime.jsx)("button", {
1616
+ type: "button",
1617
+ className: TokenQuotaPanel_module_css_default.noteWinBtn,
1618
+ title: t("noteCloseHint"),
1619
+ onClick: () => {
1620
+ closeNote(note.id);
1621
+ },
1622
+ children: "×"
1623
+ })
1624
+ ]
1625
+ }), !note.collapsed && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("textarea", {
1626
+ className: TokenQuotaPanel_module_css_default.noteWinText,
1627
+ value: note.text,
1628
+ placeholder: t("notePlaceholder"),
1629
+ spellCheck: false,
1630
+ onChange: (event) => {
1631
+ patchNote(note.id, { text: event.target.value }, false);
1632
+ }
1633
+ }), (0, react_jsx_runtime.jsx)("span", {
1634
+ className: TokenQuotaPanel_module_css_default.noteWinResize,
1635
+ title: t("noteResizeHint"),
1636
+ onPointerDown: (event) => {
1637
+ beginResize(event, event.currentTarget.parentElement, (size) => {
1638
+ patchNote(note.id, size, false);
1639
+ });
1640
+ }
1641
+ })] })]
1642
+ }, note.id)),
1643
+ noteMenu !== null && (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("div", {
1644
+ className: TokenQuotaPanel_module_css_default.noteMenuBackdrop,
1645
+ onPointerDown: () => {
1646
+ setNoteMenu(null);
1647
+ },
1648
+ onContextMenu: (event) => {
1649
+ event.preventDefault();
1650
+ setNoteMenu(null);
1651
+ }
1652
+ }), (0, react_jsx_runtime.jsxs)("div", {
1653
+ className: TokenQuotaPanel_module_css_default.noteMenu,
1654
+ style: {
1655
+ left: `${noteMenu.x}px`,
1656
+ top: `${noteMenu.y}px`
1657
+ },
1658
+ children: [(0, react_jsx_runtime.jsx)("button", {
1659
+ type: "button",
1660
+ className: TokenQuotaPanel_module_css_default.noteMenuItem,
1661
+ onClick: () => {
1662
+ closeNote(noteMenu.id);
1663
+ setNoteMenu(null);
1664
+ },
1665
+ children: t("noteClose")
1666
+ }), (0, react_jsx_runtime.jsx)("button", {
1667
+ type: "button",
1668
+ className: TokenQuotaPanel_module_css_default.noteMenuItem,
1669
+ onClick: () => {
1670
+ removeNote(noteMenu.id);
1671
+ },
1672
+ children: t("noteDelete")
1673
+ })]
1674
+ })] })
1675
+ ] });
1345
1676
  }
1346
1677
  //#endregion
1347
1678
  //#region lib/types/client/music.js
@@ -1994,6 +2325,17 @@ window.__ModuleLoader__.load({
1994
2325
  settingsTabMusic: "音乐设置",
1995
2326
  settingsTabOther: "其它",
1996
2327
  reorderHint: "拖动排序",
2328
+ noteNewHint: "新建笔记(最多 5 个)",
2329
+ noteMaxHint: "最多 5 个笔记",
2330
+ noteUntitled: "未命名",
2331
+ noteRenameHint: "点击可修改标题",
2332
+ noteCollapse: "收起",
2333
+ noteExpand: "展开",
2334
+ noteClose: "关闭(内容保留)",
2335
+ noteCloseHint: "关闭(内容保留,可从首字图标重新打开)",
2336
+ noteDelete: "删除笔记",
2337
+ noteResizeHint: "拖动改变大小",
2338
+ notePlaceholder: "在这里记录…",
1997
2339
  monitorLabel: "监控模型",
1998
2340
  monitorHint: "未勾选的模型不显示、不计入用量、不受限额限制",
1999
2341
  monitorAll: "全部",
@@ -2076,6 +2418,17 @@ window.__ModuleLoader__.load({
2076
2418
  settingsTabMusic: "Music",
2077
2419
  settingsTabOther: "Other",
2078
2420
  reorderHint: "Drag to reorder",
2421
+ noteNewHint: "New note (max 5)",
2422
+ noteMaxHint: "At most 5 notes",
2423
+ noteUntitled: "Untitled",
2424
+ noteRenameHint: "Click to rename",
2425
+ noteCollapse: "Collapse",
2426
+ noteExpand: "Expand",
2427
+ noteClose: "Close (keep content)",
2428
+ noteCloseHint: "Close but keep the content; reopen from its chip",
2429
+ noteDelete: "Delete note",
2430
+ noteResizeHint: "Drag to resize",
2431
+ notePlaceholder: "Write here…",
2079
2432
  monitorLabel: "Monitored models",
2080
2433
  monitorHint: "Unchecked models are hidden, not metered, and never capped",
2081
2434
  monitorAll: "All",
@@ -2212,6 +2565,28 @@ window.__ModuleLoader__.load({
2212
2565
  window.removeEventListener("pointerdown", autoStartMusic);
2213
2566
  window.removeEventListener("keydown", autoStartMusic);
2214
2567
  }, "token-quota-ui: music autostart gestures");
2568
+ /**
2569
+ * Coerce the persisted note array into complete notes: older documents may
2570
+ * lack fields added later, and a hand-edited file may hold junk. The cap is
2571
+ * enforced here too so a tampered document cannot grow past it.
2572
+ */
2573
+ const normalizeNotes = (raw) => {
2574
+ if (!Array.isArray(raw)) return [];
2575
+ return raw.slice(0, 5).flatMap((note) => {
2576
+ if (typeof note !== "object" || note === null || typeof note.id !== "string") return [];
2577
+ return [{
2578
+ id: note.id,
2579
+ title: typeof note.title === "string" ? note.title : "",
2580
+ text: typeof note.text === "string" ? note.text : "",
2581
+ x: typeof note.x === "number" ? note.x : 80,
2582
+ y: typeof note.y === "number" ? note.y : 80,
2583
+ width: typeof note.width === "number" ? note.width : 220,
2584
+ height: typeof note.height === "number" ? note.height : 220,
2585
+ collapsed: note.collapsed === true,
2586
+ visible: note.visible !== false
2587
+ }];
2588
+ });
2589
+ };
2215
2590
  /** Build a writable music-settings clone with defaults applied. */
2216
2591
  const musicDefaults = (raw) => ({
2217
2592
  enabled: raw?.enabled ?? false,
@@ -2328,6 +2703,7 @@ window.__ModuleLoader__.load({
2328
2703
  bound?.setCheckUpdates(doc?.checkUpdates ?? true);
2329
2704
  bound?.setDimWhenIdle(doc?.dimWhenIdle ?? false);
2330
2705
  bound?.setOrder(Array.isArray(doc?.order) ? doc.order : []);
2706
+ bound?.setNotes(normalizeNotes(doc?.notes));
2331
2707
  bound?.setReset(lastReset);
2332
2708
  const musicSettings = musicDefaults(doc?.music);
2333
2709
  lastOnlyCurrentSession = musicSettings.onlyCurrentSession;
@@ -2413,6 +2789,10 @@ window.__ModuleLoader__.load({
2413
2789
  bound?.setOrder(order);
2414
2790
  scope.set("order", order);
2415
2791
  };
2792
+ /** Persist the floating scratchpad notes (content, title, placement). */
2793
+ const saveNotes = (notes) => {
2794
+ scope.set("notes", notes.slice(0, 5));
2795
+ };
2416
2796
  const setMusicEnabled = (enabled) => {
2417
2797
  const doc = scope.getSnapshot().value;
2418
2798
  const current = musicDefaults(doc?.music);
@@ -2526,7 +2906,8 @@ window.__ModuleLoader__.load({
2526
2906
  setMusicVolume,
2527
2907
  setMusicStyle,
2528
2908
  setMusicOnlyCurrentSession,
2529
- setModelOrder
2909
+ setModelOrder,
2910
+ saveNotes
2530
2911
  };
2531
2912
  };
2532
2913
  ctx.slots.inject("shell.overlay", () => ctx.slots.register({