perf: further improvements to ep list speed for onepiece
Some checks are pending
Check / check (push) Waiting to run

This commit is contained in:
ThaUnknown 2025-07-18 14:32:57 +02:00
parent 35bc9a48c0
commit 8c5e19a9b7
No known key found for this signature in database
4 changed files with 40 additions and 45 deletions

View file

@ -1,6 +1,6 @@
{
"name": "ui",
"version": "6.4.55",
"version": "6.4.56",
"license": "BUSL-1.1",
"private": true,
"packageManager": "pnpm@9.15.5",

View file

@ -11,7 +11,7 @@
import type { EpisodesResponse } from '$lib/modules/anizip/types'
import { episodes as _episodes, dedupeAiring, notes, type Media } from '$lib/modules/anilist'
import { episodes as _episodes, notes, type Media } from '$lib/modules/anilist'
import { authAggregator, list, progress } from '$lib/modules/auth'
import { makeEpisodeList } from '$lib/modules/extensions'
import { click, dragScroll } from '$lib/modules/navigate'
@ -23,19 +23,11 @@
$: episodeCount = _episodes(media) ?? eps?.episodeCount ?? 0
const alSchedule: Record<number, Date | undefined> = {}
$: {
for (const { a: airingAt, e: episode } of dedupeAiring(media)) {
alSchedule[episode] = new Date(airingAt * 1000)
}
}
$: episodeList = media && makeEpisodeList(media, eps)
const perPage = 16
function getPage (page: number, list: typeof episodeList = episodeList) {
function getPage (page: number, list = episodeList) {
return list.slice((page - 1) * perPage, page * perPage)
}

View file

@ -1,6 +1,5 @@
import type { ScheduleMedia } from './queries'
import type { Media, MediaEdge } from './types'
import type { Episode, Episodes } from '../anizip/types'
import type { ResultOf } from 'gql.tada'
export function banner (media: Pick<Media, 'trailer' | 'bannerImage' | 'coverImage'>): string | undefined {
@ -145,31 +144,6 @@ export const nextYear = date.getFullYear() + (nextSeason === 'WINTER' ? 1 : 0)
export const lastSeason = ['WINTER', 'SPRING', 'SUMMER', 'FALL'].at(Math.floor(((date.getMonth() - 3) / 12) * 4) % 4) as 'WINTER' | 'SPRING' | 'SUMMER' | 'FALL'
export const lastYear = date.getFullYear() - (lastSeason === 'FALL' ? 1 : 0)
export function episodeByAirDate (alDate: Date | undefined, episodes: Episodes, episode: number): Episode | undefined {
if (!alDate || !+alDate) return episodes[Number(episode)] ?? episodes[episode]
// 1 is key for episod 1, not index
// find closest episodes by air date, multiple episodes can have the same air date distance
const closestEpisodes: Episode[] = Object.values(episodes).reduce<Episode[]>((prev, curr) => {
if (!prev[0]) return [curr]
const prevDate = Math.abs(+new Date(prev[0].airdate ?? 0) - +alDate)
const currDate = Math.abs(+new Date(curr.airdate ?? 0) - +alDate)
if (prevDate === currDate) {
prev.push(curr)
return prev
}
if (currDate < prevDate) return [curr]
return prev
}, [])
if (!closestEpisodes.length) return episodes[Number(episode)] ?? episodes[episode]
// if multiple episodes have the same air date, return the one closest to the requested episode number
return closestEpisodes.reduce((prev, curr) => {
return Math.abs(Number(curr.episode) - episode) < Math.abs(Number(prev.episode) - episode) ? curr : prev
})
}
export function dedupeAiring (media: ResultOf<typeof ScheduleMedia>) {
return [...media.aired?.n ?? [], ...media.notaired?.n ?? []].filter((v, i, a) => v != null && a.findIndex(s => s?.e === v.e) === i) as Array<{ a: number, e: number }>
}

View file

@ -1,14 +1,14 @@
import anitomyscript, { type AnitomyResult } from 'anitomyscript'
import { get } from 'svelte/store'
import { dedupeAiring, episodeByAirDate, episodes, isMovie, type Media, getParentForSpecial, isSingleEpisode } from '../anilist'
import { dedupeAiring, episodes, isMovie, type Media, getParentForSpecial, isSingleEpisode } from '../anilist'
import { episodes as _episodes } from '../anizip'
import native from '../native'
import { settings, type videoResolutions } from '../settings'
import { storage } from './storage'
import type { EpisodesResponse, Titles } from '../anizip/types'
import type { EpisodesResponse, Titles, Episode } from '../anizip/types'
import type { TorrentResult } from 'hayase-extensions'
import { dev } from '$app/environment'
@ -52,6 +52,31 @@ export interface SingleEpisode {
anidbEid?: number
}
export function episodeByAirDate (alDate: Date | undefined, episodes: Map<string, Episode & { airdatems?: number }>, episode: number): Episode & { airdatems?: number } | undefined {
if (!alDate || !+alDate) return episodes.get('' + episode)
// 1 is key for episod 1, not index
// find closest episodes by air date, multiple episodes can have the same air date distance
const closestEpisodes: Episode[] = Object.values(episodes).reduce<Episode[]>((prev, curr) => {
if (!prev[0]) return [curr]
const prevDate = Math.abs(+new Date(prev[0].airdate ?? 0) - +alDate)
const currDate = Math.abs(+new Date(curr.airdate ?? 0) - +alDate)
if (prevDate === currDate) {
prev.push(curr)
return prev
}
if (currDate < prevDate) return [curr]
return prev
}, [])
if (!closestEpisodes.length) return episodes.get('' + episode)
// if multiple episodes have the same air date, return the one closest to the requested episode number
return closestEpisodes.reduce((prev, curr) => {
return Math.abs(Number(curr.episode) - episode) < Math.abs(Number(prev.episode) - episode) ? curr : prev
})
}
// TODO: https://anilist.co/anime/13055/
export function makeEpisodeList (media: Media, episodesRes?: EpisodesResponse | null) {
const count = episodes(media) ?? episodesRes?.episodeCount ?? 0
@ -66,7 +91,12 @@ export function makeEpisodeList (media: Media, episodesRes?: EpisodesResponse |
}
const episodeList: SingleEpisode[] = []
const filtered = { ...episodesRes?.episodes ?? {} }
const filtered = new Map<string, Episode & { airdatems?: number }>()
const now = Date.now()
for (const [key, value] of Object.entries(episodesRes?.episodes ?? {})) {
filtered.set(key, { ...value, airdatems: value.airdate ? +new Date(value.airdate) : undefined })
}
const hasSpecial = !!episodesRes?.specialCount
const hasCountMatch = (episodes(media) ?? 0) === (episodesRes?.episodeCount ?? 0)
// this code... doesn't scale well into the thousands, it takes almost a second or two to run for one piece
@ -85,16 +115,15 @@ export function makeEpisodeList (media: Media, episodesRes?: EpisodesResponse |
// return false
// })))
const resolvedEpisode = (needsValidation ? episodeByAirDate(airingAt, filtered, episode) : episodesRes?.episodes?.[Number(episode)])
const resolvedEpisode = needsValidation ? episodeByAirDate(airingAt, filtered, episode) : filtered.get('' + episode)
// we want to exclude episodes which were previously consumed
if (needsValidation && resolvedEpisode) {
for (const [key, value] of Object.entries(filtered)) {
for (const [key, value] of filtered.entries()) {
if (
(value.anidbEid != null && value.anidbEid === resolvedEpisode.anidbEid) ||
(value.airdate != null && new Date(value.airdate) < new Date(resolvedEpisode.airdate ?? Date.now()))
(value.airdatems != null && value.airdatems < (resolvedEpisode.airdatems ?? now))
) {
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
delete filtered[key as keyof typeof filtered]
filtered.delete(key)
}
}
}