add albumfilterdialog
This commit is contained in:
@@ -4,6 +4,7 @@ import (
|
|||||||
"github.com/dweymouth/supersonic/backend"
|
"github.com/dweymouth/supersonic/backend"
|
||||||
"github.com/dweymouth/supersonic/sharedutil"
|
"github.com/dweymouth/supersonic/sharedutil"
|
||||||
"github.com/dweymouth/supersonic/ui/controller"
|
"github.com/dweymouth/supersonic/ui/controller"
|
||||||
|
"github.com/dweymouth/supersonic/ui/dialogs"
|
||||||
"github.com/dweymouth/supersonic/ui/util"
|
"github.com/dweymouth/supersonic/ui/util"
|
||||||
"github.com/dweymouth/supersonic/ui/widgets"
|
"github.com/dweymouth/supersonic/ui/widgets"
|
||||||
|
|
||||||
@@ -27,7 +28,9 @@ type AlbumsPage struct {
|
|||||||
grid *widgets.GridView
|
grid *widgets.GridView
|
||||||
searchGrid *widgets.GridView
|
searchGrid *widgets.GridView
|
||||||
searcher *widgets.SearchEntry
|
searcher *widgets.SearchEntry
|
||||||
|
filterBtn *widgets.AlbumFilterButton
|
||||||
searchText string
|
searchText string
|
||||||
|
filter backend.AlbumFilter
|
||||||
titleDisp *widget.RichText
|
titleDisp *widget.RichText
|
||||||
sortOrder *selectWidget
|
sortOrder *selectWidget
|
||||||
container *fyne.Container
|
container *fyne.Container
|
||||||
@@ -71,11 +74,12 @@ func NewAlbumsPage(cfg *backend.AlbumsPageConfig, contr *controller.Controller,
|
|||||||
cfg.SortOrder = string(backend.AlbumSortRecentlyAdded)
|
cfg.SortOrder = string(backend.AlbumSortRecentlyAdded)
|
||||||
}
|
}
|
||||||
a.sortOrder.Selected = cfg.SortOrder
|
a.sortOrder.Selected = cfg.SortOrder
|
||||||
iter := lm.AlbumsIter(backend.AlbumSortOrder(a.sortOrder.Selected), backend.AlbumFilter{})
|
iter := lm.AlbumsIter(backend.AlbumSortOrder(a.sortOrder.Selected), a.filter)
|
||||||
a.grid = widgets.NewGridView(widgets.NewGridViewAlbumIterator(iter), im)
|
a.grid = widgets.NewGridView(widgets.NewGridViewAlbumIterator(iter), im)
|
||||||
contr.ConnectAlbumGridActions(a.grid)
|
contr.ConnectAlbumGridActions(a.grid)
|
||||||
a.searcher = widgets.NewSearchEntry()
|
a.searcher = widgets.NewSearchEntry()
|
||||||
a.searcher.OnSearched = a.OnSearched
|
a.searcher.OnSearched = a.OnSearched
|
||||||
|
a.filterBtn = widgets.NewAlbumFilterButton(&a.filter, func(filter *backend.AlbumFilter) fyne.CanvasObject { return dialogs.NewAlbumFilterDialog(filter) })
|
||||||
a.createContainer(false)
|
a.createContainer(false)
|
||||||
|
|
||||||
return a
|
return a
|
||||||
@@ -89,7 +93,7 @@ func (a *AlbumsPage) createContainer(searchgrid bool) {
|
|||||||
g = a.searchGrid
|
g = a.searchGrid
|
||||||
}
|
}
|
||||||
a.container = container.NewBorder(
|
a.container = container.NewBorder(
|
||||||
container.NewHBox(util.NewHSpace(6), a.titleDisp, sortVbox, layout.NewSpacer(), searchVbox, util.NewHSpace(12)),
|
container.NewHBox(util.NewHSpace(6), a.titleDisp, sortVbox, layout.NewSpacer(), a.filterBtn, searchVbox, util.NewHSpace(12)),
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
nil,
|
nil,
|
||||||
@@ -154,7 +158,7 @@ func (a *AlbumsPage) Reload() {
|
|||||||
if a.searchText != "" {
|
if a.searchText != "" {
|
||||||
a.doSearch(a.searchText)
|
a.doSearch(a.searchText)
|
||||||
} else {
|
} else {
|
||||||
iter := a.lm.AlbumsIter(backend.AlbumSortOrder(a.sortOrder.Selected), backend.AlbumFilter{})
|
iter := a.lm.AlbumsIter(backend.AlbumSortOrder(a.sortOrder.Selected), a.filter)
|
||||||
a.grid.Reset(widgets.NewGridViewAlbumIterator(iter))
|
a.grid.Reset(widgets.NewGridViewAlbumIterator(iter))
|
||||||
a.grid.Refresh()
|
a.grid.Refresh()
|
||||||
}
|
}
|
||||||
@@ -190,7 +194,7 @@ func (a *AlbumsPage) doSearch(query string) {
|
|||||||
|
|
||||||
func (a *AlbumsPage) onSortOrderChanged(order string) {
|
func (a *AlbumsPage) onSortOrderChanged(order string) {
|
||||||
a.cfg.SortOrder = a.sortOrder.Selected
|
a.cfg.SortOrder = a.sortOrder.Selected
|
||||||
iter := a.lm.AlbumsIter(backend.AlbumSortOrder(order), backend.AlbumFilter{})
|
iter := a.lm.AlbumsIter(backend.AlbumSortOrder(order), a.filter)
|
||||||
a.grid.Reset(widgets.NewGridViewAlbumIterator(iter))
|
a.grid.Reset(widgets.NewGridViewAlbumIterator(iter))
|
||||||
if a.searchText == "" {
|
if a.searchText == "" {
|
||||||
a.container.Objects[0] = a.grid
|
a.container.Objects[0] = a.grid
|
||||||
|
|||||||
@@ -0,0 +1,76 @@
|
|||||||
|
package dialogs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
"github.com/dweymouth/supersonic/backend"
|
||||||
|
"github.com/dweymouth/supersonic/ui/widgets"
|
||||||
|
)
|
||||||
|
|
||||||
|
type AlbumFilterDialog struct {
|
||||||
|
widget.BaseWidget
|
||||||
|
|
||||||
|
OnDismissed func()
|
||||||
|
|
||||||
|
filter *backend.AlbumFilter
|
||||||
|
container *fyne.Container
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAlbumFilterDialog(filter *backend.AlbumFilter) *AlbumFilterDialog {
|
||||||
|
a := &AlbumFilterDialog{filter: filter}
|
||||||
|
a.ExtendBaseWidget(a)
|
||||||
|
|
||||||
|
// setup min and max year filters
|
||||||
|
yearValidator := func(curText string, r rune) bool {
|
||||||
|
return unicode.IsDigit(r) && len(curText) <= 3
|
||||||
|
}
|
||||||
|
minYear := widgets.NewTextRestrictedEntry(yearValidator)
|
||||||
|
minYear.OnChanged = func(yearStr string) {
|
||||||
|
if i, err := strconv.Atoi(yearStr); err == nil {
|
||||||
|
a.filter.MinYear = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if filter.MinYear > 0 {
|
||||||
|
minYear.Text = strconv.Itoa(filter.MinYear)
|
||||||
|
}
|
||||||
|
maxYear := widgets.NewTextRestrictedEntry(yearValidator)
|
||||||
|
maxYear.OnChanged = func(yearStr string) {
|
||||||
|
if i, err := strconv.Atoi(yearStr); err == nil {
|
||||||
|
a.filter.MaxYear = i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if filter.MaxYear > 0 {
|
||||||
|
maxYear.Text = strconv.Itoa(filter.MaxYear)
|
||||||
|
}
|
||||||
|
|
||||||
|
var isNotFavorite *widget.Check
|
||||||
|
// setup is favorite/not favorite filters
|
||||||
|
isFavorite := widget.NewCheck("Is favorite", func(fav bool) {
|
||||||
|
if fav {
|
||||||
|
isNotFavorite.SetChecked(false)
|
||||||
|
}
|
||||||
|
a.filter.ExcludeUnfavorited = fav
|
||||||
|
})
|
||||||
|
isNotFavorite = widget.NewCheck("Is not favorite", func(fav bool) {
|
||||||
|
if fav {
|
||||||
|
isFavorite.SetChecked(false)
|
||||||
|
}
|
||||||
|
a.filter.ExcludeFavorited = fav
|
||||||
|
})
|
||||||
|
|
||||||
|
a.container = container.NewVBox(
|
||||||
|
container.NewHBox(widget.NewLabel("Year from"), minYear, widget.NewLabel("to"), maxYear),
|
||||||
|
isFavorite,
|
||||||
|
isNotFavorite,
|
||||||
|
)
|
||||||
|
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AlbumFilterDialog) CreateRenderer() fyne.WidgetRenderer {
|
||||||
|
return widget.NewSimpleRenderer(a.container)
|
||||||
|
}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
package widgets
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/dweymouth/supersonic/backend"
|
||||||
|
"github.com/dweymouth/supersonic/res"
|
||||||
|
"github.com/dweymouth/supersonic/ui/theme"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
)
|
||||||
|
|
||||||
|
type FavoriteButton struct {
|
||||||
|
widget.Button
|
||||||
|
|
||||||
|
IsFavorited bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewFavoriteButton(onTapped func()) *FavoriteButton {
|
||||||
|
f := &FavoriteButton{
|
||||||
|
Button: widget.Button{
|
||||||
|
OnTapped: onTapped,
|
||||||
|
Icon: res.ResHeartOutlineInvertPng,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
f.ExtendBaseWidget(f)
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FavoriteButton) Tapped(e *fyne.PointEvent) {
|
||||||
|
f.IsFavorited = !f.IsFavorited
|
||||||
|
f.Button.Tapped(e)
|
||||||
|
f.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (f *FavoriteButton) Refresh() {
|
||||||
|
if f.IsFavorited {
|
||||||
|
f.Icon = theme.FavoriteIcon
|
||||||
|
} else {
|
||||||
|
f.Icon = theme.NotFavoriteIcon
|
||||||
|
}
|
||||||
|
f.Button.Refresh()
|
||||||
|
}
|
||||||
|
|
||||||
|
type AlbumFilterButton struct {
|
||||||
|
widget.Button
|
||||||
|
|
||||||
|
filter *backend.AlbumFilter
|
||||||
|
|
||||||
|
dialogConstructor func(*backend.AlbumFilter) fyne.CanvasObject
|
||||||
|
dialog *widget.PopUp
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAlbumFilterButton(filter *backend.AlbumFilter, dialogConstructor func(*backend.AlbumFilter) fyne.CanvasObject) *AlbumFilterButton {
|
||||||
|
a := &AlbumFilterButton{
|
||||||
|
filter: filter,
|
||||||
|
dialogConstructor: dialogConstructor,
|
||||||
|
Button: widget.Button{
|
||||||
|
Icon: theme.AlbumIcon,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
a.OnTapped = a.showFilterDialog
|
||||||
|
a.ExtendBaseWidget(a)
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AlbumFilterButton) showFilterDialog() {
|
||||||
|
if a.dialog == nil {
|
||||||
|
a.dialog = widget.NewModalPopUp(a.dialogConstructor(a.filter), fyne.CurrentApp().Driver().CanvasForObject(a))
|
||||||
|
}
|
||||||
|
a.dialog.Show()
|
||||||
|
}
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
package widgets
|
|
||||||
|
|
||||||
import (
|
|
||||||
"github.com/dweymouth/supersonic/res"
|
|
||||||
"github.com/dweymouth/supersonic/ui/theme"
|
|
||||||
|
|
||||||
"fyne.io/fyne/v2"
|
|
||||||
"fyne.io/fyne/v2/widget"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FavoriteButton struct {
|
|
||||||
widget.Button
|
|
||||||
|
|
||||||
IsFavorited bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFavoriteButton(onTapped func()) *FavoriteButton {
|
|
||||||
f := &FavoriteButton{
|
|
||||||
Button: widget.Button{
|
|
||||||
OnTapped: onTapped,
|
|
||||||
Icon: res.ResHeartOutlineInvertPng,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
f.ExtendBaseWidget(f)
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FavoriteButton) Tapped(e *fyne.PointEvent) {
|
|
||||||
f.IsFavorited = !f.IsFavorited
|
|
||||||
f.Button.Tapped(e)
|
|
||||||
f.Refresh()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FavoriteButton) Refresh() {
|
|
||||||
if f.IsFavorited {
|
|
||||||
f.Icon = theme.FavoriteIcon
|
|
||||||
} else {
|
|
||||||
f.Icon = theme.NotFavoriteIcon
|
|
||||||
}
|
|
||||||
f.Button.Refresh()
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user