forked from akai/readest
sync: fix tauri storage API (#264)
This commit is contained in:
@@ -7,7 +7,7 @@ const appPlatform = process.env['NEXT_PUBLIC_APP_PLATFORM'];
|
||||
const nextConfig = {
|
||||
// Ensure Next.js uses SSG instead of SSR
|
||||
// https://nextjs.org/docs/pages/building-your-application/deploying/static-exports
|
||||
output: appPlatform === 'web' ? undefined : 'export',
|
||||
output: appPlatform === 'web' || isDev ? undefined : 'export',
|
||||
// Note: This feature is required to use the Next.js Image component in SSG mode.
|
||||
// See https://nextjs.org/docs/messages/export-image-api for different workarounds.
|
||||
images: {
|
||||
|
||||
@@ -44,6 +44,9 @@
|
||||
"allow": [
|
||||
{
|
||||
"url": "https://*.deepl.com"
|
||||
},
|
||||
{
|
||||
"url": "https://*.cloudflarestorage.com"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -52,12 +52,17 @@ const BookItem: React.FC<BookItemProps> = ({
|
||||
/>
|
||||
<div
|
||||
className={clsx(
|
||||
'invisible absolute inset-0 flex items-center justify-center p-1',
|
||||
'text-neutral-content rounded-none text-center font-serif text-base font-medium',
|
||||
'line-clamp-3',
|
||||
'invisible absolute inset-0 rounded-none p-2',
|
||||
'text-neutral-content text-center font-serif font-medium',
|
||||
)}
|
||||
>
|
||||
{book.title}
|
||||
<div className='flex h-1/2 items-center justify-center'>
|
||||
<span className='line-clamp-3 text-lg'>{book.title}</span>
|
||||
</div>
|
||||
<div className='h-1/6'></div>
|
||||
<div className='flex h-1/3 items-center justify-center'>
|
||||
<span className='text-neutral-content/50 line-clamp-1 text-base'>{book.author}</span>
|
||||
</div>
|
||||
</div>
|
||||
{(selectedBooks.includes(book.hash) || clickedBookHash === book.hash) && (
|
||||
<div className='absolute inset-0 bg-black opacity-30 transition-opacity duration-300'></div>
|
||||
@@ -73,12 +78,7 @@ const BookItem: React.FC<BookItemProps> = ({
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className={clsx(
|
||||
'flex w-full p-0 pt-2',
|
||||
isWebAppPlatform() ? 'flex-col' : 'flex-row justify-between',
|
||||
)}
|
||||
>
|
||||
<div className={clsx('flex w-full p-0 pt-2', isWebAppPlatform() ? 'flex-col' : 'flex-col')}>
|
||||
<div className='min-w-0 flex-1'>
|
||||
<h4 className='block overflow-hidden text-ellipsis whitespace-nowrap text-[0.6em] text-xs font-semibold'>
|
||||
{book.title}
|
||||
@@ -88,31 +88,29 @@ const BookItem: React.FC<BookItemProps> = ({
|
||||
className={clsx('flex items-center', book.progress ? 'justify-between' : 'justify-end')}
|
||||
>
|
||||
{book.progress && <ReadingProgress book={book} />}
|
||||
{isWebAppPlatform() && (
|
||||
<div className='flex items-center gap-x-1'>
|
||||
<button
|
||||
className='show-detail-button opacity-0 group-hover:opacity-100'
|
||||
onClick={() => {
|
||||
if (!book.uploadedAt) {
|
||||
handleBookUpload(book);
|
||||
} else if (!book.downloadedAt) {
|
||||
handleBookDownload(book);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{!book.uploadedAt && <LiaCloudUploadAltSolid size={iconSize15} />}
|
||||
{book.uploadedAt && !book.downloadedAt && (
|
||||
<LiaCloudDownloadAltSolid size={iconSize15} />
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
className='show-detail-button opacity-0 group-hover:opacity-100'
|
||||
onClick={() => showBookDetailsModal(book)}
|
||||
>
|
||||
<CiCircleMore size={iconSize15} />
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
<div className='flex items-center gap-x-1'>
|
||||
<button
|
||||
className='show-detail-button opacity-0 group-hover:opacity-100'
|
||||
onClick={() => {
|
||||
if (!book.uploadedAt) {
|
||||
handleBookUpload(book);
|
||||
} else if (!book.downloadedAt) {
|
||||
handleBookDownload(book);
|
||||
}
|
||||
}}
|
||||
>
|
||||
{!book.uploadedAt && <LiaCloudUploadAltSolid size={iconSize15} />}
|
||||
{book.uploadedAt && !book.downloadedAt && (
|
||||
<LiaCloudDownloadAltSolid size={iconSize15} />
|
||||
)}
|
||||
</button>
|
||||
<button
|
||||
className='show-detail-button opacity-0 group-hover:opacity-100'
|
||||
onClick={() => showBookDetailsModal(book)}
|
||||
>
|
||||
<CiCircleMore size={iconSize15} />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -80,7 +80,6 @@ const Bookshelf: React.FC<BookshelfProps> = ({
|
||||
const [showDetailsBook, setShowDetailsBook] = useState<Book | null>(null);
|
||||
|
||||
const makeBookAvailable = async (book: Book) => {
|
||||
console.log('Make book available:', book);
|
||||
if (book.uploadedAt && !book.downloadedAt) {
|
||||
setLoading(true);
|
||||
let available = false;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { useEnv } from '@/context/EnvContext';
|
||||
import { useSyncContext } from '@/context/SyncContext';
|
||||
import { SyncData, SyncOp, SyncResult, SyncType } from '@/libs/sync';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
@@ -33,7 +34,8 @@ const computeMaxTimestamp = (records: BookDataRecord[]): number => {
|
||||
const SEVEN_DAYS_IN_MS = 7 * 24 * 60 * 60 * 1000;
|
||||
|
||||
export function useSync(bookKey?: string) {
|
||||
const { settings } = useSettingsStore();
|
||||
const { envConfig } = useEnv();
|
||||
const { settings, setSettings, saveSettings } = useSettingsStore();
|
||||
const { getConfig, setConfig } = useBookDataStore();
|
||||
const config = bookKey ? getConfig(bookKey) : null;
|
||||
|
||||
@@ -92,10 +94,14 @@ export function useSync(bookKey?: string) {
|
||||
switch (type) {
|
||||
case 'books':
|
||||
settings.lastSyncedAtBooks = maxTime;
|
||||
setSettings(settings);
|
||||
saveSettings(envConfig, settings);
|
||||
break;
|
||||
case 'configs':
|
||||
if (!bookId) {
|
||||
settings.lastSyncedAtConfigs = maxTime;
|
||||
setSettings(settings);
|
||||
saveSettings(envConfig, settings);
|
||||
} else if (bookKey && config) {
|
||||
config.lastSyncedAtConfig = maxTime;
|
||||
setConfig(bookKey, config);
|
||||
@@ -104,6 +110,8 @@ export function useSync(bookKey?: string) {
|
||||
case 'notes':
|
||||
if (!bookId) {
|
||||
settings.lastSyncedAtNotes = maxTime;
|
||||
setSettings(settings);
|
||||
saveSettings(envConfig, settings);
|
||||
} else if (bookKey && config) {
|
||||
config.lastSyncedAtNotes = maxTime;
|
||||
setConfig(bookKey, config);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { getAPIBaseUrl } from '@/services/environment';
|
||||
import { getAPIBaseUrl, isWebAppPlatform } from '@/services/environment';
|
||||
import { getAccessToken, getUserID } from '@/utils/access';
|
||||
|
||||
const API_ENDPOINTS = {
|
||||
@@ -43,10 +43,12 @@ export const uploadFile = async (file: File, bookHash?: string) => {
|
||||
});
|
||||
|
||||
const { uploadUrl } = await response.json();
|
||||
|
||||
const fetch = isWebAppPlatform()
|
||||
? window.fetch
|
||||
: (await import('@tauri-apps/plugin-http')).fetch;
|
||||
const uploadResponse = await fetch(uploadUrl, {
|
||||
method: 'PUT',
|
||||
body: file,
|
||||
body: isWebAppPlatform() ? file : await file.arrayBuffer(),
|
||||
});
|
||||
|
||||
if (!uploadResponse.ok) {
|
||||
|
||||
@@ -117,6 +117,7 @@ export const WINDOWS_FONTS = [
|
||||
'Gabriola',
|
||||
'Gadugi',
|
||||
'Georgia',
|
||||
'Heiti',
|
||||
'HoloLens MDL2 Assets',
|
||||
'Impact',
|
||||
'Ink Free',
|
||||
@@ -166,6 +167,7 @@ export const WINDOWS_FONTS = [
|
||||
'Verdana',
|
||||
'Webdings',
|
||||
'Wingdings',
|
||||
'XiHeiti',
|
||||
'Yu Gothic',
|
||||
'Yu Mincho',
|
||||
];
|
||||
@@ -201,6 +203,7 @@ export const MACOS_FONTS = [
|
||||
'Didot',
|
||||
'DIN Alternate',
|
||||
'DIN Condensed',
|
||||
'FangSong',
|
||||
'Futura',
|
||||
'Geneva',
|
||||
'Georgia',
|
||||
@@ -250,6 +253,7 @@ export const MACOS_FONTS = [
|
||||
'Trattatello',
|
||||
'Trebuchet MS',
|
||||
'Verdana',
|
||||
'XiHeiti',
|
||||
'Yu Mincho',
|
||||
'Zapfino',
|
||||
];
|
||||
@@ -264,11 +268,14 @@ export const LINUX_FONTS = [
|
||||
'DejaVu Serif',
|
||||
'Droid Sans',
|
||||
'Droid Sans Mono',
|
||||
'FangSong',
|
||||
'FreeMono',
|
||||
'FreeSans',
|
||||
'FreeSerif',
|
||||
'Georgia',
|
||||
'Heiti',
|
||||
'Impact',
|
||||
'Kaiti',
|
||||
'Liberation Mono',
|
||||
'Liberation Sans',
|
||||
'Liberation Serif',
|
||||
@@ -294,6 +301,7 @@ export const LINUX_FONTS = [
|
||||
'Wingdings',
|
||||
'WenQuanYi Micro Hei',
|
||||
'WenQuanYi Zen Hei',
|
||||
'XiHeiti',
|
||||
];
|
||||
|
||||
export const IOS_FONTS = [
|
||||
@@ -301,7 +309,9 @@ export const IOS_FONTS = [
|
||||
'Avenir Next',
|
||||
'Courier',
|
||||
'Courier New',
|
||||
'FangSong',
|
||||
'Georgia',
|
||||
'Heiti',
|
||||
'Helvetica',
|
||||
'Helvetica Neue',
|
||||
'Hiragino Mincho',
|
||||
@@ -317,14 +327,18 @@ export const IOS_FONTS = [
|
||||
'Songti',
|
||||
'Times New Roman',
|
||||
'Verdana',
|
||||
'XiHeiti',
|
||||
];
|
||||
|
||||
export const ANDROID_FONTS = [
|
||||
'Arial',
|
||||
'Droid Sans',
|
||||
'Droid Serif',
|
||||
'FangSong',
|
||||
'FZLanTingHei',
|
||||
'Georgia',
|
||||
'Heiti',
|
||||
'Kaiti',
|
||||
'Noto Sans',
|
||||
'Noto Sans CJK',
|
||||
'Noto Sans JP',
|
||||
@@ -339,6 +353,7 @@ export const ANDROID_FONTS = [
|
||||
'STSong',
|
||||
'Tahoma',
|
||||
'Verdana',
|
||||
'XiHeiti',
|
||||
];
|
||||
|
||||
export const ONE_COLUMN_MAX_INLINE_SIZE = 9999;
|
||||
|
||||
Reference in New Issue
Block a user