This commit is contained in:
User
2024-12-28 22:41:16 -05:00
parent 55414d56a4
commit 2b52f7f15a
8 changed files with 163 additions and 40 deletions

View File

@@ -113,7 +113,11 @@ export default function Chapters({ auth, comic, chapters, histories }) {
</tr>
<tr>
<td className="text-right pr-3">Authors</td>
<td>{ comic.comic.author.map(a => <Badge key={ a.path_word } className="m-2" variant="outline"><Link>{ a.name }</Link></Badge>) }</td>
<td>{ comic.comic.author.map(a => (
<Badge key={ a.path_word } className="m-2" variant="outline">
<Link href={ route('comics.author', [a.path_word]) }>{ a.name }</Link>
</Badge>
) ) }</td>
</tr>
<tr>
<td className="text-right pr-3">Description</td>

View File

@@ -12,7 +12,7 @@ import { useToast } from '@/hooks/use-toast.js';
export default function Index({ comics, offset, auth }) {
const url = new URL(window.location).searchParams;
const url = new URL(window.location); //searchParams
const [favourites, setFavourites] = useState(auth.user.favourites);
const { toast } = useToast();
@@ -43,7 +43,11 @@ export default function Index({ comics, offset, auth }) {
<CardContent>
<CardTitle><Link href={ `/comic/${ props.path_word }` }>{ props.name }</Link></CardTitle>
<CardDescription className="pt-2">
{ props.author.map(a => <Badge className="m-1" key={ a.path_word } variant="outline"><Link>{ a.name }</Link></Badge>) }
{ props.author.map(a => (
<Badge className="m-1" key={ a.path_word } variant="outline">
{ a.name }
</Badge>)
) }
</CardDescription>
</CardContent>
</Card>
@@ -65,11 +69,11 @@ export default function Index({ comics, offset, auth }) {
<PaginationContent>
{ parseInt(offset) !== 0 &&
<PaginationItem>
<PaginationPrevious href={ `/?${url}` } only={['comics', 'offset']} headers={{ offset: parseInt(offset) - 30 }} />
<PaginationPrevious href={ `${ url.pathname }?${ url.searchParams }` } only={['comics', 'offset']} headers={{ offset: parseInt(offset) - 30 }} />
</PaginationItem>
}
<PaginationItem>
<PaginationNext href={ `/?${url}` } only={['comics', 'offset']} headers={{ offset: parseInt(offset) + 30 }} />
<PaginationNext href={ `${ url.pathname }?${ url.searchParams }` } only={['comics', 'offset']} headers={{ offset: parseInt(offset) + 30 }} />
</PaginationItem>
</PaginationContent>
</Pagination>

View File

@@ -18,7 +18,7 @@ export default function Read({ auth, comic, chapter }) {
const validReadingModes = ['rtl', 'utd'];
const [readingMode, setReadingMode] = useState('rtl'); // rtl, utd
const [isTwoPagesPerScreen, setIsTwoPagePerScreen] = useState(false);
const [isTwoPagesPerScreen, setIsTwoPagePerScreen] = useState(false); // TODO
const [currentImage, setCurrentImage] = useState(1);
const windowSize = useWindowSize();
@@ -228,13 +228,13 @@ export default function Read({ auth, comic, chapter }) {
let visibleImageIndex = 0;
// Determine which image is visible based on scroll position
images.forEach((image, index) => {
images.forEach((image, i) => {
const imageTop = image.offsetTop; // Distance from top of the container
const imageBottom = imageTop + image.offsetHeight;
// Check if the image is in the visible area
if (containerScrollTop + 80 >= imageTop && containerScrollTop < imageBottom) {
visibleImageIndex = index;
visibleImageIndex = i;
}
});
@@ -242,12 +242,9 @@ export default function Read({ auth, comic, chapter }) {
setCurrentImage(visibleImageIndex + 1);
};
const throttledHandleScroll = throttle(handleScroll, 100); // Throttle for performance
const throttledHandleScroll = throttle(handleScroll, 1000); // Throttle for performance
ref.current.addEventListener("scroll", throttledHandleScroll);
// Initial check for visible image
handleScroll();
return () => {
if (ref.current) {
ref.current.removeEventListener("scroll", throttledHandleScroll);

View File

@@ -1,18 +1,26 @@
import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarMenu, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem, SidebarMenuSub, SidebarMenuSubButton, SidebarMenuSubItem } from '@/components/ui/sidebar';
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
import { useState } from 'react';
import { Link, router, usePage } from '@inertiajs/react';
import { BadgeCheck, ChevronsUpDown, Star, History, ChevronDown, LogOut, Search, Book } from 'lucide-react';
import { BadgeCheck, ChevronsUpDown, Star, History, ChevronDown, LogOut, ChevronRight } from 'lucide-react';
import { Link, usePage } from '@inertiajs/react';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible"
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
import { DropdownMenu, DropdownMenuContent, DropdownMenuGroup, DropdownMenuItem, DropdownMenuLabel, DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu';
import { Sidebar, SidebarContent, SidebarFooter, SidebarGroup, SidebarGroupContent, SidebarGroupLabel, SidebarHeader, SidebarInput, SidebarMenu, SidebarMenuBadge, SidebarMenuButton, SidebarMenuItem } from '@/components/ui/sidebar';
export function AppSidebar({ auth }) {
const { tags } = usePage().props;
const [search, setSearch] = useState('');
const searchOnSubmitHandler = (e) => {
e.preventDefault();
// Visit the search page
router.get(route('comics.search', [search]), {}, {
});
}
const SidebarItem = (props) => {
const searchParams = new URL(window.location).searchParams;
const isActive = (!searchParams.has(props.query) && props.name === 'All') || (searchParams.has(props.query) && searchParams.get(props.query) === props.path_word);
@@ -27,8 +35,9 @@ export function AppSidebar({ auth }) {
return (
<SidebarMenuItem>
<SidebarMenuButton asChild isActive={ isActive }>
<Link
href={ "/?" + searchParams.toString() }><span>{ props.name }</span></Link>
<Link href={ "/?" + searchParams.toString() } onClick={ (e) => setSearch("") }>
<span>{ props.name }</span>
</Link>
</SidebarMenuButton>
{ props.count && <SidebarMenuBadge>{ props.count }</SidebarMenuBadge> }
</SidebarMenuItem>
@@ -38,6 +47,32 @@ export function AppSidebar({ auth }) {
return (
<Sidebar>
<SidebarContent>
<SidebarHeader>
<SidebarMenu>
<SidebarMenuItem>
<SidebarMenuButton size="lg" asChild>
<Link href={ route('comics.index')}>
<div className="flex aspect-square size-8 items-center justify-center rounded-lg bg-sidebar-primary text-sidebar-primary-foreground">
<Book className="size-4" />
</div>
<div className="flex flex-col gap-0.5 leading-none">
<span className="font-semibold">Comic</span>
<span>0.0.0</span>
</div>
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
</SidebarMenu>
<SidebarGroup className="py-0">
<SidebarGroupContent className="relative">
<form onSubmit={ (e) => searchOnSubmitHandler(e)} >
<label htmlFor="search" className="sr-only">Search</label>
<SidebarInput onChange={ (e) => setSearch(e.target.value) } id="search" placeholder="Search" className="pl-8" />
<Search className="pointer-events-none absolute left-2 top-1/2 size-4 -translate-y-1/2 select-none opacity-50" />
</form>
</SidebarGroupContent>
</SidebarGroup>
</SidebarHeader>
<Collapsible defaultOpen className="group/collapsible">
<SidebarGroup>
<SidebarGroupLabel asChild>
@@ -48,7 +83,7 @@ export function AppSidebar({ auth }) {
<CollapsibleContent>
<SidebarGroupContent>
<SidebarMenu>
<SidebarItem path_word="all" query="tag" name="All" />
<SidebarItem path_word="all" query="tag" name="All" />
{ tags.theme.map(item => <SidebarItem query="tag" key={ item.path_word } { ...item } />) }
</SidebarMenu>
</SidebarGroupContent>