fix: add metadata parsed from cbz zip comment, closes #639 (#688)

This commit is contained in:
Huang Xin 2025-03-24 01:18:08 +08:00 committed by GitHub
parent 14f2db730a
commit d098487cd1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 53 additions and 21 deletions

View file

@ -112,6 +112,7 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
<SectionInfo
section={sectionLabel}
showDoubleBorder={viewSettings.vertical && viewSettings.doubleBorder}
isScrolled={viewSettings.scrolled}
isVertical={viewSettings.vertical}
horizontalGap={horizontalGapPercent}
verticalMargin={verticalMarginPixels}
@ -130,6 +131,7 @@ const BooksGrid: React.FC<BooksGridProps> = ({ bookKeys, onCloseBook }) => {
section={section}
pageinfo={pageinfo}
showDoubleBorder={viewSettings.vertical && viewSettings.doubleBorder}
isScrolled={viewSettings.scrolled}
isVertical={viewSettings.vertical}
horizontalGap={horizontalGapPercent}
verticalMargin={verticalMarginPixels}

View file

@ -9,6 +9,7 @@ interface PageInfoProps {
section?: PageInfo;
pageinfo?: PageInfo;
showDoubleBorder: boolean;
isScrolled: boolean;
isVertical: boolean;
horizontalGap: number;
verticalMargin: number;
@ -19,34 +20,32 @@ const PageInfoView: React.FC<PageInfoProps> = ({
section,
pageinfo,
showDoubleBorder,
isScrolled,
isVertical,
horizontalGap,
verticalMargin,
}) => {
const _ = useTranslation();
const { appService } = useEnv();
const pageInfo =
bookFormat === 'PDF'
? section
? isVertical
? `${section.current + 1} · ${section.total}`
: `${section.current + 1} / ${section.total}`
: ''
: pageinfo
? _(
isVertical ? '{{currentPage}} · {{totalPage}}' : 'Loc. {{currentPage}} / {{totalPage}}',
{
currentPage: (pageinfo.next ?? pageinfo.current) + 1,
totalPage: pageinfo.total,
},
)
: '';
const pageInfo = ['PDF', 'CBZ'].includes(bookFormat)
? section
? isVertical
? `${section.current + 1} · ${section.total}`
: `${section.current + 1} / ${section.total}`
: ''
: pageinfo
? _(isVertical ? '{{currentPage}} · {{totalPage}}' : 'Loc. {{currentPage}} / {{totalPage}}', {
currentPage: (pageinfo.next ?? pageinfo.current) + 1,
totalPage: pageinfo.total,
})
: '';
return (
<div
className={clsx(
'pageinfo absolute bottom-0 flex items-center justify-end',
isVertical ? 'writing-vertical-rl' : 'bg-base-100 h-12 w-full',
isVertical ? 'writing-vertical-rl' : 'h-12 w-full',
isScrolled && 'bg-base-100',
)}
style={
isVertical

View file

@ -4,6 +4,7 @@ import React from 'react';
interface SectionInfoProps {
section?: string;
showDoubleBorder: boolean;
isScrolled: boolean;
isVertical: boolean;
horizontalGap: number;
verticalMargin: number;
@ -12,6 +13,7 @@ interface SectionInfoProps {
const SectionInfo: React.FC<SectionInfoProps> = ({
section,
showDoubleBorder,
isScrolled,
isVertical,
horizontalGap,
verticalMargin,
@ -20,7 +22,8 @@ const SectionInfo: React.FC<SectionInfoProps> = ({
<div
className={clsx(
'sectioninfo absolute flex items-center overflow-hidden',
isVertical ? 'writing-vertical-rl max-h-[85%]' : 'bg-base-100 top-0 h-[44px]',
isVertical ? 'writing-vertical-rl max-h-[85%]' : 'top-0 h-[44px]',
isScrolled && 'bg-base-100',
)}
style={
isVertical

View file

@ -99,6 +99,31 @@ export class DocumentLoader {
}
private async makeZipLoader() {
const getComment = async (): Promise<string | null> => {
const EOCD_SIGNATURE = [0x50, 0x4b, 0x05, 0x06];
const maxEOCDSearch = 1024 * 64;
const sliceSize = Math.min(maxEOCDSearch, this.file.size);
const tail = await this.file.slice(this.file.size - sliceSize, this.file.size).arrayBuffer();
const bytes = new Uint8Array(tail);
for (let i = bytes.length - 22; i >= 0; i--) {
if (
bytes[i] === EOCD_SIGNATURE[0] &&
bytes[i + 1] === EOCD_SIGNATURE[1] &&
bytes[i + 2] === EOCD_SIGNATURE[2] &&
bytes[i + 3] === EOCD_SIGNATURE[3]
) {
const commentLength = bytes[i + 20]! + (bytes[i + 21]! << 8);
const commentStart = i + 22;
const commentBytes = bytes.slice(commentStart, commentStart + commentLength);
return new TextDecoder().decode(commentBytes);
}
}
return null;
};
const { configure, ZipReader, BlobReader, TextWriter, BlobWriter } = await import(
'@zip.js/zip.js'
);
@ -120,7 +145,7 @@ export class DocumentLoader {
);
const getSize = (name: string) => map.get(name)?.uncompressedSize ?? 0;
return { entries, loadText, loadBlob, getSize, sha1: undefined };
return { entries, loadText, loadBlob, getSize, getComment, sha1: undefined };
}
private isCBZ(): boolean {
@ -155,7 +180,7 @@ export class DocumentLoader {
if (this.isCBZ()) {
const { makeComicBook } = await import('foliate-js/comic-book.js');
book = makeComicBook(loader, this.file);
book = await makeComicBook(loader, this.file);
format = 'CBZ';
} else if (this.isFBZ()) {
const entry = entries.find((entry) => entry.filename.endsWith(`.${EXTS.FB2}`));

View file

@ -198,6 +198,9 @@ export abstract class BaseAppService implements AppService {
if (!existingBook) {
await this.saveBookConfig(book, INIT_BOOK_CONFIG);
books.splice(0, 0, book);
} else {
existingBook.title = book.title;
existingBook.author = book.author;
}
if (typeof file === 'string' && isValidURL(file)) {

@ -1 +1 @@
Subproject commit 48f5c1858486b1d7fdb9a13a54d6a8b087baa7ec
Subproject commit ef67dd98015d7f92bbc21a3d73d8fb03bb39c4cb