misc: Upgrade Go to v1.21
Upgrade to 1.21 as 1.20 is now unmaintained. Most changes are related to the new `slices` package from standard library, which can replace some existing custom functions.
This commit is contained in:
@@ -24,7 +24,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.20'
|
||||
go-version: '1.21'
|
||||
|
||||
- name: Install Dependencies
|
||||
run: brew install --force mpv && brew install dylibbundler
|
||||
|
||||
@@ -18,7 +18,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.20'
|
||||
go-version: '1.21'
|
||||
|
||||
- name: Install dependencies
|
||||
run: sudo apt update && sudo apt install libmpv-dev gcc libegl1-mesa-dev xorg-dev
|
||||
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.20'
|
||||
go-version: '1.21'
|
||||
|
||||
- name: Install Dependencies
|
||||
run: >
|
||||
|
||||
+2
-2
@@ -8,12 +8,12 @@ import (
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"slices"
|
||||
"time"
|
||||
|
||||
"github.com/dweymouth/supersonic/backend/player"
|
||||
"github.com/dweymouth/supersonic/backend/player/mpv"
|
||||
"github.com/dweymouth/supersonic/backend/util"
|
||||
"github.com/dweymouth/supersonic/sharedutil"
|
||||
"github.com/fsnotify/fsnotify"
|
||||
"github.com/google/uuid"
|
||||
|
||||
@@ -233,7 +233,7 @@ func (a *App) setupMPV() error {
|
||||
a.LocalPlayer.SetAudioDevice(desiredDevice)
|
||||
|
||||
rgainOpts := []string{ReplayGainNone, ReplayGainAlbum, ReplayGainTrack, ReplayGainAuto}
|
||||
if !sharedutil.SliceContains(rgainOpts, a.Config.ReplayGain.Mode) {
|
||||
if !slices.Contains(rgainOpts, a.Config.ReplayGain.Mode) {
|
||||
a.Config.ReplayGain.Mode = ReplayGainNone
|
||||
}
|
||||
mode := player.ReplayGainNone
|
||||
|
||||
@@ -64,9 +64,7 @@ func (r *baseIter[T]) Next() *T {
|
||||
}
|
||||
r.serverPos += len(items)
|
||||
if !r.filter.IsNil() {
|
||||
items = sharedutil.FilterSlice(items, func(al *T) bool {
|
||||
return r.filter.Matches(al)
|
||||
})
|
||||
items = sharedutil.FilterSlice(items, r.filter.Matches)
|
||||
}
|
||||
r.prefetched = items
|
||||
if len(items) > 0 {
|
||||
|
||||
@@ -5,15 +5,6 @@ import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// Return a slice of range [0, n)
|
||||
func Range(n int) []int {
|
||||
s := make([]int, n)
|
||||
for i := 0; i < n; i++ {
|
||||
s[i] = i
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func CopyFile(srcPath, dstPath string) error {
|
||||
fin, err := os.Open(srcPath)
|
||||
if err != nil {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module github.com/dweymouth/supersonic
|
||||
|
||||
go 1.20
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
fyne.io/fyne/v2 v2.4.4
|
||||
|
||||
@@ -110,6 +110,7 @@ github.com/go-text/render v0.0.0-20230619120952-35bccb6164b8/go.mod h1:h29xCucjN
|
||||
github.com/go-text/typesetting v0.1.0 h1:vioSaLPYcHwPEPLT7gsjCGDCoYSbljxoHJzMnKwVvHw=
|
||||
github.com/go-text/typesetting v0.1.0/go.mod h1:d22AnmeKq/on0HNv73UFriMKc4Ez6EqZAofLhAzpSzI=
|
||||
github.com/go-text/typesetting-utils v0.0.0-20231211103740-d9332ae51f04 h1:zBx+p/W2aQYtNuyZNcTfinWvXBQwYtDfme051PR/lAY=
|
||||
github.com/go-text/typesetting-utils v0.0.0-20231211103740-d9332ae51f04/go.mod h1:DDxDdQEnB70R8owOx3LVpEFvpMK9eeH1o2r0yZhFI9o=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||
|
||||
@@ -2,32 +2,11 @@ package sharedutil
|
||||
|
||||
import (
|
||||
"math"
|
||||
"sort"
|
||||
"slices"
|
||||
|
||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||
)
|
||||
|
||||
func SliceEqual[T comparable](a []T, b []T) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(a); i++ {
|
||||
if a[i] != b[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func SliceContains[T comparable](ts []T, t T) bool {
|
||||
for _, x := range ts {
|
||||
if x == t {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func FilterSlice[T any](ss []T, test func(T) bool) []T {
|
||||
if ss == nil {
|
||||
return nil
|
||||
@@ -52,19 +31,6 @@ func MapSlice[T any, U any](ts []T, f func(T) U) []U {
|
||||
return result
|
||||
}
|
||||
|
||||
func Find[T any](ts []T, f func(T) bool) int {
|
||||
for i, tt := range ts {
|
||||
if f(tt) {
|
||||
return i
|
||||
}
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
func IndexOf[T comparable](ts []T, t T) int {
|
||||
return Find(ts, func(tt T) bool { return t == tt })
|
||||
}
|
||||
|
||||
func Reversed[T any](ts []T) []T {
|
||||
if ts == nil {
|
||||
return nil
|
||||
@@ -133,7 +99,7 @@ func ReorderTracks(tracks []*mediaprovider.Track, idxToMove []int, op TrackReord
|
||||
topIdx := 0
|
||||
botIdx := len(idxToMove)
|
||||
for i, t := range tracks {
|
||||
if SliceContains(idxToMove, i) {
|
||||
if slices.Contains(idxToMove, i) {
|
||||
newTracks[topIdx] = t
|
||||
topIdx++
|
||||
} else {
|
||||
@@ -145,7 +111,7 @@ func ReorderTracks(tracks []*mediaprovider.Track, idxToMove []int, op TrackReord
|
||||
topIdx := 0
|
||||
botIdx := len(tracks) - len(idxToMove)
|
||||
for i, t := range tracks {
|
||||
if SliceContains(idxToMove, i) {
|
||||
if slices.Contains(idxToMove, i) {
|
||||
newTracks[botIdx] = t
|
||||
botIdx++
|
||||
} else {
|
||||
@@ -178,7 +144,7 @@ func ReorderTracks(tracks []*mediaprovider.Track, idxToMove []int, op TrackReord
|
||||
|
||||
func firstIdxCanMoveUp(idxs []int) int {
|
||||
prevIdx := -1
|
||||
sort.Ints(idxs)
|
||||
slices.Sort(idxs)
|
||||
for _, idx := range idxs {
|
||||
if idx > prevIdx+1 {
|
||||
return idx
|
||||
@@ -190,7 +156,7 @@ func firstIdxCanMoveUp(idxs []int) int {
|
||||
|
||||
func lastIdxCanMoveDown(idxs []int, lenSlice int) int {
|
||||
prevIdx := lenSlice
|
||||
sort.Ints(idxs)
|
||||
slices.Sort(idxs)
|
||||
for i := len(idxs) - 1; i >= 0; i-- {
|
||||
idx := idxs[i]
|
||||
if idx < prevIdx-1 {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package sharedutil
|
||||
|
||||
import (
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||
@@ -79,13 +80,7 @@ func Test_ReorderTracks(t *testing.T) {
|
||||
|
||||
func tracklistsEqual(t *testing.T, a, b []*mediaprovider.Track) bool {
|
||||
t.Helper()
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i, _ := range a {
|
||||
if a[i].ID != b[i].ID {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
return slices.EqualFunc(a, b, func(a, b *mediaprovider.Track) bool {
|
||||
return a.ID == b.ID
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
package browsing
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/widget"
|
||||
"github.com/dweymouth/supersonic/backend"
|
||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||
"github.com/dweymouth/supersonic/sharedutil"
|
||||
"github.com/dweymouth/supersonic/ui/controller"
|
||||
myTheme "github.com/dweymouth/supersonic/ui/theme"
|
||||
"github.com/dweymouth/supersonic/ui/util"
|
||||
@@ -37,7 +38,7 @@ func (a *albumsPageAdapter) Route() controller.Route { return controller.AlbumsR
|
||||
func (a *albumsPageAdapter) SortOrders() ([]string, string) {
|
||||
orders := a.mp.AlbumSortOrders()
|
||||
sortOrder := a.cfg.SortOrder
|
||||
if !sharedutil.SliceContains(orders, sortOrder) {
|
||||
if !slices.Contains(orders, sortOrder) {
|
||||
sortOrder = string(orders[0])
|
||||
}
|
||||
return orders, sortOrder
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"image"
|
||||
"log"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/dweymouth/supersonic/backend"
|
||||
@@ -106,13 +107,13 @@ func NewNowPlayingPage(
|
||||
}
|
||||
a.queueList.OnSetRating = func(trackIDs []string, rating int) {
|
||||
contr.SetTrackRatings(trackIDs, rating)
|
||||
if sharedutil.SliceContains(trackIDs, a.nowPlayingID) {
|
||||
if slices.Contains(trackIDs, a.nowPlayingID) {
|
||||
a.card.SetDisplayedRating(rating)
|
||||
}
|
||||
}
|
||||
a.queueList.OnSetFavorite = func(trackIDs []string, fav bool) {
|
||||
contr.SetTrackFavorites(trackIDs, fav)
|
||||
if sharedutil.SliceContains(trackIDs, a.nowPlayingID) {
|
||||
if slices.Contains(trackIDs, a.nowPlayingID) {
|
||||
a.card.SetDisplayedFavorite(fav)
|
||||
}
|
||||
}
|
||||
@@ -232,7 +233,7 @@ func (a *NowPlayingPage) Tapped(*fyne.PointEvent) {
|
||||
func (a *NowPlayingPage) doSetNewTrackOrder(trackIDs []string, op sharedutil.TrackReorderOp) {
|
||||
idxs := make([]int, 0, len(trackIDs))
|
||||
for i, tr := range a.queue {
|
||||
if sharedutil.SliceContains(trackIDs, tr.ID) {
|
||||
if slices.Contains(trackIDs, tr.ID) {
|
||||
idxs = append(idxs, i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package browsing
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"slices"
|
||||
|
||||
"github.com/dweymouth/supersonic/backend"
|
||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||
@@ -183,7 +184,7 @@ func (a *PlaylistPage) doSetNewTrackOrder(op sharedutil.TrackReorderOp) {
|
||||
ids := a.tracklist.SelectedTrackIDs()
|
||||
idxs := make([]int, 0, len(ids))
|
||||
for i, tr := range a.tracks {
|
||||
if sharedutil.SliceContains(ids, tr.ID) {
|
||||
if slices.Contains(ids, tr.ID) {
|
||||
idxs = append(idxs, i)
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -4,15 +4,15 @@ import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"image/color"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/dweymouth/supersonic/backend"
|
||||
"github.com/dweymouth/supersonic/res"
|
||||
"github.com/dweymouth/supersonic/sharedutil"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
@@ -200,7 +200,7 @@ func (m *MyTheme) Font(style fyne.TextStyle) fyne.Resource {
|
||||
}
|
||||
case fyne.TextStyle{Bold: true}:
|
||||
if m.BoldFont != "" && boldFont == nil {
|
||||
if content, err := ioutil.ReadFile(m.BoldFont); err != nil {
|
||||
if content, err := os.ReadFile(m.BoldFont); err != nil {
|
||||
m.BoldFont = ""
|
||||
} else {
|
||||
normalFont = fyne.NewStaticResource("boldFont", content)
|
||||
@@ -222,7 +222,7 @@ func (m *MyTheme) Size(name fyne.ThemeSizeName) float32 {
|
||||
|
||||
func (m *MyTheme) getVariant() fyne.ThemeVariant {
|
||||
v := DefaultAppearance // default if config has invalid or missing setting
|
||||
if sharedutil.SliceContains(
|
||||
if slices.Contains(
|
||||
[]string{string(AppearanceLight), string(AppearanceDark), string(AppearanceAuto)},
|
||||
m.config.Appearance) {
|
||||
v = AppearanceMode(m.config.Appearance)
|
||||
@@ -242,7 +242,7 @@ func readTTFFile(filepath string) ([]byte, error) {
|
||||
log.Printf("error loading custom font %q: %s", filepath, err.Error())
|
||||
return nil, err
|
||||
}
|
||||
content, err := ioutil.ReadFile(filepath)
|
||||
content, err := os.ReadFile(filepath)
|
||||
if err != nil {
|
||||
log.Printf("error loading custom font %q: %s", filepath, err.Error())
|
||||
}
|
||||
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
"image/color"
|
||||
"io"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"fyne.io/fyne/v2"
|
||||
"fyne.io/fyne/v2/theme"
|
||||
"github.com/dweymouth/supersonic/sharedutil"
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
)
|
||||
|
||||
@@ -109,7 +109,7 @@ func DecodeThemeFile(reader io.Reader) (*ThemeFile, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if theme.SupersonicTheme.Name == "" || !sharedutil.SliceContains(validThemeVersions, theme.SupersonicTheme.Version) {
|
||||
if theme.SupersonicTheme.Name == "" || !slices.Contains(validThemeVersions, theme.SupersonicTheme.Version) {
|
||||
return nil, errors.New("invalid theme file name or version")
|
||||
}
|
||||
if !(theme.SupersonicTheme.SupportsDark || theme.SupersonicTheme.SupportsLight) {
|
||||
@@ -129,7 +129,7 @@ func (t *ThemeFile) SupportsVariant(v fyne.ThemeVariant) bool {
|
||||
|
||||
// Parses a CSS-style #RRGGBB or #RRGGBBAA string
|
||||
func ColorStringToColor(colorStr string) (color.Color, error) {
|
||||
if !strings.HasPrefix(colorStr, "#") || !sharedutil.SliceContains([]int{7, 9}, len(colorStr)) {
|
||||
if !strings.HasPrefix(colorStr, "#") || !slices.Contains([]int{7, 9}, len(colorStr)) {
|
||||
return color.Black, errors.New("invalid color string")
|
||||
}
|
||||
colorBytes := make([]byte, 4)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package util
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
"github.com/dweymouth/supersonic/backend/mediaprovider"
|
||||
"github.com/dweymouth/supersonic/sharedutil"
|
||||
)
|
||||
@@ -69,15 +71,15 @@ func SelectTrackRange(tracks []*TrackListModel, idx int) {
|
||||
tracks[idx].Selected = true
|
||||
return
|
||||
}
|
||||
from := minInt(idx, lastSelected)
|
||||
to := maxInt(idx, lastSelected)
|
||||
from := min(idx, lastSelected)
|
||||
to := max(idx, lastSelected)
|
||||
for i := from; i <= to; i++ {
|
||||
tracks[i].Selected = true
|
||||
}
|
||||
}
|
||||
|
||||
func FindTrackByID(tracks []*TrackListModel, id string) (*mediaprovider.Track, int) {
|
||||
idx := sharedutil.Find(tracks, func(tr *TrackListModel) bool {
|
||||
idx := slices.IndexFunc(tracks, func(tr *TrackListModel) bool {
|
||||
return tr.Track.ID == id
|
||||
})
|
||||
if idx >= 0 {
|
||||
@@ -85,17 +87,3 @@ func FindTrackByID(tracks []*TrackListModel, id string) (*mediaprovider.Track, i
|
||||
}
|
||||
return nil, -1
|
||||
}
|
||||
|
||||
func minInt(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func maxInt(a, b int) int {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ package widgets
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
@@ -49,7 +49,7 @@ func NewAlbumFilterButton(filter *mediaprovider.AlbumFilter, fetchGenresFunc fun
|
||||
genreNames := sharedutil.MapSlice(genres, func(g *mediaprovider.Genre) string {
|
||||
return g.Name
|
||||
})
|
||||
sort.Strings(genreNames)
|
||||
slices.Sort(genreNames)
|
||||
a.genreListChan <- genreNames
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -3,9 +3,9 @@ package widgets
|
||||
import (
|
||||
"image"
|
||||
"image/color"
|
||||
"slices"
|
||||
|
||||
"github.com/dweymouth/supersonic/res"
|
||||
"github.com/dweymouth/supersonic/sharedutil"
|
||||
"github.com/dweymouth/supersonic/ui/layouts"
|
||||
"github.com/dweymouth/supersonic/ui/util"
|
||||
|
||||
@@ -205,7 +205,7 @@ func (g *GridViewItem) createContainer() {
|
||||
}
|
||||
|
||||
func (g *GridViewItem) NeedsUpdate(model GridViewItemModel) bool {
|
||||
return g.itemID != model.ID || !sharedutil.SliceEqual(g.secondaryIDs, model.SecondaryIDs)
|
||||
return g.itemID != model.ID || !slices.Equal(g.secondaryIDs, model.SecondaryIDs)
|
||||
}
|
||||
|
||||
func (g *GridViewItem) Update(model GridViewItemModel) {
|
||||
|
||||
@@ -3,6 +3,7 @@ package widgets
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"slices"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -271,7 +272,7 @@ func (t *Tracklist) Sorting() TracklistSort {
|
||||
func (t *Tracklist) SetSorting(sorting TracklistSort) {
|
||||
if sorting.ColumnName == "" {
|
||||
// nil case - reset current sort
|
||||
if sharedutil.SliceContains(columns, t.sorting.ColumnName) {
|
||||
if slices.Contains(columns, t.sorting.ColumnName) {
|
||||
t.hdr.SetSorting(ListHeaderSort{ColNumber: ColNumber(t.sorting.ColumnName), Type: SortNone})
|
||||
}
|
||||
return
|
||||
@@ -667,7 +668,7 @@ func (t *Tracklist) lenTracks() int {
|
||||
}
|
||||
|
||||
func ColNumber(colName string) int {
|
||||
i := sharedutil.IndexOf(columns, colName)
|
||||
i := slices.Index(columns, colName)
|
||||
if i < 0 {
|
||||
log.Printf("error: Tracklist: invalid column name %s", colName)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user