diff --git a/Companion.Tests/ViewModels/FirmwareTabViewModelTests.cs b/Companion.Tests/ViewModels/FirmwareTabViewModelTests.cs index 4e05941..b096092 100644 --- a/Companion.Tests/ViewModels/FirmwareTabViewModelTests.cs +++ b/Companion.Tests/ViewModels/FirmwareTabViewModelTests.cs @@ -143,6 +143,39 @@ public void CanExecuteDownloadFirmware_ReturnsTrue_IfValidState() Assert.That(canExecute, Is.True); } + [Test] + public void SelectedFirmwareSource_DefaultsToOpenIpcBuilder() + { + Assert.That(_viewModel.SelectedFirmwareSource, Is.EqualTo("OpenIPC Builder")); + } + + [Test] + public void BuildFirmwareDownloadUrl_DefaultSource_UsesOpenIpcReleaseUrl() + { + var url = (string)InvokePrivateMethod(_viewModel, "BuildFirmwareDownloadUrl", "test-fw.tgz"); + Assert.That(url, Is.EqualTo("https://github.com/OpenIPC/builder/releases/download/latest/test-fw.tgz")); + } + + [Test] + public void BuildFirmwareDownloadUrl_GregSource_UsesRawGithubUrl() + { + _viewModel.SelectedFirmwareSource = "Greg APFPV"; + + var url = (string)InvokePrivateMethod(_viewModel, "BuildFirmwareDownloadUrl", "test-fw.tgz"); + + Assert.That(url, Is.EqualTo("https://raw.githubusercontent.com/sickgreg/OpenIPC_sickgregFPV_apfpv/main/test-fw.tgz")); + } + + [Test] + public void CanUseDropdowns_GregSource_ReturnsFalse() + { + _viewModel.CanConnect = true; + _viewModel.IsConnected = true; + _viewModel.SelectedFirmwareSource = "Greg APFPV"; + + Assert.That(_viewModel.CanUseDropdowns, Is.False); + } + [Test] public void UpdateSysupgradeProgressFromLine_KernelWritingPercent_MapsToRange() { diff --git a/Companion/Models/OpenIPC.cs b/Companion/Models/OpenIPC.cs index f415384..ad86fa5 100644 --- a/Companion/Models/OpenIPC.cs +++ b/Companion/Models/OpenIPC.cs @@ -19,6 +19,10 @@ public enum FileType public const string OpenIPCBuilderGitHubApiUrl = "https://api.github.com/repos/OpenIPC/builder/releases/latest"; public const string OpenIPCFirmwareGitHubApiUrl = "https://api.github.com/repos/OpenIPC/firmware/releases/latest"; + public const string GregApfpvContentsGitHubApiUrl = + "https://api.github.com/repos/sickgreg/OpenIPC_sickgregFPV_apfpv/contents"; + public const string GregApfpvRawBaseUrl = + "https://raw.githubusercontent.com/sickgreg/OpenIPC_sickgregFPV_apfpv/main/"; public const string MajesticFileLoc = "/etc/majestic.yaml"; public const string WfbConfFileLoc = "/etc/wfb.conf"; public const string WfbYamlFileLoc = "/etc/wfb.yaml"; diff --git a/Companion/ViewModels/FirmwareTabViewModel.cs b/Companion/ViewModels/FirmwareTabViewModel.cs index 13dc69c..0bdc186 100644 --- a/Companion/ViewModels/FirmwareTabViewModel.cs +++ b/Companion/ViewModels/FirmwareTabViewModel.cs @@ -79,6 +79,8 @@ private enum SysupgradePhase private static readonly Regex MtdLineRegex = new(@"^(?mtd\d+):\s+(?[0-9a-fA-F]+)\s+(?[0-9a-fA-F]+)\s+""(?[^""]+)""", RegexOptions.Compiled); + private const string OpenIpcFirmwareSource = "OpenIPC Builder"; + private const string GregApfpvFirmwareSource = "Greg APFPV"; #endregion #region Observable Properties @@ -106,6 +108,7 @@ private enum SysupgradePhase [ObservableProperty] private bool _firmwareUpgradeInProgress; [ObservableProperty] private bool _isFirmwareExpanded = true; [ObservableProperty] private bool _isBootloaderExpanded; + [ObservableProperty] private string _selectedFirmwareSource; #endregion @@ -114,7 +117,7 @@ private enum SysupgradePhase /// /// Gets whether dropdowns should be enabled based on connection and firmware selection state /// - public bool CanUseDropdowns => IsConnected; + public bool CanUseDropdowns => IsConnected && !IsGregApfpvSourceSelected(); /// /// Gets whether soc dropdowns should be enabled based on connection and firmware selection state @@ -147,6 +150,11 @@ private enum SysupgradePhase /// public ObservableCollection FirmwareBySoc { get; set; } = new(); public ObservableCollection Bootloaders { get; set; } = new(); + public ObservableCollection FirmwareSources { get; } = new() + { + OpenIpcFirmwareSource, + GregApfpvFirmwareSource + }; #endregion @@ -201,6 +209,7 @@ private void InitializeProperties() FirmwareUpgradeInProgress = false; IsFirmwareExpanded = true; IsBootloaderExpanded = false; + SelectedFirmwareSource = OpenIpcFirmwareSource; } partial void OnIsFirmwareExpandedChanged(bool value) @@ -299,6 +308,15 @@ partial void OnSelectedFirmwareBySocChanged(string value) _bRecursionSelectGuard = false; UpdateCanExecuteCommands(); } + + partial void OnSelectedFirmwareSourceChanged(string value) + { + if (string.IsNullOrWhiteSpace(value) || _bRecursionSelectGuard) + return; + + ClearFirmwareSelectionsAndCollections(); + _ = LoadManufacturersAsync(); + } partial void OnSelectedManufacturerChanged(string value) { @@ -593,6 +611,30 @@ private void ClearForm() UpdateCanExecuteCommands(); } + private void ClearFirmwareSelectionsAndCollections() + { + _bRecursionSelectGuard = true; + + SelectedManufacturer = string.Empty; + SelectedDevice = string.Empty; + SelectedFirmware = string.Empty; + SelectedFirmwareBySoc = string.Empty; + ManualLocalFirmwarePackageFile = string.Empty; + + IsLocalFirmwarePackageSelected = false; + IsManufacturerDeviceFirmwareComboSelected = false; + IsManualUpdateEnabled = true; + IsFirmwareBySocSelected = false; + + Manufacturers.Clear(); + Devices.Clear(); + Firmwares.Clear(); + FirmwareBySoc.Clear(); + + _bRecursionSelectGuard = false; + UpdateCanExecuteCommands(); + } + private bool CanExecuteDownloadFirmware() { return CanConnect && @@ -646,7 +688,9 @@ private async Task FetchFirmwareListAsync() Logger.Information($"Fetched {filenames.Count()} firmware files."); - FirmwareData firmwareData = ProcessFilenames(filenames); + FirmwareData firmwareData = IsGregApfpvSourceSelected() + ? new FirmwareData { Manufacturers = new ObservableCollection() } + : ProcessFilenames(filenames); // Populate FirmwareBySoc PopulateFirmwareBySoc(filenames); // Calling populate method here @@ -696,11 +740,31 @@ private void PopulateFirmwareBySoc(IEnumerable filenames) private async Task> GetFilenamesAsync() { - var response = await _gitHubService.GetGitHubDataAsync(OpenIPC.OpenIPCBuilderGitHubApiUrl); - var releaseData = JObject.Parse(response.ToString()); - var assets = releaseData["assets"]; - return assets?.Select(asset => asset["name"]?.ToString()).Where(name => !string.IsNullOrEmpty(name)) ?? - Enumerable.Empty(); + if (IsGregApfpvSourceSelected()) + { + var response = await _gitHubService.GetGitHubDataAsync(OpenIPC.GregApfpvContentsGitHubApiUrl); + if (string.IsNullOrEmpty(response)) + return Enumerable.Empty(); + + var items = JArray.Parse(response); + return items + .Where(item => item["type"]?.ToString() == "file") + .Select(item => item["name"]?.ToString()) + .Where(name => !string.IsNullOrEmpty(name)) + .Select(name => name!) + .Where(name => name.EndsWith(".tgz", StringComparison.OrdinalIgnoreCase)); + } + else + { + var response = await _gitHubService.GetGitHubDataAsync(OpenIPC.OpenIPCBuilderGitHubApiUrl); + if (string.IsNullOrEmpty(response)) + return Enumerable.Empty(); + + var releaseData = JObject.Parse(response); + var assets = releaseData["assets"]; + return assets?.Select(asset => asset["name"]?.ToString()).Where(name => !string.IsNullOrEmpty(name)) ?? + Enumerable.Empty(); + } } private async Task> GetBootloaderFilenamesAsync() @@ -1385,7 +1449,7 @@ private async Task PerformFirmwareUpgradeFromSocAsync() if (!string.IsNullOrEmpty(firmwwareFile)) { filename = firmwwareFile; - downloadUrl = $"https://github.com/OpenIPC/builder/releases/download/latest/{firmwwareFile}"; + downloadUrl = BuildFirmwareDownloadUrl(firmwwareFile); } else @@ -1441,7 +1505,7 @@ private async Task PerformFirmwareUpgradeFromDropdownAsync() !string.IsNullOrEmpty(firmware?.Name)) { filename = firmware.PackageFile; - downloadUrl = $"https://github.com/OpenIPC/builder/releases/download/latest/{filename}"; + downloadUrl = BuildFirmwareDownloadUrl(filename); } else @@ -1727,6 +1791,19 @@ public async Task SelectLocalFirmwarePackage(Window window) } } + private bool IsGregApfpvSourceSelected() + { + return string.Equals(SelectedFirmwareSource, GregApfpvFirmwareSource, StringComparison.OrdinalIgnoreCase); + } + + private string BuildFirmwareDownloadUrl(string firmwareFilename) + { + if (IsGregApfpvSourceSelected()) + return $"{OpenIPC.GregApfpvRawBaseUrl}{firmwareFilename}"; + + return $"https://github.com/OpenIPC/builder/releases/download/latest/{firmwareFilename}"; + } + #endregion } diff --git a/Companion/Views/FirmwareTabView.axaml b/Companion/Views/FirmwareTabView.axaml index b8c06a7..bc46ab5 100644 --- a/Companion/Views/FirmwareTabView.axaml +++ b/Companion/Views/FirmwareTabView.axaml @@ -77,13 +77,24 @@ ShowGridLines="False"> - - - + + + + + + - - + - - +