Official plugins
Updater
An update window in the manner of Sparkle, which checks for updates and offers to install them.
The updater plugin gives an app the update window that Mac users know from
Sparkle, on every platform: it checks for updates in the background, shows
the release notes of a new version and offers to install it, skip it or
remind the user later, then downloads it with a progress bar and relaunches
the app into it. It is all Go, with no npm package, and works in apps of
web pages and of native UI alike. Its window is a web page, or
native UI with native.Plugin, for apps that show no web
page at all.
It is built on mygo.Updater, so the app must be built with updates: see
auto-updates to sign and publish them.
Set up
Use the plugin in Go:
import (
"github.com/egoist/mygo"
"github.com/egoist/mygo/plugins/updater"
)
func main() {
mygo.Use(updater.Plugin)
// ...
}- It checks in the background once a day, the first time 10 seconds after launch when a check is due. When a new version is out, a window shows its release notes and offers Install Update, Remind Me Later and Skip This Version. Background checks do not offer a skipped version again, but offer the next one.
- Installing downloads the update with a progress bar, then offers to relaunch; otherwise the update runs at the next launch.
- With the window's "Automatically download and install updates in the future" checked, background checks install updates without asking, and they run at the next launch.
Builds that cannot update themselves, such as development builds and apps installed by a package manager, never check in the background, and the window says why when the user checks.
Checking from the menu
updater.CheckForUpdates() checks as the user asked: the window shows at
once, and says when the app is up to date or the check failed. It also
shows updates the user skipped. updater.MenuItem() is a "Check for
Updates…" item that calls it, which goes after About on macOS:
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},
}))A button of the app's page can call CheckForUpdates through a bound
method, too. While a check is under way, calling it again brings its
window to the front.
Options
updater.New takes options instead of the defaults of updater.Plugin:
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
}))Intervalis the time between background checks, a day by default.DisableAutomaticChecksturns background checks off untilSetAutomaticChecks(true), for apps that ask the user first or only check from the menu.Iconis the PNG image of the window; by default,icon.pngamong the app's resources, the icon thatmygo builduses, when there is one.LanguageandStringschoose and change the window's texts (see languages).
Preferences
The user's choices are kept in updater.json in PathUserData.
AutomaticChecks and AutomaticDownloads read them and
SetAutomaticChecks and SetAutomaticDownloads change them, for a
preferences page; LastCheck returns when the app last checked.
OnChange calls a function on the main thread whenever one of them
changed, after a check or an answer in the update window as well, so the
page can show them again:
// UpdatePreferences tells the preferences page what they are now.
var UpdatePreferences = mygo.NewEvent[Prefs]("update-preferences")
updater.OnChange(func() {
UpdatePreferences.Broadcast(Prefs{
AutomaticChecks: updater.AutomaticChecks(),
AutomaticDownloads: updater.AutomaticDownloads(),
LastCheck: updater.LastCheck(),
})
})Sparkle asks on the second launch whether to check automatically: apps
that want to ask set DisableAutomaticChecks and call SetAutomaticChecks
with the answer.
Languages
The window speaks the user's language (App.Locale) when the plugin has
it: English, Chinese (Simplified and Traditional), Dutch, French, German,
Italian, Japanese, Korean, Polish, Portuguese (Brazil), Russian, Spanish,
Turkish and Ukrainian, with their decimal marks and units ("1,5 Mo").
Other languages get English. Language picks one, such as the language the
app itself shows, and Strings changes texts or adds languages, by language
tag; the fields an app leaves empty keep the plugin's texts:
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" /* … */},
},
}))Some texts are formats, such as AvailableMessage, whose arguments are the
app's name, the new version and the running one: indexed verbs (%[2]s)
let a language order them. mygo.Use fails when a format does not fit its
arguments. go doc github.com/egoist/mygo/plugins/updater.Strings lists
the texts and the arguments of the formats.
Languages written from right to left, such as Arabic and Hebrew, get a mirrored window, and release notes take the direction of the language they are written in.
Native UI
The window of updater.Plugin is a web page, so it needs WebKitGTK on
Linux and the WebView2 Runtime on Windows 10 even in an app whose own
windows all show native UI. Package native draws the same
window in native UI instead, and needs no webview:
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{...})
// ...
}It takes the same options and speaks the same languages, and everything
else is package updater's: updater.MenuItem(),
updater.CheckForUpdates() and the preferences work as with
updater.Plugin. Use one of the two plugins only. The window looks the
same; its release notes are the same Markdown, with text to select and
links that open in the browser.
Your own update UI
The window is one way to offer updates. For an interface of your own, such
as a banner in the app's page, use mygo.Updater instead of the plugin:
see your own update UI.