dsh-plugin-subscription-oauth 0.10.2 → 0.12.0
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.dev.md +434 -0
- package/README.md +50 -391
- package/README.zh.dev.md +371 -0
- package/README.zh.md +50 -328
- package/lib/auth/mimo-flow.d.ts +9 -0
- package/lib/auth/mimo-flow.js +171 -0
- package/lib/auth/registry.d.ts +10 -1
- package/lib/auth/registry.js +11 -1
- package/lib/auth/rpc.js +6 -0
- package/lib/client/SubscriptionsSection.js +96 -30
- package/lib/client/locales.d.ts +3 -1
- package/lib/client/locales.js +4 -2
- package/lib/client.js +230 -159
- package/lib/client.js.map +1 -1
- package/lib/index.js +1 -1
- package/lib/protocol.d.ts +13 -1
- package/lib/protocol.js +1 -0
- package/lib/providers/auto.js +3 -0
- package/lib/providers/grok.d.ts +2 -0
- package/lib/providers/grok.js +31 -21
- package/lib/providers/kimi-provider.js +2 -1
- package/lib/providers/kimi.js +18 -13
- package/lib/providers/mimo.d.ts +10 -0
- package/lib/providers/mimo.js +65 -1
- package/lib/settings.d.ts +8 -0
- package/lib/settings.js +19 -5
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -39,7 +39,7 @@ react_jsx_runtime = __toESM(react_jsx_runtime);
|
|
|
39
39
|
/** English strings. */
|
|
40
40
|
const en = {
|
|
41
41
|
nav: "Subscriptions",
|
|
42
|
-
intro: "Sign in with
|
|
42
|
+
intro: "Sign in with the AI subscriptions you already pay for — no API key. Pick a provider below, connect once, and its models join the model picker with live plan usage. Tokens stay on this machine.",
|
|
43
43
|
loading: "Checking subscriptions…",
|
|
44
44
|
unavailable: "The subscriptions page needs the web connection service, which this composition does not provide.",
|
|
45
45
|
statusConnected: "Connected · {count} account(s)",
|
|
@@ -57,6 +57,7 @@ const en = {
|
|
|
57
57
|
logout: "Sign out",
|
|
58
58
|
makeDefault: "Use by default",
|
|
59
59
|
defaultBadge: "Default",
|
|
60
|
+
badgeLive: "Live",
|
|
60
61
|
accountNeedsLogin: "Sign in again",
|
|
61
62
|
accountNeedsLoginHint: "The provider refused this account's grant, so its token cannot be renewed",
|
|
62
63
|
accountExpired: "token expired",
|
|
@@ -133,7 +134,7 @@ const en = {
|
|
|
133
134
|
/** Chinese strings. */
|
|
134
135
|
const zh = {
|
|
135
136
|
nav: "订阅",
|
|
136
|
-
intro: "
|
|
137
|
+
intro: "使用你已付费的 AI 订阅 —— 无需 API Key。在下方选择服务,连接一次,其模型即进入模型选择器并显示实时额度。令牌仅保存在本机。",
|
|
137
138
|
loading: "正在检查订阅…",
|
|
138
139
|
unavailable: "订阅页面需要 Web 连接服务,当前组合未提供该服务。",
|
|
139
140
|
statusConnected: "已连接 {count} 个账号",
|
|
@@ -151,6 +152,7 @@ const zh = {
|
|
|
151
152
|
logout: "退出登录",
|
|
152
153
|
makeDefault: "设为默认",
|
|
153
154
|
defaultBadge: "默认",
|
|
155
|
+
badgeLive: "已连接",
|
|
154
156
|
accountNeedsLogin: "需重新登录",
|
|
155
157
|
accountNeedsLoginHint: "服务方已拒绝该账号的授权,令牌无法自动续期",
|
|
156
158
|
accountExpired: "令牌已过期",
|
|
@@ -877,30 +879,52 @@ const styles = {
|
|
|
877
879
|
maxWidth: SECTION_WIDTH,
|
|
878
880
|
color: "var(--dsw-alias-label-primary)"
|
|
879
881
|
},
|
|
882
|
+
sectionHeader: {
|
|
883
|
+
display: "flex",
|
|
884
|
+
flexDirection: "column",
|
|
885
|
+
gap: 4,
|
|
886
|
+
marginBottom: 2
|
|
887
|
+
},
|
|
888
|
+
heading: {
|
|
889
|
+
margin: 0,
|
|
890
|
+
fontSize: 18,
|
|
891
|
+
lineHeight: "26px",
|
|
892
|
+
fontWeight: 600,
|
|
893
|
+
color: "var(--dsw-alias-label-primary)"
|
|
894
|
+
},
|
|
880
895
|
intro: {
|
|
881
896
|
margin: 0,
|
|
882
897
|
color: "var(--dsw-alias-label-tertiary)",
|
|
883
|
-
fontSize:
|
|
884
|
-
lineHeight: "
|
|
898
|
+
fontSize: 13,
|
|
899
|
+
lineHeight: "20px",
|
|
900
|
+
maxWidth: 560
|
|
885
901
|
},
|
|
886
902
|
card: {
|
|
887
903
|
border: "0.5px solid var(--dsw-alias-settings-card-stroke, var(--dsw-alias-border-l4))",
|
|
888
|
-
borderRadius: "var(--dsw-radius-xl,
|
|
904
|
+
borderRadius: "var(--dsw-radius-xl, 16px)",
|
|
889
905
|
background: "var(--dsw-alias-settings-card-fill, var(--dsw-alias-bg-layer-2))",
|
|
890
|
-
padding: "
|
|
906
|
+
padding: "14px 16px",
|
|
891
907
|
display: "flex",
|
|
892
908
|
flexDirection: "column",
|
|
893
|
-
gap:
|
|
909
|
+
gap: 8,
|
|
910
|
+
transition: "border-color 120ms ease, background 120ms ease"
|
|
911
|
+
},
|
|
912
|
+
cardOpen: {
|
|
913
|
+
borderColor: "var(--dsw-alias-border-l2, var(--dsw-alias-border-l3))",
|
|
914
|
+
background: "var(--dsw-alias-settings-card-fill-hover, var(--dsw-alias-settings-card-fill, var(--dsw-alias-bg-layer-2)))"
|
|
894
915
|
},
|
|
895
916
|
cardHeader: {
|
|
896
917
|
display: "flex",
|
|
897
918
|
alignItems: "center",
|
|
898
|
-
gap:
|
|
919
|
+
gap: 10,
|
|
920
|
+
cursor: "pointer",
|
|
921
|
+
userSelect: "none"
|
|
899
922
|
},
|
|
900
923
|
cardBody: {
|
|
901
924
|
display: "flex",
|
|
902
925
|
flexDirection: "column",
|
|
903
|
-
gap:
|
|
926
|
+
gap: 10,
|
|
927
|
+
marginTop: 2
|
|
904
928
|
},
|
|
905
929
|
cardSummary: {
|
|
906
930
|
fontSize: 12,
|
|
@@ -911,19 +935,24 @@ const styles = {
|
|
|
911
935
|
width: 8,
|
|
912
936
|
height: 8,
|
|
913
937
|
borderRadius: "50%",
|
|
914
|
-
flexShrink: 0
|
|
938
|
+
flexShrink: 0,
|
|
939
|
+
border: "1.5px solid var(--dsw-alias-label-dimmed)",
|
|
940
|
+
background: "transparent"
|
|
941
|
+
},
|
|
942
|
+
dotLive: {
|
|
943
|
+
borderColor: "var(--dsw-alias-state-success-primary, #067647)",
|
|
944
|
+
background: "var(--dsw-alias-state-success-primary, #067647)"
|
|
945
|
+
},
|
|
946
|
+
dotBusy: {
|
|
947
|
+
borderColor: "var(--dsw-alias-state-warn-primary, #f5a524)",
|
|
948
|
+
background: "var(--dsw-alias-state-warn-primary, #f5a524)"
|
|
915
949
|
},
|
|
916
950
|
name: {
|
|
917
|
-
fontWeight:
|
|
951
|
+
fontWeight: 600,
|
|
918
952
|
fontSize: 14,
|
|
919
953
|
lineHeight: "22px",
|
|
920
954
|
color: "var(--dsw-alias-label-primary)"
|
|
921
955
|
},
|
|
922
|
-
providerId: {
|
|
923
|
-
fontSize: 12,
|
|
924
|
-
lineHeight: "18px",
|
|
925
|
-
color: "var(--dsw-alias-label-dimmed)"
|
|
926
|
-
},
|
|
927
956
|
statusLine: {
|
|
928
957
|
margin: 0,
|
|
929
958
|
fontSize: 12,
|
|
@@ -954,9 +983,9 @@ const styles = {
|
|
|
954
983
|
flexDirection: "column",
|
|
955
984
|
gap: 6,
|
|
956
985
|
border: "0.5px solid var(--dsw-alias-border-l2)",
|
|
957
|
-
borderRadius: "var(--dsw-radius-lg,
|
|
958
|
-
padding: "
|
|
959
|
-
|
|
986
|
+
borderRadius: "var(--dsw-radius-lg, 12px)",
|
|
987
|
+
padding: "10px 12px",
|
|
988
|
+
background: "var(--dsw-alias-bg-layer-1)"
|
|
960
989
|
},
|
|
961
990
|
accountHeader: {
|
|
962
991
|
display: "flex",
|
|
@@ -982,14 +1011,33 @@ const styles = {
|
|
|
982
1011
|
userSelect: "all"
|
|
983
1012
|
},
|
|
984
1013
|
badge: {
|
|
985
|
-
fontSize:
|
|
986
|
-
lineHeight: "
|
|
987
|
-
padding: "
|
|
988
|
-
borderRadius:
|
|
989
|
-
|
|
1014
|
+
fontSize: 10,
|
|
1015
|
+
lineHeight: "14px",
|
|
1016
|
+
padding: "1px 7px",
|
|
1017
|
+
borderRadius: 999,
|
|
1018
|
+
fontWeight: 500,
|
|
1019
|
+
background: "var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-layer-1))",
|
|
990
1020
|
border: "0.5px solid var(--dsw-alias-border-l2)",
|
|
991
1021
|
color: "var(--dsw-alias-label-secondary)"
|
|
992
1022
|
},
|
|
1023
|
+
badgeDefault: {
|
|
1024
|
+
fontSize: 10,
|
|
1025
|
+
lineHeight: "14px",
|
|
1026
|
+
padding: "1px 7px",
|
|
1027
|
+
borderRadius: 999,
|
|
1028
|
+
fontWeight: 500,
|
|
1029
|
+
background: "var(--dsw-alias-state-success-primary, #067647)",
|
|
1030
|
+
color: "var(--dsw-alias-label-primary-foreground, #fff)"
|
|
1031
|
+
},
|
|
1032
|
+
badgeWarn: {
|
|
1033
|
+
fontSize: 10,
|
|
1034
|
+
lineHeight: "14px",
|
|
1035
|
+
padding: "1px 7px",
|
|
1036
|
+
borderRadius: 999,
|
|
1037
|
+
fontWeight: 500,
|
|
1038
|
+
background: "var(--dsw-alias-state-warn-primary, #f5a524)",
|
|
1039
|
+
color: "var(--dsw-alias-label-primary-foreground, #fff)"
|
|
1040
|
+
},
|
|
993
1041
|
pushRight: {
|
|
994
1042
|
marginLeft: "auto",
|
|
995
1043
|
flexShrink: 0
|
|
@@ -1097,10 +1145,10 @@ const styles = {
|
|
|
1097
1145
|
usage: {
|
|
1098
1146
|
display: "flex",
|
|
1099
1147
|
flexDirection: "column",
|
|
1100
|
-
gap:
|
|
1101
|
-
marginTop:
|
|
1148
|
+
gap: 8,
|
|
1149
|
+
marginTop: 2,
|
|
1102
1150
|
borderTop: "0.5px solid var(--dsw-alias-border-l2)",
|
|
1103
|
-
paddingTop:
|
|
1151
|
+
paddingTop: 10
|
|
1104
1152
|
},
|
|
1105
1153
|
usageHeader: {
|
|
1106
1154
|
display: "flex",
|
|
@@ -1111,7 +1159,7 @@ const styles = {
|
|
|
1111
1159
|
usageRow: {
|
|
1112
1160
|
display: "flex",
|
|
1113
1161
|
flexDirection: "column",
|
|
1114
|
-
gap:
|
|
1162
|
+
gap: 4
|
|
1115
1163
|
},
|
|
1116
1164
|
usageLine: {
|
|
1117
1165
|
display: "flex",
|
|
@@ -1123,7 +1171,23 @@ const styles = {
|
|
|
1123
1171
|
height: 6,
|
|
1124
1172
|
borderRadius: 999,
|
|
1125
1173
|
background: "var(--dsw-alias-bg-layer-3, var(--dsw-alias-bg-layer-2))",
|
|
1126
|
-
overflow: "hidden"
|
|
1174
|
+
overflow: "hidden",
|
|
1175
|
+
boxShadow: "inset 0 0 0 1px #8a8f9833"
|
|
1176
|
+
},
|
|
1177
|
+
usageAccount: {
|
|
1178
|
+
display: "flex",
|
|
1179
|
+
flexDirection: "column",
|
|
1180
|
+
gap: 6,
|
|
1181
|
+
padding: "8px 10px",
|
|
1182
|
+
borderRadius: "var(--dsw-radius-md, 10px)",
|
|
1183
|
+
background: "var(--dsw-alias-bg-layer-1)",
|
|
1184
|
+
border: "0.5px solid var(--dsw-alias-border-l2)"
|
|
1185
|
+
},
|
|
1186
|
+
usageInline: {
|
|
1187
|
+
display: "flex",
|
|
1188
|
+
flexDirection: "column",
|
|
1189
|
+
gap: 6,
|
|
1190
|
+
marginTop: 4
|
|
1127
1191
|
},
|
|
1128
1192
|
modelRow: {
|
|
1129
1193
|
display: "flex",
|
|
@@ -1233,11 +1297,11 @@ const styles = {
|
|
|
1233
1297
|
},
|
|
1234
1298
|
divider: { borderTop: "0.5px solid var(--dsw-alias-border-l2)" }
|
|
1235
1299
|
};
|
|
1236
|
-
/** Status dot
|
|
1237
|
-
function
|
|
1238
|
-
if (status.busy) return
|
|
1239
|
-
if (status.loggedIn) return
|
|
1240
|
-
return
|
|
1300
|
+
/** Status dot style for one provider's connection state. */
|
|
1301
|
+
function dotStyle(status) {
|
|
1302
|
+
if (status.busy) return styles.dotBusy;
|
|
1303
|
+
if (status.loggedIn) return styles.dotLive;
|
|
1304
|
+
return {};
|
|
1241
1305
|
}
|
|
1242
1306
|
/** Localized label for one provider-owned detail row. */
|
|
1243
1307
|
function detailLabel(t, row) {
|
|
@@ -1255,70 +1319,38 @@ function windowAmount(window$1) {
|
|
|
1255
1319
|
if (window$1.used !== void 0 && window$1.limit !== void 0) return `${String(window$1.used)}/${String(window$1.limit)}`;
|
|
1256
1320
|
return "—";
|
|
1257
1321
|
}
|
|
1258
|
-
/** One account's
|
|
1259
|
-
function
|
|
1260
|
-
const {
|
|
1322
|
+
/** One account's metered windows, rendered under its account row. */
|
|
1323
|
+
function AccountUsage(props) {
|
|
1324
|
+
const { entry, t } = props;
|
|
1325
|
+
if (entry === void 0) return null;
|
|
1261
1326
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1262
|
-
style: styles.
|
|
1263
|
-
children: [
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1327
|
+
style: styles.usageInline,
|
|
1328
|
+
children: [entry.windows.map((window$1) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1329
|
+
style: styles.usageRow,
|
|
1330
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1331
|
+
style: styles.usageLine,
|
|
1332
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1333
|
+
style: styles.modelName,
|
|
1334
|
+
children: [
|
|
1335
|
+
windowLabel(t, window$1),
|
|
1336
|
+
" · ",
|
|
1337
|
+
windowAmount(window$1)
|
|
1338
|
+
]
|
|
1339
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1340
|
+
style: styles.modelMeta,
|
|
1341
|
+
children: window$1.resetsAt === void 0 ? "" : formatReset$1(window$1.resetsAt, t)
|
|
1276
1342
|
})]
|
|
1277
|
-
}),
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1289
|
-
style: styles.usageLine,
|
|
1290
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1291
|
-
style: styles.modelMeta,
|
|
1292
|
-
children: [entry.plan === void 0 ? entry.account : t("usagePlan", { plan: entry.plan }), entry.renewsAt === void 0 ? "" : ` · ${t("usageRenews", { time: formatTime(entry.renewsAt) })}`]
|
|
1293
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1294
|
-
style: styles.modelMeta,
|
|
1295
|
-
children: t("usageFetched", { time: formatTime(entry.fetchedAt) })
|
|
1296
|
-
})]
|
|
1297
|
-
}), entry.windows.map((window$1) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1298
|
-
style: styles.usageRow,
|
|
1299
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1300
|
-
style: styles.usageLine,
|
|
1301
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
1302
|
-
style: styles.modelName,
|
|
1303
|
-
children: [
|
|
1304
|
-
windowLabel(t, window$1),
|
|
1305
|
-
" · ",
|
|
1306
|
-
windowAmount(window$1)
|
|
1307
|
-
]
|
|
1308
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1309
|
-
style: styles.modelMeta,
|
|
1310
|
-
children: window$1.resetsAt === void 0 ? "" : formatReset$1(window$1.resetsAt, t)
|
|
1311
|
-
})]
|
|
1312
|
-
}), window$1.usedPercent !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1313
|
-
className: "dsh-subscription-meter",
|
|
1314
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1315
|
-
style: { width: `${String(Math.min(100, Math.max(0, window$1.usedPercent)))}%` },
|
|
1316
|
-
"data-exhausted": window$1.usedPercent >= 90 ? "true" : "false"
|
|
1317
|
-
})
|
|
1318
|
-
})]
|
|
1319
|
-
}, `${entry.account}-${window$1.label}`))]
|
|
1320
|
-
}, entry.account))
|
|
1321
|
-
]
|
|
1343
|
+
}), window$1.usedPercent !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1344
|
+
className: "dsh-subscription-meter",
|
|
1345
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1346
|
+
style: { width: `${String(Math.min(100, Math.max(0, window$1.usedPercent)))}%` },
|
|
1347
|
+
"data-exhausted": window$1.usedPercent >= 90 ? "true" : "false"
|
|
1348
|
+
})
|
|
1349
|
+
})]
|
|
1350
|
+
}, `${entry.account}-${window$1.label}`)), entry.windows.length === 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1351
|
+
style: styles.statusLine,
|
|
1352
|
+
children: t("usageNone")
|
|
1353
|
+
})]
|
|
1322
1354
|
});
|
|
1323
1355
|
}
|
|
1324
1356
|
/** The pending-login block: a device code, or a link to the sign-in page. */
|
|
@@ -1522,15 +1554,28 @@ function ProviderCard(props) {
|
|
|
1522
1554
|
*/
|
|
1523
1555
|
const summaryLine = !connectable ? t("statusAuto", { count: models.filter((model) => model.visible).length }) : busy ? t("statusBusy") : status.loggedIn ? t("statusConnected", { count: accounts.length }) : t("statusSignedOut");
|
|
1524
1556
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1525
|
-
style:
|
|
1557
|
+
style: cardOpen ? {
|
|
1558
|
+
...styles.card,
|
|
1559
|
+
...styles.cardOpen
|
|
1560
|
+
} : styles.card,
|
|
1526
1561
|
children: [
|
|
1527
1562
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1528
1563
|
style: styles.cardHeader,
|
|
1564
|
+
role: "button",
|
|
1565
|
+
tabIndex: 0,
|
|
1566
|
+
"aria-expanded": cardOpen,
|
|
1567
|
+
onClick: toggleCardOpen,
|
|
1568
|
+
onKeyDown: (event) => {
|
|
1569
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
1570
|
+
event.preventDefault();
|
|
1571
|
+
toggleCardOpen();
|
|
1572
|
+
}
|
|
1573
|
+
},
|
|
1529
1574
|
children: [
|
|
1530
1575
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1531
1576
|
style: {
|
|
1532
1577
|
...styles.dot,
|
|
1533
|
-
|
|
1578
|
+
...dotStyle(status)
|
|
1534
1579
|
},
|
|
1535
1580
|
"aria-hidden": "true"
|
|
1536
1581
|
}),
|
|
@@ -1538,9 +1583,9 @@ function ProviderCard(props) {
|
|
|
1538
1583
|
style: styles.name,
|
|
1539
1584
|
children: status.displayName
|
|
1540
1585
|
}),
|
|
1541
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1542
|
-
style: styles.
|
|
1543
|
-
children:
|
|
1586
|
+
status.loggedIn && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1587
|
+
style: styles.badgeDefault,
|
|
1588
|
+
children: t("badgeLive")
|
|
1544
1589
|
}),
|
|
1545
1590
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1546
1591
|
style: styles.cardSummary,
|
|
@@ -1552,7 +1597,10 @@ function ProviderCard(props) {
|
|
|
1552
1597
|
style: styles.pushRight,
|
|
1553
1598
|
"aria-expanded": cardOpen,
|
|
1554
1599
|
"aria-controls": `dsh-subscription-card-${status.provider}`,
|
|
1555
|
-
onClick:
|
|
1600
|
+
onClick: (event) => {
|
|
1601
|
+
event.stopPropagation();
|
|
1602
|
+
toggleCardOpen();
|
|
1603
|
+
},
|
|
1556
1604
|
children: cardOpen ? t("collapse") : t("edit")
|
|
1557
1605
|
})
|
|
1558
1606
|
]
|
|
@@ -1580,52 +1628,62 @@ function ProviderCard(props) {
|
|
|
1580
1628
|
className: "dsh-subscription-success",
|
|
1581
1629
|
children: message.text
|
|
1582
1630
|
}),
|
|
1583
|
-
accounts.map((account) =>
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
style: styles.
|
|
1587
|
-
children: [
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1631
|
+
accounts.map((account) => {
|
|
1632
|
+
const usageEntry = (status.usage ?? []).find((entry) => entry.account === account.account);
|
|
1633
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1634
|
+
style: styles.accountRow,
|
|
1635
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1636
|
+
style: styles.accountHeader,
|
|
1637
|
+
children: [
|
|
1638
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1639
|
+
type: "button",
|
|
1640
|
+
style: styles.starButton,
|
|
1641
|
+
title: account.isDefault ? t("defaultBadge") : t("makeDefault"),
|
|
1642
|
+
"aria-label": account.isDefault ? t("defaultBadge") : t("makeDefault"),
|
|
1643
|
+
disabled: busyAction || account.isDefault,
|
|
1644
|
+
onClick: () => {
|
|
1645
|
+
props.onSetDefault(account.account);
|
|
1646
|
+
},
|
|
1647
|
+
children: account.isDefault ? "★" : "☆"
|
|
1648
|
+
}),
|
|
1649
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1650
|
+
style: styles.accountName,
|
|
1651
|
+
children: account.label
|
|
1652
|
+
}),
|
|
1653
|
+
account.isDefault && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1654
|
+
style: styles.badgeDefault,
|
|
1655
|
+
children: t("defaultBadge")
|
|
1656
|
+
}),
|
|
1657
|
+
account.needsLogin === true && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1658
|
+
style: styles.badgeWarn,
|
|
1659
|
+
title: t("accountNeedsLoginHint"),
|
|
1660
|
+
children: t("accountNeedsLogin")
|
|
1661
|
+
}),
|
|
1662
|
+
usageEntry?.plan !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1663
|
+
style: styles.badge,
|
|
1664
|
+
children: t("usagePlan", { plan: usageEntry.plan })
|
|
1665
|
+
}),
|
|
1666
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1667
|
+
style: styles.statusLine,
|
|
1668
|
+
children: account.expired ? t("accountExpired") : t("accountExpires", { time: formatTime(account.expiresAt) })
|
|
1669
|
+
}),
|
|
1670
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1671
|
+
type: "button",
|
|
1672
|
+
className: "dsh-subscription-quiet",
|
|
1673
|
+
style: styles.pushRight,
|
|
1674
|
+
disabled: busyAction,
|
|
1675
|
+
onClick: () => {
|
|
1676
|
+
props.onLogout(account.account);
|
|
1677
|
+
},
|
|
1678
|
+
children: t("logout")
|
|
1679
|
+
})
|
|
1680
|
+
]
|
|
1681
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AccountUsage, {
|
|
1682
|
+
entry: usageEntry,
|
|
1683
|
+
t
|
|
1684
|
+
})]
|
|
1685
|
+
}, account.account);
|
|
1686
|
+
}),
|
|
1629
1687
|
status.loggedIn && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1630
1688
|
style: styles.catalog,
|
|
1631
1689
|
children: [
|
|
@@ -1816,13 +1874,6 @@ function ProviderCard(props) {
|
|
|
1816
1874
|
})
|
|
1817
1875
|
]
|
|
1818
1876
|
}),
|
|
1819
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageBlock, {
|
|
1820
|
-
usage: status.usage ?? [],
|
|
1821
|
-
...status.usageError === void 0 ? {} : { error: status.usageError },
|
|
1822
|
-
t,
|
|
1823
|
-
busyAction,
|
|
1824
|
-
onRefresh: props.onRefreshUsage
|
|
1825
|
-
}),
|
|
1826
1877
|
connectable && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1827
1878
|
style: styles.actions,
|
|
1828
1879
|
children: [
|
|
@@ -2079,6 +2130,20 @@ function SubscriptionsSection(props) {
|
|
|
2079
2130
|
startPolling,
|
|
2080
2131
|
stopPolling
|
|
2081
2132
|
]);
|
|
2133
|
+
/**
|
|
2134
|
+
* Signed-in providers read first: a route with a live account is the one a
|
|
2135
|
+
* reader most likely wants, and `auto` (which owns no account) leads the rest.
|
|
2136
|
+
* The sort is stable, so equal ranks keep the host's configured order.
|
|
2137
|
+
*/
|
|
2138
|
+
const orderedProviders = (0, react.useMemo)(() => {
|
|
2139
|
+
const providers = status?.providers ?? [];
|
|
2140
|
+
const rank = (provider) => {
|
|
2141
|
+
if (provider.provider === "auto") return 0;
|
|
2142
|
+
if (provider.loggedIn) return 1;
|
|
2143
|
+
return 2;
|
|
2144
|
+
};
|
|
2145
|
+
return [...providers].sort((left, right) => rank(left) - rank(right));
|
|
2146
|
+
}, [status?.providers]);
|
|
2082
2147
|
/** Run one action for one provider, reporting its own failure. */
|
|
2083
2148
|
const act = (0, react.useCallback)(async (provider, run) => {
|
|
2084
2149
|
setBusyAction(true);
|
|
@@ -2248,9 +2313,15 @@ function SubscriptionsSection(props) {
|
|
|
2248
2313
|
style: styles.section,
|
|
2249
2314
|
children: [
|
|
2250
2315
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: subscriptionsCss }),
|
|
2251
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
2252
|
-
style: styles.
|
|
2253
|
-
children:
|
|
2316
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2317
|
+
style: styles.sectionHeader,
|
|
2318
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
2319
|
+
style: styles.heading,
|
|
2320
|
+
children: t("nav")
|
|
2321
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2322
|
+
style: styles.intro,
|
|
2323
|
+
children: t("intro")
|
|
2324
|
+
})]
|
|
2254
2325
|
}),
|
|
2255
2326
|
error !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
2256
2327
|
className: "dsh-subscription-error",
|
|
@@ -2260,7 +2331,7 @@ function SubscriptionsSection(props) {
|
|
|
2260
2331
|
style: styles.statusLine,
|
|
2261
2332
|
children: t("loading")
|
|
2262
2333
|
}),
|
|
2263
|
-
|
|
2334
|
+
orderedProviders.map((provider) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProviderCard, {
|
|
2264
2335
|
status: provider,
|
|
2265
2336
|
t,
|
|
2266
2337
|
busyAction,
|