fix: Preserve Default Category After Reordering (Closes #1922)
This commit is contained in:
@@ -28,3 +28,8 @@ export const CHAPTER_FILTER = {
|
||||
export type ChapterFilterPositiveKey = keyof typeof CHAPTER_FILTER_POSITIVE;
|
||||
export type ChapterFilterKey = keyof typeof CHAPTER_FILTER;
|
||||
export type ChapterFilter = (typeof CHAPTER_FILTER)[ChapterFilterKey];
|
||||
|
||||
export const BUILT_IN_CATEGORY_IDS = {
|
||||
default: 1,
|
||||
local: 2,
|
||||
} as const;
|
||||
|
||||
@@ -186,10 +186,10 @@ export const updateCategoryOrderInDb = async (
|
||||
}
|
||||
|
||||
await dbManager.write(async tx => {
|
||||
for (const category of categories) {
|
||||
for (const [index, category] of categories.entries()) {
|
||||
await tx
|
||||
.update(categorySchema)
|
||||
.set({ sort: category.sort })
|
||||
.set({ sort: index + 1 })
|
||||
.where(eq(categorySchema.id, category.id))
|
||||
.run();
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
import type { TransactionParameter } from '@database/manager/manager.d';
|
||||
import { getLibraryDefaultCategoryId } from '@hooks/persisted/useSettings';
|
||||
import NativeFile from '@modules/native-file';
|
||||
import { BUILT_IN_CATEGORY_IDS } from '@database/constants';
|
||||
|
||||
const getCategoryForNewNovel = async (tx: TransactionParameter) => {
|
||||
const preferredCategoryId = getLibraryDefaultCategoryId();
|
||||
@@ -40,7 +41,7 @@ const getCategoryForNewNovel = async (tx: TransactionParameter) => {
|
||||
return tx
|
||||
.select({ id: categorySchema.id })
|
||||
.from(categorySchema)
|
||||
.where(eq(categorySchema.sort, 1))
|
||||
.where(eq(categorySchema.id, BUILT_IN_CATEGORY_IDS.default))
|
||||
.get();
|
||||
};
|
||||
|
||||
@@ -174,7 +175,7 @@ export const switchNovelToLibraryQuery = async (
|
||||
.insert(novelCategorySchema)
|
||||
.values({
|
||||
novelId: novel.id,
|
||||
categoryId: 2,
|
||||
categoryId: BUILT_IN_CATEGORY_IDS.local,
|
||||
})
|
||||
.onConflictDoNothing()
|
||||
.run();
|
||||
@@ -386,7 +387,7 @@ export const updateNovelCategories = async (
|
||||
.where(
|
||||
and(
|
||||
inArray(novelCategorySchema.novelId, novelIds),
|
||||
ne(novelCategorySchema.categoryId, 2),
|
||||
ne(novelCategorySchema.categoryId, BUILT_IN_CATEGORY_IDS.local),
|
||||
),
|
||||
)
|
||||
.run();
|
||||
|
||||
@@ -212,7 +212,7 @@ describe('CategoryQueries', () => {
|
||||
});
|
||||
|
||||
describe('updateCategoryOrderInDb', () => {
|
||||
it('should update sort order for multiple categories', async () => {
|
||||
it('should persist categories using one-based display order', async () => {
|
||||
const testDb = getTestDb();
|
||||
const cat1 = await insertTestCategory(testDb, {
|
||||
name: 'Cat 1',
|
||||
@@ -231,8 +231,8 @@ describe('CategoryQueries', () => {
|
||||
const categories = await getCategoriesFromDb();
|
||||
const updated1 = categories.find(c => c.id === cat1);
|
||||
const updated2 = categories.find(c => c.id === cat2);
|
||||
expect(updated1?.sort).toBe(30);
|
||||
expect(updated2?.sort).toBe(40);
|
||||
expect(updated1?.sort).toBe(1);
|
||||
expect(updated2?.sort).toBe(2);
|
||||
});
|
||||
|
||||
it('should handle empty array', async () => {
|
||||
|
||||
@@ -13,7 +13,8 @@ import {
|
||||
clearAllTables,
|
||||
} from './testData';
|
||||
import { categorySchema, novelCategorySchema } from '@database/schema';
|
||||
import { eq, sql } from 'drizzle-orm';
|
||||
import { eq } from 'drizzle-orm';
|
||||
import { BUILT_IN_CATEGORY_IDS } from '@database/constants';
|
||||
|
||||
import {
|
||||
getAllNovels,
|
||||
@@ -178,7 +179,7 @@ describe('NovelQueries', () => {
|
||||
expect(Boolean(novel?.inLibrary)).toBe(false);
|
||||
});
|
||||
|
||||
it('should assign default category when adding to library', async () => {
|
||||
it('should fall back to the built-in default category by ID', async () => {
|
||||
const testDb = getTestDb();
|
||||
const novelId = await insertTestNovel(testDb, {
|
||||
inLibrary: false,
|
||||
@@ -186,12 +187,16 @@ describe('NovelQueries', () => {
|
||||
pluginId: 'test-plugin',
|
||||
});
|
||||
|
||||
// Get default category (sort = 1)
|
||||
const defaultCategory = await testDb.drizzleDb
|
||||
.select()
|
||||
.from(categorySchema)
|
||||
.where(sql`${categorySchema.sort} = 1`)
|
||||
.get();
|
||||
await testDb.drizzleDb
|
||||
.update(categorySchema)
|
||||
.set({ sort: 0 })
|
||||
.where(eq(categorySchema.id, BUILT_IN_CATEGORY_IDS.default))
|
||||
.run();
|
||||
await testDb.drizzleDb
|
||||
.update(categorySchema)
|
||||
.set({ sort: 1 })
|
||||
.where(eq(categorySchema.id, BUILT_IN_CATEGORY_IDS.local))
|
||||
.run();
|
||||
|
||||
await switchNovelToLibraryQuery('/test/novel', 'test-plugin');
|
||||
|
||||
@@ -202,10 +207,17 @@ describe('NovelQueries', () => {
|
||||
.all();
|
||||
|
||||
expect(associations.length).toBeGreaterThan(0);
|
||||
|
||||
expect(
|
||||
associations.some(a => a.categoryId === (defaultCategory?.id ?? -1)),
|
||||
).toBe(!!defaultCategory);
|
||||
associations.some(
|
||||
association =>
|
||||
association.categoryId === BUILT_IN_CATEGORY_IDS.default,
|
||||
),
|
||||
).toBe(true);
|
||||
expect(
|
||||
associations.some(
|
||||
association => association.categoryId === BUILT_IN_CATEGORY_IDS.local,
|
||||
),
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should assign the user-selected default category', async () => {
|
||||
@@ -257,7 +269,10 @@ describe('NovelQueries', () => {
|
||||
.all();
|
||||
|
||||
expect(
|
||||
associations.some(association => association.categoryId === 1),
|
||||
associations.some(
|
||||
association =>
|
||||
association.categoryId === BUILT_IN_CATEGORY_IDS.default,
|
||||
),
|
||||
).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -51,13 +51,8 @@ const CategoriesScreen = () => {
|
||||
return;
|
||||
}
|
||||
|
||||
const updatedOrderCategories = data.map((category, index) => ({
|
||||
...category,
|
||||
sort: index,
|
||||
}));
|
||||
|
||||
setCategories(updatedOrderCategories);
|
||||
updateCategoryOrderInDb(updatedOrderCategories);
|
||||
setCategories(data);
|
||||
updateCategoryOrderInDb(data);
|
||||
};
|
||||
|
||||
const renderItem = ({
|
||||
|
||||
Reference in New Issue
Block a user