mirror of
https://github.com/moku-project/Moku.git
synced 2026-06-13 17:29:55 -05:00
Chore: Remove Old Directory (Prepare for Patches)
This commit is contained in:
@@ -38,25 +38,19 @@
|
||||
|
||||
let allRecs: RecommendedManga[] = $state([])
|
||||
let loading = $state(false)
|
||||
let _ctrl: AbortController | null = null
|
||||
|
||||
$effect(() => {
|
||||
const _history = history
|
||||
const _library = libraryManga
|
||||
if (!_history.length || !_library.length) { allRecs = []; return }
|
||||
_ctrl?.abort()
|
||||
if (!history.length || !libraryManga.length) { allRecs = []; return }
|
||||
const ctrl = new AbortController()
|
||||
_ctrl = ctrl
|
||||
loading = true
|
||||
fetchRecommendations(_history, _library, ctrl.signal)
|
||||
fetchRecommendations(history, libraryManga, ctrl.signal)
|
||||
.then(r => { if (!ctrl.signal.aborted) { allRecs = r; loading = false } })
|
||||
.catch(() => { if (!ctrl.signal.aborted) loading = false })
|
||||
return () => ctrl.abort()
|
||||
})
|
||||
|
||||
const genres = $derived(topGenres(history, libraryManga))
|
||||
|
||||
let genreIdx = $state(0)
|
||||
|
||||
const genres = $derived(topGenres(history, libraryManga))
|
||||
let genreIdx = $state(0)
|
||||
const activeGenre = $derived(genres[genreIdx] ?? null)
|
||||
|
||||
const visibleRecs = $derived(
|
||||
@@ -233,7 +227,6 @@
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.empty-msg {
|
||||
font-family: var(--font-ui);
|
||||
font-size: var(--text-sm);
|
||||
|
||||
@@ -13,6 +13,7 @@ const TARGET_PER_GENRE = 20
|
||||
export function topGenres(history: ReadSession[], libraryManga: Manga[]): string[] {
|
||||
const byId = new Map(libraryManga.map(m => [m.id, m]))
|
||||
const tally = new Map<string, { count: number; original: string }>()
|
||||
|
||||
for (const session of history) {
|
||||
const manga = byId.get(session.mangaId)
|
||||
if (!manga?.genre?.length) continue
|
||||
@@ -23,6 +24,7 @@ export function topGenres(history: ReadSession[], libraryManga: Manga[]): string
|
||||
else tally.set(key, { count: 1, original: g })
|
||||
}
|
||||
}
|
||||
|
||||
return [...tally.values()]
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.slice(0, TOP_GENRES)
|
||||
@@ -35,25 +37,32 @@ export async function fetchRecommendations(
|
||||
signal?: AbortSignal,
|
||||
): Promise<RecommendedManga[]> {
|
||||
if (!history.length || !libraryManga.length) return []
|
||||
|
||||
const genres = topGenres(history, libraryManga)
|
||||
if (!genres.length) return []
|
||||
|
||||
const adapter = getAdapter()
|
||||
const globalSeen = new Set<number>(libraryManga.map(m => m.id))
|
||||
const merged: Manga[] = []
|
||||
|
||||
for (const genre of genres) {
|
||||
if (signal?.aborted) break
|
||||
try {
|
||||
const results = await adapter.getMangaByGenre(genre, { excludeInLibrary: true }, signal)
|
||||
for (const m of results) {
|
||||
if (globalSeen.has(m.id)) continue
|
||||
globalSeen.add(m.id)
|
||||
merged.push(m)
|
||||
if (merged.length >= genres.length * TARGET_PER_GENRE) break
|
||||
const perGenre = await Promise.all(
|
||||
genres.map(async genre => {
|
||||
if (signal?.aborted) return []
|
||||
try {
|
||||
const { items } = await adapter.getMangaList({ tags: [genre], inLibrary: false })
|
||||
return items
|
||||
} catch {
|
||||
return []
|
||||
}
|
||||
} catch {
|
||||
continue
|
||||
})
|
||||
)
|
||||
|
||||
const merged: Manga[] = []
|
||||
for (const items of perGenre) {
|
||||
for (const m of items) {
|
||||
if (globalSeen.has(m.id)) continue
|
||||
globalSeen.add(m.id)
|
||||
merged.push(m)
|
||||
if (merged.length >= genres.length * TARGET_PER_GENRE) break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user