Fixed images on rtl mode
This commit is contained in:
@@ -8,6 +8,8 @@ use App\Models\Comic;
|
||||
use App\Models\Image;
|
||||
use App\Remote\CopyManga;
|
||||
use App\Remote\ImageFetcher;
|
||||
use Exception;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use Illuminate\Contracts\Routing\ResponseFactory;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Foundation\Application;
|
||||
@@ -118,6 +120,13 @@ class ComicController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @param Request $request
|
||||
* @return Response
|
||||
* @throws GuzzleException
|
||||
*/
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$params = [];
|
||||
@@ -152,7 +161,7 @@ class ComicController extends Controller
|
||||
{
|
||||
$comics = $this->copyManga->search($search, 30, $request->header('offset', 0));
|
||||
|
||||
// Seacrh API is limited, no upsert
|
||||
// Search API is limited, no upsert
|
||||
|
||||
return Inertia::render('Comic/Index', [
|
||||
'comics' => $comics,
|
||||
@@ -163,7 +172,7 @@ class ComicController extends Controller
|
||||
public function chapters(Request $request, string $pathword = ''): Response
|
||||
{
|
||||
$comic = $this->copyManga->comic($pathword);
|
||||
$chapters = $this->copyManga->chapters($pathword, 200, 0, [], $request->get('group', 'default'));
|
||||
$chapters = $this->copyManga->chapters($pathword, 200, $request->header('offset', 0), [], $request->get('group', 'default'));
|
||||
|
||||
// Get the comic object and fill other parameters
|
||||
try {
|
||||
@@ -221,7 +230,8 @@ class ComicController extends Controller
|
||||
return Inertia::render('Comic/Chapters', [
|
||||
'comic' => $comic,
|
||||
'chapters' => $chapters,
|
||||
'histories' => $histories
|
||||
'histories' => $histories,
|
||||
'offset' => $request->header('offset', 0)
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -276,7 +286,7 @@ class ComicController extends Controller
|
||||
{
|
||||
// Get history
|
||||
$histories = $request->user()->readingHistories()->with(['comic:id,name,pathword'])->orderByDesc('reading_histories.created_at')
|
||||
->select(['reading_histories.id as hid', 'reading_histories.created_at', 'chapters.comic_id', 'chapters.name'])->paginate(50)->toArray();
|
||||
->select(['reading_histories.id as hid', 'reading_histories.created_at as read_at', 'chapters.comic_id', 'chapters.name'])->paginate(50)->toArray();
|
||||
|
||||
return Inertia::render('Comic/Histories', [
|
||||
'histories' => $histories
|
||||
|
||||
10
composer.lock
generated
10
composer.lock
generated
@@ -1654,16 +1654,16 @@
|
||||
},
|
||||
{
|
||||
"name": "league/commonmark",
|
||||
"version": "2.6.0",
|
||||
"version": "2.6.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/thephpleague/commonmark.git",
|
||||
"reference": "d150f911e0079e90ae3c106734c93137c184f932"
|
||||
"reference": "d990688c91cedfb69753ffc2512727ec646df2ad"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d150f911e0079e90ae3c106734c93137c184f932",
|
||||
"reference": "d150f911e0079e90ae3c106734c93137c184f932",
|
||||
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d990688c91cedfb69753ffc2512727ec646df2ad",
|
||||
"reference": "d990688c91cedfb69753ffc2512727ec646df2ad",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -1757,7 +1757,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2024-12-07T15:34:16+00:00"
|
||||
"time": "2024-12-29T14:10:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "league/config",
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { Link } from '@inertiajs/react';
|
||||
|
||||
export default function GuestLayout({ children }) {
|
||||
return (
|
||||
<div className="flex min-h-svh w-full items-center justify-center p-6 md:p-10">
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { Head, Link, useForm } from '@inertiajs/react';
|
||||
import GuestLayout from "@/Layouts/GuestLayout.jsx";
|
||||
|
||||
import InputError from '@/components/InputError';
|
||||
import Checkbox from '@/components/Checkbox';
|
||||
import PrimaryButton from '@/components/PrimaryButton';
|
||||
import TextInput from '@/components/TextInput';
|
||||
import { Head, Link, useForm } from '@inertiajs/react';
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card.jsx";
|
||||
import GuestLayout from "@/Layouts/GuestLayout.jsx";
|
||||
import { Alert, AlertDescription } from "@/components/ui/alert.jsx";
|
||||
|
||||
export default function Login({ status, canResetPassword }) {
|
||||
@@ -45,7 +46,7 @@ export default function Login({ status, canResetPassword }) {
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="email">E-mail Address</Label>
|
||||
<TextInput type="email" id="email" placeholder="me@yumj.in" value={ data.email }
|
||||
onChange={ (e) => setData('email', e.target.value) } required />
|
||||
tabIndex="1" onChange={ (e) => setData('email', e.target.value) } required />
|
||||
<InputError message={ errors.email } className="mt-2" />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
@@ -57,26 +58,23 @@ export default function Login({ status, canResetPassword }) {
|
||||
</Link>
|
||||
</div>
|
||||
<TextInput id="password" type="password" name="password" value={ data.password }
|
||||
autoComplete="current-password"
|
||||
autoComplete="current-password" tabIndex="2"
|
||||
onChange={ (e) => setData('password', e.target.value) } />
|
||||
<InputError message={ errors.password } className="mt-2" />
|
||||
</div>
|
||||
<div className="grid gap-2">
|
||||
<div className="flex items-center space-x-2">
|
||||
<Checkbox
|
||||
id="remember"
|
||||
name="remember"
|
||||
checked={ data.remember }
|
||||
onChange={ (e) =>
|
||||
setData('remember', e.target.checked)
|
||||
}
|
||||
/>
|
||||
<Checkbox id="remember" tabIndex="3" name="remember" checked={ data.remember }
|
||||
onChange={ (e) => setData('remember', e.target.checked) } />
|
||||
<label htmlFor="remember"
|
||||
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">Remember me</label>
|
||||
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70">
|
||||
Remember me
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<PrimaryButton type="submit" disabled={ processing }
|
||||
className="w-full">Login</PrimaryButton>
|
||||
<PrimaryButton type="submit" disabled={ processing } tabIndex="4" className="w-full">
|
||||
Login
|
||||
</PrimaryButton>
|
||||
</div>
|
||||
<div className="mt-4 text-center text-sm">
|
||||
Don't have an account?
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useState } from 'react';
|
||||
import { Head, Link, router } from '@inertiajs/react';
|
||||
import { Plus, Star, ArrowDownNarrowWide, ArrowUpNarrowWide } from 'lucide-react';
|
||||
import { Plus, Star, ArrowDownNarrowWide, ArrowUpNarrowWide, ChevronsLeft, ChevronsRight } from 'lucide-react';
|
||||
|
||||
import AppLayout from '@/Layouts/AppLayout.jsx';
|
||||
|
||||
@@ -12,7 +12,7 @@ import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip';
|
||||
import { useToast } from '@/hooks/use-toast';
|
||||
|
||||
export default function Chapters({ auth, comic, chapters, histories }) {
|
||||
export default function Chapters({ auth, comic, chapters, histories, offset }) {
|
||||
|
||||
const [group, setGroup] = useState('default');
|
||||
const [favourites, setFavourites] = useState(auth.user.favourites);
|
||||
@@ -113,11 +113,13 @@ export default function Chapters({ auth, comic, chapters, histories }) {
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-right pr-3">Authors</td>
|
||||
<td>{ comic.comic.author.map(a => (
|
||||
<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>
|
||||
) ) }
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-right pr-3">Description</td>
|
||||
@@ -125,7 +127,11 @@ export default function Chapters({ auth, comic, chapters, histories }) {
|
||||
</tr>
|
||||
<tr>
|
||||
<td className="text-right pr-3">Updated At</td>
|
||||
<td>{ comic.comic.datetime_updated }</td>
|
||||
<td>
|
||||
<Link href={ route('comics.read', [comic.comic.path_word, comic.comic.last_chapter.uuid])}>
|
||||
{ comic.comic.datetime_updated } - { comic.comic.last_chapter.name }
|
||||
</Link>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -151,9 +157,23 @@ export default function Chapters({ auth, comic, chapters, histories }) {
|
||||
</div>
|
||||
<TabsContent value={ group }>
|
||||
<div className="w-full grid grid-cols-1 md:grid-cols-2 lg:grid-cols-6 xl:grid-cols-12 gap-1">
|
||||
{ (chapters.total > chapters.limit && chapters.offset > 0) && (
|
||||
<Button size="sm" variant="outline" asChild>
|
||||
<Link href="?" only={['chapters', 'offset']} headers={{ offset: parseInt(chapters.offset) - chapters.limit }}>
|
||||
<ChevronsLeft /> Prev
|
||||
</Link>
|
||||
</Button>
|
||||
) }
|
||||
{ chapters.list.sort((a, b) => ascending ? (a.index - b.index) : (b.index - a.index)).map(c => (
|
||||
<ComicChapterLink key={ c.uuid } { ...c } />
|
||||
) ) }
|
||||
{ (chapters.total > chapters.limit && chapters.offset === 0) && (
|
||||
<Button size="sm" variant="outline" asChild>
|
||||
<Link href="?" only={['chapters', 'offset']} headers={{ offset: parseInt(chapters.offset) + chapters.limit }}>
|
||||
Next <ChevronsRight />
|
||||
</Link>
|
||||
</Button>
|
||||
) }
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
|
||||
@@ -97,7 +97,7 @@ export default function Histories({ auth, histories }) {
|
||||
{ h.comic.name }
|
||||
</Link>
|
||||
</TableCell>
|
||||
<TableCell className="hidden lg:block">{ datetimeConversion(h.created_at) }</TableCell>
|
||||
<TableCell className="hidden lg:block">{ datetimeConversion(h.read_at) }</TableCell>
|
||||
</TableRow>
|
||||
)) }
|
||||
</TableBody>
|
||||
|
||||
@@ -43,7 +43,7 @@ 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 => (
|
||||
{ props.author && props.author.map(a => (
|
||||
<Badge className="m-1" key={ a.path_word } variant="outline">
|
||||
{ a.name }
|
||||
</Badge>)
|
||||
|
||||
@@ -76,7 +76,7 @@ export default function Read({ auth, comic, chapter }) {
|
||||
} else if (divDimensions[0] > divDimensions[1] && readingMode === 'utd') {
|
||||
imgStyles = { width: '50%' };
|
||||
} else if (readingMode === 'rtl') {
|
||||
imgStyles = { height: 'calc(100dvh - 90px)' };
|
||||
imgStyles = { width: '100%', height: 'calc(100dvh - 90px)', objectFit: 'contain' };
|
||||
}
|
||||
|
||||
const handleImageClick = (e) => {
|
||||
@@ -156,6 +156,10 @@ export default function Read({ auth, comic, chapter }) {
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
|
||||
<Button variant="ghost">
|
||||
{ currentImage } / { chapter.sorted.length }
|
||||
</Button>
|
||||
|
||||
<TooltipProvider>
|
||||
<Tooltip>
|
||||
<TooltipTrigger>
|
||||
@@ -204,10 +208,6 @@ export default function Read({ auth, comic, chapter }) {
|
||||
</Tooltip>
|
||||
</TooltipProvider>
|
||||
) }
|
||||
|
||||
<Button variant="ghost">
|
||||
{ currentImage } / { chapter.sorted.length }
|
||||
</Button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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, Search, Book, TableOfContents } from 'lucide-react';
|
||||
|
||||
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible';
|
||||
@@ -57,7 +57,7 @@ export function AppSidebar({ auth }) {
|
||||
</div>
|
||||
<div className="flex flex-col gap-0.5 leading-none">
|
||||
<span className="font-semibold">Comic</span>
|
||||
<span>0.0.0</span>
|
||||
<span>0.0.1</span>
|
||||
</div>
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
@@ -73,6 +73,21 @@ export function AppSidebar({ auth }) {
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
</SidebarHeader>
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel>Others</SidebarGroupLabel>
|
||||
<SidebarGroupContent>
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton asChild>
|
||||
<Link href={ route('comics.index')}>
|
||||
<TableOfContents />
|
||||
<span>Manual</span>
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
</SidebarGroupContent>
|
||||
</SidebarGroup>
|
||||
<Collapsible defaultOpen className="group/collapsible">
|
||||
<SidebarGroup>
|
||||
<SidebarGroupLabel asChild>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=0, minimal-ui">
|
||||
<title inertia>{{ config('app.name', 'Laravel') }}</title>
|
||||
@routes
|
||||
@viteReactRefresh
|
||||
|
||||
Reference in New Issue
Block a user