diff --git a/src/locales/ar.json b/src/locales/ar.json index 0f6a2020..bb568c1f 100644 --- a/src/locales/ar.json +++ b/src/locales/ar.json @@ -913,6 +913,11 @@ "title": "الإعدادات", "description": "إدارة إعدادات {{appName}} الخاصة بك", "deleteAccount": "حذف الحساب", + "groups": { + "account": "الحساب", + "app": "التطبيق", + "system": "النظام" + }, "sections": { "profile": "الملف الشخصي", "profileDesc": "اسم العرض والسيرة الذاتية والصورة الرمزية والتحقق.", diff --git a/src/locales/en.json b/src/locales/en.json index 13af3ab7..f68c3bd5 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1376,6 +1376,11 @@ "title": "Settings", "description": "Manage your {{appName}} settings", "deleteAccount": "Delete account", + "groups": { + "account": "Account", + "app": "App", + "system": "System" + }, "sections": { "profile": "Profile", "profileDesc": "Display name, bio, avatar, and verification.", diff --git a/src/locales/es.json b/src/locales/es.json index 6f7cbd5e..9ab8bfdd 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -923,6 +923,11 @@ "title": "Ajustes", "description": "Administra tus ajustes de {{appName}}", "deleteAccount": "Eliminar cuenta", + "groups": { + "account": "Cuenta", + "app": "Aplicación", + "system": "Sistema" + }, "sections": { "profile": "Perfil", "profileDesc": "Nombre, biografía, avatar y verificación.", diff --git a/src/locales/fa.json b/src/locales/fa.json index a75e7309..a4224927 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -923,6 +923,11 @@ "title": "تنظیمات", "description": "مدیریت تنظیمات {{appName}} شما", "deleteAccount": "حذف حساب", + "groups": { + "account": "حساب", + "app": "برنامه", + "system": "سیستم" + }, "sections": { "profile": "نمایه", "profileDesc": "نام نمایشی، بیوگرافی، آواتار و تأیید هویت.", diff --git a/src/locales/fr.json b/src/locales/fr.json index 971f96cd..287cabe4 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -1362,6 +1362,11 @@ "title": "Paramètres", "description": "Gérez vos paramètres {{appName}}", "deleteAccount": "Supprimer le compte", + "groups": { + "account": "Compte", + "app": "Application", + "system": "Système" + }, "sections": { "profile": "Profil", "profileDesc": "Nom d'affichage, biographie, avatar et vérification.", diff --git a/src/locales/hi.json b/src/locales/hi.json index 99ac3918..57de7480 100644 --- a/src/locales/hi.json +++ b/src/locales/hi.json @@ -1365,6 +1365,11 @@ "title": "सेटिंग्स", "description": "अपनी {{appName}} सेटिंग्स प्रबंधित करें", "deleteAccount": "अकाउंट डिलीट करें", + "groups": { + "account": "खाता", + "app": "ऐप", + "system": "सिस्टम" + }, "sections": { "profile": "प्रोफ़ाइल", "profileDesc": "डिस्प्ले नाम, बायो, अवतार, और सत्यापन।", diff --git a/src/locales/id.json b/src/locales/id.json index 31cfc808..ed02bc4f 100644 --- a/src/locales/id.json +++ b/src/locales/id.json @@ -1365,6 +1365,11 @@ "title": "Pengaturan", "description": "Kelola pengaturan {{appName}} Anda", "deleteAccount": "Hapus akun", + "groups": { + "account": "Akun", + "app": "Aplikasi", + "system": "Sistem" + }, "sections": { "profile": "Profil", "profileDesc": "Nama tampilan, bio, avatar, dan verifikasi.", diff --git a/src/locales/km.json b/src/locales/km.json index d1637420..c464d16d 100644 --- a/src/locales/km.json +++ b/src/locales/km.json @@ -923,6 +923,11 @@ "title": "ការកំណត់", "description": "គ្រប់គ្រងការកំណត់ {{appName}} របស់អ្នក", "deleteAccount": "លុបគណនី", + "groups": { + "account": "គណនី", + "app": "កម្មវិធី", + "system": "ប្រព័ន្ធ" + }, "sections": { "profile": "ប្រវត្តិរូប", "profileDesc": "ឈ្មោះបង្ហាញ ប្រវត្តិរូបសង្ខេប រូបតំណាង និងការផ្ទៀងផ្ទាត់។", diff --git a/src/locales/ps.json b/src/locales/ps.json index f4cdd4bd..3c06453c 100644 --- a/src/locales/ps.json +++ b/src/locales/ps.json @@ -925,6 +925,11 @@ "title": "تنظیمات", "description": "د {{appName}} تنظیماتو اداره کول", "deleteAccount": "حساب ړنګول", + "groups": { + "account": "حساب", + "app": "اپلیکیشن", + "system": "سیسټم" + }, "sections": { "profile": "پروفایل", "profileDesc": "د ښودنې نوم، بیوګرافي، اواتار، او تصدیق.", diff --git a/src/locales/pt.json b/src/locales/pt.json index 32688dcb..df63f018 100644 --- a/src/locales/pt.json +++ b/src/locales/pt.json @@ -1367,6 +1367,11 @@ "title": "Configurações", "description": "Gerencie suas configurações do {{appName}}", "deleteAccount": "Excluir conta", + "groups": { + "account": "Conta", + "app": "Aplicativo", + "system": "Sistema" + }, "sections": { "profile": "Perfil", "profileDesc": "Nome de exibição, biografia, avatar e verificação.", diff --git a/src/locales/ru.json b/src/locales/ru.json index ab13f5da..ba04b467 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -1367,6 +1367,11 @@ "title": "Настройки", "description": "Управляйте настройками {{appName}}", "deleteAccount": "Удалить аккаунт", + "groups": { + "account": "Аккаунт", + "app": "Приложение", + "system": "Система" + }, "sections": { "profile": "Профиль", "profileDesc": "Имя для отображения, биография, аватар и верификация.", diff --git a/src/locales/sn.json b/src/locales/sn.json index 9bcdaba5..4a7b05b1 100644 --- a/src/locales/sn.json +++ b/src/locales/sn.json @@ -925,6 +925,11 @@ "title": "Marongero", "description": "Tarisira marongero ako e{{appName}}", "deleteAccount": "Bvisa akaunti", + "groups": { + "account": "Akaundi", + "app": "Puroguramu", + "system": "Sisitimu" + }, "sections": { "profile": "Profile", "profileDesc": "Zita rinoratidzwa, nhoroondo, mufananidzo, nokutsigirwa.", diff --git a/src/locales/sw.json b/src/locales/sw.json index f02196e9..0c8eaec8 100644 --- a/src/locales/sw.json +++ b/src/locales/sw.json @@ -1364,6 +1364,11 @@ "title": "Mipangilio", "description": "Simamia mipangilio yako ya {{appName}}", "deleteAccount": "Futa akaunti", + "groups": { + "account": "Akaunti", + "app": "Programu", + "system": "Mfumo" + }, "sections": { "profile": "Wasifu", "profileDesc": "Jina la kuonyesha, wasifu, picha, na uthibitisho.", diff --git a/src/locales/tr.json b/src/locales/tr.json index 8fd3aa79..da61c295 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -1366,6 +1366,11 @@ "title": "Ayarlar", "description": "{{appName}} ayarlarınızı yönetin", "deleteAccount": "Hesabı sil", + "groups": { + "account": "Hesap", + "app": "Uygulama", + "system": "Sistem" + }, "sections": { "profile": "Profil", "profileDesc": "Görünen ad, biyografi, avatar ve doğrulama.", diff --git a/src/locales/zh-Hant.json b/src/locales/zh-Hant.json index 4125f16b..962664b0 100644 --- a/src/locales/zh-Hant.json +++ b/src/locales/zh-Hant.json @@ -925,6 +925,11 @@ "title": "設定", "description": "管理你的 {{appName}} 設定", "deleteAccount": "刪除賬戶", + "groups": { + "account": "帳戶", + "app": "應用程式", + "system": "系統" + }, "sections": { "profile": "個人資料", "profileDesc": "顯示名稱、簡介、頭像和驗證。", diff --git a/src/locales/zh.json b/src/locales/zh.json index c41e2d98..00708869 100644 --- a/src/locales/zh.json +++ b/src/locales/zh.json @@ -925,6 +925,11 @@ "title": "设置", "description": "管理你的 {{appName}} 设置", "deleteAccount": "删除账户", + "groups": { + "account": "账户", + "app": "应用", + "system": "系统" + }, "sections": { "profile": "个人资料", "profileDesc": "显示名称、简介、头像和验证。", diff --git a/src/pages/AdvancedSettingsPage.tsx b/src/pages/AdvancedSettingsPage.tsx index 0c663e68..ced4b46a 100644 --- a/src/pages/AdvancedSettingsPage.tsx +++ b/src/pages/AdvancedSettingsPage.tsx @@ -37,11 +37,11 @@ export function AdvancedSettingsPage() { } /> -
+
{/* Intro */} -
-

{t('settings.advanced.powerUserHeading')}

-

+

+

{t('settings.advanced.powerUserHeading')}

+

{t('settings.advanced.intro')}

diff --git a/src/pages/AppearanceSettingsPage.tsx b/src/pages/AppearanceSettingsPage.tsx index 7cbb1343..b3a1744b 100644 --- a/src/pages/AppearanceSettingsPage.tsx +++ b/src/pages/AppearanceSettingsPage.tsx @@ -1,5 +1,5 @@ import { useSeoMeta } from '@unhead/react'; -import { Monitor, Moon, Sun } from 'lucide-react'; +import { Check, Monitor, Moon, Sun } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { PageHeader } from '@/components/PageHeader'; import { useAppContext } from '@/hooks/useAppContext'; @@ -60,52 +60,47 @@ export function AppearanceSettingsPage() { } /> -
+
{/* Intro */} -
-

{t('settings.appearance.colorMode')}

-

+

+

{t('settings.appearance.colorMode')}

+

{t('settings.appearance.intro')}

{/* Theme options */} -
+
{themeOptions.map((option) => ( ))} diff --git a/src/pages/LanguageSettingsPage.tsx b/src/pages/LanguageSettingsPage.tsx index c60c1b52..a046ed78 100644 --- a/src/pages/LanguageSettingsPage.tsx +++ b/src/pages/LanguageSettingsPage.tsx @@ -63,14 +63,18 @@ export function LanguageSettingsPage() { } /> -
-
-

+

+
+

{t('language.intro')}

-
    +
      {SUPPORTED_LANGUAGES.map((language) => { const selected = language.code === currentLng; const rtl = isRTLLanguage(language.code); @@ -82,34 +86,25 @@ export function LanguageSettingsPage() { aria-checked={selected} onClick={() => handleSelect(language.code)} className={cn( - 'w-full flex items-center gap-4 px-4 py-3.5 rounded-xl border-2 transition-all duration-200', - 'focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring', - selected - ? 'border-primary bg-primary/5 shadow-sm' - : 'border-border/50 hover:border-primary/40 hover:bg-muted/30', + 'w-full flex items-center gap-4 px-3.5 py-3 transition-colors', + 'hover:bg-muted/50 active:bg-muted/70', + 'focus-visible:outline-none focus-visible:bg-muted/50', )} > -
      +

      {language.nativeName}

      -

      +

      {language.code}

      {selected && ( -
    -

    +

    {t('language.translationNote')}

diff --git a/src/pages/NetworkSettingsPage.tsx b/src/pages/NetworkSettingsPage.tsx index 359584e7..7dcebb47 100644 --- a/src/pages/NetworkSettingsPage.tsx +++ b/src/pages/NetworkSettingsPage.tsx @@ -50,28 +50,25 @@ export function NetworkSettingsPage() { } /> -
+
{/* Intro */} -
-

{t('settings.network.connectionsHeading')}

-

+

+

{t('settings.network.connectionsHeading')}

+

{t('settings.network.connectionsIntro')}

{/* Low-Bandwidth Mode */} -
-
-

{t('settings.network.lowBandwidthHeading')}

-
-
-
+
+

{t('settings.network.lowBandwidthHeading')}

+
-
@@ -86,13 +83,13 @@ export function NetworkSettingsPage() { {/* Image Proxy — independent of Low-Bandwidth. Controls whether images are fetched from a downsizing proxy. */} -
+
-
@@ -156,40 +153,27 @@ export function NetworkSettingsPage() { )}
-
+
{/* Relays */} -
-
-

{t('settings.network.relays')}

-
-
-
- -
-
+
+

{t('settings.network.relays')}

+ +
{/* Blossom Servers */} -
-
-

{t('settings.network.blossomServers')}

-
-
-
- -
-
+
+

{t('settings.network.blossomServers')}

+ +
{/* Image Upload Quality */} -
-
-

{t('settings.network.imageUploads')}

-
-
-
+
+

{t('settings.network.imageUploads')}

+
- -

+ +

{t('settings.network.uploadQualityDesc')}

@@ -210,7 +194,7 @@ export function NetworkSettingsPage() { ))}
-
+
); diff --git a/src/pages/SettingsPage.tsx b/src/pages/SettingsPage.tsx index aefdddc9..f434e0f3 100644 --- a/src/pages/SettingsPage.tsx +++ b/src/pages/SettingsPage.tsx @@ -1,12 +1,24 @@ import { useSeoMeta } from '@unhead/react'; import { lazy, Suspense, useState } from 'react'; -import { ChevronRight, Settings } from 'lucide-react'; +import { + ChevronRight, + Settings, + User, + BadgeCheck, + Palette, + Languages, + Wifi, + Bell, + SlidersHorizontal, + ShieldCheck, +} from 'lucide-react'; import { Link, useNavigate } from 'react-router-dom'; import { useTranslation } from 'react-i18next'; import { PageHeader } from '@/components/PageHeader'; import { useCurrentUser } from '@/hooks/useCurrentUser'; import { useAppContext } from '@/hooks/useAppContext'; import { isAdmin } from '@/lib/admins'; +import { cn } from '@/lib/utils'; const RequestToVanishDialog = lazy(() => import('@/components/RequestToVanishDialog').then(m => ({ default: m.RequestToVanishDialog }))); @@ -17,6 +29,12 @@ interface SettingsSection { /** i18n key under `settings.sections.*` for the row description. */ descriptionKey: string; path: string; + /** Icon rendered in the colored leading tile. */ + icon: React.ReactNode; + /** Tailwind classes for the icon tile background gradient. */ + tile: string; + /** Which visual group this row belongs to. */ + group: 'account' | 'app' | 'system'; requiresAuth?: boolean; /** When true, only shown to platform admins (see `isAdmin` in `@/lib/admins`). */ requiresAdmin?: boolean; @@ -28,6 +46,9 @@ const settingsSections: SettingsSection[] = [ labelKey: 'settings.sections.profile', descriptionKey: 'settings.sections.profileDesc', path: '/settings/profile', + icon: , + tile: 'bg-gradient-to-b from-blue-400 to-blue-600', + group: 'account', requiresAuth: true, }, { @@ -35,6 +56,9 @@ const settingsSections: SettingsSection[] = [ labelKey: 'settings.sections.verifier', descriptionKey: 'settings.sections.verifierDesc', path: '/settings/verifier', + icon: , + tile: 'bg-gradient-to-b from-emerald-400 to-emerald-600', + group: 'account', requiresAuth: true, }, { @@ -42,25 +66,37 @@ const settingsSections: SettingsSection[] = [ labelKey: 'settings.sections.appearance', descriptionKey: 'settings.sections.appearanceDesc', path: '/settings/appearance', + icon: , + tile: 'bg-gradient-to-b from-violet-400 to-violet-600', + group: 'app', }, { id: 'language', labelKey: 'settings.sections.language', descriptionKey: 'settings.sections.languageDesc', path: '/settings/language', - }, - { - id: 'network', - labelKey: 'settings.sections.network', - descriptionKey: 'settings.sections.networkDesc', - path: '/settings/network', - requiresAuth: true, + icon: , + tile: 'bg-gradient-to-b from-sky-400 to-sky-600', + group: 'app', }, { id: 'notifications', labelKey: 'settings.sections.notifications', descriptionKey: 'settings.sections.notificationsDesc', path: '/settings/notifications', + icon: , + tile: 'bg-gradient-to-b from-rose-400 to-rose-600', + group: 'app', + requiresAuth: true, + }, + { + id: 'network', + labelKey: 'settings.sections.network', + descriptionKey: 'settings.sections.networkDesc', + path: '/settings/network', + icon: , + tile: 'bg-gradient-to-b from-amber-400 to-amber-600', + group: 'system', requiresAuth: true, }, { @@ -68,17 +104,25 @@ const settingsSections: SettingsSection[] = [ labelKey: 'settings.sections.advanced', descriptionKey: 'settings.sections.advancedDesc', path: '/settings/advanced', + icon: , + tile: 'bg-gradient-to-b from-slate-400 to-slate-600', + group: 'system', }, { id: 'organizers', labelKey: 'settings.sections.organizers', descriptionKey: 'settings.sections.organizersDesc', path: '/organizers', + icon: , + tile: 'bg-gradient-to-b from-teal-400 to-teal-600', + group: 'system', requiresAuth: true, requiresAdmin: true, }, ]; +const GROUP_ORDER: Array = ['account', 'app', 'system']; + export function SettingsPage() { const { t } = useTranslation(); const { user } = useCurrentUser(); @@ -86,7 +130,6 @@ export function SettingsPage() { const navigate = useNavigate(); const [deleteAccountOpen, setDeleteAccountOpen] = useState(false); - useSeoMeta({ title: `${t('settings.title')} | ${config.appName}`, description: t('settings.description', { appName: config.appName }), @@ -98,31 +141,60 @@ export function SettingsPage() { return true; }); + const groups = GROUP_ORDER + .map((group) => ({ group, items: visibleSections.filter((s) => s.group === group) })) + .filter((g) => g.items.length > 0); + return (
} backTo="/" /> - {/* Settings list */} -