diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json new file mode 100644 index 00000000..d591af40 --- /dev/null +++ b/.config/dotnet-tools.json @@ -0,0 +1,12 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "vpk": { + "version": "0.0.359", + "commands": [ + "vpk" + ] + } + } +} \ No newline at end of file diff --git a/.github/wiki/Development-Windows.md b/.github/wiki/Development-Windows.md index 6f8d7eaf..7d31d9cc 100644 --- a/.github/wiki/Development-Windows.md +++ b/.github/wiki/Development-Windows.md @@ -97,11 +97,11 @@ To manually build a release on your machine, run the following command at the ro `dotnet publish /p:Configuration=Release /p:Version=X.X.X /p:PublishProfile=FolderProfile` -You must specific a version in the numeral format of X.X.X (e.g. 1.69.420). Version numbering does not really matter for local release builds. +You must specify a version in the numeral format of X.X.X (e.g. 1.69.420). Version numbering does not really matter for local release builds. -The build will make use of Squirrel and create deltas or full packages, including a Setup file. You can find these files in `/bin/Deployment/Releases/`. +The build will make use of Velopack and create deltas or full packages, including a Setup file. You can find these files in `/bin/Deployment/Releases/`. -You can learn more about the Squirrel deployment process [here](https://github.com/Squirrel/Squirrel.Windows/blob/develop/docs/getting-started/0-overview.md#overview). +You can learn more about the Velopack deployment process [here](https://docs.velopack.io/). # 7. (Optional) Using Visual Studio Code diff --git a/.gitignore b/.gitignore index 8f4bb715..a6925924 100644 --- a/.gitignore +++ b/.gitignore @@ -239,3 +239,7 @@ _Pvt_Extensions # FAKE - F# Make .fake/ Classes/WindowsInterface.resx + + +# Dotnet tool configuration is needed for vpk +!./.config/dotnet-tools.json diff --git a/Classes/Program.cs b/Classes/Program.cs index b79f1290..350c53b3 100644 --- a/Classes/Program.cs +++ b/Classes/Program.cs @@ -11,13 +11,11 @@ using RePlays.Utils; using RePlays.Services; using static RePlays.Utils.Functions; - - +using Velopack; #if !WINDOWS using RePlays.Classes.Utils; using RePlays.Recorders; #else -using Squirrel; using System.Windows.Forms; #endif @@ -25,6 +23,7 @@ namespace RePlays { static class Program { [DllImport("kernel32.dll")] static extern bool AttachConsole(int dwProcessId); + const int ATTACH_PARENT_PROCESS = -1; static readonly ManualResetEventSlim ApplicationExitEvent = new(false); @@ -62,7 +61,8 @@ static void Main(string[] args) { // prevent multiple instances var mutex = new Mutex(true, @"Global\RePlays", out var createdNew); if (!createdNew) { - Logger.WriteLine("RePlays is already running! Exiting the application and bringing the other instance to foreground."); + Logger.WriteLine( + "RePlays is already running! Exiting the application and bringing the other instance to foreground."); try { using (var sender = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)) { sender.Connect(new IPEndPoint(IPAddress.Loopback, 3333)); @@ -73,10 +73,11 @@ static void Main(string[] args) { catch (Exception ex) { Logger.WriteLine($"Socket client exception: {ex.Message}"); } + return; } -#if DEBUG && WINDOWS && !NO_SERVER +#if DEBUG && WINDOWS // this will run our react app if its not already running var startInfo = new ProcessStartInfo { FileName = "cmd.exe", @@ -102,25 +103,30 @@ static void Main(string[] args) { KeybindService.Start(); PurgeTempVideos(); Updater.CheckForUpdates(); -#if WINDOWS - ScreenSize.UpdateMaximumScreenResolution(); - // squirrel configuration + + // Velopack configuration try { - SquirrelAwareApp.HandleEvents( - onInitialInstall: (_, tools) => tools.CreateShortcutForThisExe(), - onAppUpdate: (_, tools) => tools.CreateShortcutForThisExe(), - onAppUninstall: (_, tools) => tools.RemoveShortcutForThisExe() - ); + VelopackApp.Build() + /* Add this line if updating should create a shortcut as well +#if WINDOWS + .WithAfterUpdateFastCallback(v => new Shortcuts().CreateShortcutForThisExe()) +#endif + */ + .Run(); } catch (Exception exception) { Logger.WriteLine(exception.ToString()); } +#if WINDOWS + ScreenSize.UpdateMaximumScreenResolution(); + Application.SetHighDpiMode(HighDpiMode.SystemAware); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new WindowsInterface()); - (Process.GetCurrentProcess()).Kill(); // this is not a clean exit, need to look into why we can't cleanly exit + (Process.GetCurrentProcess()) + .Kill(); // this is not a clean exit, need to look into why we can't cleanly exit #else Directory.SetCurrentDirectory(AppContext.BaseDirectory); //Necessary for libobs in debug(?) SettingsService.LoadSettings(); diff --git a/Classes/Utils/JSONObjects.cs b/Classes/Utils/JSONObjects.cs index 221a3af7..c2f92ab9 100644 --- a/Classes/Utils/JSONObjects.cs +++ b/Classes/Utils/JSONObjects.cs @@ -1,6 +1,9 @@ using System; using System.Collections.Generic; using System.IO; +#if WINDOWS +using Velopack.Windows; +#endif namespace RePlays.Utils { public class VideoList { @@ -51,17 +54,16 @@ public bool launchStartup { _launchStartup = value; #if WINDOWS try { - using (var manager = new Squirrel.UpdateManager(Environment.GetEnvironmentVariable("LocalAppData") + @"\RePlays\packages")) { - if (_launchStartup == true) - manager.CreateShortcutsForExecutable("RePlays.exe", Squirrel.ShortcutLocation.Startup, false); - else - manager.RemoveShortcutsForExecutable("RePlays.exe", Squirrel.ShortcutLocation.Startup); - } + var shortcuts = new Shortcuts(); + if (_launchStartup == true) + shortcuts.CreateShortcut("RePlays.exe", ShortcutLocation.Startup, false, null); + else + shortcuts.DeleteShortcuts("RePlays.exe", ShortcutLocation.Startup); } catch (Exception exception) { Logger.WriteLine("Error: Issue editing program startup setting: " + exception.ToString()); } -#endif +#endif } } private bool _startMinimized = false; diff --git a/Classes/Utils/Messages.cs b/Classes/Utils/Messages.cs index 9119b8d6..afaa5444 100644 --- a/Classes/Utils/Messages.cs +++ b/Classes/Utils/Messages.cs @@ -10,6 +10,7 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using Velopack; using static RePlays.Services.SettingsService; using static RePlays.Utils.Compression; using static RePlays.Utils.Functions; @@ -418,6 +419,10 @@ public static async Task ReceiveMessage(string message) { break; #if WINDOWS case "Restart": { + if (Updater.manager?.IsUpdatePendingRestart ?? false) { + Updater.manager.ApplyUpdatesAndRestart((VelopackAsset)null); + } + string path = Path.Join(GetStartupPath(), @"../RePlays.exe"); string cmdCommand = $"/C timeout /t 1 & start \"\" \"{path}\""; diff --git a/Classes/Utils/Updater.cs b/Classes/Utils/Updater.cs index 1c289122..cd7d68e0 100644 --- a/Classes/Utils/Updater.cs +++ b/Classes/Utils/Updater.cs @@ -1,13 +1,15 @@ using RePlays.Services; -using Squirrel; using System; using System.Threading.Tasks; +using Velopack; +using Velopack.Sources; using static RePlays.Utils.Functions; namespace RePlays.Utils { internal class Updater { public static string currentVersion = "?"; public static string latestVersion = "Offline"; + public static UpdateManager? manager; public static bool applyingUpdate { get; internal set; } [Obsolete] @@ -16,57 +18,63 @@ public static async void CheckForUpdates(bool forceUpdate = false) { Logger.WriteLine($"Currently in the middle of applying an update. Cannot check for updates."); return; } + + bool isNightly = SettingsService.Settings.generalSettings.updateChannel != "Stable"; try { if (forceUpdate) WebMessage.DisplayToast("CheckUpdateProgress", "Checking for updates", "Update", "none", (long)40, (long)100); - using var manager = await UpdateManager.GitHubUpdateManager("https://github.com/lulzsun/RePlays", - prerelease: SettingsService.Settings.generalSettings.updateChannel != "Stable"); + if (manager == null) + manager = new UpdateManager(new GithubSource("https://github.com/lulzsun/RePlays", null, isNightly)); if (forceUpdate) WebMessage.DisplayToast("CheckUpdateProgress", "Checking for updates", "Update", "none", (long)70, (long)100); - if (manager.CurrentlyInstalledVersion() != null) { - currentVersion = manager.CurrentlyInstalledVersion().ToString(); + if (manager.CurrentVersion != null) { + currentVersion = manager.CurrentVersion.ToString(); } - var updateInfo = await manager.CheckForUpdate(SettingsService.Settings.generalSettings.updateChannel != "Stable"); // if nightly, we ignore deltas + + var updateInfo = await manager.CheckForUpdatesAsync(); if (forceUpdate) { - WebMessage.DisplayToast("CheckUpdateProgress", "Checking for updates", "Update", "none", (long)100, (long)100); + WebMessage.DisplayToast("CheckUpdateProgress", "Checking for updates", "Update", "none", (long)100, + (long)100); await Task.Delay(500); WebMessage.DestroyToast("CheckUpdateProgress"); } - latestVersion = updateInfo.FutureReleaseEntry.Version.ToString(); + + // If UpdateInfo is null, we are on the latest version + latestVersion = updateInfo != null ? updateInfo.TargetFullRelease.Version.ToString() : currentVersion; SettingsService.SaveSettings(); WebMessage.SendMessage(GetUserSettings()); if (SettingsService.Settings.generalSettings.update == "none") return; - if (updateInfo.ReleasesToApply.Count > 0) { + if (updateInfo != null) { Action progressCallback = (progressValue) => { WebMessage.DisplayToast("UpdateProgress", "Installing update", "Updating", "none", (long)progressValue, (long)100); }; if (SettingsService.Settings.generalSettings.update == "automatic") { - Logger.WriteLine($"New version found! Preparing to automatically update to version {updateInfo.FutureReleaseEntry.Version} from {updateInfo.CurrentlyInstalledVersion.Version}"); + Logger.WriteLine($"New version found! Preparing to automatically update to version {updateInfo.TargetFullRelease.Version} from {manager.CurrentVersion}"); applyingUpdate = true; - await manager.UpdateApp(progressCallback); + await manager.DownloadUpdatesAsync(updateInfo, progressCallback, isNightly); WebMessage.DestroyToast("UpdateProgress"); applyingUpdate = false; - Logger.WriteLine($"Update to version {updateInfo.FutureReleaseEntry.Version} successful!"); + Logger.WriteLine($"Update to version {updateInfo.TargetFullRelease.Version} successful!"); WebMessage.DisplayModal("New update applied! Click Confirm to restart and complete the update.", "Update", "update"); } else { // manual if (forceUpdate) { - Logger.WriteLine($"New version found! Preparing to automatically update to version {updateInfo.FutureReleaseEntry.Version} from {updateInfo.CurrentlyInstalledVersion.Version}"); + Logger.WriteLine($"New version found! Preparing to automatically update to version {updateInfo.TargetFullRelease.Version} from {manager.CurrentVersion}"); WebMessage.DestroyToast("ManualUpdate"); applyingUpdate = true; - await manager.UpdateApp(progressCallback); + await manager.DownloadUpdatesAsync(updateInfo, progressCallback); WebMessage.DestroyToast("UpdateProgress"); applyingUpdate = false; - Logger.WriteLine($"Update to version {updateInfo.FutureReleaseEntry.Version} successful!"); + Logger.WriteLine($"Update to version {updateInfo.TargetFullRelease.Version} successful!"); WebMessage.DisplayModal("New update applied! Click Confirm to restart and complete the update.", "Update", "update"); } else WebMessage.DisplayToast("ManualUpdate", "New version available!", "Update", "info"); } } else { - Logger.WriteLine($"Found no updates higher than current version {updateInfo.CurrentlyInstalledVersion.Version}"); + Logger.WriteLine($"Found no updates higher than current version {manager.CurrentVersion}"); } } catch (System.Exception exception) { diff --git a/RePlays.csproj b/RePlays.csproj index f6508cef..e6666de8 100644 --- a/RePlays.csproj +++ b/RePlays.csproj @@ -2,7 +2,6 @@ False - Debug;Release;ReleaseWithSymbols @@ -51,7 +50,6 @@ $(PkgNuGet_CommandLine)\tools - $(PkgClowd_Squirrel)\tools 1.0.0 RePlays.nuspec annotations @@ -59,15 +57,6 @@ True app.manifest - - - True - TRACE;DEBUG - - - - false - @@ -93,7 +82,6 @@ - @@ -106,6 +94,7 @@ + @@ -177,13 +166,15 @@ - - - + + + - - - + + + + +