fix: open with new files from file browsers when there is already an instance running, closes #208 (#466)

This commit is contained in:
Huang Xin
2025-02-28 08:42:49 +01:00
committed by GitHub
parent cab757257e
commit 2f29295c6c
6 changed files with 84 additions and 16 deletions
+1 -1
View File
@@ -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];
+34 -9
View File
@@ -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]);
+2
View File
@@ -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
}, []);
}
+2 -2
View File
@@ -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();