@morehao/dsh-github-trending 0.8.12 → 0.8.13

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.
Files changed (2) hide show
  1. package/client.js +100 -39
  2. package/package.json +1 -1
package/client.js CHANGED
@@ -278,6 +278,7 @@ var DICT = {
278
278
  "shell.update.failed": "更新失败",
279
279
  "shell.update.checkFailed": "检查失败,可稍后重试",
280
280
  "shell.update.available": "有新版本 v{latest}",
281
+ "shell.update.badgeTitle": "最新版本 v{version}",
281
282
  "shell.update.latest": "已是最新 v{version}",
282
283
  "shell.update.apply": "更新到 v{version}",
283
284
  "shell.update.confirmHint": "更新会重装插件,需重启 DSH 生效",
@@ -829,6 +830,7 @@ var DICT = {
829
830
  "shell.update.failed": "Update failed",
830
831
  "shell.update.checkFailed": "Check failed, try again later",
831
832
  "shell.update.available": "v{latest} available",
833
+ "shell.update.badgeTitle": "Latest version v{version}",
832
834
  "shell.update.latest": "Up to date · v{version}",
833
835
  "shell.update.apply": "Update to v{version}",
834
836
  "shell.update.confirmHint": "Reinstalls the plugin; restart DSH to apply",
@@ -1341,15 +1343,34 @@ var CSS = `
1341
1343
  .dshgt-id-sep{width:1px;height:16px;background:var(--gt-border);flex:none;}
1342
1344
  .dshgt-id-pkg{appearance:none;border:0;background:none;padding:2px 4px;border-radius:5px;color:var(--gt-muted);cursor:pointer;font-size:12px;max-width:min(44vw,360px);min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:0 1 auto;}
1343
1345
  .dshgt-id-pkg:hover{color:var(--gt-fg);background:color-mix(in srgb,var(--gt-fg) 5%,var(--gt-bg));}
1344
- .dshgt-idbar-right{margin-left:auto;display:flex;align-items:center;gap:10px;flex:none;min-width:0;}
1346
+ .dshgt-idbar-right{margin-left:auto;position:relative;display:flex;align-items:center;gap:10px;flex:none;min-width:0;}
1345
1347
  .dshgt-id-gh{display:inline-flex;align-items:center;justify-content:center;width:26px;height:26px;border-radius:6px;color:var(--gt-muted);border:1px solid transparent;flex:none;}
1346
1348
  .dshgt-id-gh:hover{color:var(--gt-fg);background:color-mix(in srgb,var(--gt-fg) 6%,var(--gt-bg));border-color:var(--gt-border);}
1347
- .dshgt-id-upd{display:flex;align-items:center;gap:10px;min-width:0;}
1348
- .dshgt-id-status{font-size:12px;color:var(--gt-muted);white-space:nowrap;display:inline-flex;align-items:center;gap:6px;min-width:0;overflow:hidden;text-overflow:ellipsis;}
1349
- .dshgt-id-status.ok{color:var(--gt-ok);}
1350
- .dshgt-id-status.new{color:var(--gt-warn);}
1351
- .dshgt-id-status.err{color:var(--gt-err);}
1352
- .dshgt-id-actions{display:flex;align-items:center;gap:8px;flex:none;}
1349
+ /* 更新入口:版本徽标 + 纯图标刷新,作为一个整体;与 GitHub 图标同形制 */
1350
+ .dshgt-upd-unit{display:inline-flex;align-items:center;gap:4px;flex:none;}
1351
+ /* 版本徽标:仅「有新版本」时出现,透明底细描边,高度对齐图标按钮中线 */
1352
+ .dshgt-ver-badge{box-sizing:border-box;display:inline-flex;align-items:center;justify-content:center;height:22px;padding:0 8px;border-radius:999px;
1353
+ border:1px solid color-mix(in srgb,var(--gt-warn) 42%,transparent);background:transparent;color:var(--gt-warn);
1354
+ font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;line-height:1;font-variant-numeric:tabular-nums;white-space:nowrap;cursor:pointer;
1355
+ transition:background .12s ease,border-color .12s ease;}
1356
+ .dshgt-ver-badge:hover{background:color-mix(in srgb,var(--gt-warn) 12%,transparent);border-color:color-mix(in srgb,var(--gt-warn) 60%,transparent);}
1357
+ .dshgt-ver-badge:focus-visible{outline:2px solid var(--gt-accent);outline-offset:1px;}
1358
+ /* 纯图标刷新:状态靠图标颜色 + 角标 + 旋转表达,文案走 title(tooltip) */
1359
+ .dshgt-refresh{position:relative;}
1360
+ .dshgt-refresh svg{display:block;transition:color .12s ease;}
1361
+ .dshgt-refresh[data-state="available"]{color:var(--gt-warn);}
1362
+ .dshgt-refresh[data-state="available"]::after{content:"";position:absolute;top:3px;right:3px;width:6px;height:6px;border-radius:50%;background:var(--gt-warn);box-shadow:0 0 0 1.5px var(--gt-bg);}
1363
+ .dshgt-refresh[data-state="checking"]{color:var(--gt-muted);cursor:default;}
1364
+ .dshgt-refresh[data-state="checking"] svg{animation:dshgt-refresh-spin .9s linear infinite;}
1365
+ .dshgt-refresh[data-state="error"]{color:var(--gt-err);}
1366
+ .dshgt-refresh[data-state="ok-flash"]{color:var(--gt-ok);}
1367
+ @keyframes dshgt-refresh-spin{to{transform:rotate(360deg);}}
1368
+ /* 确认气泡:贴刷新图标右下方弹出 */
1369
+ .dshgt-confirm-pop{position:absolute;top:calc(100% + 8px);right:0;z-index:30;box-sizing:border-box;min-width:210px;max-width:280px;
1370
+ display:flex;flex-direction:column;gap:10px;padding:12px;border-radius:12px;background:var(--gt-card);border:1px solid var(--gt-border);
1371
+ box-shadow:0 12px 32px rgba(0,0,0,.28);}
1372
+ .dshgt-confirm-title{font-size:12.5px;color:var(--gt-fg);line-height:1.45;}
1373
+ .dshgt-confirm-actions{display:flex;gap:8px;justify-content:flex-end;}
1353
1374
 
1354
1375
  /* ——— 横向 tab(第二行)+ 右侧状态 ——— */
1355
1376
  .dshgt-tabsbar{display:flex;align-items:stretch;gap:12px;height:46px;padding:0 var(--dshgt-inset);border-bottom:1px solid var(--gt-border);flex:none;background:var(--gt-bg);min-width:0;}
@@ -5881,48 +5902,54 @@ function githubIcon() {
5881
5902
  d: "M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.01 8.01 0 0 0 16 8c0-4.42-3.58-8-8-8Z"
5882
5903
  }));
5883
5904
  }
5905
+ function refreshIcon() {
5906
+ return h(
5907
+ "svg",
5908
+ { width: 15, height: 15, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: 2, strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true" },
5909
+ h("path", { d: "M20 12a8 8 0 1 1-2.34-5.66" }),
5910
+ h("path", { d: "M20 4v5h-5" })
5911
+ );
5912
+ }
5884
5913
  function IdentityBar(props) {
5885
5914
  const { t, plugin } = props;
5886
5915
  const [confirming, setConfirming] = import_react.default.useState(false);
5887
5916
  const [updateState, controller] = usePluginUpdate();
5888
5917
  const view = updateState.view;
5889
5918
  const status = updateState.status;
5890
- import_react.default.useEffect(() => {
5891
- if (status === "applying" || status === "restart-required" || status === "applied") setConfirming(false);
5892
- }, [status]);
5893
5919
  const busy = status === "checking" || status === "applying";
5894
5920
  const settled = status === "restart-required" || status === "applied";
5895
5921
  const latestVersion = view === null ? "" : view.latestVersion ?? "";
5896
5922
  const updateAvailable = view !== null && view.updateAvailable;
5897
- const actionable = updateAvailable && view !== null && view.canApply && !settled && !busy;
5923
+ const actionable = updateAvailable && view !== null && view.canApply && !busy && !settled;
5898
5924
  const currentVersion = view === null ? plugin.version : view.currentVersion ?? plugin.version;
5899
- function statusLine() {
5900
- if (status === "checking" || view === null) return { text: t("shell.update.checking"), kind: "muted" };
5901
- if (status === "applying") return { text: t("shell.update.applying", { version: latestVersion }), kind: "muted" };
5902
- if (status === "restart-required" || status === "applied") return { text: t("shell.update.done", { version: latestVersion }), kind: "ok" };
5903
- if (status === "failed") return { text: updateState.error?.code === "CHECK_FAILED" ? t("shell.update.checkFailed") : t("shell.update.failed"), kind: "err" };
5904
- if (view.checkFailed) return { text: t("shell.update.checkFailed"), kind: "err" };
5905
- if (view.updateAvailable) return { text: t("shell.update.available", { latest: view.latestVersion ?? "" }), kind: "new" };
5906
- return { text: t("shell.update.latest", { version: currentVersion }), kind: "ok" };
5925
+ import_react.default.useEffect(() => {
5926
+ if (!updateAvailable || busy || settled) setConfirming(false);
5927
+ }, [updateAvailable, busy, settled]);
5928
+ function stateAndTip() {
5929
+ if (status === "checking" || view === null) return { state: "checking", tip: t("shell.update.checking") };
5930
+ if (status === "applying") return { state: "checking", tip: t("shell.update.applying", { version: latestVersion }) };
5931
+ if (status === "restart-required" || status === "applied") return { state: "ok-flash", tip: t("shell.update.done", { version: latestVersion }) };
5932
+ if (status === "failed") return { state: "error", tip: updateState.error?.code === "CHECK_FAILED" ? t("shell.update.checkFailed") : t("shell.update.failed") };
5933
+ if (view.checkFailed) return { state: "error", tip: t("shell.update.checkFailed") };
5934
+ if (view.updateAvailable) return { state: "available", tip: t("shell.update.available", { latest: latestVersion }) };
5935
+ return { state: "latest", tip: t("shell.update.latest", { version: currentVersion }) };
5907
5936
  }
5908
- function action() {
5909
- if (status === "applying") return h(Btn, { small: true, disabled: true }, t("shell.update.applyingShort"));
5937
+ const st = stateAndTip();
5938
+ function onRefreshClick() {
5939
+ if (busy) return;
5910
5940
  if (actionable) {
5911
- if (confirming) {
5912
- return [
5913
- h(Btn, { key: "yes", small: true, variant: "danger", onClick: () => {
5914
- setConfirming(false);
5915
- writePendingUpdate(currentVersion, latestVersion);
5916
- void controller.apply();
5917
- } }, t("shell.update.confirmYes")),
5918
- h(Btn, { key: "no", small: true, onClick: () => setConfirming(false) }, t("shell.update.cancel"))
5919
- ];
5920
- }
5921
- return h(Btn, { small: true, variant: "primary", onClick: () => setConfirming(true) }, t("shell.update.apply", { version: latestVersion }));
5941
+ setConfirming((v) => !v);
5942
+ return;
5922
5943
  }
5923
- return h(Btn, { small: true, disabled: busy, onClick: () => void controller.check({ fresh: true }) }, t("shell.update.check"));
5944
+ void controller.check({ fresh: true });
5924
5945
  }
5925
- const line = statusLine();
5946
+ function onConfirmUpdate() {
5947
+ setConfirming(false);
5948
+ writePendingUpdate(currentVersion, latestVersion);
5949
+ void controller.apply();
5950
+ }
5951
+ const showBadge = Boolean(updateAvailable && view?.canApply && !busy && !settled);
5952
+ const confirmOpen = confirming && actionable;
5926
5953
  return h(
5927
5954
  "div",
5928
5955
  { className: "dshgt-idbar" },
@@ -5942,11 +5969,45 @@ function IdentityBar(props) {
5942
5969
  "div",
5943
5970
  { className: "dshgt-idbar-right" },
5944
5971
  h(
5945
- "span",
5946
- { className: "dshgt-id-upd" },
5947
- confirming ? h("span", { className: "dshgt-id-status new" }, t("shell.update.confirmHint")) : h("span", { className: `dshgt-id-status ${line.kind}` }, line.text),
5948
- h("span", { className: "dshgt-id-actions" }, action())
5949
- )
5972
+ "div",
5973
+ { className: "dshgt-upd-unit" },
5974
+ showBadge ? h(
5975
+ "button",
5976
+ {
5977
+ type: "button",
5978
+ className: "dshgt-ver-badge",
5979
+ title: t("shell.update.badgeTitle", { version: latestVersion }),
5980
+ "aria-label": t("shell.update.badgeTitle", { version: latestVersion }),
5981
+ onClick: () => setConfirming((v) => !v)
5982
+ },
5983
+ `v${latestVersion}`
5984
+ ) : null,
5985
+ h(
5986
+ "button",
5987
+ {
5988
+ type: "button",
5989
+ className: "dshgt-id-gh dshgt-refresh",
5990
+ "data-state": st.state,
5991
+ disabled: busy,
5992
+ title: st.tip,
5993
+ "aria-label": st.tip,
5994
+ "aria-expanded": confirmOpen ? "true" : void 0,
5995
+ onClick: onRefreshClick
5996
+ },
5997
+ refreshIcon()
5998
+ )
5999
+ ),
6000
+ confirmOpen ? h(
6001
+ "div",
6002
+ { className: "dshgt-confirm-pop", role: "dialog", "aria-label": t("shell.update.confirmHint") },
6003
+ h("div", { className: "dshgt-confirm-title" }, t("shell.update.confirmHint")),
6004
+ h(
6005
+ "div",
6006
+ { className: "dshgt-confirm-actions" },
6007
+ h(Btn, { small: true, onClick: () => setConfirming(false) }, t("shell.update.cancel")),
6008
+ h(Btn, { small: true, variant: "primary", onClick: onConfirmUpdate }, t("shell.update.confirmYes"))
6009
+ )
6010
+ ) : null
5950
6011
  )
5951
6012
  );
5952
6013
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@morehao/dsh-github-trending",
3
- "version": "0.8.12",
3
+ "version": "0.8.13",
4
4
  "description": "GitHub 趋势日报的 DeepSeek Harness 插件:按日 / 周 / 月周期定时 spawn 本地 trendradar 核心,抓取 Trending、生成中文简介与周期总结,并可选把订阅仓库的新 Release 合成中文摘要,一起提交到你的仓库、自动开 PR 合并;内置概览 / 榜单 / 运行记录 / 订阅 / 设置工作台。",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",