mirror of
https://github.com/KuekHaoYang/KVideo.git
synced 2026-08-22 12:13:43 +08:00
feat: remove Google Drive integration, associated hooks, components, API routes, and dependencies.
This commit is contained in:
@@ -1,141 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useSearchParams, useRouter } from 'next/navigation';
|
||||
import { useAuthStore, type LinuxDoUser } from '@/lib/store/auth-store';
|
||||
import { useHistoryStore } from '@/lib/store/history-store';
|
||||
import { useSearchHistoryStore } from '@/lib/store/search-history-store';
|
||||
|
||||
export function AccountSettings() {
|
||||
const [isHydrated, setIsHydrated] = useState(false);
|
||||
const searchParams = useSearchParams();
|
||||
const router = useRouter();
|
||||
const { user, isAuthenticated, login, logout } = useAuthStore();
|
||||
const { clearHistory } = useHistoryStore();
|
||||
const { clearSearchHistory } = useSearchHistoryStore();
|
||||
|
||||
// Wait for Zustand to hydrate from localStorage
|
||||
useEffect(() => {
|
||||
setIsHydrated(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
const authSuccess = searchParams.get('auth_success');
|
||||
const token = searchParams.get('token');
|
||||
const userStr = searchParams.get('user');
|
||||
|
||||
console.log('[AccountSettings] Checking URL params:', {
|
||||
authSuccess,
|
||||
hasToken: !!token,
|
||||
hasUser: !!userStr,
|
||||
});
|
||||
|
||||
if (authSuccess && token && userStr) {
|
||||
try {
|
||||
const userData = JSON.parse(userStr) as LinuxDoUser;
|
||||
console.log('[AccountSettings] Parsed user data:', {
|
||||
id: userData.id,
|
||||
username: userData.username,
|
||||
});
|
||||
|
||||
clearHistory();
|
||||
clearSearchHistory();
|
||||
login(userData, token);
|
||||
|
||||
console.log('[AccountSettings] Login complete, redirecting...');
|
||||
router.replace('/settings');
|
||||
} catch (e) {
|
||||
console.error('[AccountSettings] Failed to parse user data:', e);
|
||||
}
|
||||
}
|
||||
}, [searchParams, login, clearHistory, clearSearchHistory, router]);
|
||||
|
||||
const handleLogin = () => {
|
||||
clearHistory();
|
||||
clearSearchHistory();
|
||||
router.push('/api/oauth/authorize');
|
||||
};
|
||||
|
||||
const handleLogout = () => {
|
||||
logout();
|
||||
clearHistory();
|
||||
clearSearchHistory();
|
||||
};
|
||||
|
||||
// Don't render until hydrated to prevent flash
|
||||
if (!isHydrated) {
|
||||
return (
|
||||
<section className="space-y-6">
|
||||
<div className="flex items-center gap-3 pb-2 border-b border-[var(--glass-border)]">
|
||||
<svg className="w-6 h-6 text-[var(--accent-color)]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
|
||||
<circle cx="12" cy="7" r="4" />
|
||||
</svg>
|
||||
<h2 className="text-xl font-semibold text-[var(--text-color)]">账号</h2>
|
||||
</div>
|
||||
<div className="p-6 rounded-[var(--radius-2xl)] bg-[var(--glass-bg)] border border-[var(--glass-border)] backdrop-blur-xl">
|
||||
<div className="flex items-center justify-center text-[var(--text-color-secondary)]">加载中...</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="space-y-6">
|
||||
<div className="flex items-center gap-3 pb-2 border-b border-[var(--glass-border)]">
|
||||
<svg className="w-6 h-6 text-[var(--accent-color)]" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2">
|
||||
<path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" />
|
||||
<circle cx="12" cy="7" r="4" />
|
||||
</svg>
|
||||
<h2 className="text-xl font-semibold text-[var(--text-color)]">账号</h2>
|
||||
</div>
|
||||
|
||||
<div className="p-6 rounded-[var(--radius-2xl)] bg-[var(--glass-bg)] border border-[var(--glass-border)] backdrop-blur-xl shadow-[var(--shadow-md)]">
|
||||
{!isAuthenticated ? (
|
||||
<div className="flex flex-col items-center gap-4 text-center">
|
||||
<p className="text-[var(--text-color-secondary)]">登录 Linux DO 以同步您的账号信息</p>
|
||||
<button
|
||||
onClick={handleLogin}
|
||||
className="px-6 py-3 rounded-[var(--radius-2xl)] bg-[var(--accent-color)] text-white font-semibold hover:brightness-110 transition-all shadow-[var(--shadow-sm)] hover:shadow-[var(--shadow-md)] active:scale-95"
|
||||
>
|
||||
使用 Linux DO 登录
|
||||
</button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="flex flex-col gap-6">
|
||||
<div className="flex items-center gap-4">
|
||||
<img
|
||||
src={user?.avatar_template.replace('{size}', '100')}
|
||||
alt={user?.name || user?.username}
|
||||
className="w-16 h-16 rounded-[var(--radius-full)] border-2 border-[var(--glass-border)]"
|
||||
/>
|
||||
<div>
|
||||
<h3 className="text-lg font-bold text-[var(--text-color)]">{user?.name || user?.username}</h3>
|
||||
<p className="text-[var(--text-color-secondary)]">@{user?.username}</p>
|
||||
<div className="flex gap-2 mt-2">
|
||||
<span className="px-3 py-1 text-xs font-medium rounded-[var(--radius-full)] bg-[var(--accent-color)] text-white">
|
||||
Trust Level {user?.trust_level}
|
||||
</span>
|
||||
{user?.active && (
|
||||
<span className="px-3 py-1 text-xs font-medium rounded-[var(--radius-full)] bg-green-500/20 text-green-600 border border-green-500/30">
|
||||
Active
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="pt-4 border-t border-[var(--glass-border)]">
|
||||
<button
|
||||
onClick={handleLogout}
|
||||
className="w-full px-4 py-2 text-red-500 hover:bg-red-500/10 rounded-[var(--radius-2xl)] transition-colors font-medium"
|
||||
>
|
||||
退出登录
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
}
|
||||
@@ -1,139 +0,0 @@
|
||||
'use client';
|
||||
|
||||
import { useSync } from '@/lib/hooks/useSync';
|
||||
import { Icons } from '@/components/ui/Icon';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
|
||||
export function SyncSettings() {
|
||||
const {
|
||||
user,
|
||||
isInitialized,
|
||||
isLoading,
|
||||
error,
|
||||
lastSynced,
|
||||
autoSync,
|
||||
toggleAutoSync,
|
||||
signIn,
|
||||
signOut,
|
||||
syncNow,
|
||||
restoreNow
|
||||
} = useSync();
|
||||
|
||||
if (!isInitialized) {
|
||||
if (error) {
|
||||
return (
|
||||
<div className="bg-[var(--glass-bg)] border border-[var(--glass-border)] rounded-[var(--radius-2xl)] shadow-[var(--shadow-sm)] p-6">
|
||||
<h2 className="text-xl font-semibold text-[var(--text-color)] mb-4 flex items-center gap-2">
|
||||
<Icons.Cloud size={24} />
|
||||
<span>云端同步 (Google Drive)</span>
|
||||
</h2>
|
||||
<div className="p-4 bg-yellow-50 dark:bg-yellow-900/20 border border-yellow-200 dark:border-yellow-800 rounded-[var(--radius-xl)] text-sm text-yellow-600 dark:text-yellow-400">
|
||||
<p className="font-medium mb-2">配置缺失</p>
|
||||
<p className="opacity-90">请在 .env.local 文件中添加 Google Client ID:</p>
|
||||
<code className="block mt-2 p-2 bg-black/10 dark:bg-white/10 rounded">
|
||||
NEXT_PUBLIC_GOOGLE_CLIENT_ID=你的客户端ID
|
||||
</code>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-[var(--glass-bg)] border border-[var(--glass-border)] rounded-[var(--radius-2xl)] shadow-[var(--shadow-sm)] p-6">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="animate-spin rounded-full h-5 w-5 border-2 border-[var(--accent-color)] border-t-transparent"></div>
|
||||
<span className="text-[var(--text-color-secondary)]">正在初始化同步服务...</span>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="bg-[var(--glass-bg)] border border-[var(--glass-border)] rounded-[var(--radius-2xl)] shadow-[var(--shadow-sm)] p-6">
|
||||
<div className="flex items-center justify-between mb-4">
|
||||
<h2 className="text-xl font-semibold text-[var(--text-color)] flex items-center gap-2">
|
||||
<Icons.Cloud size={24} />
|
||||
<span>云端同步 (Google Drive)</span>
|
||||
</h2>
|
||||
{user && (
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm text-[var(--text-color-secondary)]">
|
||||
{user.email}
|
||||
</span>
|
||||
<Button
|
||||
variant="ghost"
|
||||
onClick={signOut}
|
||||
className="text-red-500 hover:text-red-600 hover:bg-red-50 dark:hover:bg-red-900/20"
|
||||
>
|
||||
退出
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{error && (
|
||||
<div className="mb-4 p-3 bg-red-50 dark:bg-red-900/20 border border-red-200 dark:border-red-800 rounded-[var(--radius-xl)] text-sm text-red-600 dark:text-red-400">
|
||||
{error}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!user ? (
|
||||
<div className="text-center py-6">
|
||||
<p className="text-[var(--text-color-secondary)] mb-4">
|
||||
登录 Google 账号以在设备间同步您的设置和历史记录。
|
||||
数据将存储在您 Google Drive 的专用应用文件夹中。
|
||||
</p>
|
||||
<Button onClick={signIn} variant="primary" className="w-full sm:w-auto">
|
||||
<Icons.Google className="mr-2" size={20} />
|
||||
连接 Google Drive
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between p-4 bg-[var(--glass-bg)] border border-[var(--glass-border)] rounded-[var(--radius-xl)]">
|
||||
<div>
|
||||
<p className="font-medium text-[var(--text-color)]">自动同步</p>
|
||||
<p className="text-sm text-[var(--text-color-secondary)]">
|
||||
更改设置或观看视频时自动同步
|
||||
</p>
|
||||
</div>
|
||||
<label className="relative inline-flex items-center cursor-pointer">
|
||||
<input
|
||||
type="checkbox"
|
||||
className="sr-only peer"
|
||||
checked={autoSync}
|
||||
onChange={(e) => toggleAutoSync(e.target.checked)}
|
||||
/>
|
||||
<div className="w-11 h-6 bg-gray-200 peer-focus:outline-none peer-focus:ring-4 peer-focus:ring-blue-300 dark:peer-focus:ring-blue-800 rounded-full peer dark:bg-gray-700 peer-checked:after:translate-x-full peer-checked:after:border-white after:content-[''] after:absolute after:top-[2px] after:left-[2px] after:bg-white after:border-gray-300 after:border after:rounded-full after:h-5 after:w-5 after:transition-all dark:border-gray-600 peer-checked:bg-[var(--accent-color)]"></div>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-3">
|
||||
<Button
|
||||
onClick={syncNow}
|
||||
disabled={isLoading}
|
||||
className="flex-1"
|
||||
variant="secondary"
|
||||
>
|
||||
{isLoading ? '同步中...' : '立即同步 (上传)'}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={restoreNow}
|
||||
disabled={isLoading}
|
||||
className="flex-1"
|
||||
variant="secondary"
|
||||
>
|
||||
{isLoading ? '同步中...' : '立即恢复 (下载)'}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{lastSynced && (
|
||||
<p className="text-xs text-center text-[var(--text-color-secondary)]">
|
||||
上次同步: {lastSynced.toLocaleString()}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user