add updater

This commit is contained in:
aynakeya
2024-05-06 08:17:30 +08:00
parent 68c7c591ff
commit f24b3e73fb
10 changed files with 130 additions and 85 deletions

View File

@@ -276,6 +276,10 @@
"en": "Show", "en": "Show",
"zh-CN": "打开" "zh-CN": "打开"
}, },
"gui.update.already_latest_version": {
"en": "no update available",
"zh-CN": "没有可用更新"
},
"gui.update.new_version": { "gui.update.new_version": {
"en": "New Version Available", "en": "New Version Available",
"zh-CN": "有新版本可用" "zh-CN": "有新版本可用"

15
core/events/updater.go Normal file
View File

@@ -0,0 +1,15 @@
package events
import "AynaLivePlayer/core/model"
const CheckUpdateCmd = "cmd.update.check"
type CheckUpdateCmdEvent struct {
}
const CheckUpdateResultUpdate = "update.update.check"
type CheckUpdateResultUpdateEvent struct {
HasUpdate bool
Info model.VersionInfo
}

View File

@@ -114,28 +114,16 @@ func (b *bascicConfig) CreatePanel() fyne.CanvasObject {
&config.General.PlayNextOnFail, &config.General.PlayNextOnFail,
config.General.PlayNextOnFail), config.General.PlayNextOnFail),
) )
//checkUpdateBox := container.NewHBox( checkUpdateBox := container.NewHBox(
// widget.NewLabel(i18n.T("gui.config.basic.auto_check_update")), widget.NewLabel(i18n.T("gui.config.basic.auto_check_update")),
// component.NewCheckOneWayBinding( component.NewCheckOneWayBinding(
// i18n.T("gui.config.basic.auto_check_update.prompt"), i18n.T("gui.config.basic.auto_check_update.prompt"),
// &config.General.AutoCheckUpdate, &config.General.AutoCheckUpdate,
// config.General.AutoCheckUpdate), config.General.AutoCheckUpdate),
//) )
//checkUpdateBtn := widget.NewButton(i18n.T("gui.config.basic.check_update"), func() { checkUpdateBtn := widget.NewButton(i18n.T("gui.config.basic.check_update"), func() {
// err := API.App().CheckUpdate() global.EventManager.CallA(events.CheckUpdateCmd, events.CheckUpdateCmdEvent{})
// if err != nil { })
// showDialogIfError(err) b.panel = container.NewVBox(randomPlaylist, skipWhenErr, outputDevice, checkUpdateBox, checkUpdateBtn)
// return
// }
// if API.App().LatestVersion().Version > API.App().Version().Version {
// dialog.ShowCustom(
// i18n.T("gui.update.new_version"),
// "OK",
// widget.NewRichTextFromMarkdown(API.App().LatestVersion().Info),
// MainWindow)
// }
//})
//b.panel = container.NewVBox(randomPlaylist, outputDevice, skipPlaylist, skipWhenErr, checkUpdateBox, checkUpdateBtn)
b.panel = container.NewVBox(randomPlaylist, skipWhenErr, outputDevice)
return b.panel return b.panel
} }

View File

@@ -78,28 +78,9 @@ func Initialize() {
dialog.ShowError(err, MainWindow) dialog.ShowError(err, MainWindow)
}) })
checkUpdate()
MainWindow.SetFixedSize(true) MainWindow.SetFixedSize(true)
if config.General.ShowSystemTray { if config.General.ShowSystemTray {
setupSysTray() setupSysTray()
} }
} }
//
//func checkUpdate() {
// l().Info("checking updates...")
// err := API.App().CheckUpdate()
// if err != nil {
// showDialogIfError(err)
// l().Warnf("check update failed", err)
// return
// }
// l().Infof("latest version: v%s", API.App().LatestVersion().Version)
// if API.App().LatestVersion().Version > API.App().Version().Version {
// l().Info("new update available")
// dialog.ShowCustom(
// i18n.T("gui.update.new_version"),
// "OK",
// widget.NewRichTextFromMarkdown(API.App().LatestVersion().Info),
// MainWindow)
// }
//}

31
gui/updater.go Normal file
View File

@@ -0,0 +1,31 @@
package gui
import (
"AynaLivePlayer/core/events"
"AynaLivePlayer/global"
"AynaLivePlayer/pkg/event"
"AynaLivePlayer/pkg/i18n"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/widget"
)
func checkUpdate() {
global.EventManager.RegisterA(
events.CheckUpdateResultUpdate, "gui.updater.check_update", func(event *event.Event) {
data := event.Data.(events.CheckUpdateResultUpdateEvent)
msg := data.Info.Version.String() + "\n\n\n" + data.Info.Info
if data.HasUpdate {
dialog.ShowCustom(
i18n.T("gui.update.new_version"),
"OK",
widget.NewRichTextFromMarkdown(msg),
MainWindow)
} else {
dialog.ShowCustom(
i18n.T("gui.update.already_latest_version"),
"OK",
widget.NewRichTextFromMarkdown(""),
MainWindow)
}
})
}

View File

@@ -7,6 +7,7 @@ import (
"AynaLivePlayer/internal/playlist" "AynaLivePlayer/internal/playlist"
"AynaLivePlayer/internal/plugins" "AynaLivePlayer/internal/plugins"
"AynaLivePlayer/internal/source" "AynaLivePlayer/internal/source"
"AynaLivePlayer/internal/updater"
"AynaLivePlayer/plugin/diange" "AynaLivePlayer/plugin/diange"
"AynaLivePlayer/plugin/durationmgmt" "AynaLivePlayer/plugin/durationmgmt"
"AynaLivePlayer/plugin/qiege" "AynaLivePlayer/plugin/qiege"
@@ -28,6 +29,7 @@ func Initialize() {
durationmgmt.NewMaxDuration(), durationmgmt.NewMaxDuration(),
wshub.NewWsHub(), wshub.NewWsHub(),
) )
updater.Initialize()
} }
func Stop() { func Stop() {

View File

@@ -1,41 +0,0 @@
package todo
import (
"AynaLivePlayer/core/model"
"AynaLivePlayer/pkg/config"
"errors"
"fmt"
"github.com/go-resty/resty/v2"
"github.com/tidwall/gjson"
)
type AppBilibiliChannel struct {
latestVersion model.Version
}
func (app *AppBilibiliChannel) Version() model.VersionInfo {
return model.VersionInfo{
model.Version(config.Version), "",
}
}
func (app *AppBilibiliChannel) LatestVersion() model.VersionInfo {
return model.VersionInfo{
app.latestVersion,
fmt.Sprintf("v%s\n\n[https://play-live.bilibili.com/details/1661006726438](https://play-live.bilibili.com/details/1661006726438)", app.latestVersion),
}
}
func (app *AppBilibiliChannel) CheckUpdate() error {
uri := "https://api.live.bilibili.com/xlive/virtual-interface/v1/app/detail?app_id=1661006726438"
resp, err := resty.New().R().Get(uri)
if err != nil {
return err
}
lv := model.VersionFromString(gjson.ParseBytes(resp.Body()).Get("data.version").String())
if lv == 0 {
return errors.New("failed to get latest version")
}
app.latestVersion = lv
return nil
}

View File

@@ -0,0 +1,63 @@
package updater
import (
"AynaLivePlayer/core/events"
"AynaLivePlayer/core/model"
"AynaLivePlayer/global"
"AynaLivePlayer/pkg/config"
"AynaLivePlayer/pkg/event"
"AynaLivePlayer/pkg/logger"
"github.com/go-resty/resty/v2"
"github.com/tidwall/gjson"
"strconv"
)
var log logger.ILogger = nil
func Initialize() {
log = global.Logger.WithPrefix("internal.updater")
if config.General.AutoCheckUpdate {
go func() {
info, hasUpdate := CheckUpdate()
if !hasUpdate {
return
}
global.EventManager.CallA(
events.CheckUpdateResultUpdate,
events.CheckUpdateResultUpdateEvent{
HasUpdate: hasUpdate,
Info: info,
})
}()
}
global.EventManager.RegisterA(
events.CheckUpdateCmd, "internal.updater.handle",
func(evt *event.Event) {
info, hasUpdate := CheckUpdate()
global.EventManager.CallA(
events.CheckUpdateResultUpdate,
events.CheckUpdateResultUpdateEvent{
HasUpdate: hasUpdate,
Info: info,
})
})
}
func CheckUpdate() (model.VersionInfo, bool) {
uri := config.General.InfoApiServer + "/api/version/check_update"
resp, err := resty.New().R().SetQueryParam("client_version", strconv.Itoa(int(config.Version))).Get(uri)
if err != nil {
log.Errorf("failed to check update: %s", err.Error())
return model.VersionInfo{}, false
}
result := gjson.ParseBytes(resp.Body())
if !result.Get("data.has_update").Bool() {
log.Infof("no update available")
return model.VersionInfo{}, false
}
log.Infof("new version available: %s", model.Version(result.Get("data.latest.version").Uint()).String())
return model.VersionInfo{
Version: model.Version(result.Get("data.latest.version").Uint()),
Info: result.Get("data.latest.note").String(),
}, true
}

View File

@@ -10,7 +10,7 @@ import (
const ( const (
ProgramName = "卡西米尔唱片机" ProgramName = "卡西米尔唱片机"
Version uint32 = 0x010005 Version uint32 = 0x010006
) )
const ( const (

View File

@@ -5,6 +5,7 @@ type _GeneralConfig struct {
Width float32 Width float32
Height float32 Height float32
Language string Language string
InfoApiServer string
AutoCheckUpdate bool AutoCheckUpdate bool
ShowSystemTray bool ShowSystemTray bool
PlayNextOnFail bool PlayNextOnFail bool
@@ -17,6 +18,7 @@ func (c *_GeneralConfig) Name() string {
var General = &_GeneralConfig{ var General = &_GeneralConfig{
Language: "zh-CN", Language: "zh-CN",
ShowSystemTray: false, ShowSystemTray: false,
InfoApiServer: "http://localhost:9090",
AutoCheckUpdate: true, AutoCheckUpdate: true,
Width: 960, Width: 960,
Height: 480, Height: 480,