diff --git a/go.mod b/go.mod index 52dcb83..9f28862 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21.1 require ( github.com/gen2brain/raylib-go/raylib v0.0.0-20241215043839-7a899c5e3aae - weforge.xyz/Spitfire/SPM v0.0.2 + weforge.xyz/Spitfire/SPM v0.1.2 ) require ( diff --git a/go.sum b/go.sum index f0dfdb6..2640b76 100644 --- a/go.sum +++ b/go.sum @@ -17,5 +17,7 @@ gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -weforge.xyz/Spitfire/SPM v0.0.2 h1:VU487KrwK1ldW7cMDGZgUcYPjtb8djG7glQlXg5Do3E= -weforge.xyz/Spitfire/SPM v0.0.2/go.mod h1:LkLCJPROt/UW0Ntlbm1Vk8CpqpBscY0IScfT3PprsC4= +weforge.xyz/Spitfire/SPM v0.1.1 h1:E3bJROvtW8CJNXdZTd0QW8cfxAr/zIxgKIVR7sMBwYg= +weforge.xyz/Spitfire/SPM v0.1.1/go.mod h1:LkLCJPROt/UW0Ntlbm1Vk8CpqpBscY0IScfT3PprsC4= +weforge.xyz/Spitfire/SPM v0.1.2 h1:jY3WvRV5WFE9spne1YFGQNPOnnZqAxnZaa3l57pTigw= +weforge.xyz/Spitfire/SPM v0.1.2/go.mod h1:LkLCJPROt/UW0Ntlbm1Vk8CpqpBscY0IScfT3PprsC4= diff --git a/installer.go b/installer.go index 0cb16f9..b035b18 100644 --- a/installer.go +++ b/installer.go @@ -1,3 +1,5 @@ +//go:build !windows + package main import ( @@ -62,8 +64,8 @@ func (inst *Installer) StartDownloadDecompress() { } spm.UpdateProgress(0, "Downloading specified packages...") - if err := spm.AutoDownloadSpecified(specs); err != nil { - fmt.Println("AutoDownloadSpecifiedPackages failed:", err) + if err := spm.DownloadSpecified(specs); err != nil { + fmt.Println("DownloadSpecifiedPackages failed:", err) inst.LastError = err return } @@ -93,7 +95,7 @@ func (inst *Installer) FinalInstall() { inst.doFinalInstall() } -// doFinalInstall does the actual installation by invoking AutoInstallUpdates. +// doFinalInstall does the actual installation by invoking InstallUpdates. func (inst *Installer) doFinalInstall() { inst.IsInstalling = true inst.PendingInstall = false // we are fulfilling the install now @@ -105,14 +107,7 @@ func (inst *Installer) doFinalInstall() { }() spm.UpdateProgress(0, "Installing updates...") - if err := spm.AutoInstallUpdates(); err != nil { - inst.LastError = err - return - } - - // Register the app in Windows (i.e. create registry entries) - spm.UpdateProgress(0, "Registering app...") - if err := spm.RegisterApp(); err != nil { + if err := spm.InstallUpdates(); err != nil { inst.LastError = err return } diff --git a/installer_win.go b/installer_win.go new file mode 100644 index 0000000..e7e24e3 --- /dev/null +++ b/installer_win.go @@ -0,0 +1,130 @@ +//go:build windows + +package main + +import ( + "fmt" + "runtime" + + spm "weforge.xyz/Spitfire/SPM" +) + +// Installer manages the download, decompression, and installation processes. +type Installer struct { + // Progress info from SPM + Progress int + Task string + + // Internal states + IsDownloading bool + IsInstalling bool + DoneDownload bool + DoneInstall bool + LastError error + PendingInstall bool +} + +// NewInstaller creates a new Installer with initial state. +func NewInstaller() *Installer { + return &Installer{} +} + +// StartDownloadDecompress starts the download and decompression in a background goroutine. +func (inst *Installer) StartDownloadDecompress() { + inst.IsDownloading = true + go func() { + defer func() { + inst.IsDownloading = false + // Signal that download phase is complete. + inst.DoneDownload = (inst.LastError == nil) + // If a final install was requested, go ahead. + if inst.PendingInstall && inst.DoneDownload && !inst.IsInstalling && !inst.DoneInstall { + inst.doFinalInstall() + } + }() + + spm.UpdateProgress(0, "Preparing to download...") + + // Define the package specifications. + specs := []spm.AppIndexEntry{ + { + Name: "spitfire-luncher", + Release: "nightly", + OS: "windows", + Arch: runtime.GOARCH, + Type: "luncher", + }, + { + Name: "spitfire-browser", + Release: "nightly", + OS: "windows", + Arch: runtime.GOARCH, + Type: "browser", + }, + } + + spm.UpdateProgress(0, "Downloading specified packages...") + if err := spm.DownloadSpecified(specs); err != nil { + fmt.Println("DownloadSpecifiedPackages failed:", err) + inst.LastError = err + return + } + + spm.UpdateProgress(0, "Download and decompression complete!") + // Here, update your installer state so FinalInstall() can proceed. + inst.DoneDownload = true + }() +} + +// FinalInstall is called by the UI to request installation. +// If download is done, it runs immediately, otherwise sets PendingInstall=true. +func (inst *Installer) FinalInstall() { + // Already installed or installing => ignore repeated calls. + if inst.IsInstalling || inst.DoneInstall { + return + } + + // If not done downloading, mark that we want to install once finished. + if !inst.DoneDownload { + fmt.Println("Cannot install now: download and decompression not complete -> pending install.") + inst.PendingInstall = true + return + } + + // Otherwise, go ahead and install now. + inst.doFinalInstall() +} + +// doFinalInstall does the actual installation by invoking InstallUpdates. +func (inst *Installer) doFinalInstall() { + inst.IsInstalling = true + inst.PendingInstall = false // we are fulfilling the install now + + go func() { + defer func() { + inst.IsInstalling = false + inst.DoneInstall = (inst.LastError == nil) + }() + + spm.UpdateProgress(0, "Installing updates...") + if err := spm.InstallUpdates(); err != nil { + inst.LastError = err + return + } + + // Register the app in Windows (i.e. create registry entries) + spm.UpdateProgress(0, "Registering app...") + if err := spm.RegisterApp(); err != nil { + inst.LastError = err + return + } + + spm.UpdateProgress(100, "Installation complete!") + }() +} + +// PollProgress fetches the latest progress and task from SPM. +func (inst *Installer) PollProgress() { + p, t := spm.GetProgress() + inst.Progress, inst.Task = p, t +}