History Links

LocalStorage for reading mode
Debugging with Sentry
This commit is contained in:
User
2024-12-28 15:34:35 -05:00
parent 38ad983d6d
commit 58f85bfc22
16 changed files with 758 additions and 106 deletions

View File

@@ -1,14 +1,16 @@
import { SidebarInset, SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar';
import { useEffect, useState } from 'react';
import { Link } from '@inertiajs/react';
import { Moon, Sun } from 'lucide-react';
import { Separator } from '@radix-ui/react-separator';
import { Tooltip, TooltipProvider, TooltipTrigger } from '@radix-ui/react-tooltip';
import { AppSidebar } from '@/components/ui/app-sidebar.jsx';
import { Separator } from "@radix-ui/react-separator";
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList } from "@/components/ui/breadcrumb";
import { Toaster } from '@/components/ui/toaster';
import { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbList } from '@/components/ui/breadcrumb';
import { Button } from '@/components/ui/button';
import { Moon, Settings, Sun } from 'lucide-react';
import { Link, usePage } from '@inertiajs/react';
import { useEffect, useState } from "react";
import { Tooltip, TooltipProvider, TooltipTrigger } from "@radix-ui/react-tooltip";
import { TooltipContent } from "@/components/ui/tooltip.jsx";
import { SidebarInset, SidebarProvider, SidebarTrigger } from '@/components/ui/sidebar';
import { TooltipContent } from '@/components/ui/tooltip.jsx';
import { Toaster } from '@/components/ui/toaster';
export default function AppLayout({ auth, header, children, toolbar }) {

View File

@@ -1,5 +1,5 @@
import { useState } from "react";
import { Head, router } from '@inertiajs/react';
import { useState } from 'react';
import { Head, Link, router } from '@inertiajs/react';
import AppLayout from '@/Layouts/AppLayout.jsx';
import { BreadcrumbItem, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb";
@@ -24,16 +24,9 @@ export default function Histories({ auth, histories }) {
}
}
const deleteButtonOnClickHandler = (e) => {
if (ids.length === 0) {
toast({
title: "Error",
description: `No items selected.`,
});
return;
}
const deleteButtonOnClickHandler = () => {
router.visit(route('comics.destroyHistories'), {
data: { ids: ids },
data: (ids.length > 0) ? { ids: ids } : { ids: 'all' },
method: "PATCH",
only: ['histories'],
onSuccess: data => {
@@ -58,15 +51,17 @@ export default function Histories({ auth, histories }) {
<title>Histories</title>
</Head>
<div className="p-3 pt-1 w-[90%] mx-auto">
<div className="flex justify-end">
<Button size="sm" onClick={ () => deleteButtonOnClickHandler() }>Delete Selected</Button>
<div className="flex justify-end gap-2">
<Button size="sm" variant="destructive" onClick={ () => deleteButtonOnClickHandler() }>
{ ids.length > 0 ? `Delete selected (${ids.length})` : "Delete All" }
</Button>
</div>
<Table>
<TableHeader>
<TableRow>
<TableHead>Select</TableHead>
<TableHead>Comic</TableHead>
<TableHead>Chapter</TableHead>
<TableHead>Comic</TableHead>
<TableHead>Read at</TableHead>
</TableRow>
</TableHeader>
@@ -80,8 +75,16 @@ export default function Histories({ auth, histories }) {
onChange={ (e) => checkboxOnChangeHandler(e) } />
</label>
</TableCell>
<TableCell>{ h.name }</TableCell>
<TableCell>{ h.comic.name }</TableCell>
<TableCell>
<Link href={ route('comics.read', [h.comic.pathword, h.chapter_uuid]) }>
{ h.name }
</Link>
</TableCell>
<TableCell>
<Link href={ route('comics.chapters', [h.comic.pathword]) }>
{ h.comic.name }
</Link>
</TableCell>
<TableCell>{ h.created_at }</TableCell>
</TableRow>
)) }

View File

@@ -58,8 +58,9 @@ export default function Index({ comics, offset, auth }) {
<Head>
<title>Home</title>
</Head>
<div className="p-3 pt-1 grid lg:grid-cols-6 sm:grid-cols-2 gap-2">
<div className="p-3 pt-1 grid 2xl:grid-cols-6 xl:grid-cols-4 sm:grid-cols-2 gap-2">
<ComicCards { ...comics } />
<button onClick={() => {throw new Error("This is your first error!");}}>Break the world</button>;
</div>
<Pagination className="justify-end pb-2">
<PaginationContent>

View File

@@ -1,18 +1,22 @@
import { Head, Link, router } from '@inertiajs/react';
import AppLayout from '@/Layouts/AppLayout.jsx';
import React, { useEffect, useLayoutEffect, useRef, useState } from 'react';
import { BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator } from "@/components/ui/breadcrumb.jsx";
import { Button } from "@/components/ui/button";
import { ChevronFirst, ChevronLast, Rows3, Settings } from "lucide-react";
import { Tooltip, TooltipProvider, TooltipTrigger } from '@radix-ui/react-tooltip';
import { throttle } from 'lodash';
import { BreadcrumbItem, BreadcrumbLink, BreadcrumbPage, BreadcrumbSeparator } from '@/components/ui/breadcrumb';
import { Button } from '@/components/ui/button';
import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog";
import PrimaryButton from "@/components/PrimaryButton.jsx";
import { Switch } from "@/components/ui/switch";
import { Tooltip, TooltipProvider, TooltipTrigger } from "@radix-ui/react-tooltip";
import { TooltipContent } from "@/components/ui/tooltip.jsx";
import { throttle } from "lodash";
import PrimaryButton from '@/components/PrimaryButton';
import { Switch } from '@/components/ui/switch';
import { TooltipContent } from "@/components/ui/tooltip";
export default function Read({ auth, comic, chapter }) {
const validReadingModes = ['rtl', 'utd'];
const [readingMode, setReadingMode] = useState('rtl'); // rtl, utd
const [isTwoPagesPerScreen, setIsTwoPagePerScreen] = useState(false);
const [currentImage, setCurrentImage] = useState(1);
@@ -24,6 +28,14 @@ export default function Read({ auth, comic, chapter }) {
const [loading, setLoading] = useState(true);
const getLocalStorageReadingMode = () => {
if (window.localStorage.getItem('readingMode') !== null && validReadingModes.includes(window.localStorage.getItem('readingMode'))) {
return window.localStorage.getItem('readingMode');
}
return "rtl";
}
function useWindowSize() {
const [size, setSize] = useState([0, 0]);
useLayoutEffect(() => {
@@ -41,8 +53,10 @@ export default function Read({ auth, comic, chapter }) {
const toggleReadingMode = (e) => {
if (e) {
window.localStorage.setItem('readingMode', 'utd');
setReadingMode('utd');
} else {
window.localStorage.setItem('readingMode', 'rtl');
setReadingMode('rtl');
}
}
@@ -154,7 +168,7 @@ export default function Read({ auth, comic, chapter }) {
<label>Reading Mode</label>
<p>Turn on for UTD mode</p>
</div>
<Switch defaultChecked={ readingMode === "utd" }
<Switch defaultChecked={ (readingMode === "utd") }
onCheckedChange={ (e) => toggleReadingMode(e) } />
</div>
</div>
@@ -227,6 +241,8 @@ export default function Read({ auth, comic, chapter }) {
}, [windowSize]);
useEffect(() => {
setReadingMode(getLocalStorageReadingMode());
if (!ref.current) return;
const handleScroll = () => {

View File

@@ -4,9 +4,25 @@ import './bootstrap';
import { createInertiaApp } from '@inertiajs/react';
import { resolvePageComponent } from 'laravel-vite-plugin/inertia-helpers';
import { createRoot } from 'react-dom/client';
import * as Sentry from "@sentry/react";
const appName = import.meta.env.VITE_APP_NAME || 'Laravel';
Sentry.init({
dsn: "https://2adec7430e89618582219032ea835a8d@o1017868.ingest.us.sentry.io/4508547646029824",
integrations: [
Sentry.browserTracingIntegration(),
Sentry.replayIntegration(),
],
// Tracing
tracesSampleRate: 0.1, // Capture 10% of the transactions
// Set 'tracePropagationTargets' to control for which URLs distributed tracing should be enabled
tracePropagationTargets: ["localhost", /^https:\/\/c\.yumj\.in/],
// Session Replay
replaysSessionSampleRate: 0.1, // This sets the sample rate at 10%. You may want to change it to 100% while in development and then sample at a lower rate in production.
replaysOnErrorSampleRate: 1.0, // If you're not already sampling the entire session, change the sample rate to 100% when sampling sessions where errors occur.
});
createInertiaApp({
title: (title) => `${title} - ${appName}`,
resolve: (name) =>