[FA-27] Still need to test events

This commit is contained in:
gamer147
2026-01-19 15:40:21 -05:00
parent 1ecfd9cc99
commit c97654631b
2 changed files with 256 additions and 24 deletions

View File

@@ -54,6 +54,7 @@
} from '$lib/components/ui/tooltip';
import { formatRelativeTime, formatAbsoluteTime } from '$lib/utils/time';
import { sanitizeHtml } from '$lib/utils/sanitize';
import ChapterBookmarkButton from './ChapterBookmarkButton.svelte';
// Direct imports for faster builds
import ArrowLeft from '@lucide/svelte/icons/arrow-left';
import ExternalLink from '@lucide/svelte/icons/external-link';
@@ -144,6 +145,32 @@
)
);
// Bookmark lookup by chapterId for quick access in chapter list
const bookmarkLookup = $derived(
new Map(bookmarks.map((b) => [b.chapterId, b]))
);
function handleChapterBookmarkChange(chapterId: number, isBookmarked: boolean, description?: string | null) {
if (isBookmarked) {
// Add or update bookmark in local state
const existingIndex = bookmarks.findIndex((b) => b.chapterId === chapterId);
const newBookmark = {
id: existingIndex >= 0 ? bookmarks[existingIndex].id : -1, // temp id
chapterId,
description: description ?? null,
createdTime: new Date().toISOString()
};
if (existingIndex >= 0) {
bookmarks[existingIndex] = newBookmark;
} else {
bookmarks = [...bookmarks, newBookmark];
}
} else {
// Remove bookmark from local state
bookmarks = bookmarks.filter((b) => b.chapterId !== chapterId);
}
}
const chapterCount = $derived(
sortedVolumes.reduce((sum, v) => sum + v.chapters.length, 0)
);
@@ -200,9 +227,9 @@
}
});
// Load bookmarks when tab is first activated
// Load bookmarks when novel is loaded (for count display)
$effect(() => {
if (activeTab === 'bookmarks' && !bookmarksLoaded && novelId) {
if (novel && !bookmarksLoaded && novelId) {
fetchBookmarks();
}
});
@@ -591,24 +618,36 @@
<div class="max-h-96 overflow-y-auto -mx-2">
{#each singleVolumeChapters as chapter (chapter.id)}
{@const chapterDate = chapter.lastUpdatedTime ? new Date(chapter.lastUpdatedTime) : null}
<a
href="/novels/{novelId}/volumes/{sortedVolumes[0]?.order}/chapters/{chapter.order}"
class="flex items-center justify-between px-3 py-2.5 hover:bg-muted/50 rounded-md transition-colors group"
>
<div class="flex items-center gap-3 min-w-0">
{@const chapterBookmark = bookmarkLookup.get(chapter.id)}
<div class="flex items-center px-3 py-2.5 hover:bg-muted/50 rounded-md transition-colors group">
<a
href="/novels/{novelId}/volumes/{sortedVolumes[0]?.order}/chapters/{chapter.order}"
class="flex items-center gap-3 min-w-0 flex-1"
>
<span class="text-muted-foreground text-sm font-medium shrink-0 w-14">
Ch. {chapter.order}
</span>
<span class="text-sm truncate group-hover:text-primary transition-colors">
{chapter.name}
</span>
</a>
<div class="flex items-center gap-2 shrink-0 ml-2">
{#if chapterDate}
<span class="text-xs text-muted-foreground/70">
{formatRelativeTime(chapterDate)}
</span>
{/if}
{#if novelId}
<ChapterBookmarkButton
novelId={parseInt(novelId, 10)}
chapterId={chapter.id}
isBookmarked={!!chapterBookmark}
bookmarkDescription={chapterBookmark?.description}
onBookmarkChange={(isBookmarked, description) => handleChapterBookmarkChange(chapter.id, isBookmarked, description)}
/>
{/if}
</div>
{#if chapterDate}
<span class="text-xs text-muted-foreground/70 shrink-0 ml-2">
{formatRelativeTime(chapterDate)}
</span>
{/if}
</a>
</div>
{/each}
</div>
{:else}
@@ -630,24 +669,36 @@
<div class="space-y-0.5">
{#each volumeChapters as chapter (chapter.id)}
{@const chapterDate = chapter.lastUpdatedTime ? new Date(chapter.lastUpdatedTime) : null}
<a
href="/novels/{novelId}/volumes/{volume.order}/chapters/{chapter.order}"
class="flex items-center justify-between px-3 py-2.5 hover:bg-muted/50 rounded-md transition-colors group"
>
<div class="flex items-center gap-3 min-w-0">
{@const chapterBookmark = bookmarkLookup.get(chapter.id)}
<div class="flex items-center px-3 py-2.5 hover:bg-muted/50 rounded-md transition-colors group">
<a
href="/novels/{novelId}/volumes/{volume.order}/chapters/{chapter.order}"
class="flex items-center gap-3 min-w-0 flex-1"
>
<span class="text-muted-foreground text-sm font-medium shrink-0 w-14">
Ch. {chapter.order}
</span>
<span class="text-sm truncate group-hover:text-primary transition-colors">
{chapter.name}
</span>
</a>
<div class="flex items-center gap-2 shrink-0 ml-2">
{#if chapterDate}
<span class="text-xs text-muted-foreground/70">
{formatRelativeTime(chapterDate)}
</span>
{/if}
{#if novelId}
<ChapterBookmarkButton
novelId={parseInt(novelId, 10)}
chapterId={chapter.id}
isBookmarked={!!chapterBookmark}
bookmarkDescription={chapterBookmark?.description}
onBookmarkChange={(isBookmarked, description) => handleChapterBookmarkChange(chapter.id, isBookmarked, description)}
/>
{/if}
</div>
{#if chapterDate}
<span class="text-xs text-muted-foreground/70 shrink-0 ml-2">
{formatRelativeTime(chapterDate)}
</span>
{/if}
</a>
</div>
{/each}
</div>
</AccordionContent>