diff --git a/apps/readest-app/public/locales/ar/translation.json b/apps/readest-app/public/locales/ar/translation.json index 8b2278f1..83c007cd 100644 --- a/apps/readest-app/public/locales/ar/translation.json +++ b/apps/readest-app/public/locales/ar/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "فشل في تحليل ملف EPUB.", "This book format is not supported.": "هذا تنسيق الكتاب غير مدعوم.", "Unable to fetch the translation. Please log in first and try again.": "تعذر جلب الترجمة. يرجى تسجيل الدخول أولاً ثم المحاولة مرة أخرى.", - "Group": "تجميع" + "Group": "تجميع", + "Always on Top": "دائمًا في المقدمة" } diff --git a/apps/readest-app/public/locales/de/translation.json b/apps/readest-app/public/locales/de/translation.json index 7a4d6cbb..b066200a 100644 --- a/apps/readest-app/public/locales/de/translation.json +++ b/apps/readest-app/public/locales/de/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "Fehler beim Parsen der EPUB-Datei.", "This book format is not supported.": "Dieses Buchformat wird nicht unterstützt.", "Unable to fetch the translation. Please log in first and try again.": "Übersetzung konnte nicht abgerufen werden. Bitte zuerst anmelden und erneut versuchen.", - "Group": "Gruppieren" + "Group": "Gruppieren", + "Always on Top": "Immer im Vordergrund" } diff --git a/apps/readest-app/public/locales/el/translation.json b/apps/readest-app/public/locales/el/translation.json index 12fead21..22892735 100644 --- a/apps/readest-app/public/locales/el/translation.json +++ b/apps/readest-app/public/locales/el/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "Αποτυχία ανάλυσης του αρχείου EPUB.", "This book format is not supported.": "Αυτή η μορφή βιβλίου δεν υποστηρίζεται.", "Unable to fetch the translation. Please log in first and try again.": "Αδυναμία λήψης της μετάφρασης. Παρακαλώ συνδεθείτε πρώτα και δοκιμάστε ξανά.", - "Group": "Ομάδα" + "Group": "Ομάδα", + "Always on Top": "Πάντα στην κορυφή" } diff --git a/apps/readest-app/public/locales/es/translation.json b/apps/readest-app/public/locales/es/translation.json index f71f395c..e6a6cc5d 100644 --- a/apps/readest-app/public/locales/es/translation.json +++ b/apps/readest-app/public/locales/es/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "Error al analizar el archivo EPUB.", "This book format is not supported.": "Este formato de libro no es compatible.", "Unable to fetch the translation. Please log in first and try again.": "No se puede obtener la traducción. Por favor, inicia sesión primero e inténtalo de nuevo.", - "Group": "Grupo" + "Group": "Grupo", + "Always on Top": "Siempre en la parte superior" } diff --git a/apps/readest-app/public/locales/fr/translation.json b/apps/readest-app/public/locales/fr/translation.json index 01b5dc68..7f9ab99f 100644 --- a/apps/readest-app/public/locales/fr/translation.json +++ b/apps/readest-app/public/locales/fr/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "Échec de l'analyse du fichier EPUB.", "This book format is not supported.": "Ce format de livre n'est pas pris en charge.", "Unable to fetch the translation. Please log in first and try again.": "Impossible de récupérer la traduction. Veuillez d'abord vous connecter et réessayer.", - "Group": "Groupe" + "Group": "Groupe", + "Always on Top": "Toujours au-dessus" } diff --git a/apps/readest-app/public/locales/hi/translation.json b/apps/readest-app/public/locales/hi/translation.json index ed0bf573..45c1c6e4 100644 --- a/apps/readest-app/public/locales/hi/translation.json +++ b/apps/readest-app/public/locales/hi/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "EPUB फ़ाइल को पार्स करने में विफल।", "This book format is not supported.": "यह पुस्तक प्रारूप समर्थित नहीं है।", "Unable to fetch the translation. Please log in first and try again.": "अनुवाद प्राप्त करने में असमर्थ। कृपया पहले लॉग इन करें और पुनः प्रयास करें।", - "Group": "समूह" + "Group": "समूह", + "Always on Top": "सर्वोच्च पर हमेशा" } diff --git a/apps/readest-app/public/locales/id/translation.json b/apps/readest-app/public/locales/id/translation.json index 0e97b05f..c8d8e5cd 100644 --- a/apps/readest-app/public/locales/id/translation.json +++ b/apps/readest-app/public/locales/id/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "Gagal mengurai file EPUB.", "This book format is not supported.": "Format buku ini tidak didukung.", "Unable to fetch the translation. Please log in first and try again.": "Tidak dapat mengambil terjemahan. Silakan masuk terlebih dahulu dan coba lagi.", - "Group": "Grup" + "Group": "Grup", + "Always on Top": "Selalu di Atas" } diff --git a/apps/readest-app/public/locales/it/translation.json b/apps/readest-app/public/locales/it/translation.json index 2b1cf62d..8585889c 100644 --- a/apps/readest-app/public/locales/it/translation.json +++ b/apps/readest-app/public/locales/it/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "Impossibile analizzare il file EPUB.", "This book format is not supported.": "Questo formato di libro non è supportato.", "Unable to fetch the translation. Please log in first and try again.": "Impossibile recuperare la traduzione. Accedi prima e riprova.", - "Group": "Gruppo" + "Group": "Gruppo", + "Always on Top": "Sempre in primo piano" } diff --git a/apps/readest-app/public/locales/ja/translation.json b/apps/readest-app/public/locales/ja/translation.json index d8043354..7eaf2230 100644 --- a/apps/readest-app/public/locales/ja/translation.json +++ b/apps/readest-app/public/locales/ja/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "EPUBファイルの解析に失敗しました。", "This book format is not supported.": "この書籍形式はサポートされていません。", "Unable to fetch the translation. Please log in first and try again.": "翻訳を取得できません。まずログインして再試行してください。", - "Group": "グループ" + "Group": "グループ", + "Always on Top": "常に最前面" } diff --git a/apps/readest-app/public/locales/ko/translation.json b/apps/readest-app/public/locales/ko/translation.json index 0c876608..e32cef52 100644 --- a/apps/readest-app/public/locales/ko/translation.json +++ b/apps/readest-app/public/locales/ko/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "EPUB 파일 구문 분석 실패.", "This book format is not supported.": "이 책 형식은 지원되지 않습니다.", "Unable to fetch the translation. Please log in first and try again.": "번역을 가져올 수 없습니다. 먼저 로그인하고 다시 시도하세요.", - "Group": "그룹" + "Group": "그룹", + "Always on Top": "항상 위에" } diff --git a/apps/readest-app/public/locales/pl/translation.json b/apps/readest-app/public/locales/pl/translation.json index e3bd14f8..2041262a 100644 --- a/apps/readest-app/public/locales/pl/translation.json +++ b/apps/readest-app/public/locales/pl/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "Nie udało się przeanalizować pliku EPUB.", "This book format is not supported.": "Ten format książki nie jest obsługiwany.", "Unable to fetch the translation. Please log in first and try again.": "Nie można pobrać tłumaczenia. Proszę najpierw się zalogować i spróbować ponownie.", - "Group": "Grupa" + "Group": "Grupa", + "Always on Top": "Zawsze na wierzchu" } diff --git a/apps/readest-app/public/locales/pt/translation.json b/apps/readest-app/public/locales/pt/translation.json index 1669a650..e910f0c6 100644 --- a/apps/readest-app/public/locales/pt/translation.json +++ b/apps/readest-app/public/locales/pt/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "Falha ao analisar o arquivo EPUB.", "This book format is not supported.": "Este formato de livro não é suportado.", "Unable to fetch the translation. Please log in first and try again.": "Não foi possível buscar a tradução. Faça login primeiro e tente novamente.", - "Group": "Grupo" + "Group": "Grupo", + "Always on Top": "Sempre no Topo" } diff --git a/apps/readest-app/public/locales/ru/translation.json b/apps/readest-app/public/locales/ru/translation.json index 1b31edab..952c9880 100644 --- a/apps/readest-app/public/locales/ru/translation.json +++ b/apps/readest-app/public/locales/ru/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "Не удалось разобрать файл EPUB.", "This book format is not supported.": "Этот формат книги не поддерживается.", "Unable to fetch the translation. Please log in first and try again.": "Не удалось получить перевод. Пожалуйста, войдите в систему и попробуйте снова.", - "Group": "Группа" + "Group": "Группа", + "Always on Top": "Всегда сверху" } diff --git a/apps/readest-app/public/locales/tr/translation.json b/apps/readest-app/public/locales/tr/translation.json index ca49042a..3978a11d 100644 --- a/apps/readest-app/public/locales/tr/translation.json +++ b/apps/readest-app/public/locales/tr/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "EPUB dosyası ayrıştırılamadı.", "This book format is not supported.": "Bu kitap formatı desteklenmiyor.", "Unable to fetch the translation. Please log in first and try again.": "Çeviri alınamıyor. Lütfen önce giriş yapın ve tekrar deneyin.", - "Group": "Grup" + "Group": "Grup", + "Always on Top": "Her Zaman Üstte" } diff --git a/apps/readest-app/public/locales/uk/translation.json b/apps/readest-app/public/locales/uk/translation.json index 628e42e5..fd06735d 100644 --- a/apps/readest-app/public/locales/uk/translation.json +++ b/apps/readest-app/public/locales/uk/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "Не вдалося розібрати файл EPUB.", "This book format is not supported.": "Цей формат книги не підтримується.", "Unable to fetch the translation. Please log in first and try again.": "Не вдалося отримати переклад. Будь ласка, спочатку увійдіть у систему та спробуйте ще раз.", - "Group": "Група" + "Group": "Група", + "Always on Top": "Завжди зверху" } diff --git a/apps/readest-app/public/locales/vi/translation.json b/apps/readest-app/public/locales/vi/translation.json index 83a296ea..e492bdcf 100644 --- a/apps/readest-app/public/locales/vi/translation.json +++ b/apps/readest-app/public/locales/vi/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "Không thể phân tích tệp EPUB.", "This book format is not supported.": "Định dạng sách này không được hỗ trợ.", "Unable to fetch the translation. Please log in first and try again.": "Không thể tải dịch vụ. Vui lòng đăng nhập trước và thử lại.", - "Group": "Nhóm" + "Group": "Nhóm", + "Always on Top": "Luôn ở trên cùng" } diff --git a/apps/readest-app/public/locales/zh-CN/translation.json b/apps/readest-app/public/locales/zh-CN/translation.json index 28c61d27..5b5f3d55 100644 --- a/apps/readest-app/public/locales/zh-CN/translation.json +++ b/apps/readest-app/public/locales/zh-CN/translation.json @@ -230,7 +230,7 @@ "Maximum Column Height": "最大列高", "Maximum Column Width": "最大列宽", "Continuous Scroll": "连续滚动", - "Fullscreen": "全屏", + "Fullscreen": "全屏显示", "No supported files found. Supported formats: {{formats}}": "未找到支持的文件。支持的格式:{{formats}}", "Drop to Import Books": "拖放导入书籍", "Custom": "自定义", @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "无法解析 EPUB 文件。", "This book format is not supported.": "不支持此书籍格式。", "Unable to fetch the translation. Please log in first and try again.": "无法获取翻译。请登录后重试。", - "Group": "分组" + "Group": "分组", + "Always on Top": "窗口置顶" } diff --git a/apps/readest-app/public/locales/zh-TW/translation.json b/apps/readest-app/public/locales/zh-TW/translation.json index 7485006b..6ccafd4c 100644 --- a/apps/readest-app/public/locales/zh-TW/translation.json +++ b/apps/readest-app/public/locales/zh-TW/translation.json @@ -265,5 +265,6 @@ "Failed to parse the EPUB file.": "無法解析 EPUB 文件。", "This book format is not supported.": "不支援此書籍格式。", "Unable to fetch the translation. Please log in first and try again.": "無法獲取翻譯。請先登入然後重試。", - "Group": "分組" + "Group": "分組", + "Always on Top": "視窗置頂" } diff --git a/apps/readest-app/src-tauri/capabilities/default.json b/apps/readest-app/src-tauri/capabilities/default.json index f3728a8c..f372850d 100644 --- a/apps/readest-app/src-tauri/capabilities/default.json +++ b/apps/readest-app/src-tauri/capabilities/default.json @@ -63,6 +63,7 @@ "core:window:allow-start-dragging", "core:window:allow-toggle-maximize", "core:window:allow-set-fullscreen", + "core:window:allow-set-always-on-top", "log:default", "shell:default", "process:default", diff --git a/apps/readest-app/src/app/library/components/SettingsMenu.tsx b/apps/readest-app/src/app/library/components/SettingsMenu.tsx index 62ec83dd..a973cd43 100644 --- a/apps/readest-app/src/app/library/components/SettingsMenu.tsx +++ b/apps/readest-app/src/app/library/components/SettingsMenu.tsx @@ -14,7 +14,7 @@ import { useSettingsStore } from '@/store/settingsStore'; import { useTranslation } from '@/hooks/useTranslation'; import { getStoragePlanData } from '@/utils/access'; import { navigateToLogin, navigateToProfile } from '@/utils/nav'; -import { tauriHandleToggleFullScreen } from '@/utils/window'; +import { tauriHandleSetAlwaysOnTop, tauriHandleToggleFullScreen } from '@/utils/window'; import { QuotaType } from '@/types/user'; import MenuItem from '@/components/MenuItem'; import Quota from '@/components/Quota'; @@ -32,6 +32,7 @@ const SettingsMenu: React.FC = ({ setIsDropdownOpen }) => { const [quotas, setQuotas] = React.useState([]); const [isAutoUpload, setIsAutoUpload] = useState(settings.autoUpload); const [isAutoCheckUpdates, setIsAutoCheckUpdates] = useState(settings.autoCheckUpdates); + const [isAlwaysOnTop, setIsAlwaysOnTop] = useState(settings.alwaysOnTop); const [isScreenWakeLock, setIsScreenWakeLock] = useState(settings.screenWakeLock); const [isAutoImportBooksOnOpen, setIsAutoImportBooksOnOpen] = useState( settings.autoImportBooksOnOpen, @@ -66,6 +67,15 @@ const SettingsMenu: React.FC = ({ setIsDropdownOpen }) => { setIsDropdownOpen?.(false); }; + const toggleAlwaysOnTop = () => { + settings.alwaysOnTop = !settings.alwaysOnTop; + setSettings(settings); + saveSettings(envConfig, settings); + setIsAlwaysOnTop(settings.alwaysOnTop); + tauriHandleSetAlwaysOnTop(settings.alwaysOnTop); + setIsDropdownOpen?.(false); + }; + const toggleAutoUploadBooks = () => { settings.autoUpload = !settings.autoUpload; setSettings(settings); @@ -174,13 +184,20 @@ const SettingsMenu: React.FC = ({ setIsDropdownOpen }) => { onClick={toggleAutoCheckUpdates} /> )} +
+ {appService?.hasWindow && } + {appService?.hasWindow && ( + : undefined} + onClick={toggleAlwaysOnTop} + /> + )} : undefined} onClick={toggleScreenWakeLock} /> -
- {appService?.hasWindow && }
{isWebApp && } diff --git a/apps/readest-app/src/app/library/page.tsx b/apps/readest-app/src/app/library/page.tsx index 3cfac479..585e6f4c 100644 --- a/apps/readest-app/src/app/library/page.tsx +++ b/apps/readest-app/src/app/library/page.tsx @@ -31,7 +31,7 @@ import { useDemoBooks } from './hooks/useDemoBooks'; import { useBooksSync } from './hooks/useBooksSync'; import { useScreenWakeLock } from '@/hooks/useScreenWakeLock'; import { useOpenWithBooks } from '@/hooks/useOpenWithBooks'; -import { tauriQuitApp } from '@/utils/window'; +import { tauriHandleSetAlwaysOnTop, tauriQuitApp } from '@/utils/window'; import { AboutWindow } from '@/components/AboutWindow'; import { Toast } from '@/components/Toast'; @@ -104,6 +104,9 @@ const LibraryPageContent = ({ searchParams }: { searchParams: ReadonlyURLSearchP await checkForAppUpdates(_); } }; + if (settings.alwaysOnTop) { + tauriHandleSetAlwaysOnTop(settings.alwaysOnTop); + } doCheckAppUpdates(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [settings]); diff --git a/apps/readest-app/src/services/constants.ts b/apps/readest-app/src/services/constants.ts index 2376f434..ce4738db 100644 --- a/apps/readest-app/src/services/constants.ts +++ b/apps/readest-app/src/services/constants.ts @@ -34,6 +34,7 @@ export const BOOK_UNGROUPED_ID = ''; export const DEFAULT_SYSTEM_SETTINGS: Partial = { keepLogin: false, autoUpload: true, + alwaysOnTop: false, autoCheckUpdates: true, screenWakeLock: true, autoImportBooksOnOpen: false, diff --git a/apps/readest-app/src/types/settings.ts b/apps/readest-app/src/types/settings.ts index 5b19d4d3..a3dbf147 100644 --- a/apps/readest-app/src/types/settings.ts +++ b/apps/readest-app/src/types/settings.ts @@ -22,6 +22,7 @@ export interface SystemSettings { keepLogin: boolean; autoUpload: boolean; + alwaysOnTop: boolean; autoCheckUpdates: boolean; screenWakeLock: boolean; autoImportBooksOnOpen: boolean; diff --git a/apps/readest-app/src/utils/window.ts b/apps/readest-app/src/utils/window.ts index 8b0b3fb9..ee187087 100644 --- a/apps/readest-app/src/utils/window.ts +++ b/apps/readest-app/src/utils/window.ts @@ -38,6 +38,16 @@ export const tauriHandleToggleFullScreen = async () => { await currentWindow.setFullscreen(newIsFullscreen); }; +export const tauriHandleSetAlwaysOnTop = async (isAlwaysOnTop: boolean) => { + const currentWindow = getCurrentWindow(); + await currentWindow.setAlwaysOnTop(isAlwaysOnTop); +}; + +export const tauriGetAlwaysOnTop = async () => { + const currentWindow = getCurrentWindow(); + return await currentWindow.isAlwaysOnTop(); +}; + export const tauriHandleOnWindowFocus = async (callback: () => void) => { const currentWindow = getCurrentWindow(); return currentWindow.listen(TauriEvent.WINDOW_FOCUS, async () => {