mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-22 04:03:42 +08:00
Comprehensive UI overhaul across the Liquid Glass design system: - Refined color palette with deeper dark mode tones and better contrast - Updated glass morphism effects with improved blur and saturation values - Polished Button, Card, Badge, Input, Switch, SegmentedControl components - Improved VideoCard with poster zoom effect, gradient overlay, and better badge layout - Refined Navbar with tighter spacing and better icon button hover states - Enhanced sidebar toggle buttons (rounded-full, better sizing) - Split PlayerSettings into PlayerSettings + DanmakuSettings (150-line limit) - Fixed broken rgba(var(--accent-color-rgb)) references with color-mix() - Added new CSS variables: --radius-xs/sm/md/lg, --shadow-lg, --transition-spring/snappy - Added staggered children animation and sidebar enter keyframes - Better scrollbar styling and focus states Co-Authored-By: Claude Opus 4.6 <[email protected]>
98 lines
5.6 KiB
TypeScript
98 lines
5.6 KiB
TypeScript
'use client';
|
|
|
|
import { Icons } from '@/components/ui/Icon';
|
|
import type { ProxyMode } from '@/lib/store/settings-store';
|
|
import { DanmakuSettings } from './DanmakuSettings';
|
|
|
|
interface PlayerSettingsProps {
|
|
fullscreenType: 'auto' | 'native' | 'window';
|
|
onFullscreenTypeChange: (type: 'auto' | 'native' | 'window') => void;
|
|
proxyMode: ProxyMode;
|
|
onProxyModeChange: (mode: ProxyMode) => void;
|
|
danmakuApiUrl: string;
|
|
onDanmakuApiUrlChange: (url: string) => void;
|
|
danmakuOpacity: number;
|
|
onDanmakuOpacityChange: (value: number) => void;
|
|
danmakuFontSize: number;
|
|
onDanmakuFontSizeChange: (value: number) => void;
|
|
danmakuDisplayArea: number;
|
|
onDanmakuDisplayAreaChange: (value: number) => void;
|
|
showDanmakuApi?: boolean;
|
|
}
|
|
|
|
const activeBtn = 'bg-[var(--accent-color)] border-[var(--accent-color)] text-white shadow-[0_2px_12px_color-mix(in_srgb,var(--accent-color)_35%,transparent)]';
|
|
const inactiveBtn = 'bg-[var(--glass-bg)] border-[var(--glass-border)] text-[var(--text-color)] hover:bg-[color-mix(in_srgb,var(--accent-color)_8%,transparent)] hover:border-[color-mix(in_srgb,var(--accent-color)_20%,var(--glass-border))]';
|
|
const btnBase = 'px-4 py-3 rounded-[var(--radius-2xl)] border text-left font-medium transition-all duration-200 cursor-pointer';
|
|
|
|
export function PlayerSettings(props: PlayerSettingsProps) {
|
|
const { fullscreenType, onFullscreenTypeChange, proxyMode, onProxyModeChange } = props;
|
|
|
|
return (
|
|
<div className="bg-[var(--glass-bg)] backdrop-blur-[12px] [-webkit-backdrop-filter:blur(12px)] border border-[var(--glass-border)] rounded-[var(--radius-2xl)] shadow-[var(--shadow-sm)] p-5 sm:p-6 mb-5">
|
|
<h2 className="text-lg font-bold text-[var(--text-color)] mb-4 tracking-[-0.02em]">播放器设置</h2>
|
|
|
|
<div className="space-y-5">
|
|
{/* Fullscreen Mode */}
|
|
<div>
|
|
<h3 className="font-medium text-sm text-[var(--text-color)] mb-1.5 inline-flex items-center gap-2">
|
|
<Icons.Maximize size={16} className="text-[var(--accent-color)]" />
|
|
默认全屏方式
|
|
</h3>
|
|
<p className="text-xs text-[var(--text-color-secondary)] mb-3">选择在桌面端点击播放器全屏按钮时的行为</p>
|
|
<div className="grid grid-cols-1 sm:grid-cols-2 gap-2.5">
|
|
<button onClick={() => onFullscreenTypeChange('native')} className={`${btnBase} ${fullscreenType === 'native' ? activeBtn : inactiveBtn}`}>
|
|
<div className="font-semibold text-sm">系统全屏</div>
|
|
<div className="text-xs opacity-75 mt-0.5">进入浏览器原生全屏状态</div>
|
|
</button>
|
|
<button onClick={() => onFullscreenTypeChange('window')} className={`${btnBase} ${fullscreenType === 'window' ? activeBtn : inactiveBtn}`}>
|
|
<div className="font-semibold text-sm">网页全屏</div>
|
|
<div className="text-xs opacity-75 mt-0.5">播放器填满当前浏览器窗口</div>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="border-t border-[var(--glass-border)]" />
|
|
|
|
{/* Proxy Mode */}
|
|
<div>
|
|
<h3 className="font-medium text-sm text-[var(--text-color)] mb-1.5 inline-flex items-center gap-2">
|
|
<Icons.Globe size={16} className="text-[var(--accent-color)]" />
|
|
代理播放模式
|
|
</h3>
|
|
<p className="text-xs text-[var(--text-color-secondary)] mb-3">控制视频播放时的网络请求策略</p>
|
|
<div className="grid grid-cols-1 sm:grid-cols-3 gap-2.5">
|
|
{(['retry', 'none', 'always'] as ProxyMode[]).map((mode) => {
|
|
const labels: Record<ProxyMode, [string, string]> = {
|
|
retry: ['智能重试 (推荐)', '直连优先,失败时尝试代理'],
|
|
none: ['仅直连', '不使用代理,失败则报错'],
|
|
always: ['总是代理', '所有请求都通过代理转发'],
|
|
};
|
|
return (
|
|
<button key={mode} onClick={() => onProxyModeChange(mode)} className={`${btnBase} ${proxyMode === mode ? activeBtn : inactiveBtn}`}>
|
|
<div className="font-semibold text-sm">{labels[mode][0]}</div>
|
|
<div className="text-xs opacity-75 mt-0.5">{labels[mode][1]}</div>
|
|
</button>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="border-t border-[var(--glass-border)]" />
|
|
|
|
{/* Danmaku Settings */}
|
|
<DanmakuSettings
|
|
danmakuApiUrl={props.danmakuApiUrl}
|
|
onDanmakuApiUrlChange={props.onDanmakuApiUrlChange}
|
|
danmakuOpacity={props.danmakuOpacity}
|
|
onDanmakuOpacityChange={props.onDanmakuOpacityChange}
|
|
danmakuFontSize={props.danmakuFontSize}
|
|
onDanmakuFontSizeChange={props.onDanmakuFontSizeChange}
|
|
danmakuDisplayArea={props.danmakuDisplayArea}
|
|
onDanmakuDisplayAreaChange={props.onDanmakuDisplayAreaChange}
|
|
showDanmakuApi={props.showDanmakuApi}
|
|
/>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|