This commit is contained in:
User
2025-01-21 19:57:07 -05:00
parent befc90dd02
commit d9f57e4e86
17 changed files with 206 additions and 230 deletions

View File

@@ -3,7 +3,6 @@
namespace App\Http\Controllers;
use App\Helper\ZhConversion;
use App\Jobs\ComicInsert;
use App\Jobs\ComicUpsert;
use App\Jobs\ImageUpsert;
use App\Jobs\RemotePrefetch;
@@ -224,7 +223,7 @@ class ComicController extends Controller
$offset = $request->header('offset', 0);
$comic = $this->copyManga->comic($pathword);
$chapters = $this->copyManga->chapters($pathword, 200, $offset, [], $request->get('group', 'default'));
$chapters = $this->copyManga->chapters($pathword, 200, $offset, [], $request->get('group', 'default'), $request->get('reload', false));
// Get the comic object and fill other parameters
try {

View File

@@ -4,15 +4,13 @@ namespace App\Jobs;
use App\Models\Author;
use App\Models\Comic;
use App\Models\Image;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Log;
use romanzipp\QueueMonitor\Traits\IsMonitored;
class ComicUpsert implements ShouldQueue
{
use IsMonitored, Queueable;
use Queueable;
/**
* Create a new job instance.
@@ -26,7 +24,6 @@ class ComicUpsert implements ShouldQueue
*/
public function handle(): void
{
$this->queueProgress(0);
Log::info("JOB ComicUpsert START");
$comicsUpsertArray = [];
@@ -66,6 +63,5 @@ class ComicUpsert implements ShouldQueue
}
Log::info('JOB ComicUpsert END');
$this->queueProgress(100);
}
}

View File

@@ -6,11 +6,10 @@ use App\Models\Image;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Log;
use romanzipp\QueueMonitor\Traits\IsMonitored;
class ImageUpsert implements ShouldQueue
{
use IsMonitored, Queueable;
use Queueable;
/**
* Create a new job instance.
@@ -26,12 +25,7 @@ class ImageUpsert implements ShouldQueue
*/
public function handle(): void
{
$this->queueProgress(0);
Log::info("JOB ImageUpsert START, comicId: {$this->comicId}, chapterId: {$this->chapterId}");
$this->queueData([
'comicId' => $this->comicId,
'chapterId' => $this->chapterId,
]);
$arrayForUpsert = [];
@@ -53,6 +47,5 @@ class ImageUpsert implements ShouldQueue
Image::upsert($arrayForUpsert, uniqueBy: 'url');
Log::info('JOB ImageUpsert END');
$this->queueProgress(100);
}
}

View File

@@ -6,11 +6,10 @@ use App\Remote\CopyManga;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Illuminate\Support\Facades\Log;
use romanzipp\QueueMonitor\Traits\IsMonitored;
class RemotePrefetch implements ShouldQueue
{
use IsMonitored, Queueable;
use Queueable;
/**
* Create a new job instance.
@@ -25,17 +24,11 @@ class RemotePrefetch implements ShouldQueue
*/
public function handle(): void
{
$this->queueProgress(0);
$copyManga = new CopyManga();
switch ($this->action) {
case 'chapter':
Log::info("JOB RemotePrefetch START, action '{$this->action}', Pathword: {$this->parameters['pathword']}, UUID: {$this->parameters['uuid']}");
$this->queueData([
'action' => $this->action,
'pathword' => $this->parameters['pathword'],
'uuid' => $this->parameters['uuid']
]);
$copyManga->chapter($this->parameters['pathword'], $this->parameters['uuid']);
@@ -46,13 +39,6 @@ class RemotePrefetch implements ShouldQueue
break;
case 'comics':
Log::info("JOB RemotePrefetch START, action '{$this->action}', Offset: {$this->parameters['offset']}");
$this->queueData([
'action' => $this->action,
'offset' => $this->parameters['offset'],
'limit' => $this->parameters['limit'],
'top' => $this->parameters['top'],
'params' => $this->parameters['params']
]);
$copyManga->comics($this->parameters['offset'], $this->parameters['limit'], $this->parameters['top'], $this->parameters['params']);
@@ -62,7 +48,5 @@ class RemotePrefetch implements ShouldQueue
Log::info("JOB RemotePrefetch Unknown action '{$this->action}'");
break;
}
$this->queueProgress(100);
}
}

View File

@@ -123,19 +123,24 @@ class CopyManga
* @param string $method
* @param string $userAgent
* @param int $ttl
* @param bool $force
* @return mixed|string
* @throws GuzzleException
*/
protected function execute(string $url, string $method = 'GET', string $userAgent = "", int $ttl = 0): mixed
protected function execute(string $url, string $method = 'GET', string $userAgent = "", int $ttl = 0, bool $force = false): mixed
{
if ($this->options['caching']) {
// Check cache exist
if (Cache::has("URL_{$url}")) {
$cache = Cache::get("URL_{$url}");
if (isset($cache['type']) && $cache['type'] == 'HTML') {
return $cache['response'];
} else {
return $cache;
if ($force) {
$this->forget($url);
} else {
if ($this->options['caching']) {
// Check cache exist
if (Cache::has("URL_{$url}")) {
$cache = Cache::get("URL_{$url}");
if (isset($cache['type']) && $cache['type'] == 'HTML') {
return $cache['response'];
} else {
return $cache;
}
}
}
}
@@ -178,6 +183,17 @@ class CopyManga
}
}
/**
* Remove a cache with key
*
* @param string $url
* @return void
*/
public function forget(string $url): void
{
Cache::forget("URL_{$url}");
}
/**
* Get tags available
*
@@ -256,16 +272,17 @@ class CopyManga
* @param int $offset
* @param array $parameters
* @param string $group
* @param bool $force
* @return mixed|string
* @throws GuzzleException
*/
public function chapters(string $comic, int $limit = 200, int $offset = 0, array $parameters = [], string $group = "default"): mixed
public function chapters(string $comic, int $limit = 200, int $offset = 0, array $parameters = [], string $group = "default", bool $force = false): mixed
{
$parameters['limit'] = $limit;
$parameters['offset'] = $offset;
$options = $this->execute($this->buildUrl("comic/{$comic}/group/{$group}/chapters", $parameters, false), 'OPTIONS');
return $this->execute($this->buildUrl("comic/{$comic}/group/{$group}/chapters", $parameters), ttl: 24 * 60 * 60);
return $this->execute($this->buildUrl("comic/{$comic}/group/{$group}/chapters", $parameters), ttl: 24 * 60 * 60, force: $force);
}
/**

View File

@@ -2,4 +2,5 @@
return [
App\Providers\AppServiceProvider::class,
App\Providers\HorizonServiceProvider::class,
];

BIN
bun.lockb

Binary file not shown.

View File

@@ -11,11 +11,11 @@
"ext-openssl": "*",
"inertiajs/inertia-laravel": "^2.0",
"laravel/framework": "^11.31",
"laravel/horizon": "^5.30",
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.9",
"plesk/ext-laravel-integration": "^7.0",
"predis/predis": "^2.0",
"romanzipp/laravel-queue-monitor": "^5.3",
"sentry/sentry-laravel": "^4.10",
"tightenco/ziggy": "^2.0"
},
@@ -60,7 +60,7 @@
],
"dev": [
"Composer\\Config::disableProcessTimeout",
"npx concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"npm run dev\" --names=server,queue,logs,vite"
"bun concurrently -c \"#93c5fd,#c4b5fd,#fb7185,#fdba74\" \"php artisan serve\" \"php artisan queue:listen --tries=1\" \"php artisan pail --timeout=0\" \"bun run dev\" --names=server,queue,logs,vite"
]
},
"extra": {

208
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "6f784bba21b3b875b87a164afa37ff36",
"content-hash": "4fdc8c399054a90a77205cf8919b938e",
"packages": [
{
"name": "brick/math",
@@ -1189,16 +1189,16 @@
},
{
"name": "laravel/framework",
"version": "v11.38.2",
"version": "v11.39.0",
"source": {
"type": "git",
"url": "https://github.com/laravel/framework.git",
"reference": "9d290aa90fcad44048bedca5219d2b872e98772a"
"reference": "996c96955f78e8a2b26a24c490a1721cfb14574f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/framework/zipball/9d290aa90fcad44048bedca5219d2b872e98772a",
"reference": "9d290aa90fcad44048bedca5219d2b872e98772a",
"url": "https://api.github.com/repos/laravel/framework/zipball/996c96955f78e8a2b26a24c490a1721cfb14574f",
"reference": "996c96955f78e8a2b26a24c490a1721cfb14574f",
"shasum": ""
},
"require": {
@@ -1399,7 +1399,87 @@
"issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework"
},
"time": "2025-01-15T00:06:46+00:00"
"time": "2025-01-21T15:02:43+00:00"
},
{
"name": "laravel/horizon",
"version": "v5.30.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/horizon.git",
"reference": "baef526f036717b0090754cbd9c9b67f879739fd"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/horizon/zipball/baef526f036717b0090754cbd9c9b67f879739fd",
"reference": "baef526f036717b0090754cbd9c9b67f879739fd",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-pcntl": "*",
"ext-posix": "*",
"illuminate/contracts": "^9.21|^10.0|^11.0",
"illuminate/queue": "^9.21|^10.0|^11.0",
"illuminate/support": "^9.21|^10.0|^11.0",
"nesbot/carbon": "^2.17|^3.0",
"php": "^8.0",
"ramsey/uuid": "^4.0",
"symfony/console": "^6.0|^7.0",
"symfony/error-handler": "^6.0|^7.0",
"symfony/polyfill-php83": "^1.28",
"symfony/process": "^6.0|^7.0"
},
"require-dev": {
"mockery/mockery": "^1.0",
"orchestra/testbench": "^7.0|^8.0|^9.0",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^9.0|^10.4",
"predis/predis": "^1.1|^2.0"
},
"suggest": {
"ext-redis": "Required to use the Redis PHP driver.",
"predis/predis": "Required when not using the Redis PHP driver (^1.1|^2.0)."
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Horizon": "Laravel\\Horizon\\Horizon"
},
"providers": [
"Laravel\\Horizon\\HorizonServiceProvider"
]
},
"branch-alias": {
"dev-master": "5.x-dev"
}
},
"autoload": {
"psr-4": {
"Laravel\\Horizon\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Taylor Otwell",
"email": "taylor@laravel.com"
}
],
"description": "Dashboard and code-driven configuration for Laravel queues.",
"keywords": [
"laravel",
"queue"
],
"support": {
"issues": "https://github.com/laravel/horizon/issues",
"source": "https://github.com/laravel/horizon/tree/v5.30.2"
},
"time": "2025-01-13T16:51:22+00:00"
},
{
"name": "laravel/prompts",
@@ -3681,76 +3761,6 @@
],
"time": "2024-04-27T21:32:50+00:00"
},
{
"name": "romanzipp/laravel-queue-monitor",
"version": "5.3.7",
"source": {
"type": "git",
"url": "https://github.com/romanzipp/Laravel-Queue-Monitor.git",
"reference": "7412f5315bbb2fa5ea4a05743d615e56b397a96e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/romanzipp/Laravel-Queue-Monitor/zipball/7412f5315bbb2fa5ea4a05743d615e56b397a96e",
"reference": "7412f5315bbb2fa5ea4a05743d615e56b397a96e",
"shasum": ""
},
"require": {
"ext-json": "*",
"ext-mbstring": "*",
"illuminate/database": "^5.5|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0",
"illuminate/queue": "^5.5|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0",
"illuminate/support": "^5.5|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0",
"nesbot/carbon": "^2.0|^3.0",
"php": "^8.0"
},
"require-dev": {
"doctrine/dbal": "^3.1",
"friendsofphp/php-cs-fixer": "^3.0",
"laravel/framework": "^5.5|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0",
"mockery/mockery": "^1.3.2",
"orchestra/testbench": ">=3.8",
"phpstan/phpstan": "^0.12.99|^1.0",
"phpunit/phpunit": "^8.5.23|^9.0|^10.5",
"romanzipp/php-cs-fixer-config": "^3.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"romanzipp\\QueueMonitor\\Providers\\QueueMonitorProvider"
]
}
},
"autoload": {
"psr-4": {
"romanzipp\\QueueMonitor\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "romanzipp",
"email": "ich@ich.wtf",
"homepage": "https://ich.wtf"
}
],
"description": "Queue Monitoring for Laravel Database Job Queue",
"support": {
"issues": "https://github.com/romanzipp/Laravel-Queue-Monitor/issues",
"source": "https://github.com/romanzipp/Laravel-Queue-Monitor/tree/5.3.7"
},
"funding": [
{
"url": "https://github.com/romanzipp",
"type": "github"
}
],
"time": "2024-12-05T14:46:27+00:00"
},
{
"name": "sentry/sentry",
"version": "4.10.0",
@@ -7036,16 +7046,16 @@
},
{
"name": "laravel/breeze",
"version": "v2.3.1",
"version": "v2.3.2",
"source": {
"type": "git",
"url": "https://github.com/laravel/breeze.git",
"reference": "60ac80abfa08c3c2dbc61e4b16f02230b843cfd3"
"reference": "2a4764055792b14e0e571a710adbda9c9eb300d4"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/laravel/breeze/zipball/60ac80abfa08c3c2dbc61e4b16f02230b843cfd3",
"reference": "60ac80abfa08c3c2dbc61e4b16f02230b843cfd3",
"url": "https://api.github.com/repos/laravel/breeze/zipball/2a4764055792b14e0e571a710adbda9c9eb300d4",
"reference": "2a4764055792b14e0e571a710adbda9c9eb300d4",
"shasum": ""
},
"require": {
@@ -7093,7 +7103,7 @@
"issues": "https://github.com/laravel/breeze/issues",
"source": "https://github.com/laravel/breeze"
},
"time": "2025-01-13T16:52:29+00:00"
"time": "2025-01-21T14:57:42+00:00"
},
{
"name": "laravel/pail",
@@ -7544,16 +7554,16 @@
},
{
"name": "pestphp/pest",
"version": "v3.7.1",
"version": "v3.7.2",
"source": {
"type": "git",
"url": "https://github.com/pestphp/pest.git",
"reference": "bf3178473dcaa53b0458f21dfdb271306ea62512"
"reference": "709ecb1ba2641fc0c4653ebe1fd8a402bbf4d18b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/pestphp/pest/zipball/bf3178473dcaa53b0458f21dfdb271306ea62512",
"reference": "bf3178473dcaa53b0458f21dfdb271306ea62512",
"url": "https://api.github.com/repos/pestphp/pest/zipball/709ecb1ba2641fc0c4653ebe1fd8a402bbf4d18b",
"reference": "709ecb1ba2641fc0c4653ebe1fd8a402bbf4d18b",
"shasum": ""
},
"require": {
@@ -7564,17 +7574,17 @@
"pestphp/pest-plugin-arch": "^3.0.0",
"pestphp/pest-plugin-mutate": "^3.0.5",
"php": "^8.2.0",
"phpunit/phpunit": "^11.5.1"
"phpunit/phpunit": "^11.5.3"
},
"conflict": {
"filp/whoops": "<2.16.0",
"phpunit/phpunit": ">11.5.1",
"phpunit/phpunit": ">11.5.3",
"sebastian/exporter": "<6.0.0",
"webmozart/assert": "<1.11.0"
},
"require-dev": {
"pestphp/pest-dev-tools": "^3.3.0",
"pestphp/pest-plugin-type-coverage": "^3.2.0",
"pestphp/pest-plugin-type-coverage": "^3.2.3",
"symfony/process": "^7.2.0"
},
"bin": [
@@ -7640,7 +7650,7 @@
],
"support": {
"issues": "https://github.com/pestphp/pest/issues",
"source": "https://github.com/pestphp/pest/tree/v3.7.1"
"source": "https://github.com/pestphp/pest/tree/v3.7.2"
},
"funding": [
{
@@ -7652,7 +7662,7 @@
"type": "github"
}
],
"time": "2024-12-12T11:52:01+00:00"
"time": "2025-01-19T17:35:09+00:00"
},
{
"name": "pestphp/pest-plugin",
@@ -8605,16 +8615,16 @@
},
{
"name": "phpunit/phpunit",
"version": "11.5.1",
"version": "11.5.3",
"source": {
"type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "2b94d4f2450b9869fa64a46fd8a6a41997aef56a"
"reference": "30e319e578a7b5da3543073e30002bf82042f701"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2b94d4f2450b9869fa64a46fd8a6a41997aef56a",
"reference": "2b94d4f2450b9869fa64a46fd8a6a41997aef56a",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/30e319e578a7b5da3543073e30002bf82042f701",
"reference": "30e319e578a7b5da3543073e30002bf82042f701",
"shasum": ""
},
"require": {
@@ -8628,14 +8638,14 @@
"phar-io/manifest": "^2.0.4",
"phar-io/version": "^3.2.1",
"php": ">=8.2",
"phpunit/php-code-coverage": "^11.0.7",
"phpunit/php-code-coverage": "^11.0.8",
"phpunit/php-file-iterator": "^5.1.0",
"phpunit/php-invoker": "^5.0.1",
"phpunit/php-text-template": "^4.0.1",
"phpunit/php-timer": "^7.0.1",
"sebastian/cli-parser": "^3.0.2",
"sebastian/code-unit": "^3.0.1",
"sebastian/comparator": "^6.2.1",
"sebastian/code-unit": "^3.0.2",
"sebastian/comparator": "^6.3.0",
"sebastian/diff": "^6.0.2",
"sebastian/environment": "^7.2.0",
"sebastian/exporter": "^6.3.0",
@@ -8686,7 +8696,7 @@
"support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.1"
"source": "https://github.com/sebastianbergmann/phpunit/tree/11.5.3"
},
"funding": [
{
@@ -8702,7 +8712,7 @@
"type": "tidelift"
}
],
"time": "2024-12-11T10:52:48+00:00"
"time": "2025-01-13T09:36:00+00:00"
},
{
"name": "sebastian/cli-parser",

View File

@@ -1,60 +0,0 @@
<?php
return [
// Set the table to be used for monitoring data.
'table' => 'queue_monitor',
'connection' => null,
/*
* Set the model used for monitoring.
* If using a custom model, be sure to implement the
* romanzipp\QueueMonitor\Models\Contracts\MonitorContract
* interface or extend the base model.
*/
'model' => \romanzipp\QueueMonitor\Models\Monitor::class,
// Determined if the queued jobs should be monitored
'monitor_queued_jobs' => true,
// Specify the max character length to use for storing exception backtraces.
'db_max_length_exception' => 4294967295,
'db_max_length_exception_message' => 65535,
// The optional UI settings.
'ui' => [
// Enable the UI
'enabled' => true,
// Accepts route group configuration
'route' => [
'prefix' => 'queues',
'middleware' => [],
],
// Set the monitored jobs count to be displayed per page.
'per_page' => 50,
// Show custom data stored on model
'show_custom_data' => true,
// Allow the deletion of single monitor items.
'allow_deletion' => true,
// Allow retry for a single failed monitor item.
'allow_retry' => true,
// Allow purging all monitor entries.
'allow_purge' => true,
'show_metrics' => true,
// Time frame used to calculate metrics values (in days).
'metrics_time_frame' => 14,
// The interval before refreshing the dashboard (in seconds).
'refresh_interval' => 5,
// Order the queued but not started jobs first
'order_queued_first' => false,
],
];

View File

@@ -7,18 +7,18 @@
},
"devDependencies": {
"@headlessui/react": "^2.2.0",
"@inertiajs/react": "^2.0.2",
"@inertiajs/react": "^2.0.3",
"@tailwindcss/forms": "^0.5.10",
"@vitejs/plugin-react": "^4.3.4",
"autoprefixer": "^10.4.20",
"axios": "^1.7.9",
"concurrently": "^9.1.2",
"laravel-vite-plugin": "^1.1.1",
"laravel-vite-plugin": "^1.2.0",
"postcss": "^8.5.1",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"tailwindcss": "^3.4.17",
"vite": "^6.0.7"
"vite": "^6.0.11"
},
"dependencies": {
"@hookform/resolvers": "^3.10.0",

View File

@@ -1,6 +1,6 @@
import { useState } from 'react';
import { Head, Link, router } from '@inertiajs/react';
import { Plus, Star, ArrowDownNarrowWide, ArrowUpNarrowWide, ChevronsLeft, ChevronsRight, Trash2 } from 'lucide-react';
import { Plus, Star, ArrowDownNarrowWide, ArrowUpNarrowWide, ChevronsLeft, ChevronsRight, Trash2, RefreshCw } from 'lucide-react';
import AppLayout from '@/Layouts/AppLayout.jsx';
@@ -47,6 +47,13 @@ export default function Chapters({ auth, comic, chapters, histories, offset }) {
});
}
const forceReload = (pathword) => {
router.get(`/comic/${ comic.comic.path_word }?reload=true`, {}, {
only: ['chapters'],
preserveState: true,
});
}
const groupOnClickHandler = (pathword) => {
router.get(`/comic/${ comic.comic.path_word }?group=${ pathword }`, {}, {
only: ['chapters'],
@@ -97,7 +104,8 @@ export default function Chapters({ auth, comic, chapters, histories, offset }) {
<Head>
<title>{ comic.comic.name }</title>
</Head>
<div className="p-3 pt-1">
<div className="p-3 pt-1 pb-1 flex flex-wrap justify-center" scroll-region="true"
style={{ overflowAnchor: "none", height: "calc(100dvh - 90px)", overflowY: "scroll" }}>
<Card>
<CardHeader>
<CardTitle className="flex flex-row content-end items-center">
@@ -188,6 +196,19 @@ export default function Chapters({ auth, comic, chapters, histories, offset }) {
</Tooltip>
</TooltipProvider>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="link" size="icon" onClick={ () => forceReload(comic.comic.path_word) }>
<RefreshCw />
</Button>
</TooltipTrigger>
<TooltipContent>
<p>Force reload</p>
</TooltipContent>
</Tooltip>
</TooltipProvider>
<TooltipProvider>
<Tooltip>
<TooltipTrigger asChild>
@@ -205,7 +226,7 @@ export default function Chapters({ auth, comic, chapters, histories, offset }) {
<TabsContent value={ group }>
<div
className="w-full grid grid-cols-1 md:grid-cols-2 lg:grid-cols-6 2xl:grid-cols-12 gap-1">
{ (chapters.total > chapters.limit && chapters.offset > 0) && (
{ (chapters.total > (chapters.limit + chapters.offset) && chapters.offset > 0) && (
<Button size="sm" variant="outline" asChild>
<Link href="?" only={['chapters', 'offset']} headers={{ offset: parseInt(chapters.offset) - chapters.limit }}>
<ChevronsLeft /> Prev

View File

@@ -73,7 +73,7 @@ export default function Histories({ auth, histories }) {
<div className="p-3 pt-1 w-[90%] mx-auto">
<div className="flex justify-end gap-2">
<Button size="sm" variant="destructive" onClick={ () => deleteButtonOnClickHandler() }>
{ ids.length > 0 ? `Delete selected (${ids.length})` : "Delete All" }
{ ids.length > 0 ? `Delete selected (${ ids.length })` : "Delete All" }
</Button>
<Button size="sm" variant="destructive" onClick={ () => removeDuplicatedButtonOnClickHandler() }>

View File

@@ -1,4 +1,4 @@
import { useState } from 'react';
import React, { useState } from 'react';
import { Head, Link } from '@inertiajs/react';
import { Star } from 'lucide-react';
@@ -82,21 +82,24 @@ export default function Index({ comics, offset, auth }) {
<Head>
<title>Home</title>
</Head>
<div className="p-3 pt-1 grid 2xl:grid-cols-6 xl:grid-cols-4 sm:grid-cols-2 gap-2">
<ComicCards { ...comics } />
</div>
<Pagination className="justify-end pb-2">
<PaginationContent>
{ parseInt(offset) !== 0 &&
<div className="p-3 pt-1 pb-1 flex flex-wrap justify-center" scroll-region="true"
style={{ overflowAnchor: "none", height: "calc(100dvh - 90px)", overflowY: "scroll" }}>
<div className="grid 2xl:grid-cols-6 xl:grid-cols-4 sm:grid-cols-2 gap-2">
<ComicCards { ...comics } />
</div>
<Pagination className="justify-end pt-2">
<PaginationContent>
{ parseInt(offset) !== 0 &&
<PaginationItem>
<PaginationPrevious href={ `${ url.pathname }?${ url.searchParams }` } only={['comics', 'offset']} headers={{ offset: parseInt(offset) - 30 }} />
</PaginationItem>
}
<PaginationItem>
<PaginationPrevious href={ `${ url.pathname }?${ url.searchParams }` } only={['comics', 'offset']} headers={{ offset: parseInt(offset) - 30 }} />
<PaginationNext href={ `${ url.pathname }?${ url.searchParams }` } only={['comics', 'offset']} headers={{ offset: parseInt(offset) + 30 }} />
</PaginationItem>
}
<PaginationItem>
<PaginationNext href={ `${ url.pathname }?${ url.searchParams }` } only={['comics', 'offset']} headers={{ offset: parseInt(offset) + 30 }} />
</PaginationItem>
</PaginationContent>
</Pagination>
</PaginationContent>
</Pagination>
</div>
</AppLayout>
);
}

View File

@@ -137,7 +137,7 @@ export default function Read({ auth, comic, chapter, chapters }) {
if (img.innerKey === 0 && chapter.chapter.prev) {
router.visit(route('comics.read', [comic.comic.path_word, chapter.chapter.prev]));
} else {
document.getElementById(`image-${img.innerKey - 1}`)?.scrollIntoView();
document.getElementById(`image-${ img.innerKey - 1 }`)?.scrollIntoView();
}
}
@@ -145,7 +145,7 @@ export default function Read({ auth, comic, chapter, chapters }) {
if (img.innerKey >= chapter.sorted.length - 1 && chapter.chapter.next) {
router.visit(route('comics.read', [comic.comic.path_word, chapter.chapter.next]));
} else {
document.getElementById(`image-${img.innerKey + 1}`)?.scrollIntoView();
document.getElementById(`image-${ img.innerKey + 1 }`)?.scrollIntoView();
}
}
@@ -370,7 +370,7 @@ export default function Read({ auth, comic, chapter, chapters }) {
<Head>
<title>{ chapter.chapter.name.concat(" - ", comic.comic.name) }</title>
</Head>
<div className="p-3 pt-1 pb-1 flex flex-wrap justify-center" id="mvp" ref={ ref }
<div className="p-3 pt-1 pb-1 flex flex-wrap justify-center" id="mvp" ref={ ref } scroll-region="true"
style={{ overflowAnchor: "none", height: "calc(100dvh - 90px)", overflowY: "scroll" }}>
{ chapter.sorted.map((img, j) => <ImageForComic key={ j } innerKey={ j } { ...img } />) }
</div>

View File

@@ -13,7 +13,19 @@ export default function Updates({ auth }) {
<div className="p-3 pt-1">
<Card className="w-[90%] m-3 mx-auto">
<CardHeader>
<CardTitle>0.1.3</CardTitle>
<CardTitle>0.1.4</CardTitle>
<CardDescription>Release: 21 Jan 2025</CardDescription>
</CardHeader>
<CardContent>
<ul>
<li>Ability for force refetch on chapters</li>
<li>Fixed top toolbar on comic pages</li>
</ul>
</CardContent>
</Card>
<Card className="w-[90%] m-3 mx-auto">
<CardHeader>
<CardTitle>0.1.3 / 0.1.3A</CardTitle>
<CardDescription>Release: 19 Jan 2025 / 18 Jan 2025</CardDescription>
</CardHeader>
<CardContent>

View File

@@ -86,7 +86,7 @@ export function AppSidebar({ auth }) {
</div>
<div className="flex flex-col gap-0.5 leading-none">
<span className="font-semibold">Comic</span>
<span>0.1.3A</span>
<span>0.1.4</span>
</div>
</Link>
</SidebarMenuButton>