dsh-vidi 0.7.9 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/client.js +86 -3
- package/lib/index.mjs +57 -8
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -34794,6 +34794,46 @@ function Settings(props) {
|
|
|
34794
34794
|
const { engine, onEngine, mode, onMode, spoken, onSpoken, langOptions, login, onLogin, browsers, providers, shared, name, onKey, disabled, open, onOpen, update, onCheckUpdate, t } = props;
|
|
34795
34795
|
const [checking, setChecking] = (0, react.useState)(false);
|
|
34796
34796
|
const [checked, setChecked] = (0, react.useState)(false);
|
|
34797
|
+
const [installing, setInstalling] = (0, react.useState)(false);
|
|
34798
|
+
const [installed, setInstalled] = (0, react.useState)(null);
|
|
34799
|
+
const installUpdate = async () => {
|
|
34800
|
+
setInstalling(true);
|
|
34801
|
+
setInstalled(null);
|
|
34802
|
+
const target = update?.latest;
|
|
34803
|
+
try {
|
|
34804
|
+
const j = await (await fetch("/live/api/update", {
|
|
34805
|
+
method: "POST",
|
|
34806
|
+
headers: { "content-type": "application/json" },
|
|
34807
|
+
body: "{}"
|
|
34808
|
+
})).json();
|
|
34809
|
+
setInstalled(j);
|
|
34810
|
+
if (j.status === "applied") {
|
|
34811
|
+
try {
|
|
34812
|
+
sessionStorage.setItem("dsh-vidi.reopen", "1");
|
|
34813
|
+
} catch {}
|
|
34814
|
+
setTimeout(() => location.reload(), 800);
|
|
34815
|
+
}
|
|
34816
|
+
setInstalling(false);
|
|
34817
|
+
return;
|
|
34818
|
+
} catch {}
|
|
34819
|
+
for (let i = 0; i < 60; i++) {
|
|
34820
|
+
await new Promise((res) => setTimeout(res, 1500));
|
|
34821
|
+
try {
|
|
34822
|
+
if ((await (await fetch("/live/api/version")).json()).current === target) {
|
|
34823
|
+
try {
|
|
34824
|
+
sessionStorage.setItem("dsh-vidi.reopen", "1");
|
|
34825
|
+
} catch {}
|
|
34826
|
+
location.reload();
|
|
34827
|
+
return;
|
|
34828
|
+
}
|
|
34829
|
+
} catch {}
|
|
34830
|
+
}
|
|
34831
|
+
setInstalled({
|
|
34832
|
+
status: "failed",
|
|
34833
|
+
message: "no answer"
|
|
34834
|
+
});
|
|
34835
|
+
setInstalling(false);
|
|
34836
|
+
};
|
|
34797
34837
|
const box = (0, react.useRef)(null);
|
|
34798
34838
|
const [draft, setDraft] = (0, react.useState)("");
|
|
34799
34839
|
const [busy, setBusy] = (0, react.useState)(false);
|
|
@@ -35127,9 +35167,14 @@ function Settings(props) {
|
|
|
35127
35167
|
children: [
|
|
35128
35168
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
35129
35169
|
className: "vline",
|
|
35130
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("upd.version").replace("{v}", update.current) }), update.newer ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("
|
|
35170
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: t("upd.version").replace("{v}", update.current) }), update.newer ? update.canInstall && !installed ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
35171
|
+
className: "dshl-btn primary small",
|
|
35172
|
+
disabled: installing,
|
|
35173
|
+
onClick: () => void installUpdate(),
|
|
35174
|
+
children: installing ? t("upd.installing") : t("upd.install").replace("{v}", update.latest ?? "")
|
|
35175
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
35131
35176
|
className: "new",
|
|
35132
|
-
children: t("upd.available").replace("{v}", update.latest ?? "")
|
|
35177
|
+
children: installed?.status === "restart" ? t("upd.restart").replace("{v}", installed.version ?? "") : installed?.status === "applied" ? t("upd.applied") : t("upd.available").replace("{v}", update.latest ?? "")
|
|
35133
35178
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
35134
35179
|
className: "dshl-link",
|
|
35135
35180
|
disabled: checking,
|
|
@@ -35143,10 +35188,18 @@ function Settings(props) {
|
|
|
35143
35188
|
children: checking ? t("upd.checking") : checked && !update.error ? t("upd.latest") : t("upd.check")
|
|
35144
35189
|
})]
|
|
35145
35190
|
}),
|
|
35146
|
-
update.newer && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
35191
|
+
update.newer && !update.canInstall && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
35147
35192
|
className: "hint",
|
|
35148
35193
|
children: t("upd.how")
|
|
35149
35194
|
}),
|
|
35195
|
+
installed?.status === "restart" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
35196
|
+
className: "hint",
|
|
35197
|
+
children: t("upd.restartHow")
|
|
35198
|
+
}),
|
|
35199
|
+
installed?.status === "failed" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
35200
|
+
className: "hint",
|
|
35201
|
+
children: t("upd.installFailed").replace("{m}", installed.message ?? "")
|
|
35202
|
+
}),
|
|
35150
35203
|
checked && update.error && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
35151
35204
|
className: "hint",
|
|
35152
35205
|
children: t("upd.failed")
|
|
@@ -37227,6 +37280,12 @@ const en = {
|
|
|
37227
37280
|
"upd.latest": "Up to date",
|
|
37228
37281
|
"upd.available": "Version {v} is out",
|
|
37229
37282
|
"upd.how": "Update it from DSH’s Plugins page, then restart the app.",
|
|
37283
|
+
"upd.install": "Update to {v}",
|
|
37284
|
+
"upd.installing": "Updating…",
|
|
37285
|
+
"upd.restart": "{v} installed",
|
|
37286
|
+
"upd.restartHow": "Restart the app to use it.",
|
|
37287
|
+
"upd.applied": "Updated",
|
|
37288
|
+
"upd.installFailed": "The update did not go through ({m}). The Plugins page can update it too.",
|
|
37230
37289
|
"upd.failed": "Could not reach npm just now; it checks again tomorrow.",
|
|
37231
37290
|
"src.tip": "Where the video comes from",
|
|
37232
37291
|
"src.link": "Link",
|
|
@@ -37652,6 +37711,12 @@ const zh = {
|
|
|
37652
37711
|
"upd.latest": "已是最新",
|
|
37653
37712
|
"upd.available": "有新版本 {v}",
|
|
37654
37713
|
"upd.how": "到 DSH 的「插件」页面更新,再重启 app。",
|
|
37714
|
+
"upd.install": "更新到 {v}",
|
|
37715
|
+
"upd.installing": "正在更新…",
|
|
37716
|
+
"upd.restart": "{v} 已装好",
|
|
37717
|
+
"upd.restartHow": "重启 app 后生效。",
|
|
37718
|
+
"upd.applied": "已更新",
|
|
37719
|
+
"upd.installFailed": "这次没更新成({m}),也可以到「插件」页面更新。",
|
|
37655
37720
|
"upd.failed": "这会儿连不上 npm,明天会再查一次。",
|
|
37656
37721
|
"src.tip": "视频从哪里来",
|
|
37657
37722
|
"src.link": "链接",
|
|
@@ -38528,6 +38593,7 @@ body > .dshl-menu { z-index: 2147483002; }
|
|
|
38528
38593
|
.dshl-pop.settings .srow + .srow { border-top: 1px solid var(--line-soft); }
|
|
38529
38594
|
.dshl-pop.settings .srow.version .vline { display: flex; align-items: center; justify-content: space-between; gap: 12px; width: 100%; color: var(--faint); font-size: 12.5px; }
|
|
38530
38595
|
.dshl-pop.settings .srow.version .new { color: #e5484d; font-weight: 550; }
|
|
38596
|
+
.dshl-pop.settings .srow.version .dshl-btn.small { height: 28px; padding: 0 12px; border-radius: 7px; font-size: 12.5px; }
|
|
38531
38597
|
.dshl-pop.settings .srow > .dshl-select, .dshl-pop.settings .srow > .dshl-seg { width: 168px; }
|
|
38532
38598
|
.dshl-pop.settings .srow > .dshl-seg button { flex: 1; padding: 0 6px; }
|
|
38533
38599
|
.dshl .srow.col { display: grid; justify-content: stretch; gap: 8px; padding: 10px 0; }
|
|
@@ -39005,6 +39071,23 @@ function apply(ctx) {
|
|
|
39005
39071
|
subscribe: (fn) => c.layout.panelInfo.subscribe(fn)
|
|
39006
39072
|
}
|
|
39007
39073
|
}), "dsh-vidi: main panel host");
|
|
39074
|
+
c.effect(() => {
|
|
39075
|
+
let back = false;
|
|
39076
|
+
try {
|
|
39077
|
+
back = sessionStorage.getItem("dsh-vidi.reopen") === "1";
|
|
39078
|
+
sessionStorage.removeItem("dsh-vidi.reopen");
|
|
39079
|
+
} catch {}
|
|
39080
|
+
if (!back) return () => {};
|
|
39081
|
+
let tries = 0;
|
|
39082
|
+
const timer = setInterval(() => {
|
|
39083
|
+
const s = sessions(), cur = s?.current();
|
|
39084
|
+
if (s && cur) {
|
|
39085
|
+
clearInterval(timer);
|
|
39086
|
+
openPage(s, { sessionId: cur });
|
|
39087
|
+
} else if (++tries > 40) clearInterval(timer);
|
|
39088
|
+
}, 250);
|
|
39089
|
+
return () => clearInterval(timer);
|
|
39090
|
+
}, "dsh-vidi: reopen after update");
|
|
39008
39091
|
c.slots.inject("main", () => c.slots.register({
|
|
39009
39092
|
name: "main",
|
|
39010
39093
|
key: PANEL_ID,
|
package/lib/index.mjs
CHANGED
|
@@ -5780,6 +5780,9 @@ function metered(llm, meter) {
|
|
|
5780
5780
|
}
|
|
5781
5781
|
// src/updates.ts
|
|
5782
5782
|
const DAY = 864e5;
|
|
5783
|
+
/** pnpm holds back releases younger than a day: offer only versions it will install. */
|
|
5784
|
+
const MIN_AGE = process.env.VIDI_UPDATE_MIN_AGE_HOURS !== void 0 ? Number(process.env.VIDI_UPDATE_MIN_AGE_HOURS) * 36e5 : DAY;
|
|
5785
|
+
const NAME = "dsh-vidi";
|
|
5783
5786
|
/** a > b for plain x.y.z versions (pre-releases count as older than the release). */
|
|
5784
5787
|
function greater(a, b) {
|
|
5785
5788
|
const parse = (v) => {
|
|
@@ -5793,38 +5796,76 @@ function greater(a, b) {
|
|
|
5793
5796
|
for (let i = 0; i < 3; i++) if ((x.n[i] ?? 0) !== (y.n[i] ?? 0)) return (x.n[i] ?? 0) > (y.n[i] ?? 0);
|
|
5794
5797
|
return !x.pre && !!y.pre;
|
|
5795
5798
|
}
|
|
5796
|
-
function updateChecker(log) {
|
|
5799
|
+
function updateChecker(log, manager) {
|
|
5797
5800
|
let current = "0.0.0";
|
|
5798
5801
|
try {
|
|
5799
5802
|
current = String(JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version);
|
|
5800
5803
|
} catch {}
|
|
5801
5804
|
let latest, checkedAt, error;
|
|
5805
|
+
let canInstall = false;
|
|
5802
5806
|
let running;
|
|
5803
5807
|
const state = () => ({
|
|
5804
5808
|
current,
|
|
5805
5809
|
latest,
|
|
5806
5810
|
newer: !!latest && greater(latest, current),
|
|
5811
|
+
canInstall,
|
|
5807
5812
|
checkedAt,
|
|
5808
5813
|
error
|
|
5809
5814
|
});
|
|
5810
5815
|
const check = () => running ??= (async () => {
|
|
5811
5816
|
try {
|
|
5812
|
-
const r = await fetch(
|
|
5813
|
-
signal: AbortSignal.timeout(
|
|
5817
|
+
const r = await fetch(`https://registry.npmjs.org/${NAME}`, {
|
|
5818
|
+
signal: AbortSignal.timeout(15e3),
|
|
5814
5819
|
headers: { accept: "application/json" }
|
|
5815
5820
|
});
|
|
5816
5821
|
if (!r.ok) throw new Error(`registry ${r.status}`);
|
|
5817
|
-
|
|
5822
|
+
const doc = await r.json();
|
|
5823
|
+
latest = Object.keys(doc.versions ?? {}).filter((v) => !v.includes("-") && Date.now() - Date.parse(doc.time?.[v] ?? "") >= MIN_AGE).reduce((best, v) => !best || greater(v, best) ? v : best, void 0);
|
|
5818
5824
|
error = void 0;
|
|
5819
5825
|
if (latest && greater(latest, current)) log(`update: ${latest} available (running ${current})`);
|
|
5820
5826
|
} catch (err) {
|
|
5821
5827
|
error = err.message;
|
|
5822
|
-
} finally {
|
|
5823
|
-
checkedAt = Date.now();
|
|
5824
|
-
running = void 0;
|
|
5825
5828
|
}
|
|
5829
|
+
try {
|
|
5830
|
+
canInstall = !!(await manager()?.listBundles())?.find((b) => b.name === NAME)?.updatable;
|
|
5831
|
+
} catch {
|
|
5832
|
+
canInstall = false;
|
|
5833
|
+
}
|
|
5834
|
+
checkedAt = Date.now();
|
|
5835
|
+
running = void 0;
|
|
5826
5836
|
return state();
|
|
5827
5837
|
})();
|
|
5838
|
+
/** Install the newest version through DSH's plugin manager. */
|
|
5839
|
+
const install = async () => {
|
|
5840
|
+
const pm = manager();
|
|
5841
|
+
if (!pm || !latest || !greater(latest, current)) return {
|
|
5842
|
+
status: "failed",
|
|
5843
|
+
message: "nothing to install"
|
|
5844
|
+
};
|
|
5845
|
+
log(`update: installing ${latest}`);
|
|
5846
|
+
try {
|
|
5847
|
+
const out = await pm.updateBundle(NAME, latest, { requestId: `vidi-update-${Date.now()}` });
|
|
5848
|
+
const app = out.result?.application;
|
|
5849
|
+
if (app === "restart-required") return {
|
|
5850
|
+
status: "restart",
|
|
5851
|
+
version: latest
|
|
5852
|
+
};
|
|
5853
|
+
if (app === "applied" || app === "unchanged") return {
|
|
5854
|
+
status: "applied",
|
|
5855
|
+
version: latest
|
|
5856
|
+
};
|
|
5857
|
+
const e = out.result?.error;
|
|
5858
|
+
return {
|
|
5859
|
+
status: "failed",
|
|
5860
|
+
message: e?.diagnostic || e?.message || e?.code || app || "failed"
|
|
5861
|
+
};
|
|
5862
|
+
} catch (err) {
|
|
5863
|
+
return {
|
|
5864
|
+
status: "failed",
|
|
5865
|
+
message: err.message
|
|
5866
|
+
};
|
|
5867
|
+
}
|
|
5868
|
+
};
|
|
5828
5869
|
check();
|
|
5829
5870
|
const timer = setInterval(() => void check(), DAY);
|
|
5830
5871
|
timer.unref?.();
|
|
@@ -5834,6 +5875,7 @@ function updateChecker(log) {
|
|
|
5834
5875
|
return state();
|
|
5835
5876
|
},
|
|
5836
5877
|
check,
|
|
5878
|
+
install,
|
|
5837
5879
|
stop: () => clearInterval(timer)
|
|
5838
5880
|
};
|
|
5839
5881
|
}
|
|
@@ -6449,6 +6491,7 @@ function apply(ctx, config) {
|
|
|
6449
6491
|
return send(res, 200, job.summary());
|
|
6450
6492
|
}
|
|
6451
6493
|
if (route === "version") return send(res, 200, req.method === "POST" ? await updates.check() : updates.state());
|
|
6494
|
+
if (route === "update" && req.method === "POST") return send(res, 200, await updates.install());
|
|
6452
6495
|
if (route === "devices") {
|
|
6453
6496
|
const devices = await listDevices();
|
|
6454
6497
|
log(`devices: ${devices.filter((d) => d.kind !== "mic").length} picture, ${devices.filter((d) => d.kind === "mic").length} microphone`);
|
|
@@ -6890,7 +6933,13 @@ function apply(ctx, config) {
|
|
|
6890
6933
|
}), "dsh-vidi: media route");
|
|
6891
6934
|
let updates;
|
|
6892
6935
|
ctx.effect(() => {
|
|
6893
|
-
updates = updateChecker(log)
|
|
6936
|
+
updates = updateChecker(log, () => {
|
|
6937
|
+
try {
|
|
6938
|
+
return ctx.get?.("pluginManager");
|
|
6939
|
+
} catch {
|
|
6940
|
+
return;
|
|
6941
|
+
}
|
|
6942
|
+
});
|
|
6894
6943
|
return () => updates.stop();
|
|
6895
6944
|
}, "dsh-vidi: update check");
|
|
6896
6945
|
ctx.effect(() => startOverlay(config.overlayPort, () => [...jobs.values()].filter((j) => j.summary().status === "running").at(-1) ?? [...jobs.values()].at(-1), (fn) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-vidi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "A video tool for DeepSeek Harness: watch live streams, videos and podcasts with real-time subtitles in any language, then clip and download",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "PolyForm-Noncommercial-1.0.0",
|