@@ -396,26 +396,23 @@ export abstract class BaseAppService implements AppService {
|
||||
if (!(await this.fs.exists(getDir(book), 'Books'))) {
|
||||
await this.fs.createDir(getDir(book), 'Books');
|
||||
}
|
||||
if (
|
||||
saveBook &&
|
||||
!transient &&
|
||||
(!(await this.fs.exists(getLocalBookFilename(book), 'Books')) || overwrite)
|
||||
) {
|
||||
const bookFilename = getLocalBookFilename(book);
|
||||
if (saveBook && !transient && (!(await this.fs.exists(bookFilename, 'Books')) || overwrite)) {
|
||||
if (/\.txt$/i.test(filename)) {
|
||||
await this.fs.writeFile(getLocalBookFilename(book), 'Books', fileobj);
|
||||
await this.fs.writeFile(bookFilename, 'Books', fileobj);
|
||||
} else if (typeof file === 'string' && isContentURI(file)) {
|
||||
await this.fs.copyFile(file, getLocalBookFilename(book), 'Books');
|
||||
await this.fs.copyFile(file, bookFilename, 'Books');
|
||||
} else if (typeof file === 'string' && !isValidURL(file)) {
|
||||
try {
|
||||
// try to copy the file directly first in case of large files to avoid memory issues
|
||||
// on desktop when reading recursively from selected directory the direct copy will fail
|
||||
// due to permission issues, then fallback to read and write files
|
||||
await this.fs.copyFile(file, getLocalBookFilename(book), 'Books');
|
||||
await this.fs.copyFile(file, bookFilename, 'Books');
|
||||
} catch {
|
||||
await this.fs.writeFile(getLocalBookFilename(book), 'Books', fileobj);
|
||||
await this.fs.writeFile(bookFilename, 'Books', await fileobj.arrayBuffer());
|
||||
}
|
||||
} else {
|
||||
await this.fs.writeFile(getLocalBookFilename(book), 'Books', fileobj);
|
||||
await this.fs.writeFile(bookFilename, 'Books', fileobj);
|
||||
}
|
||||
}
|
||||
if (saveCover && (!(await this.fs.exists(getCoverFilename(book), 'Books')) || overwrite)) {
|
||||
|
||||
@@ -347,6 +347,11 @@ export const nativeFileSystem: FileSystem = {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
async stats(path: string, base: BaseDir) {
|
||||
const { fp, baseDir } = this.resolvePath(path, base);
|
||||
|
||||
return await stat(fp, baseDir ? { baseDir } : undefined);
|
||||
},
|
||||
};
|
||||
|
||||
const DIST_CHANNEL = (process.env['NEXT_PUBLIC_DIST_CHANNEL'] || 'readest') as DistChannel;
|
||||
|
||||
@@ -218,6 +218,43 @@ const indexedDBFileSystem: FileSystem = {
|
||||
request.onerror = () => reject(request.error);
|
||||
});
|
||||
},
|
||||
async stats(path: string, base: BaseDir) {
|
||||
const { fp } = this.resolvePath(path, base);
|
||||
const db = await openIndexedDB();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = db.transaction('files', 'readonly');
|
||||
const store = transaction.objectStore('files');
|
||||
const request = store.get(fp);
|
||||
|
||||
request.onsuccess = () => {
|
||||
const result = request.result;
|
||||
if (result) {
|
||||
const content = result.content;
|
||||
const size =
|
||||
content instanceof Blob
|
||||
? content.size
|
||||
: typeof content === 'string'
|
||||
? content.length
|
||||
: content instanceof ArrayBuffer
|
||||
? content.byteLength
|
||||
: 0;
|
||||
resolve({
|
||||
isFile: true,
|
||||
isDirectory: false,
|
||||
size,
|
||||
mtime: null,
|
||||
atime: null,
|
||||
birthtime: null,
|
||||
});
|
||||
} else {
|
||||
reject(new Error(`File not found: ${fp}`));
|
||||
}
|
||||
};
|
||||
|
||||
request.onerror = () => reject(request.error);
|
||||
});
|
||||
},
|
||||
};
|
||||
|
||||
export class WebAppService extends BaseAppService {
|
||||
|
||||
@@ -25,6 +25,15 @@ export type FileItem = {
|
||||
size: number;
|
||||
};
|
||||
|
||||
export type FileInfo = {
|
||||
isFile: boolean;
|
||||
isDirectory: boolean;
|
||||
size: number;
|
||||
mtime: Date | null;
|
||||
atime: Date | null;
|
||||
birthtime: Date | null;
|
||||
};
|
||||
|
||||
export interface FileSystem {
|
||||
resolvePath(path: string, base: BaseDir): ResolvedPath;
|
||||
getURL(path: string): string;
|
||||
@@ -39,6 +48,7 @@ export interface FileSystem {
|
||||
createDir(path: string, base: BaseDir, recursive?: boolean): Promise<void>;
|
||||
removeDir(path: string, base: BaseDir, recursive?: boolean): Promise<void>;
|
||||
exists(path: string, base: BaseDir): Promise<boolean>;
|
||||
stats(path: string, base: BaseDir): Promise<FileInfo>;
|
||||
getPrefix(base: BaseDir): Promise<string>;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user