diff --git a/fluXis.Desktop/FluXisGameDesktop.cs b/fluXis.Desktop/FluXisGameDesktop.cs
index 2b6bb5cb..357a2ab3 100644
--- a/fluXis.Desktop/FluXisGameDesktop.cs
+++ b/fluXis.Desktop/FluXisGameDesktop.cs
@@ -58,5 +58,5 @@ protected override void Dispose(bool isDisposing)
}
public override LightController CreateLightController() => new OpenRGBController();
- public override IUpdatePerformer CreateUpdatePerformer() => OperatingSystem.IsWindows() ? new WindowsUpdatePerformer(NotificationManager) : null;
+ public override IUpdatePerformer CreateUpdatePerformer() => OperatingSystem.IsWindows() ? new VelopackUpdatePerformer(NotificationManager) : null;
}
diff --git a/fluXis.Desktop/Program.cs b/fluXis.Desktop/Program.cs
index b5cb7fbc..f7d691f2 100644
--- a/fluXis.Desktop/Program.cs
+++ b/fluXis.Desktop/Program.cs
@@ -12,6 +12,7 @@
using osu.Framework;
using osu.Framework.Localisation;
using osu.Framework.Logging;
+using Velopack;
namespace fluXis.Desktop;
@@ -21,6 +22,8 @@ public static class Program
public static void Main(string[] args)
{
+ VelopackApp.Build().Run();
+
if (args.Contains("--generate-langfiles"))
{
generateDefaultLangfiles();
diff --git a/fluXis.Desktop/VelopackUpdatePerformer.cs b/fluXis.Desktop/VelopackUpdatePerformer.cs
new file mode 100644
index 00000000..6718aa03
--- /dev/null
+++ b/fluXis.Desktop/VelopackUpdatePerformer.cs
@@ -0,0 +1,61 @@
+using fluXis.Game;
+using fluXis.Game.Graphics.Sprites;
+using fluXis.Game.Overlay.Notifications;
+using fluXis.Game.Overlay.Notifications.Tasks;
+using fluXis.Game.Updater;
+using osu.Framework.Logging;
+using Velopack;
+using Velopack.Sources;
+
+namespace fluXis.Desktop;
+
+public partial class VelopackUpdatePerformer : IUpdatePerformer
+{
+ private NotificationManager notifications { get; }
+ private readonly Logger logger = Logger.GetLogger("update");
+
+ public VelopackUpdatePerformer(NotificationManager notifications)
+ {
+ this.notifications = notifications;
+ }
+
+ public void Perform(bool silent, bool beta)
+ {
+ if (FluXisGameBase.IsDebug)
+ {
+ logger.Add("Skipping update in debug.");
+ return;
+ }
+
+ logger.Add("Checking for updates...");
+ var mgr = new UpdateManager(new GithubSource("https://github.com/TeamFluXis/fluXis", "", beta));
+
+ var update = mgr.CheckForUpdates();
+
+ if (update is null)
+ {
+ logger.Add("No update found.");
+
+ if (!silent)
+ notifications.SendText("No updates available.", "You are running the latest version.", FontAwesome6.Solid.Check);
+
+ return;
+ }
+
+ var notification = new TaskNotificationData
+ {
+ Text = "New update available!",
+ TextWorking = "Downloading...",
+ TextFailed = "Failed! Check update.log for more information.",
+ TextFinished = "Done! Starting update..."
+ };
+
+ notifications.AddTask(notification);
+ logger.Add($"Downloading {update.TargetFullRelease.Version}...");
+ mgr.DownloadUpdates(update, i => notification.Progress = i / 100f);
+
+ logger.Add("Applying...");
+ notification.State = LoadingState.Complete;
+ mgr.ApplyUpdatesAndRestart(update);
+ }
+}
diff --git a/fluXis.Desktop/WindowsUpdatePerformer.cs b/fluXis.Desktop/WindowsUpdatePerformer.cs
deleted file mode 100644
index 322cd584..00000000
--- a/fluXis.Desktop/WindowsUpdatePerformer.cs
+++ /dev/null
@@ -1,167 +0,0 @@
-using System;
-using System.Diagnostics;
-using System.IO;
-using System.IO.Compression;
-using System.Linq;
-using System.Runtime.Versioning;
-using fluXis.Game.Overlay.Notifications;
-using fluXis.Game.Overlay.Notifications.Tasks;
-using fluXis.Game.Updater;
-using osu.Framework.IO.Network;
-using osu.Framework.Logging;
-
-namespace fluXis.Desktop;
-
-[SupportedOSPlatform("windows")]
-public partial class WindowsUpdatePerformer : IUpdatePerformer
-{
- private NotificationManager notifications { get; }
- private readonly Logger logger = Logger.GetLogger("update");
-
- private string folder => $"{AppContext.BaseDirectory}";
- private string patcher => @$"{folder}\patcher.exe";
- private string patches => @$"{folder}\patches";
-
- public WindowsUpdatePerformer(NotificationManager notifications)
- {
- this.notifications = notifications;
- }
-
- public void Perform(string version)
- {
- if (string.IsNullOrEmpty(version))
- return;
-
- if (!File.Exists(patcher))
- getPatcher(() => startUpdate(version));
- else
- startUpdate(version);
- }
-
- public void UpdateFromFile(FileInfo file)
- {
- if (!File.Exists(patcher))
- {
- getPatcher(() => UpdateFromFile(file));
- return;
- }
-
- try
- {
- // open the as zip and check if it contains a fluXis.exe
- using var zip = ZipFile.OpenRead(file.FullName);
-
- if (zip.Entries.All(e => e.Name != "fluXis.exe"))
- {
- logger.Add("Invalid update file.");
- notifications.SendError("Invalid update file.");
- return;
- }
-
- // the backslash to forward slash is absolutely needed here
- // else the patcher thinks the closing quote of the folder
- // is escaped since it ends in \
- Process.Start(new ProcessStartInfo
- {
- FileName = patcher,
- UseShellExecute = true,
- Arguments = $"\"{file.FullName.Replace("\\", "/")}\" \"{folder.Replace("\\", "/")}\" ",
- WorkingDirectory = folder
- });
- Environment.Exit(0);
- }
- catch (Exception e)
- {
- logger.Add("Failed to install update.", LogLevel.Error, e);
- notifications.SendError("Failed to install update.", "Check update.log for more information.");
- }
- }
-
- private void startUpdate(string latest)
- {
- var notification = new TaskNotificationData
- {
- Text = "New update available!",
- TextWorking = "Downloading...",
- TextFailed = "Failed! Check update.log for more information.",
- TextFinished = "Done! Starting update..."
- };
-
- notifications.AddTask(notification);
-
- try
- {
- var request = new WebRequest($"https://dl.flux.moe/fluXis/{latest}.zip");
- request.DownloadProgress += (currentBytes, totalBytes) => notification.Progress = (float)currentBytes / totalBytes;
- request.Failed += e =>
- {
- logger.Add($"Failed to download update. {e.Message}", LogLevel.Error, e);
- notifications.SendError("Failed to download update.", "Check update.log for more information.");
- notification.State = LoadingState.Failed;
- };
- request.Finished += () =>
- {
- logger.Add("Downloaded update. Starting update...");
- Directory.CreateDirectory(patches);
-
- var bytes = request.GetResponseData();
- using var stream = new MemoryStream(bytes);
-
- var path = patches + $"/{latest}.zip";
- File.WriteAllBytes(path, bytes);
-
- notification.State = LoadingState.Complete;
- logger.Add("Update complete. Launching patcher...");
- UpdateFromFile(new FileInfo(path));
- };
-
- request.Perform();
- }
- catch (Exception e)
- {
- logger.Add($"Failed to download update. {e.Message}");
- notifications.SendError("Failed to download update.", "Check update.log for more information.");
- notification.State = LoadingState.Failed;
- }
- }
-
- private async void getPatcher(Action callback)
- {
- var notification = new TaskNotificationData
- {
- Text = "Game patcher download",
- TextWorking = "Downloading...",
- TextFailed = "Failed! Check update.log for more information.",
- TextFinished = "Done! Starting update...",
- };
-
- notifications.AddTask(notification);
-
- const string url = "https://dl.flux.moe/fluXis/patcher.exe";
- var request = new WebRequest(url);
- request.DownloadProgress += (currentBytes, totalBytes) => notification.Progress = (float)currentBytes / totalBytes;
- request.Failed += e =>
- {
- logger.Add($"Failed to download patcher. {e.Message}");
- notification.State = LoadingState.Failed;
- };
- request.Finished += () =>
- {
- Directory.CreateDirectory(folder);
-
- var bytes = request.GetResponseData();
- using var stream = new MemoryStream(bytes);
- File.WriteAllBytes(patcher, bytes);
-
- notification.State = LoadingState.Complete;
- callback?.Invoke();
- };
-
- try { await request.PerformAsync(); }
- catch (Exception e)
- {
- logger.Add("Failed to download patcher.", LogLevel.Error, e);
- notification.State = LoadingState.Failed;
- }
- }
-}
diff --git a/fluXis.Desktop/fluXis.Desktop.csproj b/fluXis.Desktop/fluXis.Desktop.csproj
index c048c503..2aef60cd 100644
--- a/fluXis.Desktop/fluXis.Desktop.csproj
+++ b/fluXis.Desktop/fluXis.Desktop.csproj
@@ -19,6 +19,7 @@
+
diff --git a/fluXis.Game/FluXisGameBase.cs b/fluXis.Game/FluXisGameBase.cs
index e0520abe..ca66bc41 100644
--- a/fluXis.Game/FluXisGameBase.cs
+++ b/fluXis.Game/FluXisGameBase.cs
@@ -289,26 +289,15 @@ protected override void LoadComplete()
}, true);
}
- public void PerformUpdateCheck(bool silent, bool forceUpdate = false)
+ public void PerformUpdateCheck(bool silent) => Task.Run(() =>
{
- Task.Run(() =>
- {
- var checker = new UpdateChecker(Config.Get(FluXisSetting.ReleaseChannel));
+ var performer = CreateUpdatePerformer();
- if (forceUpdate || checker.UpdateAvailable)
- {
- var performer = CreateUpdatePerformer();
- var version = checker.LatestVersion;
+ if (performer is null)
+ return;
- if (performer != null)
- performer.Perform(version);
- else
- NotificationManager.SendText($"New update available! ({version})", "Check the github releases to download the latest version.", FontAwesome6.Solid.Download);
- }
- else if (!silent)
- NotificationManager.SendText("No updates available.", "You are running the latest version.", FontAwesome6.Solid.Check);
- });
- }
+ performer.Perform(silent, Config.Get(FluXisSetting.ReleaseChannel) == ReleaseChannel.Beta);
+ });
private Season getSeason()
{
diff --git a/fluXis.Game/Localization/Categories/Settings/SettingsDebugStrings.cs b/fluXis.Game/Localization/Categories/Settings/SettingsDebugStrings.cs
index 5083c337..3a72307c 100644
--- a/fluXis.Game/Localization/Categories/Settings/SettingsDebugStrings.cs
+++ b/fluXis.Game/Localization/Categories/Settings/SettingsDebugStrings.cs
@@ -10,10 +10,6 @@ public class SettingsDebugStrings : LocalizationCategory
public TranslatableString ShowLogOverlay => Get("show-log-overlay", "Show Log Overlay");
public TranslatableString ImportFile => Get("import-file", "Import File");
- public TranslatableString InstallUpdateFromFile => Get("update-from-file", "Install Update From File");
-
- public TranslatableString InstallUpdateFromFileDescription =>
- Get("update-from-file-description", "Installs an update from a .zip file. Be careful from where you download the file from though!");
public TranslatableString LogAPI => Get("log-api", "Log API Responses.");
public TranslatableString LogAPIDescription => Get("log-api-description", "Logs all API request responses to the console and log files. This might contain sensitive info like emails and tokens.");
diff --git a/fluXis.Game/Overlay/Settings/Sections/DebugSection.cs b/fluXis.Game/Overlay/Settings/Sections/DebugSection.cs
index 43d672d1..8a5025d8 100644
--- a/fluXis.Game/Overlay/Settings/Sections/DebugSection.cs
+++ b/fluXis.Game/Overlay/Settings/Sections/DebugSection.cs
@@ -42,20 +42,6 @@ private void load(FrameworkConfigManager frameworkConfig, FluXisConfig config, F
};
}
},
- new SettingsButton
- {
- Label = strings.InstallUpdateFromFile,
- Description = strings.InstallUpdateFromFileDescription,
- ButtonText = "Find",
- Action = () =>
- {
- panels.Content = new FileSelect
- {
- AllowedExtensions = new[] { ".zip" },
- OnFileSelected = file => game.CreateUpdatePerformer()?.UpdateFromFile(file)
- };
- }
- },
new SettingsToggle
{
Label = strings.LogAPI,
diff --git a/fluXis.Game/Overlay/Settings/Sections/General/GeneralUpdatesSection.cs b/fluXis.Game/Overlay/Settings/Sections/General/GeneralUpdatesSection.cs
index 89b4166a..b1ea01c7 100644
--- a/fluXis.Game/Overlay/Settings/Sections/General/GeneralUpdatesSection.cs
+++ b/fluXis.Game/Overlay/Settings/Sections/General/GeneralUpdatesSection.cs
@@ -7,7 +7,6 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Sprites;
-using osu.Framework.Input;
using osu.Framework.Localisation;
namespace fluXis.Game.Overlay.Settings.Sections.General;
@@ -19,8 +18,6 @@ public partial class GeneralUpdatesSection : SettingsSubSection
private SettingsGeneralStrings strings => LocalizationStrings.Settings.General;
- private InputManager inputManager;
-
[BackgroundDependencyLoader]
private void load(FluXisGameBase game)
{
@@ -38,14 +35,8 @@ private void load(FluXisGameBase game)
Label = strings.UpdatesCheck,
Description = strings.UpdatesCheckDescription,
ButtonText = "Check",
- Action = () => game.PerformUpdateCheck(false, inputManager.CurrentState.Keyboard.AltPressed)
+ Action = () => game.PerformUpdateCheck(false)
}
});
}
-
- protected override void LoadComplete()
- {
- base.LoadComplete();
- inputManager = GetContainingInputManager();
- }
}
diff --git a/fluXis.Game/Updater/GitHub/GitHubAsset.cs b/fluXis.Game/Updater/GitHub/GitHubAsset.cs
new file mode 100644
index 00000000..d2004a83
--- /dev/null
+++ b/fluXis.Game/Updater/GitHub/GitHubAsset.cs
@@ -0,0 +1,15 @@
+using Newtonsoft.Json;
+
+namespace fluXis.Game.Updater.GitHub;
+
+public class GitHubAsset
+{
+ [JsonProperty("url")]
+ public string Url { get; set; } = string.Empty;
+
+ [JsonProperty("id")]
+ public int Id { get; set; }
+
+ [JsonProperty("name")]
+ public string Name { get; set; } = string.Empty;
+}
diff --git a/fluXis.Game/Updater/GitHub/GitHubRelease.cs b/fluXis.Game/Updater/GitHub/GitHubRelease.cs
index 0c5c5e9e..b38b849d 100644
--- a/fluXis.Game/Updater/GitHub/GitHubRelease.cs
+++ b/fluXis.Game/Updater/GitHub/GitHubRelease.cs
@@ -1,12 +1,25 @@
+using System;
using Newtonsoft.Json;
namespace fluXis.Game.Updater.GitHub;
public class GitHubRelease
{
+ [JsonProperty("name")]
+ public string Name { get; set; } = "";
+
[JsonProperty("tag_name")]
public string TagName { get; set; } = "";
[JsonProperty("prerelease")]
public bool PreRelease { get; set; }
+
+ [JsonProperty("draft")]
+ public bool Draft { get; set; }
+
+ [JsonProperty("target_commitish")]
+ public string TargetCommitish { get; set; }
+
+ [JsonProperty("assets")]
+ public GitHubAsset[] Assets { get; set; } = Array.Empty();
}
diff --git a/fluXis.Game/Updater/IUpdatePerformer.cs b/fluXis.Game/Updater/IUpdatePerformer.cs
index 4b21789a..cf9771aa 100644
--- a/fluXis.Game/Updater/IUpdatePerformer.cs
+++ b/fluXis.Game/Updater/IUpdatePerformer.cs
@@ -1,5 +1,3 @@
-using System.IO;
-
namespace fluXis.Game.Updater;
///
@@ -10,16 +8,11 @@ public interface IUpdatePerformer
///
/// Performs an update. (If available)
///
- ///
- /// The version to update to.
+ ///
+ /// Whether to show a notification when there is no new update.
///
- public void Perform(string version);
-
- ///
- /// Installs an update from a file.
- ///
- ///
- /// The file to install from.
+ ///
+ /// Whether to include beta versions.
///
- public void UpdateFromFile(FileInfo file);
+ public void Perform(bool silent, bool beta);
}