Skip to content

Updater(自动更新) ​

updater 插件为应用提供 Mac 用户从 Sparkle 熟悉的那个更新窗口,并且适用于 每个平台:它在后台检查更新,展示新版本的发布说明并提供安装、跳过或稍后 提醒用户,然后带进度条下载它,并重启应用进入新版本。它全部是 Go,没有 npm 包,在 Web 页面应用和原生 UI应用中同样工作。它的 窗口是一个 Web 页面,或者对于完全不显示 Web 页面的应用,用 native.Plugin 以原生 UI 显示。

它基于 mygo.Updater 构建,因此应用必须以启用更新的方式构建:关于签名 与发布,参见自动更新。

设置 ​

在 Go 中使用该插件:

go
import (
	"github.com/egoist/mygo"
	"github.com/egoist/mygo/plugins/updater"
)

func main() {
	mygo.Use(updater.Plugin)
	// ...
}
  • 它在启动 10 秒后在后台检查,之后在应用运行期间每天一次,因此自上次 运行以来发布的新版本会在应用再次打开时显示。当有新版本时,一个窗口 会显示它的发布说明并提供安装更新、稍后提醒和跳过此版本。 后台检查不会再提供被跳过的版本,但会提供下一个版本。
  • 安装会带进度条下载更新,然后提供重启;否则更新会在下次启动时运行。
  • 勾选窗口的"以后自动下载并安装更新"后,后台检查会不经询问地安装更新, 它们会在下次启动时运行。

无法自我更新的构建,例如开发构建和由包管理器安装的应用,从不在后台检查, 并且当用户手动检查时窗口会说明原因。

从菜单检查 ​

updater.CheckForUpdates() 按用户的请求检查:窗口立即显示,并在应用已是 最新或检查失败时说明。它也会显示用户跳过的更新。updater.MenuItem() 是 一个调用它的"检查更新…"项,在 macOS 上放在"关于"之后:

go
mygo.App.SetMenu(mygo.NewMenu([]*mygo.MenuItem{
	{Label: "My App", Submenu: []*mygo.MenuItem{
		{Role: mygo.RoleAbout},
		updater.MenuItem(),
		mygo.Separator(),
		{Role: mygo.RoleQuit},
	}},
	{Role: mygo.RoleEditMenu},
	{Role: mygo.RoleWindowMenu},
}))

应用页面的一个按钮也可以通过绑定方法调用 CheckForUpdates。当检查正在 进行时,再次调用会把它的窗口带到前面。

选项 ​

updater.New 接受选项,取代 updater.Plugin 的默认值:

go
mygo.Use(updater.New(updater.Options{
	Interval:               12 * time.Hour, // between checks (default a day)
	DisableAutomaticChecks: true,           // until SetAutomaticChecks(true)
	Icon:                   iconPNG,        // default: icon.png among the resources
}))
  • Interval 是后台检查之间的时间间隔,默认一天。
  • DisableAutomaticChecks 关闭后台检查,直到调用 SetAutomaticChecks(true), 适用于先询问用户或只从菜单检查的应用。
  • Icon 是窗口的 PNG 图像;默认为应用资源中的 icon.png,即 mygo build 使用的图标(当它存在时)。
  • Language 和 Strings 选择并修改窗口的文本(参见语言)。

偏好设置 ​

用户的选择保存在 PathUserData 中的 updater.json 里。 AutomaticChecks 和 AutomaticDownloads 读取它们,SetAutomaticChecks 和 SetAutomaticDownloads 修改它们,供偏好设置页面使用;LastCheck 返回应用上次检查的时间。每当其中一项改变时,OnChange 会在主线程上调用 一个函数,在检查之后或在更新窗口中作出回答之后同样如此,以便页面重新 显示它们:

go
// UpdatePreferences 把当前的偏好设置告知偏好页面。
var UpdatePreferences = mygo.NewEvent[Prefs]("update-preferences")

updater.OnChange(func() {
	UpdatePreferences.Broadcast(Prefs{
		AutomaticChecks:    updater.AutomaticChecks(),
		AutomaticDownloads: updater.AutomaticDownloads(),
		LastCheck:          updater.LastCheck(),
	})
})

Sparkle 在第二次启动时询问是否自动检查:想要询问的应用设置 DisableAutomaticChecks,并根据回答调用 SetAutomaticChecks。

语言 ​

当插件拥有用户的语言时,窗口就说这种语言(App.Locale):英语、中文 (简体和繁体)、荷兰语、法语、德语、意大利语、日语、韩语、波兰语、葡萄牙 语(巴西)、俄语、西班牙语、土耳其语和乌克兰语,带有它们的小数点和单位 ("1,5 Mo")。其他语言使用英语。Language 选定一种,例如应用自身显示的 语言,Strings 按语言标签修改文本或添加语言;应用留空的字段保留插件的 文本:

go
mygo.Use(updater.New(updater.Options{
	Language: settings.Language, // "" follows the system
	Strings: map[string]updater.Strings{
		"en": {Install: "Update Now"},
		"sv": {Title: "Programuppdatering", Install: "Installera uppdatering" /* … */},
	},
}))

窗口在其检查开始时说应用显示的语言,并在打开期间保持它。在 App.SetLocale 之后,或在应用跟随的用户语言变化时,下一个窗口会采用新 语言,MenuItem 在那之后返回的项也一样:在 App.OnLocaleChanged 中重建 菜单的应用会得到新语言的"检查更新…"。

一些文本是格式化串,例如 AvailableMessage,其参数是应用名、新版本和 正在运行的版本:带索引的动词(%[2]s)让某种语言重排它们。当格式化串与 其参数不符时,mygo.Use 会失败。 go doc github.com/egoist/mygo/plugins/updater.Strings 列出文本和格式化 串的参数。

从右到左书写的语言,例如阿拉伯语和希伯来语,会得到镜像的窗口,发布说明 采用其书写语言的方向。

原生 UI ​

updater.Plugin 的窗口是一个 Web 页面,因此即使在自身窗口全部显示 原生 UI的应用中,它也需要 Linux 上的 WebKitGTK 和 Windows 10 上的 WebView2 Runtime。native 包改为以原生 UI 绘制同一个 窗口,不需要 webview:

go
import (
	"github.com/egoist/mygo"
	"github.com/egoist/mygo/plugins/updater"
	"github.com/egoist/mygo/plugins/updater/native"
)

func main() {
	mygo.Use(native.Plugin) // or native.New(updater.Options{...})
	// ...
}

它接受相同的选项,说相同的语言,其余一切都是 updater 包的: updater.MenuItem()、updater.CheckForUpdates() 和偏好设置与 updater.Plugin 一样工作。只使用两个插件中的一个。窗口看起来相同;它的 发布说明是相同的 Markdown,文本可选中,链接在浏览器中打开。

自定义更新 UI ​

窗口是提供更新的一种方式。对于你自己的界面,例如应用页面中的一个横幅, 使用 mygo.Updater 而不是插件:参见你自己的更新 UI。