fix: Apply active filters to chapter count display (Closes #1793) (#1797)

* fix: Apply active filters to chapter count display (Closes #1793)

getChapterCount was always returning the total count regardless of
the active filter. When filtering by unread/downloaded/bookmarked,
the count shown in the novel header stayed the same as the total.

Added an optional filter parameter to getChapterCount and pass the
current settingsFilter from useNovel so the displayed count matches
the filtered chapter list.

* fix lint warning and add tests for filtered chapter count

- Use settingsFilter instead of novelSettings.filter in useNovel
  to fix the react-hooks/exhaustive-deps warning
- Add tests for getChapterCount with filter parameter
- Update chapterFilterToSQL mock in test setup to actually apply
  filter conditions so filtered count tests work correctly
This commit is contained in:
Definisi
2026-04-14 01:39:48 +07:00
committed by GitHub
parent 3de93c5c09
commit 01596c045a
4 changed files with 81 additions and 9 deletions
+10 -2
View File
@@ -395,10 +395,18 @@ export const getPageChapters = async (
return query.all();
};
export const getChapterCount = async (novelId: number, page: string = '1') =>
export const getChapterCount = async (
novelId: number,
page: string = '1',
filter?: ChapterFilterKey[],
) =>
await dbManager.$count(
chapterSchema,
and(eq(chapterSchema.novelId, novelId), eq(chapterSchema.page, page)),
and(
eq(chapterSchema.novelId, novelId),
eq(chapterSchema.page, page),
chapterFilterToSQL(filter),
),
);
export const getPageChaptersBatched = async (
@@ -712,6 +712,54 @@ describe('ChapterQueries', () => {
expect(result).toBe(2);
});
it('should return filtered count when filter is provided', async () => {
const testDb = getTestDb();
const novelId = await insertTestNovel(testDb, { inLibrary: true });
await insertTestChapter(testDb, novelId, {
page: '1',
unread: true,
});
await insertTestChapter(testDb, novelId, {
page: '1',
unread: false,
});
await insertTestChapter(testDb, novelId, {
page: '1',
unread: true,
});
const total = await getChapterCount(novelId, '1');
expect(total).toBe(3);
const unreadOnly = await getChapterCount(novelId, '1', ['not-read']);
expect(unreadOnly).toBe(2);
const readOnly = await getChapterCount(novelId, '1', ['read']);
expect(readOnly).toBe(1);
});
it('should return total count when no filter is provided', async () => {
const testDb = getTestDb();
const novelId = await insertTestNovel(testDb, { inLibrary: true });
await insertTestChapter(testDb, novelId, {
page: '1',
unread: true,
});
await insertTestChapter(testDb, novelId, {
page: '1',
unread: false,
});
const result = await getChapterCount(novelId, '1');
expect(result).toBe(2);
const noFilter = await getChapterCount(novelId, '1', undefined);
expect(noFilter).toBe(2);
const emptyFilter = await getChapterCount(novelId, '1', []);
expect(emptyFilter).toBe(2);
});
});
describe('getPageChaptersBatched', () => {
+20 -4
View File
@@ -115,10 +115,26 @@ jest.mock('expo-document-picker', () => ({
}));
// Mock database utilities
jest.mock('@database/utils/parser', () => ({
chapterFilterToSQL: jest.fn().mockReturnValue(undefined),
chapterOrderToSQL: jest.fn().mockReturnValue(undefined),
}));
jest.mock('@database/utils/parser', () => {
const { sql } = require('drizzle-orm');
return {
chapterFilterToSQL: jest.fn().mockImplementation(filter => {
if (!filter || !filter.length) return undefined;
const map: Record<string, string> = {
'read': '`unread`=0',
'not-read': '`unread`=1',
'downloaded': 'isDownloaded=1',
'not-downloaded': 'isDownloaded=0',
'bookmarked': 'bookmark=1',
'not-bookmarked': 'bookmark=0',
};
const parts = filter.map((f: string) => map[f]).filter(Boolean);
if (!parts.length) return undefined;
return sql.raw(parts.join(' AND '));
}),
chapterOrderToSQL: jest.fn().mockReturnValue(undefined),
};
});
// Mock database constants
jest.mock('@database/constants', () => ({
+3 -3
View File
@@ -238,7 +238,7 @@ export const useNovel = (novelOrPath: string | NovelInfo, pluginId: string) => {
const config = [novel.id, settingsSort, settingsFilter, page] as const;
let chapterCount = await getChapterCount(novel.id, page);
let chapterCount = await getChapterCount(novel.id, page, settingsFilter);
if (chapterCount) {
try {
@@ -259,7 +259,7 @@ export const useNovel = (novelOrPath: string | NovelInfo, pluginId: string) => {
});
await insertChapters(novel.id, sourceChapters);
newChapters = await _getPageChapters(...config);
chapterCount = await getChapterCount(novel.id, page);
chapterCount = await getChapterCount(novel.id, page, settingsFilter);
}
setBatchInformation({
@@ -271,7 +271,7 @@ export const useNovel = (novelOrPath: string | NovelInfo, pluginId: string) => {
const unread = await _getFirstUnreadChapter(
novel.id,
novelSettings.filter,
settingsFilter,
page,
);
setFirstUnreadChapter(unread ?? undefined);