mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 08:21:39 -06:00
feat(reader): support single-page mode for fixed-layout epubs
Adds a fixedLayoutSpread preference to EPUB reader settings to allow forcing single-page display. This is particularly useful for image-based EPUBs like comics and manga. Closes #487
This commit is contained in:
@@ -200,6 +200,7 @@ describe('ReaderPreferencesService', () => {
|
||||
flow: 'paginated' as const,
|
||||
overrideBookFormatting: true,
|
||||
footerDisplayMode: 0 as const,
|
||||
fixedLayoutSpread: 'auto' as const,
|
||||
};
|
||||
|
||||
it('accepts valid footerDisplayMode values (0, 1, 2) in full epub defaults', async () => {
|
||||
@@ -225,6 +226,15 @@ describe('ReaderPreferencesService', () => {
|
||||
expect(mockRepo.upsertPreference).toHaveBeenCalledWith(7, 20, { footerDisplayMode: 1 });
|
||||
});
|
||||
|
||||
it('accepts partial epub per-book settings with fixedLayoutSpread', async () => {
|
||||
const user = makeUser();
|
||||
mockBookService.verifyFileAccess.mockResolvedValueOnce({ format: 'epub' });
|
||||
|
||||
await service.upsertPreference(user, 22, { fixedLayoutSpread: 'none' });
|
||||
|
||||
expect(mockRepo.upsertPreference).toHaveBeenCalledWith(7, 22, { fixedLayoutSpread: 'none' });
|
||||
});
|
||||
|
||||
it('rejects partial epub per-book settings with invalid footerDisplayMode', async () => {
|
||||
const user = makeUser();
|
||||
mockBookService.verifyFileAccess.mockResolvedValueOnce({ format: 'epub' });
|
||||
@@ -233,11 +243,26 @@ describe('ReaderPreferencesService', () => {
|
||||
expect(mockRepo.upsertPreference).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('rejects partial epub per-book settings with invalid fixedLayoutSpread', async () => {
|
||||
const user = makeUser();
|
||||
mockBookService.verifyFileAccess.mockResolvedValueOnce({ format: 'epub' });
|
||||
|
||||
await expect(service.upsertPreference(user, 23, { fixedLayoutSpread: 'two-page' })).rejects.toThrow(BadRequestException);
|
||||
expect(mockRepo.upsertPreference).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('requires footerDisplayMode when saving full epub defaults', async () => {
|
||||
const withoutFooterMode = { ...validEpubDefaults };
|
||||
delete (withoutFooterMode as Record<string, unknown>).footerDisplayMode;
|
||||
|
||||
await expect(service.upsertDefault(1, 'epub', withoutFooterMode)).rejects.toThrow(BadRequestException);
|
||||
});
|
||||
|
||||
it('requires fixedLayoutSpread when saving full epub defaults', async () => {
|
||||
const withoutSpread = { ...validEpubDefaults };
|
||||
delete (withoutSpread as Record<string, unknown>).fixedLayoutSpread;
|
||||
|
||||
await expect(service.upsertDefault(1, 'epub', withoutSpread)).rejects.toThrow(BadRequestException);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,6 +25,7 @@ const EPUB_SETTINGS_SCHEMA = z
|
||||
flow: z.enum(['paginated', 'scrolled']),
|
||||
overrideBookFormatting: z.boolean(),
|
||||
footerDisplayMode: z.union([z.literal(0), z.literal(1), z.literal(2)]),
|
||||
fixedLayoutSpread: z.enum(['auto', 'none']),
|
||||
})
|
||||
.strict();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user