diff --git a/apps/readest-app/src/app/auth/page.tsx b/apps/readest-app/src/app/auth/page.tsx
index 478e59af..8f491bd1 100644
--- a/apps/readest-app/src/app/auth/page.tsx
+++ b/apps/readest-app/src/app/auth/page.tsx
@@ -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];
diff --git a/apps/readest-app/src/app/library/page.tsx b/apps/readest-app/src/app/library/page.tsx
index e2916270..e522b799 100644
--- a/apps/readest-app/src/app/library/page.tsx
+++ b/apps/readest-app/src/app/library/page.tsx
@@ -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 ;
+};
+
+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(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 (
+
+
+
+ }
+ >
+
+
+ );
+};
+
export default LibraryPage;
diff --git a/apps/readest-app/src/app/reader/hooks/useProgressAutoSave.ts b/apps/readest-app/src/app/reader/hooks/useProgressAutoSave.ts
index 791d7591..d401236c 100644
--- a/apps/readest-app/src/app/reader/hooks/useProgressAutoSave.ts
+++ b/apps/readest-app/src/app/reader/hooks/useProgressAutoSave.ts
@@ -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]);
diff --git a/apps/readest-app/src/app/reader/page.tsx b/apps/readest-app/src/app/reader/page.tsx
index 78ad075d..45168b19 100644
--- a/apps/readest-app/src/app/reader/page.tsx
+++ b/apps/readest-app/src/app/reader/page.tsx
@@ -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 () => {
diff --git a/apps/readest-app/src/hooks/useOpenWithBooks.ts b/apps/readest-app/src/hooks/useOpenWithBooks.ts
new file mode 100644
index 00000000..dc4f8eb4
--- /dev/null
+++ b/apps/readest-app/src/hooks/useOpenWithBooks.ts
@@ -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
+ }, []);
+}
diff --git a/apps/readest-app/src/store/libraryStore.ts b/apps/readest-app/src/store/libraryStore.ts
index ea563465..bdf2b3f3 100644
--- a/apps/readest-app/src/store/libraryStore.ts
+++ b/apps/readest-app/src/store/libraryStore.ts
@@ -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((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();