diff options
Diffstat (limited to 'apps/web/app/reader')
| -rw-r--r-- | apps/web/app/reader/[bookmarkId]/page.tsx | 140 | ||||
| -rw-r--r-- | apps/web/app/reader/layout.tsx | 39 |
2 files changed, 51 insertions, 128 deletions
diff --git a/apps/web/app/reader/[bookmarkId]/page.tsx b/apps/web/app/reader/[bookmarkId]/page.tsx index e32811a9..133bb601 100644 --- a/apps/web/app/reader/[bookmarkId]/page.tsx +++ b/apps/web/app/reader/[bookmarkId]/page.tsx @@ -3,36 +3,18 @@ import { Suspense, useState } from "react"; import { useParams, useRouter } from "next/navigation"; import HighlightCard from "@/components/dashboard/highlights/HighlightCard"; +import ReaderSettingsPopover from "@/components/dashboard/preview/ReaderSettingsPopover"; import ReaderView from "@/components/dashboard/preview/ReaderView"; import { Button } from "@/components/ui/button"; import { FullPageSpinner } from "@/components/ui/full-page-spinner"; -import { - Popover, - PopoverContent, - PopoverTrigger, -} from "@/components/ui/popover"; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from "@/components/ui/select"; import { Separator } from "@/components/ui/separator"; -import { Slider } from "@/components/ui/slider"; -import { - HighlighterIcon as Highlight, - Minus, - Plus, - Printer, - Settings, - Type, - X, -} from "lucide-react"; +import { useReaderSettings } from "@/lib/readerSettings"; +import { HighlighterIcon as Highlight, Printer, X } from "lucide-react"; import { useSession } from "next-auth/react"; import { api } from "@karakeep/shared-react/trpc"; import { BookmarkTypes } from "@karakeep/shared/types/bookmarks"; +import { READER_FONT_FAMILIES } from "@karakeep/shared/types/readers"; import { getBookmarkTitle } from "@karakeep/shared/utils/bookmarkUtils"; export default function ReaderViewPage() { @@ -47,19 +29,10 @@ export default function ReaderViewPage() { const { data: session } = useSession(); const router = useRouter(); - const [fontSize, setFontSize] = useState([18]); - const [lineHeight, setLineHeight] = useState([1.6]); - const [fontFamily, setFontFamily] = useState("serif"); + const { settings } = useReaderSettings(); const [showHighlights, setShowHighlights] = useState(false); - const [showSettings, setShowSettings] = useState(false); const isOwner = session?.user?.id === bookmark?.userId; - const fontFamilies = { - serif: "ui-serif, Georgia, Cambria, serif", - sans: "ui-sans-serif, system-ui, sans-serif", - mono: "ui-monospace, Menlo, Monaco, monospace", - }; - const onClose = () => { if (window.history.length > 1) { router.back(); @@ -89,94 +62,7 @@ export default function ReaderViewPage() { <Printer className="h-4 w-4" /> </Button> - <Popover open={showSettings} onOpenChange={setShowSettings}> - <PopoverTrigger asChild> - <Button variant="ghost" size="icon"> - <Settings className="h-4 w-4" /> - </Button> - </PopoverTrigger> - <PopoverContent side="bottom" align="end" className="w-80"> - <div className="space-y-4"> - <div className="flex items-center gap-2 pb-2"> - <Type className="h-4 w-4" /> - <h3 className="font-semibold">Reading Settings</h3> - </div> - - <div className="space-y-4"> - <div className="space-y-2"> - <label className="text-sm font-medium">Font Family</label> - <Select value={fontFamily} onValueChange={setFontFamily}> - <SelectTrigger> - <SelectValue /> - </SelectTrigger> - <SelectContent> - <SelectItem value="serif">Serif</SelectItem> - <SelectItem value="sans">Sans Serif</SelectItem> - <SelectItem value="mono">Monospace</SelectItem> - </SelectContent> - </Select> - </div> - - <div className="space-y-2"> - <div className="flex items-center justify-between"> - <label className="text-sm font-medium">Font Size</label> - <span className="text-sm text-muted-foreground"> - {fontSize[0]}px - </span> - </div> - <div className="flex items-center gap-2"> - <Button - variant="outline" - size="icon" - className="h-7 w-7 bg-transparent" - onClick={() => - setFontSize([Math.max(12, fontSize[0] - 1)]) - } - > - <Minus className="h-3 w-3" /> - </Button> - <Slider - value={fontSize} - onValueChange={setFontSize} - max={24} - min={12} - step={1} - className="flex-1" - /> - <Button - variant="outline" - size="icon" - className="h-7 w-7 bg-transparent" - onClick={() => - setFontSize([Math.min(24, fontSize[0] + 1)]) - } - > - <Plus className="h-3 w-3" /> - </Button> - </div> - </div> - - <div className="space-y-2"> - <div className="flex items-center justify-between"> - <label className="text-sm font-medium"> - Line Height - </label> - <span className="text-sm text-muted-foreground"> - {lineHeight[0]} - </span> - </div> - <Slider - value={lineHeight} - onValueChange={setLineHeight} - max={2.5} - min={1.2} - step={0.1} - /> - </div> - </div> - </div> - </PopoverContent> - </Popover> + <ReaderSettingsPopover variant="ghost" /> <Button variant={showHighlights ? "default" : "ghost"} @@ -216,10 +102,9 @@ export default function ReaderViewPage() { <h1 className="font-bold leading-tight" style={{ - fontFamily: - fontFamilies[fontFamily as keyof typeof fontFamilies], - fontSize: `${fontSize[0] * 1.8}px`, - lineHeight: lineHeight[0] * 0.9, + fontFamily: READER_FONT_FAMILIES[settings.fontFamily], + fontSize: `${settings.fontSize * 1.8}px`, + lineHeight: settings.lineHeight * 0.9, }} > {getBookmarkTitle(bookmark)} @@ -239,10 +124,9 @@ export default function ReaderViewPage() { <ReaderView className="prose prose-neutral max-w-none break-words dark:prose-invert [&_code]:break-all [&_img]:h-auto [&_img]:max-w-full [&_pre]:overflow-x-auto [&_table]:block [&_table]:overflow-x-auto" style={{ - fontFamily: - fontFamilies[fontFamily as keyof typeof fontFamilies], - fontSize: `${fontSize[0]}px`, - lineHeight: lineHeight[0], + fontFamily: READER_FONT_FAMILIES[settings.fontFamily], + fontSize: `${settings.fontSize}px`, + lineHeight: settings.lineHeight, }} bookmarkId={bookmarkId} readOnly={!isOwner} diff --git a/apps/web/app/reader/layout.tsx b/apps/web/app/reader/layout.tsx new file mode 100644 index 00000000..b0c27c84 --- /dev/null +++ b/apps/web/app/reader/layout.tsx @@ -0,0 +1,39 @@ +import { redirect } from "next/navigation"; +import { ReaderSettingsProvider } from "@/lib/readerSettings"; +import { UserSettingsContextProvider } from "@/lib/userSettings"; +import { api } from "@/server/api/client"; +import { getServerAuthSession } from "@/server/auth"; +import { TRPCError } from "@trpc/server"; + +import { tryCatch } from "@karakeep/shared/tryCatch"; + +export default async function ReaderLayout({ + children, +}: Readonly<{ + children: React.ReactNode; +}>) { + const session = await getServerAuthSession(); + if (!session) { + redirect("/"); + } + + const userSettings = await tryCatch(api.users.settings()); + + if (userSettings.error) { + if (userSettings.error instanceof TRPCError) { + if ( + userSettings.error.code === "NOT_FOUND" || + userSettings.error.code === "UNAUTHORIZED" + ) { + redirect("/logout"); + } + } + throw userSettings.error; + } + + return ( + <UserSettingsContextProvider userSettings={userSettings.data}> + <ReaderSettingsProvider>{children}</ReaderSettingsProvider> + </UserSettingsContextProvider> + ); +} |
