From 5628209b47f354205e14354e57fa33588f39a408 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 22 Nov 2024 14:23:10 +0000 Subject: [PATCH 1/4] friday websites update (#894) * Remove MonoManga * Remove TsukiMangas * Remove ComicOnlineFree parking page * domain changes --- web/src/engine/websites/ComicOnlineFree.ts | 37 ------ web/src/engine/websites/ComicOnlineFree.webp | Bin 430 -> 0 bytes .../engine/websites/ComicOnlineFree_e2e.ts | 23 ---- web/src/engine/websites/MonoManga.ts | 21 ---- web/src/engine/websites/MonoManga.webp | Bin 472 -> 0 bytes web/src/engine/websites/MonoManga_e2e.ts | 24 ---- web/src/engine/websites/SekaiKomik.ts | 2 +- web/src/engine/websites/SekaiKomik_e2e.ts | 2 +- web/src/engine/websites/TsukiMangas.ts | 114 ------------------ web/src/engine/websites/TsukiMangas.webp | Bin 1158 -> 0 bytes web/src/engine/websites/TsukiMangas_e2e.ts | 24 ---- web/src/engine/websites/YaoiMangaOku.ts | 2 +- web/src/engine/websites/YaoiMangaOku_e2e.ts | 2 +- web/src/engine/websites/_index.ts | 3 - web/src/engine/websites/legacy/MeioNovel.ts | 2 +- web/src/engine/websites/legacy/NhatTruyen.ts | 2 +- 16 files changed, 6 insertions(+), 252 deletions(-) delete mode 100644 web/src/engine/websites/ComicOnlineFree.ts delete mode 100644 web/src/engine/websites/ComicOnlineFree.webp delete mode 100644 web/src/engine/websites/ComicOnlineFree_e2e.ts delete mode 100755 web/src/engine/websites/MonoManga.ts delete mode 100644 web/src/engine/websites/MonoManga.webp delete mode 100755 web/src/engine/websites/MonoManga_e2e.ts delete mode 100644 web/src/engine/websites/TsukiMangas.ts delete mode 100644 web/src/engine/websites/TsukiMangas.webp delete mode 100644 web/src/engine/websites/TsukiMangas_e2e.ts diff --git a/web/src/engine/websites/ComicOnlineFree.ts b/web/src/engine/websites/ComicOnlineFree.ts deleted file mode 100644 index ce07bde4ae..0000000000 --- a/web/src/engine/websites/ComicOnlineFree.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { Tags } from '../Tags'; -import icon from './ComicOnlineFree.webp'; -import { DecoratableMangaScraper, type Manga, type MangaPlugin } from '../providers/MangaPlugin'; -import * as Common from './decorators/Common'; - -function ChapterExtractor(anchor: HTMLAnchorElement) { - const id = anchor.pathname + '/full'; - const title = anchor.text.trim(); - return { id, title }; -} -function PageExtractor(element: HTMLImageElement): string { - return element.dataset.original || element.getAttribute('src'); -} - -@Common.MangaCSS(/^{origin}\/comic\/[^/]+$/, 'div.manga-details td strong') -@Common.ChaptersSinglePageCSS('ul.basic-list li a.ch-name', ChapterExtractor) -@Common.PagesSinglePageCSS('div.chapter-container img', PageExtractor) -@Common.ImageAjax() -export default class extends DecoratableMangaScraper { - - public constructor() { - super('comiconlinefree', `ComicOnlineFree`, 'https://comiconlinefree.org', Tags.Language.English, Tags.Media.Comic, Tags.Source.Aggregator); - } - - public override get Icon() { - return icon; - } - - public override async FetchMangas(provider: MangaPlugin) : Promise{ - const mangalist : Manga[] = []; - const paths = ['others'].concat('abcdefghijklmnopqrstuvwxyz'.split('')); - for (const letter of paths) { - mangalist.push(... await Common.FetchMangasMultiPageCSS.call(this, provider, `/comic-list/${letter}/{page}`, 'div.chapter a.jtip')); - } - return mangalist; - } -} \ No newline at end of file diff --git a/web/src/engine/websites/ComicOnlineFree.webp b/web/src/engine/websites/ComicOnlineFree.webp deleted file mode 100644 index a76ea76d607b6835cf5d4d7e35bf8ba3c0ac8dc0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 430 zcmV;f0a5-^Nk&Gd0RRA3MM6+kP&go(0RR9n4FH`1DnI~006v96p-`nHBO<%`C;*@k zfCCxi0OuyD9lP>Z*(%ZgD}*w~=KvW|d**+H(s{Q=D<0T7YfLB$#o6 z@D8;k*fm#M_(GvE(@4Ju8u%{);tb09XX|h&C+WLMACh+eTEPTBq;m8T!;M&)0&_2* zcRy&SaAX+LZQ)};zoVWXodsNhu_^!E&a%I6h9v}@lS6m4pCp52kN+qF(eJ`3>)hb+ z&)K-W_TxG=bYTz{+X>4Q=0o6Skvn2Uph0ZT2e>H~HOzEfHQ~}uRZJ%dwdKE$Jlp6` YY8w&&wQCFapWU+~NHBXUmR#|G00sofW&i*H diff --git a/web/src/engine/websites/ComicOnlineFree_e2e.ts b/web/src/engine/websites/ComicOnlineFree_e2e.ts deleted file mode 100644 index 21e5e406fb..0000000000 --- a/web/src/engine/websites/ComicOnlineFree_e2e.ts +++ /dev/null @@ -1,23 +0,0 @@ -import { TestFixture, type Config } from '../../../test/WebsitesFixture'; -const config: Config = { - plugin: { - id: 'comiconlinefree', - title: 'ComicOnlineFree' - }, - container: { - url: 'https://comiconlinefree.org/comic/avengers-spotlight', - id: '/comic/avengers-spotlight', - title: 'Avengers: Spotlight' - }, - child: { - id: '/avengers-spotlight/issue-full/full', - title: '#Full' - }, - entry: { - index: 0, - size: 492_586, - type: 'image/jpeg' - } -}; - -new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/MonoManga.ts b/web/src/engine/websites/MonoManga.ts deleted file mode 100755 index c199896bd0..0000000000 --- a/web/src/engine/websites/MonoManga.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { Tags } from '../Tags'; -import icon from './MonoManga.webp'; -import { DecoratableMangaScraper } from '../providers/MangaPlugin'; -import * as Madara from './decorators/WordPressMadara'; -import * as Common from './decorators/Common'; - -@Madara.MangaCSS(/^{origin}\/manga\/[^/]+\/$/, 'div.post-title h1') -@Madara.MangasMultiPageAJAX() -@Madara.ChaptersSinglePageAJAXv2() -@Madara.PagesSinglePageCSS() -@Common.ImageAjax() -export default class extends DecoratableMangaScraper { - - public constructor() { - super('monomanga', 'MonoManga', 'https://monomanga.com', Tags.Media.Manhua, Tags.Media.Manhwa, Tags.Language.Turkish); - } - - public override get Icon() { - return icon; - } -} \ No newline at end of file diff --git a/web/src/engine/websites/MonoManga.webp b/web/src/engine/websites/MonoManga.webp deleted file mode 100644 index 0a398875366daf5c358406619595b4a8d0a63505..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 472 zcmV;}0Vn=aNk&G{0RRA3MM6+kP&gpO0RRBd2mqY{DnI~006x)JrcNj%qoOJt$}s>M z31a}yg}RZuXb^yMp=TMDcqhp_Igm1LoJ{z#N_QUTbKX!mu~FpC-Ygv7a~6Ou#7Yn| zf*=6?_CGwOy}>79xQj{6!9CLx^rPROen>g9F5jJR;z##f!~V84YgJ6wme5()n>3D8?7>$bH^tRip zNv=k9FN-mJhTVqDJSk0Y7m}4c9D{cYLL{i@6KosS;5teobHC5k>A!pRA`30lcQ-?ca&*IXb9$1Tcj294QyC1?}EjwNY7GHON>GjW?TVON{`vdgyv1yL~4%CLRRo1#bj O9ECk#My%0VKmY)^f!Ce@ diff --git a/web/src/engine/websites/MonoManga_e2e.ts b/web/src/engine/websites/MonoManga_e2e.ts deleted file mode 100755 index 69705bfa6f..0000000000 --- a/web/src/engine/websites/MonoManga_e2e.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; - -const config = { - plugin: { - id: 'monomanga', - title: 'MonoManga' - }, - container: { - url: 'https://monomanga.com/manga/tomodachi-game/', - id: JSON.stringify({ post: '1944', slug: '/manga/tomodachi-game/' }), - title: 'Tomodachi Game' - }, - child: { - id: '/manga/tomodachi-game/anime-sonrasi/bolum-26/', - title: 'Bölüm 26 - Bu Oyunu "Reddedemezsiniz"' - }, - entry: { - index: 0, - size: 763_441, - type: 'image/png' - } -}; - -new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/SekaiKomik.ts b/web/src/engine/websites/SekaiKomik.ts index 85150842fc..56ab8fba13 100644 --- a/web/src/engine/websites/SekaiKomik.ts +++ b/web/src/engine/websites/SekaiKomik.ts @@ -12,7 +12,7 @@ import * as Common from './decorators/Common'; export default class extends DecoratableMangaScraper { public constructor() { - super('sekaikomik', 'SekaiKomik', 'https://sekaikomik.lol', Tags.Media.Manga, Tags.Media.Manhwa, Tags.Language.Indonesian, Tags.Rating.Pornographic, Tags.Source.Aggregator); + super('sekaikomik', 'SekaiKomik', 'https://sekaikomik.mom', Tags.Media.Manga, Tags.Media.Manhwa, Tags.Language.Indonesian, Tags.Rating.Pornographic, Tags.Source.Aggregator); } public override get Icon() { diff --git a/web/src/engine/websites/SekaiKomik_e2e.ts b/web/src/engine/websites/SekaiKomik_e2e.ts index ad49e52554..790f4097d5 100644 --- a/web/src/engine/websites/SekaiKomik_e2e.ts +++ b/web/src/engine/websites/SekaiKomik_e2e.ts @@ -6,7 +6,7 @@ const config: Config = { title: 'SekaiKomik' }, container: { - url: 'https://sekaikomik.lol/manga/circles/', + url: 'https://sekaikomik.mom/manga/circles/', id: '/manga/circles/', title: 'Circles' }, diff --git a/web/src/engine/websites/TsukiMangas.ts b/web/src/engine/websites/TsukiMangas.ts deleted file mode 100644 index e944e5854d..0000000000 --- a/web/src/engine/websites/TsukiMangas.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { Tags } from '../Tags'; -import icon from './TsukiMangas.webp'; -import { Chapter, DecoratableMangaScraper, Manga, type MangaPlugin, Page } from '../providers/MangaPlugin'; -import * as Common from './decorators/Common'; -import { Fetch, FetchJSON } from '../platform/FetchProvider'; -import type { Priority } from '../taskpool/DeferredTask'; - -type APIResult = { - data : T -} - -type APIManga = { - id: number, - title: string, -} - -type APIChapter = { - id: number, - number: string, - title: string | null - pages?: { - url: string, - }[] -} - -type PageParameters = { - mirrors: string[], -}; - -@Common.ImageAjax() -export default class extends DecoratableMangaScraper { - - private readonly apiUrl = `${this.URI.origin}/api/v3/`; - public constructor() { - super('tsukimangas', 'Tsuki-Mangas', 'https://tsuki-mangas.com', Tags.Media.Manhwa, Tags.Media.Manhua, Tags.Media.Manga, Tags.Language.Portuguese, Tags.Source.Aggregator); - } - - public override get Icon() { - return icon; - } - - public override ValidateMangaURL(url: string): boolean { - return new RegExp(`^${this.URI.origin}/obra/\\d+/[^/]+$`).test(url); - } - - public override async FetchManga(provider: MangaPlugin, url: string): Promise { - const mangaId = url.split('/').at(-2); - const { title } = await FetchJSON(this.CreateRequest(`mangas/${mangaId}`)); - return new Manga(this, provider, mangaId, title); - } - - public override async FetchMangas(provider: MangaPlugin): Promise { - const mangaList : Manga[]= []; - for (let page = 1, run = true; run; page++) { - await new Promise(resolve => setTimeout(resolve, 500)); - const mangas = await this.GetMangasFromPage(page, provider); - mangas.length > 0 ? mangaList.push(...mangas) : run = false; - } - return mangaList; - } - - private async GetMangasFromPage(page: number, provider: MangaPlugin): Promise { - const { data } = await FetchJSON>(this.CreateRequest(`home/lastests?page=${page}?format=0`)); - return data.map(manga => new Manga(this, provider, manga.id.toString(), manga.title)); - } - - public override async FetchChapters(manga: Manga): Promise { - const chapterList = []; - for (let page = 1, run = true; run; page++) { - await new Promise(resolve => setTimeout(resolve, 200)); - const chapters = await this.GetChaptersFromPage(manga, page); - chapters.length > 0 ? chapterList.push(...chapters) : run = false; - } - return chapterList; - } - - public async GetChaptersFromPage(manga: Manga, page : number): Promise { - const { data } = await FetchJSON>(this.CreateRequest(`chapters?manga_id=${manga.Identifier}&page=${page}&order=desc`)); - return data.map(chapter => { - const title = chapter.title ? [chapter.number, chapter.title].join(' : ') : chapter.number; - return new Chapter(this, manga, chapter.id.toString(), title.trim()); - }); - } - - public override async FetchPages(chapter: Chapter): Promise[]> { - const { pages } = await FetchJSON(this.CreateRequest(`chapter/versions/${chapter.Identifier}`)); - return pages?.map(page => { - return new Page(this, chapter, new URL(`https://cdn.tsuki-mangas.com/tsuki${page.url}`), { - mirrors: [ - new URL(page.url, 'https://cdn2.tsuki-mangas.com').href - ] - }); - }) ?? []; - } - - public override async FetchImage(page: Page, priority: Priority, signal: AbortSignal): Promise { - return this.imageTaskPool.Add(async () => { - for (const uri of [page.Link, ...page.Parameters.mirrors]) { - try { - const request = new Request(uri, { signal: signal, headers: { Referer: this.URI.href } }); - const response = await Fetch(request); - if (response.headers.get('Content-Type').startsWith('image/')) { - return response.blob(); - } - } catch { } - } - }, priority, signal); - } - - private CreateRequest(endpoint: string): Request { - return new Request(new URL(endpoint, this.apiUrl), { headers: { Referer: this.URI.origin } }); - } - -} \ No newline at end of file diff --git a/web/src/engine/websites/TsukiMangas.webp b/web/src/engine/websites/TsukiMangas.webp deleted file mode 100644 index 5dbcd1bb0557cb78f26dd8b06d6aabbd88523453..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1158 zcmV;11bO>XNk&F~1ONb6MM6+kP&il$0000G0000#002J#06|PpNQ43a00E#xYuh17 zdcOaUzihQ__t^Hii4%$YIYRzaJHL4AIMhyfYjOrWLNYAK&kmXtJ zpI?6c?To(o zuSA){+Ku_YDOIXudpK1(o`{H}r88-GS6UG^N|jq4drew1%dzOu2k!n@`s(icpIVn& zHS)(pUrWz5aEf$X#!=GggtwKh$e6FB-SNC4t)5jHaj@hgYRFDsT-PCY?uvr|lbQFARukGH)B{qaIvUL>wxeON8TA#d_z6Sy)X9 zJO8M7RXlZ>{}skSAe9?;f?ai4TJdq{6b81|a9cZn9BsgeIzz}L>P z%0=JZ+K4?Y?Z>=gq6>OM&$&v5<`camEzcX$=c948Ifuxzmqzr}gP$lZ&Vj2G>#q<0 zRID2?_qNiNSoBY#MCf;z@YG@A*z{r11Xs7)I-npB9t&^JCj_*fY65mLYI<;iq_Op2+>RawX8x-`@sc z4nKM6=>Z3r(KutNnN2tcbociKjL_dZFhEy-f1t+R0P~cZr_>vj8nrbu%fg&hLL0aj2rAk+Z>05A&xodGI906+jfg+ifFr6eOFvHWNNpb&rnP9?7b zXine^dSB|k%>FAg+w>Q(Kk85X4!|CU|DXrxA8+@ri8Tmi}{`t^$4r}FS6aqoPi|N1`ox<(LL{L3!S2ym|hF*U%vNl-% zm}q7CO+wvDJIV^uQ=6#^P2x@=U>Jia;kNrLfv)foKE6>OK5m#A!@V0ZE6M!)%x8^# z{L!jnlFp_nLw+FAf8Ei~R%7S?^Oy6hwpZQQ4xScS6Ad(H&>%oc2>k6A;sTeNbl{R zAG+L5ZCj`g`f&Tb55bTbKLqQsUeXWQZsx0==?axKEQgWDK0KDclGc@K;Y`s@U+5?M zb;)vfvpT@9P{zw1gI}vc36fOY4V|=JiMh2ccBWBANXLY2k2;q_?5`=&N0BR*R#Q*>R diff --git a/web/src/engine/websites/TsukiMangas_e2e.ts b/web/src/engine/websites/TsukiMangas_e2e.ts deleted file mode 100644 index d2732c3ff6..0000000000 --- a/web/src/engine/websites/TsukiMangas_e2e.ts +++ /dev/null @@ -1,24 +0,0 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; - -const config = { - plugin: { - id: 'tsukimangas', - title: 'Tsuki-Mangas' - }, /* CloudFlare - container: { - url: 'https://tsuki-mangas.com/obra/105/tower-of-god-3-season', - id: '105', - title: 'Tower of God 3 season' - }, - child: { - id: '/read/207989/34655/1', - title: '217' - }, - entry: { - index: 0, - size: 632_904, - type: 'image/png' - }*/ -}; - -new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/YaoiMangaOku.ts b/web/src/engine/websites/YaoiMangaOku.ts index c7fca50ffd..318ea8f4d3 100644 --- a/web/src/engine/websites/YaoiMangaOku.ts +++ b/web/src/engine/websites/YaoiMangaOku.ts @@ -12,7 +12,7 @@ import * as Common from './decorators/Common'; export default class extends DecoratableMangaScraper { public constructor() { - super('yaoimangaoku', 'YaoiMangaOku', 'https://yaoimangaoku.com', Tags.Media.Manga, Tags.Media.Manhwa, Tags.Media.Manhua, Tags.Language.Turkish, Tags.Source.Aggregator); + super('yaoimangaoku', 'YaoiMangaOku', 'https://yaoimangaoku.net', Tags.Media.Manga, Tags.Media.Manhwa, Tags.Media.Manhua, Tags.Language.Turkish, Tags.Source.Aggregator); } public override get Icon() { diff --git a/web/src/engine/websites/YaoiMangaOku_e2e.ts b/web/src/engine/websites/YaoiMangaOku_e2e.ts index 64be7deaf2..7e2207bdfe 100644 --- a/web/src/engine/websites/YaoiMangaOku_e2e.ts +++ b/web/src/engine/websites/YaoiMangaOku_e2e.ts @@ -6,7 +6,7 @@ const config: Config = { title: 'YaoiMangaOku' }, container: { - url: 'https://yaoimangaoku.com/manga/she-is-still-cute-today/', + url: 'https://yaoimangaoku.net/manga/she-is-still-cute-today/', id: JSON.stringify({ post: '681', slug: '/manga/she-is-still-cute-today/'}), title: 'She Is Still Cute Today' }, diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 83a1260309..557ed4eb4b 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -67,7 +67,6 @@ export { default as ComicGardo } from './ComicGardo'; export { default as ComicGrowl } from './ComicGrowl'; export { default as ComicK } from './ComicK'; export { default as Comico } from './Comico'; -export { default as ComicOnlineFree } from './ComicOnlineFree'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; @@ -457,7 +456,6 @@ export { default as MiniTwoScan } from './MiniTwoScan'; export { default as mkzhan } from './mkzhan'; export { default as MMFenix } from './MMFenix'; export { default as MonochromeScans } from './MonochromeScans'; -export { default as MonoManga } from './MonoManga'; export { default as MonzeeKomik } from './MonzeeKomik'; export { default as MrYaoi } from './MrYaoi'; export { default as MultPorn } from './MultPorn'; @@ -657,7 +655,6 @@ export { default as TruyenTranhDammy } from './TruyenTranhDammy'; export { default as TruyenTranhOnline } from './TruyenTranhOnline'; export { default as TruyenTranhtuan } from './TruyenTranhtuan'; export { default as TRWebtoon } from './TRWebtoon'; -export { default as TsukiMangas } from './TsukiMangas'; export { default as Tsumino } from './Tsumino'; export { default as TukangKomik } from './TukangKomik'; export { default as TuMangaNet } from './TuMangaNet'; diff --git a/web/src/engine/websites/legacy/MeioNovel.ts b/web/src/engine/websites/legacy/MeioNovel.ts index 4a54476b5a..8e8c608a96 100755 --- a/web/src/engine/websites/legacy/MeioNovel.ts +++ b/web/src/engine/websites/legacy/MeioNovel.ts @@ -8,7 +8,7 @@ import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; export default class extends DecoratableMangaScraper { public constructor() { - super('meionovel', `Meio Novel`, 'https://meionovel.id' /*, Tags.Language.English, Tags ... */); + super('meionovel', `Meio Novel`, 'https://meionovels.com' /*, Tags.Language.English, Tags ... */); } public override get Icon() { diff --git a/web/src/engine/websites/legacy/NhatTruyen.ts b/web/src/engine/websites/legacy/NhatTruyen.ts index 6ed1eadebd..6fdf577b6e 100755 --- a/web/src/engine/websites/legacy/NhatTruyen.ts +++ b/web/src/engine/websites/legacy/NhatTruyen.ts @@ -8,7 +8,7 @@ import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; export default class extends DecoratableMangaScraper { public constructor() { - super('nhattruyen', `NhatTruyen`, 'https://nhattruyenvn.com' /*, Tags.Language.English, Tags ... */); + super('nhattruyen', `NhatTruyen`, 'https://nhattruyenv.com' /*, Tags.Language.English, Tags ... */); } public override get Icon() { From afbc234b28b24f141fad77a3de27d0cd7d668fca Mon Sep 17 00:00:00 2001 From: Sheep Date: Fri, 22 Nov 2024 16:04:06 +0100 Subject: [PATCH 2/4] [UI classic] Plugin datatable svelte5 fix --- .../classic/components/PluginSelect.svelte | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/web/src/frontend/classic/components/PluginSelect.svelte b/web/src/frontend/classic/components/PluginSelect.svelte index 72c5e1dc39..d84bed3a00 100644 --- a/web/src/frontend/classic/components/PluginSelect.svelte +++ b/web/src/frontend/classic/components/PluginSelect.svelte @@ -45,22 +45,20 @@ }; } - export let isPluginModalOpen = false; - let pagination = { - totalItems: 0, - page: 1, - pageSize: 10, - pageSizes: [5, 10, 20], - }; + interface Props { + isPluginModalOpen?: boolean; + } + + let { isPluginModalOpen = $bindable(false) }: Props = $props(); - let pluginToConfigure: MediaContainer; + let pluginToConfigure: MediaContainer = $state(); const langTags = Tags.Language.toArray(); const typeTags = Tags.Media.toArray(); const otherTags = [...Tags.Source.toArray(), ...Tags.Rating.toArray()]; - let pluginNameFilter = ''; - let pluginTagsFilter: Tag[] = []; + let pluginNameFilter = $state(''); + let pluginTagsFilter: Tag[] = $state([]); function addTagFilter(tag: Tag) { if (!pluginTagsFilter.includes(tag)) { @@ -71,10 +69,8 @@ pluginTagsFilter = pluginTagsFilter.filter((value) => tag !== value); } - let filterFavorites = false; - let filteredPluginlist: ReturnType[] = []; - $: { - filteredPluginlist = HakuNeko.PluginController.WebsitePlugins.filter( + let filterFavorites = $state(false); + let filteredPluginlist: ReturnType[] = $derived(HakuNeko.PluginController.WebsitePlugins.filter( (plugin) => { let rejectconditions: Array = []; if ( @@ -92,9 +88,14 @@ } return !rejectconditions.length; }, - ).map((item) => createDataRow(item)); - pagination.totalItems = filteredPluginlist.length; - } + ).map((item) => createDataRow(item))); + + // Pagination + let page = $state(1); + let pageSize = $state(10); + let pageSizes = $state([5, 10, 20]); + let totalItems = $derived(filteredPluginlist.length); + { $selectedPlugin = event.detail.overflow; @@ -185,7 +186,8 @@ /> - + + {#if header.key === 'favorite'}