dsh-subscriptions 0.1.3 → 0.1.4
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/README.md +64 -0
- package/lib/auth/rpc.d.ts +3 -1
- package/lib/auth/rpc.js +10 -1
- package/lib/client/ProviderAccountManager.js +34 -41
- package/lib/client/ProviderModelEditor.js +5 -9
- package/lib/client/SpeedSelect.js +8 -7
- package/lib/client/SubscriptionUsageBadge.js +6 -5
- package/lib/client/SubscriptionsSection.d.ts +22 -0
- package/lib/client/SubscriptionsSection.js +128 -38
- package/lib/client/UsageBadgeDisplaySetting.js +4 -8
- package/lib/client/host-contract.d.ts +1 -1
- package/lib/client/host-contract.js +22 -0
- package/lib/client/locales.d.ts +58 -0
- package/lib/client/locales.js +58 -0
- package/lib/client/provider-settings-styles.d.ts +3 -0
- package/lib/client/provider-settings-styles.js +206 -0
- package/lib/client/reset-action.d.ts +14 -0
- package/lib/client/reset-action.js +15 -0
- package/lib/client/reset-credits-view.d.ts +53 -0
- package/lib/client/reset-credits-view.js +103 -0
- package/lib/client.js +937 -310
- package/lib/client.js.map +1 -1
- package/lib/index.d.ts +9 -0
- package/lib/index.js +1099 -608
- package/lib/providers/account-preferences.js +3 -2
- package/lib/providers/catalog-store.d.ts +3 -2
- package/lib/providers/catalog-store.js +57 -26
- package/lib/providers/claude.d.ts +22 -3
- package/lib/providers/claude.js +113 -15
- package/lib/providers/codex.d.ts +15 -2
- package/lib/providers/codex.js +72 -4
- package/lib/providers/common.d.ts +25 -0
- package/lib/providers/common.js +22 -18
- package/lib/providers/copilot.d.ts +2 -1
- package/lib/providers/copilot.js +10 -3
- package/lib/providers/grok.d.ts +2 -2
- package/lib/providers/grok.js +2 -2
- package/lib/providers/pool-health.d.ts +2 -0
- package/lib/providers/pool-health.js +9 -0
- package/lib/providers/pool-usage.d.ts +13 -1
- package/lib/providers/pool-usage.js +39 -7
- package/lib/providers/pool.d.ts +7 -5
- package/lib/providers/pool.js +89 -12
- package/lib/providers/rate-limit.d.ts +0 -14
- package/lib/providers/rate-limit.js +0 -26
- package/lib/providers/replay.d.ts +4 -0
- package/lib/providers/replay.js +50 -0
- package/lib/providers/reset-redemption.d.ts +51 -0
- package/lib/providers/reset-redemption.js +102 -0
- package/lib/translate/anthropic.d.ts +21 -2
- package/lib/translate/anthropic.js +35 -11
- package/lib/translate/antigravity.js +13 -6
- package/lib/translate/chat-completions.js +1 -1
- package/lib/translate/resolved.d.ts +21 -0
- package/lib/translate/resolved.js +63 -3
- package/lib/translate/responses.js +8 -6
- package/lib/translate/sse.js +8 -0
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -139,6 +139,35 @@ const en = {
|
|
|
139
139
|
usageColorPaceHint: "Yellow when usage leads elapsed time by {allowance} points; red at 90% used takes priority. Saved in this browser; only colors change.",
|
|
140
140
|
usageColorRemainingHint: "Red at 90% used; no yellow pace warnings. Reliable time markers remain visible. Saved in this browser.",
|
|
141
141
|
usagePlan: "Plan: {plan}",
|
|
142
|
+
resetCreditsTitle: "Usage limit resets",
|
|
143
|
+
resetCreditsAvailable: "{count} available",
|
|
144
|
+
resetCreditsError: "Usage limit resets unavailable: {message}",
|
|
145
|
+
resetCreditsErrorFixed: "Usage limit resets are unavailable. Refresh usage to try again.",
|
|
146
|
+
resetCreditReadOnly: "Read only. This page cannot spend a Claude reset.",
|
|
147
|
+
resetCreditReadOnlyLabel: "Read only",
|
|
148
|
+
resetCreditAvailable: "Available",
|
|
149
|
+
resetCreditNotUsable: "Not yet usable",
|
|
150
|
+
resetCreditPaused: "Paused",
|
|
151
|
+
resetCreditExhausted: "Exhausted",
|
|
152
|
+
resetCreditExpired: "Expired",
|
|
153
|
+
resetCreditRemaining: "{left} of {total} left",
|
|
154
|
+
resetCreditLeft: "{left} left",
|
|
155
|
+
resetCreditRemainingUnknown: "Remaining count unavailable",
|
|
156
|
+
resetCreditCooldownUntil: "Usable after {date}",
|
|
157
|
+
resetUseButton: "Use…",
|
|
158
|
+
resetUseChecking: "Checking…",
|
|
159
|
+
resetUseGuard: "You can use this reset when weekly usage reaches at least 80%.",
|
|
160
|
+
resetUseRestart: "Reset details are missing. Restart DSH, reload this page, then refresh usage.",
|
|
161
|
+
resetUseRefresh: "Refresh usage to verify current limits and reset availability.",
|
|
162
|
+
resetUseReady: "Use this reset — the earliest-expiring credit. Confirmation required.",
|
|
163
|
+
resetUseConfirmTitle: "Confirm full reset",
|
|
164
|
+
resetUseWarning: "This consumes one credit and resets weekly + 5-hour limits. This interface cannot undo it. Confirmation expires in 60 seconds.",
|
|
165
|
+
resetUseAcknowledge: "I understand that one credit will be consumed.",
|
|
166
|
+
resetUseConfirm: "Consume 1 reset",
|
|
167
|
+
resetUseSuccess: "Reset confirmed. Usage refreshed.",
|
|
168
|
+
resetCreditFull: "Full reset",
|
|
169
|
+
resetCreditExpires: "Expires {date}",
|
|
170
|
+
resetCreditExpiryUnknown: "Expiry date unavailable",
|
|
142
171
|
externalUsageTitle: "Built-in provider usage",
|
|
143
172
|
externalUsageConnected: "API key configured",
|
|
144
173
|
externalUsageNotConfigured: "Not configured",
|
|
@@ -311,6 +340,35 @@ const zh = {
|
|
|
311
340
|
usageColorPaceHint: "用量领先时间进度 {allowance} 个百分点时变黄;已用达到 90% 时优先变红。自动保存到当前浏览器,仅改变配色。",
|
|
312
341
|
usageColorRemainingHint: "已用达到 90% 时变红,不显示黄色节奏警告。可靠的时间标记仍保留,自动保存到当前浏览器。",
|
|
313
342
|
usagePlan: "计划:{plan}",
|
|
343
|
+
resetCreditsTitle: "用量限制重置",
|
|
344
|
+
resetCreditsAvailable: "可用 {count} 次",
|
|
345
|
+
resetCreditsError: "用量限制重置查询失败:{message}",
|
|
346
|
+
resetCreditsErrorFixed: "用量限制重置暂不可用,请刷新用量后重试。",
|
|
347
|
+
resetCreditReadOnly: "只读。此页面不能消耗 Claude 的重置额度。",
|
|
348
|
+
resetCreditReadOnlyLabel: "只读",
|
|
349
|
+
resetCreditAvailable: "可用",
|
|
350
|
+
resetCreditNotUsable: "暂不可用",
|
|
351
|
+
resetCreditPaused: "已暂停",
|
|
352
|
+
resetCreditExhausted: "已用尽",
|
|
353
|
+
resetCreditExpired: "已过期",
|
|
354
|
+
resetCreditRemaining: "剩余 {left} / {total}",
|
|
355
|
+
resetCreditLeft: "剩余 {left}",
|
|
356
|
+
resetCreditRemainingUnknown: "剩余次数不可用",
|
|
357
|
+
resetCreditCooldownUntil: "{date} 后可用",
|
|
358
|
+
resetUseButton: "使用…",
|
|
359
|
+
resetUseChecking: "正在检查…",
|
|
360
|
+
resetUseGuard: "每周用量达到 80% 后才可使用此重置。",
|
|
361
|
+
resetUseRestart: "缺少重置详情。请重启 DSH、重新加载页面并刷新用量。",
|
|
362
|
+
resetUseRefresh: "请刷新用量以验证当前限制和重置可用性。",
|
|
363
|
+
resetUseReady: "使用此最早到期的重置额度,操作前需要确认。",
|
|
364
|
+
resetUseConfirmTitle: "确认完整重置",
|
|
365
|
+
resetUseWarning: "将消耗一次额度并重置每周和 5 小时限制,无法撤销。确认将在 60 秒后过期。",
|
|
366
|
+
resetUseAcknowledge: "我理解将消耗一次额度。",
|
|
367
|
+
resetUseConfirm: "消耗一次重置",
|
|
368
|
+
resetUseSuccess: "重置已确认,用量已刷新。",
|
|
369
|
+
resetCreditFull: "完整重置",
|
|
370
|
+
resetCreditExpires: "{date} 到期",
|
|
371
|
+
resetCreditExpiryUnknown: "到期时间不可用",
|
|
314
372
|
externalUsageTitle: "内置供应商用量",
|
|
315
373
|
externalUsageConnected: "已配置 API 密钥",
|
|
316
374
|
externalUsageNotConfigured: "未配置",
|
|
@@ -379,6 +437,18 @@ const zh = {
|
|
|
379
437
|
commandFastUnavailable: "当前模型不支持快速档;/fast 仅对目录声明了 fast tier 的 Codex 模型可用"
|
|
380
438
|
};
|
|
381
439
|
|
|
440
|
+
//#endregion
|
|
441
|
+
//#region src/client/reset-action.ts
|
|
442
|
+
/** Explain client-side gating; the server independently revalidates before spending. */
|
|
443
|
+
function resetActionBlock(usage, now = Date.now()) {
|
|
444
|
+
const weekly = usage.windows?.find((w) => w.kind === "weekly" && w.scope === void 0);
|
|
445
|
+
if (!weekly || !Number.isFinite(weekly.usedPercent)) return "resetUseRefresh";
|
|
446
|
+
if (weekly.usedPercent < 80) return "resetUseGuard";
|
|
447
|
+
if (weekly.resetsAt === void 0 || weekly.resetsAt <= now || usage.resetCreditsError) return "resetUseRefresh";
|
|
448
|
+
if (!usage.resetCredits?.some((c) => c.id)) return "resetUseRestart";
|
|
449
|
+
if (!usage.resetCredits.some((c) => c.id && (c.expiresAt === void 0 || c.expiresAt > now))) return "resetUseRefresh";
|
|
450
|
+
}
|
|
451
|
+
|
|
382
452
|
//#endregion
|
|
383
453
|
//#region src/client/subscriptions-rpc.ts
|
|
384
454
|
/**
|
|
@@ -451,16 +521,7 @@ function mergeAccountChanges(latest, changes) {
|
|
|
451
521
|
|
|
452
522
|
//#endregion
|
|
453
523
|
//#region src/client/ProviderModelEditor.tsx
|
|
454
|
-
const border$1 = "
|
|
455
|
-
const control$1 = {
|
|
456
|
-
font: "inherit",
|
|
457
|
-
color: "inherit",
|
|
458
|
-
background: "transparent",
|
|
459
|
-
border: border$1,
|
|
460
|
-
borderRadius: 8,
|
|
461
|
-
padding: "6px 10px",
|
|
462
|
-
minWidth: 0
|
|
463
|
-
};
|
|
524
|
+
const border$1 = "0.5px solid var(--dsw-alias-border-l2, #ddd)";
|
|
464
525
|
const actions$1 = {
|
|
465
526
|
display: "flex",
|
|
466
527
|
flexWrap: "wrap",
|
|
@@ -569,10 +630,7 @@ const ProviderModelEditor = (0, react.forwardRef)(function ProviderModelEditor$1
|
|
|
569
630
|
paddingTop: 12
|
|
570
631
|
},
|
|
571
632
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
572
|
-
style: {
|
|
573
|
-
margin: 0,
|
|
574
|
-
fontSize: 15
|
|
575
|
-
},
|
|
633
|
+
style: { margin: 0 },
|
|
576
634
|
children: t("modelsEdit")
|
|
577
635
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
578
636
|
style: {
|
|
@@ -582,22 +640,18 @@ const ProviderModelEditor = (0, react.forwardRef)(function ProviderModelEditor$1
|
|
|
582
640
|
},
|
|
583
641
|
children: [
|
|
584
642
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
585
|
-
|
|
643
|
+
className: "dsh-subscription-hint",
|
|
586
644
|
children: t(provider === "cursor-subscription" ? "cursorManageHint" : "modelsHint")
|
|
587
645
|
}),
|
|
588
646
|
error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
589
647
|
role: "alert",
|
|
590
|
-
style: {
|
|
591
|
-
margin: 0,
|
|
592
|
-
color: "var(--dsw-alias-state-error-primary, #b42318)"
|
|
593
|
-
},
|
|
594
648
|
children: error
|
|
595
649
|
}),
|
|
596
650
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
597
651
|
style: actions$1,
|
|
598
652
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
599
653
|
type: "button",
|
|
600
|
-
|
|
654
|
+
className: "dsh-subscription-quiet",
|
|
601
655
|
disabled: busy || disabled || dirty,
|
|
602
656
|
onClick: () => {
|
|
603
657
|
load(true);
|
|
@@ -637,10 +691,7 @@ const ProviderModelEditor = (0, react.forwardRef)(function ProviderModelEditor$1
|
|
|
637
691
|
style: actions$1,
|
|
638
692
|
children: [
|
|
639
693
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
640
|
-
style: {
|
|
641
|
-
...control$1,
|
|
642
|
-
flex: "1 1 180px"
|
|
643
|
-
},
|
|
694
|
+
style: { flex: "1 1 180px" },
|
|
644
695
|
value: query,
|
|
645
696
|
onChange: (event) => setQuery(event.target.value),
|
|
646
697
|
placeholder: t("modelDefaultsFilterPlaceholder"),
|
|
@@ -648,7 +699,6 @@ const ProviderModelEditor = (0, react.forwardRef)(function ProviderModelEditor$1
|
|
|
648
699
|
}),
|
|
649
700
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
650
701
|
type: "button",
|
|
651
|
-
style: control$1,
|
|
652
702
|
onClick: () => edit({
|
|
653
703
|
...draft,
|
|
654
704
|
visibleModels: allModels.map((model) => model.id)
|
|
@@ -657,7 +707,6 @@ const ProviderModelEditor = (0, react.forwardRef)(function ProviderModelEditor$1
|
|
|
657
707
|
}),
|
|
658
708
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
659
709
|
type: "button",
|
|
660
|
-
style: control$1,
|
|
661
710
|
onClick: () => edit({
|
|
662
711
|
...draft,
|
|
663
712
|
visibleModels: []
|
|
@@ -705,7 +754,6 @@ const ProviderModelEditor = (0, react.forwardRef)(function ProviderModelEditor$1
|
|
|
705
754
|
children: [(model.efforts?.length ?? 0) > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
706
755
|
style: actions$1,
|
|
707
756
|
children: [t("modelDefaultsTitle"), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
|
|
708
|
-
style: control$1,
|
|
709
757
|
"aria-label": `${model.name} ${t("modelDefaultsTitle")}`,
|
|
710
758
|
value: efforts[model.id] ?? "",
|
|
711
759
|
onChange: (event) => {
|
|
@@ -741,10 +789,7 @@ const ProviderModelEditor = (0, react.forwardRef)(function ProviderModelEditor$1
|
|
|
741
789
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
742
790
|
style: actions$1,
|
|
743
791
|
children: [t("modelsContext"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
744
|
-
style: {
|
|
745
|
-
...control$1,
|
|
746
|
-
width: 140
|
|
747
|
-
},
|
|
792
|
+
style: { width: 140 },
|
|
748
793
|
inputMode: "numeric",
|
|
749
794
|
value: contexts[model.id] ?? "",
|
|
750
795
|
"aria-label": `${model.name} ${t("modelsContext")}`,
|
|
@@ -798,28 +843,218 @@ const ProviderModelEditor = (0, react.forwardRef)(function ProviderModelEditor$1
|
|
|
798
843
|
});
|
|
799
844
|
});
|
|
800
845
|
|
|
846
|
+
//#endregion
|
|
847
|
+
//#region src/client/provider-settings-styles.ts
|
|
848
|
+
/**
|
|
849
|
+
* The host loads one JS client bundle, so keep this small, scoped stylesheet
|
|
850
|
+
* with the dialog instead of relying on a separate CSS asset. Geometry and
|
|
851
|
+
* theme tokens follow the host's settings-form and ui-primitives controls.
|
|
852
|
+
*
|
|
853
|
+
* `color-scheme` is left to the host deliberately. Its boot script sets the
|
|
854
|
+
* property on `:root`, and it inherits, so native controls inside these panels
|
|
855
|
+
* follow the theme. Upstream also pins `color-scheme: light` here and flips it
|
|
856
|
+
* back under `body[data-ds-dark-theme]`; without that flip our scoped rules are
|
|
857
|
+
* more specific than `:root` and would force every native control light inside
|
|
858
|
+
* a dark theme.
|
|
859
|
+
*/
|
|
860
|
+
const formScope = ":is(.dsh-subscription-manager, .dsh-subscriptions-settings)";
|
|
861
|
+
const providerSettingsCss = `
|
|
862
|
+
.dsh-subscription-manager {
|
|
863
|
+
box-sizing: border-box;
|
|
864
|
+
padding: 0;
|
|
865
|
+
border: 0;
|
|
866
|
+
border-radius: var(--dsw-radius-panel, 16px);
|
|
867
|
+
background: var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1));
|
|
868
|
+
color: var(--dsw-alias-label-primary);
|
|
869
|
+
box-shadow: var(--dsw-elevation-prominent, 0 20px 70px #0004);
|
|
870
|
+
font-family: inherit;
|
|
871
|
+
font-size: 13px;
|
|
872
|
+
line-height: 1.5;
|
|
873
|
+
}
|
|
874
|
+
.dsh-subscriptions-settings {
|
|
875
|
+
font-family: inherit;
|
|
876
|
+
font-size: 13px;
|
|
877
|
+
line-height: 1.5;
|
|
878
|
+
}
|
|
879
|
+
.dsh-subscription-manager::backdrop {
|
|
880
|
+
background: var(--dsw-alias-bg-mask-1, #0006);
|
|
881
|
+
backdrop-filter: var(--dsw-mask-blur, none);
|
|
882
|
+
}
|
|
883
|
+
${formScope} h2 {
|
|
884
|
+
font-size: 16px;
|
|
885
|
+
line-height: 24px;
|
|
886
|
+
font-weight: 500;
|
|
887
|
+
}
|
|
888
|
+
${formScope} h3 {
|
|
889
|
+
font-size: 14px;
|
|
890
|
+
line-height: 22px;
|
|
891
|
+
font-weight: 500;
|
|
892
|
+
}
|
|
893
|
+
${formScope} strong,
|
|
894
|
+
${formScope} .dsh-subscription-label {
|
|
895
|
+
font-size: 13px;
|
|
896
|
+
line-height: 1.5;
|
|
897
|
+
font-weight: 500;
|
|
898
|
+
}
|
|
899
|
+
${formScope} legend {
|
|
900
|
+
font-size: 14px;
|
|
901
|
+
line-height: 22px;
|
|
902
|
+
font-weight: 500;
|
|
903
|
+
}
|
|
904
|
+
${formScope} small,
|
|
905
|
+
${formScope} .dsh-subscription-hint,
|
|
906
|
+
${formScope} [role="status"] {
|
|
907
|
+
margin: 0;
|
|
908
|
+
font-size: 12px;
|
|
909
|
+
line-height: 1.5;
|
|
910
|
+
color: var(--dsw-alias-label-tertiary);
|
|
911
|
+
}
|
|
912
|
+
${formScope} [role="alert"] {
|
|
913
|
+
margin: 0;
|
|
914
|
+
font-size: 12px;
|
|
915
|
+
line-height: 1.5;
|
|
916
|
+
color: var(--dsw-alias-state-error-primary, #b42318);
|
|
917
|
+
}
|
|
918
|
+
${formScope} input:not([type="checkbox"]),
|
|
919
|
+
${formScope} select {
|
|
920
|
+
box-sizing: border-box;
|
|
921
|
+
min-width: 0;
|
|
922
|
+
height: 34px;
|
|
923
|
+
padding: 0 12px;
|
|
924
|
+
border: 0.5px solid var(--dsw-alias-border-l4, var(--dsw-alias-border-l2));
|
|
925
|
+
border-radius: var(--dsw-radius-md, 8px);
|
|
926
|
+
background: var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-layer-1));
|
|
927
|
+
color: var(--dsw-alias-label-primary);
|
|
928
|
+
font: inherit;
|
|
929
|
+
font-size: 13px;
|
|
930
|
+
font-weight: 400;
|
|
931
|
+
line-height: 1.5;
|
|
932
|
+
}
|
|
933
|
+
${formScope} input::placeholder {
|
|
934
|
+
color: var(--dsw-alias-label-tertiary);
|
|
935
|
+
opacity: 1;
|
|
936
|
+
}
|
|
937
|
+
${formScope} input:not([type="checkbox"]):focus-visible,
|
|
938
|
+
${formScope} select:focus-visible {
|
|
939
|
+
outline: none;
|
|
940
|
+
border-color: var(--dsw-alias-state-business-primary, var(--dsw-alias-brand-primary));
|
|
941
|
+
}
|
|
942
|
+
${formScope} input:not([type="checkbox"]):disabled,
|
|
943
|
+
${formScope} select:disabled {
|
|
944
|
+
color: var(--dsw-alias-label-tertiary);
|
|
945
|
+
cursor: default;
|
|
946
|
+
}
|
|
947
|
+
${formScope} input[aria-invalid="true"] {
|
|
948
|
+
border-color: var(--dsw-alias-state-error-primary, #b42318);
|
|
949
|
+
}
|
|
950
|
+
${formScope} option {
|
|
951
|
+
background: var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1));
|
|
952
|
+
color: var(--dsw-alias-label-primary);
|
|
953
|
+
}
|
|
954
|
+
${formScope} label:has(> input[type="checkbox"]) {
|
|
955
|
+
display: flex;
|
|
956
|
+
align-items: flex-start;
|
|
957
|
+
gap: 6px;
|
|
958
|
+
font-size: 14px;
|
|
959
|
+
line-height: 20px;
|
|
960
|
+
cursor: pointer;
|
|
961
|
+
}
|
|
962
|
+
${formScope} input[type="checkbox"] {
|
|
963
|
+
flex: 0 0 auto;
|
|
964
|
+
width: 16px;
|
|
965
|
+
height: 16px;
|
|
966
|
+
margin: 2px 0;
|
|
967
|
+
accent-color: var(--dsw-alias-brand-primary);
|
|
968
|
+
cursor: inherit;
|
|
969
|
+
}
|
|
970
|
+
${formScope} label:has(> input[type="checkbox"]:disabled) {
|
|
971
|
+
cursor: default;
|
|
972
|
+
opacity: 0.5;
|
|
973
|
+
}
|
|
974
|
+
${formScope} button {
|
|
975
|
+
box-sizing: border-box;
|
|
976
|
+
display: inline-flex;
|
|
977
|
+
align-items: center;
|
|
978
|
+
justify-content: center;
|
|
979
|
+
flex-shrink: 0;
|
|
980
|
+
min-height: 28px;
|
|
981
|
+
padding: 0 10px;
|
|
982
|
+
border: 0.5px solid var(--dsw-alias-border-l3, var(--dsw-alias-border-l2));
|
|
983
|
+
border-radius: var(--dsw-radius-sm, 6px);
|
|
984
|
+
background: transparent;
|
|
985
|
+
color: var(--dsw-alias-label-primary);
|
|
986
|
+
font: inherit;
|
|
987
|
+
font-size: 12px;
|
|
988
|
+
line-height: 18px;
|
|
989
|
+
cursor: pointer;
|
|
990
|
+
}
|
|
991
|
+
${formScope} button:hover:not(:disabled) {
|
|
992
|
+
background: var(--dsw-alias-interactive-bg-hover, var(--dsw-alias-bg-layer-3));
|
|
993
|
+
}
|
|
994
|
+
${formScope} button:active:not(:disabled) {
|
|
995
|
+
background: var(--dsw-alias-interactive-bg-active, var(--dsw-alias-bg-layer-3));
|
|
996
|
+
}
|
|
997
|
+
${formScope} button:disabled {
|
|
998
|
+
opacity: 0.4;
|
|
999
|
+
cursor: default;
|
|
1000
|
+
}
|
|
1001
|
+
${formScope} button.dsh-subscription-quiet {
|
|
1002
|
+
border-color: transparent;
|
|
1003
|
+
color: var(--dsw-alias-label-secondary, var(--dsw-alias-label-primary));
|
|
1004
|
+
}
|
|
1005
|
+
${formScope} :is(footer, .dsh-subscription-dialog-actions) button {
|
|
1006
|
+
min-height: 34px;
|
|
1007
|
+
padding: 0 14px;
|
|
1008
|
+
border-radius: var(--dsw-radius-md, 8px);
|
|
1009
|
+
font-size: 13px;
|
|
1010
|
+
line-height: 1.5;
|
|
1011
|
+
}
|
|
1012
|
+
${formScope} button.dsh-subscription-primary {
|
|
1013
|
+
border-color: transparent;
|
|
1014
|
+
background: var(--dsw-alias-button-primary-fill, var(--dsw-alias-label-primary));
|
|
1015
|
+
color: var(--dsw-alias-label-primary-foreground, var(--dsw-alias-bg-layer-1));
|
|
1016
|
+
font-weight: 500;
|
|
1017
|
+
}
|
|
1018
|
+
${formScope} button.dsh-subscription-primary:hover:not(:disabled) {
|
|
1019
|
+
background: var(--dsw-alias-button-primary-hover, var(--dsw-alias-label-secondary));
|
|
1020
|
+
}
|
|
1021
|
+
${formScope} button:focus-visible,
|
|
1022
|
+
${formScope} input[type="checkbox"]:focus-visible,
|
|
1023
|
+
${formScope} summary:focus-visible {
|
|
1024
|
+
outline: var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));
|
|
1025
|
+
outline-offset: 2px;
|
|
1026
|
+
}
|
|
1027
|
+
${formScope} summary {
|
|
1028
|
+
border-radius: var(--dsw-radius-sm, 6px);
|
|
1029
|
+
}
|
|
1030
|
+
${formScope} summary:hover {
|
|
1031
|
+
color: var(--dsw-alias-label-secondary, var(--dsw-alias-label-primary));
|
|
1032
|
+
}
|
|
1033
|
+
`;
|
|
1034
|
+
/** Composer controls retain their own geometry, separate from settings forms. */
|
|
1035
|
+
const subscriptionChromeCss = `
|
|
1036
|
+
.dsh-subscription-usage-pill { corner-shape: round; }
|
|
1037
|
+
.dsh-subscription-usage-panel {
|
|
1038
|
+
--dsw-elevation-stroke-color: var(--dsw-alias-border-l1);
|
|
1039
|
+
backdrop-filter: var(--dsw-menu-backdrop-filter, none);
|
|
1040
|
+
}
|
|
1041
|
+
.dsh-subscription-speed button:hover:not(:disabled) {
|
|
1042
|
+
--dsh-subscription-speed-hover: var(--dsw-alias-interactive-bg-hover);
|
|
1043
|
+
}
|
|
1044
|
+
.dsh-subscription-speed button:active:not(:disabled) {
|
|
1045
|
+
--dsh-subscription-speed-hover: var(--dsw-alias-interactive-bg-active);
|
|
1046
|
+
}
|
|
1047
|
+
.dsh-subscription-speed button:disabled { opacity: 0.4; cursor: default; }
|
|
1048
|
+
.dsh-subscription-speed button:focus-visible,
|
|
1049
|
+
.dsh-subscription-usage-pill:focus-visible {
|
|
1050
|
+
outline: var(--dsw-focus-ring-width, 2px) solid var(--dsw-focus-ring-color, var(--dsw-alias-state-business-primary));
|
|
1051
|
+
outline-offset: 2px;
|
|
1052
|
+
}
|
|
1053
|
+
`;
|
|
1054
|
+
|
|
801
1055
|
//#endregion
|
|
802
1056
|
//#region src/client/ProviderAccountManager.tsx
|
|
803
|
-
const border = "
|
|
804
|
-
const control = {
|
|
805
|
-
font: "inherit",
|
|
806
|
-
color: "inherit",
|
|
807
|
-
background: "var(--dsw-alias-bg-layer-1)",
|
|
808
|
-
border,
|
|
809
|
-
borderRadius: 8,
|
|
810
|
-
padding: "7px 12px",
|
|
811
|
-
minWidth: 0
|
|
812
|
-
};
|
|
813
|
-
const button = {
|
|
814
|
-
...control,
|
|
815
|
-
cursor: "pointer"
|
|
816
|
-
};
|
|
817
|
-
const hint = {
|
|
818
|
-
margin: 0,
|
|
819
|
-
fontSize: 12,
|
|
820
|
-
lineHeight: 1.6,
|
|
821
|
-
color: "var(--dsw-alias-label-tertiary)"
|
|
822
|
-
};
|
|
1057
|
+
const border = "0.5px solid var(--dsw-alias-border-l2)";
|
|
823
1058
|
const stack = {
|
|
824
1059
|
display: "grid",
|
|
825
1060
|
gap: 12,
|
|
@@ -924,7 +1159,8 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
924
1159
|
if (alive.current) setSaving(false);
|
|
925
1160
|
}
|
|
926
1161
|
}
|
|
927
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
1162
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dialog", {
|
|
1163
|
+
className: "dsh-subscription-manager",
|
|
928
1164
|
ref: dialog,
|
|
929
1165
|
"aria-labelledby": title,
|
|
930
1166
|
"aria-describedby": description,
|
|
@@ -936,16 +1172,9 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
936
1172
|
width: 620,
|
|
937
1173
|
maxWidth: "calc(100vw - 32px)",
|
|
938
1174
|
maxHeight: "calc(100dvh - 32px)",
|
|
939
|
-
boxSizing: "border-box",
|
|
940
|
-
padding: 0,
|
|
941
|
-
border,
|
|
942
|
-
borderRadius: 16,
|
|
943
|
-
color: "var(--dsw-alias-label-primary)",
|
|
944
|
-
background: "var(--dsw-alias-bg-layer-1)",
|
|
945
|
-
boxShadow: "0 20px 70px #0004",
|
|
946
1175
|
overflow: "auto"
|
|
947
1176
|
},
|
|
948
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1177
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: providerSettingsCss }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
949
1178
|
style: {
|
|
950
1179
|
...stack,
|
|
951
1180
|
padding: 20
|
|
@@ -958,15 +1187,11 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
958
1187
|
},
|
|
959
1188
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
960
1189
|
id: title,
|
|
961
|
-
style: {
|
|
962
|
-
margin: 0,
|
|
963
|
-
fontSize: 18
|
|
964
|
-
},
|
|
1190
|
+
style: { margin: 0 },
|
|
965
1191
|
children: t("accountsTitle", { provider: name })
|
|
966
1192
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
967
1193
|
type: "button",
|
|
968
1194
|
autoFocus: true,
|
|
969
|
-
style: button,
|
|
970
1195
|
disabled: saving,
|
|
971
1196
|
onClick: onClose,
|
|
972
1197
|
children: t("imageClose")
|
|
@@ -974,25 +1199,20 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
974
1199
|
}),
|
|
975
1200
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
976
1201
|
id: description,
|
|
977
|
-
|
|
1202
|
+
className: "dsh-subscription-hint",
|
|
978
1203
|
children: t(provider === "cursor-subscription" ? "cursorAccountsHint" : "accountsHint")
|
|
979
1204
|
}),
|
|
980
1205
|
error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
981
1206
|
role: "alert",
|
|
982
|
-
style: {
|
|
983
|
-
...hint,
|
|
984
|
-
color: "var(--dsw-alias-state-error-primary)"
|
|
985
|
-
},
|
|
986
1207
|
children: error
|
|
987
1208
|
}),
|
|
988
1209
|
loading && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
989
1210
|
role: "status",
|
|
990
|
-
|
|
1211
|
+
className: "dsh-subscription-hint",
|
|
991
1212
|
children: t("accountsLoading")
|
|
992
1213
|
}),
|
|
993
1214
|
!loading && !catalog && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
994
1215
|
type: "button",
|
|
995
|
-
style: button,
|
|
996
1216
|
onClick: () => setAttempt((value) => value + 1),
|
|
997
1217
|
children: t("modelDefaultsRetry")
|
|
998
1218
|
}),
|
|
@@ -1006,24 +1226,20 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
1006
1226
|
},
|
|
1007
1227
|
children: [
|
|
1008
1228
|
catalog.accounts.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1009
|
-
|
|
1229
|
+
className: "dsh-subscription-hint",
|
|
1010
1230
|
children: t(provider === "cursor-subscription" ? "cursorManageSignIn" : "accountsEmpty")
|
|
1011
1231
|
}),
|
|
1012
1232
|
provider === "cursor-subscription" && catalog.accounts.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("fieldset", {
|
|
1013
1233
|
style: {
|
|
1014
1234
|
border,
|
|
1015
|
-
borderRadius:
|
|
1235
|
+
borderRadius: "var(--dsw-radius-lg, 12px)",
|
|
1016
1236
|
padding: 14
|
|
1017
1237
|
},
|
|
1018
1238
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("legend", {
|
|
1019
|
-
style: {
|
|
1020
|
-
padding: "0 6px",
|
|
1021
|
-
fontWeight: 600,
|
|
1022
|
-
fontSize: 14
|
|
1023
|
-
},
|
|
1239
|
+
style: { padding: "0 6px" },
|
|
1024
1240
|
children: name
|
|
1025
1241
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1026
|
-
|
|
1242
|
+
className: "dsh-subscription-hint",
|
|
1027
1243
|
children: t("cursorConnected")
|
|
1028
1244
|
})]
|
|
1029
1245
|
}),
|
|
@@ -1035,7 +1251,7 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
1035
1251
|
style: {
|
|
1036
1252
|
...stack,
|
|
1037
1253
|
border,
|
|
1038
|
-
borderRadius:
|
|
1254
|
+
borderRadius: "var(--dsw-radius-lg, 12px)",
|
|
1039
1255
|
padding: 14,
|
|
1040
1256
|
margin: 0
|
|
1041
1257
|
},
|
|
@@ -1043,15 +1259,13 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
1043
1259
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("legend", {
|
|
1044
1260
|
style: {
|
|
1045
1261
|
padding: "0 6px",
|
|
1046
|
-
fontWeight: 600,
|
|
1047
|
-
fontSize: 14,
|
|
1048
1262
|
overflowWrap: "anywhere",
|
|
1049
1263
|
maxWidth: "100%"
|
|
1050
1264
|
},
|
|
1051
1265
|
children: account.label
|
|
1052
1266
|
}),
|
|
1053
1267
|
account.unavailable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1054
|
-
|
|
1268
|
+
className: "dsh-subscription-hint",
|
|
1055
1269
|
children: t("accountsCatalogUnavailable")
|
|
1056
1270
|
}),
|
|
1057
1271
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
@@ -1060,10 +1274,9 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
1060
1274
|
gap: 6
|
|
1061
1275
|
},
|
|
1062
1276
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1063
|
-
|
|
1277
|
+
className: "dsh-subscription-label",
|
|
1064
1278
|
children: t("accountsAlias")
|
|
1065
1279
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1066
|
-
style: control,
|
|
1067
1280
|
value: preferences.alias ?? "",
|
|
1068
1281
|
placeholder: account.label,
|
|
1069
1282
|
onChange: (event) => {
|
|
@@ -1099,7 +1312,7 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
1099
1312
|
t("accountsIndependent")
|
|
1100
1313
|
] }),
|
|
1101
1314
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1102
|
-
|
|
1315
|
+
className: "dsh-subscription-hint",
|
|
1103
1316
|
children: t("accountsIndependentHint")
|
|
1104
1317
|
}),
|
|
1105
1318
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", {
|
|
@@ -1119,7 +1332,7 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
1119
1332
|
},
|
|
1120
1333
|
children: [
|
|
1121
1334
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1122
|
-
|
|
1335
|
+
className: "dsh-subscription-hint",
|
|
1123
1336
|
children: t("accountsModelsHint")
|
|
1124
1337
|
}),
|
|
1125
1338
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [
|
|
@@ -1140,7 +1353,6 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
1140
1353
|
style: actions,
|
|
1141
1354
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1142
1355
|
type: "button",
|
|
1143
|
-
style: button,
|
|
1144
1356
|
onClick: () => edit(account.key, {
|
|
1145
1357
|
...preferences,
|
|
1146
1358
|
poolModels: models.map((model) => model.id)
|
|
@@ -1148,7 +1360,6 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
1148
1360
|
children: t("modelsSelectAll")
|
|
1149
1361
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1150
1362
|
type: "button",
|
|
1151
|
-
style: button,
|
|
1152
1363
|
onClick: () => edit(account.key, {
|
|
1153
1364
|
...preferences,
|
|
1154
1365
|
poolModels: []
|
|
@@ -1164,10 +1375,7 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
1164
1375
|
overflowY: "auto"
|
|
1165
1376
|
},
|
|
1166
1377
|
children: [models.map((model) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
1167
|
-
style: {
|
|
1168
|
-
fontSize: 13,
|
|
1169
|
-
overflowWrap: "anywhere"
|
|
1170
|
-
},
|
|
1378
|
+
style: { overflowWrap: "anywhere" },
|
|
1171
1379
|
children: [
|
|
1172
1380
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
1173
1381
|
type: "checkbox",
|
|
@@ -1187,7 +1395,7 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
1187
1395
|
model.unavailable && ` (${t("modelsUnavailable")})`
|
|
1188
1396
|
]
|
|
1189
1397
|
}, model.id)), models.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1190
|
-
|
|
1398
|
+
className: "dsh-subscription-hint",
|
|
1191
1399
|
children: t("accountsNoModels")
|
|
1192
1400
|
})]
|
|
1193
1401
|
})
|
|
@@ -1211,17 +1419,13 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
1211
1419
|
...stack,
|
|
1212
1420
|
gap: 8,
|
|
1213
1421
|
borderTop: border,
|
|
1214
|
-
padding: "14px 0
|
|
1422
|
+
padding: "14px 0 8px",
|
|
1215
1423
|
position: "sticky",
|
|
1216
1424
|
bottom: 0,
|
|
1217
|
-
background: "var(--dsw-alias-bg-layer-1)"
|
|
1425
|
+
background: "var(--dsw-alias-bg-layer-2, var(--dsw-alias-bg-layer-1))"
|
|
1218
1426
|
},
|
|
1219
1427
|
children: [saveError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1220
1428
|
role: "alert",
|
|
1221
|
-
style: {
|
|
1222
|
-
...hint,
|
|
1223
|
-
color: "var(--dsw-alias-state-error-primary)"
|
|
1224
|
-
},
|
|
1225
1429
|
children: saveError
|
|
1226
1430
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1227
1431
|
style: {
|
|
@@ -1230,16 +1434,12 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
1230
1434
|
},
|
|
1231
1435
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1232
1436
|
type: "button",
|
|
1233
|
-
style: button,
|
|
1234
1437
|
disabled: saving,
|
|
1235
1438
|
onClick: onClose,
|
|
1236
1439
|
children: t("cancel")
|
|
1237
1440
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1238
1441
|
type: "button",
|
|
1239
|
-
|
|
1240
|
-
...button,
|
|
1241
|
-
fontWeight: 600
|
|
1242
|
-
},
|
|
1442
|
+
className: "dsh-subscription-primary",
|
|
1243
1443
|
disabled: loading || saving || !Object.keys(changes).length && !modelsDirty,
|
|
1244
1444
|
onClick: () => {
|
|
1245
1445
|
save();
|
|
@@ -1249,7 +1449,7 @@ function ProviderAccountManager({ provider, name, rpc, t, onClose }) {
|
|
|
1249
1449
|
})]
|
|
1250
1450
|
})
|
|
1251
1451
|
]
|
|
1252
|
-
})
|
|
1452
|
+
})]
|
|
1253
1453
|
});
|
|
1254
1454
|
}
|
|
1255
1455
|
|
|
@@ -2064,6 +2264,216 @@ function CursorCard({ rpc, t }) {
|
|
|
2064
2264
|
});
|
|
2065
2265
|
}
|
|
2066
2266
|
|
|
2267
|
+
//#endregion
|
|
2268
|
+
//#region src/client/reset-credits-view.tsx
|
|
2269
|
+
const STATE_KEYS = {
|
|
2270
|
+
available: "resetCreditAvailable",
|
|
2271
|
+
notUsable: "resetCreditNotUsable",
|
|
2272
|
+
paused: "resetCreditPaused",
|
|
2273
|
+
exhausted: "resetCreditExhausted",
|
|
2274
|
+
expired: "resetCreditExpired"
|
|
2275
|
+
};
|
|
2276
|
+
/**
|
|
2277
|
+
* Classify one grant. Expired outranks every other flag. A future
|
|
2278
|
+
* `cooldownUntil` or `usableNow: false` is not usable even when `claimable`
|
|
2279
|
+
* is true. `claimable` does not change the word: it is not an action.
|
|
2280
|
+
*/
|
|
2281
|
+
function resetCreditState(credit, now) {
|
|
2282
|
+
if (credit.expiresAt !== void 0 && credit.expiresAt <= now) return "expired";
|
|
2283
|
+
if (credit.paused === true) return "paused";
|
|
2284
|
+
if (credit.resetsLeft === 0) return "exhausted";
|
|
2285
|
+
if (credit.cooldownUntil !== void 0 && credit.cooldownUntil > now || credit.usableNow === false) return "notUsable";
|
|
2286
|
+
return "available";
|
|
2287
|
+
}
|
|
2288
|
+
/**
|
|
2289
|
+
* Headline count. Codex passes one entry per credit, so the count is the
|
|
2290
|
+
* list length. Claude passes one entry per grant, so the count is the sum of
|
|
2291
|
+
* `resetsLeft` on grants that are neither expired nor paused. A missing
|
|
2292
|
+
* `resetsLeft` adds nothing; the row says the count is unavailable.
|
|
2293
|
+
*/
|
|
2294
|
+
function resetCreditsAvailableCount(credits, now, mode) {
|
|
2295
|
+
if (mode === "credits") return credits.length;
|
|
2296
|
+
let sum = 0;
|
|
2297
|
+
for (const credit of credits) {
|
|
2298
|
+
const state = resetCreditState(credit, now);
|
|
2299
|
+
if (state === "expired" || state === "paused") continue;
|
|
2300
|
+
if (typeof credit.resetsLeft === "number" && Number.isFinite(credit.resetsLeft) && credit.resetsLeft > 0) sum += credit.resetsLeft;
|
|
2301
|
+
}
|
|
2302
|
+
return sum;
|
|
2303
|
+
}
|
|
2304
|
+
function expiryText(t, credit) {
|
|
2305
|
+
return credit.expiresAt === void 0 ? t("resetCreditExpiryUnknown") : t("resetCreditExpires", { date: new Date(credit.expiresAt).toLocaleString() });
|
|
2306
|
+
}
|
|
2307
|
+
function remainingText(t, credit) {
|
|
2308
|
+
const left = credit.resetsLeft;
|
|
2309
|
+
const total = credit.resetsTotal;
|
|
2310
|
+
const hasLeft = typeof left === "number" && Number.isFinite(left);
|
|
2311
|
+
if (hasLeft && typeof total === "number" && Number.isFinite(total)) return t("resetCreditRemaining", {
|
|
2312
|
+
left,
|
|
2313
|
+
total
|
|
2314
|
+
});
|
|
2315
|
+
if (hasLeft) return t("resetCreditLeft", { left });
|
|
2316
|
+
return t("resetCreditRemainingUnknown");
|
|
2317
|
+
}
|
|
2318
|
+
/** Accessible name of one Claude grant row: state, remaining, and expiry, not a control name. */
|
|
2319
|
+
function resetCreditRowName(t, credit, now) {
|
|
2320
|
+
const state = resetCreditState(credit, now);
|
|
2321
|
+
const parts = [
|
|
2322
|
+
t("resetCreditFull"),
|
|
2323
|
+
t(STATE_KEYS[state]),
|
|
2324
|
+
remainingText(t, credit),
|
|
2325
|
+
expiryText(t, credit)
|
|
2326
|
+
];
|
|
2327
|
+
if (state === "notUsable" && credit.cooldownUntil !== void 0 && credit.cooldownUntil > now) parts.push(t("resetCreditCooldownUntil", { date: new Date(credit.cooldownUntil).toLocaleString() }));
|
|
2328
|
+
return parts.join(", ");
|
|
2329
|
+
}
|
|
2330
|
+
/** Claude omits an empty grant list; Codex still shows a defined, possibly empty, list. */
|
|
2331
|
+
function showsResetCredits(provider, credits) {
|
|
2332
|
+
if (provider === "codex") return credits !== void 0;
|
|
2333
|
+
return (credits?.length ?? 0) > 0;
|
|
2334
|
+
}
|
|
2335
|
+
/** The error line the settings card mounts. Claude never interpolates provider text. */
|
|
2336
|
+
function ResetCreditsErrorLine({ provider, message: message$1, t }) {
|
|
2337
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2338
|
+
style: subscriptionCardStyles.error,
|
|
2339
|
+
children: resetCreditsErrorText(provider, message$1, t)
|
|
2340
|
+
});
|
|
2341
|
+
}
|
|
2342
|
+
/** Fixed sentence for Claude. Codex may include the lookup message; Claude must not. */
|
|
2343
|
+
function resetCreditsErrorText(provider, message$1, t) {
|
|
2344
|
+
return provider === "claude" ? t("resetCreditsErrorFixed") : t("resetCreditsError", { message: message$1 });
|
|
2345
|
+
}
|
|
2346
|
+
const summaryStyle = {
|
|
2347
|
+
...subscriptionCardStyles.usageMeta,
|
|
2348
|
+
cursor: "pointer",
|
|
2349
|
+
listStyle: "none",
|
|
2350
|
+
justifyContent: "flex-start",
|
|
2351
|
+
gap: 6
|
|
2352
|
+
};
|
|
2353
|
+
/**
|
|
2354
|
+
* The closed disclosure both providers share. Claude rows are plain text:
|
|
2355
|
+
* no button, no `role="button"`, and `cursor: default`, including when
|
|
2356
|
+
* `claimable` is true.
|
|
2357
|
+
*/
|
|
2358
|
+
function ResetCreditsDisclosure({ mode, credits, t, now = Date.now(), nextCredit, useAction, statusMessage }) {
|
|
2359
|
+
const count = resetCreditsAvailableCount(credits, now, mode);
|
|
2360
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("details", {
|
|
2361
|
+
className: "subscriptions-reset-credits",
|
|
2362
|
+
style: subscriptionCardStyles.usageRow,
|
|
2363
|
+
children: [
|
|
2364
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("summary", {
|
|
2365
|
+
style: summaryStyle,
|
|
2366
|
+
children: [
|
|
2367
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
2368
|
+
"aria-hidden": "true",
|
|
2369
|
+
width: "12",
|
|
2370
|
+
height: "12",
|
|
2371
|
+
viewBox: "0 0 16 16",
|
|
2372
|
+
style: { flexShrink: 0 },
|
|
2373
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
2374
|
+
d: "m6 3 5 5-5 5",
|
|
2375
|
+
fill: "none",
|
|
2376
|
+
stroke: "currentColor",
|
|
2377
|
+
strokeWidth: "1.5",
|
|
2378
|
+
strokeLinecap: "round",
|
|
2379
|
+
strokeLinejoin: "round"
|
|
2380
|
+
})
|
|
2381
|
+
}),
|
|
2382
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("resetCreditsTitle") }),
|
|
2383
|
+
mode === "grants" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("resetCreditReadOnlyLabel") }),
|
|
2384
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2385
|
+
style: { marginLeft: "auto" },
|
|
2386
|
+
children: t("resetCreditsAvailable", { count })
|
|
2387
|
+
})
|
|
2388
|
+
]
|
|
2389
|
+
}),
|
|
2390
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: ".subscriptions-reset-credits > summary::-webkit-details-marker { display: none; }.subscriptions-reset-credits[open] > summary > svg { transform: rotate(90deg); }" }),
|
|
2391
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2392
|
+
style: {
|
|
2393
|
+
paddingLeft: 18,
|
|
2394
|
+
marginTop: 6
|
|
2395
|
+
},
|
|
2396
|
+
children: [
|
|
2397
|
+
mode === "grants" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2398
|
+
style: subscriptionCardStyles.status,
|
|
2399
|
+
children: t("resetCreditReadOnly")
|
|
2400
|
+
}),
|
|
2401
|
+
credits.map((credit, index) => {
|
|
2402
|
+
const state = resetCreditState(credit, now);
|
|
2403
|
+
const showUse = mode === "credits" && useAction !== void 0 && credit === nextCredit;
|
|
2404
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2405
|
+
"data-reset-state": mode === "grants" ? state : void 0,
|
|
2406
|
+
"data-reset-claimable": mode === "grants" && credit.claimable === true ? "true" : void 0,
|
|
2407
|
+
role: mode === "grants" ? "group" : void 0,
|
|
2408
|
+
"aria-label": mode === "grants" ? resetCreditRowName(t, credit, now) : void 0,
|
|
2409
|
+
style: {
|
|
2410
|
+
...subscriptionCardStyles.usageMeta,
|
|
2411
|
+
minHeight: 28,
|
|
2412
|
+
gap: 12,
|
|
2413
|
+
cursor: mode === "grants" ? "default" : void 0
|
|
2414
|
+
},
|
|
2415
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2416
|
+
style: {
|
|
2417
|
+
display: "inline-flex",
|
|
2418
|
+
alignItems: "center",
|
|
2419
|
+
gap: 8,
|
|
2420
|
+
flexShrink: 0
|
|
2421
|
+
},
|
|
2422
|
+
children: [
|
|
2423
|
+
t("resetCreditFull"),
|
|
2424
|
+
mode === "grants" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2425
|
+
"aria-hidden": "true",
|
|
2426
|
+
"data-reset-state-word": state,
|
|
2427
|
+
children: t(STATE_KEYS[state])
|
|
2428
|
+
}),
|
|
2429
|
+
showUse && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2430
|
+
type: "button",
|
|
2431
|
+
"aria-disabled": useAction.disabled,
|
|
2432
|
+
title: useAction.title,
|
|
2433
|
+
style: {
|
|
2434
|
+
minHeight: 22,
|
|
2435
|
+
height: 22,
|
|
2436
|
+
padding: "0 7px",
|
|
2437
|
+
borderRadius: 6,
|
|
2438
|
+
opacity: useAction.disabled ? .35 : 1,
|
|
2439
|
+
cursor: useAction.disabled ? "not-allowed" : "pointer"
|
|
2440
|
+
},
|
|
2441
|
+
onClick: () => {
|
|
2442
|
+
if (!useAction.disabled) useAction.onUse();
|
|
2443
|
+
},
|
|
2444
|
+
children: useAction.busy ? t("resetUseChecking") : useAction.label
|
|
2445
|
+
})
|
|
2446
|
+
]
|
|
2447
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2448
|
+
style: { textAlign: "right" },
|
|
2449
|
+
children: [
|
|
2450
|
+
mode === "grants" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2451
|
+
"aria-hidden": "true",
|
|
2452
|
+
children: [remainingText(t, credit), " · "]
|
|
2453
|
+
}),
|
|
2454
|
+
mode === "grants" && state === "notUsable" && credit.cooldownUntil !== void 0 && credit.cooldownUntil > now && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2455
|
+
"aria-hidden": "true",
|
|
2456
|
+
children: [t("resetCreditCooldownUntil", { date: new Date(credit.cooldownUntil).toLocaleString() }), " · "]
|
|
2457
|
+
}),
|
|
2458
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2459
|
+
"aria-hidden": mode === "grants" ? true : void 0,
|
|
2460
|
+
children: expiryText(t, credit)
|
|
2461
|
+
})
|
|
2462
|
+
]
|
|
2463
|
+
})]
|
|
2464
|
+
}, credit.id ?? index);
|
|
2465
|
+
}),
|
|
2466
|
+
statusMessage !== void 0 && statusMessage !== "" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2467
|
+
role: "status",
|
|
2468
|
+
style: subscriptionCardStyles.status,
|
|
2469
|
+
children: statusMessage
|
|
2470
|
+
})
|
|
2471
|
+
]
|
|
2472
|
+
})
|
|
2473
|
+
]
|
|
2474
|
+
});
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2067
2477
|
//#endregion
|
|
2068
2478
|
//#region src/client/UsageBadgeDisplaySetting.tsx
|
|
2069
2479
|
/** Browser-local display preference; never changes provider or account settings. */
|
|
@@ -2161,8 +2571,9 @@ function UsageBadgeDisplaySetting({ t }) {
|
|
|
2161
2571
|
}
|
|
2162
2572
|
const styles$6 = {
|
|
2163
2573
|
card: {
|
|
2164
|
-
border: "
|
|
2165
|
-
borderRadius:
|
|
2574
|
+
border: "0.5px solid var(--dsw-alias-settings-card-stroke, var(--dsw-alias-border-l4))",
|
|
2575
|
+
borderRadius: "var(--dsw-radius-xl, 20px)",
|
|
2576
|
+
background: "var(--dsw-alias-settings-card-fill, var(--dsw-alias-bg-layer-2))",
|
|
2166
2577
|
padding: "12px 14px",
|
|
2167
2578
|
display: "flex",
|
|
2168
2579
|
flexDirection: "column",
|
|
@@ -2171,21 +2582,12 @@ const styles$6 = {
|
|
|
2171
2582
|
field: {
|
|
2172
2583
|
display: "flex",
|
|
2173
2584
|
flexDirection: "column",
|
|
2174
|
-
gap:
|
|
2175
|
-
fontSize:
|
|
2176
|
-
|
|
2177
|
-
|
|
2178
|
-
select: {
|
|
2179
|
-
height: 32,
|
|
2180
|
-
width: "100%",
|
|
2181
|
-
boxSizing: "border-box",
|
|
2182
|
-
border: "1px solid var(--dsw-alias-border-l2)",
|
|
2183
|
-
borderRadius: 8,
|
|
2184
|
-
padding: "0 10px",
|
|
2185
|
-
font: "inherit",
|
|
2186
|
-
background: "var(--dsw-alias-bg-layer-1)",
|
|
2187
|
-
color: "var(--dsw-alias-label-primary)"
|
|
2585
|
+
gap: 6,
|
|
2586
|
+
fontSize: 13,
|
|
2587
|
+
fontWeight: 500,
|
|
2588
|
+
lineHeight: "20px"
|
|
2188
2589
|
},
|
|
2590
|
+
select: { width: "100%" },
|
|
2189
2591
|
hint: {
|
|
2190
2592
|
margin: 0,
|
|
2191
2593
|
fontSize: 12,
|
|
@@ -2265,7 +2667,12 @@ const styles$5 = {
|
|
|
2265
2667
|
fontSize: 14,
|
|
2266
2668
|
lineHeight: "22px"
|
|
2267
2669
|
},
|
|
2268
|
-
card:
|
|
2670
|
+
card: {
|
|
2671
|
+
...subscriptionCardStyles.card,
|
|
2672
|
+
border: "0.5px solid var(--dsw-alias-settings-card-stroke, var(--dsw-alias-border-l4))",
|
|
2673
|
+
borderRadius: "var(--dsw-radius-xl, 20px)",
|
|
2674
|
+
background: "var(--dsw-alias-settings-card-fill, var(--dsw-alias-bg-layer-2))"
|
|
2675
|
+
},
|
|
2269
2676
|
cardHeader: subscriptionCardStyles.header,
|
|
2270
2677
|
dot: subscriptionCardStyles.dot,
|
|
2271
2678
|
name: subscriptionCardStyles.name,
|
|
@@ -2278,21 +2685,32 @@ const styles$5 = {
|
|
|
2278
2685
|
},
|
|
2279
2686
|
errorLine: subscriptionCardStyles.error,
|
|
2280
2687
|
actions: subscriptionCardStyles.actions,
|
|
2281
|
-
|
|
2282
|
-
|
|
2688
|
+
usage: {
|
|
2689
|
+
...subscriptionCardStyles.usage,
|
|
2690
|
+
borderTop: "0.5px solid var(--dsw-alias-border-l2)"
|
|
2691
|
+
},
|
|
2283
2692
|
usageHeader: subscriptionCardStyles.usageHeader,
|
|
2284
2693
|
usageTitle: subscriptionCardStyles.usageTitle,
|
|
2285
2694
|
usagePlan: subscriptionCardStyles.usagePlan,
|
|
2286
|
-
usageRefresh:
|
|
2695
|
+
usageRefresh: {
|
|
2696
|
+
minHeight: 22,
|
|
2697
|
+
height: 22,
|
|
2698
|
+
padding: "0 8px",
|
|
2699
|
+
marginLeft: "auto"
|
|
2700
|
+
},
|
|
2287
2701
|
usageRow: subscriptionCardStyles.usageRow,
|
|
2288
2702
|
usageMeta: subscriptionCardStyles.usageMeta,
|
|
2289
|
-
accountRow:
|
|
2703
|
+
accountRow: {
|
|
2704
|
+
...subscriptionCardStyles.account,
|
|
2705
|
+
border: "0.5px solid var(--dsw-alias-border-l2)",
|
|
2706
|
+
borderRadius: "var(--dsw-radius-lg, 16px)"
|
|
2707
|
+
},
|
|
2290
2708
|
accountHeader: subscriptionCardStyles.accountHeader,
|
|
2291
2709
|
accountName: subscriptionCardStyles.accountName,
|
|
2292
2710
|
starButton: {
|
|
2293
2711
|
border: "none",
|
|
2294
|
-
background: "transparent",
|
|
2295
2712
|
padding: 0,
|
|
2713
|
+
width: 28,
|
|
2296
2714
|
font: "inherit",
|
|
2297
2715
|
fontSize: 14,
|
|
2298
2716
|
lineHeight: "20px",
|
|
@@ -2304,8 +2722,8 @@ const styles$5 = {
|
|
|
2304
2722
|
display: "flex",
|
|
2305
2723
|
flexDirection: "column",
|
|
2306
2724
|
gap: 6,
|
|
2307
|
-
border: "
|
|
2308
|
-
borderRadius:
|
|
2725
|
+
border: "0.5px solid var(--dsw-alias-border-l2)",
|
|
2726
|
+
borderRadius: "var(--dsw-radius-lg, 16px)",
|
|
2309
2727
|
padding: "10px 12px",
|
|
2310
2728
|
background: "var(--dsw-alias-bg-layer-1)"
|
|
2311
2729
|
},
|
|
@@ -2317,6 +2735,21 @@ const styles$5 = {
|
|
|
2317
2735
|
color: "var(--dsw-alias-label-primary)",
|
|
2318
2736
|
userSelect: "all"
|
|
2319
2737
|
},
|
|
2738
|
+
manual: {
|
|
2739
|
+
fontSize: 13,
|
|
2740
|
+
lineHeight: "20px"
|
|
2741
|
+
},
|
|
2742
|
+
manualRow: {
|
|
2743
|
+
display: "flex",
|
|
2744
|
+
flexWrap: "wrap",
|
|
2745
|
+
gap: 8,
|
|
2746
|
+
alignItems: "center",
|
|
2747
|
+
marginTop: 8
|
|
2748
|
+
},
|
|
2749
|
+
manualInput: {
|
|
2750
|
+
flex: "1 1 200px",
|
|
2751
|
+
minWidth: 0
|
|
2752
|
+
},
|
|
2320
2753
|
modalOverlay: {
|
|
2321
2754
|
position: "fixed",
|
|
2322
2755
|
inset: 0,
|
|
@@ -2325,7 +2758,8 @@ const styles$5 = {
|
|
|
2325
2758
|
alignItems: "center",
|
|
2326
2759
|
justifyContent: "center",
|
|
2327
2760
|
padding: 16,
|
|
2328
|
-
background: "
|
|
2761
|
+
background: "var(--dsw-alias-bg-mask-1, #0006)",
|
|
2762
|
+
backdropFilter: "var(--dsw-mask-blur, none)"
|
|
2329
2763
|
},
|
|
2330
2764
|
modal: {
|
|
2331
2765
|
width: 460,
|
|
@@ -2337,9 +2771,10 @@ const styles$5 = {
|
|
|
2337
2771
|
flexDirection: "column",
|
|
2338
2772
|
gap: 12,
|
|
2339
2773
|
padding: "16px 18px",
|
|
2340
|
-
borderRadius:
|
|
2341
|
-
background: "var(--dsw-alias-bg-layer-
|
|
2342
|
-
border:
|
|
2774
|
+
borderRadius: "var(--dsw-radius-panel, 28px)",
|
|
2775
|
+
background: "var(--dsw-alias-bg-layer-2)",
|
|
2776
|
+
border: 0,
|
|
2777
|
+
boxShadow: "var(--dsw-elevation-prominent)"
|
|
2343
2778
|
},
|
|
2344
2779
|
modalHeader: {
|
|
2345
2780
|
display: "flex",
|
|
@@ -2347,9 +2782,9 @@ const styles$5 = {
|
|
|
2347
2782
|
gap: 8
|
|
2348
2783
|
},
|
|
2349
2784
|
modalTitle: {
|
|
2350
|
-
fontWeight:
|
|
2351
|
-
fontSize:
|
|
2352
|
-
lineHeight: "
|
|
2785
|
+
fontWeight: 500,
|
|
2786
|
+
fontSize: 16,
|
|
2787
|
+
lineHeight: "24px",
|
|
2353
2788
|
color: "var(--dsw-alias-label-primary)"
|
|
2354
2789
|
}
|
|
2355
2790
|
};
|
|
@@ -2419,10 +2854,22 @@ function SubscriptionsSection(props) {
|
|
|
2419
2854
|
const [observedAt, setObservedAt] = (0, react.useState)({});
|
|
2420
2855
|
const [usageErrors, setUsageErrors] = (0, react.useState)({});
|
|
2421
2856
|
const [usageLoading, setUsageLoading] = (0, react.useState)({});
|
|
2857
|
+
const [resetConfirmation, setResetConfirmation] = (0, react.useState)();
|
|
2858
|
+
const [resetBusy, setResetBusy] = (0, react.useState)(false);
|
|
2859
|
+
const [resetAcknowledged, setResetAcknowledged] = (0, react.useState)(false);
|
|
2860
|
+
const [resetMessage, setResetMessage] = (0, react.useState)("");
|
|
2861
|
+
const [resetAccount, setResetAccount] = (0, react.useState)();
|
|
2862
|
+
const resetDialogRef = (0, react.useRef)(null);
|
|
2863
|
+
(0, react.useEffect)(() => {
|
|
2864
|
+
if (resetConfirmation) resetDialogRef.current?.showModal();
|
|
2865
|
+
else resetDialogRef.current?.close();
|
|
2866
|
+
}, [resetConfirmation]);
|
|
2867
|
+
const resetInflight = (0, react.useRef)(false);
|
|
2422
2868
|
const mountedRef = (0, react.useRef)(true);
|
|
2423
2869
|
const pollersRef = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
2424
2870
|
/** Accounts with a `usage` call in flight; guards the auto-fetch effect against re-entry. */
|
|
2425
|
-
|
|
2871
|
+
/** In-flight usage reads per key, holding the promise so a forced read can wait one out. */
|
|
2872
|
+
const usageInflightRef = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
2426
2873
|
const usageRosterSignatureRef = (0, react.useRef)();
|
|
2427
2874
|
const [managedProvider, setManagedProvider] = (0, react.useState)();
|
|
2428
2875
|
const setProviderError = (0, react.useCallback)((provider, message$1) => {
|
|
@@ -2499,47 +2946,97 @@ function SubscriptionsSection(props) {
|
|
|
2499
2946
|
};
|
|
2500
2947
|
}, [refresh, startPolling]);
|
|
2501
2948
|
const loadUsage = (0, react.useCallback)(async (provider, account, force = false) => {
|
|
2949
|
+
if (rpc === void 0) return;
|
|
2502
2950
|
const key = `${provider}:${account}`;
|
|
2951
|
+
const pending = usageInflightRef.current.get(key);
|
|
2952
|
+
if (pending !== void 0) {
|
|
2953
|
+
if (!force) return;
|
|
2954
|
+
await pending;
|
|
2955
|
+
}
|
|
2503
2956
|
if (rpc === void 0 || usageInflightRef.current.has(key)) return;
|
|
2504
|
-
|
|
2505
|
-
|
|
2506
|
-
...prev,
|
|
2507
|
-
[key]: true
|
|
2508
|
-
}));
|
|
2509
|
-
try {
|
|
2510
|
-
const usage = await callSubscriptionsAuth(rpc, "usage", {
|
|
2511
|
-
provider,
|
|
2512
|
-
account,
|
|
2513
|
-
...force ? { force: true } : {}
|
|
2514
|
-
});
|
|
2515
|
-
if (!mountedRef.current) return;
|
|
2516
|
-
setUsages((prev) => ({
|
|
2957
|
+
const read = (async () => {
|
|
2958
|
+
setUsageLoading((prev) => ({
|
|
2517
2959
|
...prev,
|
|
2518
|
-
[key]:
|
|
2960
|
+
[key]: true
|
|
2519
2961
|
}));
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2962
|
+
try {
|
|
2963
|
+
const usage = await callSubscriptionsAuth(rpc, "usage", {
|
|
2964
|
+
provider,
|
|
2965
|
+
account,
|
|
2966
|
+
...force ? { force: true } : {}
|
|
2967
|
+
});
|
|
2968
|
+
if (!mountedRef.current) return;
|
|
2969
|
+
setUsages((prev) => ({
|
|
2970
|
+
...prev,
|
|
2971
|
+
[key]: usage
|
|
2972
|
+
}));
|
|
2973
|
+
setObservedAt((prev) => ({
|
|
2974
|
+
...prev,
|
|
2975
|
+
[key]: usage.observedAt ?? Date.now()
|
|
2976
|
+
}));
|
|
2977
|
+
window.dispatchEvent(new Event(USAGE_BADGE_REFRESH_EVENT));
|
|
2978
|
+
setUsageErrors((prev) => {
|
|
2979
|
+
const next = { ...prev };
|
|
2980
|
+
delete next[key];
|
|
2981
|
+
return next;
|
|
2982
|
+
});
|
|
2983
|
+
} catch (error) {
|
|
2984
|
+
if (mountedRef.current) setUsageErrors((prev) => ({
|
|
2985
|
+
...prev,
|
|
2986
|
+
[key]: messageOf(error)
|
|
2987
|
+
}));
|
|
2988
|
+
} finally {
|
|
2989
|
+
usageInflightRef.current.delete(key);
|
|
2990
|
+
if (mountedRef.current) setUsageLoading((prev) => ({
|
|
2991
|
+
...prev,
|
|
2992
|
+
[key]: false
|
|
2993
|
+
}));
|
|
2994
|
+
}
|
|
2995
|
+
})();
|
|
2996
|
+
usageInflightRef.current.set(key, read);
|
|
2997
|
+
await read;
|
|
2998
|
+
}, [rpc]);
|
|
2999
|
+
async function prepareReset(account) {
|
|
3000
|
+
if (!rpc || resetInflight.current) return;
|
|
3001
|
+
resetInflight.current = true;
|
|
3002
|
+
setResetBusy(true);
|
|
3003
|
+
setResetAccount(account);
|
|
3004
|
+
setResetConfirmation(void 0);
|
|
3005
|
+
setResetMessage("");
|
|
3006
|
+
try {
|
|
3007
|
+
const result = await callSubscriptionsAuth(rpc, "prepareReset", { account });
|
|
3008
|
+
setResetAcknowledged(false);
|
|
3009
|
+
setResetConfirmation({
|
|
3010
|
+
...result,
|
|
3011
|
+
account
|
|
2529
3012
|
});
|
|
2530
3013
|
} catch (error) {
|
|
2531
|
-
|
|
2532
|
-
...prev,
|
|
2533
|
-
[key]: messageOf(error)
|
|
2534
|
-
}));
|
|
3014
|
+
setResetMessage(messageOf(error));
|
|
2535
3015
|
} finally {
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
...prev,
|
|
2539
|
-
[key]: false
|
|
2540
|
-
}));
|
|
3016
|
+
resetInflight.current = false;
|
|
3017
|
+
setResetBusy(false);
|
|
2541
3018
|
}
|
|
2542
|
-
}
|
|
3019
|
+
}
|
|
3020
|
+
async function consumeReset() {
|
|
3021
|
+
if (!rpc || !resetConfirmation || !resetAcknowledged || resetInflight.current) return;
|
|
3022
|
+
const { account, ticket } = resetConfirmation;
|
|
3023
|
+
resetInflight.current = true;
|
|
3024
|
+
setResetBusy(true);
|
|
3025
|
+
setResetConfirmation(void 0);
|
|
3026
|
+
try {
|
|
3027
|
+
await callSubscriptionsAuth(rpc, "consumeReset", {
|
|
3028
|
+
account,
|
|
3029
|
+
ticket
|
|
3030
|
+
});
|
|
3031
|
+
setResetMessage(t("resetUseSuccess"));
|
|
3032
|
+
} catch (error) {
|
|
3033
|
+
setResetMessage(messageOf(error));
|
|
3034
|
+
} finally {
|
|
3035
|
+
await loadUsage("codex", account, true);
|
|
3036
|
+
resetInflight.current = false;
|
|
3037
|
+
setResetBusy(false);
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
2543
3040
|
(0, react.useEffect)(() => {
|
|
2544
3041
|
const live = /* @__PURE__ */ new Set();
|
|
2545
3042
|
for (const { id } of PROVIDERS) for (const account of statuses[id]?.accounts ?? []) {
|
|
@@ -2687,8 +3184,10 @@ function SubscriptionsSection(props) {
|
|
|
2687
3184
|
children: t("unavailable")
|
|
2688
3185
|
});
|
|
2689
3186
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3187
|
+
className: "dsh-subscriptions-settings",
|
|
2690
3188
|
style: styles$5.section,
|
|
2691
3189
|
children: [
|
|
3190
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: providerSettingsCss }),
|
|
2692
3191
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2693
3192
|
style: styles$5.intro,
|
|
2694
3193
|
children: t("intro")
|
|
@@ -2737,6 +3236,10 @@ function SubscriptionsSection(props) {
|
|
|
2737
3236
|
const usage = usages[usageKey];
|
|
2738
3237
|
const usageError = usageErrors[usageKey];
|
|
2739
3238
|
const display = account.account ?? account.key;
|
|
3239
|
+
const sortedCredits = [...usage?.resetCredits ?? []].sort((a, b) => (a.expiresAt ?? Infinity) - (b.expiresAt ?? Infinity));
|
|
3240
|
+
const nextReset = sortedCredits.find((c) => c.expiresAt === void 0 || c.expiresAt > Date.now());
|
|
3241
|
+
const resetBlock = usage ? resetActionBlock(usage) : "resetUseRefresh";
|
|
3242
|
+
const resetDisabled = resetBusy || resetBlock !== void 0;
|
|
2740
3243
|
const showUsage = usage?.supported !== false && (usage !== void 0 || usageError !== void 0 || usageLoading[usageKey] === true);
|
|
2741
3244
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2742
3245
|
style: styles$5.accountRow,
|
|
@@ -2767,7 +3270,6 @@ function SubscriptionsSection(props) {
|
|
|
2767
3270
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2768
3271
|
type: "button",
|
|
2769
3272
|
style: {
|
|
2770
|
-
...styles$5.button,
|
|
2771
3273
|
marginLeft: "auto",
|
|
2772
3274
|
flexShrink: 0
|
|
2773
3275
|
},
|
|
@@ -2793,13 +3295,7 @@ function SubscriptionsSection(props) {
|
|
|
2793
3295
|
}),
|
|
2794
3296
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2795
3297
|
type: "button",
|
|
2796
|
-
style:
|
|
2797
|
-
...styles$5.usageRefresh,
|
|
2798
|
-
...usageLoading[usageKey] === true ? {
|
|
2799
|
-
opacity: .5,
|
|
2800
|
-
cursor: "default"
|
|
2801
|
-
} : {}
|
|
2802
|
-
},
|
|
3298
|
+
style: styles$5.usageRefresh,
|
|
2803
3299
|
disabled: usageLoading[usageKey] === true,
|
|
2804
3300
|
onClick: () => {
|
|
2805
3301
|
loadUsage(id, account.key, true);
|
|
@@ -2834,6 +3330,28 @@ function SubscriptionsSection(props) {
|
|
|
2834
3330
|
stale: usageError !== void 0 || usage.stale === true
|
|
2835
3331
|
})]
|
|
2836
3332
|
}, index);
|
|
3333
|
+
}),
|
|
3334
|
+
(id === "codex" || id === "claude") && usage?.resetCreditsError !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResetCreditsErrorLine, {
|
|
3335
|
+
provider: id,
|
|
3336
|
+
message: usage.resetCreditsError,
|
|
3337
|
+
t
|
|
3338
|
+
}),
|
|
3339
|
+
(id === "codex" || id === "claude") && showsResetCredits(id, usage?.resetCredits) && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ResetCreditsDisclosure, {
|
|
3340
|
+
mode: id === "claude" ? "grants" : "credits",
|
|
3341
|
+
credits: sortedCredits,
|
|
3342
|
+
t,
|
|
3343
|
+
...nextReset !== void 0 ? { nextCredit: nextReset } : {},
|
|
3344
|
+
...id === "codex" ? { useAction: {
|
|
3345
|
+
accountKey: account.key,
|
|
3346
|
+
busy: resetBusy && resetAccount === account.key,
|
|
3347
|
+
disabled: resetDisabled,
|
|
3348
|
+
title: t(resetBusy ? "resetUseChecking" : resetBlock ?? "resetUseReady"),
|
|
3349
|
+
label: t("resetUseButton"),
|
|
3350
|
+
onUse: () => {
|
|
3351
|
+
if (!resetDisabled) prepareReset(account.key);
|
|
3352
|
+
}
|
|
3353
|
+
} } : {},
|
|
3354
|
+
...resetAccount === account.key && resetMessage !== "" ? { statusMessage: resetMessage } : {}
|
|
2837
3355
|
})
|
|
2838
3356
|
]
|
|
2839
3357
|
})]
|
|
@@ -2844,7 +3362,6 @@ function SubscriptionsSection(props) {
|
|
|
2844
3362
|
children: [
|
|
2845
3363
|
!busy && accounts.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2846
3364
|
type: "button",
|
|
2847
|
-
style: styles$5.button,
|
|
2848
3365
|
onClick: () => {
|
|
2849
3366
|
login(id);
|
|
2850
3367
|
},
|
|
@@ -2852,14 +3369,12 @@ function SubscriptionsSection(props) {
|
|
|
2852
3369
|
}),
|
|
2853
3370
|
!busy && accounts.length > 0 && id === "claude" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2854
3371
|
type: "button",
|
|
2855
|
-
style: styles$5.button,
|
|
2856
3372
|
onClick: () => {
|
|
2857
3373
|
login(id, "oauth");
|
|
2858
3374
|
},
|
|
2859
3375
|
children: t("addAccountOAuth")
|
|
2860
3376
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2861
3377
|
type: "button",
|
|
2862
|
-
style: styles$5.button,
|
|
2863
3378
|
onClick: () => {
|
|
2864
3379
|
login(id, "keychain");
|
|
2865
3380
|
},
|
|
@@ -2867,7 +3382,6 @@ function SubscriptionsSection(props) {
|
|
|
2867
3382
|
})] }),
|
|
2868
3383
|
!busy && accounts.length > 0 && id !== "claude" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2869
3384
|
type: "button",
|
|
2870
|
-
style: styles$5.button,
|
|
2871
3385
|
onClick: () => {
|
|
2872
3386
|
login(id);
|
|
2873
3387
|
},
|
|
@@ -2875,7 +3389,6 @@ function SubscriptionsSection(props) {
|
|
|
2875
3389
|
}),
|
|
2876
3390
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2877
3391
|
type: "button",
|
|
2878
|
-
style: styles$5.button,
|
|
2879
3392
|
"aria-haspopup": "dialog",
|
|
2880
3393
|
onClick: () => setManagedProvider({
|
|
2881
3394
|
id,
|
|
@@ -2885,7 +3398,6 @@ function SubscriptionsSection(props) {
|
|
|
2885
3398
|
}),
|
|
2886
3399
|
busy && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2887
3400
|
type: "button",
|
|
2888
|
-
style: styles$5.button,
|
|
2889
3401
|
onClick: () => {
|
|
2890
3402
|
cancel(id);
|
|
2891
3403
|
},
|
|
@@ -2912,14 +3424,12 @@ function SubscriptionsSection(props) {
|
|
|
2912
3424
|
style: styles$5.actions,
|
|
2913
3425
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2914
3426
|
type: "button",
|
|
2915
|
-
style: styles$5.button,
|
|
2916
3427
|
onClick: () => {
|
|
2917
3428
|
copyDeviceCode(id, deviceCode.userCode);
|
|
2918
3429
|
},
|
|
2919
3430
|
children: copiedCode === id ? t("deviceCodeCopied") : t("deviceCodeCopy")
|
|
2920
3431
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2921
3432
|
type: "button",
|
|
2922
|
-
style: styles$5.button,
|
|
2923
3433
|
onClick: () => {
|
|
2924
3434
|
window.open(deviceCode.verificationUrl, "_blank", "noopener");
|
|
2925
3435
|
},
|
|
@@ -2942,7 +3452,6 @@ function SubscriptionsSection(props) {
|
|
|
2942
3452
|
}))
|
|
2943
3453
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
2944
3454
|
type: "button",
|
|
2945
|
-
style: styles$5.button,
|
|
2946
3455
|
onClick: () => {
|
|
2947
3456
|
submitManual(id);
|
|
2948
3457
|
},
|
|
@@ -2967,6 +3476,90 @@ function SubscriptionsSection(props) {
|
|
|
2967
3476
|
rpc,
|
|
2968
3477
|
t,
|
|
2969
3478
|
onClose: () => setManagedProvider(void 0)
|
|
3479
|
+
}),
|
|
3480
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: ".subscriptions-reset-dialog::backdrop { background: var(--dsw-alias-bg-mask-1, #0006); backdrop-filter: var(--dsw-mask-blur, none); }" }),
|
|
3481
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("dialog", {
|
|
3482
|
+
ref: resetDialogRef,
|
|
3483
|
+
className: "subscriptions-reset-dialog",
|
|
3484
|
+
"aria-labelledby": "subscriptions-reset-title",
|
|
3485
|
+
onCancel: () => setResetConfirmation(void 0),
|
|
3486
|
+
onClose: () => setResetConfirmation(void 0),
|
|
3487
|
+
style: {
|
|
3488
|
+
...styles$5.modal,
|
|
3489
|
+
display: resetConfirmation ? "flex" : "none",
|
|
3490
|
+
margin: "auto",
|
|
3491
|
+
color: "var(--dsw-alias-label-primary)"
|
|
3492
|
+
},
|
|
3493
|
+
children: resetConfirmation && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
3494
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h3", {
|
|
3495
|
+
id: "subscriptions-reset-title",
|
|
3496
|
+
style: {
|
|
3497
|
+
...styles$5.modalTitle,
|
|
3498
|
+
margin: 0
|
|
3499
|
+
},
|
|
3500
|
+
children: t("resetUseConfirmTitle")
|
|
3501
|
+
}),
|
|
3502
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3503
|
+
style: {
|
|
3504
|
+
...styles$5.statusLine,
|
|
3505
|
+
overflowWrap: "anywhere"
|
|
3506
|
+
},
|
|
3507
|
+
children: statuses.codex?.accounts.find((a) => a.key === resetConfirmation.account)?.account ?? resetConfirmation.account
|
|
3508
|
+
}),
|
|
3509
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3510
|
+
style: {
|
|
3511
|
+
...styles$5.usageMeta,
|
|
3512
|
+
gap: 12
|
|
3513
|
+
},
|
|
3514
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("usageWeekly") }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("strong", { children: [Math.round(resetConfirmation.weeklyUsedPercent), "%"] })]
|
|
3515
|
+
}),
|
|
3516
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3517
|
+
style: styles$5.usageMeta,
|
|
3518
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: resetConfirmation.creditExpiresAt === void 0 ? t("resetCreditExpiryUnknown") : t("resetCreditExpires", { date: new Date(resetConfirmation.creditExpiresAt).toLocaleString() }) })
|
|
3519
|
+
}),
|
|
3520
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3521
|
+
style: {
|
|
3522
|
+
...styles$5.statusLine,
|
|
3523
|
+
margin: "4px 0"
|
|
3524
|
+
},
|
|
3525
|
+
children: t("resetUseWarning")
|
|
3526
|
+
}),
|
|
3527
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
|
|
3528
|
+
style: {
|
|
3529
|
+
display: "flex",
|
|
3530
|
+
gap: 8,
|
|
3531
|
+
alignItems: "flex-start",
|
|
3532
|
+
fontSize: 12
|
|
3533
|
+
},
|
|
3534
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
3535
|
+
type: "checkbox",
|
|
3536
|
+
checked: resetAcknowledged,
|
|
3537
|
+
onChange: (e) => setResetAcknowledged(e.target.checked)
|
|
3538
|
+
}), t("resetUseAcknowledge")]
|
|
3539
|
+
}),
|
|
3540
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3541
|
+
className: "dsh-subscription-dialog-actions",
|
|
3542
|
+
style: {
|
|
3543
|
+
...styles$5.actions,
|
|
3544
|
+
justifyContent: "flex-end",
|
|
3545
|
+
marginTop: 8
|
|
3546
|
+
},
|
|
3547
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3548
|
+
type: "button",
|
|
3549
|
+
autoFocus: true,
|
|
3550
|
+
onClick: () => setResetConfirmation(void 0),
|
|
3551
|
+
children: t("cancel")
|
|
3552
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3553
|
+
type: "button",
|
|
3554
|
+
className: "dsh-subscription-primary",
|
|
3555
|
+
disabled: !resetAcknowledged || resetBusy,
|
|
3556
|
+
onClick: () => {
|
|
3557
|
+
consumeReset();
|
|
3558
|
+
},
|
|
3559
|
+
children: t("resetUseConfirm")
|
|
3560
|
+
})]
|
|
3561
|
+
})
|
|
3562
|
+
] })
|
|
2970
3563
|
})
|
|
2971
3564
|
]
|
|
2972
3565
|
});
|
|
@@ -3253,20 +3846,42 @@ const HOST_CONTRACT = {
|
|
|
3253
3846
|
package: "@deepseek-ai/dsh-client-ui-theme",
|
|
3254
3847
|
names: [
|
|
3255
3848
|
"--dsw-alias-bg-layer-1",
|
|
3849
|
+
"--dsw-alias-bg-layer-2",
|
|
3850
|
+
"--dsw-alias-bg-layer-3",
|
|
3851
|
+
"--dsw-alias-bg-mask-1",
|
|
3256
3852
|
"--dsw-alias-bg-skeleton",
|
|
3853
|
+
"--dsw-alias-border-l1",
|
|
3257
3854
|
"--dsw-alias-border-l2",
|
|
3258
3855
|
"--dsw-alias-border-l2-darkmode-thin",
|
|
3856
|
+
"--dsw-alias-border-l3",
|
|
3857
|
+
"--dsw-alias-border-l4",
|
|
3858
|
+
"--dsw-alias-brand-primary",
|
|
3859
|
+
"--dsw-alias-button-primary-fill",
|
|
3860
|
+
"--dsw-alias-button-primary-hover",
|
|
3861
|
+
"--dsw-alias-interactive-bg-active",
|
|
3259
3862
|
"--dsw-alias-interactive-bg-hover",
|
|
3260
3863
|
"--dsw-alias-interactive-bg-hover-solid",
|
|
3261
3864
|
"--dsw-alias-label-dimmed",
|
|
3262
3865
|
"--dsw-alias-label-primary",
|
|
3866
|
+
"--dsw-alias-label-primary-foreground",
|
|
3263
3867
|
"--dsw-alias-label-secondary",
|
|
3264
3868
|
"--dsw-alias-label-tertiary",
|
|
3869
|
+
"--dsw-alias-settings-card-fill",
|
|
3870
|
+
"--dsw-alias-settings-card-stroke",
|
|
3871
|
+
"--dsw-alias-state-business-primary",
|
|
3265
3872
|
"--dsw-alias-state-error-primary",
|
|
3266
3873
|
"--dsw-alias-state-success-primary",
|
|
3267
3874
|
"--dsw-alias-state-warn-label",
|
|
3268
3875
|
"--dsw-elevation-prominent",
|
|
3876
|
+
"--dsw-focus-ring-color",
|
|
3877
|
+
"--dsw-focus-ring-width",
|
|
3878
|
+
"--dsw-mask-blur",
|
|
3269
3879
|
"--dsw-menu-backdrop-filter",
|
|
3880
|
+
"--dsw-radius-lg",
|
|
3881
|
+
"--dsw-radius-md",
|
|
3882
|
+
"--dsw-radius-panel",
|
|
3883
|
+
"--dsw-radius-sm",
|
|
3884
|
+
"--dsw-radius-xl",
|
|
3270
3885
|
"--dsw-specific-menu"
|
|
3271
3886
|
]
|
|
3272
3887
|
}
|
|
@@ -3804,6 +4419,7 @@ function SpeedSelect({ loadSpeed, setSpeed, t }) {
|
|
|
3804
4419
|
const triggerLabel = `${translate("speed")} · ${tierName(state.tier)}`;
|
|
3805
4420
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3806
4421
|
ref: rootRef,
|
|
4422
|
+
className: "dsh-subscription-speed",
|
|
3807
4423
|
style: styles$1.root,
|
|
3808
4424
|
onKeyDown: (event) => {
|
|
3809
4425
|
if (event.key === "Escape" && open) {
|
|
@@ -3811,46 +4427,50 @@ function SpeedSelect({ loadSpeed, setSpeed, t }) {
|
|
|
3811
4427
|
setOpen(false);
|
|
3812
4428
|
}
|
|
3813
4429
|
},
|
|
3814
|
-
children: [
|
|
3815
|
-
style:
|
|
3816
|
-
|
|
3817
|
-
|
|
3818
|
-
|
|
4430
|
+
children: [
|
|
4431
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: subscriptionChromeCss }),
|
|
4432
|
+
open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4433
|
+
style: styles$1.menu,
|
|
4434
|
+
role: "menu",
|
|
4435
|
+
"aria-label": translate("speed"),
|
|
4436
|
+
children: TIERS.map((tier) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4437
|
+
type: "button",
|
|
4438
|
+
role: "menuitemradio",
|
|
4439
|
+
"aria-checked": tier === state.tier,
|
|
4440
|
+
style: styles$1.item,
|
|
4441
|
+
disabled: busy,
|
|
4442
|
+
onClick: () => {
|
|
4443
|
+
choose(tier);
|
|
4444
|
+
},
|
|
4445
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4446
|
+
style: styles$1.itemCheck,
|
|
4447
|
+
children: tier === state.tier ? "✓" : ""
|
|
4448
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4449
|
+
style: styles$1.itemText,
|
|
4450
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4451
|
+
style: styles$1.itemName,
|
|
4452
|
+
children: tierName(tier)
|
|
4453
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4454
|
+
style: styles$1.itemDescription,
|
|
4455
|
+
children: tierDescription(tier)
|
|
4456
|
+
})]
|
|
4457
|
+
})]
|
|
4458
|
+
}, tier))
|
|
4459
|
+
}),
|
|
4460
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3819
4461
|
type: "button",
|
|
3820
|
-
|
|
3821
|
-
"aria-
|
|
3822
|
-
|
|
4462
|
+
style: styles$1.trigger,
|
|
4463
|
+
"aria-haspopup": "menu",
|
|
4464
|
+
"aria-expanded": open,
|
|
4465
|
+
title: triggerLabel,
|
|
3823
4466
|
disabled: busy,
|
|
3824
4467
|
onClick: () => {
|
|
3825
|
-
|
|
4468
|
+
if (open) setOpen(false);
|
|
4469
|
+
else show();
|
|
3826
4470
|
},
|
|
3827
|
-
children:
|
|
3828
|
-
|
|
3829
|
-
|
|
3830
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
3831
|
-
style: styles$1.itemText,
|
|
3832
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3833
|
-
style: styles$1.itemName,
|
|
3834
|
-
children: tierName(tier)
|
|
3835
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3836
|
-
style: styles$1.itemDescription,
|
|
3837
|
-
children: tierDescription(tier)
|
|
3838
|
-
})]
|
|
3839
|
-
})]
|
|
3840
|
-
}, tier))
|
|
3841
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
3842
|
-
type: "button",
|
|
3843
|
-
style: styles$1.trigger,
|
|
3844
|
-
"aria-haspopup": "menu",
|
|
3845
|
-
"aria-expanded": open,
|
|
3846
|
-
title: triggerLabel,
|
|
3847
|
-
disabled: busy,
|
|
3848
|
-
onClick: () => {
|
|
3849
|
-
if (open) setOpen(false);
|
|
3850
|
-
else show();
|
|
3851
|
-
},
|
|
3852
|
-
children: triggerLabel
|
|
3853
|
-
})]
|
|
4471
|
+
children: triggerLabel
|
|
4472
|
+
})
|
|
4473
|
+
]
|
|
3854
4474
|
});
|
|
3855
4475
|
}
|
|
3856
4476
|
const styles$1 = {
|
|
@@ -3859,9 +4479,9 @@ const styles$1 = {
|
|
|
3859
4479
|
display: "inline-flex"
|
|
3860
4480
|
},
|
|
3861
4481
|
trigger: {
|
|
3862
|
-
border: "
|
|
3863
|
-
borderRadius:
|
|
3864
|
-
background: "transparent",
|
|
4482
|
+
border: "0.5px solid var(--dsw-alias-border-l3)",
|
|
4483
|
+
borderRadius: "var(--dsw-radius-sm, 8px)",
|
|
4484
|
+
background: "var(--dsh-subscription-speed-hover, transparent)",
|
|
3865
4485
|
color: "var(--dsw-alias-label-secondary)",
|
|
3866
4486
|
font: "inherit",
|
|
3867
4487
|
fontSize: 12,
|
|
@@ -3878,9 +4498,10 @@ const styles$1 = {
|
|
|
3878
4498
|
minWidth: 180,
|
|
3879
4499
|
padding: 4,
|
|
3880
4500
|
zIndex: 20,
|
|
3881
|
-
background: "var(--dsw-alias-bg-layer-
|
|
3882
|
-
border:
|
|
3883
|
-
|
|
4501
|
+
background: "var(--dsw-specific-menu, var(--dsw-alias-bg-layer-2))",
|
|
4502
|
+
border: 0,
|
|
4503
|
+
boxShadow: "var(--dsw-elevation-prominent)",
|
|
4504
|
+
borderRadius: "var(--dsw-radius-lg, 16px)",
|
|
3884
4505
|
display: "flex",
|
|
3885
4506
|
flexDirection: "column",
|
|
3886
4507
|
gap: 2
|
|
@@ -3891,8 +4512,8 @@ const styles$1 = {
|
|
|
3891
4512
|
gap: 6,
|
|
3892
4513
|
width: "100%",
|
|
3893
4514
|
border: "none",
|
|
3894
|
-
borderRadius:
|
|
3895
|
-
background: "transparent",
|
|
4515
|
+
borderRadius: "var(--dsw-radius-sm, 8px)",
|
|
4516
|
+
background: "var(--dsh-subscription-speed-hover, transparent)",
|
|
3896
4517
|
padding: "6px 8px",
|
|
3897
4518
|
cursor: "pointer",
|
|
3898
4519
|
font: "inherit",
|
|
@@ -4391,81 +5012,87 @@ function SubscriptionUsageBadge({ rpc, currentModel, t, rotationMs }) {
|
|
|
4391
5012
|
const pill = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4392
5013
|
ref: rootRef,
|
|
4393
5014
|
style: styles.anchor,
|
|
4394
|
-
children: [
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4412
|
-
|
|
4413
|
-
|
|
4414
|
-
|
|
4415
|
-
|
|
4416
|
-
|
|
4417
|
-
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4421
|
-
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
5015
|
+
children: [
|
|
5016
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: subscriptionChromeCss }),
|
|
5017
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
5018
|
+
type: "button",
|
|
5019
|
+
className: "dsh-subscription-usage-pill",
|
|
5020
|
+
style: {
|
|
5021
|
+
...styles.pill,
|
|
5022
|
+
...hover || open ? styles.pillActive : {}
|
|
5023
|
+
},
|
|
5024
|
+
"aria-haspopup": "dialog",
|
|
5025
|
+
"aria-expanded": open,
|
|
5026
|
+
"aria-label": `${title} · ${label}`,
|
|
5027
|
+
title,
|
|
5028
|
+
onMouseEnter: () => {
|
|
5029
|
+
setHover(true);
|
|
5030
|
+
},
|
|
5031
|
+
onMouseLeave: () => {
|
|
5032
|
+
setHover(false);
|
|
5033
|
+
},
|
|
5034
|
+
onClick: toggle,
|
|
5035
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageBadgeIcon, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5036
|
+
style: styles.label,
|
|
5037
|
+
children: label
|
|
5038
|
+
})]
|
|
5039
|
+
}),
|
|
5040
|
+
open && (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5041
|
+
ref: panelRef,
|
|
5042
|
+
role: "dialog",
|
|
5043
|
+
"aria-label": title,
|
|
5044
|
+
className: "dsh-subscription-usage-panel",
|
|
5045
|
+
style: {
|
|
5046
|
+
...styles.panel,
|
|
5047
|
+
...pos ?? MEASURE_STYLE
|
|
5048
|
+
},
|
|
5049
|
+
children: [
|
|
5050
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5051
|
+
style: styles.title,
|
|
5052
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5053
|
+
style: styles.titleLabel,
|
|
5054
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageBadgeIcon, {}), title]
|
|
5055
|
+
})
|
|
5056
|
+
}),
|
|
5057
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5058
|
+
style: styles.titleRule,
|
|
5059
|
+
"aria-hidden": true
|
|
5060
|
+
}),
|
|
5061
|
+
expanded.map((d, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("section", {
|
|
5062
|
+
style: index === 0 ? void 0 : styles.section,
|
|
5063
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5064
|
+
style: styles.providerRow,
|
|
5065
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
5066
|
+
style: styles.providerName,
|
|
5067
|
+
children: [d.name, d.provider === current && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5068
|
+
style: styles.currentTag,
|
|
5069
|
+
children: translate("usageBadgeCurrent")
|
|
5070
|
+
})]
|
|
5071
|
+
}), d.accounts.length === 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountMeta, {
|
|
5072
|
+
account: d.accounts[0],
|
|
5073
|
+
translate
|
|
4444
5074
|
})]
|
|
4445
|
-
}), d.accounts.
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
account,
|
|
5075
|
+
}), d.accounts.map((account, accountIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5076
|
+
style: accountIndex === 0 ? void 0 : styles.accountBlock,
|
|
5077
|
+
children: [d.accounts.length > 1 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5078
|
+
style: styles.accountRow,
|
|
5079
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountMeta, {
|
|
5080
|
+
account,
|
|
5081
|
+
translate
|
|
5082
|
+
})
|
|
5083
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountWindows, {
|
|
5084
|
+
windows: account.windows,
|
|
5085
|
+
observedAt: account.observedAt,
|
|
5086
|
+
stale: account.stale,
|
|
5087
|
+
model: d.provider === dialogProvider ? dialogModel : void 0,
|
|
5088
|
+
provider: d.provider,
|
|
4455
5089
|
translate
|
|
4456
|
-
})
|
|
4457
|
-
}
|
|
4458
|
-
|
|
4459
|
-
|
|
4460
|
-
|
|
4461
|
-
|
|
4462
|
-
provider: d.provider,
|
|
4463
|
-
translate
|
|
4464
|
-
}, `${d.provider}:${dialogModel ?? ""}`)]
|
|
4465
|
-
}, account.key))]
|
|
4466
|
-
}, d.provider))
|
|
4467
|
-
]
|
|
4468
|
-
}), document.body)]
|
|
5090
|
+
}, `${d.provider}:${dialogModel ?? ""}`)]
|
|
5091
|
+
}, account.key))]
|
|
5092
|
+
}, d.provider))
|
|
5093
|
+
]
|
|
5094
|
+
}), document.body)
|
|
5095
|
+
]
|
|
4469
5096
|
});
|
|
4470
5097
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [seat, statsRow !== null && statsRow.isConnected ? (0, react_dom.createPortal)(pill, statsRow) : pill] });
|
|
4471
5098
|
}
|
|
@@ -4565,13 +5192,13 @@ const styles = {
|
|
|
4565
5192
|
maxWidth: "100%",
|
|
4566
5193
|
color: "var(--dsw-alias-label-tertiary)",
|
|
4567
5194
|
font: "inherit",
|
|
4568
|
-
fontSize: "var(--dsh-content-font-size-secondary, 13px)",
|
|
5195
|
+
fontSize: "calc(var(--dsh-content-font-size-secondary, 13px) - 1px)",
|
|
4569
5196
|
fontVariantNumeric: "tabular-nums",
|
|
4570
|
-
lineHeight: "20px",
|
|
5197
|
+
lineHeight: "calc(20px + var(--dsh-content-font-delta-secondary, 0px))",
|
|
4571
5198
|
whiteSpace: "nowrap",
|
|
4572
5199
|
background: "transparent",
|
|
4573
5200
|
border: "none",
|
|
4574
|
-
borderRadius:
|
|
5201
|
+
borderRadius: 999,
|
|
4575
5202
|
alignItems: "center",
|
|
4576
5203
|
gap: 6,
|
|
4577
5204
|
padding: "1px 8px",
|
|
@@ -4603,7 +5230,7 @@ const styles = {
|
|
|
4603
5230
|
color: "var(--dsw-alias-label-secondary)",
|
|
4604
5231
|
cursor: "default",
|
|
4605
5232
|
border: 0,
|
|
4606
|
-
borderRadius:
|
|
5233
|
+
borderRadius: "var(--dsw-radius-lg, 16px)",
|
|
4607
5234
|
padding: 16,
|
|
4608
5235
|
fontSize: 12,
|
|
4609
5236
|
lineHeight: "18px"
|