forked from akai/readest
fix: open with new files from file browsers when there is already an instance running, closes #208 (#466)
This commit is contained in:
@@ -129,7 +129,7 @@ export default function AuthPage() {
|
||||
};
|
||||
|
||||
const handleOAuthUrl = async (url: string) => {
|
||||
console.log('Received OAuth URL:', url);
|
||||
console.log('Handle OAuth URL:', url);
|
||||
const hashMatch = url.match(/#(.*)/);
|
||||
if (hashMatch) {
|
||||
const hash = hashMatch[1];
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
import clsx from 'clsx';
|
||||
import * as React from 'react';
|
||||
import { useState, useRef, useEffect } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useState, useRef, useEffect, Suspense } from 'react';
|
||||
import { ReadonlyURLSearchParams, useRouter, useSearchParams } from 'next/navigation';
|
||||
|
||||
import { Book } from '@/types/book';
|
||||
import { AppService } from '@/types/system';
|
||||
@@ -28,6 +28,7 @@ import { usePullToRefresh } from '@/hooks/usePullToRefresh';
|
||||
import { useDemoBooks } from './hooks/useDemoBooks';
|
||||
import { useBooksSync } from './hooks/useBooksSync';
|
||||
import { useScreenWakeLock } from '@/hooks/useScreenWakeLock';
|
||||
import { useOpenWithBooks } from '@/hooks/useOpenWithBooks';
|
||||
import { tauriQuitApp } from '@/utils/window';
|
||||
|
||||
import { AboutWindow } from '@/components/AboutWindow';
|
||||
@@ -38,7 +39,12 @@ import Bookshelf from './components/Bookshelf';
|
||||
import BookDetailModal from '@/components/BookDetailModal';
|
||||
import useShortcuts from '@/hooks/useShortcuts';
|
||||
|
||||
const LibraryPage = () => {
|
||||
const LibraryPageWithSearchParams = () => {
|
||||
const searchParams = useSearchParams();
|
||||
return <LibraryPageContent searchParams={searchParams} />;
|
||||
};
|
||||
|
||||
const LibraryPageContent = ({ searchParams }: { searchParams: ReadonlyURLSearchParams | null }) => {
|
||||
const router = useRouter();
|
||||
const { envConfig, appService } = useEnv();
|
||||
const { token, user } = useAuth();
|
||||
@@ -47,7 +53,7 @@ const LibraryPage = () => {
|
||||
updateBook,
|
||||
setLibrary,
|
||||
checkOpenWithBooks,
|
||||
clearOpenWithBooks,
|
||||
setCheckOpenWithBooks,
|
||||
} = useLibraryStore();
|
||||
const _ = useTranslation();
|
||||
const { updateAppTheme } = useTheme();
|
||||
@@ -63,6 +69,8 @@ const LibraryPage = () => {
|
||||
const demoBooks = useDemoBooks();
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
useOpenWithBooks();
|
||||
|
||||
const { pullLibrary, pushLibrary } = useBooksSync({
|
||||
onSyncStart: () => setLoading(true),
|
||||
onSyncEnd: () => setLoading(false),
|
||||
@@ -113,7 +121,9 @@ const LibraryPage = () => {
|
||||
|
||||
console.log('Opening books:', bookIds);
|
||||
if (bookIds.length > 0) {
|
||||
navigateToReader(router, bookIds);
|
||||
setTimeout(() => {
|
||||
navigateToReader(router, bookIds);
|
||||
}, 0);
|
||||
}
|
||||
},
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@@ -148,7 +158,7 @@ const LibraryPage = () => {
|
||||
if (checkOpenWithBooks && isTauriAppPlatform()) {
|
||||
await handleOpenWithBooks(appService, libraryBooks);
|
||||
} else {
|
||||
clearOpenWithBooks();
|
||||
setCheckOpenWithBooks(false);
|
||||
setLibrary(libraryBooks);
|
||||
}
|
||||
|
||||
@@ -163,7 +173,7 @@ const LibraryPage = () => {
|
||||
if (openWithFiles.length > 0) {
|
||||
await processOpenWithFiles(appService, openWithFiles, libraryBooks);
|
||||
} else {
|
||||
clearOpenWithBooks();
|
||||
setCheckOpenWithBooks(false);
|
||||
setLibrary(libraryBooks);
|
||||
}
|
||||
};
|
||||
@@ -171,10 +181,11 @@ const LibraryPage = () => {
|
||||
initLogin();
|
||||
initLibrary();
|
||||
return () => {
|
||||
clearOpenWithBooks();
|
||||
setCheckOpenWithBooks(false);
|
||||
isInitiating.current = false;
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
}, [searchParams]);
|
||||
|
||||
useEffect(() => {
|
||||
if (demoBooks.length > 0 && libraryLoaded) {
|
||||
@@ -449,4 +460,18 @@ const LibraryPage = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const LibraryPage = () => {
|
||||
return (
|
||||
<Suspense
|
||||
fallback={
|
||||
<div className='fixed inset-0 z-50 flex items-center justify-center'>
|
||||
<Spinner loading />
|
||||
</div>
|
||||
}
|
||||
>
|
||||
<LibraryPageWithSearchParams />
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
|
||||
export default LibraryPage;
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useSettingsStore } from '@/store/settingsStore';
|
||||
import { throttle } from '@/utils/throttle';
|
||||
|
||||
export const useProgressAutoSave = (bookKey: string) => {
|
||||
const { envConfig, appService } = useEnv();
|
||||
const { envConfig } = useEnv();
|
||||
const { getConfig, saveConfig } = useBookDataStore();
|
||||
const { getProgress } = useReaderStore();
|
||||
const progress = getProgress(bookKey);
|
||||
@@ -22,9 +22,6 @@ export const useProgressAutoSave = (bookKey: string) => {
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
// FIXME: On Android and iOS we need a better way to be notified
|
||||
// when the app is about to go in background
|
||||
if (!appService?.isMobile || !progress) return;
|
||||
saveBookConfig();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [progress, bookKey]);
|
||||
|
||||
@@ -5,6 +5,7 @@ import { useTheme } from '@/hooks/useTheme';
|
||||
import { hasUpdater } from '@/services/environment';
|
||||
import { checkForAppUpdates } from '@/helpers/updater';
|
||||
import { useTranslation } from '@/hooks/useTranslation';
|
||||
import { useOpenWithBooks } from '@/hooks/useOpenWithBooks';
|
||||
import { useSettingsStore } from '@/store/settingsStore';
|
||||
import Reader from './components/Reader';
|
||||
|
||||
@@ -13,6 +14,7 @@ export default function Page() {
|
||||
const { settings } = useSettingsStore();
|
||||
|
||||
useTheme();
|
||||
useOpenWithBooks();
|
||||
|
||||
useEffect(() => {
|
||||
const doCheckAppUpdates = async () => {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { onOpenUrl } from '@tauri-apps/plugin-deep-link';
|
||||
import { isTauriAppPlatform } from '@/services/environment';
|
||||
import { useLibraryStore } from '@/store/libraryStore';
|
||||
import { navigateToLibrary } from '@/utils/nav';
|
||||
|
||||
export function useOpenWithBooks() {
|
||||
const router = useRouter();
|
||||
const { setCheckOpenWithBooks } = useLibraryStore();
|
||||
const listenedOpenWithBooks = useRef(false);
|
||||
|
||||
const handleOpenWithFileUrl = (url: string) => {
|
||||
let filePath = url;
|
||||
if (filePath.startsWith('file://')) {
|
||||
filePath = decodeURI(filePath.replace('file://', ''));
|
||||
}
|
||||
if (filePath.startsWith('/')) {
|
||||
window.OPEN_WITH_FILES = [filePath];
|
||||
setCheckOpenWithBooks(true);
|
||||
navigateToLibrary(router, `reload=${Date.now()}`);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (!isTauriAppPlatform()) return;
|
||||
if (listenedOpenWithBooks.current) return;
|
||||
listenedOpenWithBooks.current = true;
|
||||
|
||||
const listenOpenWithFiles = async () => {
|
||||
return await onOpenUrl((urls) => {
|
||||
urls.forEach((url) => {
|
||||
handleOpenWithFileUrl(url);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const unlisten = listenOpenWithFiles();
|
||||
return () => {
|
||||
unlisten.then((f) => f());
|
||||
};
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
}
|
||||
@@ -5,7 +5,7 @@ import { EnvConfigType } from '@/services/environment';
|
||||
interface LibraryState {
|
||||
library: Book[];
|
||||
checkOpenWithBooks: boolean;
|
||||
clearOpenWithBooks: () => void;
|
||||
setCheckOpenWithBooks: (check: boolean) => void;
|
||||
setLibrary: (books: Book[]) => void;
|
||||
updateBook: (envConfig: EnvConfigType, book: Book) => void;
|
||||
}
|
||||
@@ -13,7 +13,7 @@ interface LibraryState {
|
||||
export const useLibraryStore = create<LibraryState>((set, get) => ({
|
||||
library: [],
|
||||
checkOpenWithBooks: true,
|
||||
clearOpenWithBooks: () => set({ checkOpenWithBooks: false }),
|
||||
setCheckOpenWithBooks: (check) => set({ checkOpenWithBooks: check }),
|
||||
setLibrary: (books) => set({ library: books }),
|
||||
updateBook: async (envConfig: EnvConfigType, book: Book) => {
|
||||
const appService = await envConfig.getAppService();
|
||||
|
||||
Reference in New Issue
Block a user