Refactor code structure for improved readability and maintainability

This commit is contained in:
shuaiplus
2026-04-29 03:23:04 +08:00
parent 29a846c562
commit 85147e1569
14 changed files with 2748 additions and 881 deletions
@@ -25,8 +25,13 @@ interface AppAuthenticatedShellProps {
mainRoutesProps: AppMainRoutesProps;
}
function isAdminProfile(profile: Profile | null): boolean {
return String(profile?.role || '').toLowerCase() === 'admin';
}
export default function AppAuthenticatedShell(props: AppAuthenticatedShellProps) {
const routeAnimationKey = props.isImportRoute ? props.importRoute : props.location;
const isAdmin = isAdminProfile(props.profile);
return (
<div className="app-page">
@@ -83,7 +88,7 @@ export default function AppAuthenticatedShell(props: AppAuthenticatedShellProps)
<SendIcon size={16} />
<span>{t('nav_sends')}</span>
</Link>
{props.profile?.role === 'admin' && (
{isAdmin && (
<Link href="/admin" className={`side-link ${props.location === '/admin' ? 'active' : ''}`}>
<ShieldUser size={16} />
<span>{t('nav_admin_panel')}</span>
@@ -97,7 +102,7 @@ export default function AppAuthenticatedShell(props: AppAuthenticatedShellProps)
<Shield size={16} />
<span>{t('nav_device_management')}</span>
</Link>
{props.profile?.role === 'admin' && (
{isAdmin && (
<Link href="/backup" className={`side-link ${props.location === '/backup' ? 'active' : ''}`}>
<Cloud size={16} />
<span>{t('nav_backup_strategy')}</span>
+4 -3
View File
@@ -129,6 +129,7 @@ export interface AppMainRoutesProps {
export default function AppMainRoutes(props: AppMainRoutesProps) {
const importRoutePaths = [props.importRoute, '/tools/import', '/tools/import-export', '/tools/import-data', '/import', '/import-export'] as const;
const isAdmin = String(props.profile?.role || '').toLowerCase() === 'admin';
const importPageContent = (
<Suspense fallback={<RouteContentFallback />}>
<ImportPage
@@ -262,13 +263,13 @@ export default function AppMainRoutes(props: AppMainRoutesProps) {
<ArrowUpDown size={18} />
<span>{t('nav_import_export')}</span>
</Link>
{props.profile.role === 'admin' && (
{isAdmin && (
<Link href="/admin" className="mobile-settings-link">
<ShieldUser size={18} />
<span>{t('nav_admin_panel')}</span>
</Link>
)}
{props.profile.role === 'admin' && (
{isAdmin && (
<Link href="/backup" className="mobile-settings-link">
<Cloud size={18} />
<span>{t('nav_backup_strategy')}</span>
@@ -340,7 +341,7 @@ export default function AppMainRoutes(props: AppMainRoutesProps) {
<LegacyBackupRedirect onNavigate={props.onNavigate} />
</Route>
<Route path="/backup">
{props.profile?.role === 'admin' ? (
{isAdmin ? (
<div className="stack">
{props.mobileLayout && (
<div className="mobile-settings-subhead">
+27 -5
View File
@@ -1,9 +1,9 @@
import { useEffect, useMemo, useState } from 'preact/hooks';
import { Clipboard, KeyRound, Lightbulb, RefreshCw, ShieldCheck, ShieldOff } from 'lucide-preact';
import { Clipboard, KeyRound, RefreshCw, ShieldCheck, ShieldOff } from 'lucide-preact';
import { copyTextToClipboard } from '@/lib/clipboard';
import qrcode from 'qrcode-generator';
import type { Profile } from '@/lib/types';
import { t } from '@/lib/i18n';
import { AVAILABLE_LOCALES, getLocale, setLocale, t, type Locale } from '@/lib/i18n';
import ConfirmDialog from '@/components/ConfirmDialog';
interface SettingsPageProps {
@@ -79,6 +79,7 @@ export default function SettingsPage(props: SettingsPageProps) {
const [masterPasswordPrompt, setMasterPasswordPrompt] = useState<null | 'recovery' | 'apiKey' | 'rotateApiKey'>(null);
const [masterPasswordPromptValue, setMasterPasswordPromptValue] = useState('');
const [masterPasswordPromptSubmitting, setMasterPasswordPromptSubmitting] = useState(false);
const [selectedLocale, setSelectedLocale] = useState<Locale>(() => getLocale());
useEffect(() => {
clearLegacyTotpSetupSecrets();
@@ -167,6 +168,13 @@ export default function SettingsPage(props: SettingsPageProps) {
return parsed.toLocaleString();
}
async function changeLocale(next: Locale): Promise<void> {
if (next === getLocale()) return;
setSelectedLocale(next);
await setLocale(next);
window.location.reload();
}
return (
<div className="settings-modules-grid">
<section className="card settings-module">
@@ -200,9 +208,23 @@ export default function SettingsPage(props: SettingsPageProps) {
</div>
</section>
<section className="card settings-module settings-module-placeholder">
<Lightbulb size={26} aria-hidden="true" />
<span>{t('txt_in_planning')}</span>
<section className="card settings-module">
<h3>{t('txt_language')}</h3>
<label className="field">
<span>{t('txt_display_language')}</span>
<select
className="input"
value={selectedLocale}
onInput={(e) => void changeLocale((e.currentTarget as HTMLSelectElement).value as Locale)}
>
{AVAILABLE_LOCALES.map((option) => (
<option key={option.value} value={option.value}>
{option.label}
</option>
))}
</select>
<div className="field-help">{t('txt_language_saved_locally')}</div>
</label>
</section>
<section className="card settings-module">