forked from akai/readest
ux: incrementally loading new books after synchronization (#303)
* auth: workaround to get deeplink data when completing oauth on Android * ux: incrementally loading new books after synchronization
This commit is contained in:
@@ -62,6 +62,14 @@ export default function AuthPage() {
|
||||
const [isMounted, setIsMounted] = useState(false);
|
||||
const osPlatform = getOSPlatform();
|
||||
|
||||
const getTauriRedirectTo = () => {
|
||||
return process.env.NODE_ENV === 'production'
|
||||
? ['android', 'ios'].includes(osPlatform)
|
||||
? 'https://web.readest.com/auth/callback'
|
||||
: 'readest://auth/callback'
|
||||
: `http://localhost:${port}`;
|
||||
};
|
||||
|
||||
const tauriSignIn = async (provider: OAuthProvider) => {
|
||||
if (!supabase) {
|
||||
throw new Error('No backend connected');
|
||||
@@ -71,12 +79,7 @@ export default function AuthPage() {
|
||||
provider,
|
||||
options: {
|
||||
skipBrowserRedirect: true,
|
||||
redirectTo:
|
||||
process.env.NODE_ENV === 'production'
|
||||
? ['android', 'ios'].includes(osPlatform)
|
||||
? 'https://web.readest.com/auth/callback'
|
||||
: 'readest://auth/callback'
|
||||
: `http://localhost:${port}`,
|
||||
redirectTo: getTauriRedirectTo(),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -85,6 +88,13 @@ export default function AuthPage() {
|
||||
return;
|
||||
}
|
||||
openUrl(data.url);
|
||||
|
||||
// FIXME: For Android we need a better way to trigger the deeplink redirect
|
||||
if (getOSPlatform() === 'android') {
|
||||
setTimeout(() => {
|
||||
router.back();
|
||||
}, 5000);
|
||||
}
|
||||
};
|
||||
|
||||
const handleOAuthUrl = async (url: string) => {
|
||||
@@ -226,7 +236,7 @@ export default function AuthPage() {
|
||||
theme={isDarkMode ? 'dark' : 'light'}
|
||||
magicLink={true}
|
||||
providers={[]}
|
||||
redirectTo={`http://localhost:${port}`}
|
||||
redirectTo={getTauriRedirectTo()}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -6,7 +6,12 @@ import { useLibraryStore } from '@/store/libraryStore';
|
||||
import { SYNC_BOOKS_INTERVAL_SEC } from '@/services/constants';
|
||||
import { Book } from '@/types/book';
|
||||
|
||||
export const useBooksSync = () => {
|
||||
export interface UseBooksSyncProps {
|
||||
onSyncStart?: () => void;
|
||||
onSyncEnd?: () => void;
|
||||
}
|
||||
|
||||
export const useBooksSync = ({ onSyncStart, onSyncEnd }: UseBooksSyncProps) => {
|
||||
const { user } = useAuth();
|
||||
const { appService } = useEnv();
|
||||
const { library, setLibrary } = useLibraryStore();
|
||||
@@ -91,16 +96,23 @@ export const useBooksSync = () => {
|
||||
if (!updatedLibrary.some((oldBook) => oldBook.hash === newBook.hash)) {
|
||||
if (newBook.uploadedAt && !newBook.deletedAt) {
|
||||
try {
|
||||
updatedLibrary.push(newBook);
|
||||
await appService?.downloadBook(newBook, true);
|
||||
newBook.coverImageUrl = await appService?.generateCoverImageUrl(newBook);
|
||||
updatedLibrary.push(newBook);
|
||||
setLibrary(updatedLibrary);
|
||||
} catch {
|
||||
console.error('Failed to download book:', newBook);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
await Promise.all(syncedBooks.map(processNewBook));
|
||||
onSyncStart?.();
|
||||
const batchSize = 3;
|
||||
for (let i = 0; i < syncedBooks.length; i += batchSize) {
|
||||
const batch = syncedBooks.slice(i, i + batchSize);
|
||||
await Promise.all(batch.map(processNewBook));
|
||||
}
|
||||
onSyncEnd?.();
|
||||
setLibrary(updatedLibrary);
|
||||
appService?.saveLibraryBooks(updatedLibrary);
|
||||
};
|
||||
|
||||
@@ -57,7 +57,10 @@ const LibraryPage = () => {
|
||||
const demoBooks = useDemoBooks();
|
||||
const containerRef = useRef<HTMLDivElement>(null);
|
||||
|
||||
const { pullLibrary, pushLibrary } = useBooksSync();
|
||||
const { pullLibrary, pushLibrary } = useBooksSync({
|
||||
onSyncStart: () => setLoading(true),
|
||||
onSyncEnd: () => setLoading(false),
|
||||
});
|
||||
|
||||
usePullToRefresh(containerRef, pullLibrary);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user