Sort the library by reading progress (current/total pages). Books that have never been opened read 0% and sort to the unread end; groups sort by their most-progressed book. Direction reuses the existing ascending/descending toggle, so "most read first" is Descending. Adds the "Progress Read" entry to the Sort by menu and translates it across all locales. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1944,5 +1944,6 @@
|
|||||||
"Show recently read": "إظهار المقروءة مؤخرًا",
|
"Show recently read": "إظهار المقروءة مؤخرًا",
|
||||||
"Find:": "بحث:",
|
"Find:": "بحث:",
|
||||||
"Enable rule": "تفعيل القاعدة",
|
"Enable rule": "تفعيل القاعدة",
|
||||||
"Disable rule": "تعطيل القاعدة"
|
"Disable rule": "تعطيل القاعدة",
|
||||||
|
"Progress Read": "تقدم القراءة"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1812,5 +1812,6 @@
|
|||||||
"Show recently read": "সম্প্রতি পড়া দেখান",
|
"Show recently read": "সম্প্রতি পড়া দেখান",
|
||||||
"Find:": "খুঁজুন:",
|
"Find:": "খুঁজুন:",
|
||||||
"Enable rule": "নিয়ম সক্রিয় করুন",
|
"Enable rule": "নিয়ম সক্রিয় করুন",
|
||||||
"Disable rule": "নিয়ম নিষ্ক্রিয় করুন"
|
"Disable rule": "নিয়ম নিষ্ক্রিয় করুন",
|
||||||
|
"Progress Read": "পড়ার অগ্রগতি"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1773,5 +1773,6 @@
|
|||||||
"Show recently read": "ཉེ་ཆར་བཀླགས་པ་སྟོན་པ།",
|
"Show recently read": "ཉེ་ཆར་བཀླགས་པ་སྟོན་པ།",
|
||||||
"Find:": "འཚོལ་བཤེར།:",
|
"Find:": "འཚོལ་བཤེར།:",
|
||||||
"Enable rule": "སྲིད་སྒྲིག་སྤྱོད་པ།",
|
"Enable rule": "སྲིད་སྒྲིག་སྤྱོད་པ།",
|
||||||
"Disable rule": "སྲིད་སྒྲིག་སྒོ་བརྒྱབ།"
|
"Disable rule": "སྲིད་སྒྲིག་སྒོ་བརྒྱབ།",
|
||||||
|
"Progress Read": "ཀློག་པའི་ཡར་འཕེལ།"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1812,5 +1812,6 @@
|
|||||||
"Show recently read": "Zuletzt gelesen anzeigen",
|
"Show recently read": "Zuletzt gelesen anzeigen",
|
||||||
"Find:": "Suchen:",
|
"Find:": "Suchen:",
|
||||||
"Enable rule": "Regel aktivieren",
|
"Enable rule": "Regel aktivieren",
|
||||||
"Disable rule": "Regel deaktivieren"
|
"Disable rule": "Regel deaktivieren",
|
||||||
|
"Progress Read": "Lesefortschritt"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1812,5 +1812,6 @@
|
|||||||
"Show recently read": "Εμφάνιση πρόσφατα αναγνωσμένων",
|
"Show recently read": "Εμφάνιση πρόσφατα αναγνωσμένων",
|
||||||
"Find:": "Εύρεση:",
|
"Find:": "Εύρεση:",
|
||||||
"Enable rule": "Ενεργοποίηση κανόνα",
|
"Enable rule": "Ενεργοποίηση κανόνα",
|
||||||
"Disable rule": "Απενεργοποίηση κανόνα"
|
"Disable rule": "Απενεργοποίηση κανόνα",
|
||||||
|
"Progress Read": "Πρόοδος ανάγνωσης"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1845,5 +1845,6 @@
|
|||||||
"Show recently read": "Mostrar leídos recientemente",
|
"Show recently read": "Mostrar leídos recientemente",
|
||||||
"Find:": "Buscar:",
|
"Find:": "Buscar:",
|
||||||
"Enable rule": "Activar regla",
|
"Enable rule": "Activar regla",
|
||||||
"Disable rule": "Desactivar regla"
|
"Disable rule": "Desactivar regla",
|
||||||
|
"Progress Read": "Progreso de Lectura"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1812,5 +1812,6 @@
|
|||||||
"Show recently read": "نمایش موارد اخیراً خواندهشده",
|
"Show recently read": "نمایش موارد اخیراً خواندهشده",
|
||||||
"Find:": "جستجو:",
|
"Find:": "جستجو:",
|
||||||
"Enable rule": "فعال کردن قانون",
|
"Enable rule": "فعال کردن قانون",
|
||||||
"Disable rule": "غیرفعال کردن قانون"
|
"Disable rule": "غیرفعال کردن قانون",
|
||||||
|
"Progress Read": "وضعیت مطالعه"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1845,5 +1845,6 @@
|
|||||||
"Show recently read": "Afficher les lectures récentes",
|
"Show recently read": "Afficher les lectures récentes",
|
||||||
"Find:": "Rechercher :",
|
"Find:": "Rechercher :",
|
||||||
"Enable rule": "Activer la règle",
|
"Enable rule": "Activer la règle",
|
||||||
"Disable rule": "Désactiver la règle"
|
"Disable rule": "Désactiver la règle",
|
||||||
|
"Progress Read": "Progression de lecture"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1845,5 +1845,6 @@
|
|||||||
"Show recently read": "הצגת ספרים שנקראו לאחרונה",
|
"Show recently read": "הצגת ספרים שנקראו לאחרונה",
|
||||||
"Find:": "חיפוש:",
|
"Find:": "חיפוש:",
|
||||||
"Enable rule": "הפעל כלל",
|
"Enable rule": "הפעל כלל",
|
||||||
"Disable rule": "השבת כלל"
|
"Disable rule": "השבת כלל",
|
||||||
|
"Progress Read": "התקדמות קריאה"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1812,5 +1812,6 @@
|
|||||||
"Show recently read": "हाल ही में पढ़े गए दिखाएँ",
|
"Show recently read": "हाल ही में पढ़े गए दिखाएँ",
|
||||||
"Find:": "खोजें:",
|
"Find:": "खोजें:",
|
||||||
"Enable rule": "नियम सक्षम करें",
|
"Enable rule": "नियम सक्षम करें",
|
||||||
"Disable rule": "नियम अक्षम करें"
|
"Disable rule": "नियम अक्षम करें",
|
||||||
|
"Progress Read": "पढ़ने की प्रगति"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1812,5 +1812,6 @@
|
|||||||
"Show recently read": "Nemrég olvasottak megjelenítése",
|
"Show recently read": "Nemrég olvasottak megjelenítése",
|
||||||
"Find:": "Keresés:",
|
"Find:": "Keresés:",
|
||||||
"Enable rule": "Szabály engedélyezése",
|
"Enable rule": "Szabály engedélyezése",
|
||||||
"Disable rule": "Szabály letiltása"
|
"Disable rule": "Szabály letiltása",
|
||||||
|
"Progress Read": "Olvasási haladás"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1779,5 +1779,6 @@
|
|||||||
"Show recently read": "Tampilkan baru dibaca",
|
"Show recently read": "Tampilkan baru dibaca",
|
||||||
"Find:": "Cari:",
|
"Find:": "Cari:",
|
||||||
"Enable rule": "Aktifkan aturan",
|
"Enable rule": "Aktifkan aturan",
|
||||||
"Disable rule": "Nonaktifkan aturan"
|
"Disable rule": "Nonaktifkan aturan",
|
||||||
|
"Progress Read": "Progres Membaca"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1845,5 +1845,6 @@
|
|||||||
"Show recently read": "Mostra letti di recente",
|
"Show recently read": "Mostra letti di recente",
|
||||||
"Find:": "Trova:",
|
"Find:": "Trova:",
|
||||||
"Enable rule": "Attiva regola",
|
"Enable rule": "Attiva regola",
|
||||||
"Disable rule": "Disattiva regola"
|
"Disable rule": "Disattiva regola",
|
||||||
|
"Progress Read": "Progresso di lettura"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1779,5 +1779,6 @@
|
|||||||
"Show recently read": "最近読んだ本を表示",
|
"Show recently read": "最近読んだ本を表示",
|
||||||
"Find:": "検索:",
|
"Find:": "検索:",
|
||||||
"Enable rule": "ルールを有効化",
|
"Enable rule": "ルールを有効化",
|
||||||
"Disable rule": "ルールを無効化"
|
"Disable rule": "ルールを無効化",
|
||||||
|
"Progress Read": "読書進捗"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1779,5 +1779,6 @@
|
|||||||
"Show recently read": "최근 읽은 책 표시",
|
"Show recently read": "최근 읽은 책 표시",
|
||||||
"Find:": "찾기:",
|
"Find:": "찾기:",
|
||||||
"Enable rule": "규칙 활성화",
|
"Enable rule": "규칙 활성화",
|
||||||
"Disable rule": "규칙 비활성화"
|
"Disable rule": "규칙 비활성화",
|
||||||
|
"Progress Read": "읽기 진행 상황"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1779,5 +1779,6 @@
|
|||||||
"Show recently read": "Tunjukkan baru dibaca",
|
"Show recently read": "Tunjukkan baru dibaca",
|
||||||
"Find:": "Cari:",
|
"Find:": "Cari:",
|
||||||
"Enable rule": "Dayakan peraturan",
|
"Enable rule": "Dayakan peraturan",
|
||||||
"Disable rule": "Nyahdayakan peraturan"
|
"Disable rule": "Nyahdayakan peraturan",
|
||||||
|
"Progress Read": "Kemajuan Membaca"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1812,5 +1812,6 @@
|
|||||||
"Show recently read": "Onlangs gelezen tonen",
|
"Show recently read": "Onlangs gelezen tonen",
|
||||||
"Find:": "Zoeken:",
|
"Find:": "Zoeken:",
|
||||||
"Enable rule": "Regel inschakelen",
|
"Enable rule": "Regel inschakelen",
|
||||||
"Disable rule": "Regel uitschakelen"
|
"Disable rule": "Regel uitschakelen",
|
||||||
|
"Progress Read": "Leesvoortgang"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1878,5 +1878,6 @@
|
|||||||
"Show recently read": "Pokaż ostatnio czytane",
|
"Show recently read": "Pokaż ostatnio czytane",
|
||||||
"Find:": "Znajdź:",
|
"Find:": "Znajdź:",
|
||||||
"Enable rule": "Włącz regułę",
|
"Enable rule": "Włącz regułę",
|
||||||
"Disable rule": "Wyłącz regułę"
|
"Disable rule": "Wyłącz regułę",
|
||||||
|
"Progress Read": "Postęp czytania"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1845,5 +1845,6 @@
|
|||||||
"Show recently read": "Mostrar lidos recentemente",
|
"Show recently read": "Mostrar lidos recentemente",
|
||||||
"Find:": "Localizar:",
|
"Find:": "Localizar:",
|
||||||
"Enable rule": "Ativar regra",
|
"Enable rule": "Ativar regra",
|
||||||
"Disable rule": "Desativar regra"
|
"Disable rule": "Desativar regra",
|
||||||
|
"Progress Read": "Progresso de leitura"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1845,5 +1845,6 @@
|
|||||||
"Show recently read": "Mostrar lidos recentemente",
|
"Show recently read": "Mostrar lidos recentemente",
|
||||||
"Find:": "Localizar:",
|
"Find:": "Localizar:",
|
||||||
"Enable rule": "Ativar regra",
|
"Enable rule": "Ativar regra",
|
||||||
"Disable rule": "Desativar regra"
|
"Disable rule": "Desativar regra",
|
||||||
|
"Progress Read": "Progresso de Leitura"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1845,5 +1845,6 @@
|
|||||||
"Show recently read": "Afișează citite recent",
|
"Show recently read": "Afișează citite recent",
|
||||||
"Find:": "Găsește:",
|
"Find:": "Găsește:",
|
||||||
"Enable rule": "Activează regula",
|
"Enable rule": "Activează regula",
|
||||||
"Disable rule": "Dezactivează regula"
|
"Disable rule": "Dezactivează regula",
|
||||||
|
"Progress Read": "Progresul citirii"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1878,5 +1878,6 @@
|
|||||||
"Show recently read": "Показывать недавно прочитанные",
|
"Show recently read": "Показывать недавно прочитанные",
|
||||||
"Find:": "Найти:",
|
"Find:": "Найти:",
|
||||||
"Enable rule": "Включить правило",
|
"Enable rule": "Включить правило",
|
||||||
"Disable rule": "Отключить правило"
|
"Disable rule": "Отключить правило",
|
||||||
|
"Progress Read": "Прогресс чтения"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1812,5 +1812,6 @@
|
|||||||
"Show recently read": "මෑතකදී කියවූ ඒවා පෙන්වන්න",
|
"Show recently read": "මෑතකදී කියවූ ඒවා පෙන්වන්න",
|
||||||
"Find:": "සොයන්න:",
|
"Find:": "සොයන්න:",
|
||||||
"Enable rule": "නියමය සක්රීය කරන්න",
|
"Enable rule": "නියමය සක්රීය කරන්න",
|
||||||
"Disable rule": "නියමය අක්රීය කරන්න"
|
"Disable rule": "නියමය අක්රීය කරන්න",
|
||||||
|
"Progress Read": "කියවීමේ ප්රගතිය"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1878,5 +1878,6 @@
|
|||||||
"Show recently read": "Pokaži nedavno prebrano",
|
"Show recently read": "Pokaži nedavno prebrano",
|
||||||
"Find:": "Najdi:",
|
"Find:": "Najdi:",
|
||||||
"Enable rule": "Omogoči pravilo",
|
"Enable rule": "Omogoči pravilo",
|
||||||
"Disable rule": "Onemogoči pravilo"
|
"Disable rule": "Onemogoči pravilo",
|
||||||
|
"Progress Read": "Napredek branja"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1812,5 +1812,6 @@
|
|||||||
"Show recently read": "Visa nyligen lästa",
|
"Show recently read": "Visa nyligen lästa",
|
||||||
"Find:": "Sök:",
|
"Find:": "Sök:",
|
||||||
"Enable rule": "Aktivera regel",
|
"Enable rule": "Aktivera regel",
|
||||||
"Disable rule": "Inaktivera regel"
|
"Disable rule": "Inaktivera regel",
|
||||||
|
"Progress Read": "Läsframsteg"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1812,5 +1812,6 @@
|
|||||||
"Show recently read": "சமீபத்தில் படித்தவற்றைக் காட்டு",
|
"Show recently read": "சமீபத்தில் படித்தவற்றைக் காட்டு",
|
||||||
"Find:": "தேடு:",
|
"Find:": "தேடு:",
|
||||||
"Enable rule": "விதியை இயக்கு",
|
"Enable rule": "விதியை இயக்கு",
|
||||||
"Disable rule": "விதியை முடக்கு"
|
"Disable rule": "விதியை முடக்கு",
|
||||||
|
"Progress Read": "வாசிப்பு முன்னேற்றம்"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1779,5 +1779,6 @@
|
|||||||
"Show recently read": "แสดงรายการอ่านล่าสุด",
|
"Show recently read": "แสดงรายการอ่านล่าสุด",
|
||||||
"Find:": "ค้นหา:",
|
"Find:": "ค้นหา:",
|
||||||
"Enable rule": "เปิดใช้กฎ",
|
"Enable rule": "เปิดใช้กฎ",
|
||||||
"Disable rule": "ปิดใช้กฎ"
|
"Disable rule": "ปิดใช้กฎ",
|
||||||
|
"Progress Read": "ความคืบหน้าในการอ่าน"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1812,5 +1812,6 @@
|
|||||||
"Show recently read": "Son okunanları göster",
|
"Show recently read": "Son okunanları göster",
|
||||||
"Find:": "Bul:",
|
"Find:": "Bul:",
|
||||||
"Enable rule": "Kuralı etkinleştir",
|
"Enable rule": "Kuralı etkinleştir",
|
||||||
"Disable rule": "Kuralı devre dışı bırak"
|
"Disable rule": "Kuralı devre dışı bırak",
|
||||||
|
"Progress Read": "Okuma İlerlemesi"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1878,5 +1878,6 @@
|
|||||||
"Show recently read": "Показувати нещодавно прочитані",
|
"Show recently read": "Показувати нещодавно прочитані",
|
||||||
"Find:": "Знайти:",
|
"Find:": "Знайти:",
|
||||||
"Enable rule": "Увімкнути правило",
|
"Enable rule": "Увімкнути правило",
|
||||||
"Disable rule": "Вимкнути правило"
|
"Disable rule": "Вимкнути правило",
|
||||||
|
"Progress Read": "Проґрес читання"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1812,5 +1812,6 @@
|
|||||||
"Show recently read": "Yaqinda o'qilganlarni ko'rsatish",
|
"Show recently read": "Yaqinda o'qilganlarni ko'rsatish",
|
||||||
"Find:": "Topish:",
|
"Find:": "Topish:",
|
||||||
"Enable rule": "Qoidani yoqish",
|
"Enable rule": "Qoidani yoqish",
|
||||||
"Disable rule": "Qoidani o‘chirish"
|
"Disable rule": "Qoidani o‘chirish",
|
||||||
|
"Progress Read": "Oʻqish jarayoni"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1779,5 +1779,6 @@
|
|||||||
"Show recently read": "Hiển thị mục đã đọc gần đây",
|
"Show recently read": "Hiển thị mục đã đọc gần đây",
|
||||||
"Find:": "Tìm:",
|
"Find:": "Tìm:",
|
||||||
"Enable rule": "Bật quy tắc",
|
"Enable rule": "Bật quy tắc",
|
||||||
"Disable rule": "Tắt quy tắc"
|
"Disable rule": "Tắt quy tắc",
|
||||||
|
"Progress Read": "Tiến độ đọc"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1779,5 +1779,6 @@
|
|||||||
"Show recently read": "显示最近阅读",
|
"Show recently read": "显示最近阅读",
|
||||||
"Find:": "查找:",
|
"Find:": "查找:",
|
||||||
"Enable rule": "启用规则",
|
"Enable rule": "启用规则",
|
||||||
"Disable rule": "禁用规则"
|
"Disable rule": "禁用规则",
|
||||||
|
"Progress Read": "阅读进度"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1779,5 +1779,6 @@
|
|||||||
"Show recently read": "顯示最近閱讀",
|
"Show recently read": "顯示最近閱讀",
|
||||||
"Find:": "尋找:",
|
"Find:": "尋找:",
|
||||||
"Enable rule": "啟用規則",
|
"Enable rule": "啟用規則",
|
||||||
"Disable rule": "停用規則"
|
"Disable rule": "停用規則",
|
||||||
|
"Progress Read": "閱讀進度"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,6 +195,21 @@ describe('getBookSortValue', () => {
|
|||||||
const book = createMockBook({ updatedAt: 99999 });
|
const book = createMockBook({ updatedAt: 99999 });
|
||||||
expect(getBookSortValue(book, 'unknown' as LibrarySortByType)).toBe(99999);
|
expect(getBookSortValue(book, 'unknown' as LibrarySortByType)).toBe(99999);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return read ratio for Progress sort', () => {
|
||||||
|
const book = createMockBook({ progress: [50, 100] });
|
||||||
|
expect(getBookSortValue(book, LibrarySortByType.Progress)).toBe(0.5);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return 0 for Progress sort when book has no progress', () => {
|
||||||
|
const book = createMockBook({});
|
||||||
|
expect(getBookSortValue(book, LibrarySortByType.Progress)).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return 0 for Progress sort when total pages is 0', () => {
|
||||||
|
const book = createMockBook({ progress: [0, 0] });
|
||||||
|
expect(getBookSortValue(book, LibrarySortByType.Progress)).toBe(0);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('compareSortValues', () => {
|
describe('compareSortValues', () => {
|
||||||
@@ -310,4 +325,21 @@ describe('createBookSorter - additional cases', () => {
|
|||||||
expect(sorted[0]!.title).toBe('Older');
|
expect(sorted[0]!.title).toBe('Older');
|
||||||
expect(sorted[1]!.title).toBe('Newer');
|
expect(sorted[1]!.title).toBe('Newer');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should sort by reading progress ascending (unread books first)', () => {
|
||||||
|
const books = [
|
||||||
|
createMockBook({ title: 'Almost done', progress: [90, 100] }),
|
||||||
|
createMockBook({ title: 'Not started' }),
|
||||||
|
createMockBook({ title: 'Just begun', progress: [10, 100] }),
|
||||||
|
createMockBook({ title: 'Halfway', progress: [1, 2] }),
|
||||||
|
];
|
||||||
|
const sorter = createBookSorter(LibrarySortByType.Progress, 'en');
|
||||||
|
const sorted = [...books].sort(sorter);
|
||||||
|
expect(sorted.map((b) => b.title)).toEqual([
|
||||||
|
'Not started',
|
||||||
|
'Just begun',
|
||||||
|
'Halfway',
|
||||||
|
'Almost done',
|
||||||
|
]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -544,6 +544,18 @@ describe('getGroupSortValue', () => {
|
|||||||
expect(getGroupSortValue(group, LibrarySortByType.Series)).toBe('My Series');
|
expect(getGroupSortValue(group, LibrarySortByType.Series)).toBe('My Series');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should return max read ratio for progress sort', () => {
|
||||||
|
const group = createMockGroup({
|
||||||
|
books: [
|
||||||
|
createMockBook({ progress: [10, 100] }),
|
||||||
|
createMockBook({ progress: [80, 100] }),
|
||||||
|
createMockBook({}),
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(getGroupSortValue(group, LibrarySortByType.Progress)).toBe(0.8);
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle empty groups gracefully', () => {
|
it('should handle empty groups gracefully', () => {
|
||||||
const group = createMockGroup({ books: [] });
|
const group = createMockGroup({ books: [] });
|
||||||
|
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ const ViewMenu: React.FC<ViewMenuProps> = ({ setIsDropdownOpen }) => {
|
|||||||
{ label: _('Date Read'), value: LibrarySortByType.Updated },
|
{ label: _('Date Read'), value: LibrarySortByType.Updated },
|
||||||
{ label: _('Date Added'), value: LibrarySortByType.Created },
|
{ label: _('Date Added'), value: LibrarySortByType.Created },
|
||||||
{ label: _('Date Published'), value: LibrarySortByType.Published },
|
{ label: _('Date Published'), value: LibrarySortByType.Published },
|
||||||
|
{ label: _('Progress Read'), value: LibrarySortByType.Progress },
|
||||||
];
|
];
|
||||||
|
|
||||||
const sortBy2Options: { label: string; value: LibrarySecondarySortByType }[] = [
|
const sortBy2Options: { label: string; value: LibrarySecondarySortByType }[] = [
|
||||||
|
|||||||
@@ -178,6 +178,17 @@ export const createBookFilter = (queryTerm: string | null) => (item: Book) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fraction of the book that has been read, in [0, 1]. `progress` is a 1-based
|
||||||
|
* `[current, total]` page pair; books that have never been opened have no
|
||||||
|
* progress and read 0 (they sort to the unread end).
|
||||||
|
*/
|
||||||
|
const getBookReadRatio = (book: Book): number => {
|
||||||
|
const [current, total] = book.progress ?? [];
|
||||||
|
if (!current || !total || total <= 0) return 0;
|
||||||
|
return current / total;
|
||||||
|
};
|
||||||
|
|
||||||
const compareBookByKey = (a: Book, b: Book, sortBy: string, uiLanguage: string): number => {
|
const compareBookByKey = (a: Book, b: Book, sortBy: string, uiLanguage: string): number => {
|
||||||
switch (sortBy) {
|
switch (sortBy) {
|
||||||
case LibrarySortByType.Title: {
|
case LibrarySortByType.Title: {
|
||||||
@@ -196,6 +207,8 @@ const compareBookByKey = (a: Book, b: Book, sortBy: string, uiLanguage: string):
|
|||||||
return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
|
return new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime();
|
||||||
case LibrarySortByType.Format:
|
case LibrarySortByType.Format:
|
||||||
return a.format.localeCompare(b.format, uiLanguage || navigator.language);
|
return a.format.localeCompare(b.format, uiLanguage || navigator.language);
|
||||||
|
case LibrarySortByType.Progress:
|
||||||
|
return getBookReadRatio(a) - getBookReadRatio(b);
|
||||||
case LibrarySortByType.Series: {
|
case LibrarySortByType.Series: {
|
||||||
// Group by series name first so books of the same series stay consecutive,
|
// Group by series name first so books of the same series stay consecutive,
|
||||||
// then order within a series by index. Comparing index alone would interleave
|
// then order within a series by index. Comparing index alone would interleave
|
||||||
@@ -496,6 +509,9 @@ export const getBookSortValue = (book: Book, sortBy: LibrarySortByType): number
|
|||||||
case LibrarySortByType.Format:
|
case LibrarySortByType.Format:
|
||||||
return book.format;
|
return book.format;
|
||||||
|
|
||||||
|
case LibrarySortByType.Progress:
|
||||||
|
return getBookReadRatio(book);
|
||||||
|
|
||||||
case LibrarySortByType.Published: {
|
case LibrarySortByType.Published: {
|
||||||
const published = book.metadata?.published;
|
const published = book.metadata?.published;
|
||||||
if (!published) return 0;
|
if (!published) return 0;
|
||||||
@@ -555,6 +571,10 @@ export const getGroupSortValue = (
|
|||||||
// Return the most recent createdAt
|
// Return the most recent createdAt
|
||||||
return Math.max(...books.map((b) => b.createdAt));
|
return Math.max(...books.map((b) => b.createdAt));
|
||||||
|
|
||||||
|
case LibrarySortByType.Progress:
|
||||||
|
// Return the most-progressed book's read ratio
|
||||||
|
return Math.max(...books.map((b) => getBookReadRatio(b)));
|
||||||
|
|
||||||
case LibrarySortByType.Published: {
|
case LibrarySortByType.Published: {
|
||||||
// Return the most recent published date
|
// Return the most recent published date
|
||||||
const publishedDates = books
|
const publishedDates = books
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ export const LibrarySortByType = {
|
|||||||
Size: 'size',
|
Size: 'size',
|
||||||
Format: 'format',
|
Format: 'format',
|
||||||
Published: 'published',
|
Published: 'published',
|
||||||
|
Progress: 'progress',
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export type LibrarySortByType = (typeof LibrarySortByType)[keyof typeof LibrarySortByType];
|
export type LibrarySortByType = (typeof LibrarySortByType)[keyof typeof LibrarySortByType];
|
||||||
|
|||||||
Reference in New Issue
Block a user