dsh-vidi 0.2.2 → 0.3.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/lib/client.js +90 -13
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -33858,6 +33858,43 @@ const Player = (0, react.forwardRef)(function Player(props, ref) {
|
|
|
33858
33858
|
});
|
|
33859
33859
|
});
|
|
33860
33860
|
|
|
33861
|
+
// src/client/extensions.ts
|
|
33862
|
+
function registry() {
|
|
33863
|
+
let items = [];
|
|
33864
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
33865
|
+
const emit = () => {
|
|
33866
|
+
for (const l of listeners) l();
|
|
33867
|
+
};
|
|
33868
|
+
return {
|
|
33869
|
+
get: () => items,
|
|
33870
|
+
subscribe(l) {
|
|
33871
|
+
listeners.add(l);
|
|
33872
|
+
return () => {
|
|
33873
|
+
listeners.delete(l);
|
|
33874
|
+
};
|
|
33875
|
+
},
|
|
33876
|
+
/** Add one; returns the function that removes it. */
|
|
33877
|
+
add(item) {
|
|
33878
|
+
items = [...items.filter((x) => x.id !== item.id), item].sort((a, b) => (a.order ?? 50) - (b.order ?? 50));
|
|
33879
|
+
emit();
|
|
33880
|
+
return () => {
|
|
33881
|
+
items = items.filter((x) => x !== item);
|
|
33882
|
+
emit();
|
|
33883
|
+
};
|
|
33884
|
+
}
|
|
33885
|
+
};
|
|
33886
|
+
}
|
|
33887
|
+
/**
|
|
33888
|
+
* Extension points of the video page, for companion plugins (inject
|
|
33889
|
+
* 'vidiUi'): extra tabs under the player and extra player menus. The page
|
|
33890
|
+
* itself stays in this package; companions only add.
|
|
33891
|
+
*/
|
|
33892
|
+
const vidiUi = {
|
|
33893
|
+
version: 1,
|
|
33894
|
+
panels: registry(),
|
|
33895
|
+
playerMenus: registry()
|
|
33896
|
+
};
|
|
33897
|
+
|
|
33861
33898
|
// src/client/RestreamPanel.tsx
|
|
33862
33899
|
/** Platforms, in the order people in China most often push to; YouTube and Twitch have one fixed ingest address. */
|
|
33863
33900
|
const PLATFORMS = [
|
|
@@ -35073,24 +35110,45 @@ function LiveView(props) {
|
|
|
35073
35110
|
})] });
|
|
35074
35111
|
/** On the video page the tools share the tab row, leaving the height to the lines. */
|
|
35075
35112
|
const inline = pageMode && tab === "transcript" && !!job;
|
|
35113
|
+
const extPanels = (0, react.useSyncExternalStore)(vidiUi.panels.subscribe, vidiUi.panels.get);
|
|
35114
|
+
const extMenus = (0, react.useSyncExternalStore)(vidiUi.playerMenus.subscribe, vidiUi.playerMenus.get);
|
|
35115
|
+
const view = job ? {
|
|
35116
|
+
job,
|
|
35117
|
+
cues,
|
|
35118
|
+
sessionId,
|
|
35119
|
+
now,
|
|
35120
|
+
seek: (s) => player.current?.seek(s),
|
|
35121
|
+
style: subStyle,
|
|
35122
|
+
lines: shownLines,
|
|
35123
|
+
ui
|
|
35124
|
+
} : void 0;
|
|
35076
35125
|
/** Subtitle lines and glossary: under the player on the video page, beside it in a conversation. */
|
|
35077
35126
|
const transcriptBox = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
35078
35127
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
35079
35128
|
className: "dshl-sidetabs",
|
|
35080
35129
|
role: "tablist",
|
|
35081
|
-
children: [
|
|
35082
|
-
|
|
35083
|
-
|
|
35084
|
-
|
|
35085
|
-
|
|
35086
|
-
|
|
35087
|
-
|
|
35088
|
-
|
|
35089
|
-
|
|
35090
|
-
|
|
35091
|
-
|
|
35092
|
-
|
|
35093
|
-
|
|
35130
|
+
children: [
|
|
35131
|
+
["transcript", "glossary"].map((k) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
35132
|
+
role: "tab",
|
|
35133
|
+
className: tab === k ? "on" : "",
|
|
35134
|
+
onClick: () => setTab(k),
|
|
35135
|
+
children: t(`tab.${k}`)
|
|
35136
|
+
}, k)),
|
|
35137
|
+
job && extPanels.map((p) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
35138
|
+
role: "tab",
|
|
35139
|
+
className: tab === p.id ? "on" : "",
|
|
35140
|
+
onClick: () => setTab(p.id),
|
|
35141
|
+
children: p.label(ui)
|
|
35142
|
+
}, p.id)),
|
|
35143
|
+
inline && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
35144
|
+
className: "dshl-tools inline",
|
|
35145
|
+
children: [
|
|
35146
|
+
trMode === "lines" && trSearch,
|
|
35147
|
+
trSeg,
|
|
35148
|
+
trAction
|
|
35149
|
+
]
|
|
35150
|
+
})
|
|
35151
|
+
]
|
|
35094
35152
|
}),
|
|
35095
35153
|
!job && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
35096
35154
|
className: "dshl-panel dshl-muted",
|
|
@@ -35172,6 +35230,10 @@ function LiveView(props) {
|
|
|
35172
35230
|
})
|
|
35173
35231
|
]
|
|
35174
35232
|
}),
|
|
35233
|
+
job && view && extPanels.filter((p) => p.id === tab).map((p) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
35234
|
+
className: "dshl-panel dshl-ext",
|
|
35235
|
+
children: p.render(view)
|
|
35236
|
+
}, p.id)),
|
|
35175
35237
|
tab === "glossary" && job && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GlossaryPanel, {
|
|
35176
35238
|
jobId: job.id,
|
|
35177
35239
|
terms,
|
|
@@ -35408,6 +35470,12 @@ function LiveView(props) {
|
|
|
35408
35470
|
t
|
|
35409
35471
|
})
|
|
35410
35472
|
},
|
|
35473
|
+
...extMenus.map((m) => ({
|
|
35474
|
+
id: `ext:${m.id}`,
|
|
35475
|
+
icon: m.icon,
|
|
35476
|
+
title: m.title(ui),
|
|
35477
|
+
content: view ? m.render(view, () => {}) : null
|
|
35478
|
+
})),
|
|
35411
35479
|
{
|
|
35412
35480
|
id: "download",
|
|
35413
35481
|
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon.download, {}),
|
|
@@ -36761,6 +36829,14 @@ const CSS = `
|
|
|
36761
36829
|
.dshl-toast { position: fixed; left: 50%; bottom: 28px; z-index: 2147483001; max-width: min(560px, calc(100vw - 32px)); padding: 10px 16px; border-radius: 10px;
|
|
36762
36830
|
background: rgba(28,28,31,.95); color: #f2f2f3; font: 13.5px/1.5 system-ui, -apple-system, sans-serif; box-shadow: 0 10px 30px rgba(0,0,0,.3); transform: translateX(-50%); pointer-events: none; }
|
|
36763
36831
|
.dshl-pagewrap { position: absolute; inset: 0; z-index: 1; pointer-events: auto; background: var(--dsw-alias-bg-base, #fff); }
|
|
36832
|
+
/* Desktop app: the page covers the whole window. Windows: start under the title bar. macOS: the
|
|
36833
|
+
traffic lights sit over the top-left, so the top bar leaves them room, lines its controls up
|
|
36834
|
+
with them, and its empty space moves the window like the app's own top strip. Full screen and
|
|
36835
|
+
the web page need none of this. */
|
|
36836
|
+
.dshl-pagewrap { top: var(--dsh-frame-chrome-top, 0px); }
|
|
36837
|
+
html[data-platform='darwin']:not([data-fullscreen]) .dshl.page .dshl-top { padding: 4px 16px 8px 84px; -webkit-app-region: drag; app-region: drag; }
|
|
36838
|
+
html[data-platform='darwin']:not([data-fullscreen]) .dshl.page .dshl-top :is(button, input, label, a, select, .dshl-pick) { -webkit-app-region: no-drag; app-region: no-drag; }
|
|
36839
|
+
@media (max-width: 600px) { html[data-platform='darwin']:not([data-fullscreen]) .dshl.page .dshl-top { padding-left: 80px; } }
|
|
36764
36840
|
.dshl.page { display: flex; flex-direction: column; height: 100%; overflow: hidden; }
|
|
36765
36841
|
.dshl.page .dshl-main { flex: 1; min-height: 0; grid-template-columns: minmax(0, 1fr) clamp(320px, 30vw, 420px); align-items: stretch; padding-bottom: 16px; }
|
|
36766
36842
|
/* Video page: player on top, then the status row, then subtitles/glossary filling what is left; chat on the right. */
|
|
@@ -37424,6 +37500,7 @@ function apply(ctx) {
|
|
|
37424
37500
|
zh,
|
|
37425
37501
|
en
|
|
37426
37502
|
}), "dsh-vidi: dictionaries");
|
|
37503
|
+
ctx.effect(() => ctx.provide("vidiUi", vidiUi), "dsh-vidi: page extensions");
|
|
37427
37504
|
const t = ctx.locale.bind(NS);
|
|
37428
37505
|
const extra = {};
|
|
37429
37506
|
ctx.inject(["uiWorkspace"], (c) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-vidi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
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",
|