From 3f8d03ae288dd08ce89023a8e5c42590f53e2fbd Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Tue, 3 Jun 2025 17:43:58 +0800 Subject: [PATCH] sync: add sync status menu item in view menu, closes #844 (#1324) --- .../public/locales/ar/translation.json | 5 +- .../public/locales/de/translation.json | 5 +- .../public/locales/el/translation.json | 5 +- .../public/locales/es/translation.json | 5 +- .../public/locales/fr/translation.json | 5 +- .../public/locales/hi/translation.json | 5 +- .../public/locales/id/translation.json | 5 +- .../public/locales/it/translation.json | 5 +- .../public/locales/ja/translation.json | 5 +- .../public/locales/ko/translation.json | 5 +- .../public/locales/nl/translation.json | 5 +- .../public/locales/pl/translation.json | 5 +- .../public/locales/pt/translation.json | 5 +- .../public/locales/ru/translation.json | 5 +- .../public/locales/tr/translation.json | 5 +- .../public/locales/uk/translation.json | 5 +- .../public/locales/vi/translation.json | 5 +- .../public/locales/zh-CN/translation.json | 5 +- .../public/locales/zh-TW/translation.json | 5 +- .../src/app/reader/components/ViewMenu.tsx | 39 +++++++++++- .../src/app/reader/hooks/useProgressSync.ts | 63 ++++++++----------- apps/readest-app/src/services/constants.ts | 2 +- 22 files changed, 142 insertions(+), 57 deletions(-) diff --git a/apps/readest-app/public/locales/ar/translation.json b/apps/readest-app/public/locales/ar/translation.json index 57ba8748..820c6ebb 100644 --- a/apps/readest-app/public/locales/ar/translation.json +++ b/apps/readest-app/public/locales/ar/translation.json @@ -346,5 +346,8 @@ "Search in {{count}} Book(s)..._many": "بحث في {{count}} كتابًا...", "Search in {{count}} Book(s)..._other": "بحث في {{count}} من الكتب...", "No notes match your search": "لا توجد ملاحظات تطابق بحثك", - "Search notes and excerpts...": "بحث في الملاحظات والمقتطفات..." + "Search notes and excerpts...": "بحث في الملاحظات والمقتطفات...", + "Sign in to Sync": "سجّل للمزامنة", + "Synced at {{time}}": "تمت عند {{time}}", + "Never synced": "لم تُزامَن" } diff --git a/apps/readest-app/public/locales/de/translation.json b/apps/readest-app/public/locales/de/translation.json index c4320321..0a361714 100644 --- a/apps/readest-app/public/locales/de/translation.json +++ b/apps/readest-app/public/locales/de/translation.json @@ -338,5 +338,8 @@ "Search in {{count}} Book(s)..._one": "Suche in {{count}} Buch...", "Search in {{count}} Book(s)..._other": "Suche in {{count}} Büchern...", "No notes match your search": "Noch keine Notizen gefunden", - "Search notes and excerpts...": "Notizen und Auszüge suchen..." + "Search notes and excerpts...": "Notizen und Auszüge suchen...", + "Sign in to Sync": "Anmelden zum Synchronisieren", + "Synced at {{time}}": "Synchronisiert um {{time}}", + "Never synced": "Nie synchronisiert" } diff --git a/apps/readest-app/public/locales/el/translation.json b/apps/readest-app/public/locales/el/translation.json index c9e338dd..367f1bef 100644 --- a/apps/readest-app/public/locales/el/translation.json +++ b/apps/readest-app/public/locales/el/translation.json @@ -338,5 +338,8 @@ "Search in {{count}} Book(s)..._one": "Αναζήτηση σε {{count}} Βιβλίο...", "Search in {{count}} Book(s)..._other": "Αναζήτηση σε {{count}} Βιβλία...", "No notes match your search": "Καμία σημείωση δεν βρέθηκε", - "Search notes and excerpts...": "Αναζήτηση σημειώσεων..." + "Search notes and excerpts...": "Αναζήτηση σημειώσεων...", + "Sign in to Sync": "Σύνδεση για συγχρονισμό", + "Synced at {{time}}": "Συγχρονίστηκε στις {{time}}", + "Never synced": "Ποτέ δεν συγχρονίστηκε" } diff --git a/apps/readest-app/public/locales/es/translation.json b/apps/readest-app/public/locales/es/translation.json index c5ee4877..935fac1b 100644 --- a/apps/readest-app/public/locales/es/translation.json +++ b/apps/readest-app/public/locales/es/translation.json @@ -340,5 +340,8 @@ "Search in {{count}} Book(s)..._many": "Buscar en {{count}} libros...", "Search in {{count}} Book(s)..._other": "Buscar en {{count}} libros...", "No notes match your search": "No se encontraron notas", - "Search notes and excerpts...": "Buscar notas..." + "Search notes and excerpts...": "Buscar notas...", + "Sign in to Sync": "Inicia sesión para sincronizar", + "Synced at {{time}}": "Sincronizado a las {{time}}", + "Never synced": "Nunca sincronizado" } diff --git a/apps/readest-app/public/locales/fr/translation.json b/apps/readest-app/public/locales/fr/translation.json index dca9492d..9aff539c 100644 --- a/apps/readest-app/public/locales/fr/translation.json +++ b/apps/readest-app/public/locales/fr/translation.json @@ -340,5 +340,8 @@ "Search in {{count}} Book(s)..._many": "Rechercher dans {{count}} Livres...", "Search in {{count}} Book(s)..._other": "Rechercher dans {{count}} Livres...", "No notes match your search": "Aucune note trouvée", - "Search notes and excerpts...": "Rechercher des notes..." + "Search notes and excerpts...": "Rechercher des notes...", + "Sign in to Sync": "Connectez-vous pour synchroniser", + "Synced at {{time}}": "Synchronisé à {{time}}", + "Never synced": "Jamais synchronisé" } diff --git a/apps/readest-app/public/locales/hi/translation.json b/apps/readest-app/public/locales/hi/translation.json index c866060a..2d23a6f1 100644 --- a/apps/readest-app/public/locales/hi/translation.json +++ b/apps/readest-app/public/locales/hi/translation.json @@ -338,5 +338,8 @@ "Search in {{count}} Book(s)..._one": "{{count}} पुस्तक में खोजें...", "Search in {{count}} Book(s)..._other": "{{count}} पुस्तकों में खोजें...", "No notes match your search": "कोई नोट्स नहीं मिले", - "Search notes and excerpts...": "नोट्स खोजें..." + "Search notes and excerpts...": "नोट्स खोजें...", + "Sign in to Sync": "सिंक करने के लिए साइन इन करें", + "Synced at {{time}}": "{{time}} पर सिंक किया गया", + "Never synced": "कभी सिंक नहीं किया गया" } diff --git a/apps/readest-app/public/locales/id/translation.json b/apps/readest-app/public/locales/id/translation.json index fcb881c3..25aee966 100644 --- a/apps/readest-app/public/locales/id/translation.json +++ b/apps/readest-app/public/locales/id/translation.json @@ -336,5 +336,8 @@ "Sort TOC by Page": "Urutkan TOC berdasarkan Halaman", "Search in {{count}} Book(s)..._other": "Cari di {{count}} Buku...", "No notes match your search": "Tidak ada catatan ditemukan", - "Search notes and excerpts...": "Cari catatan..." + "Search notes and excerpts...": "Cari catatan...", + "Sign in to Sync": "Masuk untuk Sinkronisasi", + "Synced at {{time}}": "Disinkronkan pada {{time}}", + "Never synced": "Belum pernah disinkronkan" } diff --git a/apps/readest-app/public/locales/it/translation.json b/apps/readest-app/public/locales/it/translation.json index 7047c4f2..92cbf62e 100644 --- a/apps/readest-app/public/locales/it/translation.json +++ b/apps/readest-app/public/locales/it/translation.json @@ -340,5 +340,8 @@ "Search in {{count}} Book(s)..._many": "Cerca in {{count}} libri...", "Search in {{count}} Book(s)..._other": "Cerca in {{count}} libri...", "No notes match your search": "Nessuna nota trovata", - "Search notes and excerpts...": "Cerca nelle note..." + "Search notes and excerpts...": "Cerca nelle note...", + "Sign in to Sync": "Accedi per sincronizzare", + "Synced at {{time}}": "Sincronizzato alle {{time}}", + "Never synced": "Mai sincronizzato" } diff --git a/apps/readest-app/public/locales/ja/translation.json b/apps/readest-app/public/locales/ja/translation.json index 9531d9ee..da568484 100644 --- a/apps/readest-app/public/locales/ja/translation.json +++ b/apps/readest-app/public/locales/ja/translation.json @@ -336,5 +336,8 @@ "Sort TOC by Page": "目次をページで並べ替え", "Search in {{count}} Book(s)..._other": "{{count}}冊の本を検索...", "No notes match your search": "ノートが見つかりません", - "Search notes and excerpts...": "ノートを検索..." + "Search notes and excerpts...": "ノートを検索...", + "Sign in to Sync": "同期するにはサインイン", + "Synced at {{time}}": "{{time}} に同期済み", + "Never synced": "まだ同期されていません" } diff --git a/apps/readest-app/public/locales/ko/translation.json b/apps/readest-app/public/locales/ko/translation.json index 56318206..3ee94257 100644 --- a/apps/readest-app/public/locales/ko/translation.json +++ b/apps/readest-app/public/locales/ko/translation.json @@ -336,5 +336,8 @@ "Sort TOC by Page": "목차를 페이지별로 정렬", "Search in {{count}} Book(s)..._other": "{{count}}권의 책에서 검색...", "No notes match your search": "일치하는 노트가 없습니다", - "Search notes and excerpts...": "노트 검색..." + "Search notes and excerpts...": "노트 검색...", + "Sign in to Sync": "동기화를 위해 로그인하세요", + "Synced at {{time}}": "{{time}}에 동기화됨", + "Never synced": "동기화된 적 없음" } diff --git a/apps/readest-app/public/locales/nl/translation.json b/apps/readest-app/public/locales/nl/translation.json index 17700d46..f2e0f67a 100644 --- a/apps/readest-app/public/locales/nl/translation.json +++ b/apps/readest-app/public/locales/nl/translation.json @@ -338,5 +338,8 @@ "Search in {{count}} Book(s)..._one": "Zoeken in {{count}} Boek...", "Search in {{count}} Book(s)..._other": "Zoeken in {{count}} Boeken...", "No notes match your search": "Geen notities gevonden", - "Search notes and excerpts...": "Zoek notities..." + "Search notes and excerpts...": "Zoek notities...", + "Sign in to Sync": "Meld je aan om te synchroniseren", + "Synced at {{time}}": "Gesynchroniseerd om {{time}}", + "Never synced": "Nooit gesynchroniseerd" } diff --git a/apps/readest-app/public/locales/pl/translation.json b/apps/readest-app/public/locales/pl/translation.json index 7cd81881..63411db4 100644 --- a/apps/readest-app/public/locales/pl/translation.json +++ b/apps/readest-app/public/locales/pl/translation.json @@ -342,5 +342,8 @@ "Search in {{count}} Book(s)..._many": "Szukaj w {{count}} książkach...", "Search in {{count}} Book(s)..._other": "Szukaj w {{count}} książkach...", "No notes match your search": "Nie znaleziono notatek", - "Search notes and excerpts...": "Szukaj notatek..." + "Search notes and excerpts...": "Szukaj notatek...", + "Sign in to Sync": "Zaloguj się", + "Synced at {{time}}": "Sync: {{time}}", + "Never synced": "Brak synchronizacji" } diff --git a/apps/readest-app/public/locales/pt/translation.json b/apps/readest-app/public/locales/pt/translation.json index 01998efd..69305dfa 100644 --- a/apps/readest-app/public/locales/pt/translation.json +++ b/apps/readest-app/public/locales/pt/translation.json @@ -340,5 +340,8 @@ "Search in {{count}} Book(s)..._many": "Pesquisar em {{count}} Livros...", "Search in {{count}} Book(s)..._other": "Pesquisar em {{count}} Livros...", "No notes match your search": "Nenhuma nota encontrada", - "Search notes and excerpts...": "Buscar notas..." + "Search notes and excerpts...": "Buscar notas...", + "Sign in to Sync": "Entrar", + "Synced at {{time}}": "Sincronizado às {{time}}", + "Never synced": "Nunca sincronizado" } diff --git a/apps/readest-app/public/locales/ru/translation.json b/apps/readest-app/public/locales/ru/translation.json index 3dd01d91..dbed1603 100644 --- a/apps/readest-app/public/locales/ru/translation.json +++ b/apps/readest-app/public/locales/ru/translation.json @@ -342,5 +342,8 @@ "Search in {{count}} Book(s)..._many": "Поиск в {{count}} книгах...", "Search in {{count}} Book(s)..._other": "Поиск в {{count}} книгах...", "No notes match your search": "Записи не найдены", - "Search notes and excerpts...": "Искать записи..." + "Search notes and excerpts...": "Искать записи...", + "Sign in to Sync": "Войти", + "Synced at {{time}}": "Синхр. в {{time}}", + "Never synced": "Не синхр." } diff --git a/apps/readest-app/public/locales/tr/translation.json b/apps/readest-app/public/locales/tr/translation.json index 8fe0929e..ce4c19bb 100644 --- a/apps/readest-app/public/locales/tr/translation.json +++ b/apps/readest-app/public/locales/tr/translation.json @@ -338,5 +338,8 @@ "Search in {{count}} Book(s)..._one": "{{count}} kitapta ara...", "Search in {{count}} Book(s)..._other": "{{count}} kitapta ara...", "No notes match your search": "Eşleşen not bulunamadı", - "Search notes and excerpts...": "Notlarda ara..." + "Search notes and excerpts...": "Notlarda ara...", + "Sign in to Sync": "Giriş yap", + "Synced at {{time}}": "{{time}}'de eşzlendi", + "Never synced": "Hiç eşzlenmedi" } diff --git a/apps/readest-app/public/locales/uk/translation.json b/apps/readest-app/public/locales/uk/translation.json index 90521fd2..e5a2fc47 100644 --- a/apps/readest-app/public/locales/uk/translation.json +++ b/apps/readest-app/public/locales/uk/translation.json @@ -342,5 +342,8 @@ "Search in {{count}} Book(s)..._many": "Шукати в {{count}} книгах...", "Search in {{count}} Book(s)..._other": "Шукати в {{count}} книгах...", "No notes match your search": "Нотаток не знайдено", - "Search notes and excerpts...": "Шукати нотатки..." + "Search notes and excerpts...": "Шукати нотатки...", + "Sign in to Sync": "Увійти", + "Synced at {{time}}": "Синхр. о {{time}}", + "Never synced": "Ніколи не синхр." } diff --git a/apps/readest-app/public/locales/vi/translation.json b/apps/readest-app/public/locales/vi/translation.json index 0cc82895..835b42b2 100644 --- a/apps/readest-app/public/locales/vi/translation.json +++ b/apps/readest-app/public/locales/vi/translation.json @@ -336,5 +336,8 @@ "Sort TOC by Page": "Sort Mục lục theo Trang", "Search in {{count}} Book(s)..._other": "Tìm kiếm trong {{count}} cuốn sách...", "No notes match your search": "Không tìm thấy ghi chú nào", - "Search notes and excerpts...": "Tìm ghi chú..." + "Search notes and excerpts...": "Tìm ghi chú...", + "Sign in to Sync": "Đăng nhập", + "Synced at {{time}}": "Đã đồng bộ lúc {{time}}", + "Never synced": "Chưa từng đồng bộ" } diff --git a/apps/readest-app/public/locales/zh-CN/translation.json b/apps/readest-app/public/locales/zh-CN/translation.json index 2919a779..07feebab 100644 --- a/apps/readest-app/public/locales/zh-CN/translation.json +++ b/apps/readest-app/public/locales/zh-CN/translation.json @@ -336,5 +336,8 @@ "Sort TOC by Page": "按页码排序目录", "Search in {{count}} Book(s)..._other": "在 {{count}} 本书籍中搜索...", "No notes match your search": "未找到匹配的笔记", - "Search notes and excerpts...": "搜索笔记..." + "Search notes and excerpts...": "搜索笔记...", + "Sign in to Sync": "登录后同步", + "Synced at {{time}}": "同步于:{{time}}", + "Never synced": "从未同步" } diff --git a/apps/readest-app/public/locales/zh-TW/translation.json b/apps/readest-app/public/locales/zh-TW/translation.json index 1dc54c0b..53309b9f 100644 --- a/apps/readest-app/public/locales/zh-TW/translation.json +++ b/apps/readest-app/public/locales/zh-TW/translation.json @@ -336,5 +336,8 @@ "Sort TOC by Page": "依頁碼排序目錄", "Search in {{count}} Book(s)..._other": "在 {{count}} 本書中搜索...", "No notes match your search": "找不到符合的筆記", - "Search notes and excerpts...": "搜尋筆記..." + "Search notes and excerpts...": "搜尋筆記...", + "Sign in to Sync": "登入以同步", + "Synced at {{time}}": "同步於:{{time}}", + "Never synced": "從未同步" } diff --git a/apps/readest-app/src/app/reader/components/ViewMenu.tsx b/apps/readest-app/src/app/reader/components/ViewMenu.tsx index 258bbbb2..99be0325 100644 --- a/apps/readest-app/src/app/reader/components/ViewMenu.tsx +++ b/apps/readest-app/src/app/reader/components/ViewMenu.tsx @@ -1,16 +1,22 @@ import clsx from 'clsx'; import React, { useEffect } from 'react'; import { useState } from 'react'; +import { useRouter } from 'next/navigation'; import { BiMoon, BiSun } from 'react-icons/bi'; import { TbSunMoon } from 'react-icons/tb'; import { MdZoomOut, MdZoomIn, MdCheck } from 'react-icons/md'; +import { MdSync, MdSyncProblem } from 'react-icons/md'; import { MAX_ZOOM_LEVEL, MIN_ZOOM_LEVEL, ZOOM_STEP } from '@/services/constants'; import { useEnv } from '@/context/EnvContext'; +import { useAuth } from '@/context/AuthContext'; import { useThemeStore } from '@/store/themeStore'; import { useReaderStore } from '@/store/readerStore'; +import { useBookDataStore } from '@/store/bookDataStore'; import { useTranslation } from '@/hooks/useTranslation'; import { getStyles } from '@/utils/style'; +import { navigateToLogin } from '@/utils/nav'; +import { eventDispatcher } from '@/utils/event'; import { getMaxInlineSize } from '@/utils/config'; import { tauriHandleToggleFullScreen } from '@/utils/window'; import { saveViewSettings } from '../utils/viewSettingsHelper'; @@ -28,8 +34,12 @@ const ViewMenu: React.FC = ({ onSetSettingsDialogOpen, }) => { const _ = useTranslation(); + const router = useRouter(); + const { user } = useAuth(); const { envConfig, appService } = useEnv(); + const { getConfig } = useBookDataStore(); const { getView, getViewSettings, setViewSettings } = useReaderStore(); + const config = getConfig(bookKey)!; const viewSettings = getViewSettings(bookKey)!; const { themeMode, isDarkMode, setThemeMode } = useThemeStore(); @@ -59,6 +69,15 @@ const ViewMenu: React.FC = ({ setIsDropdownOpen?.(false); }; + const handleSync = () => { + if (!user) { + navigateToLogin(router); + setIsDropdownOpen?.(false); + } else { + eventDispatcher.dispatch('sync-book-progress', { bookKey }); + } + }; + useEffect(() => { if (isScrolledMode === viewSettings!.scrolled) return; viewSettings!.scrolled = isScrolledMode; @@ -83,10 +102,12 @@ const ViewMenu: React.FC = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [invertImgColorInDark]); + const lastSyncTime = Math.max(config?.lastSyncedAtConfig || 0, config?.lastSyncedAtNotes || 0); + return (