dsh-openup-lewis 1.2.5 → 1.2.6
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.md +5 -4
- package/lib/build-info.json +1 -1
- package/lib/client.js +29 -217
- package/lib/index.js +4 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
|
|
11
11
|
## 产品功能
|
|
12
12
|
|
|
13
|
-
-
|
|
13
|
+
- **完整开场**:内置「启」「数字生命」「朋克」「半面」四段视频和「莱茵生命」动画,视频按原长度、原速播放,铺满当前 Harness 窗口,保持窗口大小、位置和最大化状态。
|
|
14
14
|
- **任意键进入**:动画中按任意键或点击画面进入标题页,再操作一次进入 Harness;动画自然结束后也会停留在标题页。
|
|
15
15
|
- **三款标题封面**:远山、黑金、蓝雾,保留原有图片与文字。
|
|
16
16
|
- **自定义素材**:上传自己的视频作为开场,上传喜欢的图片作为结束封面。
|
|
17
|
-
-
|
|
17
|
+
- **声音与画面**:支持静音和音量调整;开场视频始终铺满当前窗口,可固定播放喜欢的动画,或每次随机选择。
|
|
18
18
|
- **启动检查更新**:每次重新打开 Harness 自动检查新版本,开场结束并进入应用后再提醒;可选择稍后或直接更新,无需先卸载。
|
|
19
19
|
- **雾光更新提醒**:半透明磨砂弹窗,支持自定义磨砂度与圆角,可在设置中预览。
|
|
20
20
|
- **可选快捷入口**:默认从设置进入,可自行开启头像上方的“开机动画”按钮;附魔台系列共享最多 17 个快捷入口。
|
|
@@ -42,9 +42,10 @@
|
|
|
42
42
|
| 统一品牌 | DSH LEWIS ENCHANT · 附魔台 |
|
|
43
43
|
| 功能项目 | 开机动画 |
|
|
44
44
|
| 插件名称 | dsh-openup-lewis |
|
|
45
|
-
| 当前版本 | 1.2.
|
|
45
|
+
| 当前版本 | 1.2.6 |
|
|
46
46
|
| 作者 | FerrariLewis |
|
|
47
|
-
| 适用版本 | DeepSeek Harness ≥ 0.2.1-rc.2 且 < 0.3.0
|
|
47
|
+
| 适用版本 | DeepSeek Harness ≥ 0.2.1-rc.2 且 < 0.3.0 |
|
|
48
|
+
| 窗口按钮 | 当前 Harness 桌面版尚未提供插件单独隐藏原生关闭、最大化、最小化按钮的接口。 |
|
|
48
49
|
| 安装方法 | 在 Harness → 插件 → 添加插件 → 包名或地址中,粘贴本文第一行的安装码,安装并启用后重新打开 Harness。无需 Git、npm 账号或命令行。 |
|
|
49
50
|
| 设置入口 | 设置 → 开机动画 |
|
|
50
51
|
| 视频格式 | MP4 / M4V / WebM,单个文件最大 200 MB |
|
package/lib/build-info.json
CHANGED
package/lib/client.js
CHANGED
|
@@ -91,9 +91,8 @@ var CSS = `
|
|
|
91
91
|
@media(max-width:850px){.bs-studio{padding:26px 24px}.bs-library{grid-template-columns:repeat(2,minmax(0,1fr))}.bs-heading h1{font-size:26px}.bs-modal{padding:14px}.bs-modal-close{right:20px;top:20px}}
|
|
92
92
|
@media(max-width:520px){.bs-studio{padding:24px 16px;border-radius:10px}.bs-heading h1{font-size:23px}.bs-heading h1 span{margin-left:7px}.bs-eyebrow{font-size:8px}.bs-heading p{font-size:11px}.bs-toolbar{align-items:flex-start;flex-direction:column;margin-top:20px;gap:12px}.bs-library{gap:9px}.bs-clip-info{padding:9px 8px 6px;display:block}.bs-clip-info h3{font-size:11px}.bs-clip-info>span{font-size:9px}.bs-clip-actions{padding:0 8px 9px}.bs-clip-actions button{font-size:10px}.bs-upload{min-height:165px;padding:10px}.bs-upload small{font-size:9px}.bs-section-title>span{font-size:9px}.bs-toggle-row,.bs-field{padding:13px 12px;gap:10px}.bs-toggle-row small,.bs-field small{font-size:10px}.bs-toggle-row input{right:12px}.bs-player-top{padding:16px}.bs-player-top>span{font-size:8px;letter-spacing:1px}.bs-player-top b{display:none}.bs-player-top button{font-size:11px;padding:7px 9px}.bs-player-bottom{padding:18px 16px;font-size:10px}.bs-sound{right:16px;bottom:60px}.bs-modal{padding:7px}.bs-modal-close{right:13px;top:17px;font-size:10px}.bs-modal-body .bs-heading h1{font-size:21px}}
|
|
93
93
|
@media(prefers-reduced-motion:reduce){.bs-player,.bs-studio *,.bs-player *{animation:none!important;transition:none!important}}
|
|
94
|
-
/*
|
|
95
|
-
|
|
96
|
-
html[data-lewis-immersive="true"] [data-windows-menu]{visibility:hidden!important;pointer-events:none!important}
|
|
94
|
+
/* Hide only the optional HTML menu. The desktop host owns native caption buttons. */
|
|
95
|
+
html[data-lewis-player="true"] [data-windows-menu]{visibility:hidden!important;pointer-events:none!important}
|
|
97
96
|
.bs-entry-title{margin-top:26px}
|
|
98
97
|
.bs-reset-area{display:flex;align-items:center;justify-content:space-between;gap:20px;margin-top:30px;padding:24px 0 2px;border-top:1px solid var(--bs-line)}
|
|
99
98
|
.bs-reset-area strong{font-size:12px;font-weight:500;color:#d4dfd9}
|
|
@@ -3068,204 +3067,6 @@ function UpdatePrompt({ request, status = {}, settings = {}, onDismiss, onUpdate
|
|
|
3068
3067
|
} }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "bs-startup-update-card", style: { "--bs-update-radius": `${radius}px`, "--bs-update-blur": `${blur}px` } }, /* @__PURE__ */ import_react3.default.createElement("button", { className: "bs-startup-update-close", type: "button", "aria-label": completed ? "\u5173\u95ED\u66F4\u65B0\u63D0\u793A" : "\u7A0D\u540E\u518D\u8BF4", disabled: busy, onClick: close }, "\xD7"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "bs-startup-update-glyph", "aria-hidden": "true" }, "\u2727"), /* @__PURE__ */ import_react3.default.createElement("p", { className: "bs-startup-update-brand" }, "DSH LEWIS ENCHANT", preview2 && /* @__PURE__ */ import_react3.default.createElement("span", null, " \xB7 \u66F4\u65B0\u63D0\u9192\u5916\u89C2\u9884\u89C8")), /* @__PURE__ */ import_react3.default.createElement("h2", { id: "bs-startup-update-title" }, completed ? "\u65B0\u7684\u5F00\u573A\uFF0C\u5DF2\u51C6\u5907\u5C31\u7EEA\u3002" : "\u65B0\u7684\u5F00\u573A\uFF0C\u51C6\u5907\u597D\u4E86\u3002"), /* @__PURE__ */ import_react3.default.createElement("p", { id: "bs-startup-update-description", className: "bs-startup-update-copy" }, preview2 ? "\u8FD9\u91CC\u53EA\u9884\u89C8\u5F39\u7A97\u5916\u89C2\uFF0C\u4E0D\u4F1A\u4E0B\u8F7D\u6216\u5B89\u88C5\u66F4\u65B0\u3002" : completed ? "\u91CD\u65B0\u6253\u5F00 Harness\uFF0C\u5373\u53EF\u4F7F\u7528\u65B0\u7248\u672C\u3002" : "\u53D1\u73B0\u5F00\u673A\u52A8\u753B\u65B0\u7248\u672C\uFF0C\u4E3A\u4E0B\u4E00\u6B21\u542F\u52A8\u6DFB\u4E00\u70B9\u65B0\u610F\u3002"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "bs-startup-update-versions" }, /* @__PURE__ */ import_react3.default.createElement("span", null, "v", status?.currentVersion || "1.2.5"), /* @__PURE__ */ import_react3.default.createElement("span", { "aria-hidden": "true" }, "\u2192"), /* @__PURE__ */ import_react3.default.createElement("strong", null, preview2 ? "\u540E\u7EED\u7248\u672C" : `v${status.latestVersion}`)), !busy && !completed && /* @__PURE__ */ import_react3.default.createElement("div", { className: "bs-startup-update-summary" }, /* @__PURE__ */ import_react3.default.createElement("p", null, "\u5B8C\u6574\u5B89\u88C5\u5305\u6821\u9A8C\u540E\u66F4\u65B0"), /* @__PURE__ */ import_react3.default.createElement("p", null, "\u4FDD\u7559\u4E2A\u4EBA\u89C6\u9891\u4E0E\u5C01\u9762"), /* @__PURE__ */ import_react3.default.createElement("p", null, "\u91CD\u65B0\u6253\u5F00\u540E\u4F7F\u7528\u65B0\u7248\u672C")), /* @__PURE__ */ import_react3.default.createElement("p", { className: "bs-startup-update-retain" }, "\u4F60\u7684\u89C6\u9891\u3001\u56FE\u7247\u548C\u8BBE\u7F6E\u90FD\u4F1A\u4FDD\u7559"), busy && /* @__PURE__ */ import_react3.default.createElement("p", { className: "bs-startup-update-status", role: "status", "aria-live": "polite" }, phase === "install" ? "\u6821\u9A8C\u901A\u8FC7\uFF0C\u6B63\u5728\u901A\u8FC7 Harness \u5E94\u7528\u66F4\u65B0\u2026" : "\u6B63\u5728\u4E0B\u8F7D\u5E76\u6821\u9A8C\u66F4\u65B0\u5305\u2026"), error && /* @__PURE__ */ import_react3.default.createElement("p", { className: "bs-startup-update-error", role: "alert" }, error), completed && /* @__PURE__ */ import_react3.default.createElement("p", { className: "bs-startup-update-status", role: "status" }, completed.result.application === "restart-required" ? "\u66F4\u65B0\u5B8C\u6210\u3002\u8BF7\u5B8C\u5168\u9000\u51FA\u5E76\u91CD\u65B0\u6253\u5F00 Harness\u3002" : "\u65B0\u7248\u672C\u5DF2\u5E94\u7528\u3002\u5EFA\u8BAE\u91CD\u65B0\u6253\u5F00 Harness\uFF0C\u8BA9\u6240\u6709\u7A97\u53E3\u4F7F\u7528\u65B0\u7248\u672C\u3002"), /* @__PURE__ */ import_react3.default.createElement("div", { className: "bs-startup-update-actions" }, preview2 ? /* @__PURE__ */ import_react3.default.createElement("button", { className: "bs-startup-update-primary", type: "button", onClick: close }, "\u5173\u95ED\u9884\u89C8") : completed ? /* @__PURE__ */ import_react3.default.createElement("button", { className: "bs-startup-update-primary", type: "button", onClick: close }, "\u77E5\u9053\u4E86") : /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement("button", { type: "button", disabled: busy, onClick: close }, "\u7A0D\u540E\u518D\u8BF4"), /* @__PURE__ */ import_react3.default.createElement("button", { className: "bs-startup-update-primary", type: "button", disabled: busy, onClick: accept }, busy ? "\u6B63\u5728\u66F4\u65B0\u2026" : error ? "\u91CD\u8BD5\u66F4\u65B0" : `\u66F4\u65B0\u5230 ${status.latestVersion}`)))));
|
|
3069
3068
|
}
|
|
3070
3069
|
|
|
3071
|
-
// src/immersive.js
|
|
3072
|
-
var sessions = /* @__PURE__ */ new WeakMap();
|
|
3073
|
-
var ATTRIBUTE = "data-lewis-immersive";
|
|
3074
|
-
function nativeFullscreen(root) {
|
|
3075
|
-
return root?.getAttribute?.("data-fullscreen") === "true";
|
|
3076
|
-
}
|
|
3077
|
-
function hasFullscreen(state) {
|
|
3078
|
-
return Boolean(state.doc.fullscreenElement) || nativeFullscreen(state.root);
|
|
3079
|
-
}
|
|
3080
|
-
function report(state, error) {
|
|
3081
|
-
state.lastError = error;
|
|
3082
|
-
for (const lease of state.leases) {
|
|
3083
|
-
try {
|
|
3084
|
-
lease.onError?.(error);
|
|
3085
|
-
} catch {
|
|
3086
|
-
}
|
|
3087
|
-
}
|
|
3088
|
-
}
|
|
3089
|
-
function mark(state) {
|
|
3090
|
-
state.originalAttribute = state.root.getAttribute(ATTRIBUTE);
|
|
3091
|
-
state.root.setAttribute(ATTRIBUTE, "true");
|
|
3092
|
-
state.marked = true;
|
|
3093
|
-
}
|
|
3094
|
-
function unmark(state) {
|
|
3095
|
-
if (!state.marked) return;
|
|
3096
|
-
if (state.originalAttribute === null) state.root.removeAttribute(ATTRIBUTE);
|
|
3097
|
-
else state.root.setAttribute(ATTRIBUTE, state.originalAttribute);
|
|
3098
|
-
state.marked = false;
|
|
3099
|
-
}
|
|
3100
|
-
function clean(state) {
|
|
3101
|
-
if (state.leases.size || state.pending || state.exiting) return;
|
|
3102
|
-
unmark(state);
|
|
3103
|
-
state.doc.removeEventListener?.("fullscreenchange", state.changed);
|
|
3104
|
-
if (sessions.get(state.doc) === state) sessions.delete(state.doc);
|
|
3105
|
-
}
|
|
3106
|
-
async function idle(state) {
|
|
3107
|
-
if (state.leases.size) return;
|
|
3108
|
-
if (state.pending) {
|
|
3109
|
-
await state.pending;
|
|
3110
|
-
return idle(state);
|
|
3111
|
-
}
|
|
3112
|
-
if (state.exiting) {
|
|
3113
|
-
await state.exiting;
|
|
3114
|
-
return idle(state);
|
|
3115
|
-
}
|
|
3116
|
-
if (state.owned && state.doc.fullscreenElement === state.root) {
|
|
3117
|
-
state.owned = false;
|
|
3118
|
-
state.status = "restoring";
|
|
3119
|
-
let exit;
|
|
3120
|
-
state.exiting = Promise.resolve();
|
|
3121
|
-
try {
|
|
3122
|
-
exit = state.doc.exitFullscreen();
|
|
3123
|
-
} catch (error) {
|
|
3124
|
-
report(state, error);
|
|
3125
|
-
}
|
|
3126
|
-
const done = Promise.resolve(exit).catch((error) => report(state, error)).then(() => {
|
|
3127
|
-
if (state.exiting === done) state.exiting = null;
|
|
3128
|
-
if (!state.leases.size) {
|
|
3129
|
-
state.status = "released";
|
|
3130
|
-
clean(state);
|
|
3131
|
-
}
|
|
3132
|
-
});
|
|
3133
|
-
state.exiting = done;
|
|
3134
|
-
await done;
|
|
3135
|
-
return;
|
|
3136
|
-
}
|
|
3137
|
-
state.owned = false;
|
|
3138
|
-
state.status = "released";
|
|
3139
|
-
clean(state);
|
|
3140
|
-
}
|
|
3141
|
-
function enter(state, retry = false) {
|
|
3142
|
-
if (!state.leases.size) return Promise.resolve(false);
|
|
3143
|
-
if (state.exiting) return state.exiting.then(() => enter(state, retry));
|
|
3144
|
-
if (state.pending) return state.pending;
|
|
3145
|
-
if (state.leftByUser) {
|
|
3146
|
-
state.status = "left-fullscreen";
|
|
3147
|
-
return Promise.resolve(false);
|
|
3148
|
-
}
|
|
3149
|
-
if (hasFullscreen(state)) {
|
|
3150
|
-
if (!state.owned) state.preserved = true;
|
|
3151
|
-
state.status = state.owned ? "active" : "existing-fullscreen";
|
|
3152
|
-
return Promise.resolve(true);
|
|
3153
|
-
}
|
|
3154
|
-
if (typeof state.root.requestFullscreen !== "function" || state.doc.fullscreenEnabled === false) {
|
|
3155
|
-
state.status = "unsupported";
|
|
3156
|
-
return Promise.resolve(false);
|
|
3157
|
-
}
|
|
3158
|
-
if (state.attempted && !retry) return Promise.resolve(false);
|
|
3159
|
-
state.attempted = true;
|
|
3160
|
-
state.status = "requesting";
|
|
3161
|
-
const attempt = { entered: false };
|
|
3162
|
-
state.attempt = attempt;
|
|
3163
|
-
let request;
|
|
3164
|
-
try {
|
|
3165
|
-
request = state.root.requestFullscreen({ navigationUI: "hide" });
|
|
3166
|
-
} catch (error) {
|
|
3167
|
-
request = Promise.reject(error);
|
|
3168
|
-
}
|
|
3169
|
-
const pending = Promise.resolve(request).then(() => {
|
|
3170
|
-
if (state.doc.fullscreenElement === state.root && !state.leftByUser) {
|
|
3171
|
-
state.owned = true;
|
|
3172
|
-
state.status = "active";
|
|
3173
|
-
return true;
|
|
3174
|
-
}
|
|
3175
|
-
state.status = state.leftByUser ? "left-fullscreen" : "not-entered";
|
|
3176
|
-
return false;
|
|
3177
|
-
}, (error) => {
|
|
3178
|
-
state.status = "denied";
|
|
3179
|
-
report(state, error);
|
|
3180
|
-
return false;
|
|
3181
|
-
}).then(async (active) => {
|
|
3182
|
-
if (state.pending === pending) state.pending = null;
|
|
3183
|
-
if (state.attempt === attempt) state.attempt = null;
|
|
3184
|
-
if (!state.leases.size) {
|
|
3185
|
-
await idle(state);
|
|
3186
|
-
return false;
|
|
3187
|
-
}
|
|
3188
|
-
return active;
|
|
3189
|
-
});
|
|
3190
|
-
state.pending = pending;
|
|
3191
|
-
return pending;
|
|
3192
|
-
}
|
|
3193
|
-
function createSession(doc) {
|
|
3194
|
-
const state = {
|
|
3195
|
-
doc,
|
|
3196
|
-
root: doc.documentElement,
|
|
3197
|
-
leases: /* @__PURE__ */ new Set(),
|
|
3198
|
-
pending: null,
|
|
3199
|
-
exiting: null,
|
|
3200
|
-
owned: false,
|
|
3201
|
-
leftByUser: false,
|
|
3202
|
-
attempted: false,
|
|
3203
|
-
retryUsed: false,
|
|
3204
|
-
preserved: false,
|
|
3205
|
-
attempt: null,
|
|
3206
|
-
marked: false,
|
|
3207
|
-
originalAttribute: null,
|
|
3208
|
-
status: "idle",
|
|
3209
|
-
lastError: null
|
|
3210
|
-
};
|
|
3211
|
-
state.changed = () => {
|
|
3212
|
-
const current = doc.fullscreenElement;
|
|
3213
|
-
if (state.attempt && current === state.root) state.attempt.entered = true;
|
|
3214
|
-
if ((state.owned || state.attempt?.entered) && current !== state.root && !state.exiting) {
|
|
3215
|
-
state.owned = false;
|
|
3216
|
-
state.leftByUser = true;
|
|
3217
|
-
state.status = "left-fullscreen";
|
|
3218
|
-
}
|
|
3219
|
-
};
|
|
3220
|
-
doc.addEventListener?.("fullscreenchange", state.changed);
|
|
3221
|
-
sessions.set(doc, state);
|
|
3222
|
-
return state;
|
|
3223
|
-
}
|
|
3224
|
-
function acquireImmersive(doc = globalThis.document, options = {}) {
|
|
3225
|
-
if (!doc?.documentElement) {
|
|
3226
|
-
return {
|
|
3227
|
-
ready: Promise.resolve(false),
|
|
3228
|
-
release: () => Promise.resolve(),
|
|
3229
|
-
retryFromGesture: () => Promise.resolve(false),
|
|
3230
|
-
getStatus: () => "unsupported"
|
|
3231
|
-
};
|
|
3232
|
-
}
|
|
3233
|
-
let state = sessions.get(doc);
|
|
3234
|
-
if (!state) state = createSession(doc);
|
|
3235
|
-
if (!state.leases.size) {
|
|
3236
|
-
state.leftByUser = false;
|
|
3237
|
-
state.attempted = false;
|
|
3238
|
-
state.retryUsed = false;
|
|
3239
|
-
state.preserved = false;
|
|
3240
|
-
state.lastError = null;
|
|
3241
|
-
mark(state);
|
|
3242
|
-
}
|
|
3243
|
-
const record = { released: false, onError: options.onError };
|
|
3244
|
-
state.leases.add(record);
|
|
3245
|
-
const resultForLease = (promise) => promise.then((active) => !record.released && active);
|
|
3246
|
-
const ready = resultForLease(enter(state));
|
|
3247
|
-
return {
|
|
3248
|
-
ready,
|
|
3249
|
-
getStatus: () => record.released ? "released" : state.status,
|
|
3250
|
-
retryFromGesture(event) {
|
|
3251
|
-
if (record.released || state.leftByUser || event?.isTrusted !== true) return Promise.resolve(false);
|
|
3252
|
-
if (state.preserved) return Promise.resolve(hasFullscreen(state));
|
|
3253
|
-
if (state.pending || state.exiting || hasFullscreen(state)) return resultForLease(enter(state));
|
|
3254
|
-
if (state.retryUsed) return Promise.resolve(false);
|
|
3255
|
-
state.retryUsed = true;
|
|
3256
|
-
return resultForLease(enter(state, true));
|
|
3257
|
-
},
|
|
3258
|
-
release() {
|
|
3259
|
-
if (!record.released) {
|
|
3260
|
-
record.released = true;
|
|
3261
|
-
state.leases.delete(record);
|
|
3262
|
-
if (!state.leases.size) unmark(state);
|
|
3263
|
-
}
|
|
3264
|
-
return idle(state);
|
|
3265
|
-
}
|
|
3266
|
-
};
|
|
3267
|
-
}
|
|
3268
|
-
|
|
3269
3070
|
// src/shortcut-registry.js
|
|
3270
3071
|
var SHORTCUT_LIMIT = 17;
|
|
3271
3072
|
var SHORTCUT_REGISTRY_KEY = Symbol.for("dsh.lewis.enchant.shortcuts.v1");
|
|
@@ -3397,7 +3198,27 @@ var launchRequest = null;
|
|
|
3397
3198
|
var launchDecisionSettled = false;
|
|
3398
3199
|
var latestState = null;
|
|
3399
3200
|
var subscribers = /* @__PURE__ */ new Set();
|
|
3400
|
-
var
|
|
3201
|
+
var playerWindows = /* @__PURE__ */ new WeakMap();
|
|
3202
|
+
var VERSION2 = true ? "1.2.6" : "1.2.6";
|
|
3203
|
+
function acquirePlayerWindow(doc) {
|
|
3204
|
+
const root = doc.documentElement;
|
|
3205
|
+
let state = playerWindows.get(doc);
|
|
3206
|
+
if (!state) {
|
|
3207
|
+
state = { count: 0, previous: root.getAttribute("data-lewis-player") };
|
|
3208
|
+
playerWindows.set(doc, state);
|
|
3209
|
+
}
|
|
3210
|
+
state.count++;
|
|
3211
|
+
root.setAttribute("data-lewis-player", "true");
|
|
3212
|
+
let released = false;
|
|
3213
|
+
return () => {
|
|
3214
|
+
if (released) return;
|
|
3215
|
+
released = true;
|
|
3216
|
+
if (--state.count) return;
|
|
3217
|
+
if (state.previous === null) root.removeAttribute("data-lewis-player");
|
|
3218
|
+
else root.setAttribute("data-lewis-player", state.previous);
|
|
3219
|
+
playerWindows.delete(doc);
|
|
3220
|
+
};
|
|
3221
|
+
}
|
|
3401
3222
|
async function api(path, options = {}) {
|
|
3402
3223
|
const controller = new AbortController();
|
|
3403
3224
|
const timeout = ["/upload", "/end-images", "/updates/prepare", "/reset"].includes(path) ? 18e4 : path === "/updates/check" ? 2e4 : 7e3;
|
|
@@ -3450,7 +3271,6 @@ function Player({ clip, settings, onClose, endOnly = false }) {
|
|
|
3450
3271
|
useStyles();
|
|
3451
3272
|
const video = (0, import_react5.useRef)(null);
|
|
3452
3273
|
const dialog = (0, import_react5.useRef)(null);
|
|
3453
|
-
const immersive = (0, import_react5.useRef)(null);
|
|
3454
3274
|
const closed = (0, import_react5.useRef)(false);
|
|
3455
3275
|
const [phase, setPhase] = (0, import_react5.useState)(endOnly ? "end" : "intro");
|
|
3456
3276
|
const phaseRef = (0, import_react5.useRef)(endOnly ? "end" : "intro");
|
|
@@ -3488,24 +3308,19 @@ function Player({ clip, settings, onClose, endOnly = false }) {
|
|
|
3488
3308
|
closed.current = false;
|
|
3489
3309
|
const playerDialog = dialog.current;
|
|
3490
3310
|
const previous = document.activeElement;
|
|
3491
|
-
const
|
|
3492
|
-
immersive.current = lease;
|
|
3311
|
+
const releaseWindow = acquirePlayerWindow(document);
|
|
3493
3312
|
if (typeof playerDialog.showModal === "function" && !playerDialog.open) playerDialog.showModal();
|
|
3494
3313
|
else playerDialog.setAttribute("open", "");
|
|
3495
3314
|
const key = (e) => {
|
|
3496
3315
|
e.preventDefault();
|
|
3497
3316
|
e.stopPropagation();
|
|
3498
|
-
if (!e.repeat && !e.isComposing)
|
|
3499
|
-
void lease.retryFromGesture(e);
|
|
3500
|
-
advance();
|
|
3501
|
-
}
|
|
3317
|
+
if (!e.repeat && !e.isComposing) advance();
|
|
3502
3318
|
};
|
|
3503
3319
|
window.addEventListener("keydown", key, true);
|
|
3504
3320
|
playerDialog.focus();
|
|
3505
3321
|
return () => {
|
|
3506
3322
|
closed.current = true;
|
|
3507
|
-
|
|
3508
|
-
void lease.release();
|
|
3323
|
+
releaseWindow();
|
|
3509
3324
|
window.removeEventListener("keydown", key, true);
|
|
3510
3325
|
if (playerDialog.open && typeof playerDialog.close === "function") playerDialog.close();
|
|
3511
3326
|
if (previous?.isConnected) previous.focus?.();
|
|
@@ -3600,10 +3415,7 @@ function Player({ clip, settings, onClose, endOnly = false }) {
|
|
|
3600
3415
|
advance();
|
|
3601
3416
|
},
|
|
3602
3417
|
onPointerDown: (e) => {
|
|
3603
|
-
if (!e.target.closest("[data-bs-control]"))
|
|
3604
|
-
void immersive.current?.retryFromGesture(e.nativeEvent);
|
|
3605
|
-
advance();
|
|
3606
|
-
}
|
|
3418
|
+
if (!e.target.closest("[data-bs-control]")) advance();
|
|
3607
3419
|
}
|
|
3608
3420
|
},
|
|
3609
3421
|
phase === "end" ? /* @__PURE__ */ import_react5.default.createElement(EndTitle, { settings }) : /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, clip.kind === "sequence" ? /* @__PURE__ */ import_react5.default.createElement(StartupSequence, { sound: settings.sound, volume: settings.volume, onEnded: showEnd }) : /* @__PURE__ */ import_react5.default.createElement(
|
|
@@ -3615,7 +3427,7 @@ function Player({ clip, settings, onClose, endOnly = false }) {
|
|
|
3615
3427
|
loop: false,
|
|
3616
3428
|
playsInline: true,
|
|
3617
3429
|
preload: "auto",
|
|
3618
|
-
style: { objectFit:
|
|
3430
|
+
style: { objectFit: "cover" },
|
|
3619
3431
|
onPlaying: () => setBlocked(false),
|
|
3620
3432
|
onEnded: showEnd,
|
|
3621
3433
|
onError: showEnd
|
|
@@ -3922,7 +3734,7 @@ function SettingsPanel({ standalone = false }) {
|
|
|
3922
3734
|
e.target.value = "";
|
|
3923
3735
|
} }), /* @__PURE__ */ import_react5.default.createElement("div", { className: "bs-section-title" }, /* @__PURE__ */ import_react5.default.createElement("h2", null, "\u64AD\u653E\u504F\u597D"), /* @__PURE__ */ import_react5.default.createElement("span", null, "\u4FEE\u6539\u7ACB\u5373\u4FDD\u5B58")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "bs-preferences" }, /* @__PURE__ */ import_react5.default.createElement(Toggle, { label: "\u542F\u52A8\u65F6\u64AD\u653E", description: "\u6BCF\u6B21\u6253\u5F00 Harness \u64AD\u653E\u4E00\u6B21\uFF0C\u5207\u6362\u4F1A\u8BDD\u4E0D\u91CD\u590D", checked: settings.enabled, disabled: busy, onChange: (enabled) => save({ enabled }) }), /* @__PURE__ */ import_react5.default.createElement(Toggle, { label: "\u64AD\u653E\u58F0\u97F3", description: "\u6D4F\u89C8\u5668\u82E5\u62E6\u622A\u6709\u58F0\u81EA\u52A8\u64AD\u653E\uFF0C\u52A8\u753B\u4ECD\u4F1A\u9759\u97F3\u5F00\u59CB", checked: settings.sound, disabled: busy, onChange: (sound) => save({ sound }) }), settings.sound && /* @__PURE__ */ import_react5.default.createElement("label", { className: "bs-field" }, /* @__PURE__ */ import_react5.default.createElement("span", null, "\u97F3\u91CF"), /* @__PURE__ */ import_react5.default.createElement("input", { "aria-label": "\u97F3\u91CF", type: "range", min: "0", max: "100", value: draftVolume, disabled: busy, onChange: (e) => setDraftVolume(Number(e.target.value)), onPointerUp: () => save({ volume: draftVolume / 100 }), onKeyUp: (e) => {
|
|
3924
3736
|
if (["ArrowLeft", "ArrowRight", "Home", "End"].includes(e.key)) save({ volume: draftVolume / 100 });
|
|
3925
|
-
} }), /* @__PURE__ */ import_react5.default.createElement("output", null, draftVolume, "%")), /* @__PURE__ */ import_react5.default.createElement(
|
|
3737
|
+
} }), /* @__PURE__ */ import_react5.default.createElement("output", null, draftVolume, "%")), /* @__PURE__ */ import_react5.default.createElement(Toggle, { label: "\u968F\u673A\u5F00\u573A", description: "\u6BCF\u6B21\u542F\u52A8\u4ECE\u7247\u5E93\u968F\u673A\u9009\u62E9\uFF1B\u5173\u95ED\u540E\u4F7F\u7528\u5F53\u524D\u52A8\u753B", checked: settings.shuffle, disabled: busy, onChange: (shuffle) => save({ shuffle }) })), /* @__PURE__ */ import_react5.default.createElement("div", { className: "bs-help" }, /* @__PURE__ */ import_react5.default.createElement("strong", null, "\u50CF\u6E38\u620F\u4E00\u6837\u5F00\u542F\u3002"), /* @__PURE__ */ import_react5.default.createElement("p", null, "\u52A8\u753B\u4E2D\u6309\u4EFB\u610F\u952E\u8DF3\u5230\u6807\u9898\u9875\uFF0C\u518D\u6309\u4EFB\u610F\u952E\u8FDB\u5165\u3002\u4E5F\u652F\u6301\u9F20\u6807\u70B9\u51FB\u4E0E\u89E6\u5C4F\uFF1B\u957F\u6309\u4E0D\u4F1A\u8FDE\u8DF3\u3002\u89C6\u9891\u548C\u7ED3\u675F\u56FE\u7247\u90FD\u4FDD\u5B58\u5728\u672C\u673A\u3002"), /* @__PURE__ */ import_react5.default.createElement("span", null, "\u89C6\u9891\uFF1Adsh-boot-animation \xB7 BSD-3-Clause\u3000\u6280\u672F\u6863\u6848\uFF1Adsh-startup-screen \xB7 MIT")), /* @__PURE__ */ import_react5.default.createElement(UpdatePanel, { request: api, standalone }), /* @__PURE__ */ import_react5.default.createElement("div", { className: "bs-section-title" }, /* @__PURE__ */ import_react5.default.createElement("h2", null, "\u66F4\u65B0\u63D0\u9192\u5916\u89C2"), /* @__PURE__ */ import_react5.default.createElement("button", { className: "bs-text-button", type: "button", onClick: () => setAppearancePreview(true) }, "\u9884\u89C8\u66F4\u65B0\u63D0\u9192")), /* @__PURE__ */ import_react5.default.createElement("div", { className: "bs-preferences" }, /* @__PURE__ */ import_react5.default.createElement("label", { className: "bs-field" }, /* @__PURE__ */ import_react5.default.createElement("span", null, "\u78E8\u7802\u5EA6", /* @__PURE__ */ import_react5.default.createElement("small", null, "\u8C03\u6574\u66F4\u65B0\u5F39\u7A97\u7684\u80CC\u666F\u6A21\u7CCA\u7A0B\u5EA6")), /* @__PURE__ */ import_react5.default.createElement("input", { "aria-label": "\u66F4\u65B0\u5F39\u7A97\u78E8\u7802\u5EA6", type: "range", min: "0", max: "48", step: "1", value: draftBlur, disabled: busy, onChange: (e) => setDraftBlur(Number(e.target.value)), onPointerUp: (e) => save({ updatePromptBlur: Number(e.currentTarget.value) }), onKeyUp: (e) => {
|
|
3926
3738
|
if (["ArrowLeft", "ArrowRight", "Home", "End", "PageUp", "PageDown"].includes(e.key)) save({ updatePromptBlur: Number(e.currentTarget.value) });
|
|
3927
3739
|
} }), /* @__PURE__ */ import_react5.default.createElement("output", null, draftBlur, "px")), /* @__PURE__ */ import_react5.default.createElement("label", { className: "bs-field" }, /* @__PURE__ */ import_react5.default.createElement("span", null, "\u5F39\u7A97\u5706\u89D2", /* @__PURE__ */ import_react5.default.createElement("small", null, "\u8C03\u6574\u66F4\u65B0\u5F39\u7A97\u8FB9\u89D2\u7684\u5706\u6DA6\u7A0B\u5EA6")), /* @__PURE__ */ import_react5.default.createElement("input", { "aria-label": "\u66F4\u65B0\u5F39\u7A97\u5706\u89D2", type: "range", min: "12", max: "40", step: "1", value: draftRadius, disabled: busy, onChange: (e) => setDraftRadius(Number(e.target.value)), onPointerUp: (e) => save({ updatePromptRadius: Number(e.currentTarget.value) }), onKeyUp: (e) => {
|
|
3928
3740
|
if (["ArrowLeft", "ArrowRight", "Home", "End", "PageUp", "PageDown"].includes(e.key)) save({ updatePromptRadius: Number(e.currentTarget.value) });
|
package/lib/index.js
CHANGED
|
@@ -12,7 +12,7 @@ export const inject = ['webServer']
|
|
|
12
12
|
export const BASE_PATH = '/dsh-boot-studio'
|
|
13
13
|
export const MAX_UPLOAD_BYTES = 200 * 1024 * 1024
|
|
14
14
|
export const MAX_IMAGE_UPLOAD_BYTES = 20 * 1024 * 1024
|
|
15
|
-
export const DEFAULT_SETTINGS = Object.freeze({ enabled: true, sound: false, volume: 0.7,
|
|
15
|
+
export const DEFAULT_SETTINGS = Object.freeze({ enabled: true, sound: false, volume: 0.7, shuffle: false, selectedId: 'brand', endScreen: 'logo', endImageId: null, logoVariant: 'silver', endFit: 'contain', updatePromptBlur: 30, updatePromptRadius: 30, showShortcut: false })
|
|
16
16
|
const BUILTINS = [
|
|
17
17
|
{ id: 'brand', name: '启', file: 'deepseek-brand-intro.mp4' },
|
|
18
18
|
{ id: 'cyberpunk', name: '数字生命', file: 'deepseek-cyberpunk-intro.mp4' },
|
|
@@ -45,12 +45,12 @@ function validateSettings(patch, current, available, availableImages = new Set()
|
|
|
45
45
|
const next = { ...current }
|
|
46
46
|
for (const [key, value] of Object.entries(patch)) {
|
|
47
47
|
if (key === 'duration') throw new HttpError(400, '已取消播放时长设置,动画按原始长度完整播放。')
|
|
48
|
+
if (key === 'fit') throw new HttpError(400, '已取消画面显示设置,开机动画始终铺满当前窗口。')
|
|
48
49
|
if (!Object.hasOwn(DEFAULT_SETTINGS, key)) throw new HttpError(400, `不支持的设置:${key}`)
|
|
49
50
|
if (['enabled', 'sound', 'shuffle', 'showShortcut'].includes(key) && typeof value !== 'boolean') throw new HttpError(400, `${key} 必须是开关。`)
|
|
50
51
|
if (key === 'volume' && !(typeof value === 'number' && Number.isFinite(value) && value >= 0 && value <= 1)) throw new HttpError(400, '音量须在 0 到 1 之间。')
|
|
51
52
|
if (key === 'updatePromptBlur' && !(Number.isInteger(value) && value >= 0 && value <= 48)) throw new HttpError(400, '弹窗磨砂度须为 0 到 48 之间的整数。')
|
|
52
53
|
if (key === 'updatePromptRadius' && !(Number.isInteger(value) && value >= 12 && value <= 40)) throw new HttpError(400, '弹窗圆角须为 12 到 40 之间的整数。')
|
|
53
|
-
if (key === 'fit' && !['cover', 'contain'].includes(value)) throw new HttpError(400, '画面适配须为 cover 或 contain。')
|
|
54
54
|
if (key === 'selectedId' && !(typeof value === 'string' && available.has(value))) throw new HttpError(400, '所选动画不存在,请刷新片库。')
|
|
55
55
|
if (key === 'endScreen' && !['logo', 'image'].includes(value)) throw new HttpError(400, '结束封面须为 logo 或 image。')
|
|
56
56
|
if (key === 'endImageId' && value !== null && !(typeof value === 'string' && availableImages.has(value))) throw new HttpError(400, '所选封面图片不存在,请重新上传。')
|
|
@@ -170,11 +170,11 @@ export function createHandler(options = {}) {
|
|
|
170
170
|
const uploads = saved.uploads.filter(c => c && UPLOAD_ID.test(c.id) && Object.hasOwn(TYPES, c.ext) && typeof c.name === 'string').map(c => ({ id: c.id, ext: c.ext, name: c.name.slice(0, 120) }))
|
|
171
171
|
if (saved.endImages !== undefined && !Array.isArray(saved.endImages)) throw new HttpError(500, '结束封面片库格式不正确。')
|
|
172
172
|
const endImages = (saved.endImages || []).filter(c => c && IMAGE_ID.test(c.id) && Object.hasOwn(IMAGE_TYPES, c.ext) && typeof c.name === 'string').map(c => ({ id: c.id, ext: c.ext, name: c.name.slice(0, 120) }))
|
|
173
|
-
// Earlier releases stored a playback cap. Ignore
|
|
173
|
+
// Earlier releases stored a playback cap and video-fit preference. Ignore those retired fields while
|
|
174
174
|
// preserving every remaining setting and personal-media manifest entry.
|
|
175
175
|
const legacySettings = saved.settings || {}
|
|
176
176
|
const settings = legacySettings && typeof legacySettings === 'object' && !Array.isArray(legacySettings)
|
|
177
|
-
? Object.fromEntries(Object.entries(legacySettings).filter(([key]) => key !== 'duration')) : legacySettings
|
|
177
|
+
? Object.fromEntries(Object.entries(legacySettings).filter(([key]) => key !== 'duration' && key !== 'fit')) : legacySettings
|
|
178
178
|
try { store = { version: 1, settings: validateSettings(settings, DEFAULT_SETTINGS, new Set([...BUILTINS.map(c => c.id), SEQUENCE.id, ...uploads.map(c => c.id)]), new Set(endImages.map(c => c.id))), uploads, endImages } } catch { throw new HttpError(500, '已保存的设置格式不正确,请备份并检查 settings.json。') }
|
|
179
179
|
})()
|
|
180
180
|
await initializing
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-openup-lewis",
|
|
3
|
-
"version": "1.2.
|
|
4
|
-
"description": "DSH LEWIS ENCHANT ·
|
|
3
|
+
"version": "1.2.6",
|
|
4
|
+
"description": "DSH LEWIS ENCHANT · 附魔台|开机动画:铺满当前窗口的完整开场、自定义视频与封面、启动检查更新和磨砂提示。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
7
7
|
"exports": {
|