Initial commit

This commit is contained in:
Aynakeya
2022-06-21 13:02:22 -07:00
commit 9f75839ebc
161 changed files with 18766 additions and 0 deletions

48
gui/gui.go Normal file
View File

@@ -0,0 +1,48 @@
package gui
import (
"AynaLivePlayer/config"
"AynaLivePlayer/logger"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"github.com/sirupsen/logrus"
"os"
)
const MODULE_GUI = "GUI"
var App fyne.App
var MainWindow fyne.Window
func l() *logrus.Entry {
return logger.Logger.WithField("Module", MODULE_GUI)
}
func Initialize() {
os.Setenv("FYNE_FONT", config.GetAssetPath("msyh.ttc"))
App = app.New()
MainWindow = App.NewWindow("AynaLivePlayer")
tabs := container.NewAppTabs(
container.NewTabItem("Player",
newPaddedBoarder(nil, createPlayController(), nil, nil, createPlaylist()),
),
container.NewTabItem("Search",
newPaddedBoarder(createSearchBar(), nil, nil, nil, createSearchList()),
),
container.NewTabItem("Room",
newPaddedBoarder(createRoomController(), nil, nil, nil, createRoomLogger()),
),
container.NewTabItem("Playlist",
newPaddedBoarder(nil, nil, createPlaylists(), nil, createPlaylistMedias()),
),
)
tabs.SetTabLocation(container.TabLocationTop)
MainWindow.SetContent(tabs)
//MainWindow.Resize(fyne.NewSize(1280, 720))
MainWindow.Resize(fyne.NewSize(960, 480))
//MainWindow.SetFixedSize(true)
}

33
gui/helper.go Normal file
View File

@@ -0,0 +1,33 @@
package gui
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
func newPaddedBoarder(top, bottom, left, right fyne.CanvasObject, objects ...fyne.CanvasObject) *fyne.Container {
return container.NewPadded(container.NewBorder(top, bottom, left, right, objects...))
}
func newLabelWithWrapping(text string, wrapping fyne.TextWrap) *widget.Label {
w := widget.NewLabel(text)
w.Wrapping = wrapping
return w
}
func createAsyncOnTapped(btn *widget.Button, f func()) func() {
return func() {
btn.Disable()
go func() {
f()
btn.Enable()
}()
}
}
func createAsyncButton(btn *widget.Button, tapped func()) *widget.Button {
btn.OnTapped = createAsyncOnTapped(btn, tapped)
return btn
}

213
gui/player_controller.go Normal file
View File

@@ -0,0 +1,213 @@
package gui
import (
"AynaLivePlayer/config"
"AynaLivePlayer/controller"
"AynaLivePlayer/event"
"AynaLivePlayer/player"
"AynaLivePlayer/util"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/canvas"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/storage"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
"github.com/aynakeya/go-mpv"
)
type PlayControllerContainer struct {
Title *widget.Label
Artist *widget.Label
Username *widget.Label
Cover *canvas.Image
ButtonPrev *widget.Button
ButtonSwitch *widget.Button
ButtonNext *widget.Button
Progress *widget.Slider
Volume *widget.Slider
ButtonLrc *widget.Button
LrcWindowOpen bool
CurrentTime *widget.Label
TotalTime *widget.Label
}
func (p *PlayControllerContainer) SetDefaultCover() {
p.Cover.Resource = nil
p.Cover.File = config.GetAssetPath("empty.png")
p.Cover.Refresh()
}
var PlayController = &PlayControllerContainer{}
func createPlayController() fyne.CanvasObject {
PlayController.Cover = canvas.NewImageFromFile(config.GetAssetPath("empty.png"))
PlayController.Cover.SetMinSize(fyne.NewSize(128, 128))
PlayController.Cover.FillMode = canvas.ImageFillContain
PlayController.ButtonPrev = widget.NewButtonWithIcon("", theme.MediaSkipPreviousIcon(), func() {})
PlayController.ButtonSwitch = widget.NewButtonWithIcon("", theme.MediaPlayIcon(), func() {})
PlayController.ButtonNext = widget.NewButtonWithIcon("", theme.MediaSkipNextIcon(), func() {})
buttonsBox := container.NewCenter(
container.NewHBox(PlayController.ButtonPrev, PlayController.ButtonSwitch, PlayController.ButtonNext))
PlayController.Progress = widget.NewSlider(0, 10000)
PlayController.CurrentTime = widget.NewLabel("0:00")
PlayController.TotalTime = widget.NewLabel("0:00")
progressItem := container.NewBorder(nil, nil, PlayController.CurrentTime, PlayController.TotalTime, PlayController.Progress)
PlayController.Title = widget.NewLabel("Title")
PlayController.Artist = widget.NewLabel("Artist")
PlayController.Username = widget.NewLabel("Username")
playInfo := container.NewVBox(PlayController.Title, PlayController.Artist, PlayController.Username)
PlayController.Volume = widget.NewSlider(0, 100)
volumeIcon := widget.NewIcon(theme.VolumeMuteIcon())
PlayController.ButtonLrc = widget.NewButton("lrc", func() {})
volumeControl := container.NewBorder(nil, nil, container.NewHBox(widget.NewLabel(" "), volumeIcon), nil,
container.NewGridWithColumns(3, container.NewMax(PlayController.Volume), PlayController.ButtonLrc))
registerPlayControllerHandler()
return container.NewBorder(nil, nil, container.NewHBox(PlayController.Cover, playInfo, widget.NewSeparator()), nil,
container.NewVBox(buttonsBox, progressItem, volumeControl))
}
func registerPlayControllerHandler() {
PlayController.ButtonPrev.OnTapped = func() {
controller.Seek(0, true)
}
PlayController.ButtonSwitch.OnTapped = func() {
if controller.Toggle() {
PlayController.ButtonSwitch.Icon = theme.MediaPlayIcon()
} else {
PlayController.ButtonSwitch.Icon = theme.MediaStopIcon()
}
}
PlayController.ButtonNext.OnTapped = func() {
controller.PlayNext()
}
PlayController.ButtonLrc.OnTapped = func() {
if !PlayController.LrcWindowOpen {
PlayController.LrcWindowOpen = true
createLyricWindow().Show()
}
}
if controller.MainPlayer.ObserveProperty("pause", func(property *mpv.EventProperty) {
if property.Data == nil {
PlayController.ButtonSwitch.Icon = theme.MediaPlayIcon()
return
}
if property.Data.(mpv.Node).Value.(bool) {
PlayController.ButtonSwitch.Icon = theme.MediaPlayIcon()
} else {
PlayController.ButtonSwitch.Icon = theme.MediaStopIcon()
}
}) != nil {
l().Error("fail to register handler for switch button with property pause")
}
if controller.MainPlayer.ObserveProperty("percent-pos", func(property *mpv.EventProperty) {
if property.Data == nil {
PlayController.Progress.SetValue(0)
return
}
PlayController.Progress.Value = property.Data.(mpv.Node).Value.(float64) * 100
PlayController.Progress.Refresh()
}) != nil {
l().Error("fail to register handler for progress bar with property percent-pos")
}
if controller.MainPlayer.ObserveProperty("idle-active", func(property *mpv.EventProperty) {
isIdle := property.Data.(mpv.Node).Value.(bool)
l().Debug("receive idle active ", isIdle, " set/reset info")
// todo: @3
if isIdle {
PlayController.Progress.Value = 0
PlayController.Progress.Max = 0
//PlayController.Title.SetText("Title")
//PlayController.Artist.SetText("Artist")
//PlayController.Username.SetText("Username")
//PlayController.SetDefaultCover()
} else {
PlayController.Progress.Max = 10000
}
}) != nil {
l().Error("fail to register handler for progress bar with property idle-active")
}
PlayController.Progress.OnChanged = func(f float64) {
controller.Seek(f/100, false)
}
if controller.MainPlayer.ObserveProperty("time-pos", func(property *mpv.EventProperty) {
if property.Data == nil {
PlayController.CurrentTime.SetText("0:00")
return
}
PlayController.CurrentTime.SetText(util.FormatTime(int(property.Data.(mpv.Node).Value.(float64))))
}) != nil {
l().Error("fail to register handler for current time with property time-pos")
}
if controller.MainPlayer.ObserveProperty("duration", func(property *mpv.EventProperty) {
if property.Data == nil {
PlayController.TotalTime.SetText("0:00")
return
}
PlayController.TotalTime.SetText(util.FormatTime(int(property.Data.(mpv.Node).Value.(float64))))
}) != nil {
l().Error("fail to register handler for total time with property duration")
}
if controller.MainPlayer.ObserveProperty("volume", func(property *mpv.EventProperty) {
l().Trace("receive volume change event", *property)
if property.Data == nil {
PlayController.Volume.Value = 0
} else {
PlayController.Volume.Value = property.Data.(mpv.Node).Value.(float64)
}
PlayController.Volume.Refresh()
}) != nil {
l().Error("fail to register handler for progress bar with property percent-pos")
}
PlayController.Volume.OnChanged = func(f float64) {
controller.SetVolume(f)
}
controller.MainPlayer.EventHandler.RegisterA(player.EventPlay, "gui.player.updateinfo", func(event *event.Event) {
l().Debug("receive EventPlay update player info")
media := event.Data.(player.PlayEvent).Media
PlayController.Title.SetText(
util.StringNormalize(media.Title, 16, 16))
PlayController.Artist.SetText(
util.StringNormalize(media.Artist, 16, 16))
PlayController.Username.SetText(media.ToUser().Name)
if media.Cover == "" {
PlayController.SetDefaultCover()
} else {
uri, err := storage.ParseURI(media.Cover)
if err != nil {
l().Warn("fail to load parse cover url", media.Cover)
}
// async update
go func() {
img := canvas.NewImageFromURI(uri)
if img == nil {
l().Warn("fail to load parse cover url", media.Cover)
PlayController.SetDefaultCover()
return
}
PlayController.Cover.Resource = img.Resource
PlayController.Cover.Refresh()
}()
}
})
return
}

61
gui/player_lyric.go Normal file
View File

@@ -0,0 +1,61 @@
package gui
import (
"AynaLivePlayer/controller"
"AynaLivePlayer/event"
"AynaLivePlayer/player"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
"strings"
)
func createLyricWindow() fyne.Window {
// create widgets
w := App.NewWindow("Lyric")
currentLrc := newLabelWithWrapping("", fyne.TextWrapBreak)
currentLrc.Alignment = fyne.TextAlignCenter
lrcs := make([]string, len(controller.CurrentLyric.Lyrics))
for i := 0; i < len(lrcs); i++ {
lrcs[i] = controller.CurrentLyric.Lyrics[i].Lyric
}
fullLrc := widget.NewRichTextWithText(strings.Join(lrcs, "\n\n"))
fullLrc.Scroll = container.ScrollVerticalOnly
fullLrc.Wrapping = fyne.TextWrapWord
w.SetContent(container.NewBorder(nil,
container.NewVBox(widget.NewSeparator(), currentLrc),
nil, nil,
fullLrc))
w.Resize(fyne.NewSize(360, 540))
w.CenterOnScreen()
// register handlers
controller.CurrentLyric.Handler.RegisterA(player.EventLyricUpdate, "player.lyric.current_lyric", func(event *event.Event) {
e := event.Data.(player.LyricUpdateEvent)
if e.Lyric == nil {
currentLrc.SetText("")
return
}
currentLrc.SetText(e.Lyric.Lyric)
})
controller.CurrentLyric.Handler.RegisterA(player.EventLyricReload, "player.lyric.new_media", func(event *event.Event) {
e := event.Data.(player.LyricReloadEvent)
lrcs := make([]string, len(e.Lyrics.Lyrics))
for i := 0; i < len(lrcs); i++ {
lrcs[i] = e.Lyrics.Lyrics[i].Lyric
}
fullLrc.Segments[0] = &widget.TextSegment{
Style: widget.RichTextStyleInline,
Text: strings.Join(lrcs, "\n\n"),
}
fullLrc.Refresh()
})
w.SetOnClosed(func() {
controller.CurrentLyric.Handler.Unregister("player.lyric.current_lyric")
controller.CurrentLyric.Handler.Unregister("player.lyric.new_media")
PlayController.LrcWindowOpen = false
})
return w
}

57
gui/player_playlist.go Normal file
View File

@@ -0,0 +1,57 @@
package gui
import (
"AynaLivePlayer/controller"
"AynaLivePlayer/event"
"AynaLivePlayer/player"
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
type PlaylistContainer struct {
Playlist *player.Playlist
List *widget.List
}
var UserPlaylist = &PlaylistContainer{}
func createPlaylist() fyne.CanvasObject {
UserPlaylist.Playlist = controller.UserPlaylist
UserPlaylist.List = widget.NewList(
func() int {
//debug.PrintStack()
// todo: @4
return UserPlaylist.Playlist.Size()
},
func() fyne.CanvasObject {
return container.NewBorder(nil, nil, widget.NewLabel("index"), widget.NewLabel("user"),
container.NewGridWithColumns(2,
newLabelWithWrapping("title", fyne.TextTruncate),
newLabelWithWrapping("artist", fyne.TextTruncate)))
},
func(id widget.ListItemID, object fyne.CanvasObject) {
object.(*fyne.Container).Objects[0].(*fyne.Container).Objects[0].(*widget.Label).SetText(
UserPlaylist.Playlist.Playlist[id].Title)
object.(*fyne.Container).Objects[0].(*fyne.Container).Objects[1].(*widget.Label).SetText(
UserPlaylist.Playlist.Playlist[id].Artist)
object.(*fyne.Container).Objects[1].(*widget.Label).SetText(fmt.Sprintf("%d", id))
object.(*fyne.Container).Objects[2].(*widget.Label).SetText(UserPlaylist.Playlist.Playlist[id].ToUser().Name)
})
registerPlaylistHandler()
return container.NewBorder(
container.NewBorder(nil, nil,
widget.NewLabel("#"), widget.NewLabel("User"),
container.NewGridWithColumns(2, widget.NewLabel("Title"), widget.NewLabel("Artist"))),
widget.NewSeparator(),
nil, nil,
UserPlaylist.List,
)
}
func registerPlaylistHandler() {
UserPlaylist.Playlist.Handler.RegisterA(player.EventPlaylistUpdate, "gui.playlist.update", func(event *event.Event) {
UserPlaylist.List.Refresh()
})
}

149
gui/playlist_list.go Normal file
View File

@@ -0,0 +1,149 @@
package gui
import (
"AynaLivePlayer/config"
"AynaLivePlayer/controller"
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
type PlaylistManagerContainer struct {
Playlists *widget.List
PlaylistMedia *widget.List
Index int
AddBtn *widget.Button
RemoveBtn *widget.Button
SetAsSystemBtn *widget.Button
RefreshBtn *widget.Button
CurrentSystemPlaylist *widget.Label
}
func (p *PlaylistManagerContainer) UpdateCurrentSystemPlaylist() {
if config.Player.PlaylistIndex >= len(controller.PlaylistManager) {
p.CurrentSystemPlaylist.SetText("Current: None")
}
p.CurrentSystemPlaylist.SetText("Current: " + controller.PlaylistManager[config.Player.PlaylistIndex].Name)
}
var PlaylistManager = &PlaylistManagerContainer{}
func createPlaylists() fyne.CanvasObject {
PlaylistManager.Playlists = widget.NewList(
func() int {
return len(controller.PlaylistManager)
},
func() fyne.CanvasObject {
return widget.NewLabel("AAAAAAAAAAAAAAAA")
},
func(id widget.ListItemID, object fyne.CanvasObject) {
object.(*widget.Label).SetText(
controller.PlaylistManager[id].Name)
})
PlaylistManager.AddBtn = widget.NewButton("Add", func() {
providerEntry := widget.NewSelect(config.Provider.Priority, nil)
idEntry := widget.NewEntry()
dia := dialog.NewCustomConfirm(
"Add Playlist",
"Add",
"Cancel",
container.NewVBox(
container.New(
layout.NewFormLayout(),
widget.NewLabel("Provider"),
providerEntry,
widget.NewLabel("ID/URL"),
idEntry,
),
widget.NewLabel("Please Enter playlist id or playlist url"),
),
func(b bool) {
if b && len(providerEntry.Selected) > 0 && len(idEntry.Text) > 0 {
controller.AddPlaylist(providerEntry.Selected, idEntry.Text)
PlaylistManager.Playlists.Refresh()
PlaylistManager.PlaylistMedia.Refresh()
}
},
MainWindow,
)
dia.Resize(fyne.NewSize(512, 256))
dia.Show()
})
PlaylistManager.RemoveBtn = widget.NewButton("Remove", func() {
controller.RemovePlaylist(PlaylistManager.Index)
//PlaylistManager.Index = 0
PlaylistManager.Playlists.Select(0)
PlaylistManager.Playlists.Refresh()
PlaylistManager.PlaylistMedia.Refresh()
})
PlaylistManager.Playlists.OnSelected = func(id widget.ListItemID) {
PlaylistManager.Index = id
}
return container.NewHBox(
container.NewBorder(
nil, container.NewCenter(container.NewHBox(PlaylistManager.AddBtn, PlaylistManager.RemoveBtn)),
nil, nil,
PlaylistManager.Playlists,
),
widget.NewSeparator(),
)
}
func createPlaylistMedias() fyne.CanvasObject {
PlaylistManager.RefreshBtn = createAsyncButton(
widget.NewButtonWithIcon("Refresh", theme.ViewRefreshIcon(), nil),
func() {
controller.PreparePlaylistByIndex(PlaylistManager.Index)
PlaylistManager.PlaylistMedia.Refresh()
})
PlaylistManager.SetAsSystemBtn = createAsyncButton(
widget.NewButton("SetAsSystem", nil),
func() {
controller.SetSystemPlaylist(PlaylistManager.Index)
PlaylistManager.PlaylistMedia.Refresh()
PlaylistManager.UpdateCurrentSystemPlaylist()
})
PlaylistManager.CurrentSystemPlaylist = widget.NewLabel("Current: ")
PlaylistManager.UpdateCurrentSystemPlaylist()
PlaylistManager.PlaylistMedia = widget.NewList(
func() int {
if len(controller.PlaylistManager) == 0 {
return 0
}
return controller.PlaylistManager[PlaylistManager.Index].Size()
},
func() fyne.CanvasObject {
return container.NewBorder(nil, nil,
widget.NewLabel("index"),
container.NewHBox(
widget.NewButtonWithIcon("", theme.MediaPlayIcon(), nil),
widget.NewButtonWithIcon("", theme.ContentAddIcon(), nil),
),
container.NewGridWithColumns(2,
newLabelWithWrapping("title", fyne.TextTruncate),
newLabelWithWrapping("artist", fyne.TextTruncate)))
},
func(id widget.ListItemID, object fyne.CanvasObject) {
m := controller.PlaylistManager[PlaylistManager.Index].Playlist[id]
object.(*fyne.Container).Objects[0].(*fyne.Container).Objects[0].(*widget.Label).SetText(
m.Title)
object.(*fyne.Container).Objects[0].(*fyne.Container).Objects[1].(*widget.Label).SetText(
m.Artist)
object.(*fyne.Container).Objects[1].(*widget.Label).SetText(fmt.Sprintf("%d", id))
btns := object.(*fyne.Container).Objects[2].(*fyne.Container).Objects
btns[0].(*widget.Button).OnTapped = func() {
controller.Play(m)
}
btns[1].(*widget.Button).OnTapped = func() {
controller.UserPlaylist.Push(m)
}
})
return container.NewBorder(
container.NewHBox(PlaylistManager.RefreshBtn, PlaylistManager.SetAsSystemBtn), nil,
nil, nil,
PlaylistManager.PlaylistMedia)
}

56
gui/room_bar.go Normal file
View File

@@ -0,0 +1,56 @@
package gui
import (
"AynaLivePlayer/config"
"AynaLivePlayer/controller"
"AynaLivePlayer/event"
"AynaLivePlayer/liveclient"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
type RoomControllerContainer struct {
Input *widget.SelectEntry
ConnectBtn *widget.Button
DisConnectBtn *widget.Button
Status *widget.Label
}
var RoomController = &RoomControllerContainer{}
func createRoomController() fyne.CanvasObject {
RoomController.Input = widget.NewSelectEntry(config.LiveRoom.History)
RoomController.ConnectBtn = widget.NewButton("Connect", func() {
RoomController.ConnectBtn.Disable()
controller.SetDanmuClient(RoomController.Input.Text)
if controller.LiveClient == nil {
RoomController.Status.SetText("Set Failed")
RoomController.Status.Refresh()
return
}
RoomController.Input.SetOptions(config.LiveRoom.History)
controller.LiveClient.Handler().RegisterA(liveclient.EventStatusChange, "gui.liveclient.status", func(event *event.Event) {
d := event.Data.(liveclient.StatusChangeEvent)
if d.Connected {
RoomController.Status.SetText("Connected")
} else {
RoomController.Status.SetText("Disconnected")
}
RoomController.Status.Refresh()
})
go func() {
controller.StartDanmuClient()
RoomController.ConnectBtn.Enable()
}()
})
RoomController.DisConnectBtn = widget.NewButton("Disconnect", func() {
controller.ResetDanmuClient()
})
RoomController.Status = widget.NewLabel("Waiting")
return container.NewBorder(
nil, nil,
widget.NewLabel("Room ID:"), container.NewHBox(RoomController.ConnectBtn, RoomController.DisConnectBtn),
container.NewBorder(nil, nil, nil, RoomController.Status, RoomController.Input),
)
}

15
gui/room_logger.go Normal file
View File

@@ -0,0 +1,15 @@
package gui
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/widget"
)
type RoomLoggerContainer struct {
}
var RoomLogger = &RoomLoggerContainer{}
func createRoomLogger() fyne.CanvasObject {
return widget.NewLabel("广告位招租")
}

53
gui/search_bar.go Normal file
View File

@@ -0,0 +1,53 @@
package gui
import (
"AynaLivePlayer/config"
"AynaLivePlayer/controller"
"AynaLivePlayer/player"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
type SearchBarContainer struct {
Input *widget.Entry
Button *widget.Button
UseSource *widget.CheckGroup
Items []*player.Media
}
var SearchBar = &SearchBarContainer{}
func createSearchBar() fyne.CanvasObject {
SearchBar.Input = widget.NewEntry()
SearchBar.Input.SetPlaceHolder("Keyword")
SearchBar.Button = widget.NewButton("Search", nil)
SearchBar.Button.OnTapped = createAsyncOnTapped(SearchBar.Button, func() {
keyword := SearchBar.Input.Text
s := make([]string, len(SearchBar.UseSource.Selected))
copy(s, SearchBar.UseSource.Selected)
items := make([]*player.Media, 0)
for _, p := range s {
if r, err := controller.SearchWithProvider(keyword, p); err == nil {
items = append(items, r...)
}
}
controller.ApplyUser(items, player.SystemUser)
SearchResult.Items = items
SearchResult.List.Refresh()
})
s := make([]string, len(config.Provider.Priority))
copy(s, config.Provider.Priority)
SearchBar.UseSource = widget.NewCheckGroup(s, nil)
SearchBar.UseSource.Horizontal = true
SearchBar.UseSource.SetSelected(s)
searchInput := container.NewBorder(
nil, nil, widget.NewLabel("Search"), SearchBar.Button,
SearchBar.Input)
return container.NewVBox(
searchInput,
container.NewHBox(widget.NewLabel("Source filter: "), SearchBar.UseSource),
widget.NewSeparator())
}

64
gui/search_list.go Normal file
View File

@@ -0,0 +1,64 @@
package gui
import (
"AynaLivePlayer/controller"
"AynaLivePlayer/player"
"AynaLivePlayer/provider"
"fmt"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
type SearchResultContainer struct {
List *widget.List
Items []*player.Media
}
var SearchResult = &SearchResultContainer{Items: []*player.Media{}}
func createSearchList() fyne.CanvasObject {
SearchResult.List = widget.NewList(
func() int {
return len(SearchResult.Items)
},
func() fyne.CanvasObject {
return container.NewBorder(nil, nil,
widget.NewLabel("index"),
container.NewHBox(
widget.NewButtonWithIcon("", theme.MediaPlayIcon(), nil),
widget.NewButtonWithIcon("", theme.ContentAddIcon(), nil),
),
container.NewGridWithColumns(3,
newLabelWithWrapping("title", fyne.TextTruncate),
newLabelWithWrapping("artist", fyne.TextTruncate),
newLabelWithWrapping("source", fyne.TextTruncate)))
},
func(id widget.ListItemID, object fyne.CanvasObject) {
object.(*fyne.Container).Objects[0].(*fyne.Container).Objects[0].(*widget.Label).SetText(
SearchResult.Items[id].Title)
object.(*fyne.Container).Objects[0].(*fyne.Container).Objects[1].(*widget.Label).SetText(
SearchResult.Items[id].Artist)
object.(*fyne.Container).Objects[0].(*fyne.Container).Objects[2].(*widget.Label).SetText(
SearchResult.Items[id].Meta.(provider.Meta).Name)
object.(*fyne.Container).Objects[1].(*widget.Label).SetText(fmt.Sprintf("%d", id))
btns := object.(*fyne.Container).Objects[2].(*fyne.Container).Objects
btns[0].(*widget.Button).OnTapped = func() {
controller.Play(SearchResult.Items[id])
}
btns[1].(*widget.Button).OnTapped = func() {
controller.UserPlaylist.Push(SearchResult.Items[id])
}
})
return container.NewBorder(
container.NewBorder(nil, nil,
widget.NewLabel("#"), widget.NewLabel("Operation"),
container.NewGridWithColumns(3,
widget.NewLabel("title"),
widget.NewLabel("artist"),
widget.NewLabel("source"))),
nil, nil, nil,
SearchResult.List,
)
}