mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-12 23:33:43 +08:00
214 lines
7.2 KiB
TypeScript
214 lines
7.2 KiB
TypeScript
'use client';
|
|
|
|
import { AddSourceModal } from '@/components/settings/AddSourceModal';
|
|
import { ExportModal } from '@/components/settings/ExportModal';
|
|
import { ImportModal } from '@/components/settings/ImportModal';
|
|
import { ConfirmDialog } from '@/components/ui/ConfirmDialog';
|
|
import { SourceSettings } from '@/components/settings/SourceSettings';
|
|
import { SortSettings } from '@/components/settings/SortSettings';
|
|
import { DataSettings } from '@/components/settings/DataSettings';
|
|
import { AccountSettings } from '@/components/settings/AccountSettings';
|
|
import { DisplaySettings } from '@/components/settings/DisplaySettings';
|
|
import { PlayerSettings } from '@/components/settings/PlayerSettings';
|
|
import { SettingsHeader } from '@/components/settings/SettingsHeader';
|
|
import { AppVersionSettings } from '@/components/settings/AppVersionSettings';
|
|
import { UserSourceSettings } from '@/components/settings/UserSourceSettings';
|
|
import { UserDanmakuSettings } from '@/components/settings/UserDanmakuSettings';
|
|
import { PermissionGate } from '@/components/PermissionGate';
|
|
import { hasPermission } from '@/lib/store/auth-store';
|
|
import { useSettingsPage } from './hooks/useSettingsPage';
|
|
|
|
export default function SettingsPage() {
|
|
const {
|
|
sources,
|
|
sortBy,
|
|
realtimeLatency,
|
|
searchDisplayMode,
|
|
fullscreenType,
|
|
seekStepSeconds,
|
|
isAddModalOpen,
|
|
isExportModalOpen,
|
|
isImportModalOpen,
|
|
isResetDialogOpen,
|
|
isRestoreDefaultsDialogOpen,
|
|
setIsAddModalOpen,
|
|
setIsExportModalOpen,
|
|
setIsImportModalOpen,
|
|
setIsResetDialogOpen,
|
|
setIsRestoreDefaultsDialogOpen,
|
|
handleSourcesChange,
|
|
handleAddSource,
|
|
handleSortChange,
|
|
handleExport,
|
|
handleImportFile,
|
|
handleImportLink,
|
|
subscriptions,
|
|
handleAddSubscription,
|
|
handleRemoveSubscription,
|
|
handleRefreshSubscription,
|
|
handleRestoreDefaults,
|
|
handleResetAll,
|
|
editingSource,
|
|
handleEditSource,
|
|
setEditingSource,
|
|
handleRealtimeLatencyChange,
|
|
handleSearchDisplayModeChange,
|
|
handleFullscreenTypeChange,
|
|
proxyMode,
|
|
handleProxyModeChange,
|
|
handleSeekStepSecondsChange,
|
|
rememberScrollPosition,
|
|
videoTogetherEnabled,
|
|
handleRememberScrollPositionChange,
|
|
handleVideoTogetherEnabledChange,
|
|
locale,
|
|
handleLocaleChange,
|
|
danmakuApiUrl,
|
|
handleDanmakuApiUrlChange,
|
|
danmakuOpacity,
|
|
handleDanmakuOpacityChange,
|
|
danmakuFontSize,
|
|
handleDanmakuFontSizeChange,
|
|
danmakuDisplayArea,
|
|
handleDanmakuDisplayAreaChange,
|
|
blockedCategories,
|
|
handleBlockedCategoriesChange,
|
|
} = useSettingsPage();
|
|
|
|
return (
|
|
<div className="min-h-screen bg-[var(--bg-color)] bg-[image:var(--bg-image)] bg-fixed">
|
|
<div className="container mx-auto px-4 py-8 max-w-4xl space-y-8">
|
|
{/* Header */}
|
|
<SettingsHeader />
|
|
|
|
<AppVersionSettings />
|
|
|
|
{/* Account Settings */}
|
|
<AccountSettings />
|
|
|
|
{/* Player Settings */}
|
|
<PermissionGate permission="player_settings">
|
|
<PlayerSettings
|
|
fullscreenType={fullscreenType}
|
|
onFullscreenTypeChange={handleFullscreenTypeChange}
|
|
proxyMode={proxyMode}
|
|
onProxyModeChange={handleProxyModeChange}
|
|
seekStepSeconds={seekStepSeconds}
|
|
onSeekStepSecondsChange={handleSeekStepSecondsChange}
|
|
videoTogetherEnabled={videoTogetherEnabled}
|
|
onVideoTogetherEnabledChange={handleVideoTogetherEnabledChange}
|
|
danmakuApiUrl={danmakuApiUrl}
|
|
onDanmakuApiUrlChange={handleDanmakuApiUrlChange}
|
|
danmakuOpacity={danmakuOpacity}
|
|
onDanmakuOpacityChange={handleDanmakuOpacityChange}
|
|
danmakuFontSize={danmakuFontSize}
|
|
onDanmakuFontSizeChange={handleDanmakuFontSizeChange}
|
|
danmakuDisplayArea={danmakuDisplayArea}
|
|
onDanmakuDisplayAreaChange={handleDanmakuDisplayAreaChange}
|
|
showDanmakuApi={hasPermission('danmaku_api')}
|
|
/>
|
|
</PermissionGate>
|
|
|
|
{/* Display Settings */}
|
|
<DisplaySettings
|
|
realtimeLatency={realtimeLatency}
|
|
searchDisplayMode={searchDisplayMode}
|
|
rememberScrollPosition={rememberScrollPosition}
|
|
onRealtimeLatencyChange={handleRealtimeLatencyChange}
|
|
onSearchDisplayModeChange={handleSearchDisplayModeChange}
|
|
onRememberScrollPositionChange={handleRememberScrollPositionChange}
|
|
locale={locale}
|
|
onLocaleChange={handleLocaleChange}
|
|
blockedCategories={blockedCategories}
|
|
onBlockedCategoriesChange={handleBlockedCategoriesChange}
|
|
/>
|
|
|
|
{/* Per-User Source Settings (visible to all logged-in users) */}
|
|
<UserSourceSettings />
|
|
|
|
{/* Per-User Danmaku Settings (visible to all logged-in users) */}
|
|
<UserDanmakuSettings />
|
|
|
|
{/* Source Management */}
|
|
<PermissionGate permission="source_management">
|
|
<SourceSettings
|
|
sources={sources}
|
|
onSourcesChange={handleSourcesChange}
|
|
onRestoreDefaults={() => setIsRestoreDefaultsDialogOpen(true)}
|
|
onAddSource={() => {
|
|
setEditingSource(null);
|
|
setIsAddModalOpen(true);
|
|
}}
|
|
onEditSource={handleEditSource}
|
|
/>
|
|
</PermissionGate>
|
|
|
|
{/* Sort Options */}
|
|
<SortSettings
|
|
sortBy={sortBy}
|
|
onSortChange={handleSortChange}
|
|
/>
|
|
|
|
{/* Data Management */}
|
|
<PermissionGate permission="data_management">
|
|
<DataSettings
|
|
onExport={() => setIsExportModalOpen(true)}
|
|
onImport={() => setIsImportModalOpen(true)}
|
|
onReset={() => setIsResetDialogOpen(true)}
|
|
/>
|
|
</PermissionGate>
|
|
</div>
|
|
|
|
{/* Modals */}
|
|
<AddSourceModal
|
|
isOpen={isAddModalOpen}
|
|
onClose={() => {
|
|
setIsAddModalOpen(false);
|
|
setEditingSource(null);
|
|
}}
|
|
onAdd={handleAddSource}
|
|
existingIds={sources.map(s => s.id)}
|
|
initialValues={editingSource}
|
|
/>
|
|
|
|
<ExportModal
|
|
isOpen={isExportModalOpen}
|
|
onClose={() => setIsExportModalOpen(false)}
|
|
onExport={handleExport}
|
|
/>
|
|
|
|
<ImportModal
|
|
isOpen={isImportModalOpen}
|
|
onClose={() => setIsImportModalOpen(false)}
|
|
onImportFile={handleImportFile}
|
|
onImportLink={handleImportLink}
|
|
subscriptions={subscriptions}
|
|
onAddSubscription={handleAddSubscription}
|
|
onRemoveSubscription={handleRemoveSubscription}
|
|
onRefreshSubscription={handleRefreshSubscription}
|
|
/>
|
|
|
|
<ConfirmDialog
|
|
isOpen={isRestoreDefaultsDialogOpen}
|
|
title="恢复默认源"
|
|
message="这将重置所有视频源为默认配置。自定义源将被删除。是否继续?"
|
|
confirmText="恢复"
|
|
cancelText="取消"
|
|
onConfirm={handleRestoreDefaults}
|
|
onCancel={() => setIsRestoreDefaultsDialogOpen(false)}
|
|
/>
|
|
|
|
<ConfirmDialog
|
|
isOpen={isResetDialogOpen}
|
|
title="清除所有数据"
|
|
message="这将删除所有设置、历史记录、Cookie 和缓存。此操作不可撤销。是否继续?"
|
|
confirmText="清除"
|
|
cancelText="取消"
|
|
onConfirm={handleResetAll}
|
|
onCancel={() => setIsResetDialogOpen(false)}
|
|
dangerous
|
|
/>
|
|
</div>
|
|
);
|
|
}
|