@deepseek-ai/dsh-client-ui-settings-account 0.2.1-alpha.4 → 0.2.1-alpha.5
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.i18n.yaml +2 -2
- package/README.md +1 -1
- package/README.zh.md +1 -1
- package/lib/client.js +117 -66
- package/lib/types/client/AccountNotice.d.ts +7 -7
- package/lib/types/client/AccountSection.d.ts +2 -2
- package/lib/types/client/bonus-notices.d.ts +7 -5
- package/lib/types/client/notice-transition.d.ts +7 -0
- package/package.json +17 -17
package/README.i18n.yaml
CHANGED
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
en: c26f81e8adf0128b
|
|
16
16
|
zh: e11ab371f51f66bc
|
|
17
17
|
/deepseek-ai-dsh-client-ui-settings-account/use-this-package:
|
|
18
|
-
en:
|
|
19
|
-
zh:
|
|
18
|
+
en: 45aa7b44d5424d9b
|
|
19
|
+
zh: 20c7d344c4e9bce0
|
|
20
20
|
/deepseek-ai-dsh-client-ui-settings-account/use-this-package/desktop-onboarding:
|
|
21
21
|
en: c1c4db71fd09ca13
|
|
22
22
|
zh: a40c0a01e9951945
|
package/README.md
CHANGED
|
@@ -52,7 +52,7 @@ The account card’s More account information link has no underline and opens th
|
|
|
52
52
|
|
|
53
53
|
Sign out first queries running account-token tasks and opens a confirmation dialog. The warning describes interruption when such tasks exist; otherwise it explains that data is retained and the account can be signed in again. Cancel, close, and Escape dismiss without signing out. Failed impact queries still open confirmation with an explicit unknown-task warning; failed sign-out keeps the dialog available for retry.
|
|
54
54
|
|
|
55
|
-
A granted bonus appears as a server-authored notice above the sidebar account launcher without taking focus. The client reads the unnotified bonus when an account becomes active and once per Settings entry; it never polls. The server orders the candidates and owns the copy, so the client
|
|
55
|
+
A granted bonus appears as a server-authored notice above the sidebar account launcher without taking focus. The client reads the unnotified bonus when an account becomes active and once per Settings entry; it never polls. The server orders the candidates and owns the copy, so the client stacks every live notice in that order and renders its message verbatim. Only the foreground card is interactive and reports display for acknowledgement. Closing it promotes the next card with a 250ms ease-out position and scale transition, including changes in content height; reduced-motion preferences disable the transition. A server-supplied title replaces the localized bonus title; responses without title retain that default.
|
|
56
56
|
|
|
57
57
|
The notice waits until Desktop onboarding no longer covers the workspace, including loading, completion saving, and the exit animation, and until model credential onboarding unmounts. Closing the application during onboarding leaves the bonus unacknowledged. In the main interface, the notice is painted as soon as the server offers it, including underneath the translucent settings panel, once the document is visible and the card has passed one presented frame. That painted frame is the whole display signal: the card measures no cover, so a card behind the open overlay counts exactly as any other, and closing the card counts as a display too. Displaying a card queues its acknowledgement, so one mounted card is acknowledged once. A failed acknowledgement retries with a capped backoff for the rest of the signed-in session and never surfaces as an account UI error. A read that fails leaves the visible card and its pending acknowledgement alone, so a transport reconnect keeps retrying. Nothing is written to browser storage. The second signed-in frame of one sign-in and a reconnected stream's replayed state are one session, not a new one, so they keep the card and its retries; signing out, replacing the credential with another account's, or unloading the plugin discards them. Identity-only updates do not reach the account UI stream. Every signed-in frame reads again, and a newer read supersedes one still in flight, so a credential swapped in place is named by a fresh read rather than inheriting the replaced account's; the batch's account id then drops the previous account's card and queue even with no intervening signed-out state. The next sign-in displays whatever the server still offers, including an order an earlier sign-in acknowledged, and a card the user has already seen stays up until it is closed, even when a later read returns no bonus.
|
|
58
58
|
|
package/README.zh.md
CHANGED
|
@@ -52,7 +52,7 @@ Chat 通过 `shell.overlay` 中的宿主把已绑定 Session 的实时欠费交
|
|
|
52
52
|
|
|
53
53
|
退出登录先查询正在使用账号 token 的任务,再打开确认弹窗。有此类任务时提示执行将被打断,否则提示数据保留且可重新登录。取消、关闭和 Escape 均不退登。影响查询失败仍打开确认弹窗,并明确提示无法确认任务状态;退登失败保留弹窗以便重试。
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
赠金到账时,侧栏账号入口上方显示一条由服务端提供文案的通知,不抢占焦点。客户端仅在账号进入登录态时、以及每次进入设置页时读取一次未通知赠金,不做轮询。候选顺序与文案均由服务端决定,客户端按该顺序层叠展示全部未过期通知并原样渲染消息。只有最前面的卡片可交互,并在实际展示后触发确认。关闭前卡后,下一张卡片通过 250ms ease-out 的位置与缩放过渡(包括内容高度变化)进入前台;偏好减少动态效果时禁用过渡。服务端提供的 title 替换本地化赠金标题;未返回 title 时沿用默认标题。
|
|
56
56
|
|
|
57
57
|
通知等待 Desktop 引导界面不再遮盖主界面且模型凭证引导卸载后才展示,Desktop 引导的等待范围包括加载、完成时的保存和退出动画。在引导期间关闭应用不会确认赠金通知。进入主界面后,服务端返回即绘制通知,包括在设置面板的半透明蒙层之下;同时要求文档可见且卡片已完成一帧绘制。这一帧绘制就是全部的展示信号:卡片不检测遮挡,因此处于打开蒙层之下的卡片与其他情形同样计数,用户关闭卡片同样计入展示。卡片展示后即排队确认,因此同一张挂载的卡只确认一次。确认失败会在本次登录会话内按带上限的退避重试,且不会在账号界面报错。读取失败不会影响已展示的卡片及其待确认队列,因此连接重连后仍会继续重试。不写入浏览器存储。同一次登录的第二个登录态帧以及重连后重放的登录态属于同一会话而非新会话,因此保留卡片与重试;只有退出登录、凭证被换成另一账号,或卸载插件才会丢弃。仅身份信息更新不会进入账号界面订阅流。每个登录态帧都会重新读取,且新的读取会取代仍在进行中的旧读取,因此就地更换的凭证会由一次全新的读取来识别,而不会沿用被替换账号的读取结果;读取结果中的账号 ID 随后会丢弃上一个账号的卡片与队列,即使没有中间的退出登录状态。下一次登录会展示服务端仍然下发的内容,包括上一次登录已确认过的订单;用户已看到的卡片会保留到关闭为止,即使之后的读取没有返回赠金。
|
|
58
58
|
|
package/lib/client.js
CHANGED
|
@@ -1535,7 +1535,7 @@ window.__ModuleLoader__.load({
|
|
|
1535
1535
|
}
|
|
1536
1536
|
//#endregion
|
|
1537
1537
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-account/src/client/AccountNotice.module.css.mjs
|
|
1538
|
-
const css$4 = ".zwW4-
|
|
1538
|
+
const css$4 = ".zwW4-W_stack{z-index:40;isolation:isolate;width:280px;max-width:calc(100vw - 16px);position:fixed}.zwW4-W_card{box-sizing:border-box;background:var(--dsw-specific-input-major);width:100%;box-shadow:var(--dsw-elevation-panel);color:var(--dsw-alias-label-secondary);z-index:calc(0 - var(--notice-depth));transform:translateY(calc(-4px * var(--notice-depth))) scaleX(var(--notice-scale));transform-origin:top;border:0;border-radius:16px;padding:20px;font-size:14px;line-height:22px;transition:transform .25s ease-out;position:relative}.zwW4-W_card[data-front=false]{pointer-events:none;height:100%;position:absolute;inset:0;overflow:hidden}@media (prefers-reduced-motion:reduce){.zwW4-W_card{transition:none}}.zwW4-W_copy{overflow-wrap:anywhere;flex-direction:column;gap:2px;display:flex}.zwW4-W_copy p{white-space:pre-wrap;margin:0}.zwW4-W_title{align-items:flex-start;gap:2px;font-weight:500;line-height:20px;display:flex}.zwW4-W_icon{width:14px;height:14px;color:var(--dsw-alias-brand-primary-new-colorprimary-new-color);flex:none;margin-top:1px;display:flex}.zwW4-W_close{width:18px;height:18px;color:var(--dsw-alias-label-caption);cursor:pointer;background:0 0;border:0;justify-content:center;align-items:center;padding:4px;display:flex;position:absolute;top:6px;right:6px}.zwW4-W_close:focus-visible{outline:2px solid var(--dsw-focus-ring-color,var(--dsw-alias-state-business-primary));outline-offset:2px;border-radius:4px}";
|
|
1539
1539
|
const tagId$4 = "@deepseek-ai/dsh-client-ui-settings-account/AccountNotice.module.css";
|
|
1540
1540
|
if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=" + JSON.stringify(tagId$4) + "]") === null) {
|
|
1541
1541
|
const tag = document.createElement("style");
|
|
@@ -1549,9 +1549,45 @@ window.__ModuleLoader__.load({
|
|
|
1549
1549
|
"close": "zwW4-W_close",
|
|
1550
1550
|
"copy": "zwW4-W_copy",
|
|
1551
1551
|
"icon": "zwW4-W_icon",
|
|
1552
|
+
"stack": "zwW4-W_stack",
|
|
1552
1553
|
"title": "zwW4-W_title"
|
|
1553
1554
|
};
|
|
1554
1555
|
//#endregion
|
|
1556
|
+
//#region lib/types/client/notice-transition.js
|
|
1557
|
+
/** Animate a notification promotion across the old and new card dimensions. */
|
|
1558
|
+
/**
|
|
1559
|
+
* Close a card and animate surviving siblings from their currently displayed rectangles.
|
|
1560
|
+
* @param card - mounted foreground card whose direct parent owns the stack.
|
|
1561
|
+
* @param dismiss - synchronous notification-store update for the close gesture.
|
|
1562
|
+
*/
|
|
1563
|
+
function dismissNotice(card, dismiss) {
|
|
1564
|
+
if (typeof card.animate !== "function" || getComputedStyle(card).transitionDuration === "0s") {
|
|
1565
|
+
dismiss();
|
|
1566
|
+
return;
|
|
1567
|
+
}
|
|
1568
|
+
const before = [...card.parentElement.querySelectorAll("aside")].map((element) => ({
|
|
1569
|
+
element,
|
|
1570
|
+
rect: element.getBoundingClientRect()
|
|
1571
|
+
}));
|
|
1572
|
+
for (const { element } of before) {
|
|
1573
|
+
for (const animation of element.getAnimations()) animation.cancel();
|
|
1574
|
+
element.style.transition = "none";
|
|
1575
|
+
}
|
|
1576
|
+
(0, react_dom.flushSync)(dismiss);
|
|
1577
|
+
for (const { element, rect } of before) {
|
|
1578
|
+
if (!element.isConnected) continue;
|
|
1579
|
+
const transform = getComputedStyle(element).transform;
|
|
1580
|
+
element.style.transform = "none";
|
|
1581
|
+
const next = element.getBoundingClientRect();
|
|
1582
|
+
element.style.transform = "";
|
|
1583
|
+
element.animate([{ transform: `translate(${rect.x + rect.width / 2 - next.x - next.width / 2}px, ${rect.y - next.y}px) scale(${rect.width / next.width}, ${rect.height / next.height})` }, { transform }], {
|
|
1584
|
+
duration: 250,
|
|
1585
|
+
easing: "ease-out"
|
|
1586
|
+
});
|
|
1587
|
+
element.style.transition = "";
|
|
1588
|
+
}
|
|
1589
|
+
}
|
|
1590
|
+
//#endregion
|
|
1555
1591
|
//#region lib/types/client/AccountNotice.js
|
|
1556
1592
|
/**
|
|
1557
1593
|
* Sidebar bonus notice. The card reports a display once it has a position, the
|
|
@@ -1563,6 +1599,7 @@ window.__ModuleLoader__.load({
|
|
|
1563
1599
|
*/
|
|
1564
1600
|
/** @param expiresAt - server expiration timestamp. @returns whether the award can still be spent. */
|
|
1565
1601
|
function live(expiresAt) {
|
|
1602
|
+
if (expiresAt === "") return true;
|
|
1566
1603
|
const expires = Date.parse(expiresAt);
|
|
1567
1604
|
return Number.isNaN(expires) || expires > Date.now();
|
|
1568
1605
|
}
|
|
@@ -1590,19 +1627,18 @@ window.__ModuleLoader__.load({
|
|
|
1590
1627
|
if (timer !== void 0) clearTimeout(timer);
|
|
1591
1628
|
};
|
|
1592
1629
|
}
|
|
1593
|
-
/** @param props -
|
|
1594
|
-
* @returns a non-modal
|
|
1630
|
+
/** @param props - server-ordered notices, localized fallback copy, anchor, and display callbacks.
|
|
1631
|
+
* @returns a non-modal stack whose foreground card alone can report display or be closed.
|
|
1595
1632
|
*/
|
|
1596
|
-
function
|
|
1633
|
+
function AccountNoticeStack({ notices, anchor, title, closeLabel, onShown, onDismiss }) {
|
|
1597
1634
|
const [position, setPosition] = (0, react.useState)();
|
|
1598
|
-
const reported = (0, react.useRef)(false);
|
|
1599
1635
|
(0, react.useLayoutEffect)(() => {
|
|
1600
|
-
if (!anchor.current
|
|
1636
|
+
if (!anchor.current) return;
|
|
1601
1637
|
const element = anchor.current;
|
|
1602
1638
|
const update = () => {
|
|
1603
1639
|
const rect = element.getBoundingClientRect();
|
|
1604
1640
|
setPosition({
|
|
1605
|
-
left: Math.max(8, Math.min(rect.left, window.innerWidth -
|
|
1641
|
+
left: Math.max(8, Math.min(rect.left, window.innerWidth - 288)),
|
|
1606
1642
|
bottom: Math.max(8, window.innerHeight - rect.top + 4)
|
|
1607
1643
|
});
|
|
1608
1644
|
};
|
|
@@ -1616,13 +1652,28 @@ window.__ModuleLoader__.load({
|
|
|
1616
1652
|
window.removeEventListener("resize", update);
|
|
1617
1653
|
window.removeEventListener("scroll", update, true);
|
|
1618
1654
|
};
|
|
1619
|
-
}, [
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1655
|
+
}, [anchor]);
|
|
1656
|
+
const liveNotices = notices.filter((notice) => live(notice.expiresAt));
|
|
1657
|
+
return (0, react_dom.createPortal)((0, react_jsx_runtime.jsx)("div", {
|
|
1658
|
+
className: AccountNotice_module_css_default.stack,
|
|
1659
|
+
style: position ?? { visibility: "hidden" },
|
|
1660
|
+
children: liveNotices.map((notice, depth) => (0, react_jsx_runtime.jsx)(NoticeCard, {
|
|
1661
|
+
notice,
|
|
1662
|
+
depth,
|
|
1663
|
+
ready: position !== void 0,
|
|
1664
|
+
title: notice.title ?? title,
|
|
1665
|
+
closeLabel,
|
|
1666
|
+
onShown,
|
|
1667
|
+
onDismiss
|
|
1668
|
+
}, notice.orderId))
|
|
1669
|
+
}), document.body);
|
|
1670
|
+
}
|
|
1671
|
+
/** One stable card node remains mounted as the cards before it are dismissed. */
|
|
1672
|
+
function NoticeCard({ notice, depth, ready, title, closeLabel, onShown, onDismiss }) {
|
|
1673
|
+
const foreground = depth === 0;
|
|
1674
|
+
const reported = (0, react.useRef)(false);
|
|
1624
1675
|
(0, react.useEffect)(() => {
|
|
1625
|
-
if (
|
|
1676
|
+
if (!ready || !foreground || reported.current || !live(notice.expiresAt)) return;
|
|
1626
1677
|
let cancel;
|
|
1627
1678
|
const attempt = () => {
|
|
1628
1679
|
if (reported.current || cancel !== void 0 || !live(notice.expiresAt)) return;
|
|
@@ -1641,15 +1692,20 @@ window.__ModuleLoader__.load({
|
|
|
1641
1692
|
cancel?.();
|
|
1642
1693
|
};
|
|
1643
1694
|
}, [
|
|
1644
|
-
|
|
1695
|
+
ready,
|
|
1696
|
+
foreground,
|
|
1645
1697
|
notice.orderId,
|
|
1646
1698
|
notice.expiresAt,
|
|
1647
1699
|
onShown
|
|
1648
1700
|
]);
|
|
1649
|
-
|
|
1650
|
-
return (0, react_dom.createPortal)((0, react_jsx_runtime.jsxs)("aside", {
|
|
1701
|
+
return (0, react_jsx_runtime.jsxs)("aside", {
|
|
1651
1702
|
className: AccountNotice_module_css_default.card,
|
|
1652
|
-
|
|
1703
|
+
"data-front": foreground,
|
|
1704
|
+
"aria-hidden": !foreground,
|
|
1705
|
+
style: {
|
|
1706
|
+
"--notice-depth": depth,
|
|
1707
|
+
"--notice-scale": Math.pow(272 / 280, depth)
|
|
1708
|
+
},
|
|
1653
1709
|
children: [(0, react_jsx_runtime.jsxs)("div", {
|
|
1654
1710
|
role: "status",
|
|
1655
1711
|
className: AccountNotice_module_css_default.copy,
|
|
@@ -1679,14 +1735,17 @@ window.__ModuleLoader__.load({
|
|
|
1679
1735
|
}), (0, react_jsx_runtime.jsx)("p", { children: notice.message })]
|
|
1680
1736
|
}), (0, react_jsx_runtime.jsx)("button", {
|
|
1681
1737
|
type: "button",
|
|
1738
|
+
tabIndex: foreground ? void 0 : -1,
|
|
1682
1739
|
className: AccountNotice_module_css_default.close,
|
|
1683
1740
|
"aria-label": closeLabel,
|
|
1684
|
-
onClick: () => {
|
|
1685
|
-
|
|
1741
|
+
onClick: (event) => {
|
|
1742
|
+
dismissNotice(event.currentTarget.parentElement, () => {
|
|
1743
|
+
onDismiss(notice.orderId);
|
|
1744
|
+
});
|
|
1686
1745
|
},
|
|
1687
1746
|
children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconCloseOutlineRegular, { size: 10 })
|
|
1688
1747
|
})]
|
|
1689
|
-
})
|
|
1748
|
+
});
|
|
1690
1749
|
}
|
|
1691
1750
|
//#endregion
|
|
1692
1751
|
//#region \0dsh-css:/home/runner/work/deepseek-harness/deepseek-harness/packages/client/ui-settings-account/src/client/AccountMenu.module.css.mjs
|
|
@@ -1770,14 +1829,14 @@ window.__ModuleLoader__.load({
|
|
|
1770
1829
|
setExpiryNotice(false);
|
|
1771
1830
|
}
|
|
1772
1831
|
}),
|
|
1773
|
-
signedIn && !account.desktopOnboardingVisible && !account.onboarding && account.
|
|
1774
|
-
|
|
1832
|
+
signedIn && !account.desktopOnboardingVisible && !account.onboarding && account.notices && (0, react_jsx_runtime.jsx)(AccountNoticeStack, {
|
|
1833
|
+
notices: account.notices,
|
|
1775
1834
|
anchor,
|
|
1776
1835
|
title: t("bonusNoticeTitle"),
|
|
1777
1836
|
closeLabel: t("close"),
|
|
1778
1837
|
onShown: bonusNoticeShown,
|
|
1779
1838
|
onDismiss: bonusNoticeDismissed
|
|
1780
|
-
}
|
|
1839
|
+
}),
|
|
1781
1840
|
(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
|
|
1782
1841
|
open,
|
|
1783
1842
|
side: "top",
|
|
@@ -2605,6 +2664,7 @@ window.__ModuleLoader__.load({
|
|
|
2605
2664
|
* @returns whether the bonus can no longer be shown.
|
|
2606
2665
|
*/
|
|
2607
2666
|
function expired(expiresAt, at) {
|
|
2667
|
+
if (expiresAt === "") return false;
|
|
2608
2668
|
const expires = Date.parse(expiresAt);
|
|
2609
2669
|
return !Number.isNaN(expires) && expires <= at;
|
|
2610
2670
|
}
|
|
@@ -2616,7 +2676,7 @@ window.__ModuleLoader__.load({
|
|
|
2616
2676
|
function createBonusNoticeController(options) {
|
|
2617
2677
|
let scope;
|
|
2618
2678
|
/** Notice currently published to the sidebar, including the expiration checked at display time. */
|
|
2619
|
-
let current;
|
|
2679
|
+
let current = [];
|
|
2620
2680
|
/** Newest read; an older read still in flight has its result dropped once a newer one starts. */
|
|
2621
2681
|
let readGeneration = 0;
|
|
2622
2682
|
let ackTimer;
|
|
@@ -2630,12 +2690,15 @@ window.__ModuleLoader__.load({
|
|
|
2630
2690
|
ackTimer = void 0;
|
|
2631
2691
|
}
|
|
2632
2692
|
};
|
|
2633
|
-
const setCurrent = (
|
|
2634
|
-
if (
|
|
2635
|
-
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2693
|
+
const setCurrent = (notices) => {
|
|
2694
|
+
if (notices.length === current.length && notices.every((notice, index) => {
|
|
2695
|
+
const previous = current[index];
|
|
2696
|
+
return notice.orderId === previous?.orderId && notice.message === previous.message && notice.title === previous.title && notice.expiresAt === previous.expiresAt;
|
|
2697
|
+
})) return;
|
|
2698
|
+
const retained = new Set(notices.map((notice) => notice.orderId));
|
|
2699
|
+
for (const orderId of reported) if (!retained.has(orderId)) reported.delete(orderId);
|
|
2700
|
+
current = notices;
|
|
2701
|
+
options.publish(notices);
|
|
2639
2702
|
};
|
|
2640
2703
|
const scheduleAck = (delay) => {
|
|
2641
2704
|
clearAckTimer();
|
|
@@ -2653,36 +2716,23 @@ window.__ModuleLoader__.load({
|
|
|
2653
2716
|
if (scope !== void 0 && scope.pending.length > 0) scheduleAck(0);
|
|
2654
2717
|
};
|
|
2655
2718
|
/**
|
|
2656
|
-
* Apply
|
|
2657
|
-
*
|
|
2658
|
-
* empty batch leaves a card the user has already seen alone.
|
|
2719
|
+
* Apply the server-ordered stack, excluding expired notices. An empty batch
|
|
2720
|
+
* retains only the foreground card if the user has already seen it.
|
|
2659
2721
|
*/
|
|
2660
2722
|
const apply = (scopeAtRead, batch) => {
|
|
2661
2723
|
if (scopeAtRead.accountId !== batch.accountId) {
|
|
2662
2724
|
scopeAtRead.accountId = batch.accountId;
|
|
2663
2725
|
scopeAtRead.pending.length = 0;
|
|
2664
2726
|
resetAcks();
|
|
2665
|
-
setCurrent(
|
|
2727
|
+
setCurrent([]);
|
|
2666
2728
|
}
|
|
2667
|
-
const
|
|
2668
|
-
if (
|
|
2669
|
-
|
|
2729
|
+
const candidates = batch.bonuses.filter((notice) => !expired(notice.expiresAt, Date.now()));
|
|
2730
|
+
if (candidates.length === 0) {
|
|
2731
|
+
const foreground = current[0];
|
|
2732
|
+
setCurrent(foreground !== void 0 && reported.has(foreground.orderId) ? [foreground] : []);
|
|
2670
2733
|
return;
|
|
2671
2734
|
}
|
|
2672
|
-
|
|
2673
|
-
setCurrent({
|
|
2674
|
-
orderId: candidate.orderId,
|
|
2675
|
-
message: candidate.message,
|
|
2676
|
-
expiresAt: candidate.expiresAt
|
|
2677
|
-
});
|
|
2678
|
-
return;
|
|
2679
|
-
}
|
|
2680
|
-
if (expired(candidate.expiresAt, Date.now())) return;
|
|
2681
|
-
setCurrent({
|
|
2682
|
-
orderId: candidate.orderId,
|
|
2683
|
-
message: candidate.message,
|
|
2684
|
-
expiresAt: candidate.expiresAt
|
|
2685
|
-
});
|
|
2735
|
+
setCurrent(candidates);
|
|
2686
2736
|
};
|
|
2687
2737
|
/**
|
|
2688
2738
|
* Read once for one live lifecycle. A newer read supersedes one in flight: the
|
|
@@ -2742,7 +2792,7 @@ window.__ModuleLoader__.load({
|
|
|
2742
2792
|
/** Queue a presented order, so an acknowledgement interrupted by a failure retries within this sign-in. */
|
|
2743
2793
|
const report = (orderId) => {
|
|
2744
2794
|
const scopeAtReport = scope;
|
|
2745
|
-
if (scopeAtReport === void 0 || current?.orderId !== orderId || reported.has(orderId)) return;
|
|
2795
|
+
if (scopeAtReport === void 0 || current[0]?.orderId !== orderId || reported.has(orderId)) return;
|
|
2746
2796
|
reported.add(orderId);
|
|
2747
2797
|
if (!scopeAtReport.pending.includes(orderId)) scopeAtReport.pending.push(orderId);
|
|
2748
2798
|
ackDelay = options.ackRetryDelayMs;
|
|
@@ -2753,7 +2803,7 @@ window.__ModuleLoader__.load({
|
|
|
2753
2803
|
resetAcks();
|
|
2754
2804
|
scope = void 0;
|
|
2755
2805
|
reported.clear();
|
|
2756
|
-
setCurrent(
|
|
2806
|
+
setCurrent([]);
|
|
2757
2807
|
};
|
|
2758
2808
|
return {
|
|
2759
2809
|
begin() {
|
|
@@ -2767,14 +2817,15 @@ window.__ModuleLoader__.load({
|
|
|
2767
2817
|
return runRead(scope);
|
|
2768
2818
|
},
|
|
2769
2819
|
shown(orderId) {
|
|
2770
|
-
|
|
2771
|
-
if (
|
|
2820
|
+
setCurrent(current.filter((notice) => !expired(notice.expiresAt, Date.now())));
|
|
2821
|
+
if (current[0]?.orderId !== orderId) return;
|
|
2772
2822
|
report(orderId);
|
|
2773
2823
|
},
|
|
2774
2824
|
dismiss(orderId) {
|
|
2775
|
-
|
|
2825
|
+
setCurrent(current.filter((notice) => !expired(notice.expiresAt, Date.now())));
|
|
2826
|
+
if (current[0]?.orderId !== orderId) return;
|
|
2776
2827
|
report(orderId);
|
|
2777
|
-
setCurrent(
|
|
2828
|
+
setCurrent(current.slice(1).filter((notice) => !expired(notice.expiresAt, Date.now())));
|
|
2778
2829
|
}
|
|
2779
2830
|
};
|
|
2780
2831
|
}
|
|
@@ -4410,7 +4461,7 @@ window.__ModuleLoader__.load({
|
|
|
4410
4461
|
avatar.dispose();
|
|
4411
4462
|
}, "account: profile picture lifetime");
|
|
4412
4463
|
/** @returns the client identity for one account call, read at call time so it carries the language and zone in effect then. */
|
|
4413
|
-
const client = () => accountClientMetadata(ctx.locale.getSnapshot().active, "0.2.1-alpha.
|
|
4464
|
+
const client = () => accountClientMetadata(ctx.locale.getSnapshot().active, "0.2.1-alpha.5");
|
|
4414
4465
|
const notices = createBonusNoticeController({
|
|
4415
4466
|
ackRetryDelayMs: config.bonusAckRetryDelayMs,
|
|
4416
4467
|
ackRetryMaxDelayMs: config.bonusAckRetryMaxDelayMs,
|
|
@@ -4424,11 +4475,11 @@ window.__ModuleLoader__.load({
|
|
|
4424
4475
|
if (!result.ok) throw new Error("account bonus acknowledgement failed");
|
|
4425
4476
|
return result.value;
|
|
4426
4477
|
},
|
|
4427
|
-
publish: (
|
|
4428
|
-
const {
|
|
4429
|
-
publish(
|
|
4430
|
-
...
|
|
4431
|
-
|
|
4478
|
+
publish: (notices) => {
|
|
4479
|
+
const { notices: _replaced, ...withoutNotices } = snapshot;
|
|
4480
|
+
publish(notices.length === 0 ? withoutNotices : {
|
|
4481
|
+
...withoutNotices,
|
|
4482
|
+
notices
|
|
4432
4483
|
});
|
|
4433
4484
|
}
|
|
4434
4485
|
});
|
|
@@ -4492,14 +4543,14 @@ window.__ModuleLoader__.load({
|
|
|
4492
4543
|
refreshing = void 0;
|
|
4493
4544
|
avatar.reset();
|
|
4494
4545
|
const initialize = frame.value.status === "credential-stored" && frame.value.attempt?.phase === "succeeded" && snapshot.view?.attempt?.phase !== "succeeded";
|
|
4495
|
-
const {
|
|
4546
|
+
const { notices: previousNotices, ...previous } = snapshot;
|
|
4496
4547
|
publish({
|
|
4497
4548
|
...previous,
|
|
4498
4549
|
view: frame.value,
|
|
4499
4550
|
details: void 0,
|
|
4500
4551
|
avatar: void 0,
|
|
4501
4552
|
failed: false,
|
|
4502
|
-
...frame.value.status === "credential-stored" &&
|
|
4553
|
+
...frame.value.status === "credential-stored" && previousNotices ? { notices: previousNotices } : {}
|
|
4503
4554
|
});
|
|
4504
4555
|
browser.update(frame.value);
|
|
4505
4556
|
frame.accept();
|
|
@@ -4552,7 +4603,7 @@ window.__ModuleLoader__.load({
|
|
|
4552
4603
|
const profile = snapshot.details?.profile;
|
|
4553
4604
|
const context = {
|
|
4554
4605
|
uid: profile?.status === "ready" ? profile.value.id : null,
|
|
4555
|
-
version: "0.2.1-alpha.
|
|
4606
|
+
version: "0.2.1-alpha.5",
|
|
4556
4607
|
width: window.screen.width,
|
|
4557
4608
|
height: window.screen.height,
|
|
4558
4609
|
pixelRatio: window.devicePixelRatio
|
|
@@ -8,17 +8,17 @@
|
|
|
8
8
|
*/
|
|
9
9
|
import { type RefObject } from 'react';
|
|
10
10
|
import type { BonusNotice } from './bonus-notices.ts';
|
|
11
|
-
/** @param props -
|
|
12
|
-
* @returns a non-modal
|
|
11
|
+
/** @param props - server-ordered notices, localized fallback copy, anchor, and display callbacks.
|
|
12
|
+
* @returns a non-modal stack whose foreground card alone can report display or be closed.
|
|
13
13
|
*/
|
|
14
|
-
export declare function
|
|
15
|
-
|
|
14
|
+
export declare function AccountNoticeStack({ notices, anchor, title, closeLabel, onShown, onDismiss }: {
|
|
15
|
+
notices: readonly BonusNotice[];
|
|
16
16
|
anchor: RefObject<HTMLElement>;
|
|
17
17
|
title: string;
|
|
18
18
|
closeLabel: string;
|
|
19
|
-
/** Called
|
|
19
|
+
/** Called after the foreground card has passed a visible presented frame. */
|
|
20
20
|
onShown: (orderId: BonusNotice['orderId']) => void;
|
|
21
|
-
/** Called when the user closes the card
|
|
21
|
+
/** Called when the user closes the foreground card. */
|
|
22
22
|
onDismiss: (orderId: BonusNotice['orderId']) => void;
|
|
23
|
-
}): import("react").ReactPortal
|
|
23
|
+
}): import("react").ReactPortal;
|
|
24
24
|
//# sourceMappingURL=AccountNotice.d.ts.map
|
|
@@ -6,8 +6,8 @@ import type { AccountAvatarSnapshot } from './account-avatar.ts';
|
|
|
6
6
|
import type { BonusNotice } from './bonus-notices.ts';
|
|
7
7
|
/** Safe account snapshot shared by the settings page and launcher. */
|
|
8
8
|
export interface AccountSnapshot {
|
|
9
|
-
/** Server-authored
|
|
10
|
-
|
|
9
|
+
/** Server-authored notices in front-to-back order, absent when none are available. */
|
|
10
|
+
notices?: readonly BonusNotice[];
|
|
11
11
|
/** Latest Host state, absent until the stream responds. */
|
|
12
12
|
view: AccountView | undefined;
|
|
13
13
|
/** Sanitized profile and balance query outcomes, absent while loading. */
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Lifecycle of bonus notices: one
|
|
2
|
+
* Lifecycle of bonus notices: one foreground card in a stack, one read result in
|
|
3
3
|
* force at a time, and one acknowledgement per displayed card. Reads happen when
|
|
4
4
|
* the account becomes active and when the user asks for a refresh, never on a
|
|
5
5
|
* timer; the server owns which bonus is unnotified and what its copy says.
|
|
6
6
|
*
|
|
7
|
-
* An order is acknowledged once its card reports a presented frame: the card has
|
|
7
|
+
* An order is acknowledged once its foreground card reports a presented frame: the card has
|
|
8
8
|
* a position, the document is visible, and it painted one frame. The card measures
|
|
9
9
|
* no cover, so a card painted under the open Settings overlay reports like any
|
|
10
10
|
* other, and closing the card counts as a display too.
|
|
@@ -20,11 +20,13 @@
|
|
|
20
20
|
import type { AccountBonusBatch, AccountBonusOrderId, AccountUserId } from '@deepseek-ai/dsh-deepseek-account/types';
|
|
21
21
|
/** Notice eligible for display; the message is server-authored for the active locale. */
|
|
22
22
|
export interface BonusNotice {
|
|
23
|
+
/** Server-localized plain-text title; absent responses use the localized bonus title. */
|
|
24
|
+
readonly title?: string;
|
|
23
25
|
/** Server order identity. */
|
|
24
26
|
readonly orderId: AccountBonusOrderId;
|
|
25
27
|
/** Server-localized plain text, including any award amount or expiration. */
|
|
26
28
|
readonly message: string;
|
|
27
|
-
/** Server expiration, re-checked at display time
|
|
29
|
+
/** Server expiration, re-checked at display time; an empty string means no expiration. */
|
|
28
30
|
readonly expiresAt: string;
|
|
29
31
|
}
|
|
30
32
|
/** Deployment-varying acknowledgement retry timings. */
|
|
@@ -45,8 +47,8 @@ export interface BonusNoticeControllerOptions extends BonusNoticeTiming {
|
|
|
45
47
|
* @returns false when the account changed or signed out; a protocol failure rejects.
|
|
46
48
|
*/
|
|
47
49
|
acknowledge: (accountId: AccountUserId, orderId: AccountBonusOrderId) => Promise<boolean>;
|
|
48
|
-
/** @param
|
|
49
|
-
publish: (
|
|
50
|
+
/** @param notices - notices in front-to-back order; empty when none are shown. */
|
|
51
|
+
publish: (notices: readonly BonusNotice[]) => void;
|
|
50
52
|
}
|
|
51
53
|
/** Commands the account plugin issues to the bonus notice lifecycle. */
|
|
52
54
|
export interface BonusNoticeController {
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Close a card and animate surviving siblings from their currently displayed rectangles.
|
|
3
|
+
* @param card - mounted foreground card whose direct parent owns the stack.
|
|
4
|
+
* @param dismiss - synchronous notification-store update for the close gesture.
|
|
5
|
+
*/
|
|
6
|
+
export declare function dismissNotice(card: HTMLElement, dismiss: () => void): void;
|
|
7
|
+
//# sourceMappingURL=notice-transition.d.ts.map
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deepseek-ai/dsh-client-ui-settings-account",
|
|
3
3
|
"description": "Manage DeepSeek login and open Platform billing pages",
|
|
4
|
-
"version": "0.2.1-alpha.
|
|
4
|
+
"version": "0.2.1-alpha.5",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
7
7
|
},
|
|
@@ -45,27 +45,27 @@
|
|
|
45
45
|
},
|
|
46
46
|
"devDependencies": {
|
|
47
47
|
"@deepseek-ai/cordis": "~4.0.5-alpha.2",
|
|
48
|
-
"@deepseek-ai/dsh-api-remotes": "0.2.1-alpha.
|
|
49
|
-
"@deepseek-ai/dsh-client-locale": "0.2.1-alpha.
|
|
50
|
-
"@deepseek-ai/dsh-client-store": "0.2.1-alpha.
|
|
51
|
-
"@deepseek-ai/dsh-client-test-runtime": "0.2.1-alpha.
|
|
52
|
-
"@deepseek-ai/dsh-client-ui-chat": "0.2.1-alpha.
|
|
53
|
-
"@deepseek-ai/dsh-client-ui-layout": "0.2.1-alpha.
|
|
54
|
-
"@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.
|
|
55
|
-
"@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.
|
|
56
|
-
"@deepseek-ai/dsh-client-ui-settings": "0.2.1-alpha.
|
|
57
|
-
"@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.
|
|
58
|
-
"@deepseek-ai/dsh-client-ui-theme": "0.2.1-alpha.
|
|
59
|
-
"@deepseek-ai/dsh-deepseek-account": "0.2.1-alpha.
|
|
60
|
-
"@deepseek-ai/dsh-settings": "0.2.1-alpha.
|
|
48
|
+
"@deepseek-ai/dsh-api-remotes": "0.2.1-alpha.5",
|
|
49
|
+
"@deepseek-ai/dsh-client-locale": "0.2.1-alpha.5",
|
|
50
|
+
"@deepseek-ai/dsh-client-store": "0.2.1-alpha.5",
|
|
51
|
+
"@deepseek-ai/dsh-client-test-runtime": "0.2.1-alpha.5",
|
|
52
|
+
"@deepseek-ai/dsh-client-ui-chat": "0.2.1-alpha.5",
|
|
53
|
+
"@deepseek-ai/dsh-client-ui-layout": "0.2.1-alpha.5",
|
|
54
|
+
"@deepseek-ai/dsh-client-ui-primitives": "0.2.1-alpha.5",
|
|
55
|
+
"@deepseek-ai/dsh-client-ui-renderer": "0.2.1-alpha.5",
|
|
56
|
+
"@deepseek-ai/dsh-client-ui-settings": "0.2.1-alpha.5",
|
|
57
|
+
"@deepseek-ai/dsh-client-ui-slots": "0.2.1-alpha.5",
|
|
58
|
+
"@deepseek-ai/dsh-client-ui-theme": "0.2.1-alpha.5",
|
|
59
|
+
"@deepseek-ai/dsh-deepseek-account": "0.2.1-alpha.5",
|
|
60
|
+
"@deepseek-ai/dsh-settings": "0.2.1-alpha.5",
|
|
61
61
|
"@testing-library/react": "^16.3.3",
|
|
62
62
|
"@types/big.js": "^6.2.2",
|
|
63
63
|
"react": "^18.2.0",
|
|
64
64
|
"react-dom": "^18.2.0",
|
|
65
|
-
"@deepseek-ai/dsh-client-ui-settings-models": "0.2.1-alpha.
|
|
66
|
-
"@deepseek-ai/dsh-host-webserver": "0.2.1-alpha.
|
|
65
|
+
"@deepseek-ai/dsh-client-ui-settings-models": "0.2.1-alpha.5",
|
|
66
|
+
"@deepseek-ai/dsh-host-webserver": "0.2.1-alpha.5",
|
|
67
67
|
"big.js": "^7.0.1",
|
|
68
|
-
"@deepseek-ai/dsh-client-product-analytics": "0.2.1-alpha.
|
|
68
|
+
"@deepseek-ai/dsh-client-product-analytics": "0.2.1-alpha.5"
|
|
69
69
|
},
|
|
70
70
|
"files": [
|
|
71
71
|
"locale/*.json",
|