feat(web): add series detail page at /series/<series_id>#44
Conversation
| full_thumbnails: undefined | ||
| } | ||
| // @ts-ignore - series_index is only present in SeriesSearchResponse | ||
| this.series_index = media_response.series_index |
There was a problem hiding this comment.
Instead of adding metadata to the base rune, you should put series specific metadata on the MediaSeriesRune
| /** | ||
| * Base params interface - common fields shared by all search types | ||
| */ | ||
| export interface BaseSearchParams { |
There was a problem hiding this comment.
Let's make BaseQueryParamsManager have no opinions on the default params that a page should use. Think about this class like the manager for query params state that will be used by any page. It should handle serialization, url syncing, mount loading, and anything else that is standard scaffolding
| {/snippet} | ||
|
|
||
| {#snippet media_list({ controller })} | ||
| <MediaList {controller} /> |
There was a problem hiding this comment.
Instead of abstracting at the MediaList level, why not do it at the media tile level? We can introduce a new media tile component for series specific rendering (e.g. thumbnail + series index)
|
|
||
| <MediaBrowserLayout {controller}> | ||
| {#snippet header({ controller })} | ||
| <Header {controller} bind:height={dimensions.heights.header} /> |
There was a problem hiding this comment.
Since the SearchParams are the only things that differ, let's try making that the snippet
Address feedback from PR #44 review comments: 1. Move series_index to specific rune classes - Remove series_index from base MediaViewRune - Add series_index to MediaFileRune (where it's actually used) - Add series_index to MediaSeriesRune (for nested series support) - Prevents pollution of base class with subclass-specific metadata 2. Make BaseQueryParamsManager neutral and opinion-free - Remove BaseSearchParams interface with opinionated fields - Change generic constraint from BaseSearchParams to Record<string, any> - Move field-specific parsing logic (search_string, stars, filepath) to subclasses - Move field-specific serialization logic to subclasses - Make merge() generic instead of assuming search_string exists - Remove extend() method from base (now in subclasses only) - Base class now only handles URL state synchronization 3. Abstract at media tile level instead of MediaList level - Create reusable MediaTile component with metadata snippet slot - Browse SearchResults uses metadata slot for grouped/series links - Series SearchResults uses metadata slot for series_index display - Eliminates code duplication in tile rendering logic - Makes differences between pages explicit via snippets Benefits: - Better separation of concerns (base vs specialized logic) - More maintainable and extensible architecture - Clearer component boundaries and responsibilities - Easier to add new page types in the future
Address feedback from PR #44 review comments: 1. Move series_index to specific rune classes - Remove series_index from base MediaViewRune - Add series_index to MediaFileRune (where it's actually used) - Add series_index to MediaSeriesRune (for nested series support) - Prevents pollution of base class with subclass-specific metadata 2. Make BaseQueryParamsManager neutral and opinion-free - Remove BaseSearchParams interface with opinionated fields - Change generic constraint from BaseSearchParams to Record<string, any> - Move field-specific parsing logic (search_string, stars, filepath) to subclasses - Move field-specific serialization logic to subclasses - Make merge() generic instead of assuming search_string exists - Remove extend() method from base (now in subclasses only) - Base class now only handles URL state synchronization 3. Abstract at media tile level instead of MediaList level - Create reusable MediaTile component with metadata snippet slot - Browse SearchResults uses metadata slot for grouped/series links - Series SearchResults uses metadata slot for series_index display - Eliminates code duplication in tile rendering logic - Makes differences between pages explicit via snippets Benefits: - Better separation of concerns (base vs specialized logic) - More maintainable and extensible architecture - Clearer component boundaries and responsibilities - Easier to add new page types in the future
87eb21f to
cd741fe
Compare
Address feedback from PR #44 review comments: 1. Move series_index to specific rune classes - Remove series_index from base MediaViewRune - Add series_index to MediaFileRune (where it's actually used) - Add series_index to MediaSeriesRune (for nested series support) - Prevents pollution of base class with subclass-specific metadata 2. Make BaseQueryParamsManager neutral and opinion-free - Remove BaseSearchParams interface with opinionated fields - Change generic constraint from BaseSearchParams to Record<string, any> - Move field-specific parsing logic (search_string, stars, filepath) to subclasses - Move field-specific serialization logic to subclasses - Make merge() generic instead of assuming search_string exists - Remove extend() method from base (now in subclasses only) - Base class now only handles URL state synchronization 3. Abstract at media tile level instead of MediaList level - Create reusable MediaTile component with metadata snippet slot - Browse SearchResults uses metadata slot for grouped/series links - Series SearchResults uses metadata slot for series_index display - Eliminates code duplication in tile rendering logic - Makes differences between pages explicit via snippets Benefits: - Better separation of concerns (base vs specialized logic) - More maintainable and extensible architecture - Clearer component boundaries and responsibilities - Easier to add new page types in the future
cd741fe to
927711a
Compare
Address feedback from PR #44 review comments: 1. Move series_index to specific rune classes - Remove series_index from base MediaViewRune - Add series_index to MediaFileRune (where it's actually used) - Add series_index to MediaSeriesRune (for nested series support) - Prevents pollution of base class with subclass-specific metadata 2. Make BaseQueryParamsManager neutral and opinion-free - Remove BaseSearchParams interface with opinionated fields - Change generic constraint from BaseSearchParams to Record<string, any> - Move field-specific parsing logic (search_string, stars, filepath) to subclasses - Move field-specific serialization logic to subclasses - Make merge() generic instead of assuming search_string exists - Remove extend() method from base (now in subclasses only) - Base class now only handles URL state synchronization 3. Abstract at media tile level instead of MediaList level - Create reusable MediaTile component with metadata snippet slot - Browse SearchResults uses metadata slot for grouped/series links - Series SearchResults uses metadata slot for series_index display - Eliminates code duplication in tile rendering logic - Makes differences between pages explicit via snippets Benefits: - Better separation of concerns (base vs specialized logic) - More maintainable and extensible architecture - Clearer component boundaries and responsibilities - Easier to add new page types in the future
4e31d41 to
2114ef9
Compare
dadf78e to
1aa96f9
Compare
Implement a new page for viewing media series items with similar UI to the browse page but specialized for series navigation. Features: - New route at /series/[series_id] with full SvelteKit page structure - SeriesController and SeriesQueryParamsManager for series-specific state - Series-specific search filters and sort options (including series_index) - Display series_index number under each media tile in series view - Link from browse page media tiles to series detail page - Reuse browse components where possible (MediaDetails, MediaView, Footer) - Default sort by series_index in ascending order Changes: - Extend MediaListRune to support series.search API - Add series_index property to MediaViewRune - Create series-specific components in routes/series/[series_id]/ - Update browse SearchResults to link series items to detail page The implementation follows existing patterns and shares logic through SvelteKit layouts, shared components, and rune-based state management.
Refactor browse and series pages to share common logic through inheritance and component composition, following SvelteKit patterns. Changes: - Create BaseQueryParamsManager abstract class with common URL handling - Refactor BrowseQueryParamsManager to extend base class - Refactor SeriesQueryParamsManager to extend base class - Create MediaBrowserLayout component to share UI structure - Update browse page to use MediaBrowserLayout with snippets - Update series page to use MediaBrowserLayout with snippets Benefits: - Eliminates code duplication between browse and series queryparams - Shared layout ensures consistent UI structure - Easier to maintain and extend in the future - Follows DRY principles and Svelte 5 snippet patterns The base class handles: - URL parsing and serialization - State management (current/draft params) - Browser history integration - Common merge/extend operations Each subclass implements: - execute_search (specific API calls) - contextual_query (specific query structure) - Custom URL parsing/serialization hooks
Address feedback from PR #44 review comments: 1. Move series_index to specific rune classes - Remove series_index from base MediaViewRune - Add series_index to MediaFileRune (where it's actually used) - Add series_index to MediaSeriesRune (for nested series support) - Prevents pollution of base class with subclass-specific metadata 2. Make BaseQueryParamsManager neutral and opinion-free - Remove BaseSearchParams interface with opinionated fields - Change generic constraint from BaseSearchParams to Record<string, any> - Move field-specific parsing logic (search_string, stars, filepath) to subclasses - Move field-specific serialization logic to subclasses - Make merge() generic instead of assuming search_string exists - Remove extend() method from base (now in subclasses only) - Base class now only handles URL state synchronization 3. Abstract at media tile level instead of MediaList level - Create reusable MediaTile component with metadata snippet slot - Browse SearchResults uses metadata slot for grouped/series links - Series SearchResults uses metadata slot for series_index display - Eliminates code duplication in tile rendering logic - Makes differences between pages explicit via snippets Benefits: - Better separation of concerns (base vs specialized logic) - More maintainable and extensible architecture - Clearer component boundaries and responsibilities - Easier to add new page types in the future
Fix build error where @deno/vite-plugin attempted to resolve Vite's
virtual modules (those starting with \x00) using child_process.spawn,
which doesn't allow null bytes in arguments.
The error was:
[vite-plugin-sveltekit-compile] [vite-plugin-sveltekit-guard]
The argument 'args[2]' must be a string without null bytes.
Received '\x00vite/preload-helper.js'
Solution:
- Wrap the deno() plugin function with patchedDeno()
- Patch all resolveId hooks in the plugin(s) to return null for
virtual modules (source.startsWith('\x00'))
- This allows Vite to handle virtual modules itself instead of
passing them to the deno resolver
This fix is simple and reasonable - it's a targeted workaround for
a known limitation in @deno/vite-plugin@1.0.5 when working with
Vite 7's virtual module system.
Updated deno.lock after testing @deno/vite-plugin upgrade from 1.0.5 to 1.0.6. Discovered esbuild import resolution issues that require further investigation.
This reverts commit 9fbdb8c.
Move shared components to lib/components/browse_media/: - MediaBrowserLayout.svelte - MediaDetails.svelte - MediaView.svelte - Footer.svelte - MediaTile.svelte Move shared runes to lib/runes/: - dimensions.svelte.ts - media_selections.svelte.ts This prevents lib components from importing from routes, maintaining proper dependency hierarchy where routes are leaves that import from lib. Define MediaBrowserController interface in MediaBrowserLayout without importing concrete controller types from routes.
Implement a new page for viewing media series items with similar UI to the
browse page but specialized for series navigation.
Features:
Changes:
The implementation follows existing patterns and shares logic through
SvelteKit layouts, shared components, and rune-based state management.