show What's New dialog when launching updated version
This commit is contained in:
+12
-1
@@ -46,6 +46,8 @@ type App struct {
|
|||||||
appName string
|
appName string
|
||||||
appVersionTag string
|
appVersionTag string
|
||||||
configFile string
|
configFile string
|
||||||
|
|
||||||
|
isFirstLaunch bool // set by config file reader
|
||||||
bgrndCtx context.Context
|
bgrndCtx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
}
|
}
|
||||||
@@ -119,14 +121,23 @@ func StartupApp(appName, displayAppName, appVersionTag, configFile, latestReleas
|
|||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (a *App) IsFirstLaunch() bool {
|
||||||
|
return a.isFirstLaunch
|
||||||
|
}
|
||||||
|
|
||||||
func (a *App) readConfig() {
|
func (a *App) readConfig() {
|
||||||
configdir.MakePath(configdir.LocalConfig(a.appName))
|
configdir.MakePath(configdir.LocalConfig(a.appName))
|
||||||
cfgPath := a.configPath()
|
cfgPath := a.configPath()
|
||||||
|
var cfgExists bool
|
||||||
|
if _, err := os.Stat(cfgPath); err == nil {
|
||||||
|
cfgExists = true
|
||||||
|
}
|
||||||
|
a.isFirstLaunch = !cfgExists
|
||||||
cfg, err := ReadConfigFile(cfgPath, a.appVersionTag)
|
cfg, err := ReadConfigFile(cfgPath, a.appVersionTag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("Error reading app config file: %v", err)
|
log.Printf("Error reading app config file: %v", err)
|
||||||
cfg = DefaultConfig(a.appVersionTag)
|
cfg = DefaultConfig(a.appVersionTag)
|
||||||
if _, err := os.Stat(cfgPath); err == nil {
|
if cfgExists {
|
||||||
backupCfgName := fmt.Sprintf("%s.bak", a.configFile)
|
backupCfgName := fmt.Sprintf("%s.bak", a.configFile)
|
||||||
log.Printf("Config file may be malformed: copying to %s", backupCfgName)
|
log.Printf("Config file may be malformed: copying to %s", backupCfgName)
|
||||||
_ = util.CopyFile(cfgPath, path.Join(configdir.LocalConfig(a.appName), backupCfgName))
|
_ = util.CopyFile(cfgPath, path.Join(configdir.LocalConfig(a.appName), backupCfgName))
|
||||||
|
|||||||
@@ -25,6 +25,7 @@ type AppConfig struct {
|
|||||||
WindowWidth int
|
WindowWidth int
|
||||||
WindowHeight int
|
WindowHeight int
|
||||||
LastCheckedVersion string
|
LastCheckedVersion string
|
||||||
|
LastLaunchedVersion string
|
||||||
EnableSystemTray bool
|
EnableSystemTray bool
|
||||||
CloseToSystemTray bool
|
CloseToSystemTray bool
|
||||||
StartupPage string
|
StartupPage string
|
||||||
@@ -128,6 +129,7 @@ func DefaultConfig(appVersionTag string) *Config {
|
|||||||
WindowWidth: 1000,
|
WindowWidth: 1000,
|
||||||
WindowHeight: 800,
|
WindowHeight: 800,
|
||||||
LastCheckedVersion: appVersionTag,
|
LastCheckedVersion: appVersionTag,
|
||||||
|
LastLaunchedVersion: "",
|
||||||
EnableSystemTray: true,
|
EnableSystemTray: true,
|
||||||
CloseToSystemTray: false,
|
CloseToSystemTray: false,
|
||||||
StartupPage: "Albums",
|
StartupPage: "Albums",
|
||||||
|
|||||||
@@ -14,17 +14,10 @@ import (
|
|||||||
"fyne.io/fyne/v2/app"
|
"fyne.io/fyne/v2/app"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const configFile = "config.toml"
|
||||||
appname = "supersonic"
|
|
||||||
displayName = "Supersonic"
|
|
||||||
appVersion = "0.6.0"
|
|
||||||
appVersionTag = "v" + appVersion
|
|
||||||
configFile = "config.toml"
|
|
||||||
latestReleaseURL = "https://github.com/dweymouth/supersonic/releases/latest"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
myApp, err := backend.StartupApp(appname, displayName, appVersionTag, configFile, latestReleaseURL)
|
myApp, err := backend.StartupApp(res.AppName, res.DisplayName, res.AppVersionTag, configFile, res.LatestReleaseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("fatal startup error: %v", err.Error())
|
log.Fatalf("fatal startup error: %v", err.Error())
|
||||||
}
|
}
|
||||||
@@ -40,7 +33,7 @@ func main() {
|
|||||||
if h <= 1 {
|
if h <= 1 {
|
||||||
h = 800
|
h = 800
|
||||||
}
|
}
|
||||||
mainWindow := ui.NewMainWindow(fyneApp, appname, displayName, appVersion, myApp, fyne.NewSize(w, h))
|
mainWindow := ui.NewMainWindow(fyneApp, res.AppName, res.DisplayName, res.AppVersion, myApp, fyne.NewSize(w, h))
|
||||||
myApp.OnReactivate = mainWindow.Show
|
myApp.OnReactivate = mainWindow.Show
|
||||||
myApp.OnExit = func() {
|
myApp.OnExit = func() {
|
||||||
saveWindowSize(myApp.Config, mainWindow.Window)
|
saveWindowSize(myApp.Config, mainWindow.Window)
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package res
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"runtime"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
AppName = "supersonic"
|
||||||
|
DisplayName = "Supersonic"
|
||||||
|
AppVersion = "0.6.0"
|
||||||
|
AppVersionTag = "v" + AppVersion
|
||||||
|
ConfigFile = "config.toml"
|
||||||
|
GithubURL = "https://github.com/dweymouth/supersonic"
|
||||||
|
LatestReleaseURL = GithubURL + "/releases/latest"
|
||||||
|
KofiURL = "https://ko-fi.com/dweymouth"
|
||||||
|
)
|
||||||
|
|
||||||
|
func shortcutKey() string {
|
||||||
|
if runtime.GOOS == "darwin" {
|
||||||
|
return "Cmd"
|
||||||
|
}
|
||||||
|
return "Ctrl"
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
WhatsAdded = fmt.Sprintf(`
|
||||||
|
### Added
|
||||||
|
* New "Quick search" feature to search entire library from anywhere (%s+G shortcut)
|
||||||
|
* Support for loading WEBP images
|
||||||
|
* UI Refresh from migrating to Fyne 2.4
|
||||||
|
* New [custom theme](https://github.com/dweymouth/supersonic/wiki/Custom-Themes) color keys: Hyperlink and PageHeader (theme file syntax "0.2")
|
||||||
|
* Added playback setting to force-disable server transcoding`, shortcutKey())
|
||||||
|
|
||||||
|
WhatsFixed = `
|
||||||
|
### Fixed
|
||||||
|
* UI hang when playback slow to begin after clicking on grid view play buttons
|
||||||
|
* Crash when removing from the currently playing track to end of play queue`
|
||||||
|
)
|
||||||
@@ -66,8 +66,8 @@ func (a *AboutDialog) buildMainTabContainer(version string) *fyne.Container {
|
|||||||
ts := license.Segments[0].(*widget.TextSegment)
|
ts := license.Segments[0].(*widget.TextSegment)
|
||||||
ts.Style.TextStyle.Bold = true
|
ts.Style.TextStyle.Bold = true
|
||||||
ts.Style.Alignment = fyne.TextAlignCenter
|
ts.Style.Alignment = fyne.TextAlignCenter
|
||||||
ghUrl, _ := url.Parse("https://github.com/dweymouth/supersonic")
|
ghUrl, _ := url.Parse(res.GithubURL)
|
||||||
kofiUrl, _ := url.Parse("https://ko-fi.com/dweymouth")
|
kofiUrl, _ := url.Parse(res.KofiURL)
|
||||||
githubKofi := container.NewCenter(
|
githubKofi := container.NewCenter(
|
||||||
container.New(&layouts.HboxCustomPadding{DisableThemePad: true, ExtraPad: -10},
|
container.New(&layouts.HboxCustomPadding{DisableThemePad: true, ExtraPad: -10},
|
||||||
widget.NewHyperlink("Github page", ghUrl),
|
widget.NewHyperlink("Github page", ghUrl),
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package dialogs
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/url"
|
||||||
|
|
||||||
|
"fyne.io/fyne/v2"
|
||||||
|
"fyne.io/fyne/v2/container"
|
||||||
|
"fyne.io/fyne/v2/widget"
|
||||||
|
"github.com/dweymouth/supersonic/res"
|
||||||
|
"github.com/dweymouth/supersonic/ui/layouts"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WhatsNewDialog struct {
|
||||||
|
widget.BaseWidget
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWhatsNewDialog() *WhatsNewDialog {
|
||||||
|
w := &WhatsNewDialog{}
|
||||||
|
w.ExtendBaseWidget(w)
|
||||||
|
return w
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WhatsNewDialog) CreateRenderer() fyne.WidgetRenderer {
|
||||||
|
objects := container.NewVBox()
|
||||||
|
if res.WhatsAdded != "" {
|
||||||
|
added := widget.NewRichTextFromMarkdown(res.WhatsAdded)
|
||||||
|
added.Wrapping = fyne.TextWrapWord
|
||||||
|
objects.Add(added)
|
||||||
|
}
|
||||||
|
if res.WhatsFixed != "" {
|
||||||
|
fixed := widget.NewRichTextFromMarkdown(res.WhatsFixed)
|
||||||
|
fixed.Wrapping = fyne.TextWrapWord
|
||||||
|
objects.Add(fixed)
|
||||||
|
}
|
||||||
|
|
||||||
|
ghUrl, _ := url.Parse(res.GithubURL)
|
||||||
|
kofiUrl, _ := url.Parse(res.KofiURL)
|
||||||
|
githubKofi := container.NewCenter(
|
||||||
|
container.New(&layouts.HboxCustomPadding{DisableThemePad: true, ExtraPad: -10},
|
||||||
|
widget.NewHyperlink("Github page", ghUrl),
|
||||||
|
widget.NewLabel("·"),
|
||||||
|
widget.NewHyperlink("Support the project", kofiUrl)))
|
||||||
|
objects.Add(githubKofi)
|
||||||
|
|
||||||
|
c := container.NewVScroll(objects)
|
||||||
|
return widget.NewSimpleRenderer(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *WhatsNewDialog) MinSize() fyne.Size {
|
||||||
|
return fyne.NewSize(400, 250)
|
||||||
|
}
|
||||||
+12
-2
@@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/dweymouth/supersonic/res"
|
"github.com/dweymouth/supersonic/res"
|
||||||
"github.com/dweymouth/supersonic/ui/browsing"
|
"github.com/dweymouth/supersonic/ui/browsing"
|
||||||
"github.com/dweymouth/supersonic/ui/controller"
|
"github.com/dweymouth/supersonic/ui/controller"
|
||||||
|
"github.com/dweymouth/supersonic/ui/dialogs"
|
||||||
"github.com/dweymouth/supersonic/ui/os"
|
"github.com/dweymouth/supersonic/ui/os"
|
||||||
"github.com/dweymouth/supersonic/ui/theme"
|
"github.com/dweymouth/supersonic/ui/theme"
|
||||||
|
|
||||||
@@ -93,8 +94,13 @@ func NewMainWindow(fyneApp fyne.App, appName, displayAppName, appVersion string,
|
|||||||
app.ServerManager.OnServerConnected(func() {
|
app.ServerManager.OnServerConnected(func() {
|
||||||
m.BrowsingPane.EnableNavigationButtons()
|
m.BrowsingPane.EnableNavigationButtons()
|
||||||
m.Router.NavigateTo(m.StartupPage())
|
m.Router.NavigateTo(m.StartupPage())
|
||||||
// check if found new version on startup
|
// check if launching new version, else if found available update on startup
|
||||||
if t := app.UpdateChecker.VersionTagFound(); t != "" && t != app.Config.Application.LastCheckedVersion {
|
if l := app.Config.Application.LastLaunchedVersion; app.VersionTag() != l {
|
||||||
|
if !app.IsFirstLaunch() {
|
||||||
|
m.ShowWhatsNewDialog()
|
||||||
|
}
|
||||||
|
m.App.Config.Application.LastLaunchedVersion = app.VersionTag()
|
||||||
|
} else if t := app.UpdateChecker.VersionTagFound(); t != "" && t != app.Config.Application.LastCheckedVersion {
|
||||||
if t != app.VersionTag() {
|
if t != app.VersionTag() {
|
||||||
m.ShowNewVersionDialog(displayAppName, t)
|
m.ShowNewVersionDialog(displayAppName, t)
|
||||||
}
|
}
|
||||||
@@ -202,6 +208,10 @@ func (m *MainWindow) ShowNewVersionDialog(appName, versionTag string) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *MainWindow) ShowWhatsNewDialog() {
|
||||||
|
dialog.ShowCustom("What's new in "+res.AppVersion, "Close", dialogs.NewWhatsNewDialog(), m.Window)
|
||||||
|
}
|
||||||
|
|
||||||
func (m *MainWindow) addNavigationButtons() {
|
func (m *MainWindow) addNavigationButtons() {
|
||||||
m.BrowsingPane.AddNavigationButton(theme.NowPlayingIcon, func() {
|
m.BrowsingPane.AddNavigationButton(theme.NowPlayingIcon, func() {
|
||||||
m.Router.NavigateTo(controller.NowPlayingRoute(""))
|
m.Router.NavigateTo(controller.NowPlayingRoute(""))
|
||||||
|
|||||||
Reference in New Issue
Block a user