From e1e204ecf88ca4a39cb2c5ef93dee1832b710a77 Mon Sep 17 00:00:00 2001 From: BoiHanny <114599052+BoiHanny@users.noreply.github.com> Date: Fri, 1 Nov 2024 20:24:57 +0100 Subject: [PATCH] Add support for custom profiles and update dependencies Introduce support for custom profiles via -profile= argument. Update App.xaml.cs to handle multiple command-line arguments. Modify UpdateApp.cs to support new application location creation. Update AfkModule.cs and PulsoidModule.cs to use custom data path. Downgrade MagicChatbox.csproj version and update dependencies. Prevent updates and rollbacks while using custom profiles. Add new profile configuration in launchSettings.json. Handle updates and rollbacks in ApplicationError.xaml.cs. Add ProfileNumber and UseCustomProfile properties in ViewModel.cs. --- vrcosc-magicchatbox/App.xaml.cs | 74 +++++++++++++------ .../Classes/DataAndSecurity/UpdateApp.cs | 44 +++++++---- .../Classes/Modules/AfkModule.cs | 2 +- .../Classes/Modules/PulsoidModule.cs | 2 +- vrcosc-magicchatbox/MagicChatbox.csproj | 4 +- vrcosc-magicchatbox/MainWindow.xaml.cs | 25 ++++++- .../Properties/launchSettings.json | 4 + .../UI/Dialogs/ApplicationError.xaml.cs | 6 +- vrcosc-magicchatbox/ViewModels/ViewModel.cs | 49 ++++++++++-- 9 files changed, 156 insertions(+), 54 deletions(-) diff --git a/vrcosc-magicchatbox/App.xaml.cs b/vrcosc-magicchatbox/App.xaml.cs index 3c43ba6..9716c69 100644 --- a/vrcosc-magicchatbox/App.xaml.cs +++ b/vrcosc-magicchatbox/App.xaml.cs @@ -35,34 +35,57 @@ protected override async void OnStartup(StartupEventArgs e) // Process command-line arguments if (e.Args != null && e.Args.Length > 0) { - switch (e.Args[0]) + foreach (string arg in e.Args) { - case "-update": - loadingWindow.UpdateProgress("Go, go, go! Update, update, update!", 75); - await Task.Run(() => updater.UpdateApplication()); - Shutdown(); - return; - case "-updateadmin": - loadingWindow.UpdateProgress("Admin style update, now that's fancy!", 85); - await Task.Run(() => updater.UpdateApplication(true)); - Shutdown(); - return; - case "-rollback": - loadingWindow.UpdateProgress("Oops! Let's roll back.", 50); - await Task.Run(() => updater.RollbackApplication(loadingWindow)); - Shutdown(); - return; - case "-clearbackup": - loadingWindow.UpdateProgress("Rolling back and clearing the slate. Fresh start!", 50); - await Task.Run(() => updater.ClearBackUp()); - break; - default: - loadingWindow.Hide(); - Logging.WriteException(new Exception($"Invalid command line argument '{e.Args[0]}'"), MSGBox: true, exitapp: true); - return; + if (arg.StartsWith("-profile=")) + { + string profileNumberString = arg.Substring(9); + if (int.TryParse(profileNumberString, out int profileNumber)) + { + ViewModel.Instance.ProfileNumber = profileNumber; + ViewModel.Instance.UseCustomProfile = true; + ViewModel.Instance.SetDataPath(); + } + else + { + loadingWindow.Hide(); + Logging.WriteException(new Exception($"Invalid profile number '{profileNumberString}'"), MSGBox: true, exitapp: true); + return; + } + } + else + { + switch (arg) + { + case "-update": + loadingWindow.UpdateProgress("Go, go, go! Update, update, update!", 75); + await Task.Run(() => updater.UpdateApplication()); + Shutdown(); + return; + case "-updateadmin": + loadingWindow.UpdateProgress("Admin style update, now that's fancy!", 85); + await Task.Run(() => updater.UpdateApplication(true)); + Shutdown(); + return; + case "-rollback": + loadingWindow.UpdateProgress("Oops! Let's roll back.", 50); + await Task.Run(() => updater.RollbackApplication(loadingWindow)); + Shutdown(); + return; + case "-clearbackup": + loadingWindow.UpdateProgress("Rolling back and clearing the slate. Fresh start!", 50); + await Task.Run(() => updater.ClearBackUp()); + break; + default: + loadingWindow.Hide(); + Logging.WriteException(new Exception($"Invalid command line argument '{arg}'"), MSGBox: true, exitapp: true); + return; + } + } } } + // Initialize various components with progress updates await InitializeComponentsWithProgress(loadingWindow); @@ -153,6 +176,9 @@ private async Task InitializeComponentsWithProgress(StartUp loadingWindow) loadingWindow.UpdateProgress("Turbocharging MediaLink engines... Fast & Furious: Data Drift!", 95); ApplicationMediaController = new MediaLinkModule(ViewModel.Instance.IntgrScanMediaLink); + loadingWindow.UpdateProgress("Starting the modules... Ready, set, go!", 96); + await Task.Run(() => ViewModel.Instance.StartModules()); + loadingWindow.UpdateProgress("Loading MediaLink styles... Fashion show, here we come!", 98); await Task.Run(() => DataController.LoadAndSaveMediaLinkStyles()); } diff --git a/vrcosc-magicchatbox/Classes/DataAndSecurity/UpdateApp.cs b/vrcosc-magicchatbox/Classes/DataAndSecurity/UpdateApp.cs index e816990..b9ac0e2 100644 --- a/vrcosc-magicchatbox/Classes/DataAndSecurity/UpdateApp.cs +++ b/vrcosc-magicchatbox/Classes/DataAndSecurity/UpdateApp.cs @@ -26,16 +26,23 @@ public class UpdateApp private string magicChatboxExePath; private string backupPath; - public UpdateApp() + public UpdateApp(bool createNewAppLocation = false) { dataPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Vrcosc-MagicChatbox"); - InitializePaths(); + InitializePaths(createNewAppLocation); } - private void InitializePaths() + private void InitializePaths(bool createNewAppLocation) { string jsonFilePath = Path.Combine(dataPath, "app_location.json"); - if (File.Exists(jsonFilePath)) + string actualCurrentAppPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + + if (!File.Exists(jsonFilePath)) + { + SetDefaultPaths(); + SaveUpdateLocation(); + } + else { var settingsJson = File.ReadAllText(jsonFilePath); @@ -43,6 +50,7 @@ private void InitializePaths() { Logging.WriteInfo("The app_location.json file is empty or corrupted."); SetDefaultPaths(); + SaveUpdateLocation(); } else { @@ -50,22 +58,32 @@ private void InitializePaths() { JObject appLocation = JObject.Parse(settingsJson); currentAppPath = appLocation["currentAppPath"].ToString(); - tempPath = appLocation["tempPath"].ToString(); - unzipPath = appLocation["unzipPath"].ToString(); - magicChatboxExePath = appLocation["magicChatboxExePath"].ToString(); - backupPath = Path.Combine(dataPath, "backup"); + + // Check if the current app path matches the actual current app path + if (createNewAppLocation || !string.Equals(currentAppPath, actualCurrentAppPath, StringComparison.OrdinalIgnoreCase)) + { + // The app has been moved to a new location + Logging.WriteInfo("The application has been moved. Updating app_location.json."); + SetDefaultPaths(); + SaveUpdateLocation(); + } + else + { + // Existing code to set paths from app_location.json + tempPath = appLocation["tempPath"].ToString(); + unzipPath = appLocation["unzipPath"].ToString(); + magicChatboxExePath = appLocation["magicChatboxExePath"].ToString(); + backupPath = Path.Combine(dataPath, "backup"); + } } catch (Newtonsoft.Json.JsonReaderException ex) { Logging.WriteInfo($"Error parsing app_location.json: {ex.Message}"); SetDefaultPaths(); + SaveUpdateLocation(); } } } - else - { - SetDefaultPaths(); - } if (!Directory.Exists(tempPath)) { @@ -417,7 +435,7 @@ public void ClearBackUp() private void SaveUpdateLocation(string backupPath = null) { JObject appLocation = new JObject( - new JProperty("currentAppPath", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)), + new JProperty("currentAppPath", currentAppPath), new JProperty("tempPath", tempPath), new JProperty("unzipPath", unzipPath), new JProperty("magicChatboxExePath", magicChatboxExePath) diff --git a/vrcosc-magicchatbox/Classes/Modules/AfkModule.cs b/vrcosc-magicchatbox/Classes/Modules/AfkModule.cs index 6f6de86..c6c1400 100644 --- a/vrcosc-magicchatbox/Classes/Modules/AfkModule.cs +++ b/vrcosc-magicchatbox/Classes/Modules/AfkModule.cs @@ -29,7 +29,7 @@ partial void OnAfkTimeoutChanged(int value) } private const string SettingsFileName = "AfkModuleSettings.json"; - private static readonly string SettingsPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Vrcosc-MagicChatbox", SettingsFileName); + private static readonly string SettingsPath = Path.Combine(ViewModel.Instance.DataPath, SettingsFileName); [ObservableProperty] private int afkTimeout = 120; diff --git a/vrcosc-magicchatbox/Classes/Modules/PulsoidModule.cs b/vrcosc-magicchatbox/Classes/Modules/PulsoidModule.cs index 0e5aac5..16f5222 100644 --- a/vrcosc-magicchatbox/Classes/Modules/PulsoidModule.cs +++ b/vrcosc-magicchatbox/Classes/Modules/PulsoidModule.cs @@ -151,7 +151,7 @@ public void SaveSettings() public static string GetFullSettingsPath() { - return Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Vrcosc-MagicChatbox"), SettingsFileName); + return Path.Combine(ViewModel.Instance.DataPath, SettingsFileName); } public static PulsoidModuleSettings LoadSettings() diff --git a/vrcosc-magicchatbox/MagicChatbox.csproj b/vrcosc-magicchatbox/MagicChatbox.csproj index 7178069..871dec2 100644 --- a/vrcosc-magicchatbox/MagicChatbox.csproj +++ b/vrcosc-magicchatbox/MagicChatbox.csproj @@ -2,7 +2,7 @@ WinExe - 0.9.040 + 0.9.039 net8.0-windows10.0.22000.0 vrcosc_magicchatbox enable @@ -192,7 +192,7 @@ - + diff --git a/vrcosc-magicchatbox/MainWindow.xaml.cs b/vrcosc-magicchatbox/MainWindow.xaml.cs index 087ac61..6b0cd50 100644 --- a/vrcosc-magicchatbox/MainWindow.xaml.cs +++ b/vrcosc-magicchatbox/MainWindow.xaml.cs @@ -681,11 +681,18 @@ private void NewFavText_TextChanged(object sender, TextChangedEventArgs e) private void NewVersion_MouseUp(object sender, MouseButtonEventArgs e) { + if(ViewModel.Instance.UseCustomProfile) + { + Logging.WriteException(new Exception("Cannot update while using a custom profile."), MSGBox: true); + return; + } + + if (ViewModel.Instance.CanUpdate) { ViewModel.Instance.CanUpdate = false; ViewModel.Instance.CanUpdateLabel = false; - UpdateApp updateApp = new UpdateApp(); + UpdateApp updateApp = new UpdateApp(true); Task.Run(() => updateApp.PrepareUpdate()); } else @@ -1559,7 +1566,13 @@ private bool IsRunAsAdmin() private void UpdateByZipFile_Click(object sender, RoutedEventArgs e) { - UpdateApp updateApp = new UpdateApp(); + if (ViewModel.Instance.UseCustomProfile) + { + Logging.WriteException(new Exception("Cannot update by zip while using a custom profile."), MSGBox: true); + return; + } + + UpdateApp updateApp = new UpdateApp(true); updateApp.SelectCustomZip(); } @@ -1633,7 +1646,13 @@ private void StopRecord_Click(object sender, RoutedEventArgs e) private void Rollback_Click(object sender, RoutedEventArgs e) { - UpdateApp updateApp = new UpdateApp(); + if (ViewModel.Instance.UseCustomProfile) + { + Logging.WriteException(new Exception("Cannot rollback while using a custom profile."), MSGBox: true); + return; + } + + UpdateApp updateApp = new UpdateApp(true); updateApp.StartRollback(); } diff --git a/vrcosc-magicchatbox/Properties/launchSettings.json b/vrcosc-magicchatbox/Properties/launchSettings.json index 19636e3..b06361b 100644 --- a/vrcosc-magicchatbox/Properties/launchSettings.json +++ b/vrcosc-magicchatbox/Properties/launchSettings.json @@ -6,6 +6,10 @@ }, "Normal": { "commandName": "Project" + }, + "Profile 1": { + "commandName": "Project", + "commandLineArgs": "-profile=1" } } } \ No newline at end of file diff --git a/vrcosc-magicchatbox/UI/Dialogs/ApplicationError.xaml.cs b/vrcosc-magicchatbox/UI/Dialogs/ApplicationError.xaml.cs index 8fd6797..4e8edfc 100644 --- a/vrcosc-magicchatbox/UI/Dialogs/ApplicationError.xaml.cs +++ b/vrcosc-magicchatbox/UI/Dialogs/ApplicationError.xaml.cs @@ -60,7 +60,7 @@ private void OpenLogFolder_Click(object sender, RoutedEventArgs e) private void Update_Click(object sender, RoutedEventArgs e) { - UpdateApp updater = new UpdateApp(); + UpdateApp updater = new UpdateApp(true); updater.SelectCustomZip(); } @@ -70,7 +70,7 @@ private void NewVersion_MouseUp(object sender, System.Windows.Input.MouseButtonE { ViewModel.Instance.CanUpdate = false; ViewModel.Instance.CanUpdateLabel = false; - UpdateApp updateApp = new UpdateApp(); + UpdateApp updateApp = new UpdateApp(true); Task.Run(() => updateApp.PrepareUpdate()); } else @@ -91,7 +91,7 @@ private async Task ManualUpdateCheckAsync() private void rollback_Click(object sender, RoutedEventArgs e) { - UpdateApp updater = new UpdateApp(); + UpdateApp updater = new UpdateApp(true); updater.StartRollback(); } } diff --git a/vrcosc-magicchatbox/ViewModels/ViewModel.cs b/vrcosc-magicchatbox/ViewModels/ViewModel.cs index b9c9e01..229def7 100644 --- a/vrcosc-magicchatbox/ViewModels/ViewModel.cs +++ b/vrcosc-magicchatbox/ViewModels/ViewModel.cs @@ -325,13 +325,6 @@ public ViewModel() { nameof(Settings_Status), value => Settings_Status = value } }; - HeartRateConnector = new PulsoidModule(); - SoundpadModule = new(1000); - - - PropertyChanged += HeartRateConnector.PropertyChangedHandler; - PropertyChanged += SoundpadModule.PropertyChangedHandler; - ShuffleEmojis(); CurrentEmoji = GetNextEmoji(); } @@ -341,6 +334,16 @@ private void ProcessInfo_PropertyChanged(object sender, PropertyChangedEventArgs Resort(); } + public void StartModules() + { + HeartRateConnector = new PulsoidModule(); + SoundpadModule = new(1000); + + + PropertyChanged += HeartRateConnector.PropertyChangedHandler; + PropertyChanged += SoundpadModule.PropertyChangedHandler; + } + private void Resort() @@ -2186,6 +2189,16 @@ public int OSCPOrtIN } } + public void SetDataPath() + { + if(UseCustomProfile) + { + DataPath = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), + $"Vrcosc-MagicChatbox-profile-{ProfileNumber}"); + } + } + private string _DataPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Vrcosc-MagicChatbox"); @@ -4167,6 +4180,28 @@ public string GetNextEmoji() return CurrentEmoji = _shuffledEmojis.Dequeue(); } + private int _profileNumber; + public int ProfileNumber + { + get => _profileNumber; + set + { + _profileNumber = value; + NotifyPropertyChanged(nameof(ProfileNumber)); + } + } + + private bool _useCustomProfile; + public bool UseCustomProfile + { + get => _useCustomProfile; + set + { + _useCustomProfile = value; + NotifyPropertyChanged(nameof(UseCustomProfile)); + } + } + #endregion #region PropChangedEvent