Documentation
¶
Index ¶
- Constants
- Variables
- func CurrentAccent() lipgloss.Color
- func DominantColor(img image.Image) lipgloss.Color
- func FetchImage(ctx context.Context, url string) (image.Image, error)
- func FormatAlbumInfo(artist, year string, tracks []source.Track) string
- func FormatPartialTrackListInfo(loaded, total int) string
- func FormatTrackListInfo(tracks []source.Track) string
- func PaneBorder(active bool) lipgloss.Style
- func PlaceholderArt(w, h int) string
- func RenderNowPlaying(track *source.Track, artBlock string, albumImg image.Image, vinylMode bool, ...) string
- func ViewHelp(width, height int) string
- type ActionItem
- type ActionType
- type ActionsPopup
- type AlbumArt
- type ArtworkProvider
- type CmdType
- type Command
- type DevicePicker
- type GAction
- type GTracker
- type KeyMap
- type Mode
- type Model
- type NavState
- type Pane
- type Search
- type Sidebar
- func (s *Sidebar) ClearFilter()
- func (s *Sidebar) Resize(width, height int)
- func (s *Sidebar) Section() SidebarSection
- func (s *Sidebar) SelectedPlaylist() *source.Playlist
- func (s *Sidebar) SetCursorFromClick(y int)
- func (s *Sidebar) SetFilter(query string)
- func (s *Sidebar) SetPlaylistIcons(icons map[string]string)
- func (s *Sidebar) SetPlaylists(playlists []source.Playlist)
- func (s *Sidebar) SetQueueTracks(tracks []source.Track)
- func (s *Sidebar) SetSection(sec SidebarSection)
- func (s Sidebar) Update(msg tea.Msg) (Sidebar, tea.Cmd)
- func (s Sidebar) View(active bool) string
- type SidebarSection
- type StatusBar
- func (s *StatusBar) Resize(width int)
- func (s StatusBar) ViewModeLine(mode Mode, cmdInput string, filterInput string, filterActive string, ...) string
- func (s StatusBar) ViewNowPlaying(track *source.Track, shuffleOn bool, repeatMode source.RepeatMode, liked bool) string
- func (s StatusBar) ViewNowPlayingWithArt(track *source.Track, shuffleOn bool, repeatMode source.RepeatMode, liked bool, ...) string
- type Toast
- type ToastType
- type TrackList
- func (tl *TrackList) AppendTracks(tracks []source.Track)
- func (tl *TrackList) ClearFilter()
- func (tl *TrackList) ContextURI() string
- func (tl *TrackList) FilterText() string
- func (tl *TrackList) GetState(pane Pane) NavState
- func (tl *TrackList) JumpToTrack(trackID string) bool
- func (tl *TrackList) Resize(width, height int)
- func (tl *TrackList) RestoreState(s NavState)
- func (tl *TrackList) SelectedTrack() *source.Track
- func (tl *TrackList) SetArt(artBlock string)
- func (tl *TrackList) SetCursorFromClick(y int)
- func (tl *TrackList) SetFilter(query string)
- func (tl *TrackList) SetHeaderInfo(info string)
- func (tl *TrackList) SetLoading(title string)
- func (tl *TrackList) SetNowPlaying(trackID string)
- func (tl *TrackList) SetSubtitle(s string)
- func (tl *TrackList) SetTracks(tracks []source.Track, title, contextURI string)
- func (tl *TrackList) TickSpinner()
- func (tl TrackList) Update(msg tea.Msg) (TrackList, tea.Cmd)
- func (tl TrackList) View(active bool) string
Constants ¶
const ( ArtWidth = 24 // columns for now-playing art ArtHeight = 12 // terminal rows (= 24 pixel rows via half-blocks) MinTermRows = 28 // below this, hide art HeaderArtW = 8 // columns for tracklist header art HeaderArtH = 4 // terminal rows for tracklist header art )
Variables ¶
var ( ColorAccent = lipgloss.Color("#1DB954") ColorBg = lipgloss.Color("#191414") ColorSurface = lipgloss.Color("#282828") ColorText = lipgloss.Color("#FFFFFF") ColorTextSec = lipgloss.Color("#B3B3B3") ColorTextDim = lipgloss.Color("#535353") ColorBorder = lipgloss.Color("#333333") ColorError = lipgloss.Color("#E22134") )
Spotify-inspired color palette
var ( StyleSectionHeader = lipgloss.NewStyle(). Foreground(ColorTextDim). Bold(true). PaddingLeft(1) StyleActiveItem = lipgloss.NewStyle(). Background(ColorSurface). Foreground(ColorAccent). Bold(true) StyleDimText = lipgloss.NewStyle(). Foreground(ColorTextDim) StyleModeNormal = lipgloss.NewStyle(). Foreground(ColorBg). Background(ColorAccent). Bold(true). Padding(0, 1) StyleModeCommand = lipgloss.NewStyle(). Foreground(ColorBg). Background(ColorText). Bold(true). Padding(0, 1) StyleModeSearch = lipgloss.NewStyle(). Foreground(ColorBg). Background(lipgloss.Color("#E2B714")). Bold(true). Padding(0, 1) StyleModeFilter = lipgloss.NewStyle(). Foreground(ColorBg). Background(lipgloss.Color("#BB9AF7")). Bold(true). Padding(0, 1) StyleStatusBar = lipgloss.NewStyle(). Background(ColorSurface). Foreground(ColorText) StyleModeLine = lipgloss.NewStyle(). Background(ColorBg). Foreground(ColorTextSec) )
Reusable styles
Functions ¶
func CurrentAccent ¶
CurrentAccent returns the accent color used for active elements.
func DominantColor ¶
DominantColor samples pixels from an image and returns the most vibrant color as a lipgloss hex Color. It skips near-black and near-white pixels to find a representative accent color. Returns "" if no suitable color is found.
func FetchImage ¶
FetchImage downloads and decodes an image from a URL. Uses a dedicated client with timeout and a body size limit to prevent hangs and OOM from slow or malicious servers.
func FormatAlbumInfo ¶
FormatAlbumInfo returns "Artist · Year · N tracks".
func FormatPartialTrackListInfo ¶
FormatPartialTrackListInfo returns "N of M tracks" for partially loaded playlists.
func FormatTrackListInfo ¶
FormatTrackListInfo returns a summary string like "30 tracks · 1h 42m".
func PaneBorder ¶
PaneBorder returns a border style for a pane.
func PlaceholderArt ¶
PlaceholderArt returns a simple colored block when no art is available.
Types ¶
type ActionItem ¶
type ActionItem struct {
Type ActionType
Label string
Icon string
}
ActionItem is a single entry in the actions popup.
type ActionType ¶
type ActionType int
ActionType identifies a context action.
const ( ActionPlay ActionType = iota ActionQueue ActionLike ActionGoArtist ActionGoAlbum ActionOpenSpotify ActionCopyURI ActionPlayPlaylist ActionOpenPlaylistSpotify ActionLoadTracks )
type ActionsPopup ¶
type ActionsPopup struct {
// contains filtered or unexported fields
}
ActionsPopup is a floating overlay listing context actions for the selected item.
func NewPlaylistActions ¶
func NewPlaylistActions(playlistName, uri string, width, height int) ActionsPopup
NewPlaylistActions returns an ActionsPopup configured for a playlist.
func NewTrackActions ¶
func NewTrackActions(trackName, artistName, uri, artistID, albumID string, liked bool, width, height int) ActionsPopup
NewTrackActions returns an ActionsPopup configured for a track.
func (ActionsPopup) AlbumID ¶
func (a ActionsPopup) AlbumID() string
AlbumID returns the album ID stored in the popup.
func (ActionsPopup) ArtistID ¶
func (a ActionsPopup) ArtistID() string
ArtistID returns the artist ID stored in the popup.
func (*ActionsPopup) MoveDown ¶
func (a *ActionsPopup) MoveDown()
MoveDown moves the cursor down in the actions list.
func (*ActionsPopup) MoveUp ¶
func (a *ActionsPopup) MoveUp()
MoveUp moves the cursor up in the actions list.
func (ActionsPopup) Selected ¶
func (a ActionsPopup) Selected() ActionItem
Selected returns the currently highlighted action.
func (ActionsPopup) URI ¶
func (a ActionsPopup) URI() string
URI returns the URI stored in the popup (for clipboard copy).
func (ActionsPopup) View ¶
func (a ActionsPopup) View() string
View renders the actions popup as a centered floating overlay.
type AlbumArt ¶
type AlbumArt struct {
// contains filtered or unexported fields
}
AlbumArt renders album artwork using Unicode half-block characters.
func NewAlbumArt ¶
func NewAlbumArt() AlbumArt
func (*AlbumArt) CurrentURL ¶
type ArtworkProvider ¶
ArtworkProvider is an optional interface that source implementations can satisfy to provide embedded artwork instead of HTTP fetching. Used by demo mode to avoid network calls.
type Command ¶
func ParseCommand ¶
type DevicePicker ¶
type DevicePicker struct {
// contains filtered or unexported fields
}
DevicePicker is a floating overlay listing available Spotify Connect devices.
func NewDevicePicker ¶
func NewDevicePicker(devices []source.Device, width, height int) DevicePicker
NewDevicePicker creates a device picker popup from a list of devices.
func (DevicePicker) Selected ¶
func (d DevicePicker) Selected() *source.Device
Selected returns the currently highlighted device, or nil if empty.
func (DevicePicker) View ¶
func (d DevicePicker) View() string
View renders the device picker as a centered floating overlay.
type GTracker ¶
type GTracker struct {
// contains filtered or unexported fields
}
GTracker tracks g-prefix two-key motions (gg, gl, gq, gc, gr).
func (*GTracker) Feed ¶
Feed processes a key press. Returns the resolved GAction. When "g" is pressed the first time it returns GActionNone (pending). A second key resolves the action. Any unrecognised second key resets and returns GActionNone.
type KeyMap ¶
type KeyMap struct {
// Navigation
Up key.Binding
Down key.Binding
Top key.Binding
Bottom key.Binding
HalfUp key.Binding
HalfDown key.Binding
// Pane
FocusLeft key.Binding
FocusRight key.Binding
CyclePane key.Binding
// Playback
Enter key.Binding
PlayPause key.Binding
Next key.Binding
Prev key.Binding
SeekFwd key.Binding
SeekBack key.Binding
// Actions
AddQueue key.Binding
Like key.Binding
Actions key.Binding
Devices key.Binding
// Navigation history
Back key.Binding
// Modes
Filter key.Binding
Search key.Binding
Command key.Binding
Help key.Binding
NowPlaying key.Binding
Quit key.Binding
Escape key.Binding
// Sections
Section1 key.Binding
Section2 key.Binding
}
func DefaultKeyMap ¶
func DefaultKeyMap() KeyMap
type Model ¶
type Model struct {
// contains filtered or unexported fields
}
Model is the root Bubbletea model for waxon.
func NewModel ¶
func NewModel(src source.RichSource) Model
type NavState ¶
type NavState struct {
// contains filtered or unexported fields
}
NavState captures the tracklist state for browser-like back navigation.
type Search ¶
type Search struct {
// contains filtered or unexported fields
}
Search is the floating search overlay model.
func (Search) SelectedAlbum ¶
func (s Search) SelectedAlbum() *source.SearchAlbum
SelectedAlbum returns the selected album if the cursor is on an album row.
func (Search) SelectedArtist ¶
func (s Search) SelectedArtist() *source.SearchArtist
SelectedArtist returns the selected artist if the cursor is on an artist row.
func (Search) SelectedTrack ¶
SelectedTrack returns the selected track if the cursor is on a track row.
type Sidebar ¶
type Sidebar struct {
// contains filtered or unexported fields
}
Sidebar is the left pane model.
func NewSidebar ¶
func (*Sidebar) ClearFilter ¶
func (s *Sidebar) ClearFilter()
ClearFilter restores the full unfiltered playlist list.
func (*Sidebar) Section ¶
func (s *Sidebar) Section() SidebarSection
func (*Sidebar) SelectedPlaylist ¶
func (*Sidebar) SetCursorFromClick ¶
SetCursorFromClick maps a Y coordinate (relative to the pane top) to a list item and selects it.
func (*Sidebar) SetPlaylistIcons ¶
SetPlaylistIcons updates the library playlist items with rendered art icons. Merges into allItems (the library set) rather than the live list, so icons are preserved correctly even if the user switched to the queue view.
func (*Sidebar) SetPlaylists ¶
func (*Sidebar) SetQueueTracks ¶
func (*Sidebar) SetSection ¶
func (s *Sidebar) SetSection(sec SidebarSection)
type SidebarSection ¶
type SidebarSection int
SidebarSection identifies which section of the sidebar.
const ( SectionLibrary SidebarSection = iota SectionQueue )
type StatusBar ¶
type StatusBar struct {
// contains filtered or unexported fields
}
StatusBar renders the bottom two rows: now-playing bar and mode line.
func NewStatusBar ¶
func (StatusBar) ViewModeLine ¶
func (s StatusBar) ViewModeLine(mode Mode, cmdInput string, filterInput string, filterActive string, volume int, deviceName string) string
ViewModeLine renders the mode/command line row.
func (StatusBar) ViewNowPlaying ¶
func (s StatusBar) ViewNowPlaying(track *source.Track, shuffleOn bool, repeatMode source.RepeatMode, liked bool) string
ViewNowPlaying renders the now-playing row.
func (StatusBar) ViewNowPlayingWithArt ¶
func (s StatusBar) ViewNowPlayingWithArt(track *source.Track, shuffleOn bool, repeatMode source.RepeatMode, liked bool, artBlock string, volume int, deviceName string, mode Mode, cmdInput string, filterInput string, filterActive string) string
ViewNowPlayingWithArt renders the now-playing panel with album art on the left.
type Toast ¶
type Toast struct {
// contains filtered or unexported fields
}
Toast is a floating notification rendered in the top-right corner.
func (Toast) Overlay ¶
Overlay composites the toast box onto the top-right corner of the rendered view.
type TrackList ¶
type TrackList struct {
// contains filtered or unexported fields
}
TrackList is the right pane model showing tracks in a table.
func NewTrackList ¶
func (*TrackList) AppendTracks ¶
AppendTracks adds more tracks to the existing list without resetting the cursor position. Used for lazy-loading additional pages.
func (*TrackList) ClearFilter ¶
func (tl *TrackList) ClearFilter()
ClearFilter removes the active filter and restores the full track list.
func (*TrackList) ContextURI ¶
func (*TrackList) FilterText ¶
FilterText returns the current active filter query (empty if none).
func (*TrackList) GetState ¶
GetState snapshots the current tracklist state (including cursor position).
func (*TrackList) JumpToTrack ¶
JumpToTrack moves the cursor to the track with the given ID. Returns true if the track was found, false otherwise.
func (*TrackList) RestoreState ¶
RestoreState restores the tracklist from a previously saved NavState.
func (*TrackList) SelectedTrack ¶
func (*TrackList) SetCursorFromClick ¶
SetCursorFromClick maps a Y coordinate (relative to the pane top) to a table data row and moves the cursor there.
func (*TrackList) SetFilter ¶
SetFilter applies a case-insensitive filter matching track name or artist. An empty query clears the filter.
func (*TrackList) SetHeaderInfo ¶
func (*TrackList) SetLoading ¶
func (*TrackList) SetNowPlaying ¶
func (*TrackList) SetSubtitle ¶
func (*TrackList) TickSpinner ¶
func (tl *TrackList) TickSpinner()