From 01b4e3530d168cfac819488e997fb22def828684 Mon Sep 17 00:00:00 2001 From: Mohammed Efaz Date: Wed, 28 Jan 2026 06:26:57 +0100 Subject: [PATCH] feat: toggle finished manually (#3091) --- .../public/locales/ar/translation.json | 10 +- .../public/locales/bn/translation.json | 10 +- .../public/locales/bo/translation.json | 10 +- .../public/locales/de/translation.json | 10 +- .../public/locales/el/translation.json | 10 +- .../public/locales/en/translation.json | 10 +- .../public/locales/es/translation.json | 10 +- .../public/locales/fa/translation.json | 10 +- .../public/locales/fr/translation.json | 10 +- .../public/locales/hi/translation.json | 10 +- .../public/locales/id/translation.json | 10 +- .../public/locales/it/translation.json | 10 +- .../public/locales/ja/translation.json | 10 +- .../public/locales/ko/translation.json | 10 +- .../public/locales/ms/translation.json | 10 +- .../public/locales/nl/translation.json | 10 +- .../public/locales/pl/translation.json | 10 +- .../public/locales/pt/translation.json | 10 +- .../public/locales/ru/translation.json | 10 +- .../public/locales/si/translation.json | 10 +- .../public/locales/sv/translation.json | 10 +- .../public/locales/ta/translation.json | 10 +- .../public/locales/th/translation.json | 10 +- .../public/locales/tr/translation.json | 10 +- .../public/locales/uk/translation.json | 10 +- .../public/locales/vi/translation.json | 10 +- .../public/locales/zh-CN/translation.json | 10 +- .../public/locales/zh-TW/translation.json | 10 +- .../src/app/library/components/BookItem.tsx | 7 +- .../src/app/library/components/Bookshelf.tsx | 126 +++++++++++++++++- .../app/library/components/BookshelfItem.tsx | 31 ++++- .../library/components/ReadingProgress.tsx | 22 ++- .../library/components/SelectModeActions.tsx | 20 ++- .../app/library/components/StatusBadge.tsx | 39 ++++++ apps/readest-app/src/store/readerStore.ts | 20 ++- apps/readest-app/src/types/book.ts | 2 + apps/readest-app/src/types/records.ts | 1 + apps/readest-app/src/utils/transform.ts | 5 + 38 files changed, 516 insertions(+), 37 deletions(-) create mode 100644 apps/readest-app/src/app/library/components/StatusBadge.tsx diff --git a/apps/readest-app/public/locales/ar/translation.json b/apps/readest-app/public/locales/ar/translation.json index bb960581..fa16379d 100644 --- a/apps/readest-app/public/locales/ar/translation.json +++ b/apps/readest-app/public/locales/ar/translation.json @@ -998,5 +998,13 @@ "Ollama Model": "نموذج Ollama", "AI Gateway Model": "نموذج بوابة الذكاء الاصطناعي", "Actions": "الإجراءات", - "Navigation": "التنقل" + "Navigation": "التنقل", + "Set status for {{count}} book(s)_one": "تعيين الحالة لـ {{count}} كتاب", + "Set status for {{count}} book(s)_other": "تعيين الحالة لـ {{count}} كتب", + "Mark as Unread": "تحديد كغير مقروء", + "Mark as Finished": "تحديد كمنتهى", + "Finished": "منتهى", + "Unread": "غير مقروء", + "Clear Status": "مسح الحالة", + "Status": "الحالة" } diff --git a/apps/readest-app/public/locales/bn/translation.json b/apps/readest-app/public/locales/bn/translation.json index 7bb6b65d..58acf000 100644 --- a/apps/readest-app/public/locales/bn/translation.json +++ b/apps/readest-app/public/locales/bn/translation.json @@ -958,5 +958,13 @@ "Ollama Model": "Ollama মডেল", "AI Gateway Model": "AI গেটওয়ে মডেল", "Actions": "অ্যাকশন", - "Navigation": "নেভিগেশন" + "Navigation": "নেভিগেশন", + "Set status for {{count}} book(s)_one": "{{count}} টি বইয়ের স্ট্যাটাস সেট করুন", + "Set status for {{count}} book(s)_other": "{{count}} টি বইয়ের স্ট্যাটাস সেট করুন", + "Mark as Unread": "পড়া হয়নি হিসেবে চিহ্নিত করুন", + "Mark as Finished": "পড়া শেষ হিসেবে চিহ্নিত করুন", + "Finished": "শেষ হয়েছে", + "Unread": "অপঠিত", + "Clear Status": "স্থিতি মুছুন", + "Status": "অবস্থা" } diff --git a/apps/readest-app/public/locales/bo/translation.json b/apps/readest-app/public/locales/bo/translation.json index 3a905551..f8f9ebad 100644 --- a/apps/readest-app/public/locales/bo/translation.json +++ b/apps/readest-app/public/locales/bo/translation.json @@ -948,5 +948,13 @@ "Ollama Model": "Ollama དཔེ་གཞི།", "AI Gateway Model": "AI Gateway དཔེ་གཞི།", "Actions": "བྱ་འགུལ།", - "Navigation": "འགྲུལ་བཞུད།" + "Navigation": "འགྲུལ་བཞུད།", + "Set status for {{count}} book(s)_one": "དེབ་ {{count}} གི་གནས་སྟངས་གཏན་འཁེལ་བྱེད།", + "Set status for {{count}} book(s)_other": "དེབ་ {{count}} གི་གནས་སྟངས་གཏན་འཁེལ་བྱེད།", + "Mark as Unread": "མ་ཀློག་པར་རྟགས་རྒྱག", + "Mark as Finished": "ཚར་བར་རྟགས་རྒྱག", + "Finished": "ཚར་སོང་།", + "Unread": "མ་ཀློག་པ།", + "Clear Status": "གནས་སྟངས་གཙང་མ།", + "Status": "གནས་སྟངས།" } diff --git a/apps/readest-app/public/locales/de/translation.json b/apps/readest-app/public/locales/de/translation.json index 9492bf12..df4c12e9 100644 --- a/apps/readest-app/public/locales/de/translation.json +++ b/apps/readest-app/public/locales/de/translation.json @@ -958,5 +958,13 @@ "Ollama Model": "Ollama-Modell", "AI Gateway Model": "AI Gateway-Modell", "Actions": "Aktionen", - "Navigation": "Navigation" + "Navigation": "Navigation", + "Set status for {{count}} book(s)_one": "Status für {{count}} Buch festlegen", + "Set status for {{count}} book(s)_other": "Status für {{count}} Bücher festlegen", + "Mark as Unread": "Als ungelesen markieren", + "Mark as Finished": "Als beendet markieren", + "Finished": "Beendet", + "Unread": "Ungelesen", + "Clear Status": "Status löschen", + "Status": "Status" } diff --git a/apps/readest-app/public/locales/el/translation.json b/apps/readest-app/public/locales/el/translation.json index 790802e8..3062ebe9 100644 --- a/apps/readest-app/public/locales/el/translation.json +++ b/apps/readest-app/public/locales/el/translation.json @@ -958,5 +958,13 @@ "Ollama Model": "Μοντέλο Ollama", "AI Gateway Model": "Μοντέλο AI Gateway", "Actions": "Ενέργειες", - "Navigation": "Πλοήγηση" + "Navigation": "Πλοήγηση", + "Set status for {{count}} book(s)_one": "Ορισμός κατάστασης για {{count}} βιβλίο", + "Set status for {{count}} book(s)_other": "Ορισμός κατάστασης για {{count}} βιβλία", + "Mark as Unread": "Σήμανση ως μη αναγνωσμένο", + "Mark as Finished": "Σήμανση ως ολοκληρωμένο", + "Finished": "Ολοκληρώθηκε", + "Unread": "Μη αναγνωσμένο", + "Clear Status": "Εκκαθάριση κατάστασης", + "Status": "Κατάσταση" } diff --git a/apps/readest-app/public/locales/en/translation.json b/apps/readest-app/public/locales/en/translation.json index 9727001b..d9327915 100644 --- a/apps/readest-app/public/locales/en/translation.json +++ b/apps/readest-app/public/locales/en/translation.json @@ -19,5 +19,13 @@ "Are you sure to delete {{count}} selected file(s)?_one": "Are you sure to delete {{count}} selected file?", "Are you sure to delete {{count}} selected file(s)?_other": "Are you sure to delete {{count}} selected files?", "Successfully imported {{count}} book(s)_one": "Successfully imported {{count}} book", - "Successfully imported {{count}} book(s)_other": "Successfully imported {{count}} books" + "Successfully imported {{count}} book(s)_other": "Successfully imported {{count}} books", + "Set status for {{count}} book(s)_one": "Set status for {{count}} book", + "Set status for {{count}} book(s)_other": "Set status for {{count}} books", + "Mark as Finished": "Mark as Finished", + "Mark as Unread": "Mark as Unread", + "Finished": "Finished", + "Unread": "Unread", + "Clear Status": "Clear Status", + "Status": "Status" } diff --git a/apps/readest-app/public/locales/es/translation.json b/apps/readest-app/public/locales/es/translation.json index c0cc6a5d..ddb4179b 100644 --- a/apps/readest-app/public/locales/es/translation.json +++ b/apps/readest-app/public/locales/es/translation.json @@ -968,5 +968,13 @@ "Ollama Model": "Modelo de Ollama", "AI Gateway Model": "Modelo de AI Gateway", "Actions": "Acciones", - "Navigation": "Navegación" + "Navigation": "Navegación", + "Set status for {{count}} book(s)_one": "Establecer estado para {{count}} libro", + "Set status for {{count}} book(s)_other": "Establecer estado para {{count}} libros", + "Mark as Unread": "Marcar como no leído", + "Mark as Finished": "Marcar como terminado", + "Finished": "Terminado", + "Unread": "Sin leer", + "Clear Status": "Borrar estado", + "Status": "Estado" } diff --git a/apps/readest-app/public/locales/fa/translation.json b/apps/readest-app/public/locales/fa/translation.json index d2b37371..4c67bfd4 100644 --- a/apps/readest-app/public/locales/fa/translation.json +++ b/apps/readest-app/public/locales/fa/translation.json @@ -958,5 +958,13 @@ "Ollama Model": "مدل Ollama", "AI Gateway Model": "مدل AI Gateway", "Actions": "عملیات", - "Navigation": "ناوبری" + "Navigation": "ناوبری", + "Set status for {{count}} book(s)_one": "تعیین وضعیت برای {{count}} کتاب", + "Set status for {{count}} book(s)_other": "تعیین وضعیت برای {{count}} کتاب", + "Mark as Unread": "علامت‌گذاری به‌عنوان خوانده‌نشده", + "Mark as Finished": "علامت‌گذاری به‌عنوان تمام‌شده", + "Finished": "تمام‌شده", + "Unread": "خوانده‌نشده", + "Clear Status": "پاک کردن وضعیت", + "Status": "وضعیت" } diff --git a/apps/readest-app/public/locales/fr/translation.json b/apps/readest-app/public/locales/fr/translation.json index b908dd5b..729908ce 100644 --- a/apps/readest-app/public/locales/fr/translation.json +++ b/apps/readest-app/public/locales/fr/translation.json @@ -968,5 +968,13 @@ "Ollama Model": "Modèle Ollama", "AI Gateway Model": "Modèle AI Gateway", "Actions": "Actions", - "Navigation": "Navigation" + "Navigation": "Navigation", + "Set status for {{count}} book(s)_one": "Définir le statut pour {{count}} livre", + "Set status for {{count}} book(s)_other": "Définir le statut pour {{count}} livres", + "Mark as Unread": "Marquer comme non lu", + "Mark as Finished": "Marquer comme terminé", + "Finished": "Terminé", + "Unread": "Non lu", + "Clear Status": "Effacer le statut", + "Status": "Statut" } diff --git a/apps/readest-app/public/locales/hi/translation.json b/apps/readest-app/public/locales/hi/translation.json index 37126d9b..1e74604a 100644 --- a/apps/readest-app/public/locales/hi/translation.json +++ b/apps/readest-app/public/locales/hi/translation.json @@ -958,5 +958,13 @@ "Ollama Model": "Ollama मॉडल", "AI Gateway Model": "AI गेटवे मॉडल", "Actions": "क्रियाएं", - "Navigation": "नेविगेशन" + "Navigation": "नेविगेशन", + "Set status for {{count}} book(s)_one": "{{count}} किताब की स्थिति सेट करें", + "Set status for {{count}} book(s)_other": "{{count}} किताबों की स्थिति सेट करें", + "Mark as Unread": "अपठित के रूप में चिह्नित करें", + "Mark as Finished": "समाप्त के रूप में चिह्नित करें", + "Finished": "समाप्त", + "Unread": "अपठित", + "Clear Status": "स्थिति साफ़ करें", + "Status": "स्थिति" } diff --git a/apps/readest-app/public/locales/id/translation.json b/apps/readest-app/public/locales/id/translation.json index 062dd570..52b8253a 100644 --- a/apps/readest-app/public/locales/id/translation.json +++ b/apps/readest-app/public/locales/id/translation.json @@ -948,5 +948,13 @@ "Ollama Model": "Model Ollama", "AI Gateway Model": "Model AI Gateway", "Actions": "Tindakan", - "Navigation": "Navigasi" + "Navigation": "Navigasi", + "Set status for {{count}} book(s)_one": "Atur status untuk {{count}} buku", + "Set status for {{count}} book(s)_other": "Atur status untuk {{count}} buku", + "Mark as Unread": "Tandai sebagai Belum Dibaca", + "Mark as Finished": "Tandai sebagai Selesai", + "Finished": "Selesai", + "Unread": "Belum Dibaca", + "Clear Status": "Hapus Status", + "Status": "Status" } diff --git a/apps/readest-app/public/locales/it/translation.json b/apps/readest-app/public/locales/it/translation.json index 4a0f5084..2e1c00b3 100644 --- a/apps/readest-app/public/locales/it/translation.json +++ b/apps/readest-app/public/locales/it/translation.json @@ -968,5 +968,13 @@ "Ollama Model": "Modello Ollama", "AI Gateway Model": "Modello AI Gateway", "Actions": "Azioni", - "Navigation": "Navigazione" + "Navigation": "Navigazione", + "Set status for {{count}} book(s)_one": "Imposta stato per {{count}} libro", + "Set status for {{count}} book(s)_other": "Imposta stato per {{count}} libri", + "Mark as Unread": "Segna come non letto", + "Mark as Finished": "Segna come finito", + "Finished": "Finito", + "Unread": "Non letto", + "Clear Status": "Cancella stato", + "Status": "Stato" } diff --git a/apps/readest-app/public/locales/ja/translation.json b/apps/readest-app/public/locales/ja/translation.json index 82a62e4c..e09d5080 100644 --- a/apps/readest-app/public/locales/ja/translation.json +++ b/apps/readest-app/public/locales/ja/translation.json @@ -948,5 +948,13 @@ "Ollama Model": "Ollamaモデル", "AI Gateway Model": "AI Gatewayモデル", "Actions": "アクション", - "Navigation": "ナビゲーション" + "Navigation": "ナビゲーション", + "Set status for {{count}} book(s)_one": "{{count}} 冊の本のステータスを設定", + "Set status for {{count}} book(s)_other": "{{count}} 冊の本のステータスを設定", + "Mark as Unread": "未読にする", + "Mark as Finished": "読了にする", + "Finished": "読了", + "Unread": "未読", + "Clear Status": "ステータスをクリア", + "Status": "ステータス" } diff --git a/apps/readest-app/public/locales/ko/translation.json b/apps/readest-app/public/locales/ko/translation.json index e83ed806..10264e76 100644 --- a/apps/readest-app/public/locales/ko/translation.json +++ b/apps/readest-app/public/locales/ko/translation.json @@ -948,5 +948,13 @@ "Ollama Model": "Ollama 모델", "AI Gateway Model": "AI 게이트웨이 모델", "Actions": "작업", - "Navigation": "탐색" + "Navigation": "탐색", + "Set status for {{count}} book(s)_one": "책 {{count}}권 상태 설정", + "Set status for {{count}} book(s)_other": "책 {{count}}권 상태 설정", + "Mark as Unread": "읽지 않음으로 표시", + "Mark as Finished": "완료로 표시", + "Finished": "완료", + "Unread": "읽지 않음", + "Clear Status": "상태 지우기", + "Status": "상태" } diff --git a/apps/readest-app/public/locales/ms/translation.json b/apps/readest-app/public/locales/ms/translation.json index cc2e3635..f3a31be5 100644 --- a/apps/readest-app/public/locales/ms/translation.json +++ b/apps/readest-app/public/locales/ms/translation.json @@ -948,5 +948,13 @@ "Ollama Model": "Model Ollama", "AI Gateway Model": "Model AI Gateway", "Actions": "Tindakan", - "Navigation": "Navigasi" + "Navigation": "Navigasi", + "Set status for {{count}} book(s)_one": "Tetapkan status untuk {{count}} buku", + "Set status for {{count}} book(s)_other": "Tetapkan status untuk {{count}} buku", + "Mark as Unread": "Tandakan sebagai Belum Dibaca", + "Mark as Finished": "Tandakan sebagai Selesai", + "Finished": "Selesai", + "Unread": "Belum Dibaca", + "Clear Status": "Kosongkan Status", + "Status": "Status" } diff --git a/apps/readest-app/public/locales/nl/translation.json b/apps/readest-app/public/locales/nl/translation.json index 352c5a5f..b3a36c61 100644 --- a/apps/readest-app/public/locales/nl/translation.json +++ b/apps/readest-app/public/locales/nl/translation.json @@ -958,5 +958,13 @@ "Ollama Model": "Ollama-model", "AI Gateway Model": "AI Gateway-model", "Actions": "Acties", - "Navigation": "Navigatie" + "Navigation": "Navigatie", + "Set status for {{count}} book(s)_one": "Stel status in voor {{count}} boek", + "Set status for {{count}} book(s)_other": "Stel status in voor {{count}} boeken", + "Mark as Unread": "Markeren als ongelezen", + "Mark as Finished": "Markeren als voltooid", + "Finished": "Voltooid", + "Unread": "Ongelezen", + "Clear Status": "Status wissen", + "Status": "Status" } diff --git a/apps/readest-app/public/locales/pl/translation.json b/apps/readest-app/public/locales/pl/translation.json index cb373441..ab55c326 100644 --- a/apps/readest-app/public/locales/pl/translation.json +++ b/apps/readest-app/public/locales/pl/translation.json @@ -978,5 +978,13 @@ "Ollama Model": "Model Ollama", "AI Gateway Model": "Model AI Gateway", "Actions": "Akcje", - "Navigation": "Nawigacja" + "Navigation": "Nawigacja", + "Set status for {{count}} book(s)_one": "Ustaw status dla {{count}} książki", + "Set status for {{count}} book(s)_other": "Ustaw status dla {{count}} książek", + "Mark as Unread": "Oznacz jako nieprzeczytane", + "Mark as Finished": "Oznacz jako ukończone", + "Finished": "Ukończone", + "Unread": "Nieprzeczytane", + "Clear Status": "Wyczyść status", + "Status": "Status" } diff --git a/apps/readest-app/public/locales/pt/translation.json b/apps/readest-app/public/locales/pt/translation.json index e71a54cc..a58eeeb7 100644 --- a/apps/readest-app/public/locales/pt/translation.json +++ b/apps/readest-app/public/locales/pt/translation.json @@ -968,5 +968,13 @@ "Ollama Model": "Modelo do Ollama", "AI Gateway Model": "Modelo de AI Gateway", "Actions": "Ações", - "Navigation": "Navegação" + "Navigation": "Navegação", + "Set status for {{count}} book(s)_one": "Definir estado para {{count}} livro", + "Set status for {{count}} book(s)_other": "Definir estado para {{count}} livros", + "Mark as Unread": "Marcar como não lido", + "Mark as Finished": "Marcar como concluído", + "Finished": "Concluído", + "Unread": "Não lido", + "Clear Status": "Limpar estado", + "Status": "Estado" } diff --git a/apps/readest-app/public/locales/ru/translation.json b/apps/readest-app/public/locales/ru/translation.json index d3e30234..60630e42 100644 --- a/apps/readest-app/public/locales/ru/translation.json +++ b/apps/readest-app/public/locales/ru/translation.json @@ -978,5 +978,13 @@ "Ollama Model": "Модель Ollama", "AI Gateway Model": "Модель AI Gateway", "Actions": "Действия", - "Navigation": "Навигация" + "Navigation": "Навигация", + "Set status for {{count}} book(s)_one": "Установить статус для {{count}} книги", + "Set status for {{count}} book(s)_other": "Установить статус для {{count}} книг", + "Mark as Unread": "Отметить как непрочитанное", + "Mark as Finished": "Отметить как прочитанное", + "Finished": "Прочитано", + "Unread": "Не прочитано", + "Clear Status": "Очистить статус", + "Status": "Статус" } diff --git a/apps/readest-app/public/locales/si/translation.json b/apps/readest-app/public/locales/si/translation.json index 725f2197..66b85368 100644 --- a/apps/readest-app/public/locales/si/translation.json +++ b/apps/readest-app/public/locales/si/translation.json @@ -958,5 +958,13 @@ "Ollama Model": "Ollama ආකෘතිය", "AI Gateway Model": "AI ਗੇਟਵੇ ਆਕෘතිය", "Actions": "ක්‍රියා", - "Navigation": "සංචාලනය" + "Navigation": "සංචාලනය", + "Set status for {{count}} book(s)_one": "{{count}} පොත සඳහා තත්ත්වය සකසන්න", + "Set status for {{count}} book(s)_other": "{{count}} පොත් සඳහා තත්ත්වය සකසන්න", + "Mark as Unread": "නොකියවූ ලෙස සලකුණු කරන්න", + "Mark as Finished": "අවසන් වූ ලෙස සලකුණු කරන්න", + "Finished": "අවසන්", + "Unread": "නොකියවූ", + "Clear Status": "තත්ත්වය හිස් කරන්න", + "Status": "තත්ත්වය" } diff --git a/apps/readest-app/public/locales/sv/translation.json b/apps/readest-app/public/locales/sv/translation.json index 6aa1dd9b..695e85ac 100644 --- a/apps/readest-app/public/locales/sv/translation.json +++ b/apps/readest-app/public/locales/sv/translation.json @@ -958,5 +958,13 @@ "Ollama Model": "Ollama-modell", "AI Gateway Model": "AI Gateway-modell", "Actions": "Åtgärder", - "Navigation": "Navigering" + "Navigation": "Navigering", + "Set status for {{count}} book(s)_one": "Ange status för {{count}} bok", + "Set status for {{count}} book(s)_other": "Ange status för {{count}} böcker", + "Mark as Unread": "Markera som oläst", + "Mark as Finished": "Markera som läst", + "Finished": "Läst", + "Unread": "Oläst", + "Clear Status": "Rensa status", + "Status": "Status" } diff --git a/apps/readest-app/public/locales/ta/translation.json b/apps/readest-app/public/locales/ta/translation.json index af2d4097..c1ff048a 100644 --- a/apps/readest-app/public/locales/ta/translation.json +++ b/apps/readest-app/public/locales/ta/translation.json @@ -958,5 +958,13 @@ "Ollama Model": "Ollama மாதிரி", "AI Gateway Model": "AI கேட்வே மாதிரி", "Actions": "செயல்கள்", - "Navigation": "வழிசெலுத்தல்" + "Navigation": "வழிசெலுத்தல்", + "Set status for {{count}} book(s)_one": "{{count}} புத்தகத்திற்கான நிலையை அமைக்கவும்", + "Set status for {{count}} book(s)_other": "{{count}} புத்தகங்களுக்கான நிலையை அமைக்கவும்", + "Mark as Unread": "படிக்காததாகக் குறிக்கவும்", + "Mark as Finished": "முடித்ததாகக் குறிக்கவும்", + "Finished": "முடிந்தது", + "Unread": "படிக்கவில்லை", + "Clear Status": "நிலையை அழி", + "Status": "நிலை" } diff --git a/apps/readest-app/public/locales/th/translation.json b/apps/readest-app/public/locales/th/translation.json index 97e54544..2ced883f 100644 --- a/apps/readest-app/public/locales/th/translation.json +++ b/apps/readest-app/public/locales/th/translation.json @@ -948,5 +948,13 @@ "Ollama Model": "โมเดล Ollama", "AI Gateway Model": "โมเดล AI Gateway", "Actions": "การกระทำ", - "Navigation": "การนำทาง" + "Navigation": "การนำทาง", + "Set status for {{count}} book(s)_one": "ตั้งสถานะสำหรับหนังสือ {{count}} เล่ม", + "Set status for {{count}} book(s)_other": "ตั้งสถานะสำหรับหนังสือ {{count}} เล่ม", + "Mark as Unread": "ทำเครื่องหมายว่ายังไม่อ่าน", + "Mark as Finished": "ทำเครื่องหมายว่าอ่านจบแล้ว", + "Finished": "อ่านจบแล้ว", + "Unread": "ยังไม่ได้อ่าน", + "Clear Status": "ล้างสถานะ", + "Status": "สถานะ" } diff --git a/apps/readest-app/public/locales/tr/translation.json b/apps/readest-app/public/locales/tr/translation.json index a2a5a2a8..30f5f182 100644 --- a/apps/readest-app/public/locales/tr/translation.json +++ b/apps/readest-app/public/locales/tr/translation.json @@ -958,5 +958,13 @@ "Ollama Model": "Ollama Modeli", "AI Gateway Model": "AI Gateway Modeli", "Actions": "Eylemler", - "Navigation": "Gezين" + "Navigation": "Gezinme", + "Set status for {{count}} book(s)_one": "{{count}} kitap için durumu ayarla", + "Set status for {{count}} book(s)_other": "{{count}} kitap için durumu ayarla", + "Mark as Unread": "Okunmadı olarak işaretle", + "Mark as Finished": "Bitirildi olarak işaretle", + "Finished": "Bitirildi", + "Unread": "Okunmadı", + "Clear Status": "Durumu Temizle", + "Status": "Durum" } diff --git a/apps/readest-app/public/locales/uk/translation.json b/apps/readest-app/public/locales/uk/translation.json index 21292a26..d3dfca7e 100644 --- a/apps/readest-app/public/locales/uk/translation.json +++ b/apps/readest-app/public/locales/uk/translation.json @@ -978,5 +978,13 @@ "Ollama Model": "Модель Ollama", "AI Gateway Model": "Модель AI Gateway", "Actions": "Дії", - "Navigation": "Навігація" + "Navigation": "Навігація", + "Set status for {{count}} book(s)_one": "Встановити статус для {{count}} книги", + "Set status for {{count}} book(s)_other": "Встановити статус для {{count}} книг", + "Mark as Unread": "Позначити як непрочитане", + "Mark as Finished": "Позначити як завершене", + "Finished": "Завершено", + "Unread": "Непрочитане", + "Clear Status": "Очистити статус", + "Status": "Статус" } diff --git a/apps/readest-app/public/locales/vi/translation.json b/apps/readest-app/public/locales/vi/translation.json index 3028d1b8..497b4b65 100644 --- a/apps/readest-app/public/locales/vi/translation.json +++ b/apps/readest-app/public/locales/vi/translation.json @@ -948,5 +948,13 @@ "Ollama Model": "Mô hình Ollama", "AI Gateway Model": "Mô hình AI Gateway", "Actions": "Hành động", - "Navigation": "Điều hướng" + "Navigation": "Điều hướng", + "Set status for {{count}} book(s)_one": "Đặt trạng thái cho {{count}} cuốn sách", + "Set status for {{count}} book(s)_other": "Đặt trạng thái cho {{count}} cuốn sách", + "Mark as Unread": "Đánh dấu là chưa đọc", + "Mark as Finished": "Đánh dấu là đã hoàn thành", + "Finished": "Đã hoàn thành", + "Unread": "Chưa đọc", + "Clear Status": "Xóa trạng thái", + "Status": "Trạng thái" } diff --git a/apps/readest-app/public/locales/zh-CN/translation.json b/apps/readest-app/public/locales/zh-CN/translation.json index b87c6bd5..c7923eef 100644 --- a/apps/readest-app/public/locales/zh-CN/translation.json +++ b/apps/readest-app/public/locales/zh-CN/translation.json @@ -948,5 +948,13 @@ "Ollama Model": "Ollama 模型", "AI Gateway Model": "AI Gateway 模型", "Actions": "操作", - "Navigation": "导航" + "Navigation": "导航", + "Set status for {{count}} book(s)_one": "设置 {{count}} 本书的状态", + "Set status for {{count}} book(s)_other": "设置 {{count}} 本书的状态", + "Mark as Unread": "标记为未读", + "Mark as Finished": "标记为已读", + "Finished": "已读", + "Unread": "未读", + "Clear Status": "清除状态", + "Status": "状态" } diff --git a/apps/readest-app/public/locales/zh-TW/translation.json b/apps/readest-app/public/locales/zh-TW/translation.json index 738c5ea6..85886bd0 100644 --- a/apps/readest-app/public/locales/zh-TW/translation.json +++ b/apps/readest-app/public/locales/zh-TW/translation.json @@ -948,5 +948,13 @@ "Ollama Model": "Ollama 模型", "AI Gateway Model": "AI Gateway 模型", "Actions": "操作", - "Navigation": "導覽" + "Navigation": "導覽", + "Set status for {{count}} book(s)_one": "設定 {{count}} 本書的狀態", + "Set status for {{count}} book(s)_other": "設定 {{count}} 本書的狀態", + "Mark as Unread": "標示為未讀", + "Mark as Finished": "標示為已讀", + "Finished": "已讀", + "Unread": "未讀", + "Clear Status": "清除狀態", + "Status": "狀態" } diff --git a/apps/readest-app/src/app/library/components/BookItem.tsx b/apps/readest-app/src/app/library/components/BookItem.tsx index a19d5f02..4e249b56 100644 --- a/apps/readest-app/src/app/library/components/BookItem.tsx +++ b/apps/readest-app/src/app/library/components/BookItem.tsx @@ -118,13 +118,16 @@ const BookItem: React.FC = ({ )}
- {book.progress && } + {(book.progress || book.readingStatus) && }
{!appService?.isMobile && (
)} + {showStatusAlert && ( +
+
+
+ {_('Set status for {{count}} book(s)', { count: getSelectedBooks().length })} +
+
+ + + + +
+
+
+ )}
); }; diff --git a/apps/readest-app/src/app/library/components/BookshelfItem.tsx b/apps/readest-app/src/app/library/components/BookshelfItem.tsx index c289b252..8245dcd6 100644 --- a/apps/readest-app/src/app/library/components/BookshelfItem.tsx +++ b/apps/readest-app/src/app/library/components/BookshelfItem.tsx @@ -15,7 +15,7 @@ import { throttle } from '@/utils/throttle'; import { LibraryCoverFitType, LibraryViewModeType } from '@/types/settings'; import { BOOK_UNGROUPED_ID, BOOK_UNGROUPED_NAME } from '@/services/constants'; import { FILE_REVEAL_LABELS, FILE_REVEAL_PLATFORMS } from '@/utils/os'; -import { Book, BooksGroup } from '@/types/book'; +import { Book, BooksGroup, ReadingStatus } from '@/types/book'; import { md5Fingerprint } from '@/utils/md5'; import BookItem from './BookItem'; import GroupItem from './GroupItem'; @@ -99,6 +99,7 @@ interface BookshelfItemProps { handleBookDelete: (book: Book, syncBooks?: boolean) => Promise; handleSetSelectMode: (selectMode: boolean) => void; handleShowDetailsBook: (book: Book) => void; + handleUpdateReadingStatus: (book: Book, status: ReadingStatus | undefined) => void; } const BookshelfItem: React.FC = ({ @@ -115,6 +116,7 @@ const BookshelfItem: React.FC = ({ handleBookDownload, handleSetSelectMode, handleShowDetailsBook, + handleUpdateReadingStatus, }) => { const _ = useTranslation(); const router = useRouter(); @@ -210,6 +212,24 @@ const BookshelfItem: React.FC = ({ handleGroupBooks(); }, }); + const markAsFinishedMenuItem = await MenuItem.new({ + text: _('Mark as Finished'), + action: async () => { + handleUpdateReadingStatus(book, 'finished'); + }, + }); + const markAsUnreadMenuItem = await MenuItem.new({ + text: _('Mark as Unread'), + action: async () => { + handleUpdateReadingStatus(book, 'unread'); + }, + }); + const clearStatusMenuItem = await MenuItem.new({ + text: _('Clear Status'), + action: async () => { + handleUpdateReadingStatus(book, undefined); + }, + }); const showBookInFinderMenuItem = await MenuItem.new({ text: _(fileRevealLabel), action: async () => { @@ -244,6 +264,15 @@ const BookshelfItem: React.FC = ({ const menu = await Menu.new(); menu.append(selectBookMenuItem); menu.append(groupBooksMenuItem); + if (book.readingStatus === 'finished') { + menu.append(markAsUnreadMenuItem); + } else { + menu.append(markAsFinishedMenuItem); + } + // show "Clear Status" option when book has an explicit status set + if (book.readingStatus === 'finished' || book.readingStatus === 'unread') { + menu.append(clearStatusMenuItem); + } menu.append(showBookDetailsMenuItem); menu.append(showBookInFinderMenuItem); if (book.uploadedAt && !book.downloadedAt) { diff --git a/apps/readest-app/src/app/library/components/ReadingProgress.tsx b/apps/readest-app/src/app/library/components/ReadingProgress.tsx index fa53c53b..bb9e887d 100644 --- a/apps/readest-app/src/app/library/components/ReadingProgress.tsx +++ b/apps/readest-app/src/app/library/components/ReadingProgress.tsx @@ -1,6 +1,8 @@ import type React from 'react'; import { memo, useMemo } from 'react'; import type { Book } from '@/types/book'; +import { useTranslation } from '@/hooks/useTranslation'; +import StatusBadge from './StatusBadge'; interface ReadingProgressProps { book: Book; @@ -19,8 +21,25 @@ const getProgressPercentage = (book: Book) => { const ReadingProgress: React.FC = memo( ({ book }) => { + const _ = useTranslation(); const progressPercentage = useMemo(() => getProgressPercentage(book), [book]); + if (book.readingStatus === 'finished') { + return ( +
+ {_('Finished')} +
+ ); + } + + if (book.readingStatus === 'unread') { + return ( +
+ {_('Unread')} +
+ ); + } + if (progressPercentage === null || Number.isNaN(progressPercentage)) { return null; } @@ -38,7 +57,8 @@ const ReadingProgress: React.FC = memo( (prevProps, nextProps) => { return ( prevProps.book.hash === nextProps.book.hash && - prevProps.book.updatedAt === nextProps.book.updatedAt + prevProps.book.updatedAt === nextProps.book.updatedAt && + prevProps.book.readingStatus === nextProps.book.readingStatus ); }, ); diff --git a/apps/readest-app/src/app/library/components/SelectModeActions.tsx b/apps/readest-app/src/app/library/components/SelectModeActions.tsx index 271c4107..a6a6716b 100644 --- a/apps/readest-app/src/app/library/components/SelectModeActions.tsx +++ b/apps/readest-app/src/app/library/components/SelectModeActions.tsx @@ -1,5 +1,11 @@ import clsx from 'clsx'; -import { MdDelete, MdOpenInNew, MdOutlineCancel, MdInfoOutline } from 'react-icons/md'; +import { + MdDelete, + MdOpenInNew, + MdOutlineCancel, + MdInfoOutline, + MdCheckCircleOutline, +} from 'react-icons/md'; import { LuFolderPlus } from 'react-icons/lu'; import { useKeyDownActions } from '@/hooks/useKeyDownActions'; import { useTranslation } from '@/hooks/useTranslation'; @@ -11,6 +17,7 @@ interface SelectModeActionsProps { onOpen: () => void; onGroup: () => void; onDetails: () => void; + onStatus: () => void; onDelete: () => void; onCancel: () => void; } @@ -21,6 +28,7 @@ const SelectModeActions: React.FC = ({ onOpen, onGroup, onDetails, + onStatus, onDelete, onCancel, }) => { @@ -66,6 +74,16 @@ const SelectModeActions: React.FC = ({
{_('Group')}
+