diff --git a/apps/readest-app/.claude/memory/MEMORY.md b/apps/readest-app/.claude/memory/MEMORY.md index 769b7922..d996c0e4 100644 --- a/apps/readest-app/.claude/memory/MEMORY.md +++ b/apps/readest-app/.claude/memory/MEMORY.md @@ -38,6 +38,7 @@ - [Empty-start CFI sync bug](empty-start-cfi-sync.md) — `epubcfi(/6/24!/4,,/20/1:58)` (empty-start range) from the cfi-inert skip-link transitional window; jumps to wrong section end; `isMalformedLocationCfi` → discard the synced value in `useProgressSync` (NOT the local open path); foliate fix doesn't repair already-synced values - [Custom fonts disappear on cloud sync (#4410)](custom-fonts-reincarnation-4410.md) — CRDT remove-wins: re-import-after-delete needs a `reincarnation` token or the pull re-applies the tombstone; `addFont`/`addTexture` minted none; fix mirrors dictionary (both cases) + OPDS token style; coverage matrix per kind - [koplugin note deletion sync](koplugin-note-deletion-sync.md) — koplugin push only walked LIVE annotations so deletions never reached the server; fix = `recordDeletion` persists a `deletedAt` tombstone to `doc_settings.readest_sync.deleted_notes`, `push` folds+clears them; deletion signal in `onAnnotationsModified` is `items.index_modified < 0` +- [koplugin stats sync (#4666)](koplugin-stats-sync.md) — reading-stats sync (pull on open / push on close, whole statistics.sqlite3 delta, cursor-based); 3-bug chain: plain-table-not-LuaSettings `settings:readSetting` crash; missing required books/notes/configs; statBooks/statPages need `optional_params` (Spore expected=required∪optional, `payload`≠accepted); large-backlog UI-stall + silent-retry risk unfixed ## Testing - [Nightly updater Android E2E](nightly-updater-android-e2e.md) — real Xiaomi/HyperOS test of #4577 self-updater; `pnpm dev-android` (--features devtools) for CDP, raw-socket CDP discovery, nightly>stable comparator, MIUI 单次安装授权 install gates diff --git a/apps/readest-app/.claude/memory/koplugin-stats-sync.md b/apps/readest-app/.claude/memory/koplugin-stats-sync.md new file mode 100644 index 00000000..f7e8568c --- /dev/null +++ b/apps/readest-app/.claude/memory/koplugin-stats-sync.md @@ -0,0 +1,27 @@ +--- +name: koplugin-stats-sync +description: KOReader readest.koplugin reading-stats sync (push on close / pull on open); 3-bug chain fixed in PR +metadata: + node_type: memory + type: project + originSessionId: 9b3eaf27-8688-4293-ab42-f635af2e1905 +--- + +`readest.koplugin` reading-statistics sync (KOReader `statistics.sqlite3` page events) — fixed in PR #4666 (`readest_syncstats.lua`, `main.lua`, `readest-sync-api.json`). + +**Trigger model (fully automatic, no menu/gesture):** +- **Pull** on book OPEN: `onReaderReady` → `pullBookStats(false)` (via `nextTick`). +- **Push** on book CLOSE: `onCloseDocument` → `pushBookStats(false)` (wrapped in `goOnlineToRun`). +- Both gated on `self.settings.auto_sync and self.settings.access_token`, `interactive=false` (silent on failure). +- NOT per-book: `collectSince` queries the whole `statistics.sqlite3` (`page_stat_data JOIN book`, no book filter). Open/close is just the trigger; it syncs the entire stats delta. Incremental via `stats_push_cursor` (max `start_time`) / `stats_pull_cursor` (max `updated_at_ms`); cursor advances only on full success. + +**3 stacked bugs (each hid the next):** +1. `push`/`pull` called `settings:readSetting/saveSetting` on `self.settings`, which is the PLAIN `readest_sync` data table (from `G_reader_settings:readSetting("readest_sync", default)`), NOT a `LuaSettings` object → `attempt to call method 'readSetting' (a nil value)` on every open. Fix: field access + persist via `G_reader_settings:saveSetting("readest_sync", settings)` (mirrors `readest_syncauth.lua`). Field-access pattern is used everywhere else (`self.settings.access_token`, etc.). +2. `pushChanges` requires `books/notes/configs` (`required_params`); stats sent only `statBooks/statPages` → Spore `books is required`. Fix: send empty `books={},notes={},configs={}` alongside. Server (`src/pages/api/sync.ts`) defaults each to `[]` and processes `statBooks`/`statPages` independently (gated only on their own `.length`). +3. `statBooks/statPages` were in the spec's `payload` but not `optional_params` → Spore `statBooks is not expected`. **Spore's expected-param set = `required_params ∪ optional_params`; `payload` only controls body serialization, NOT acceptance** (`common/Spore/Request.lua` `validate()`). Fix: add `optional_params:["statBooks","statPages"]` to `readest-sync-api.json`. Must be optional not required (library/config/annotation pushes legitimately omit them). + +**Spore client:** `readest_syncclient.lua` `_dispatch` runs the RPC in a coroutine with Turbo `AsyncHTTP` (network is non-blocking, yields to event loop); `Format.JSON` encodes the body synchronously first. `SYNC_TIMEOUTS={5,10}` (block/total). + +**Large-backlog blocking risk (UNFIXED, potential follow-up):** push sends the WHOLE backlog in one request (no client chunking; only pull is paginated). For ~10k `page_stat_data` rows: `collectSince` builds a 10k-entry Lua table + ~1MB JSON encode SYNCHRONOUSLY on the main thread → ~1-2s UI stall on weak e-ink CPUs at book close (network part is async, doesn't freeze). Worse: 10s timeout + no chunking + all-or-nothing cursor → if it can't finish in time it fails silently, cursor stays 0, and every later close re-collects/re-encodes/re-uploads the same backlog (server upserts are idempotent but wasteful). Fix idea: chunk push (~500-1000/req, matching server `BATCH=500`), advance cursor per successful chunk. + +**Testing gap that hid it:** `spec/syncstats_spec.lua` originally tested only `collectSince`/`applyRemote`, never `push`/`pull`. Added tests: cursor advance on success (mock client enforces `required_params`), pull cursor from newest `updated_at_ms`, and a spec-level check parsing `readest-sync-api.json` to assert every stats-push key is an expected param (reproduces bug 3). Busted runs with `cwd=KOPLUGIN_DIR` so `io.open("readest-sync-api.json")` works; `require("json")`→dkjson via spec_helper shim. Debug logging kept (`ReadestStats` prefix). Related: [[koplugin-note-deletion-sync]], [[kosync-cfi-spine-resolution]]. diff --git a/apps/readest.koplugin/locales/ar/translation.po b/apps/readest.koplugin/locales/ar/translation.po index 4a2cdb64..9101687e 100644 --- a/apps/readest.koplugin/locales/ar/translation.po +++ b/apps/readest.koplugin/locales/ar/translation.po @@ -251,6 +251,12 @@ msgstr "المزامنة التلقائية" msgid "Readest library" msgstr "مكتبة Readest" +msgid "Push stats now" +msgstr "إرسال الإحصائيات الآن" + +msgid "Pull stats now" +msgstr "جلب الإحصائيات الآن" + msgid "Push books now" msgstr "إرسال الكتب الآن" @@ -437,8 +443,17 @@ msgstr "تمت مزامنة تقدم القراءة" msgid "No saved reading progress found for this book" msgstr "لم يتم العثور على تقدم قراءة محفوظ لهذا الكتاب" +msgid "Reading statistics are up to date" +msgstr "إحصائيات القراءة محدّثة" + +msgid "Reading statistics pushed" +msgstr "تم إرسال إحصائيات القراءة" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "فشل إرسال إحصائيات القراءة" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "فشل جلب إحصائيات القراءة" + +msgid "Reading statistics pulled" +msgstr "تم جلب إحصائيات القراءة" diff --git a/apps/readest.koplugin/locales/bn/translation.po b/apps/readest.koplugin/locales/bn/translation.po index f4d65620..e366a043 100644 --- a/apps/readest.koplugin/locales/bn/translation.po +++ b/apps/readest.koplugin/locales/bn/translation.po @@ -251,6 +251,12 @@ msgstr "অটো সিঙ্ক" msgid "Readest library" msgstr "Readest লাইব্রেরি" +msgid "Push stats now" +msgstr "এখনই পরিসংখ্যান পুশ করুন" + +msgid "Pull stats now" +msgstr "এখনই পরিসংখ্যান পুল করুন" + msgid "Push books now" msgstr "এখনই বই পুশ করুন" @@ -437,8 +443,17 @@ msgstr "পড়ার অগ্রগতি সিঙ্ক হয়েছে msgid "No saved reading progress found for this book" msgstr "এই বইয়ের জন্য সংরক্ষিত পড়ার অগ্রগতি পাওয়া যায়নি" +msgid "Reading statistics are up to date" +msgstr "পড়ার পরিসংখ্যান হালনাগাদ আছে" + +msgid "Reading statistics pushed" +msgstr "পড়ার পরিসংখ্যান পাঠানো হয়েছে" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "পড়ার পরিসংখ্যান পাঠানো ব্যর্থ" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "পড়ার পরিসংখ্যান আনা ব্যর্থ" + +msgid "Reading statistics pulled" +msgstr "পড়ার পরিসংখ্যান আনা হয়েছে" diff --git a/apps/readest.koplugin/locales/bo/translation.po b/apps/readest.koplugin/locales/bo/translation.po index 49395e2e..35f3c54d 100644 --- a/apps/readest.koplugin/locales/bo/translation.po +++ b/apps/readest.koplugin/locales/bo/translation.po @@ -251,6 +251,12 @@ msgstr "རང་འགུལ་མཉམ་སྦྱོར་" msgid "Readest library" msgstr "Readest དཔེ་མཛོད་" +msgid "Push stats now" +msgstr "གྲངས་ཐོ་ད་ལྟ་སྐུར་" + +msgid "Pull stats now" +msgstr "གྲངས་ཐོ་ད་ལྟ་ལེན་" + msgid "Push books now" msgstr "དེབ་རྣམས་ད་ལྟ་སྐུར་" @@ -437,8 +443,17 @@ msgstr "ཀློག་པའི་འཕེལ་རིམ་མཉམ་འག msgid "No saved reading progress found for this book" msgstr "དཔེ་ཆ་འདིའི་ཀློག་པའི་འཕེལ་རིམ་ཉར་ཚགས་མ་རྙེད།" +msgid "Reading statistics are up to date" +msgstr "ཀློག་པའི་གྲངས་ཐོ་གསར་ཤོས་ཡིན།" + +msgid "Reading statistics pushed" +msgstr "ཀློག་པའི་གྲངས་ཐོ་སྐུར་སོང་།" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "ཀློག་པའི་གྲངས་ཐོ་སྐུར་མ་ཐུབ།" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "ཀློག་པའི་གྲངས་ཐོ་ལེན་མ་ཐུབ།" + +msgid "Reading statistics pulled" +msgstr "ཀློག་པའི་གྲངས་ཐོ་ལེན་སོང་།" diff --git a/apps/readest.koplugin/locales/de/translation.po b/apps/readest.koplugin/locales/de/translation.po index 807931a6..7da387a4 100644 --- a/apps/readest.koplugin/locales/de/translation.po +++ b/apps/readest.koplugin/locales/de/translation.po @@ -251,6 +251,12 @@ msgstr "Automatische Synchronisierung" msgid "Readest library" msgstr "Readest-Bibliothek" +msgid "Push stats now" +msgstr "Statistik jetzt senden" + +msgid "Pull stats now" +msgstr "Statistik jetzt abrufen" + msgid "Push books now" msgstr "Bücher jetzt senden" @@ -437,8 +443,17 @@ msgstr "Lesefortschritt synchronisiert" msgid "No saved reading progress found for this book" msgstr "Kein gespeicherter Lesefortschritt für dieses Buch gefunden" +msgid "Reading statistics are up to date" +msgstr "Lesestatistik ist auf dem neuesten Stand" + +msgid "Reading statistics pushed" +msgstr "Lesestatistik gesendet" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Senden der Lesestatistik fehlgeschlagen" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Abrufen der Lesestatistik fehlgeschlagen" + +msgid "Reading statistics pulled" +msgstr "Lesestatistik abgerufen" diff --git a/apps/readest.koplugin/locales/el/translation.po b/apps/readest.koplugin/locales/el/translation.po index 9a6f9eda..d6ae937c 100644 --- a/apps/readest.koplugin/locales/el/translation.po +++ b/apps/readest.koplugin/locales/el/translation.po @@ -251,6 +251,12 @@ msgstr "Αυτόματος συγχρονισμός" msgid "Readest library" msgstr "Βιβλιοθήκη Readest" +msgid "Push stats now" +msgstr "Αποστολή στατιστικών τώρα" + +msgid "Pull stats now" +msgstr "Λήψη στατιστικών τώρα" + msgid "Push books now" msgstr "Αποστολή βιβλίων τώρα" @@ -437,8 +443,17 @@ msgstr "Η πρόοδος ανάγνωσης συγχρονίστηκε" msgid "No saved reading progress found for this book" msgstr "Δεν βρέθηκε αποθηκευμένη πρόοδος ανάγνωσης για αυτό το βιβλίο" +msgid "Reading statistics are up to date" +msgstr "Τα στατιστικά ανάγνωσης είναι ενημερωμένα" + +msgid "Reading statistics pushed" +msgstr "Τα στατιστικά ανάγνωσης αποστάλθηκαν" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Η αποστολή των στατιστικών ανάγνωσης απέτυχε" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Η λήψη των στατιστικών ανάγνωσης απέτυχε" + +msgid "Reading statistics pulled" +msgstr "Τα στατιστικά ανάγνωσης ελήφθησαν" diff --git a/apps/readest.koplugin/locales/es/translation.po b/apps/readest.koplugin/locales/es/translation.po index 616895b5..fc8604af 100644 --- a/apps/readest.koplugin/locales/es/translation.po +++ b/apps/readest.koplugin/locales/es/translation.po @@ -251,6 +251,12 @@ msgstr "Sincronización automática" msgid "Readest library" msgstr "Biblioteca de Readest" +msgid "Push stats now" +msgstr "Enviar estadísticas ahora" + +msgid "Pull stats now" +msgstr "Obtener estadísticas ahora" + msgid "Push books now" msgstr "Enviar libros ahora" @@ -437,8 +443,17 @@ msgstr "Progreso de lectura sincronizado" msgid "No saved reading progress found for this book" msgstr "No se encontró progreso de lectura guardado para este libro" +msgid "Reading statistics are up to date" +msgstr "Las estadísticas de lectura están actualizadas" + +msgid "Reading statistics pushed" +msgstr "Estadísticas de lectura enviadas" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Error al enviar las estadísticas de lectura" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Error al obtener las estadísticas de lectura" + +msgid "Reading statistics pulled" +msgstr "Estadísticas de lectura obtenidas" diff --git a/apps/readest.koplugin/locales/fa/translation.po b/apps/readest.koplugin/locales/fa/translation.po index 0c59b52f..9c5d8c05 100644 --- a/apps/readest.koplugin/locales/fa/translation.po +++ b/apps/readest.koplugin/locales/fa/translation.po @@ -251,6 +251,12 @@ msgstr "همگام‌سازی خودکار" msgid "Readest library" msgstr "کتابخانه Readest" +msgid "Push stats now" +msgstr "اکنون ارسال آمار" + +msgid "Pull stats now" +msgstr "اکنون دریافت آمار" + msgid "Push books now" msgstr "اکنون ارسال کتاب‌ها" @@ -437,8 +443,17 @@ msgstr "پیشرفت مطالعه همگام‌سازی شد" msgid "No saved reading progress found for this book" msgstr "پیشرفت مطالعه ذخیره‌شده‌ای برای این کتاب یافت نشد" +msgid "Reading statistics are up to date" +msgstr "آمار مطالعه به‌روز است" + +msgid "Reading statistics pushed" +msgstr "آمار مطالعه ارسال شد" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "ارسال آمار مطالعه ناموفق بود" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "دریافت آمار مطالعه ناموفق بود" + +msgid "Reading statistics pulled" +msgstr "آمار مطالعه دریافت شد" diff --git a/apps/readest.koplugin/locales/fr/translation.po b/apps/readest.koplugin/locales/fr/translation.po index f5b45e34..2cb19b9c 100644 --- a/apps/readest.koplugin/locales/fr/translation.po +++ b/apps/readest.koplugin/locales/fr/translation.po @@ -251,6 +251,12 @@ msgstr "Synchronisation auto" msgid "Readest library" msgstr "Bibliothèque Readest" +msgid "Push stats now" +msgstr "Envoyer les statistiques maintenant" + +msgid "Pull stats now" +msgstr "Récupérer les statistiques maintenant" + msgid "Push books now" msgstr "Envoyer les livres maintenant" @@ -437,8 +443,17 @@ msgstr "Progression de lecture synchronisée" msgid "No saved reading progress found for this book" msgstr "Aucune progression de lecture enregistrée pour ce livre" +msgid "Reading statistics are up to date" +msgstr "Les statistiques de lecture sont à jour" + +msgid "Reading statistics pushed" +msgstr "Statistiques de lecture envoyées" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Échec de l'envoi des statistiques de lecture" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Échec de la récupération des statistiques de lecture" + +msgid "Reading statistics pulled" +msgstr "Statistiques de lecture récupérées" diff --git a/apps/readest.koplugin/locales/he/translation.po b/apps/readest.koplugin/locales/he/translation.po index 49ef223b..6ffe0894 100644 --- a/apps/readest.koplugin/locales/he/translation.po +++ b/apps/readest.koplugin/locales/he/translation.po @@ -251,6 +251,12 @@ msgstr "סנכרון אוטומטי" msgid "Readest library" msgstr "ספריית Readest" +msgid "Push stats now" +msgstr "שלח סטטיסטיקות עכשיו" + +msgid "Pull stats now" +msgstr "משוך סטטיסטיקות עכשיו" + msgid "Push books now" msgstr "שלח ספרים עכשיו" @@ -437,8 +443,17 @@ msgstr "התקדמות הקריאה סונכרנה" msgid "No saved reading progress found for this book" msgstr "לא נמצאה התקדמות קריאה שמורה לספר זה" +msgid "Reading statistics are up to date" +msgstr "סטטיסטיקות הקריאה מעודכנות" + +msgid "Reading statistics pushed" +msgstr "סטטיסטיקות הקריאה נשלחו" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "שליחת סטטיסטיקות הקריאה נכשלה" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "משיכת סטטיסטיקות הקריאה נכשלה" + +msgid "Reading statistics pulled" +msgstr "סטטיסטיקות הקריאה נמשכו" diff --git a/apps/readest.koplugin/locales/hi/translation.po b/apps/readest.koplugin/locales/hi/translation.po index 018c5c46..452b702a 100644 --- a/apps/readest.koplugin/locales/hi/translation.po +++ b/apps/readest.koplugin/locales/hi/translation.po @@ -251,6 +251,12 @@ msgstr "स्वतः सिंक" msgid "Readest library" msgstr "Readest लाइब्रेरी" +msgid "Push stats now" +msgstr "अभी आँकड़े पुश करें" + +msgid "Pull stats now" +msgstr "अभी आँकड़े पुल करें" + msgid "Push books now" msgstr "अभी पुस्तकें पुश करें" @@ -437,8 +443,17 @@ msgstr "पठन प्रगति सिंक हो गई" msgid "No saved reading progress found for this book" msgstr "इस पुस्तक के लिए सहेजी गई पठन प्रगति नहीं मिली" +msgid "Reading statistics are up to date" +msgstr "पठन आँकड़े अद्यतित हैं" + +msgid "Reading statistics pushed" +msgstr "पठन आँकड़े भेजे गए" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "पठन आँकड़े भेजने में विफल" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "पठन आँकड़े प्राप्त करने में विफल" + +msgid "Reading statistics pulled" +msgstr "पठन आँकड़े प्राप्त हुए" diff --git a/apps/readest.koplugin/locales/hu/translation.po b/apps/readest.koplugin/locales/hu/translation.po index 964cde89..57825093 100644 --- a/apps/readest.koplugin/locales/hu/translation.po +++ b/apps/readest.koplugin/locales/hu/translation.po @@ -251,6 +251,12 @@ msgstr "Automatikus szinkron" msgid "Readest library" msgstr "Readest könyvtár" +msgid "Push stats now" +msgstr "Statisztikák küldése most" + +msgid "Pull stats now" +msgstr "Statisztikák lekérése most" + msgid "Push books now" msgstr "Könyvek küldése most" @@ -437,8 +443,17 @@ msgstr "Olvasási haladás szinkronizálva" msgid "No saved reading progress found for this book" msgstr "Nem található mentett olvasási haladás ehhez a könyvhöz" +msgid "Reading statistics are up to date" +msgstr "Az olvasási statisztikák naprakészek" + +msgid "Reading statistics pushed" +msgstr "Olvasási statisztikák elküldve" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Az olvasási statisztikák küldése sikertelen" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Az olvasási statisztikák lekérése sikertelen" + +msgid "Reading statistics pulled" +msgstr "Olvasási statisztikák lekérve" diff --git a/apps/readest.koplugin/locales/id/translation.po b/apps/readest.koplugin/locales/id/translation.po index 050331e5..cc7444da 100644 --- a/apps/readest.koplugin/locales/id/translation.po +++ b/apps/readest.koplugin/locales/id/translation.po @@ -251,6 +251,12 @@ msgstr "Sinkronisasi otomatis" msgid "Readest library" msgstr "Pustaka Readest" +msgid "Push stats now" +msgstr "Kirim statistik sekarang" + +msgid "Pull stats now" +msgstr "Tarik statistik sekarang" + msgid "Push books now" msgstr "Kirim buku sekarang" @@ -437,8 +443,17 @@ msgstr "Progres baca disinkronkan" msgid "No saved reading progress found for this book" msgstr "Tidak ada progres baca tersimpan untuk buku ini" +msgid "Reading statistics are up to date" +msgstr "Statistik baca sudah terbaru" + +msgid "Reading statistics pushed" +msgstr "Statistik baca terkirim" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Gagal mengirim statistik baca" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Gagal mengambil statistik baca" + +msgid "Reading statistics pulled" +msgstr "Statistik baca diambil" diff --git a/apps/readest.koplugin/locales/it/translation.po b/apps/readest.koplugin/locales/it/translation.po index 3f3ecfe8..1f5d749a 100644 --- a/apps/readest.koplugin/locales/it/translation.po +++ b/apps/readest.koplugin/locales/it/translation.po @@ -251,6 +251,12 @@ msgstr "Sincronizzazione automatica" msgid "Readest library" msgstr "Libreria Readest" +msgid "Push stats now" +msgstr "Invia statistiche ora" + +msgid "Pull stats now" +msgstr "Recupera statistiche ora" + msgid "Push books now" msgstr "Invia libri ora" @@ -437,8 +443,17 @@ msgstr "Progresso di lettura sincronizzato" msgid "No saved reading progress found for this book" msgstr "Nessun progresso di lettura salvato per questo libro" +msgid "Reading statistics are up to date" +msgstr "Le statistiche di lettura sono aggiornate" + +msgid "Reading statistics pushed" +msgstr "Statistiche di lettura inviate" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Invio delle statistiche di lettura non riuscito" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Recupero delle statistiche di lettura non riuscito" + +msgid "Reading statistics pulled" +msgstr "Statistiche di lettura ricevute" diff --git a/apps/readest.koplugin/locales/ja/translation.po b/apps/readest.koplugin/locales/ja/translation.po index fd28c072..eb573023 100644 --- a/apps/readest.koplugin/locales/ja/translation.po +++ b/apps/readest.koplugin/locales/ja/translation.po @@ -251,6 +251,12 @@ msgstr "自動同期" msgid "Readest library" msgstr "Readest ライブラリ" +msgid "Push stats now" +msgstr "今すぐ統計を送信" + +msgid "Pull stats now" +msgstr "今すぐ統計を取得" + msgid "Push books now" msgstr "今すぐ書籍を送信" @@ -437,8 +443,17 @@ msgstr "読書の進捗を同期しました" msgid "No saved reading progress found for this book" msgstr "この書籍の保存された読書進捗が見つかりません" +msgid "Reading statistics are up to date" +msgstr "読書統計は最新です" + +msgid "Reading statistics pushed" +msgstr "読書統計を送信しました" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "読書統計の送信に失敗しました" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "読書統計の取得に失敗しました" + +msgid "Reading statistics pulled" +msgstr "読書統計を取得しました" diff --git a/apps/readest.koplugin/locales/ko/translation.po b/apps/readest.koplugin/locales/ko/translation.po index a9bd2b93..9ffad8d6 100644 --- a/apps/readest.koplugin/locales/ko/translation.po +++ b/apps/readest.koplugin/locales/ko/translation.po @@ -251,6 +251,12 @@ msgstr "자동 동기화" msgid "Readest library" msgstr "Readest 라이브러리" +msgid "Push stats now" +msgstr "지금 통계 푸시" + +msgid "Pull stats now" +msgstr "지금 통계 풀" + msgid "Push books now" msgstr "지금 책 푸시" @@ -437,8 +443,17 @@ msgstr "읽기 진행 상황이 동기화되었습니다" msgid "No saved reading progress found for this book" msgstr "이 책의 저장된 읽기 진행 상황을 찾을 수 없습니다" +msgid "Reading statistics are up to date" +msgstr "읽기 통계가 최신 상태입니다" + +msgid "Reading statistics pushed" +msgstr "읽기 통계를 보냈습니다" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "읽기 통계 보내기에 실패했습니다" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "읽기 통계 가져오기에 실패했습니다" + +msgid "Reading statistics pulled" +msgstr "읽기 통계를 가져왔습니다" diff --git a/apps/readest.koplugin/locales/ms/translation.po b/apps/readest.koplugin/locales/ms/translation.po index 59f3b31d..4eaf1778 100644 --- a/apps/readest.koplugin/locales/ms/translation.po +++ b/apps/readest.koplugin/locales/ms/translation.po @@ -251,6 +251,12 @@ msgstr "Penyegerakan automatik" msgid "Readest library" msgstr "Pustaka Readest" +msgid "Push stats now" +msgstr "Hantar statistik sekarang" + +msgid "Pull stats now" +msgstr "Tarik statistik sekarang" + msgid "Push books now" msgstr "Hantar buku sekarang" @@ -437,8 +443,17 @@ msgstr "Kemajuan bacaan disegerakkan" msgid "No saved reading progress found for this book" msgstr "Tiada kemajuan bacaan tersimpan ditemui untuk buku ini" +msgid "Reading statistics are up to date" +msgstr "Statistik bacaan adalah terkini" + +msgid "Reading statistics pushed" +msgstr "Statistik bacaan dihantar" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Gagal menghantar statistik bacaan" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Gagal menarik statistik bacaan" + +msgid "Reading statistics pulled" +msgstr "Statistik bacaan ditarik" diff --git a/apps/readest.koplugin/locales/nl/translation.po b/apps/readest.koplugin/locales/nl/translation.po index 85f45640..41b4cf0f 100644 --- a/apps/readest.koplugin/locales/nl/translation.po +++ b/apps/readest.koplugin/locales/nl/translation.po @@ -251,6 +251,12 @@ msgstr "Automatische synchronisatie" msgid "Readest library" msgstr "Readest-bibliotheek" +msgid "Push stats now" +msgstr "Statistieken nu pushen" + +msgid "Pull stats now" +msgstr "Statistieken nu pullen" + msgid "Push books now" msgstr "Boeken nu pushen" @@ -437,8 +443,17 @@ msgstr "Leesvoortgang gesynchroniseerd" msgid "No saved reading progress found for this book" msgstr "Geen opgeslagen leesvoortgang gevonden voor dit boek" +msgid "Reading statistics are up to date" +msgstr "Leesstatistieken zijn up-to-date" + +msgid "Reading statistics pushed" +msgstr "Leesstatistieken verzonden" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Leesstatistieken verzenden mislukt" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Leesstatistieken ophalen mislukt" + +msgid "Reading statistics pulled" +msgstr "Leesstatistieken opgehaald" diff --git a/apps/readest.koplugin/locales/pl/translation.po b/apps/readest.koplugin/locales/pl/translation.po index 9c979f1d..5f4814f7 100644 --- a/apps/readest.koplugin/locales/pl/translation.po +++ b/apps/readest.koplugin/locales/pl/translation.po @@ -251,6 +251,12 @@ msgstr "Auto synchronizacja" msgid "Readest library" msgstr "Biblioteka Readest" +msgid "Push stats now" +msgstr "Wyślij statystyki teraz" + +msgid "Pull stats now" +msgstr "Pobierz statystyki teraz" + msgid "Push books now" msgstr "Wyślij książki teraz" @@ -437,8 +443,17 @@ msgstr "Postęp czytania zsynchronizowany" msgid "No saved reading progress found for this book" msgstr "Nie znaleziono zapisanego postępu czytania dla tej książki" +msgid "Reading statistics are up to date" +msgstr "Statystyki czytania są aktualne" + +msgid "Reading statistics pushed" +msgstr "Statystyki czytania wysłane" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Nie udało się wysłać statystyk czytania" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Nie udało się pobrać statystyk czytania" + +msgid "Reading statistics pulled" +msgstr "Statystyki czytania pobrane" diff --git a/apps/readest.koplugin/locales/pt-BR/translation.po b/apps/readest.koplugin/locales/pt-BR/translation.po index f0fc7c0c..e91caf9d 100644 --- a/apps/readest.koplugin/locales/pt-BR/translation.po +++ b/apps/readest.koplugin/locales/pt-BR/translation.po @@ -251,6 +251,12 @@ msgstr "Sincronização automática" msgid "Readest library" msgstr "Biblioteca Readest" +msgid "Push stats now" +msgstr "Enviar estatísticas agora" + +msgid "Pull stats now" +msgstr "Obter estatísticas agora" + msgid "Push books now" msgstr "Enviar livros agora" @@ -437,8 +443,17 @@ msgstr "Progresso de leitura sincronizado" msgid "No saved reading progress found for this book" msgstr "Nenhum progresso de leitura salvo encontrado para este livro" +msgid "Reading statistics are up to date" +msgstr "As estatísticas de leitura estão atualizadas" + +msgid "Reading statistics pushed" +msgstr "Estatísticas de leitura enviadas" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Falha ao enviar as estatísticas de leitura" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Falha ao obter as estatísticas de leitura" + +msgid "Reading statistics pulled" +msgstr "Estatísticas de leitura obtidas" diff --git a/apps/readest.koplugin/locales/pt/translation.po b/apps/readest.koplugin/locales/pt/translation.po index 9518fa3e..7353055b 100644 --- a/apps/readest.koplugin/locales/pt/translation.po +++ b/apps/readest.koplugin/locales/pt/translation.po @@ -251,6 +251,12 @@ msgstr "Sincronização automática" msgid "Readest library" msgstr "Biblioteca Readest" +msgid "Push stats now" +msgstr "Enviar estatísticas agora" + +msgid "Pull stats now" +msgstr "Obter estatísticas agora" + msgid "Push books now" msgstr "Enviar livros agora" @@ -437,8 +443,17 @@ msgstr "Progresso de leitura sincronizado" msgid "No saved reading progress found for this book" msgstr "Não foi encontrado progresso de leitura guardado para este livro" +msgid "Reading statistics are up to date" +msgstr "As estatísticas de leitura estão atualizadas" + +msgid "Reading statistics pushed" +msgstr "Estatísticas de leitura enviadas" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Falha ao enviar as estatísticas de leitura" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Falha ao obter as estatísticas de leitura" + +msgid "Reading statistics pulled" +msgstr "Estatísticas de leitura obtidas" diff --git a/apps/readest.koplugin/locales/ro/translation.po b/apps/readest.koplugin/locales/ro/translation.po index c589428c..2bc18be8 100644 --- a/apps/readest.koplugin/locales/ro/translation.po +++ b/apps/readest.koplugin/locales/ro/translation.po @@ -251,6 +251,12 @@ msgstr "Sincronizare automată" msgid "Readest library" msgstr "Biblioteca Readest" +msgid "Push stats now" +msgstr "Trimite statisticile acum" + +msgid "Pull stats now" +msgstr "Preia statisticile acum" + msgid "Push books now" msgstr "Trimite cărțile acum" @@ -437,8 +443,17 @@ msgstr "Progres de citire sincronizat" msgid "No saved reading progress found for this book" msgstr "Nu s-a găsit progres de citire salvat pentru această carte" +msgid "Reading statistics are up to date" +msgstr "Statisticile de citire sunt actualizate" + +msgid "Reading statistics pushed" +msgstr "Statistici de citire trimise" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Trimiterea statisticilor de citire a eșuat" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Obținerea statisticilor de citire a eșuat" + +msgid "Reading statistics pulled" +msgstr "Statistici de citire obținute" diff --git a/apps/readest.koplugin/locales/ru/translation.po b/apps/readest.koplugin/locales/ru/translation.po index 53de7f1c..c6c2ad39 100644 --- a/apps/readest.koplugin/locales/ru/translation.po +++ b/apps/readest.koplugin/locales/ru/translation.po @@ -251,6 +251,12 @@ msgstr "Автосинхронизация" msgid "Readest library" msgstr "Библиотека Readest" +msgid "Push stats now" +msgstr "Отправить статистику сейчас" + +msgid "Pull stats now" +msgstr "Получить статистику сейчас" + msgid "Push books now" msgstr "Отправить книги сейчас" @@ -437,8 +443,17 @@ msgstr "Прогресс чтения синхронизирован" msgid "No saved reading progress found for this book" msgstr "Сохранённый прогресс чтения для этой книги не найден" +msgid "Reading statistics are up to date" +msgstr "Статистика чтения актуальна" + +msgid "Reading statistics pushed" +msgstr "Статистика чтения отправлена" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Не удалось отправить статистику чтения" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Не удалось получить статистику чтения" + +msgid "Reading statistics pulled" +msgstr "Статистика чтения получена" diff --git a/apps/readest.koplugin/locales/si/translation.po b/apps/readest.koplugin/locales/si/translation.po index 8921c18e..aa9384d5 100644 --- a/apps/readest.koplugin/locales/si/translation.po +++ b/apps/readest.koplugin/locales/si/translation.po @@ -251,6 +251,12 @@ msgstr "ස්වයංක්‍රීය සමමුහූර්ත" msgid "Readest library" msgstr "Readest පුස්තකාලය" +msgid "Push stats now" +msgstr "සංඛ්‍යාලේඛන දැන් යවන්න" + +msgid "Pull stats now" +msgstr "සංඛ්‍යාලේඛන දැන් ලබාගන්න" + msgid "Push books now" msgstr "දැන් පොත් යවන්න" @@ -437,8 +443,17 @@ msgstr "කියවීමේ ප්‍රගතිය සමමුහූර් msgid "No saved reading progress found for this book" msgstr "මෙම පොත සඳහා සුරකින ලද කියවීමේ ප්‍රගතියක් හමු නොවුණි" +msgid "Reading statistics are up to date" +msgstr "කියවීමේ සංඛ්‍යාලේඛන යාවත්කාලීනයි" + +msgid "Reading statistics pushed" +msgstr "කියවීමේ සංඛ්‍යාලේඛන යවන ලදී" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "කියවීමේ සංඛ්‍යාලේඛන යැවීම අසාර්ථකයි" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "කියවීමේ සංඛ්‍යාලේඛන ලබාගැනීම අසාර්ථකයි" + +msgid "Reading statistics pulled" +msgstr "කියවීමේ සංඛ්‍යාලේඛන ලබා ගන්නා ලදී" diff --git a/apps/readest.koplugin/locales/sl/translation.po b/apps/readest.koplugin/locales/sl/translation.po index 6f37fc29..4f551ead 100644 --- a/apps/readest.koplugin/locales/sl/translation.po +++ b/apps/readest.koplugin/locales/sl/translation.po @@ -251,6 +251,12 @@ msgstr "Samodejna sinhronizacija" msgid "Readest library" msgstr "Knjižnica Readest" +msgid "Push stats now" +msgstr "Pošlji statistiko zdaj" + +msgid "Pull stats now" +msgstr "Pridobi statistiko zdaj" + msgid "Push books now" msgstr "Pošlji knjige zdaj" @@ -437,8 +443,17 @@ msgstr "Napredek branja sinhroniziran" msgid "No saved reading progress found for this book" msgstr "Za to knjigo ni shranjenega napredka branja" +msgid "Reading statistics are up to date" +msgstr "Statistika branja je posodobljena" + +msgid "Reading statistics pushed" +msgstr "Statistika branja poslana" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Pošiljanje statistike branja ni uspelo" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Pridobivanje statistike branja ni uspelo" + +msgid "Reading statistics pulled" +msgstr "Statistika branja pridobljena" diff --git a/apps/readest.koplugin/locales/sv/translation.po b/apps/readest.koplugin/locales/sv/translation.po index d8123292..89b4dd12 100644 --- a/apps/readest.koplugin/locales/sv/translation.po +++ b/apps/readest.koplugin/locales/sv/translation.po @@ -251,6 +251,12 @@ msgstr "Automatisk synkronisering" msgid "Readest library" msgstr "Readest-bibliotek" +msgid "Push stats now" +msgstr "Skicka statistik nu" + +msgid "Pull stats now" +msgstr "Hämta statistik nu" + msgid "Push books now" msgstr "Skicka böcker nu" @@ -437,8 +443,17 @@ msgstr "Läsförloppet synkroniserat" msgid "No saved reading progress found for this book" msgstr "Inget sparat läsförlopp hittades för boken" +msgid "Reading statistics are up to date" +msgstr "Lässtatistiken är uppdaterad" + +msgid "Reading statistics pushed" +msgstr "Lässtatistik skickad" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Det gick inte att skicka lässtatistiken" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Det gick inte att hämta lässtatistiken" + +msgid "Reading statistics pulled" +msgstr "Lässtatistik hämtad" diff --git a/apps/readest.koplugin/locales/ta/translation.po b/apps/readest.koplugin/locales/ta/translation.po index df21e804..4753d85e 100644 --- a/apps/readest.koplugin/locales/ta/translation.po +++ b/apps/readest.koplugin/locales/ta/translation.po @@ -251,6 +251,12 @@ msgstr "தானியங்கி ஒத்திசைவு" msgid "Readest library" msgstr "Readest நூலகம்" +msgid "Push stats now" +msgstr "புள்ளிவிவரங்களை இப்போது அனுப்பு" + +msgid "Pull stats now" +msgstr "புள்ளிவிவரங்களை இப்போது பெறு" + msgid "Push books now" msgstr "இப்போது புத்தகங்களை அனுப்பு" @@ -437,8 +443,17 @@ msgstr "வாசிப்பு முன்னேற்றம் ஒத்த msgid "No saved reading progress found for this book" msgstr "இந்த நூலுக்கான சேமிக்கப்பட்ட வாசிப்பு முன்னேற்றம் இல்லை" +msgid "Reading statistics are up to date" +msgstr "வாசிப்பு புள்ளிவிவரங்கள் புதுப்பித்த நிலையில் உள்ளன" + +msgid "Reading statistics pushed" +msgstr "வாசிப்பு புள்ளிவிவரங்கள் அனுப்பப்பட்டன" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "வாசிப்பு புள்ளிவிவரங்களை அனுப்புவதில் தோல்வி" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "வாசிப்பு புள்ளிவிவரங்களைப் பெறுவதில் தோல்வி" + +msgid "Reading statistics pulled" +msgstr "வாசிப்பு புள்ளிவிவரங்கள் பெறப்பட்டன" diff --git a/apps/readest.koplugin/locales/th/translation.po b/apps/readest.koplugin/locales/th/translation.po index 0336bab5..1ff30169 100644 --- a/apps/readest.koplugin/locales/th/translation.po +++ b/apps/readest.koplugin/locales/th/translation.po @@ -251,6 +251,12 @@ msgstr "ซิงค์อัตโนมัติ" msgid "Readest library" msgstr "คลัง Readest" +msgid "Push stats now" +msgstr "ส่งสถิติเดี๋ยวนี้" + +msgid "Pull stats now" +msgstr "ดึงสถิติเดี๋ยวนี้" + msgid "Push books now" msgstr "ส่งหนังสือเดี๋ยวนี้" @@ -437,8 +443,17 @@ msgstr "ซิงค์ความคืบหน้าการอ่านแ msgid "No saved reading progress found for this book" msgstr "ไม่พบความคืบหน้าการอ่านที่บันทึกไว้สำหรับหนังสือเล่มนี้" +msgid "Reading statistics are up to date" +msgstr "สถิติการอ่านเป็นปัจจุบันแล้ว" + +msgid "Reading statistics pushed" +msgstr "ส่งสถิติการอ่านแล้ว" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "ส่งสถิติการอ่านไม่สำเร็จ" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "ดึงสถิติการอ่านไม่สำเร็จ" + +msgid "Reading statistics pulled" +msgstr "ดึงสถิติการอ่านแล้ว" diff --git a/apps/readest.koplugin/locales/tr/translation.po b/apps/readest.koplugin/locales/tr/translation.po index 12f215c8..eab1f1dc 100644 --- a/apps/readest.koplugin/locales/tr/translation.po +++ b/apps/readest.koplugin/locales/tr/translation.po @@ -251,6 +251,12 @@ msgstr "Otomatik senkronizasyon" msgid "Readest library" msgstr "Readest kütüphanesi" +msgid "Push stats now" +msgstr "İstatistikleri şimdi gönder" + +msgid "Pull stats now" +msgstr "İstatistikleri şimdi al" + msgid "Push books now" msgstr "Kitapları şimdi gönder" @@ -437,8 +443,17 @@ msgstr "Okuma ilerlemesi senkronize edildi" msgid "No saved reading progress found for this book" msgstr "Bu kitap için kayıtlı okuma ilerlemesi bulunamadı" +msgid "Reading statistics are up to date" +msgstr "Okuma istatistikleri güncel" + +msgid "Reading statistics pushed" +msgstr "Okuma istatistikleri gönderildi" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Okuma istatistikleri gönderilemedi" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Okuma istatistikleri alınamadı" + +msgid "Reading statistics pulled" +msgstr "Okuma istatistikleri alındı" diff --git a/apps/readest.koplugin/locales/uk/translation.po b/apps/readest.koplugin/locales/uk/translation.po index 275a6442..c67c5cd0 100644 --- a/apps/readest.koplugin/locales/uk/translation.po +++ b/apps/readest.koplugin/locales/uk/translation.po @@ -251,6 +251,12 @@ msgstr "Автосинхронізація" msgid "Readest library" msgstr "Бібліотека Readest" +msgid "Push stats now" +msgstr "Надіслати статистику зараз" + +msgid "Pull stats now" +msgstr "Отримати статистику зараз" + msgid "Push books now" msgstr "Надіслати книги зараз" @@ -437,8 +443,17 @@ msgstr "Прогрес читання синхронізовано" msgid "No saved reading progress found for this book" msgstr "Збережений прогрес читання для цієї книги не знайдено" +msgid "Reading statistics are up to date" +msgstr "Статистика читання актуальна" + +msgid "Reading statistics pushed" +msgstr "Статистику читання надіслано" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Не вдалося надіслати статистику читання" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Не вдалося отримати статистику читання" + +msgid "Reading statistics pulled" +msgstr "Статистику читання отримано" diff --git a/apps/readest.koplugin/locales/uz/translation.po b/apps/readest.koplugin/locales/uz/translation.po index 0cd874f0..90bc9f67 100644 --- a/apps/readest.koplugin/locales/uz/translation.po +++ b/apps/readest.koplugin/locales/uz/translation.po @@ -251,6 +251,12 @@ msgstr "Avtomatik sinxronlash" msgid "Readest library" msgstr "Readest kutubxonasi" +msgid "Push stats now" +msgstr "Statistikani hozir yuborish" + +msgid "Pull stats now" +msgstr "Statistikani hozir olish" + msgid "Push books now" msgstr "Kitoblarni hozir yuborish" @@ -437,8 +443,17 @@ msgstr "Oʻqish jarayoni sinxronlandi" msgid "No saved reading progress found for this book" msgstr "Ushbu kitob uchun saqlangan oʻqish jarayoni topilmadi" +msgid "Reading statistics are up to date" +msgstr "Oʻqish statistikasi eng songgi holatda" + +msgid "Reading statistics pushed" +msgstr "Oʻqish statistikasi yuborildi" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Oʻqish statistikasini yuborib boʻlmadi" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Oʻqish statistikasini olib boʻlmadi" + +msgid "Reading statistics pulled" +msgstr "Oʻqish statistikasi olindi" diff --git a/apps/readest.koplugin/locales/vi/translation.po b/apps/readest.koplugin/locales/vi/translation.po index d1553fad..ada33cfc 100644 --- a/apps/readest.koplugin/locales/vi/translation.po +++ b/apps/readest.koplugin/locales/vi/translation.po @@ -251,6 +251,12 @@ msgstr "Tự động đồng bộ" msgid "Readest library" msgstr "Thư viện Readest" +msgid "Push stats now" +msgstr "Gửi thống kê ngay" + +msgid "Pull stats now" +msgstr "Lấy thống kê ngay" + msgid "Push books now" msgstr "Gửi sách ngay" @@ -437,8 +443,17 @@ msgstr "Tiến trình đọc đã đồng bộ" msgid "No saved reading progress found for this book" msgstr "Không tìm thấy tiến trình đọc đã lưu cho sách này" +msgid "Reading statistics are up to date" +msgstr "Thống kê đọc đã được cập nhật" + +msgid "Reading statistics pushed" +msgstr "Đã đẩy thống kê đọc" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "Không thể đẩy thống kê đọc" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "Không thể lấy thống kê đọc" + +msgid "Reading statistics pulled" +msgstr "Đã lấy thống kê đọc" diff --git a/apps/readest.koplugin/locales/zh-CN/translation.po b/apps/readest.koplugin/locales/zh-CN/translation.po index cf73f4e4..f6a7a37e 100644 --- a/apps/readest.koplugin/locales/zh-CN/translation.po +++ b/apps/readest.koplugin/locales/zh-CN/translation.po @@ -251,6 +251,12 @@ msgstr "自动同步" msgid "Readest library" msgstr "Readest 书库" +msgid "Push stats now" +msgstr "立即推送统计" + +msgid "Pull stats now" +msgstr "立即拉取统计" + msgid "Push books now" msgstr "立即推送书籍" @@ -437,8 +443,17 @@ msgstr "阅读进度已同步" msgid "No saved reading progress found for this book" msgstr "未找到此书籍的已保存阅读进度" +msgid "Reading statistics are up to date" +msgstr "阅读统计已是最新" + +msgid "Reading statistics pushed" +msgstr "阅读统计已推送" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "推送阅读统计失败" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "拉取阅读统计失败" + +msgid "Reading statistics pulled" +msgstr "阅读统计已拉取" diff --git a/apps/readest.koplugin/locales/zh-TW/translation.po b/apps/readest.koplugin/locales/zh-TW/translation.po index 1802d988..c86ef4f6 100644 --- a/apps/readest.koplugin/locales/zh-TW/translation.po +++ b/apps/readest.koplugin/locales/zh-TW/translation.po @@ -251,6 +251,12 @@ msgstr "自動同步" msgid "Readest library" msgstr "Readest 書庫" +msgid "Push stats now" +msgstr "立即推送統計" + +msgid "Pull stats now" +msgstr "立即拉取統計" + msgid "Push books now" msgstr "立即推送書籍" @@ -437,8 +443,17 @@ msgstr "閱讀進度已同步" msgid "No saved reading progress found for this book" msgstr "找不到此書籍的閱讀進度" +msgid "Reading statistics are up to date" +msgstr "閱讀統計已是最新" + +msgid "Reading statistics pushed" +msgstr "閱讀統計已推送" + msgid "Failed to push reading statistics" -msgstr "" +msgstr "推送閱讀統計失敗" msgid "Failed to pull reading statistics" -msgstr "" +msgstr "拉取閱讀統計失敗" + +msgid "Reading statistics pulled" +msgstr "閱讀統計已拉取" diff --git a/apps/readest.koplugin/main.lua b/apps/readest.koplugin/main.lua index eb58b315..b7b1cc09 100644 --- a/apps/readest.koplugin/main.lua +++ b/apps/readest.koplugin/main.lua @@ -331,6 +331,24 @@ function ReadestSync:addToMainMenu(menu_items) self:openLibrary() end, }, + { + text = _("Push stats now"), + enabled_func = function() + return self.settings.access_token ~= nil and self.settings.user_id ~= nil + end, + callback = function() + self:pushBookStats(true) + end, + }, + { + text = _("Pull stats now"), + enabled_func = function() + return self.settings.access_token ~= nil and self.settings.user_id ~= nil + end, + callback = function() + self:pullBookStats(true) + end, + }, { text = _("Push books now"), enabled_func = function() @@ -538,20 +556,28 @@ end -- ── Reading statistics sync ──────────────────────────────────────── function ReadestSync:pushBookStats(interactive) + logger.dbg("ReadestStats pushBookStats: triggered, interactive=" .. tostring(interactive)) if interactive and NetworkMgr:willRerunWhenOnline(function() self:pushBookStats(interactive) end) then return end local client = self:ensureClient(interactive) - if not client then return end + if not client then + logger.dbg("ReadestStats pushBookStats: no client (not signed in / offline); skipping") + return + end SyncStats:push(self.settings, client, interactive) end function ReadestSync:pullBookStats(interactive) + logger.dbg("ReadestStats pullBookStats: triggered, interactive=" .. tostring(interactive)) if NetworkMgr:willRerunWhenOnline(function() self:pullBookStats(interactive) end) then return end local client = self:ensureClient(interactive) - if not client then return end + if not client then + logger.dbg("ReadestStats pullBookStats: no client (not signed in / offline); skipping") + return + end SyncStats:pull(self.settings, client, interactive, function() SyncAuth:logout(self.settings, self.path) end) end diff --git a/apps/readest.koplugin/readest-sync-api.json b/apps/readest.koplugin/readest-sync-api.json index 757c6439..3f54f8bb 100644 --- a/apps/readest.koplugin/readest-sync-api.json +++ b/apps/readest.koplugin/readest-sync-api.json @@ -12,6 +12,7 @@ "path": "/sync", "method": "POST", "required_params": ["books", "notes", "configs"], + "optional_params": ["statBooks", "statPages"], "payload": ["books", "notes", "configs", "statBooks", "statPages"], "expected_status": [200, 201, 301, 400, 401, 403] }, diff --git a/apps/readest.koplugin/readest_syncstats.lua b/apps/readest.koplugin/readest_syncstats.lua index a55bb2bd..5ab12550 100644 --- a/apps/readest.koplugin/readest_syncstats.lua +++ b/apps/readest.koplugin/readest_syncstats.lua @@ -2,6 +2,7 @@ local DataStorage = require("datastorage") local InfoMessage = require("ui/widget/infomessage") local UIManager = require("ui/uimanager") local SQ3 = require("lua-ljsqlite3/init") +local logger = require("logger") local _ = require("readest_i18n") local SyncStats = {} @@ -85,28 +86,60 @@ function SyncStats:applyRemote(books, pages) end function SyncStats:push(settings, client, interactive) - local cursor = settings:readSetting("stats_push_cursor") or 0 + -- `settings` is the plain readest_sync data table (see main.lua:init), so + -- the cursor is a field; persist by saving the whole table back to + -- G_reader_settings, mirroring readest_syncauth. + local cursor = settings.stats_push_cursor or 0 local books, pages = self:collectSince(cursor) - if #pages == 0 then return end + logger.dbg("ReadestStats push: cursor=" .. tostring(cursor) + .. " collected books=" .. #books .. " pages=" .. #pages + .. " interactive=" .. tostring(interactive)) + if #pages == 0 then + logger.dbg("ReadestStats push: nothing to push (no page events past cursor)") + if interactive then + UIManager:show(InfoMessage:new{ text = _("Reading statistics are up to date"), timeout = 2 }) + end + return + end local max_start = cursor for _, p in ipairs(pages) do if p.start_time > max_start then max_start = p.start_time end end + logger.dbg("ReadestStats push: dispatching " .. #pages .. " page(s); new cursor would be " + .. tostring(max_start)) + -- pushChanges declares books/notes/configs as required_params (shared /sync + -- POST contract, readest-sync-api.json); include them empty so Spore sends + -- the request — the server defaults each to [] and processes statBooks/ + -- statPages independently (apps/readest-app/src/pages/api/sync.ts). client:pushChanges( - { statBooks = books, statPages = pages }, - function(success) + { books = {}, notes = {}, configs = {}, statBooks = books, statPages = pages }, + function(success, body, status) + logger.dbg("ReadestStats push: response success=" .. tostring(success) + .. " status=" .. tostring(status)) if success then - settings:saveSetting("stats_push_cursor", max_start) - elseif interactive then - UIManager:show(InfoMessage:new{ text = _("Failed to push reading statistics"), timeout = 2 }) + settings.stats_push_cursor = max_start + G_reader_settings:saveSetting("readest_sync", settings) + logger.dbg("ReadestStats push: cursor advanced to " .. tostring(max_start)) + if interactive then + UIManager:show(InfoMessage:new{ text = _("Reading statistics pushed"), timeout = 2 }) + end + else + logger.dbg("ReadestStats push: failed, cursor unchanged; body=" .. tostring(body)) + if interactive then + UIManager:show(InfoMessage:new{ text = _("Failed to push reading statistics"), timeout = 2 }) + end end end) end function SyncStats:pull(settings, client, interactive, logout_fn) - local since = settings:readSetting("stats_pull_cursor") or 0 + local since = settings.stats_pull_cursor or 0 + logger.dbg("ReadestStats pull: since=" .. tostring(since) + .. " interactive=" .. tostring(interactive)) -- pullChanges requires since/type/book/meta_hash params (readest-sync-api.json). client:pullChanges( { since = since, type = "stats", book = "", meta_hash = "" }, function(success, response, status) + logger.dbg("ReadestStats pull: response success=" .. tostring(success) + .. " status=" .. tostring(status)) if not success then if status == 401 or status == 403 then if logout_fn then logout_fn() end @@ -116,13 +149,27 @@ function SyncStats:pull(settings, client, interactive, logout_fn) end return end + local nbooks = response and response.statBooks and #response.statBooks or 0 + local npages = response and response.statPages and #response.statPages or 0 + logger.dbg("ReadestStats pull: applying statBooks=" .. nbooks .. " statPages=" .. npages) self:applyRemote(response.statBooks, response.statPages) local newest = since for _, p in ipairs(response.statPages or {}) do local u = tonumber(p.updated_at_ms) or 0 if u > newest then newest = u end end - if newest > since then settings:saveSetting("stats_pull_cursor", newest) end + if newest > since then + settings.stats_pull_cursor = newest + G_reader_settings:saveSetting("readest_sync", settings) + logger.dbg("ReadestStats pull: cursor advanced to " .. tostring(newest)) + else + logger.dbg("ReadestStats pull: cursor unchanged (no newer rows)") + end + if interactive then + local text = npages > 0 and _("Reading statistics pulled") + or _("Reading statistics are up to date") + UIManager:show(InfoMessage:new{ text = text, timeout = 2 }) + end end) end diff --git a/apps/readest.koplugin/spec/syncstats_spec.lua b/apps/readest.koplugin/spec/syncstats_spec.lua index 1dce910c..51622478 100644 --- a/apps/readest.koplugin/spec/syncstats_spec.lua +++ b/apps/readest.koplugin/spec/syncstats_spec.lua @@ -146,4 +146,101 @@ describe("readest_syncstats", function() assert.are.equal(2, tonumber(total_pages)) -- distinct pages 1,2 assert.are.equal(212, tonumber(last_open)) -- max(start_time + duration) = 200 + 12 end) + + -- settings here is the plain readest_sync data table (as returned by + -- G_reader_settings:readSetting("readest_sync", ...)), NOT a LuaSettings + -- object — push/pull must read/persist the cursor as a field, not via + -- settings:readSetting/saveSetting (which would crash on the plain table). + -- The shared /sync POST (pushChanges) declares books/notes/configs as + -- required_params in readest-sync-api.json, so Spore rejects the request + -- before sending if any is absent. This mock mirrors that rejection so the + -- stats push must include them (empty) alongside statBooks/statPages. + local PUSH_REQUIRED = { "books", "notes", "configs" } + local function makePushClient(captured) + return { + pushChanges = function(_, payload, cb) + captured.payload = payload + for _, k in ipairs(PUSH_REQUIRED) do + if payload[k] == nil then + captured.missing = k + return cb(false) -- Spore would reject; request never sent + end + end + cb(true) + end, + } + end + + it("advances stats_push_cursor as a plain field after a successful push", function() + local conn = SQ3.open(statsDbPath()) + conn:exec("INSERT INTO book (title, authors, md5) VALUES ('T', 'A', 'md5-p');") + conn:exec("INSERT INTO page_stat_data (id_book, page, start_time, duration, total_pages) VALUES (1, 1, 100, 5, 9);") + conn:exec("INSERT INTO page_stat_data (id_book, page, start_time, duration, total_pages) VALUES (1, 2, 250, 6, 9);") + conn:close() + + local settings = { stats_push_cursor = 0 } + local captured = {} + + SyncStats:push(settings, makePushClient(captured), false) + + assert.is_nil(captured.missing) -- satisfied the pushChanges required_params + assert.are.equal(2, #captured.payload.statPages) + assert.are.equal(250, settings.stats_push_cursor) -- max start_time; only set on success + end) + + -- The "Push stats now" / "Pull stats now" menu entries call push/pull with + -- interactive=true; an interactive sync must confirm its result the way the + -- sibling "now" menu items do (a silent success looks like a no-op). + it("shows an interactive confirmation when there is nothing to push", function() + local InfoMessage = require("ui/widget/infomessage") + local UIManager = require("ui/uimanager") + local orig_new, orig_show = InfoMessage.new, UIManager.show + local shown + InfoMessage.new = function(_, o) return { text = o and o.text } end + UIManager.show = function(_, w) shown = w and w.text end + + -- fresh empty stats DB (before_each) → no page events past the cursor + SyncStats:push({ stats_push_cursor = 0 }, makePushClient({}), true) + + InfoMessage.new, UIManager.show = orig_new, orig_show + assert.are.equal("Reading statistics are up to date", shown) + end) + + -- Spore's validate() (common/Spore/Request.lua) asserts every param passed + -- to a method is in required_params ∪ optional_params ("X is not expected"), + -- and that every required_param is present. Declaring a key only under + -- `payload` controls body serialization, NOT acceptance. So the readest-sync + -- spec must list statBooks/statPages as optional_params for the stats push. + it("declares the stats push payload keys as expected pushChanges params", function() + local json = require("json") + local f = assert(io.open("readest-sync-api.json", "r")) + local spec = json.decode(f:read("*a")) + f:close() + + local method = spec.methods.pushChanges + local expected = {} + for _, k in ipairs(method.required_params or {}) do expected[k] = true end + for _, k in ipairs(method.optional_params or {}) do expected[k] = true end + + -- the exact set of keys SyncStats:push sends + for _, k in ipairs({ "books", "notes", "configs", "statBooks", "statPages" }) do + assert.is_true(expected[k] == true, k .. " must be an expected pushChanges param") + end + end) + + it("advances stats_pull_cursor as a plain field after a successful pull", function() + local settings = { stats_pull_cursor = 0 } + local response = { + statBooks = { { book_hash = "md5-pull", title = "P", authors = "A" } }, + statPages = { + { book_hash = "md5-pull", page = 1, start_time = 100, duration = 5, + total_pages = 10, updated_at_ms = 4242 }, + }, + } + local client = { pullChanges = function(_, _params, cb) cb(true, response, 200) end } + + SyncStats:pull(settings, client, false, function() end) + + assert.are.equal(4242, settings.stats_pull_cursor) -- newest updated_at_ms + end) end)