search framework
This commit is contained in:
parent
0e01d77136
commit
1acc255c61
@ -64,6 +64,14 @@ func ArtistAlbums(ctx *gctx.Context, client *spotify.Client, artist spotify.ID,
|
|||||||
return albums, nil
|
return albums, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func Search(ctx *gctx.Context, client *spotify.Client, search string, page int) (*spotify.SearchResult, error) {
|
||||||
|
result, err := client.Search(ctx, search, spotify.SearchTypeAlbum|spotify.SearchTypeArtist|spotify.SearchTypeTrack|spotify.SearchTypePlaylist, spotify.Limit(50), spotify.Offset((page-1)*50))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func AlbumTracks(ctx *gctx.Context, client *spotify.Client, album spotify.ID, page int) (*spotify.SimpleTrackPage, error) {
|
func AlbumTracks(ctx *gctx.Context, client *spotify.Client, album spotify.ID, page int) (*spotify.SimpleTrackPage, error) {
|
||||||
tracks, err := client.GetAlbumTracks(ctx, album, spotify.Limit(50), spotify.Offset((page-1)*50), spotify.Market(spotify.CountryUSA))
|
tracks, err := client.GetAlbumTracks(ctx, album, spotify.Limit(50), spotify.Offset((page-1)*50), spotify.Market(spotify.CountryUSA))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -8,6 +8,7 @@ import (
|
|||||||
|
|
||||||
"github.com/charmbracelet/bubbles/key"
|
"github.com/charmbracelet/bubbles/key"
|
||||||
"github.com/charmbracelet/bubbles/list"
|
"github.com/charmbracelet/bubbles/list"
|
||||||
|
"github.com/charmbracelet/bubbles/textinput"
|
||||||
tea "github.com/charmbracelet/bubbletea"
|
tea "github.com/charmbracelet/bubbletea"
|
||||||
"github.com/charmbracelet/lipgloss"
|
"github.com/charmbracelet/lipgloss"
|
||||||
"github.com/zmb3/spotify/v2"
|
"github.com/zmb3/spotify/v2"
|
||||||
@ -36,12 +37,14 @@ func (i mainItem) FilterValue() string { return i.Title() + i.Desc }
|
|||||||
|
|
||||||
type mainModel struct {
|
type mainModel struct {
|
||||||
list list.Model
|
list list.Model
|
||||||
|
input textinput.Model
|
||||||
ctx *gctx.Context
|
ctx *gctx.Context
|
||||||
client *spotify.Client
|
client *spotify.Client
|
||||||
mode string
|
mode string
|
||||||
playlist spotify.SimplePlaylist
|
playlist spotify.SimplePlaylist
|
||||||
artist spotify.SimpleArtist
|
artist spotify.SimpleArtist
|
||||||
album spotify.SimpleAlbum
|
album spotify.SimpleAlbum
|
||||||
|
search string
|
||||||
fromArtist bool
|
fromArtist bool
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,10 +73,14 @@ func (m *mainModel) Tick() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m mainModel) View() string {
|
func (m mainModel) View() string {
|
||||||
return DocStyle.Render(m.list.View())
|
if m.input.Focused() {
|
||||||
|
return DocStyle.Render(m.list.View() + "\n" + m.input.View())
|
||||||
|
}
|
||||||
|
return DocStyle.Render(m.list.View() + "\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
||||||
|
search := false
|
||||||
m.list.NewStatusMessage(currentlyPlaying)
|
m.list.NewStatusMessage(currentlyPlaying)
|
||||||
select {
|
select {
|
||||||
case update := <-main_updates:
|
case update := <-main_updates:
|
||||||
@ -88,7 +95,28 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
switch msg := msg.(type) {
|
switch msg := msg.(type) {
|
||||||
case tea.KeyMsg:
|
case tea.KeyMsg:
|
||||||
|
if m.input.Focused() {
|
||||||
|
if msg.String() == "enter" {
|
||||||
|
m.list.NewStatusMessage("Setting view to search for " + m.input.Value())
|
||||||
|
items, err := SearchView(m.ctx, m.client, m.input.Value())
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
m.search = m.input.Value()
|
||||||
|
m.list.SetItems(items)
|
||||||
|
m.list.ResetSelected()
|
||||||
|
m.input.SetValue("")
|
||||||
|
m.input.Blur()
|
||||||
|
search = true
|
||||||
|
}
|
||||||
|
m.input, _ = m.input.Update(msg)
|
||||||
|
}
|
||||||
|
if msg.String() == "s" {
|
||||||
|
m.input.Focus()
|
||||||
|
}
|
||||||
if msg.String() == "d" {
|
if msg.String() == "d" {
|
||||||
|
if !m.input.Focused() {
|
||||||
m.mode = "devices"
|
m.mode = "devices"
|
||||||
new_items, err := DeviceView(m.ctx, m.client)
|
new_items, err := DeviceView(m.ctx, m.client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -99,8 +127,22 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
m.list.ResetSelected()
|
m.list.ResetSelected()
|
||||||
m.list.NewStatusMessage("Setting view to devices")
|
m.list.NewStatusMessage("Setting view to devices")
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if msg.String() == "backspace" || msg.String() == "esc" || msg.String() == "q" {
|
if msg.String() == "backspace" || msg.String() == "esc" || msg.String() == "q" {
|
||||||
if m.mode == "album" {
|
if m.input.Focused() {
|
||||||
|
if msg.String() == "esc" {
|
||||||
|
m.input.SetValue("")
|
||||||
|
m.input.Blur()
|
||||||
|
m.list.SetShowPagination(true)
|
||||||
|
m.mode = "main"
|
||||||
|
m.list.NewStatusMessage("Setting view to main")
|
||||||
|
new_items, err := MainView(m.ctx, m.client)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
}
|
||||||
|
m.list.SetItems(new_items)
|
||||||
|
}
|
||||||
|
} else if m.mode == "album" {
|
||||||
if m.fromArtist {
|
if m.fromArtist {
|
||||||
m.mode = "albums"
|
m.mode = "albums"
|
||||||
m.fromArtist = true
|
m.fromArtist = true
|
||||||
@ -163,6 +205,51 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
if msg.String() == "enter" || msg.String() == "spacebar" {
|
if msg.String() == "enter" || msg.String() == "spacebar" {
|
||||||
switch m.mode {
|
switch m.mode {
|
||||||
|
case "search":
|
||||||
|
switch m.list.SelectedItem().(mainItem).SpotifyItem.(type) {
|
||||||
|
case *spotify.FullArtistPage:
|
||||||
|
m.mode = "searchartists"
|
||||||
|
m.list.NewStatusMessage("Setting view to artists")
|
||||||
|
new_items, err := SearchArtistsView(m.ctx, m.client, m.list.SelectedItem().(mainItem).SpotifyItem.(*spotify.FullArtistPage))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
m.list.SetItems(new_items)
|
||||||
|
m.list.ResetSelected()
|
||||||
|
case *spotify.SimpleAlbumPage:
|
||||||
|
m.mode = "searchalbums"
|
||||||
|
m.list.NewStatusMessage("Setting view to albums")
|
||||||
|
new_items, err := SearchAlbumsView(m.ctx, m.client, m.list.SelectedItem().(mainItem).SpotifyItem.(*spotify.SimpleAlbumPage))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
m.list.SetItems(new_items)
|
||||||
|
m.list.ResetSelected()
|
||||||
|
case *spotify.SimplePlaylistPage:
|
||||||
|
m.mode = "searchplaylist"
|
||||||
|
playlists := m.list.SelectedItem().(mainItem).SpotifyItem.(*spotify.SimplePlaylistPage)
|
||||||
|
m.list.NewStatusMessage("Setting view to playlist")
|
||||||
|
new_items, err := SearchPlaylistsView(m.ctx, m.client, playlists)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
m.list.SetItems(new_items)
|
||||||
|
m.list.ResetSelected()
|
||||||
|
case *spotify.FullTrackPage:
|
||||||
|
m.mode = "searchtracks"
|
||||||
|
m.list.NewStatusMessage("Setting view to tracks")
|
||||||
|
new_items, err := SearchTracksView(m.ctx, m.client, m.list.SelectedItem().(mainItem).SpotifyItem.(*spotify.FullTrackPage))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err.Error())
|
||||||
|
return m, tea.Quit
|
||||||
|
}
|
||||||
|
m.list.SetItems(new_items)
|
||||||
|
m.list.ResetSelected()
|
||||||
|
m.list.NewStatusMessage("Setting view to tracks")
|
||||||
|
}
|
||||||
case "main":
|
case "main":
|
||||||
switch m.list.SelectedItem().(mainItem).SpotifyItem.(type) {
|
switch m.list.SelectedItem().(mainItem).SpotifyItem.(type) {
|
||||||
case *spotify.FullArtistCursorPage:
|
case *spotify.FullArtistCursorPage:
|
||||||
@ -296,9 +383,11 @@ func (m mainModel) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|||||||
}
|
}
|
||||||
case tea.WindowSizeMsg:
|
case tea.WindowSizeMsg:
|
||||||
h, v := DocStyle.GetFrameSize()
|
h, v := DocStyle.GetFrameSize()
|
||||||
m.list.SetSize(msg.Width-h, msg.Height-v)
|
m.list.SetSize(msg.Width-h, msg.Height-v-1)
|
||||||
|
}
|
||||||
|
if search {
|
||||||
|
m.mode = "search"
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmd tea.Cmd
|
var cmd tea.Cmd
|
||||||
m.list, cmd = m.list.Update(msg)
|
m.list, cmd = m.list.Update(msg)
|
||||||
return m, cmd
|
return m, cmd
|
||||||
@ -353,5 +442,11 @@ func InitMain(ctx *gctx.Context, client *spotify.Client, mode string) (tea.Model
|
|||||||
key.NewBinding(key.WithKeys("d"), key.WithHelp("d", "select device")),
|
key.NewBinding(key.WithKeys("d"), key.WithHelp("d", "select device")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
input := textinput.New()
|
||||||
|
input.Prompt = "$ "
|
||||||
|
input.Placeholder = "Search..."
|
||||||
|
input.CharLimit = 250
|
||||||
|
input.Width = 50
|
||||||
|
m.input = input
|
||||||
return m, nil
|
return m, nil
|
||||||
}
|
}
|
||||||
|
@ -63,6 +63,49 @@ func ArtistsView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error)
|
|||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SearchArtistsView(ctx *gctx.Context, client *spotify.Client, artists *spotify.FullArtistPage) ([]list.Item, error) {
|
||||||
|
items := []list.Item{}
|
||||||
|
for _, artist := range artists.Artists {
|
||||||
|
items = append(items, mainItem{
|
||||||
|
Name: artist.Name,
|
||||||
|
ID: artist.ID,
|
||||||
|
Desc: fmt.Sprintf("%d followers, genres: %s, popularity: %d", artist.Followers.Count, artist.Genres, artist.Popularity),
|
||||||
|
SpotifyItem: artist.SimpleArtist,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SearchView(ctx *gctx.Context, client *spotify.Client, search string) ([]list.Item, error) {
|
||||||
|
items := []list.Item{}
|
||||||
|
|
||||||
|
result, err := commands.Search(ctx, client, search, 1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
items = append(items, mainItem{
|
||||||
|
Name: "Tracks",
|
||||||
|
Desc: "Search results",
|
||||||
|
SpotifyItem: result.Tracks,
|
||||||
|
})
|
||||||
|
items = append(items, mainItem{
|
||||||
|
Name: "Albums",
|
||||||
|
Desc: "Search results",
|
||||||
|
SpotifyItem: result.Albums,
|
||||||
|
})
|
||||||
|
items = append(items, mainItem{
|
||||||
|
Name: "Artists",
|
||||||
|
Desc: "Search results",
|
||||||
|
SpotifyItem: result.Artists,
|
||||||
|
})
|
||||||
|
items = append(items, mainItem{
|
||||||
|
Name: "Playlists",
|
||||||
|
Desc: "Search results",
|
||||||
|
SpotifyItem: result.Playlists,
|
||||||
|
})
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
func AlbumsView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) {
|
func AlbumsView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) {
|
||||||
items := []list.Item{}
|
items := []list.Item{}
|
||||||
albums, err := commands.UserAlbums(ctx, client, 1)
|
albums, err := commands.UserAlbums(ctx, client, 1)
|
||||||
@ -80,6 +123,31 @@ func AlbumsView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error)
|
|||||||
return items, nil
|
return items, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SearchPlaylistsView(ctx *gctx.Context, client *spotify.Client, playlists *spotify.SimplePlaylistPage) ([]list.Item, error) {
|
||||||
|
items := []list.Item{}
|
||||||
|
for _, playlist := range playlists.Playlists {
|
||||||
|
items = append(items, mainItem{
|
||||||
|
Name: playlist.Name,
|
||||||
|
Desc: playlist.Description,
|
||||||
|
SpotifyItem: playlist,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SearchAlbumsView(ctx *gctx.Context, client *spotify.Client, albums *spotify.SimpleAlbumPage) ([]list.Item, error) {
|
||||||
|
items := []list.Item{}
|
||||||
|
for _, album := range albums.Albums {
|
||||||
|
items = append(items, mainItem{
|
||||||
|
Name: album.Name,
|
||||||
|
ID: album.ID,
|
||||||
|
Desc: fmt.Sprintf("%s, %d", album.Artists[0].Name, album.ReleaseDateTime()),
|
||||||
|
SpotifyItem: album,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
func ArtistAlbumsView(ctx *gctx.Context, album spotify.ID, client *spotify.Client) ([]list.Item, error) {
|
func ArtistAlbumsView(ctx *gctx.Context, album spotify.ID, client *spotify.Client) ([]list.Item, error) {
|
||||||
items := []list.Item{}
|
items := []list.Item{}
|
||||||
albums, err := commands.ArtistAlbums(ctx, client, album, 1)
|
albums, err := commands.ArtistAlbums(ctx, client, album, 1)
|
||||||
@ -115,6 +183,20 @@ func AlbumTracksView(ctx *gctx.Context, album spotify.ID, client *spotify.Client
|
|||||||
return items, err
|
return items, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func SearchTracksView(ctx *gctx.Context, client *spotify.Client, tracks *spotify.FullTrackPage) ([]list.Item, error) {
|
||||||
|
items := []list.Item{}
|
||||||
|
for _, track := range tracks.Tracks {
|
||||||
|
items = append(items, mainItem{
|
||||||
|
Name: track.Name,
|
||||||
|
Artist: track.Artists[0],
|
||||||
|
Duration: track.TimeDuration().Round(time.Second).String(),
|
||||||
|
ID: track.ID,
|
||||||
|
Desc: track.Artists[0].Name + " - " + track.TimeDuration().Round(time.Second).String(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return items, nil
|
||||||
|
}
|
||||||
|
|
||||||
func SavedTracksView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) {
|
func SavedTracksView(ctx *gctx.Context, client *spotify.Client) ([]list.Item, error) {
|
||||||
items := []list.Item{}
|
items := []list.Item{}
|
||||||
tracks, err := commands.TrackList(ctx, client, 1)
|
tracks, err := commands.TrackList(ctx, client, 1)
|
||||||
|
Loading…
Reference in New Issue
Block a user