mirror of
https://github.com/nianzhibai/91.git
synced 2026-06-15 00:44:30 +08:00
fix: refine video UI loading and playback behavior
This commit is contained in:
@@ -632,7 +632,7 @@ export function DrivesPage() {
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="admin-btn is-stop"
|
||||
className="admin-btn is-primary"
|
||||
onClick={() => handleStopDriveTasks(d)}
|
||||
disabled={!!stoppingDriveId}
|
||||
title="停止此网盘当前的扫描、封面、预览视频和视频指纹生成任务。"
|
||||
@@ -642,7 +642,7 @@ export function DrivesPage() {
|
||||
</button>
|
||||
</div>
|
||||
{d.kind !== "spider91" && (
|
||||
<button type="button" className="admin-btn" onClick={() => openEdit(d)}>
|
||||
<button type="button" className="admin-btn is-primary" onClick={() => openEdit(d)}>
|
||||
编辑配置凭证
|
||||
</button>
|
||||
)}
|
||||
|
||||
@@ -92,8 +92,11 @@ const LONG_PRESS_MS = 400;
|
||||
const FAST_RATE = 2;
|
||||
/** 默认倍速。 */
|
||||
const NORMAL_RATE = 1;
|
||||
/** ArtPlayer 内部播放失败自动重连次数。 */
|
||||
const ARTPLAYER_RECONNECT_TIME_MAX = 3;
|
||||
|
||||
Artplayer.FAST_FORWARD_VALUE = FAST_RATE;
|
||||
Artplayer.RECONNECT_TIME_MAX = ARTPLAYER_RECONNECT_TIME_MAX;
|
||||
|
||||
const DEFAULT_SETTINGS: PlayerSettings = {
|
||||
volume: 0.7,
|
||||
|
||||
@@ -492,10 +492,15 @@
|
||||
}
|
||||
|
||||
.skeleton-card {
|
||||
--skeleton-card-bg: var(--bg-surface);
|
||||
--skeleton-card-border: var(--border-subtle);
|
||||
--skeleton-shimmer-base: rgba(255, 255, 255, 0.03);
|
||||
--skeleton-shimmer-highlight: rgba(255, 255, 255, 0.08);
|
||||
|
||||
position: relative;
|
||||
aspect-ratio: 16 / 12.5;
|
||||
background: var(--bg-surface);
|
||||
border: 1px solid var(--border-subtle);
|
||||
background: var(--skeleton-card-bg);
|
||||
border: 1px solid var(--skeleton-card-border);
|
||||
border-radius: var(--radius-md);
|
||||
padding: 8px;
|
||||
box-sizing: border-box;
|
||||
@@ -504,6 +509,18 @@
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
:root[data-theme="pink"] .skeleton-card {
|
||||
--skeleton-card-border: rgba(255, 91, 138, 0.18);
|
||||
--skeleton-shimmer-base: rgba(255, 91, 138, 0.12);
|
||||
--skeleton-shimmer-highlight: rgba(255, 91, 138, 0.26);
|
||||
}
|
||||
|
||||
:root[data-theme="sky"] .skeleton-card {
|
||||
--skeleton-card-border: rgba(60, 100, 170, 0.18);
|
||||
--skeleton-shimmer-base: rgba(60, 100, 170, 0.13);
|
||||
--skeleton-shimmer-highlight: rgba(60, 100, 170, 0.26);
|
||||
}
|
||||
|
||||
/* Skeleton image thumbnail area */
|
||||
.skeleton-card::before {
|
||||
content: "";
|
||||
@@ -513,9 +530,9 @@
|
||||
border-radius: var(--radius-sm);
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
rgba(255, 255, 255, 0.03) 25%,
|
||||
rgba(255, 255, 255, 0.08) 50%,
|
||||
rgba(255, 255, 255, 0.03) 75%
|
||||
var(--skeleton-shimmer-base) 25%,
|
||||
var(--skeleton-shimmer-highlight) 50%,
|
||||
var(--skeleton-shimmer-base) 75%
|
||||
);
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-shimmer 1.6s ease-in-out infinite;
|
||||
@@ -529,8 +546,8 @@
|
||||
width: 100%;
|
||||
height: 28px;
|
||||
background:
|
||||
linear-gradient(90deg, rgba(255, 255, 255, 0.03) 25%, rgba(255, 255, 255, 0.08) 50%, rgba(255, 255, 255, 0.03) 75%) 0 0 / 70% 12px no-repeat,
|
||||
linear-gradient(90deg, rgba(255, 255, 255, 0.03) 25%, rgba(255, 255, 255, 0.08) 50%, rgba(255, 255, 255, 0.03) 75%) 0 20px / 42% 8px no-repeat;
|
||||
linear-gradient(90deg, var(--skeleton-shimmer-base) 25%, var(--skeleton-shimmer-highlight) 50%, var(--skeleton-shimmer-base) 75%) 0 0 / 70% 12px no-repeat,
|
||||
linear-gradient(90deg, var(--skeleton-shimmer-base) 25%, var(--skeleton-shimmer-highlight) 50%, var(--skeleton-shimmer-base) 75%) 0 20px / 42% 8px no-repeat;
|
||||
background-size: 200% 100%;
|
||||
animation: skeleton-shimmer 1.6s ease-in-out infinite;
|
||||
}
|
||||
|
||||
@@ -304,6 +304,21 @@ test("drive management exposes stop task controls", () => {
|
||||
assert.match(drivesPageSource, /停止所有网盘任务/);
|
||||
});
|
||||
|
||||
test("drive detail primary actions use the rescan button color", () => {
|
||||
assert.match(
|
||||
drivesPageSource,
|
||||
/className="admin-btn is-primary"\s+onClick=\{\(\) => handleRescan\(d\)\}/
|
||||
);
|
||||
assert.match(
|
||||
drivesPageSource,
|
||||
/className="admin-btn is-primary"\s+onClick=\{\(\) => handleStopDriveTasks\(d\)\}/
|
||||
);
|
||||
assert.match(
|
||||
drivesPageSource,
|
||||
/className="admin-btn is-primary"\s+onClick=\{\(\) => openEdit\(d\)\}/
|
||||
);
|
||||
});
|
||||
|
||||
test("drive rescan reports busy storage tasks instead of queueing duplicates", () => {
|
||||
assert.match(apiSource, /accepted:\s*boolean;\s*message\?:\s*string/);
|
||||
assert.match(apiSource, /scanGenerationStatus\?: DriveGenerationStatus/);
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import assert from "node:assert/strict";
|
||||
import { readFileSync } from "node:fs";
|
||||
import test from "node:test";
|
||||
|
||||
const videoCardCss = readFileSync(
|
||||
new URL("../src/styles/video-card.css", import.meta.url),
|
||||
"utf8"
|
||||
);
|
||||
|
||||
function ruleBody(css: string, selector: string): string {
|
||||
const escapedSelector = selector.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
||||
const match = css.match(new RegExp(`${escapedSelector}\\s*\\{([^}]*)\\}`));
|
||||
assert.ok(match, `Expected CSS rule for ${selector}`);
|
||||
return match[1];
|
||||
}
|
||||
|
||||
test("home video skeleton uses theme-aware non-white shimmer colors", () => {
|
||||
const skeleton = ruleBody(videoCardCss, ".skeleton-card");
|
||||
const pink = ruleBody(videoCardCss, ':root[data-theme="pink"] .skeleton-card');
|
||||
const sky = ruleBody(videoCardCss, ':root[data-theme="sky"] .skeleton-card');
|
||||
const thumb = ruleBody(videoCardCss, ".skeleton-card::before");
|
||||
const text = ruleBody(videoCardCss, ".skeleton-card::after");
|
||||
|
||||
assert.match(skeleton, /--skeleton-shimmer-base\s*:/);
|
||||
assert.match(skeleton, /--skeleton-shimmer-highlight\s*:/);
|
||||
assert.match(thumb, /var\(--skeleton-shimmer-base\)/);
|
||||
assert.match(thumb, /var\(--skeleton-shimmer-highlight\)/);
|
||||
assert.match(text, /var\(--skeleton-shimmer-base\)/);
|
||||
assert.match(text, /var\(--skeleton-shimmer-highlight\)/);
|
||||
|
||||
assert.match(pink, /--skeleton-shimmer-base\s*:\s*rgba\(255,\s*91,\s*138,\s*0\.12\)/);
|
||||
assert.match(pink, /--skeleton-shimmer-highlight\s*:\s*rgba\(255,\s*91,\s*138,\s*0\.26\)/);
|
||||
assert.match(sky, /--skeleton-shimmer-base\s*:\s*rgba\(60,\s*100,\s*170,\s*0\.13\)/);
|
||||
assert.match(sky, /--skeleton-shimmer-highlight\s*:\s*rgba\(60,\s*100,\s*170,\s*0\.26\)/);
|
||||
});
|
||||
@@ -74,6 +74,14 @@ test("detail player exposes a non-persistent loop switch in ArtPlayer settings",
|
||||
assert.match(playerSource, /item\.tooltip = next \? "开" : "关"/);
|
||||
});
|
||||
|
||||
test("detail player limits ArtPlayer automatic reconnect attempts", () => {
|
||||
assert.match(playerSource, /const ARTPLAYER_RECONNECT_TIME_MAX = 3;/);
|
||||
assert.match(
|
||||
playerSource,
|
||||
/Artplayer\.RECONNECT_TIME_MAX = ARTPLAYER_RECONNECT_TIME_MAX;/
|
||||
);
|
||||
});
|
||||
|
||||
test("detail loading skeleton matches current desktop video page layout", () => {
|
||||
assert.match(detailPageSource, /className="vd-layout vd-skeleton"/);
|
||||
assert.match(detailPageSource, /className="vd-skeleton__summary"/);
|
||||
|
||||
Reference in New Issue
Block a user