Documentation
¶
Index ¶
- Constants
- Variables
- func AddToPlaylistCmd(svc *playlist.Service, playlistID string, itemIDs []string) tea.Cmd
- func AddToQueueCmd(svc *playlist.Service, item *domain.MediaItem) tea.Cmd
- func ClearLibraryStatusCmd(libID string, delay time.Duration) tea.Cmd
- func ClearStatusCmd(delay time.Duration) tea.Cmd
- func CreatePlaylistCmd(svc *playlist.Service, title string, itemIDs []string) tea.Cmd
- func DeletePlaylistCmd(svc *playlist.Service, playlistID string) tea.Cmd
- func ListenForPlaybackStatusCmd(statusCh <-chan string) tea.Cmd
- func LoadContinueWatchingCmd(svc *library.Service) tea.Cmd
- func LoadEpisodesCmd(svc *library.Service, libID, showID, seasonID string) tea.Cmd
- func LoadLibrariesCmd(svc *library.Service) tea.Cmd
- func LoadMixedLibraryCmd(svc *library.Service, libID string) tea.Cmd
- func LoadMoviesCmd(svc *library.Service, libID string) tea.Cmd
- func LoadPlaylistItemsCmd(svc *playlist.Service, playlistID string) tea.Cmd
- func LoadPlaylistModalDataCmd(svc *playlist.Service, item *domain.MediaItem) tea.Cmd
- func LoadPlaylistsCmd(svc *playlist.Service) tea.Cmd
- func LoadSeasonForPlaybackCmd(svc *library.Service, item *domain.MediaItem, resume bool) tea.Cmd
- func LoadSeasonsCmd(svc *library.Service, libID, showID string) tea.Cmd
- func LoadShowsCmd(svc *library.Service, libID string) tea.Cmd
- func LogoutCmd() tea.Cmd
- func MarkUnwatchedCmd(svc *player.Service, libID, itemID, title string) tea.Cmd
- func MarkWatchedCmd(svc *player.Service, libID, itemID, title string) tea.Cmd
- func PlayItemCmd(svc *player.Service, item domain.MediaItem, resume bool, autoplay bool, ...) tea.Cmd
- func RemoteSearchCmd(svc *search.Service, query string) tea.Cmd
- func RemoveFromPlaylistCmd(svc *playlist.Service, playlistID, itemID string) tea.Cmd
- func RemoveFromQueueCmd(svc *playlist.Service, itemID string) tea.Cmd
- func RenderSpinner(frame int) string
- func SyncAllLibrariesCmd(svc *library.Service, libraries []domain.Library) tea.Cmd
- func SyncLibraryCmd(svc *library.Service, lib domain.Library) tea.Cmd
- func SyncPlaylistsCmd(svc *playlist.Service, playlistsID string) tea.Cmd
- func TickCmd(delay time.Duration) tea.Cmd
- func WaitForPlaybackCmd(resultCh <-chan player.ScrobbleResult) tea.Cmd
- type ApplicationState
- type ClearLibraryStatusMsg
- type ClearStatusMsg
- type ColumnStack
- func (cs *ColumnStack) CanGoBack() bool
- func (cs *ColumnStack) Depth() int
- func (cs *ColumnStack) FindColumn(contentID string) *components.ListColumn
- func (cs *ColumnStack) Get(idx int) *components.ListColumn
- func (cs *ColumnStack) Len() int
- func (cs *ColumnStack) Parent() *components.ListColumn
- func (cs *ColumnStack) Pop() (*components.ListColumn, int)
- func (cs *ColumnStack) Push(col *components.ListColumn, saveCursor int)
- func (cs *ColumnStack) Reset(col *components.ListColumn)
- func (cs *ColumnStack) Top() *components.ListColumn
- func (cs *ColumnStack) UpdateSpinnerFrame(frame int)
- func (cs *ColumnStack) UpdateTop(col *components.ListColumn)
- type ContinueWatchingLoadedMsg
- type EpisodesLoadedMsg
- type ErrMsg
- type KeyMap
- type LibrariesLoadedMsg
- type LibrarySyncProgressMsg
- type LogoutCompleteMsg
- type MarkUnwatchedMsg
- type MarkWatchedMsg
- type MixedLibraryLoadedMsg
- type Model
- type MoviesLoadedMsg
- type NavAwaitKind
- type NavPlan
- type NavTarget
- type NavigationContext
- type PlaybackFinishedMsg
- type PlaybackStartedMsg
- type PlaybackStatusMsg
- type PlaylistCreatedMsg
- type PlaylistDeletedMsg
- type PlaylistItemsLoadedMsg
- type PlaylistModalDataMsg
- type PlaylistUpdatedMsg
- type PlaylistsLoadedMsg
- type QueueUpdatedMsg
- type RefreshCurrentMsg
- type RemoteSearchLoadedMsg
- type SeasonForPlaybackLoadedMsg
- type SeasonsLoadedMsg
- type ShowsLoadedMsg
- type StatusMsg
- type TickMsg
Constants ¶
const ( // 3-Column Smart Ratios (Inspector visible) ParentColumnPercent3 = 25 // Parent context ActiveColumnPercent3 = 35 // Active/focused InspectorColumnPercent = 30 // Inspector (summary) // 3-Column Focus Mode (Inspector hidden) - show more navigation context GrandparentColumnPercent = 25 // Grandparent context ParentColumnPercent2 = 30 // Parent context ActiveColumnPercent2 = 45 // Active/focused // Root level (single column + inspector) RootColumnPercent = 40 RootInspectorPercent = 60 MinColumnWidth = 15 // Vertical layout: single footer line ChromeHeight = 1 )
Layout proportions for Miller Columns
Variables ¶
var Keys = DefaultKeyMap()
Keys is the global key bindings instance
Functions ¶
func AddToPlaylistCmd ¶
AddToPlaylistCmd adds items to a playlist
func ClearLibraryStatusCmd ¶
ClearLibraryStatusCmd returns a command that clears library status after delay
func ClearStatusCmd ¶
ClearStatusCmd returns a command that clears status after a delay
func CreatePlaylistCmd ¶
CreatePlaylistCmd creates a new playlist
func DeletePlaylistCmd ¶
DeletePlaylistCmd deletes a playlist
func ListenForPlaybackStatusCmd ¶ added in v0.0.2
ListenForPlaybackStatusCmd waits for status updates during playback
func LoadContinueWatchingCmd ¶ added in v1.1.0
LoadContinueWatchingCmd loads items currently in progress
func LoadEpisodesCmd ¶
LoadEpisodesCmd loads episodes for a season
func LoadLibrariesCmd ¶
LoadLibrariesCmd loads all available libraries
func LoadMixedLibraryCmd ¶
LoadMixedLibraryCmd loads content (movies AND shows) from a mixed library
func LoadMoviesCmd ¶
LoadMoviesCmd loads movies from a library
func LoadPlaylistItemsCmd ¶
LoadPlaylistItemsCmd loads items from a playlist
func LoadPlaylistModalDataCmd ¶
LoadPlaylistModalDataCmd loads data for the playlist management modal
func LoadPlaylistsCmd ¶
LoadPlaylistsCmd loads all playlists
func LoadSeasonForPlaybackCmd ¶ added in v1.1.0
LoadSeasonForPlaybackCmd loads all episodes for an episode's season to build a full playlist
func LoadSeasonsCmd ¶
LoadSeasonsCmd loads seasons for a show
func LoadShowsCmd ¶
LoadShowsCmd loads TV shows from a library
func MarkUnwatchedCmd ¶
MarkUnwatchedCmd marks an item as unwatched
func MarkWatchedCmd ¶
MarkWatchedCmd marks an item as watched
func PlayItemCmd ¶
func PlayItemCmd(svc *player.Service, item domain.MediaItem, resume bool, autoplay bool, playlist ...domain.MediaItem) tea.Cmd
PlayItemCmd starts playback of an item, optionally with a playlist
func RemoveFromPlaylistCmd ¶
RemoveFromPlaylistCmd removes an item from a playlist
func SyncAllLibrariesCmd ¶
SyncAllLibrariesCmd syncs all libraries in parallel
func SyncLibraryCmd ¶
SyncLibraryCmd performs smart sync with streaming progress updates
func SyncPlaylistsCmd ¶
SyncPlaylistsCmd syncs playlists and their items (two levels deep, like library sync).
func WaitForPlaybackCmd ¶ added in v0.0.2
func WaitForPlaybackCmd(resultCh <-chan player.ScrobbleResult) tea.Cmd
WaitForPlaybackCmd waits for the playback to finish and returns a message
Types ¶
type ApplicationState ¶
type ApplicationState int
ApplicationState represents the current state of the application
const ( StateBrowsing ApplicationState = iota StateHelp StateConfirmLogout StateConfirmResume StateInspecting )
type ClearLibraryStatusMsg ¶
type ClearLibraryStatusMsg struct {
LibraryID string
}
ClearLibraryStatusMsg signals that the success indicator should be removed
type ColumnStack ¶
type ColumnStack struct {
// contains filtered or unexported fields
}
ColumnStack manages the stack of navigable columns in Miller Columns layout. The stack contains list columns only - the Inspector is a separate view projection.
Visual representation:
Root: [Empty | Libraries | Inspector] Library: [Libraries | Movies | Inspector] Show: [TV Shows | Breaking Bad | Inspector] Season: [Breaking Bad | Season 1 | Inspector]
The "middle" column (top of stack) is always focused. The "left" column shows parent context. The "right" column (Inspector) shows details for the selection in middle column.
func NewColumnStack ¶
func NewColumnStack() *ColumnStack
NewColumnStack creates a new empty column stack
func (*ColumnStack) CanGoBack ¶
func (cs *ColumnStack) CanGoBack() bool
CanGoBack returns true if we can navigate back (not at root)
func (*ColumnStack) Depth ¶
func (cs *ColumnStack) Depth() int
Depth returns the navigation depth (0 = root, 1 = first drill, etc.)
func (*ColumnStack) FindColumn ¶ added in v1.0.0
func (cs *ColumnStack) FindColumn(contentID string) *components.ListColumn
FindColumn returns the column with the matching content ID, or nil if not found
func (*ColumnStack) Get ¶
func (cs *ColumnStack) Get(idx int) *components.ListColumn
Get returns the column at the given index (0 = bottom/oldest)
func (*ColumnStack) Len ¶
func (cs *ColumnStack) Len() int
Len returns the number of columns in the stack
func (*ColumnStack) Parent ¶
func (cs *ColumnStack) Parent() *components.ListColumn
Parent returns the parent column (second from top), or nil if at root
func (*ColumnStack) Pop ¶
func (cs *ColumnStack) Pop() (*components.ListColumn, int)
Pop removes and returns the top column, along with the saved cursor position. Returns nil if stack would become empty (must have at least 1 column).
func (*ColumnStack) Push ¶
func (cs *ColumnStack) Push(col *components.ListColumn, saveCursor int)
Push adds a new column to the stack, saving the current cursor position
func (*ColumnStack) Reset ¶
func (cs *ColumnStack) Reset(col *components.ListColumn)
Reset resets the stack to a single column (used when switching libraries)
func (*ColumnStack) Top ¶
func (cs *ColumnStack) Top() *components.ListColumn
Top returns the topmost (current/focused) column
func (*ColumnStack) UpdateSpinnerFrame ¶
func (cs *ColumnStack) UpdateSpinnerFrame(frame int)
UpdateSpinnerFrame updates the spinner frame for all columns
func (*ColumnStack) UpdateTop ¶
func (cs *ColumnStack) UpdateTop(col *components.ListColumn)
UpdateTop replaces the top column with the given column. This preserves encapsulation by avoiding direct access to the columns slice.
type ContinueWatchingLoadedMsg ¶ added in v1.1.0
ContinueWatchingLoadedMsg signals that continue watching items have been loaded
type EpisodesLoadedMsg ¶
EpisodesLoadedMsg signals that episodes have been loaded
type KeyMap ¶
type KeyMap struct {
// Navigation
Up key.Binding
Down key.Binding
Right key.Binding
Enter key.Binding
Back key.Binding
HalfUp key.Binding
HalfDown key.Binding
PageUp key.Binding
PageDown key.Binding
Home key.Binding
End key.Binding
// Actions
Quit key.Binding
Help key.Binding
Escape key.Binding
Filter key.Binding
GlobalSearch key.Binding
Sort key.Binding
Refresh key.Binding
RefreshAll key.Binding
MarkWatched key.Binding
MarkUnwatched key.Binding
Play key.Binding
ToggleInspector key.Binding
Logout key.Binding
PlaylistModal key.Binding
Delete key.Binding
NewPlaylist key.Binding
Queue key.Binding
NextEpisode key.Binding
// Confirmations
Confirm key.Binding
Deny key.Binding
}
KeyMap defines all key bindings for the application
type LibrariesLoadedMsg ¶
LibrariesLoadedMsg signals that libraries have been loaded
type LibrarySyncProgressMsg ¶
type LibrarySyncProgressMsg struct {
LibraryID string
LibraryType string
Loaded int
Total int
Done bool
FromCache bool
Error error
NextCmd tea.Cmd // Continuation command for streaming
}
LibrarySyncProgressMsg sent for each chunk during streaming sync
type LogoutCompleteMsg ¶
type LogoutCompleteMsg struct {
Error error
}
LogoutCompleteMsg signals that logout has been completed
type MarkUnwatchedMsg ¶
MarkUnwatchedMsg signals a request to mark an item as unwatched
type MarkWatchedMsg ¶
MarkWatchedMsg signals a request to mark an item as watched
type MixedLibraryLoadedMsg ¶
MixedLibraryLoadedMsg signals that mixed library content has been loaded
type Model ¶
type Model struct {
// Application state
State ApplicationState
Ready bool
// Cache reads (View-safe)
Store domain.Store
// Network coordination (concrete types, not interfaces)
LibraryService *library.Service
PlaylistService *playlist.Service
// Other services
SearchSvc *search.Service
PlaybackSvc *player.Service
// UI Components - Miller Columns
ColumnStack *ColumnStack // Stack of navigable list columns
Inspector components.Inspector // View projection (always shows details for middle column selection)
GlobalSearch components.GlobalSearch // Search modal
SortModal components.SortModal // Sort field selector
PlaylistModal components.PlaylistModal // Playlist management modal
InputModal components.InputModal // Simple text input modal
// Data
Libraries []domain.Library
// Dimensions
Width int
Height int
// UI state
StatusMsg string
StatusIsErr bool
Loading bool
SpinnerFrame int
ShowInspector bool // Toggle inspector visibility (default true)
// Sync state
LibraryStates map[string]components.LibrarySyncState // Tracks progress per library
SyncingCount int // Libraries still syncing
MultiLibSync bool // True when syncing multiple libraries (R / startup)
// UI preferences from config
UIConfig config.UIConfig
AppConfig *config.Config
Version string
PendingSelectionID string // ID of item to select after load completes
// contains filtered or unexported fields
}
Model is the main Bubble Tea model for the application
func NewModel ¶
func NewModel( store domain.Store, librarySvc *library.Service, playlistSvc *playlist.Service, searchSvc *search.Service, playbackSvc *player.Service, appConfig *config.Config, uiConfig config.UIConfig, version string, ) Model
NewModel creates a new application model
type MoviesLoadedMsg ¶
MoviesLoadedMsg signals that movies have been loaded
type NavAwaitKind ¶
type NavAwaitKind int
NavAwaitKind specifies what async load the plan is waiting for
const ( AwaitNone NavAwaitKind = iota AwaitMovies // AwaitID = LibraryID AwaitShows // AwaitID = LibraryID AwaitMixed // AwaitID = LibraryID (mixed content library) AwaitSeasons // AwaitID = ShowID AwaitEpisodes // AwaitID = SeasonID )
type NavPlan ¶
type NavPlan struct {
}
NavPlan represents a multi-step navigation flow
func (*NavPlan) IsComplete ¶
type NavigationContext ¶
type NavigationContext struct {
}
NavigationContext contains information needed to navigate to an item This is purely a TUI concern - the service layer provides FilterItem with LibraryID, and the TUI decides how to navigate based on that.
type PlaybackFinishedMsg ¶ added in v0.0.2
type PlaybackFinishedMsg struct {
Item domain.MediaItem
Title string
AutoMarked bool // true if auto-scrobbled as watched
Err error
}
PlaybackFinishedMsg signals that playback has ended
type PlaybackStartedMsg ¶
type PlaybackStartedMsg struct {
Item domain.MediaItem
Handle player.PlaybackHandle
}
PlaybackStartedMsg signals that playback has started (player launched)
type PlaybackStatusMsg ¶ added in v0.0.2
PlaybackStatusMsg signals a real-time status update during playback
type PlaylistCreatedMsg ¶
PlaylistCreatedMsg signals that a new playlist was created
type PlaylistDeletedMsg ¶
PlaylistDeletedMsg signals that a playlist was deleted
type PlaylistItemsLoadedMsg ¶
PlaylistItemsLoadedMsg signals that playlist items have been loaded
type PlaylistModalDataMsg ¶
type PlaylistModalDataMsg struct {
Playlists []*domain.Playlist
Membership map[string]bool
Item *domain.MediaItem
}
PlaylistModalDataMsg contains data for the playlist modal
type PlaylistUpdatedMsg ¶
PlaylistUpdatedMsg signals that a playlist was updated (item added/removed)
type PlaylistsLoadedMsg ¶
PlaylistsLoadedMsg signals that playlists have been loaded
type QueueUpdatedMsg ¶
QueueUpdatedMsg signals local queue changes.
type RefreshCurrentMsg ¶ added in v1.1.2
type RefreshCurrentMsg struct {
LibraryID string
}
RefreshCurrentMsg triggers a refresh of the current view
type RemoteSearchLoadedMsg ¶
type RemoteSearchLoadedMsg struct {
Query string
Results []search.FilterResult
Error error
}
RemoteSearchLoadedMsg carries server-side fallback search results.
type SeasonForPlaybackLoadedMsg ¶ added in v1.1.0
type SeasonForPlaybackLoadedMsg struct {
Item *domain.MediaItem
Episodes []*domain.MediaItem
Resume bool
}
SeasonForPlaybackLoadedMsg signals that a full season has been loaded for playback
type SeasonsLoadedMsg ¶
SeasonsLoadedMsg signals that seasons have been loaded
type ShowsLoadedMsg ¶
ShowsLoadedMsg signals that shows have been loaded