Archived
Resolve merge conflicts for PR #25: customizable mobile reading experience
- Backend: Replace PR's Book-only models with main's full models (EBook, BookChapter, DownloadRecord, ReadingProgress, ReadingSettings) - Backend: Add reader app (ReadingSettings model, serializer, view, URL) - Frontend: Port reader feature files from web/ to frontend/ (api, hooks, components/reader/, pages/ReadingPage, types/reader, reader.css) - Frontend: Add /read/:id route to App.tsx for chapter-based reading view - All imports adjusted for frontend/src directory structure
This commit is contained in:
@@ -0,0 +1,62 @@
|
||||
import React, { lazy, Suspense, useState } from "react";
|
||||
import { BrowserRouter, Navigate, Route, Routes } from "react-router-dom";
|
||||
import { AuthProvider, useAuth } from "./context/AuthContext";
|
||||
|
||||
const LibraryPage = lazy(() => import("./pages/Library").then((m) => ({ default: m.LibraryPage })));
|
||||
const BookDetailPage = lazy(() => import("./pages/BookDetailPage").then((m) => ({ default: m.BookDetailPage })));
|
||||
const ReaderPage = lazy(() => import("./pages/Reader").then((m) => ({ default: m.ReaderPage })));
|
||||
const AddBookPage = lazy(() => import("./pages/AddBook").then((m) => ({ default: m.AddBookPage })));
|
||||
const EditEBookPage = lazy(() => import("./pages/EditEBook").then((m) => ({ default: m.EditEBookPage })));
|
||||
const SettingsPage = lazy(() => import("./pages/Settings").then((m) => ({ default: m.SettingsPage })));
|
||||
const BookmarksNotesPage = lazy(() => import("./components/annotations/BookmarksNotesPage").then((m) => ({ default: m.BookmarksNotesPage })));
|
||||
const ReadingPage = lazy(() => import("./pages/ReadingPage").then((m) => ({ default: m.default })));
|
||||
|
||||
const AuthPage = lazy(() =>
|
||||
import("./pages/AuthPage").then((m) => ({
|
||||
default: () => {
|
||||
const [isLogin, setIsLogin] = useState(true);
|
||||
return isLogin ? <m.LoginPage onToggle={() => setIsLogin(false)} /> : <m.RegisterPage onToggle={() => setIsLogin(true)} />;
|
||||
},
|
||||
})),
|
||||
);
|
||||
|
||||
function LoadingFallback() {
|
||||
return <div style={{ display: "flex", justifyContent: "center", alignItems: "center", minHeight: "100vh", color: "#888", fontSize: 16 }}><p>Loading...</p></div>;
|
||||
}
|
||||
|
||||
function ProtectedRoute({ children }: { children: React.ReactNode }) {
|
||||
const { isAuthenticated, loading } = useAuth();
|
||||
if (loading) return <LoadingFallback />;
|
||||
if (!isAuthenticated) return <Navigate to="/auth" replace />;
|
||||
return <>{children}</>;
|
||||
}
|
||||
|
||||
function AppRoutes() {
|
||||
const { isAuthenticated } = useAuth();
|
||||
return (
|
||||
<Suspense fallback={<LoadingFallback />}>
|
||||
<Routes>
|
||||
<Route path="/auth" element={isAuthenticated ? <Navigate to="/" replace /> : <AuthPage />} />
|
||||
<Route path="/" element={<ProtectedRoute><LibraryPage /></ProtectedRoute>} />
|
||||
<Route path="/books/:id" element={<ProtectedRoute><BookDetailPage /></ProtectedRoute>} />
|
||||
<Route path="/reader/:id" element={<ProtectedRoute><ReaderPage /></ProtectedRoute>} />
|
||||
<Route path="/read/:id" element={<ProtectedRoute><ReadingPage /></ProtectedRoute>} />
|
||||
<Route path="/add" element={<ProtectedRoute><AddBookPage /></ProtectedRoute>} />
|
||||
<Route path="/edit/:id" element={<ProtectedRoute><EditEBookPage /></ProtectedRoute>} />
|
||||
<Route path="/settings" element={<ProtectedRoute><SettingsPage /></ProtectedRoute>} />
|
||||
<Route path="/bookmarks-notes/:bookId?" element={<ProtectedRoute><BookmarksNotesPage /></ProtectedRoute>} />
|
||||
<Route path="*" element={<Navigate to="/" replace />} />
|
||||
</Routes>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
export default function App() {
|
||||
return (
|
||||
<BrowserRouter>
|
||||
<AuthProvider>
|
||||
<AppRoutes />
|
||||
</AuthProvider>
|
||||
</BrowserRouter>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user