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:
Huang Xin
2025-02-06 19:07:48 +01:00
committed by GitHub
parent 8bd9e18381
commit b879184dc6
3 changed files with 36 additions and 11 deletions
+17 -7
View File
@@ -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);
};
+4 -1
View File
@@ -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);