History Links
LocalStorage for reading mode Debugging with Sentry
This commit is contained in:
@@ -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 }) {
|
||||
|
||||
|
||||
@@ -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>
|
||||
)) }
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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 = () => {
|
||||
|
||||
@@ -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) =>
|
||||
|
||||
Reference in New Issue
Block a user