import clsx from 'clsx'; import React, { useState } from 'react'; import { useRouter } from 'next/navigation'; import { PiUserCircle, PiUserCircleCheck, PiGear } from 'react-icons/pi'; import { PiSun, PiMoon } from 'react-icons/pi'; import { TbSunMoon } from 'react-icons/tb'; import { invoke, PermissionState } from '@tauri-apps/api/core'; import { isTauriAppPlatform, isWebAppPlatform } from '@/services/environment'; import { DOWNLOAD_READEST_URL } from '@/services/constants'; import { useAuth } from '@/context/AuthContext'; import { useEnv } from '@/context/EnvContext'; import { useThemeStore } from '@/store/themeStore'; import { useQuotaStats } from '@/hooks/useQuotaStats'; import { useSettingsStore } from '@/store/settingsStore'; import { useTranslation } from '@/hooks/useTranslation'; import { useResponsiveSize } from '@/hooks/useResponsiveSize'; import { navigateToLogin, navigateToProfile } from '@/utils/nav'; import { tauriHandleSetAlwaysOnTop, tauriHandleToggleFullScreen } from '@/utils/window'; import { optInTelemetry, optOutTelemetry } from '@/utils/telemetry'; import { setAboutDialogVisible } from '@/components/AboutWindow'; import { setMigrateDataDirDialogVisible } from '@/app/library/components/MigrateDataWindow'; import { saveSysSettings } from '@/helpers/settings'; import UserAvatar from '@/components/UserAvatar'; import MenuItem from '@/components/MenuItem'; import Quota from '@/components/Quota'; import Menu from '@/components/Menu'; interface SettingsMenuProps { setIsDropdownOpen?: (isOpen: boolean) => void; } interface Permissions { postNotification: PermissionState; } const SettingsMenu: React.FC = ({ setIsDropdownOpen }) => { const _ = useTranslation(); const router = useRouter(); const { envConfig, appService } = useEnv(); const { user } = useAuth(); const { userProfilePlan, quotas } = useQuotaStats(true); const { themeMode, setThemeMode } = useThemeStore(); const { settings, setSettingsDialogOpen } = useSettingsStore(); const [isAutoUpload, setIsAutoUpload] = useState(settings.autoUpload); const [isAutoCheckUpdates, setIsAutoCheckUpdates] = useState(settings.autoCheckUpdates); const [isAlwaysOnTop, setIsAlwaysOnTop] = useState(settings.alwaysOnTop); const [isAlwaysShowStatusBar, setIsAlwaysShowStatusBar] = useState(settings.alwaysShowStatusBar); const [isScreenWakeLock, setIsScreenWakeLock] = useState(settings.screenWakeLock); const [isOpenLastBooks, setIsOpenLastBooks] = useState(settings.openLastBooks); const [isAutoImportBooksOnOpen, setIsAutoImportBooksOnOpen] = useState( settings.autoImportBooksOnOpen, ); const [isTelemetryEnabled, setIsTelemetryEnabled] = useState(settings.telemetryEnabled); const [alwaysInForeground, setAlwaysInForeground] = useState(settings.alwaysInForeground); const [savedBookCoverForLockScreen, setSavedBookCoverForLockScreen] = useState( settings.savedBookCoverForLockScreen || '', ); const iconSize = useResponsiveSize(16); const showAboutReadest = () => { setAboutDialogVisible(true); setIsDropdownOpen?.(false); }; const downloadReadest = () => { window.open(DOWNLOAD_READEST_URL, '_blank'); setIsDropdownOpen?.(false); }; const handleUserLogin = () => { navigateToLogin(router); setIsDropdownOpen?.(false); }; const handleUserProfile = () => { navigateToProfile(router); setIsDropdownOpen?.(false); }; const cycleThemeMode = () => { const nextMode = themeMode === 'auto' ? 'light' : themeMode === 'light' ? 'dark' : 'auto'; setThemeMode(nextMode); }; const handleReloadPage = () => { window.location.reload(); setIsDropdownOpen?.(false); }; const handleFullScreen = () => { tauriHandleToggleFullScreen(); setIsDropdownOpen?.(false); }; const toggleOpenInNewWindow = () => { saveSysSettings(envConfig, 'openBookInNewWindow', !settings.openBookInNewWindow); setIsDropdownOpen?.(false); }; const toggleAlwaysOnTop = () => { const newValue = !settings.alwaysOnTop; saveSysSettings(envConfig, 'alwaysOnTop', newValue); setIsAlwaysOnTop(newValue); tauriHandleSetAlwaysOnTop(newValue); setIsDropdownOpen?.(false); }; const toggleAlwaysShowStatusBar = () => { const newValue = !settings.alwaysShowStatusBar; saveSysSettings(envConfig, 'alwaysShowStatusBar', newValue); setIsAlwaysShowStatusBar(newValue); }; const toggleAutoUploadBooks = () => { const newValue = !settings.autoUpload; saveSysSettings(envConfig, 'autoUpload', newValue); setIsAutoUpload(newValue); if (newValue && !user) { navigateToLogin(router); } }; const toggleAutoImportBooksOnOpen = () => { const newValue = !settings.autoImportBooksOnOpen; saveSysSettings(envConfig, 'autoImportBooksOnOpen', newValue); setIsAutoImportBooksOnOpen(newValue); }; const toggleAutoCheckUpdates = () => { const newValue = !settings.autoCheckUpdates; saveSysSettings(envConfig, 'autoCheckUpdates', newValue); setIsAutoCheckUpdates(newValue); }; const toggleScreenWakeLock = () => { const newValue = !settings.screenWakeLock; saveSysSettings(envConfig, 'screenWakeLock', newValue); setIsScreenWakeLock(newValue); }; const toggleOpenLastBooks = () => { const newValue = !settings.openLastBooks; saveSysSettings(envConfig, 'openLastBooks', newValue); setIsOpenLastBooks(newValue); }; const toggleTelemetry = () => { const newValue = !settings.telemetryEnabled; saveSysSettings(envConfig, 'telemetryEnabled', newValue); setIsTelemetryEnabled(newValue); if (newValue) { optInTelemetry(); } else { optOutTelemetry(); } }; const handleUpgrade = () => { navigateToProfile(router); setIsDropdownOpen?.(false); }; const handleSetRootDir = () => { setMigrateDataDirDialogVisible(true); setIsDropdownOpen?.(false); }; const openSettingsDialog = () => { setIsDropdownOpen?.(false); setSettingsDialogOpen(true); }; const handleSetSavedBookCoverForLockScreen = () => { const newValue = settings.savedBookCoverForLockScreen ? '' : 'default'; saveSysSettings(envConfig, 'savedBookCoverForLockScreen', newValue); setSavedBookCoverForLockScreen(newValue); }; const toggleAlwaysInForeground = async () => { const requestAlwaysInForeground = !settings.alwaysInForeground; if (requestAlwaysInForeground) { let permission = await invoke('plugin:native-tts|checkPermissions'); if (permission.postNotification !== 'granted') { permission = await invoke('plugin:native-tts|requestPermissions', { permissions: ['postNotification'], }); } if (permission.postNotification !== 'granted') return; } saveSysSettings(envConfig, 'alwaysInForeground', requestAlwaysInForeground); setAlwaysInForeground(requestAlwaysInForeground); }; const avatarUrl = user?.user_metadata?.['picture'] || user?.user_metadata?.['avatar_url']; const userFullName = user?.user_metadata?.['full_name']; const userDisplayName = userFullName ? userFullName.split(' ')[0] : null; const themeModeLabel = themeMode === 'dark' ? _('Dark Mode') : themeMode === 'light' ? _('Light Mode') : _('Auto Mode'); return ( {user ? ( ) : ( PiUserCircleCheck ) } >
) : ( )} {isTauriAppPlatform() && !appService?.isMobile && ( )} {isTauriAppPlatform() && ( )} {appService?.hasUpdater && ( )} {appService?.hasWindow && ( )} {appService?.hasWindow && } {appService?.hasWindow && ( )} {appService?.isMobileApp && ( )} {appService?.isAndroidApp && ( )} {appService?.canCustomizeRootDir && ( <>
    {appService?.isAndroidApp && ( )}
)} {user && userProfilePlan === 'free' && ( )} {isWebAppPlatform() && }
); }; export default SettingsMenu;