From 7d1a60b9ea27930e817b0480bb19fc76e9468bf1 Mon Sep 17 00:00:00 2001 From: Huang Xin Date: Wed, 24 Jun 2026 13:24:30 +0800 Subject: [PATCH] feat(library): separate background texture for library and reader (#4754) * feat(library): separate background texture for library and reader (#4743) The library and reader shared a single background texture, so a reader backdrop with borders or other reading-oriented decoration looked wrong on the bookshelf. Let users set them independently. - Add device-local libraryBackground{TextureId,Opacity,Size} to SystemSettings. Each field falls back to the reader/global value when unset (getLibraryViewSettings), so an existing bookshelf looks unchanged until the user picks a library texture, then decouples per-field. No migration needed; the selection stays per-device like the reader's, while imported images keep syncing via the texture kind. - Make the Color panel's Background Image picker context-aware: opened from the library it edits the library texture, opened while reading it edits the reader texture. A sublabel states which page it applies to. - Apply the library texture at boot and on every library mount, so returning from a textured book restores the bookshelf background. - useBackgroundTexture now unmounts on 'none' instead of early-returning, since library and reader share one style element: switching a page to None must clear a texture the other page mounted. Co-Authored-By: Claude Opus 4.8 (1M context) * i18n: translate library/reader background texture labels (#4743) Add translations for the two new context sublabels ("Applies to the Library" / "Applies to the Reader") across all 33 locales, anchored to each locale's existing Library and reading terminology. Co-Authored-By: Claude Opus 4.8 (1M context) --------- Co-authored-by: Claude Opus 4.8 (1M context) --- .../public/locales/ar/translation.json | 4 +- .../public/locales/bn/translation.json | 4 +- .../public/locales/bo/translation.json | 4 +- .../public/locales/de/translation.json | 4 +- .../public/locales/el/translation.json | 4 +- .../public/locales/es/translation.json | 4 +- .../public/locales/fa/translation.json | 4 +- .../public/locales/fr/translation.json | 4 +- .../public/locales/he/translation.json | 4 +- .../public/locales/hi/translation.json | 4 +- .../public/locales/hu/translation.json | 4 +- .../public/locales/id/translation.json | 4 +- .../public/locales/it/translation.json | 4 +- .../public/locales/ja/translation.json | 4 +- .../public/locales/ko/translation.json | 4 +- .../public/locales/ms/translation.json | 4 +- .../public/locales/nl/translation.json | 4 +- .../public/locales/pl/translation.json | 4 +- .../public/locales/pt-BR/translation.json | 4 +- .../public/locales/pt/translation.json | 4 +- .../public/locales/ro/translation.json | 4 +- .../public/locales/ru/translation.json | 4 +- .../public/locales/si/translation.json | 4 +- .../public/locales/sl/translation.json | 4 +- .../public/locales/sv/translation.json | 4 +- .../public/locales/ta/translation.json | 4 +- .../public/locales/th/translation.json | 4 +- .../public/locales/tr/translation.json | 4 +- .../public/locales/uk/translation.json | 4 +- .../public/locales/uz/translation.json | 4 +- .../public/locales/vi/translation.json | 4 +- .../public/locales/zh-CN/translation.json | 4 +- .../public/locales/zh-TW/translation.json | 4 +- .../src/__tests__/helpers/settings.test.ts | 57 ++++++++++++++++++- .../hooks/useBackgroundTexture.test.tsx | 21 +++++++ apps/readest-app/src/app/library/page.tsx | 21 +++++++ apps/readest-app/src/components/Providers.tsx | 6 +- .../src/components/settings/ColorPanel.tsx | 48 ++++++++++++---- .../color/BackgroundTextureSelector.tsx | 6 +- apps/readest-app/src/helpers/settings.ts | 23 ++++++++ .../src/hooks/useBackgroundTexture.ts | 49 +++++++++------- apps/readest-app/src/types/settings.ts | 12 ++++ 42 files changed, 309 insertions(+), 66 deletions(-) diff --git a/apps/readest-app/public/locales/ar/translation.json b/apps/readest-app/public/locales/ar/translation.json index d355a26b..e416f0ff 100644 --- a/apps/readest-app/public/locales/ar/translation.json +++ b/apps/readest-app/public/locales/ar/translation.json @@ -1920,5 +1920,7 @@ "Purge & Delete": "مسح وحذف", "Purge all reading data": "مسح جميع بيانات القراءة", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "يؤدي هذا إلى مسح تقدم القراءة والملاحظات والإشارات المرجعية نهائيًا. لا يمكن التراجع عن هذا الإجراء.", - "Also erase reading progress, notes, and bookmarks.": "يمسح أيضًا تقدم القراءة والملاحظات والإشارات المرجعية." + "Also erase reading progress, notes, and bookmarks.": "يمسح أيضًا تقدم القراءة والملاحظات والإشارات المرجعية.", + "Applies to the Library": "يُطبَّق على المكتبة", + "Applies to the Reader": "يُطبَّق على واجهة القراءة" } diff --git a/apps/readest-app/public/locales/bn/translation.json b/apps/readest-app/public/locales/bn/translation.json index 003bfe53..c938998e 100644 --- a/apps/readest-app/public/locales/bn/translation.json +++ b/apps/readest-app/public/locales/bn/translation.json @@ -1788,5 +1788,7 @@ "Purge & Delete": "পরিষ্কার করে মুছুন", "Purge all reading data": "সমস্ত পড়ার ডেটা পরিষ্কার করুন", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "এটি স্থায়ীভাবে পড়ার অগ্রগতি, নোট এবং বুকমার্ক মুছে ফেলে। এটি পূর্বাবস্থায় ফেরানো যাবে না।", - "Also erase reading progress, notes, and bookmarks.": "পড়ার অগ্রগতি, নোট এবং বুকমার্কও মুছে ফেলে।" + "Also erase reading progress, notes, and bookmarks.": "পড়ার অগ্রগতি, নোট এবং বুকমার্কও মুছে ফেলে।", + "Applies to the Library": "লাইব্রেরিতে প্রযোজ্য", + "Applies to the Reader": "রিডারে প্রযোজ্য" } diff --git a/apps/readest-app/public/locales/bo/translation.json b/apps/readest-app/public/locales/bo/translation.json index 48ce36b7..d4f78b45 100644 --- a/apps/readest-app/public/locales/bo/translation.json +++ b/apps/readest-app/public/locales/bo/translation.json @@ -1755,5 +1755,7 @@ "Purge & Delete": "གཙང་སེལ་བྱས་ནས་སུབ་པ།", "Purge all reading data": "ཀློག་པའི་གཞི་གྲངས་ཡོངས་གཙང་སེལ།", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "འདིས་ཀློག་པའི་ཡར་འཕེལ་དང་། ཟིན་བྲིས། དཔེ་རྟགས་བཅས་གཏན་དུ་སུབ་ངེས་ཡིན། ཕྱིར་ལྡོག་བྱེད་མི་ཐུབ།", - "Also erase reading progress, notes, and bookmarks.": "ཀློག་པའི་ཡར་འཕེལ་དང་། ཟིན་བྲིས། དཔེ་རྟགས་བཅས་ཀྱང་སུབ་པ།" + "Also erase reading progress, notes, and bookmarks.": "ཀློག་པའི་ཡར་འཕེལ་དང་། ཟིན་བྲིས། དཔེ་རྟགས་བཅས་ཀྱང་སུབ་པ།", + "Applies to the Library": "དེབ་མཛོད་ལ་འཇུག་པ།", + "Applies to the Reader": "ཀློག་ངོས་ལ་འཇུག་པ།" } diff --git a/apps/readest-app/public/locales/de/translation.json b/apps/readest-app/public/locales/de/translation.json index a090c2c2..296756e9 100644 --- a/apps/readest-app/public/locales/de/translation.json +++ b/apps/readest-app/public/locales/de/translation.json @@ -1788,5 +1788,7 @@ "Purge & Delete": "Bereinigen und löschen", "Purge all reading data": "Alle Lesedaten bereinigen", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Dadurch werden Lesefortschritt, Notizen und Lesezeichen dauerhaft gelöscht. Dies kann nicht rückgängig gemacht werden.", - "Also erase reading progress, notes, and bookmarks.": "Löscht auch Lesefortschritt, Notizen und Lesezeichen." + "Also erase reading progress, notes, and bookmarks.": "Löscht auch Lesefortschritt, Notizen und Lesezeichen.", + "Applies to the Library": "Gilt für die Bibliothek", + "Applies to the Reader": "Gilt für die Leseansicht" } diff --git a/apps/readest-app/public/locales/el/translation.json b/apps/readest-app/public/locales/el/translation.json index 6af7ee88..4cb72530 100644 --- a/apps/readest-app/public/locales/el/translation.json +++ b/apps/readest-app/public/locales/el/translation.json @@ -1788,5 +1788,7 @@ "Purge & Delete": "Εκκαθάριση & Διαγραφή", "Purge all reading data": "Εκκαθάριση όλων των δεδομένων ανάγνωσης", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Αυτό διαγράφει οριστικά την πρόοδο ανάγνωσης, τις σημειώσεις και τους σελιδοδείκτες. Δεν είναι δυνατή η αναίρεση.", - "Also erase reading progress, notes, and bookmarks.": "Διαγράφει επίσης την πρόοδο ανάγνωσης, τις σημειώσεις και τους σελιδοδείκτες." + "Also erase reading progress, notes, and bookmarks.": "Διαγράφει επίσης την πρόοδο ανάγνωσης, τις σημειώσεις και τους σελιδοδείκτες.", + "Applies to the Library": "Ισχύει για τη βιβλιοθήκη", + "Applies to the Reader": "Ισχύει για την προβολή ανάγνωσης" } diff --git a/apps/readest-app/public/locales/es/translation.json b/apps/readest-app/public/locales/es/translation.json index 280d0872..3282cf72 100644 --- a/apps/readest-app/public/locales/es/translation.json +++ b/apps/readest-app/public/locales/es/translation.json @@ -1821,5 +1821,7 @@ "Purge & Delete": "Purgar y eliminar", "Purge all reading data": "Purgar todos los datos de lectura", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Esto borra permanentemente el progreso de lectura, las notas y los marcadores. Esta acción no se puede deshacer.", - "Also erase reading progress, notes, and bookmarks.": "También borra el progreso de lectura, las notas y los marcadores." + "Also erase reading progress, notes, and bookmarks.": "También borra el progreso de lectura, las notas y los marcadores.", + "Applies to the Library": "Se aplica a la biblioteca", + "Applies to the Reader": "Se aplica al lector" } diff --git a/apps/readest-app/public/locales/fa/translation.json b/apps/readest-app/public/locales/fa/translation.json index 0778ca53..38e2859a 100644 --- a/apps/readest-app/public/locales/fa/translation.json +++ b/apps/readest-app/public/locales/fa/translation.json @@ -1788,5 +1788,7 @@ "Purge & Delete": "پاک‌سازی و حذف", "Purge all reading data": "پاک‌سازی همه داده‌های مطالعه", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "این کار وضعیت مطالعه، یادداشت‌ها و نشانک‌ها را برای همیشه پاک می‌کند. این عمل قابل بازگشت نیست.", - "Also erase reading progress, notes, and bookmarks.": "همچنین وضعیت مطالعه، یادداشت‌ها و نشانک‌ها را پاک می‌کند." + "Also erase reading progress, notes, and bookmarks.": "همچنین وضعیت مطالعه، یادداشت‌ها و نشانک‌ها را پاک می‌کند.", + "Applies to the Library": "برای کتابخانه اعمال می‌شود", + "Applies to the Reader": "برای صفحه مطالعه اعمال می‌شود" } diff --git a/apps/readest-app/public/locales/fr/translation.json b/apps/readest-app/public/locales/fr/translation.json index bd70c60c..30d8bbb4 100644 --- a/apps/readest-app/public/locales/fr/translation.json +++ b/apps/readest-app/public/locales/fr/translation.json @@ -1821,5 +1821,7 @@ "Purge & Delete": "Purger et supprimer", "Purge all reading data": "Purger toutes les données de lecture", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Cela efface définitivement la progression de lecture, les notes et les signets. Cette action est irréversible.", - "Also erase reading progress, notes, and bookmarks.": "Efface aussi la progression de lecture, les notes et les signets." + "Also erase reading progress, notes, and bookmarks.": "Efface aussi la progression de lecture, les notes et les signets.", + "Applies to the Library": "S’applique à la bibliothèque", + "Applies to the Reader": "S’applique à la vue de lecture" } diff --git a/apps/readest-app/public/locales/he/translation.json b/apps/readest-app/public/locales/he/translation.json index 48258636..9303c7b3 100644 --- a/apps/readest-app/public/locales/he/translation.json +++ b/apps/readest-app/public/locales/he/translation.json @@ -1821,5 +1821,7 @@ "Purge & Delete": "נקה ומחק", "Purge all reading data": "נקה את כל נתוני הקריאה", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "פעולה זו מוחקת לצמיתות את התקדמות הקריאה, ההערות והסימניות. לא ניתן לבטל פעולה זו.", - "Also erase reading progress, notes, and bookmarks.": "מוחק גם את התקדמות הקריאה, ההערות והסימניות." + "Also erase reading progress, notes, and bookmarks.": "מוחק גם את התקדמות הקריאה, ההערות והסימניות.", + "Applies to the Library": "חל על הספרייה", + "Applies to the Reader": "חל על מצב הקריאה" } diff --git a/apps/readest-app/public/locales/hi/translation.json b/apps/readest-app/public/locales/hi/translation.json index eeb6bb94..aee19242 100644 --- a/apps/readest-app/public/locales/hi/translation.json +++ b/apps/readest-app/public/locales/hi/translation.json @@ -1788,5 +1788,7 @@ "Purge & Delete": "साफ़ करें और हटाएं", "Purge all reading data": "सभी पढ़ने का डेटा साफ़ करें", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "यह पढ़ने की प्रगति, नोट्स और बुकमार्क को स्थायी रूप से मिटा देता है। इसे पूर्ववत नहीं किया जा सकता।", - "Also erase reading progress, notes, and bookmarks.": "पढ़ने की प्रगति, नोट्स और बुकमार्क भी मिटा देता है।" + "Also erase reading progress, notes, and bookmarks.": "पढ़ने की प्रगति, नोट्स और बुकमार्क भी मिटा देता है।", + "Applies to the Library": "लाइब्रेरी पर लागू होता है", + "Applies to the Reader": "रीडर पर लागू होता है" } diff --git a/apps/readest-app/public/locales/hu/translation.json b/apps/readest-app/public/locales/hu/translation.json index e06cd901..a1197ee8 100644 --- a/apps/readest-app/public/locales/hu/translation.json +++ b/apps/readest-app/public/locales/hu/translation.json @@ -1788,5 +1788,7 @@ "Purge & Delete": "Tisztítás és törlés", "Purge all reading data": "Összes olvasási adat törlése", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Ez véglegesen törli az olvasási haladást, a jegyzeteket és a könyvjelzőket. A művelet nem vonható vissza.", - "Also erase reading progress, notes, and bookmarks.": "Az olvasási haladást, jegyzeteket és könyvjelzőket is törli." + "Also erase reading progress, notes, and bookmarks.": "Az olvasási haladást, jegyzeteket és könyvjelzőket is törli.", + "Applies to the Library": "A könyvtárra vonatkozik", + "Applies to the Reader": "Az olvasónézetre vonatkozik" } diff --git a/apps/readest-app/public/locales/id/translation.json b/apps/readest-app/public/locales/id/translation.json index 93165191..2cd28776 100644 --- a/apps/readest-app/public/locales/id/translation.json +++ b/apps/readest-app/public/locales/id/translation.json @@ -1755,5 +1755,7 @@ "Purge & Delete": "Bersihkan & Hapus", "Purge all reading data": "Bersihkan semua data baca", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Ini menghapus permanen progres membaca, catatan, dan penanda. Tindakan ini tidak dapat dibatalkan.", - "Also erase reading progress, notes, and bookmarks.": "Juga menghapus progres membaca, catatan, dan penanda." + "Also erase reading progress, notes, and bookmarks.": "Juga menghapus progres membaca, catatan, dan penanda.", + "Applies to the Library": "Berlaku untuk Perpustakaan", + "Applies to the Reader": "Berlaku untuk tampilan baca" } diff --git a/apps/readest-app/public/locales/it/translation.json b/apps/readest-app/public/locales/it/translation.json index 89c9dd49..4d1d8f3c 100644 --- a/apps/readest-app/public/locales/it/translation.json +++ b/apps/readest-app/public/locales/it/translation.json @@ -1821,5 +1821,7 @@ "Purge & Delete": "Svuota ed elimina", "Purge all reading data": "Elimina tutti i dati di lettura", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Questa operazione cancella definitivamente il progresso di lettura, le note e i segnalibri. Non può essere annullata.", - "Also erase reading progress, notes, and bookmarks.": "Cancella anche il progresso di lettura, le note e i segnalibri." + "Also erase reading progress, notes, and bookmarks.": "Cancella anche il progresso di lettura, le note e i segnalibri.", + "Applies to the Library": "Si applica alla libreria", + "Applies to the Reader": "Si applica alla vista di lettura" } diff --git a/apps/readest-app/public/locales/ja/translation.json b/apps/readest-app/public/locales/ja/translation.json index 71620a6c..c6c895e6 100644 --- a/apps/readest-app/public/locales/ja/translation.json +++ b/apps/readest-app/public/locales/ja/translation.json @@ -1755,5 +1755,7 @@ "Purge & Delete": "消去して削除", "Purge all reading data": "すべての読書データを消去", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "読書進捗、メモ、ブックマークが完全に消去されます。この操作は元に戻せません。", - "Also erase reading progress, notes, and bookmarks.": "読書進捗、メモ、ブックマークも消去します。" + "Also erase reading progress, notes, and bookmarks.": "読書進捗、メモ、ブックマークも消去します。", + "Applies to the Library": "ライブラリに適用されます", + "Applies to the Reader": "リーダーに適用されます" } diff --git a/apps/readest-app/public/locales/ko/translation.json b/apps/readest-app/public/locales/ko/translation.json index a311cc88..1706ad9d 100644 --- a/apps/readest-app/public/locales/ko/translation.json +++ b/apps/readest-app/public/locales/ko/translation.json @@ -1755,5 +1755,7 @@ "Purge & Delete": "데이터 지우고 삭제", "Purge all reading data": "모든 읽기 데이터 지우기", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "읽기 진행 상황, 메모, 북마크가 영구적으로 지워집니다. 이 작업은 되돌릴 수 없습니다.", - "Also erase reading progress, notes, and bookmarks.": "읽기 진행 상황, 메모, 북마크도 함께 지웁니다." + "Also erase reading progress, notes, and bookmarks.": "읽기 진행 상황, 메모, 북마크도 함께 지웁니다.", + "Applies to the Library": "라이브러리에 적용됩니다", + "Applies to the Reader": "리더에 적용됩니다" } diff --git a/apps/readest-app/public/locales/ms/translation.json b/apps/readest-app/public/locales/ms/translation.json index aa3c9c10..c721356c 100644 --- a/apps/readest-app/public/locales/ms/translation.json +++ b/apps/readest-app/public/locales/ms/translation.json @@ -1755,5 +1755,7 @@ "Purge & Delete": "Bersihkan & Padam", "Purge all reading data": "Bersihkan semua data bacaan", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Ini memadam kemajuan membaca, nota dan penanda buku secara kekal. Tindakan ini tidak boleh dibatalkan.", - "Also erase reading progress, notes, and bookmarks.": "Turut memadam kemajuan membaca, nota dan penanda buku." + "Also erase reading progress, notes, and bookmarks.": "Turut memadam kemajuan membaca, nota dan penanda buku.", + "Applies to the Library": "Digunakan pada Perpustakaan", + "Applies to the Reader": "Digunakan pada paparan bacaan" } diff --git a/apps/readest-app/public/locales/nl/translation.json b/apps/readest-app/public/locales/nl/translation.json index 1b5e46f4..15af2e2c 100644 --- a/apps/readest-app/public/locales/nl/translation.json +++ b/apps/readest-app/public/locales/nl/translation.json @@ -1788,5 +1788,7 @@ "Purge & Delete": "Wissen en verwijderen", "Purge all reading data": "Alle leesgegevens wissen", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Hiermee worden leesvoortgang, notities en bladwijzers permanent gewist. Dit kan niet ongedaan worden gemaakt.", - "Also erase reading progress, notes, and bookmarks.": "Wist ook leesvoortgang, notities en bladwijzers." + "Also erase reading progress, notes, and bookmarks.": "Wist ook leesvoortgang, notities en bladwijzers.", + "Applies to the Library": "Geldt voor de bibliotheek", + "Applies to the Reader": "Geldt voor de leesweergave" } diff --git a/apps/readest-app/public/locales/pl/translation.json b/apps/readest-app/public/locales/pl/translation.json index f2c32bbd..9d135135 100644 --- a/apps/readest-app/public/locales/pl/translation.json +++ b/apps/readest-app/public/locales/pl/translation.json @@ -1854,5 +1854,7 @@ "Purge & Delete": "Wyczyść i usuń", "Purge all reading data": "Wyczyść wszystkie dane czytania", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Spowoduje to trwałe usunięcie postępu czytania, notatek i zakładek. Tej operacji nie można cofnąć.", - "Also erase reading progress, notes, and bookmarks.": "Usuwa również postęp czytania, notatki i zakładki." + "Also erase reading progress, notes, and bookmarks.": "Usuwa również postęp czytania, notatki i zakładki.", + "Applies to the Library": "Dotyczy biblioteki", + "Applies to the Reader": "Dotyczy widoku czytania" } diff --git a/apps/readest-app/public/locales/pt-BR/translation.json b/apps/readest-app/public/locales/pt-BR/translation.json index 6f0ce524..264da340 100644 --- a/apps/readest-app/public/locales/pt-BR/translation.json +++ b/apps/readest-app/public/locales/pt-BR/translation.json @@ -1821,5 +1821,7 @@ "Purge & Delete": "Limpar e excluir", "Purge all reading data": "Limpar todos os dados de leitura", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Isso apaga permanentemente o progresso de leitura, as notas e os marcadores. Esta ação não pode ser desfeita.", - "Also erase reading progress, notes, and bookmarks.": "Também apaga o progresso de leitura, as notas e os marcadores." + "Also erase reading progress, notes, and bookmarks.": "Também apaga o progresso de leitura, as notas e os marcadores.", + "Applies to the Library": "Aplica-se à biblioteca", + "Applies to the Reader": "Aplica-se à vista de leitura" } diff --git a/apps/readest-app/public/locales/pt/translation.json b/apps/readest-app/public/locales/pt/translation.json index 6f2d5464..a4f9db94 100644 --- a/apps/readest-app/public/locales/pt/translation.json +++ b/apps/readest-app/public/locales/pt/translation.json @@ -1821,5 +1821,7 @@ "Purge & Delete": "Limpar e excluir", "Purge all reading data": "Limpar todos os dados de leitura", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Isto apaga permanentemente o progresso de leitura, notas e marcadores. Esta ação não pode ser desfeita.", - "Also erase reading progress, notes, and bookmarks.": "Também apaga o progresso de leitura, notas e marcadores." + "Also erase reading progress, notes, and bookmarks.": "Também apaga o progresso de leitura, notas e marcadores.", + "Applies to the Library": "Aplica-se à biblioteca", + "Applies to the Reader": "Aplica-se à vista de leitura" } diff --git a/apps/readest-app/public/locales/ro/translation.json b/apps/readest-app/public/locales/ro/translation.json index 7768f307..a6796f78 100644 --- a/apps/readest-app/public/locales/ro/translation.json +++ b/apps/readest-app/public/locales/ro/translation.json @@ -1821,5 +1821,7 @@ "Purge & Delete": "Curăță și șterge", "Purge all reading data": "Curăță toate datele de citire", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Aceasta șterge definitiv progresul citirii, notele și marcajele. Această acțiune nu poate fi anulată.", - "Also erase reading progress, notes, and bookmarks.": "Șterge de asemenea progresul citirii, notele și marcajele." + "Also erase reading progress, notes, and bookmarks.": "Șterge de asemenea progresul citirii, notele și marcajele.", + "Applies to the Library": "Se aplică bibliotecii", + "Applies to the Reader": "Se aplică vizualizării de lectură" } diff --git a/apps/readest-app/public/locales/ru/translation.json b/apps/readest-app/public/locales/ru/translation.json index f221fe09..ff7ea978 100644 --- a/apps/readest-app/public/locales/ru/translation.json +++ b/apps/readest-app/public/locales/ru/translation.json @@ -1854,5 +1854,7 @@ "Purge & Delete": "Очистить и удалить", "Purge all reading data": "Очистить все данные чтения", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Это безвозвратно удалит прогресс чтения, заметки и закладки. Это действие нельзя отменить.", - "Also erase reading progress, notes, and bookmarks.": "Также удаляет прогресс чтения, заметки и закладки." + "Also erase reading progress, notes, and bookmarks.": "Также удаляет прогресс чтения, заметки и закладки.", + "Applies to the Library": "Применяется к библиотеке", + "Applies to the Reader": "Применяется к режиму чтения" } diff --git a/apps/readest-app/public/locales/si/translation.json b/apps/readest-app/public/locales/si/translation.json index 8281bede..dc6bad5d 100644 --- a/apps/readest-app/public/locales/si/translation.json +++ b/apps/readest-app/public/locales/si/translation.json @@ -1788,5 +1788,7 @@ "Purge & Delete": "ඉවත් කර මකන්න", "Purge all reading data": "සියලු කියවීම් දත්ත ඉවත් කරන්න", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "මෙය කියවීමේ ප්‍රගතිය, සටහන් සහ පොත් සලකුණු ස්ථිරවම මකා දමයි. මෙය අහෝසි කළ නොහැක.", - "Also erase reading progress, notes, and bookmarks.": "කියවීමේ ප්‍රගතිය, සටහන් සහ පොත් සලකුණු ද මකා දමයි." + "Also erase reading progress, notes, and bookmarks.": "කියවීමේ ප්‍රගතිය, සටහන් සහ පොත් සලකුණු ද මකා දමයි.", + "Applies to the Library": "පුස්තකාලයට අදාළ වේ", + "Applies to the Reader": "කියවීමේ දසුනට අදාළ වේ" } diff --git a/apps/readest-app/public/locales/sl/translation.json b/apps/readest-app/public/locales/sl/translation.json index ed60c5a5..b9753039 100644 --- a/apps/readest-app/public/locales/sl/translation.json +++ b/apps/readest-app/public/locales/sl/translation.json @@ -1854,5 +1854,7 @@ "Purge & Delete": "Počisti in izbriši", "Purge all reading data": "Počisti vse podatke o branju", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "To trajno izbriše napredek branja, opombe in zaznamke. Tega ni mogoče razveljaviti.", - "Also erase reading progress, notes, and bookmarks.": "Izbriše tudi napredek branja, opombe in zaznamke." + "Also erase reading progress, notes, and bookmarks.": "Izbriše tudi napredek branja, opombe in zaznamke.", + "Applies to the Library": "Velja za knjižnico", + "Applies to the Reader": "Velja za bralni pogled" } diff --git a/apps/readest-app/public/locales/sv/translation.json b/apps/readest-app/public/locales/sv/translation.json index c56735ee..bc0eb4c4 100644 --- a/apps/readest-app/public/locales/sv/translation.json +++ b/apps/readest-app/public/locales/sv/translation.json @@ -1788,5 +1788,7 @@ "Purge & Delete": "Rensa och ta bort", "Purge all reading data": "Rensa alla läsdata", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Detta raderar permanent läsframsteg, anteckningar och bokmärken. Detta kan inte ångras.", - "Also erase reading progress, notes, and bookmarks.": "Raderar även läsframsteg, anteckningar och bokmärken." + "Also erase reading progress, notes, and bookmarks.": "Raderar även läsframsteg, anteckningar och bokmärken.", + "Applies to the Library": "Gäller biblioteket", + "Applies to the Reader": "Gäller läsvyn" } diff --git a/apps/readest-app/public/locales/ta/translation.json b/apps/readest-app/public/locales/ta/translation.json index fc8b854b..6a41d588 100644 --- a/apps/readest-app/public/locales/ta/translation.json +++ b/apps/readest-app/public/locales/ta/translation.json @@ -1788,5 +1788,7 @@ "Purge & Delete": "அழித்து நீக்கு", "Purge all reading data": "அனைத்து வாசிப்புத் தரவையும் அழி", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "இது வாசிப்பு முன்னேற்றம், குறிப்புகள் மற்றும் புக்மார்க்குகளை நிரந்தரமாக அழிக்கும். இதை மீட்டெடுக்க முடியாது.", - "Also erase reading progress, notes, and bookmarks.": "வாசிப்பு முன்னேற்றம், குறிப்புகள் மற்றும் புக்மார்க்குகளையும் அழிக்கும்." + "Also erase reading progress, notes, and bookmarks.": "வாசிப்பு முன்னேற்றம், குறிப்புகள் மற்றும் புக்மார்க்குகளையும் அழிக்கும்.", + "Applies to the Library": "நூலகத்திற்குப் பொருந்தும்", + "Applies to the Reader": "வாசிப்புப் பக்கத்திற்குப் பொருந்தும்" } diff --git a/apps/readest-app/public/locales/th/translation.json b/apps/readest-app/public/locales/th/translation.json index f0ac8b84..1c1a7302 100644 --- a/apps/readest-app/public/locales/th/translation.json +++ b/apps/readest-app/public/locales/th/translation.json @@ -1755,5 +1755,7 @@ "Purge & Delete": "ล้างและลบ", "Purge all reading data": "ล้างข้อมูลการอ่านทั้งหมด", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "การดำเนินการนี้จะลบความคืบหน้าในการอ่าน บันทึก และบุ๊กมาร์กอย่างถาวร ไม่สามารถเลิกทำได้", - "Also erase reading progress, notes, and bookmarks.": "ลบความคืบหน้าในการอ่าน บันทึก และบุ๊กมาร์กด้วย" + "Also erase reading progress, notes, and bookmarks.": "ลบความคืบหน้าในการอ่าน บันทึก และบุ๊กมาร์กด้วย", + "Applies to the Library": "ใช้กับคลังหนังสือ", + "Applies to the Reader": "ใช้กับมุมมองการอ่าน" } diff --git a/apps/readest-app/public/locales/tr/translation.json b/apps/readest-app/public/locales/tr/translation.json index ad74a06f..2c171dae 100644 --- a/apps/readest-app/public/locales/tr/translation.json +++ b/apps/readest-app/public/locales/tr/translation.json @@ -1788,5 +1788,7 @@ "Purge & Delete": "Temizle ve sil", "Purge all reading data": "Tüm okuma verilerini temizle", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Bu, okuma ilerlemesini, notları ve yer işaretlerini kalıcı olarak siler. Bu işlem geri alınamaz.", - "Also erase reading progress, notes, and bookmarks.": "Okuma ilerlemesi, notlar ve yer işaretlerini de siler." + "Also erase reading progress, notes, and bookmarks.": "Okuma ilerlemesi, notlar ve yer işaretlerini de siler.", + "Applies to the Library": "Kütüphaneye uygulanır", + "Applies to the Reader": "Okuma görünümüne uygulanır" } diff --git a/apps/readest-app/public/locales/uk/translation.json b/apps/readest-app/public/locales/uk/translation.json index 5e60e9aa..0ea5a4db 100644 --- a/apps/readest-app/public/locales/uk/translation.json +++ b/apps/readest-app/public/locales/uk/translation.json @@ -1854,5 +1854,7 @@ "Purge & Delete": "Очистити та видалити", "Purge all reading data": "Очистити всі дані читання", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Це назавжди видалить проґрес читання, нотатки та закладки. Цю дію не можна скасувати.", - "Also erase reading progress, notes, and bookmarks.": "Також видаляє проґрес читання, нотатки та закладки." + "Also erase reading progress, notes, and bookmarks.": "Також видаляє проґрес читання, нотатки та закладки.", + "Applies to the Library": "Застосовується до бібліотеки", + "Applies to the Reader": "Застосовується до режиму читання" } diff --git a/apps/readest-app/public/locales/uz/translation.json b/apps/readest-app/public/locales/uz/translation.json index bcb1ed75..8ecb94b1 100644 --- a/apps/readest-app/public/locales/uz/translation.json +++ b/apps/readest-app/public/locales/uz/translation.json @@ -1788,5 +1788,7 @@ "Purge & Delete": "Tozalash va oʻchirish", "Purge all reading data": "Barcha oʻqish maʼlumotlarini tozalash", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Bu oʻqish jarayoni, eslatmalar va xatchoʻplarni butunlay oʻchiradi. Buni qaytarib boʻlmaydi.", - "Also erase reading progress, notes, and bookmarks.": "Shuningdek, oʻqish jarayoni, eslatmalar va xatchoʻplarni ham oʻchiradi." + "Also erase reading progress, notes, and bookmarks.": "Shuningdek, oʻqish jarayoni, eslatmalar va xatchoʻplarni ham oʻchiradi.", + "Applies to the Library": "Kutubxonaga qoʻllanadi", + "Applies to the Reader": "Oʻqish koʻrinishiga qoʻllanadi" } diff --git a/apps/readest-app/public/locales/vi/translation.json b/apps/readest-app/public/locales/vi/translation.json index 9ff9ed5f..6b72168f 100644 --- a/apps/readest-app/public/locales/vi/translation.json +++ b/apps/readest-app/public/locales/vi/translation.json @@ -1755,5 +1755,7 @@ "Purge & Delete": "Dọn sạch và xóa", "Purge all reading data": "Xóa toàn bộ dữ liệu đọc", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "Thao tác này xóa vĩnh viễn tiến độ đọc, ghi chú và dấu trang. Không thể hoàn tác.", - "Also erase reading progress, notes, and bookmarks.": "Đồng thời xóa tiến độ đọc, ghi chú và dấu trang." + "Also erase reading progress, notes, and bookmarks.": "Đồng thời xóa tiến độ đọc, ghi chú và dấu trang.", + "Applies to the Library": "Áp dụng cho Thư viện", + "Applies to the Reader": "Áp dụng cho trình đọc" } diff --git a/apps/readest-app/public/locales/zh-CN/translation.json b/apps/readest-app/public/locales/zh-CN/translation.json index ea2e3ec3..b5e62776 100644 --- a/apps/readest-app/public/locales/zh-CN/translation.json +++ b/apps/readest-app/public/locales/zh-CN/translation.json @@ -1755,5 +1755,7 @@ "Purge & Delete": "清除并删除", "Purge all reading data": "清除所有阅读数据", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "这将永久清除阅读进度、笔记和书签,且无法撤销。", - "Also erase reading progress, notes, and bookmarks.": "同时清除阅读进度、笔记和书签。" + "Also erase reading progress, notes, and bookmarks.": "同时清除阅读进度、笔记和书签。", + "Applies to the Library": "应用于书库", + "Applies to the Reader": "应用于阅读界面" } diff --git a/apps/readest-app/public/locales/zh-TW/translation.json b/apps/readest-app/public/locales/zh-TW/translation.json index 21aa8d05..891aa75b 100644 --- a/apps/readest-app/public/locales/zh-TW/translation.json +++ b/apps/readest-app/public/locales/zh-TW/translation.json @@ -1755,5 +1755,7 @@ "Purge & Delete": "清除並刪除", "Purge all reading data": "清除所有閱讀資料", "This permanently erases reading progress, notes, and bookmarks. This cannot be undone.": "這將永久清除閱讀進度、筆記和書籤,且無法復原。", - "Also erase reading progress, notes, and bookmarks.": "同時清除閱讀進度、筆記和書籤。" + "Also erase reading progress, notes, and bookmarks.": "同時清除閱讀進度、筆記和書籤。", + "Applies to the Library": "套用於書庫", + "Applies to the Reader": "套用於閱讀介面" } diff --git a/apps/readest-app/src/__tests__/helpers/settings.test.ts b/apps/readest-app/src/__tests__/helpers/settings.test.ts index 1530e7c6..54a30b2b 100644 --- a/apps/readest-app/src/__tests__/helpers/settings.test.ts +++ b/apps/readest-app/src/__tests__/helpers/settings.test.ts @@ -32,7 +32,7 @@ vi.mock('@/utils/style', () => ({ getStyles: vi.fn(() => ''), })); -import { saveViewSettings } from '@/helpers/settings'; +import { getLibraryViewSettings, saveViewSettings } from '@/helpers/settings'; import { useSettingsStore } from '@/store/settingsStore'; import type { EnvConfigType } from '@/services/environment'; import type { SystemSettings } from '@/types/settings'; @@ -55,6 +55,61 @@ beforeEach(() => { } as unknown as ReturnType); }); +describe('getLibraryViewSettings', () => { + const makeTextureSettings = (overrides: Partial = {}): SystemSettings => + ({ + globalViewSettings: { + backgroundTextureId: 'paper', + backgroundOpacity: 0.6, + backgroundSize: 'cover', + }, + ...overrides, + }) as unknown as SystemSettings; + + test('inherits the reader/global texture when no library override is set', () => { + const result = getLibraryViewSettings(makeTextureSettings()); + + expect(result.backgroundTextureId).toBe('paper'); + expect(result.backgroundOpacity).toBe(0.6); + expect(result.backgroundSize).toBe('cover'); + }); + + test('uses the library overrides when they are set', () => { + const result = getLibraryViewSettings( + makeTextureSettings({ + libraryBackgroundTextureId: 'none', + libraryBackgroundOpacity: 0.3, + libraryBackgroundSize: 'contain', + }), + ); + + expect(result.backgroundTextureId).toBe('none'); + expect(result.backgroundOpacity).toBe(0.3); + expect(result.backgroundSize).toBe('contain'); + }); + + test("tolerates the store's initial empty settings (no globalViewSettings yet)", () => { + // useSettingsStore starts as `{} as SystemSettings`; the library page's + // texture effect can resolve before appService.loadSettings() populates it. + // It must yield a usable "no texture" result instead of throwing. + const result = getLibraryViewSettings({} as SystemSettings); + + expect(result.backgroundTextureId).toBe('none'); + }); + + test('resolves each field independently — an unset field still inherits', () => { + // Only the texture id is decoupled; opacity/size were never touched and + // must keep tracking the reader/global values. + const result = getLibraryViewSettings( + makeTextureSettings({ libraryBackgroundTextureId: 'sand' }), + ); + + expect(result.backgroundTextureId).toBe('sand'); + expect(result.backgroundOpacity).toBe(0.6); + expect(result.backgroundSize).toBe('cover'); + }); +}); + describe('saveViewSettings', () => { test('global write swaps the settings reference so replicaSettingsSync subscribers fire', async () => { // Mirrors the gating subscriber installed by replicaSettingsSync.initSettingsSync. diff --git a/apps/readest-app/src/__tests__/hooks/useBackgroundTexture.test.tsx b/apps/readest-app/src/__tests__/hooks/useBackgroundTexture.test.tsx index d0833590..9fe9a43e 100644 --- a/apps/readest-app/src/__tests__/hooks/useBackgroundTexture.test.tsx +++ b/apps/readest-app/src/__tests__/hooks/useBackgroundTexture.test.tsx @@ -107,4 +107,25 @@ describe('useBackgroundTexture', () => { expect(useCustomTextureStore.getState().getTexture(SAVED_TEXTURE.id)).toBeUndefined(); }); + + test('unmounts any mounted texture when textureId is "none"', async () => { + // Library/reader share the single #background-texture style element. When a + // page whose texture is "none" becomes active (e.g. returning to a + // None-background library after reading a textured book), applying it must + // actively clear the leftover texture, not silently leave it mounted. + const { mountBackgroundTexture, unmountBackgroundTexture } = await import('@/styles/textures'); + vi.mocked(mountBackgroundTexture).mockClear(); + vi.mocked(unmountBackgroundTexture).mockClear(); + + const { result } = renderHook(() => useBackgroundTexture()); + result.current.applyBackgroundTexture( + createMockEnvConfig(), + makeViewSettings({ backgroundTextureId: 'none' }), + ); + + await vi.waitFor(() => { + expect(unmountBackgroundTexture).toHaveBeenCalled(); + }); + expect(mountBackgroundTexture).not.toHaveBeenCalled(); + }); }); diff --git a/apps/readest-app/src/app/library/page.tsx b/apps/readest-app/src/app/library/page.tsx index 8cda2c67..01f3f898 100644 --- a/apps/readest-app/src/app/library/page.tsx +++ b/apps/readest-app/src/app/library/page.tsx @@ -41,6 +41,8 @@ import { useOPDSSubscriptions } from '@/hooks/useOPDSSubscriptions'; import { useBookDataStore } from '@/store/bookDataStore'; import { useTransferStore } from '@/store/transferStore'; import { useScreenWakeLock } from '@/hooks/useScreenWakeLock'; +import { useBackgroundTexture } from '@/hooks/useBackgroundTexture'; +import { getLibraryViewSettings } from '@/helpers/settings'; import { useAppUrlIngress } from '@/hooks/useAppUrlIngress'; import { useOpenWithBooks } from '@/hooks/useOpenWithBooks'; import { useOpenAnnotationLink } from '@/hooks/useOpenAnnotationLink'; @@ -241,6 +243,25 @@ const LibraryPageContent = ({ searchParams }: { searchParams: ReadonlyURLSearchP useTheme({ systemUIVisible: true, appThemeColor: 'base-200' }); useUICSS(); + // Apply the library's own background texture (separate from the reader's, + // issue #4743). Re-applies on mount so returning from a textured book + // restores the library background, and whenever the library texture — or the + // reader/global texture it inherits when unset — changes from the Color panel. + const { applyBackgroundTexture } = useBackgroundTexture(); + useEffect(() => { + applyBackgroundTexture(envConfig, getLibraryViewSettings(settings)); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [ + envConfig, + applyBackgroundTexture, + settings.libraryBackgroundTextureId, + settings.libraryBackgroundOpacity, + settings.libraryBackgroundSize, + settings.globalViewSettings?.backgroundTextureId, + settings.globalViewSettings?.backgroundOpacity, + settings.globalViewSettings?.backgroundSize, + ]); + useAppUrlIngress(); useOpenWithBooks(); useOpenAnnotationLink(); diff --git a/apps/readest-app/src/components/Providers.tsx b/apps/readest-app/src/components/Providers.tsx index b789f48d..bdb03aa2 100644 --- a/apps/readest-app/src/components/Providers.tsx +++ b/apps/readest-app/src/components/Providers.tsx @@ -25,6 +25,7 @@ import { setTelemetryDecision, TELEMETRY_OPT_OUT_KEY, } from '@/utils/telemetry'; +import { getLibraryViewSettings } from '@/helpers/settings'; import { SETTINGS_FILENAME } from '@/services/constants'; import type { AppService } from '@/types/system'; import type { SystemSettings } from '@/types/settings'; @@ -158,7 +159,10 @@ const Providers = ({ children }: { children: React.ReactNode }) => { if (settings.customTextures?.length) { useCustomTextureStore.getState().setTextures(settings.customTextures); } - applyBackgroundTexture(envConfig, globalViewSettings); + // The app boots onto the library, so apply the library background + // (which inherits the reader/global texture until decoupled). The + // reader re-applies its own texture when a book opens (issue #4743). + applyBackgroundTexture(envConfig, getLibraryViewSettings(settings)); if (globalViewSettings.isEink) { applyEinkMode(true); } diff --git a/apps/readest-app/src/components/settings/ColorPanel.tsx b/apps/readest-app/src/components/settings/ColorPanel.tsx index 58ac95a7..4411eaf1 100644 --- a/apps/readest-app/src/components/settings/ColorPanel.tsx +++ b/apps/readest-app/src/components/settings/ColorPanel.tsx @@ -15,7 +15,7 @@ import { useSettingsStore } from '@/store/settingsStore'; import { useResetViewSettings } from '@/hooks/useResetSettings'; import { useCustomTextureStore } from '@/store/customTextureStore'; import { queueReplicaBinaryUpload } from '@/services/sync/replicaBinaryUpload'; -import { saveViewSettings } from '@/helpers/settings'; +import { saveSysSettings, saveViewSettings } from '@/helpers/settings'; import { manageSyntaxHighlighting } from '@/utils/highlightjs'; import { SettingsPanelPanelProp } from './SettingsDialog'; import { useFileSelector } from '@/hooks/useFileSelector'; @@ -42,6 +42,21 @@ const ColorPanel: React.FC = ({ bookKey, onRegisterReset const { getView, getViewSettings } = useReaderStore(); const viewSettings = getViewSettings(bookKey) || settings.globalViewSettings; + // The Background Image picker is context-aware (issue #4743): opened from the + // library (no bookKey) it edits the library's own texture, which falls back + // to the reader/global value per-field until decoupled; opened while reading + // it edits the reader texture exactly as before. + const isLibraryContext = !bookKey; + const currentTextureId = isLibraryContext + ? (settings.libraryBackgroundTextureId ?? viewSettings.backgroundTextureId) + : viewSettings.backgroundTextureId; + const currentBackgroundOpacity = isLibraryContext + ? (settings.libraryBackgroundOpacity ?? viewSettings.backgroundOpacity) + : viewSettings.backgroundOpacity; + const currentBackgroundSize = isLibraryContext + ? (settings.libraryBackgroundSize ?? viewSettings.backgroundSize) + : viewSettings.backgroundSize; + const [invertImgColorInDark, setInvertImgColorInDark] = useState( viewSettings.invertImgColorInDark, ); @@ -51,9 +66,9 @@ const ColorPanel: React.FC = ({ bookKey, onRegisterReset const [overrideColor, setOverrideColor] = useState(viewSettings.overrideColor); const [codeHighlighting, setcodeHighlighting] = useState(viewSettings.codeHighlighting); const [codeLanguage, setCodeLanguage] = useState(viewSettings.codeLanguage); - const [selectedTextureId, setSelectedTextureId] = useState(viewSettings.backgroundTextureId); - const [backgroundOpacity, setBackgroundOpacity] = useState(viewSettings.backgroundOpacity); - const [backgroundSize, setBackgroundSize] = useState(viewSettings.backgroundSize); + const [selectedTextureId, setSelectedTextureId] = useState(currentTextureId); + const [backgroundOpacity, setBackgroundOpacity] = useState(currentBackgroundOpacity); + const [backgroundSize, setBackgroundSize] = useState(currentBackgroundSize); const [highlightOpacity, setHighlightOpacity] = useState(viewSettings.highlightOpacity ?? 0.3); const [customHighlightColors, setCustomHighlightColors] = useState( settings.globalReadSettings.customHighlightColors, @@ -161,22 +176,34 @@ const ColorPanel: React.FC = ({ bookKey, onRegisterReset }, [codeHighlighting, codeLanguage]); useEffect(() => { - if (selectedTextureId === viewSettings.backgroundTextureId) return; - saveViewSettings(envConfig, bookKey, 'backgroundTextureId', selectedTextureId); + if (selectedTextureId === currentTextureId) return; + if (isLibraryContext) { + saveSysSettings(envConfig, 'libraryBackgroundTextureId', selectedTextureId); + } else { + saveViewSettings(envConfig, bookKey, 'backgroundTextureId', selectedTextureId); + } applyBackgroundTexture(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedTextureId]); useEffect(() => { - if (backgroundOpacity === viewSettings.backgroundOpacity) return; - saveViewSettings(envConfig, bookKey, 'backgroundOpacity', backgroundOpacity); + if (backgroundOpacity === currentBackgroundOpacity) return; + if (isLibraryContext) { + saveSysSettings(envConfig, 'libraryBackgroundOpacity', backgroundOpacity); + } else { + saveViewSettings(envConfig, bookKey, 'backgroundOpacity', backgroundOpacity); + } applyBackgroundTexture(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [backgroundOpacity]); useEffect(() => { - if (backgroundSize === viewSettings.backgroundSize) return; - saveViewSettings(envConfig, bookKey, 'backgroundSize', backgroundSize); + if (backgroundSize === currentBackgroundSize) return; + if (isLibraryContext) { + saveSysSettings(envConfig, 'libraryBackgroundSize', backgroundSize); + } else { + saveViewSettings(envConfig, bookKey, 'backgroundSize', backgroundSize); + } applyBackgroundTexture(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [backgroundSize]); @@ -364,6 +391,7 @@ const ColorPanel: React.FC = ({ bookKey, onRegisterReset !t.deletedAt)} + scopeLabel={isLibraryContext ? _('Applies to the Library') : _('Applies to the Reader')} selectedTextureId={selectedTextureId} backgroundOpacity={backgroundOpacity} backgroundSize={backgroundSize} diff --git a/apps/readest-app/src/components/settings/color/BackgroundTextureSelector.tsx b/apps/readest-app/src/components/settings/color/BackgroundTextureSelector.tsx index 1da7fa43..77b6ab92 100644 --- a/apps/readest-app/src/components/settings/color/BackgroundTextureSelector.tsx +++ b/apps/readest-app/src/components/settings/color/BackgroundTextureSelector.tsx @@ -15,6 +15,8 @@ interface Texture { interface BackgroundTextureSelectorProps { predefinedTextures: Texture[]; customTextures: Texture[]; + /** Optional sublabel clarifying which page this texture applies to (#4743). */ + scopeLabel?: string; selectedTextureId: string; backgroundOpacity: number; backgroundSize: string; @@ -28,6 +30,7 @@ interface BackgroundTextureSelectorProps { const BackgroundTextureSelector: React.FC = ({ predefinedTextures, customTextures, + scopeLabel, selectedTextureId, backgroundOpacity, backgroundSize, @@ -44,7 +47,8 @@ const BackgroundTextureSelector: React.FC = ({ return (
- {_('Background Image')} + {_('Background Image')} + {scopeLabel &&

{scopeLabel}

}
{allTextures.map((texture) => ( // The swatch is a div (not a