diff --git a/main.go b/main.go index 63dfbe3..d2556d1 100644 --- a/main.go +++ b/main.go @@ -37,7 +37,7 @@ func main() { if h <= 1 { h = 800 } - mainWindow := ui.NewMainWindow(fyneApp, displayName, appVersion, myApp, fyne.NewSize(w, h)) + mainWindow := ui.NewMainWindow(fyneApp, appname, displayName, appVersion, myApp, fyne.NewSize(w, h)) myApp.OnReactivate = mainWindow.Show go func() { diff --git a/ui/controller/controller.go b/ui/controller/controller.go index 951f7ca..200de35 100644 --- a/ui/controller/controller.go +++ b/ui/controller/controller.go @@ -441,14 +441,14 @@ func (c *Controller) ShowAboutDialog() { pop.Show() } -func (c *Controller) ShowSettingsDialog(themeUpdateCallbk func()) { +func (c *Controller) ShowSettingsDialog(themeUpdateCallbk func(), themeFiles map[string]string) { devs, err := c.App.Player.ListAudioDevices() if err != nil { log.Printf("error listing audio devices: %v", err) devs = []player.AudioDevice{{Name: "auto", Description: "Autoselect device"}} } - dlg := dialogs.NewSettingsDialog(c.App.Config, devs, c.MainWindow) + dlg := dialogs.NewSettingsDialog(c.App.Config, devs, themeFiles, c.MainWindow) dlg.OnReplayGainSettingsChanged = func() { c.App.PlaybackManager.SetReplayGainOptions(c.App.Config.ReplayGain) } diff --git a/ui/dialogs/settingsdialog.go b/ui/dialogs/settingsdialog.go index 0e8dbc2..b1020a4 100644 --- a/ui/dialogs/settingsdialog.go +++ b/ui/dialogs/settingsdialog.go @@ -38,14 +38,15 @@ type SettingsDialog struct { config *backend.Config audioDevices []player.AudioDevice + themeFiles map[string]string // filename -> displayName promptText *widget.RichText content fyne.CanvasObject } // TODO: having this depend on the player package for the AudioDevice type is kinda gross. Refactor. -func NewSettingsDialog(config *backend.Config, audioDeviceList []player.AudioDevice, window fyne.Window) *SettingsDialog { - s := &SettingsDialog{config: config, audioDevices: audioDeviceList} +func NewSettingsDialog(config *backend.Config, audioDeviceList []player.AudioDevice, themeFileList map[string]string, window fyne.Window) *SettingsDialog { + s := &SettingsDialog{config: config, audioDevices: audioDeviceList, themeFiles: themeFileList} s.ExtendBaseWidget(s) tabs := container.NewAppTabs( @@ -69,19 +70,39 @@ func NewSettingsDialog(config *backend.Config, audioDeviceList []player.AudioDev } func (s *SettingsDialog) createGeneralTab() *container.TabItem { - themeSelect := widget.NewSelect([]string{ - string(myTheme.AppearanceDark), - string(myTheme.AppearanceLight), - string(myTheme.AppearanceAuto)}, nil) - themeSelect.OnChanged = func(_ string) { - s.config.Theme.Appearance = themeSelect.Options[themeSelect.SelectedIndex()] + themeNames := []string{"Default"} + themeFileNames := []string{""} + i, selIndex := 1, 0 + for filename, displayname := range s.themeFiles { + themeFileNames = append(themeFileNames, filename) + themeNames = append(themeNames, displayname) + if strings.EqualFold(filename, s.config.Theme.ThemeFile) { + selIndex = i + } + i++ + } + + themeFileSelect := widget.NewSelect(themeNames, nil) + themeFileSelect.SetSelectedIndex(selIndex) + themeFileSelect.OnChanged = func(_ string) { + s.config.Theme.ThemeFile = themeFileNames[themeFileSelect.SelectedIndex()] if s.OnThemeSettingChanged != nil { s.OnThemeSettingChanged() } } - themeSelect.SetSelected(s.config.Theme.Appearance) - if themeSelect.Selected == "" { - themeSelect.SetSelectedIndex(0) + themeModeSelect := widget.NewSelect([]string{ + string(myTheme.AppearanceDark), + string(myTheme.AppearanceLight), + string(myTheme.AppearanceAuto)}, nil) + themeModeSelect.OnChanged = func(_ string) { + s.config.Theme.Appearance = themeModeSelect.Options[themeModeSelect.SelectedIndex()] + if s.OnThemeSettingChanged != nil { + s.OnThemeSettingChanged() + } + } + themeModeSelect.SetSelected(s.config.Theme.Appearance) + if themeModeSelect.Selected == "" { + themeModeSelect.SetSelectedIndex(0) } startupPage := widget.NewSelect(backend.SupportedStartupPages, func(choice string) { @@ -183,8 +204,11 @@ func (s *SettingsDialog) createGeneralTab() *container.TabItem { scrobbleEnabled.Checked = s.config.Scrobbling.Enabled return container.NewTabItem("General", container.NewVBox( - container.New(layout.NewFormLayout(), - widget.NewLabel("Appearance"), container.NewGridWithColumns(2, themeSelect), + container.NewBorder(nil, nil, widget.NewLabel("Theme"), /*left*/ + container.NewHBox(widget.NewLabel("Mode"), themeModeSelect, util.NewHSpace(5)), // right + themeFileSelect, // center + ), + container.NewHBox( widget.NewLabel("Startup page"), container.NewGridWithColumns(2, startupPage), ), container.NewHBox(systemTrayEnable, closeToTray), diff --git a/ui/mainwindow.go b/ui/mainwindow.go index 1522215..be0d54e 100644 --- a/ui/mainwindow.go +++ b/ui/mainwindow.go @@ -3,6 +3,7 @@ package ui import ( "fmt" + "github.com/20after4/configdir" "github.com/dweymouth/supersonic/backend" "github.com/dweymouth/supersonic/backend/mediaprovider" "github.com/dweymouth/supersonic/res" @@ -49,12 +50,12 @@ type MainWindow struct { container *fyne.Container } -func NewMainWindow(fyneApp fyne.App, appName, appVersion string, app *backend.App, size fyne.Size) MainWindow { +func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string, app *backend.App, size fyne.Size) MainWindow { m := MainWindow{ App: app, - Window: fyneApp.NewWindow(appName), + Window: fyneApp.NewWindow(displayAppName), BrowsingPane: browsing.NewBrowsingPane(app), - theme: theme.NewMyTheme(&app.Config.Theme), + theme: theme.NewMyTheme(&app.Config.Theme, configdir.LocalConfig(appName, "themes")), } m.theme.NormalFont = app.Config.Application.FontNormalTTF @@ -62,7 +63,7 @@ func NewMainWindow(fyneApp fyne.App, appName, appVersion string, app *backend.Ap fyneApp.Settings().SetTheme(m.theme) if app.Config.Application.EnableSystemTray { - m.SetupSystemTrayMenu(appName, fyneApp) + m.SetupSystemTrayMenu(displayAppName, fyneApp) } m.Controller = &controller.Controller{ AppVersion: appVersion, @@ -82,10 +83,10 @@ func NewMainWindow(fyneApp fyne.App, appName, appVersion string, app *backend.Ap m.Window.Resize(size) app.PlaybackManager.OnSongChange(func(song, _ *mediaprovider.Track) { if song == nil { - m.Window.SetTitle(appName) + m.Window.SetTitle(displayAppName) return } - m.Window.SetTitle(fmt.Sprintf("%s – %s · %s", song.Name, song.ArtistNames[0], appName)) + m.Window.SetTitle(fmt.Sprintf("%s – %s · %s", song.Name, song.ArtistNames[0], displayAppName)) }) app.ServerManager.OnServerConnected(func() { m.BrowsingPane.EnableNavigationButtons() @@ -93,7 +94,7 @@ func NewMainWindow(fyneApp fyne.App, appName, appVersion string, app *backend.Ap // check if found new version on startup if t := app.UpdateChecker.VersionTagFound(); t != "" && t != app.Config.Application.LastCheckedVersion { if t != app.VersionTag() { - m.ShowNewVersionDialog(appName, t) + m.ShowNewVersionDialog(displayAppName, t) } m.App.Config.Application.LastCheckedVersion = t } @@ -101,7 +102,7 @@ func NewMainWindow(fyneApp fyne.App, appName, appVersion string, app *backend.Ap m.App.UpdateChecker.OnUpdatedVersionFound = func() { t := m.App.UpdateChecker.VersionTagFound() if t != app.VersionTag() { - m.ShowNewVersionDialog(appName, t) + m.ShowNewVersionDialog(displayAppName, t) } m.App.Config.Application.LastCheckedVersion = t } @@ -117,10 +118,10 @@ func NewMainWindow(fyneApp fyne.App, appName, appVersion string, app *backend.Ap m.BrowsingPane.AddSettingsMenuItem("Check for Updates", func() { go func() { if t := app.UpdateChecker.CheckLatestVersionTag(); t != "" && t != app.VersionTag() { - m.ShowNewVersionDialog(appName, t) + m.ShowNewVersionDialog(displayAppName, t) } else { dialog.ShowInformation("No new version found", - "You are running the latest version of "+appName, + "You are running the latest version of "+displayAppName, m.Window) } }() @@ -128,7 +129,7 @@ func NewMainWindow(fyneApp fyne.App, appName, appVersion string, app *backend.Ap m.BrowsingPane.AddSettingsMenuItem("Settings...", func() { m.Controller.ShowSettingsDialog(func() { fyneApp.Settings().SetTheme(m.theme) - }) + }, m.theme.ListThemeFiles()) }) m.BrowsingPane.AddSettingsMenuItem("About...", m.Controller.ShowAboutDialog) m.addNavigationButtons() diff --git a/ui/theme/theme.go b/ui/theme/theme.go index 49c311a..4c81700 100644 --- a/ui/theme/theme.go +++ b/ui/theme/theme.go @@ -48,8 +48,8 @@ type MyTheme struct { var _ fyne.Theme = (*MyTheme)(nil) -func NewMyTheme(config *backend.ThemeConfig) *MyTheme { - m := &MyTheme{config: config} +func NewMyTheme(config *backend.ThemeConfig, themeFileDir string) *MyTheme { + m := &MyTheme{config: config, themeFileDir: themeFileDir} m.defaultThemeFile, _ = DecodeThemeFile(bytes.NewReader(res.ResDefaultToml.StaticContent)) m.createThemeIcons() return m @@ -142,9 +142,9 @@ func (m *MyTheme) Icon(name fyne.ThemeIconName) fyne.Resource { func (m *MyTheme) ListThemeFiles() map[string]string { files, _ := filepath.Glob(m.themeFileDir + "/*.toml") result := make(map[string]string) - for _, filename := range files { - if themeFile, err := ReadThemeFile(path.Join(m.themeFileDir, filename)); err == nil { - result[filename] = themeFile.SupersonicTheme.Name + for _, filepath := range files { + if themeFile, err := ReadThemeFile(filepath); err == nil { + result[path.Base(filepath)] = themeFile.SupersonicTheme.Name } } return result