From b98c165106f3ab0692e88142090a76dfcc1d455a Mon Sep 17 00:00:00 2001 From: Johnny Date: Fri, 10 Nov 2023 13:10:35 +0100 Subject: [PATCH 1/6] some tests --- src/Constants.cs | 5 + src/MainWindow.axaml | 204 +++++++++++++++----------------- src/MainWindow.axaml.cs | 2 +- src/Models/ProgressTask.cs | 16 +++ src/Models/SDK.cs | 16 +++ src/Services/DotnetService.cs | 50 +++++++- src/ViewModels/MainViewModel.cs | 8 ++ 7 files changed, 192 insertions(+), 109 deletions(-) create mode 100644 src/Models/ProgressTask.cs diff --git a/src/Constants.cs b/src/Constants.cs index 46bfa2e..3628271 100644 --- a/src/Constants.cs +++ b/src/Constants.cs @@ -43,4 +43,9 @@ public class Constants public const string SupportURl = "https://bento.me/nor0x"; public const string GithubUrl = "https://github.com/nor0x/Dots"; + + public const string DownloadingText = "Downloading..."; + public const string InstallingText = "Installing..."; + public const string UninstallingText = "Uninstalling..."; + public const string OpeningText = "Opening..."; } \ No newline at end of file diff --git a/src/MainWindow.axaml b/src/MainWindow.axaml index defdc31..c202892 100644 --- a/src/MainWindow.axaml +++ b/src/MainWindow.axaml @@ -290,6 +290,31 @@ Text="Preview" FontSize="10" /> + + + + + + - - + + @@ -510,7 +505,7 @@ @@ -537,10 +532,35 @@ + + + + + !string.IsNullOrEmpty(Path); [ObservableProperty] + [NotifyPropertyChangedFor(nameof(IsBusy))] [JsonIgnore] public bool _isDownloading; [ObservableProperty] + [NotifyPropertyChangedFor(nameof(IsBusy))] [JsonIgnore] public bool _isInstalling; + [ObservableProperty] + [JsonIgnore] + public string _statusMessage; + + [ObservableProperty] + [JsonIgnore] + public double _progress; + + [JsonIgnore] + public bool IsBusy => _isDownloading || _isInstalling; + [JsonIgnore] public string VersionDisplay { get; set; } + + [JsonIgnore] + public ProgressTask ProgressTask { get; set; } } diff --git a/src/Services/DotnetService.cs b/src/Services/DotnetService.cs index 309f2fc..8ce314a 100644 --- a/src/Services/DotnetService.cs +++ b/src/Services/DotnetService.cs @@ -1,9 +1,11 @@ -using System.Diagnostics; +using System; +using System.Diagnostics; using System.IO; using System.Net.Http; using System.Reactive.Linq; using System.Runtime.InteropServices; using System.Text.Json; +using System.Threading; using Akavache; using CliWrap; using CliWrap.Buffered; @@ -191,6 +193,10 @@ public async ValueTask Download(Sdk sdk, bool toDesktop = false) using var client = new HttpClient(); var response = await client.GetByteArrayAsync(info.Url); await File.WriteAllBytesAsync(path, response); + + sdk.ProgressTask = + + if (toDesktop) { //copy to desktop @@ -211,6 +217,48 @@ public async ValueTask Download(Sdk sdk, bool toDesktop = false) } } + void CreateProgressTask() + { + try + { + downloadProgress.DownloadTask = Task.Run(async () => + { + using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellationToken)) + using (var fileStream = new FileStream("downloadedFile.txt", FileMode.Create, FileAccess.Write)) + { + var contentLength = response.Content.Headers.ContentLength; + var buffer = new byte[8192]; + var bytesRead = default(int); + var totalBytesRead = default(long); + + while ((bytesRead = await response.Content.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0) + { + await fileStream.WriteAsync(buffer, 0, bytesRead, cancellationToken); + totalBytesRead += bytesRead; + + if (contentLength.HasValue) + downloadProgress.Progress = (int)((double)totalBytesRead / contentLength.Value * 100); + + Console.WriteLine($"{url} - {downloadProgress.Progress}%"); + } + } + }, cancellationToken); + + await downloadProgress.DownloadTask; + downloads.Remove(downloadProgress); + } + catch (TaskCanceledException) + { + Console.WriteLine($"{url} download was canceled."); + downloads.Remove(downloadProgress); + } + catch (Exception ex) + { + Console.WriteLine($"{url} download failed: {ex.Message}"); + downloads.Remove(downloadProgress); + } + } + public async ValueTask Install(string exe) { try diff --git a/src/ViewModels/MainViewModel.cs b/src/ViewModels/MainViewModel.cs index 7999b22..6f009df 100644 --- a/src/ViewModels/MainViewModel.cs +++ b/src/ViewModels/MainViewModel.cs @@ -25,6 +25,7 @@ public MainViewModel(DotnetService dotnet, ErrorPopupHelper errorHelper) { _dotnet = dotnet; _errorHelper = errorHelper; + _progressTasks = new ObservableCollection(); } string _query = ""; @@ -59,6 +60,8 @@ public MainViewModel(DotnetService dotnet, ErrorPopupHelper errorHelper) [ObservableProperty] bool _showDetails = false; + [ObservableProperty] + ObservableCollection _progressTasks; public bool SetSelectedSdk(Sdk sdk) { @@ -162,10 +165,12 @@ async Task OpenOrDownload(Sdk sdk) sdk.IsDownloading = true; if (sdk.Installed) { + sdk.StatusMessage = "Opening..."; await _dotnet.OpenFolder(sdk); } else { + sdk.StatusMessage = "Downloading..."; var path = await _dotnet.Download(sdk, true); await _dotnet.OpenFolder(path); } @@ -185,8 +190,10 @@ async Task InstallOrUninstall(Sdk sdk) try { sdk.IsInstalling = true; + if (sdk.Installed) { + sdk.StatusMessage = "Uninstalling..."; var result = await _dotnet.Uninstall(sdk); if (result) { @@ -198,6 +205,7 @@ async Task InstallOrUninstall(Sdk sdk) var path = await _dotnet.Download(sdk); if (!string.IsNullOrEmpty(path)) { + sdk.StatusMessage = "Installing..."; var result = await _dotnet.Install(path); if (result) { From d23d04cd76553d0266176855b39f9ccc02d16a69 Mon Sep 17 00:00:00 2001 From: Johnny Date: Wed, 31 Jan 2024 10:15:55 +0100 Subject: [PATCH 2/6] temp progress commit --- src/Dots.csproj | 61 ++++++++------------------------- src/Helpers/Extensions.cs | 51 +++++++++++++++++++++++++++ src/Models/ProgressTask.cs | 4 +-- src/Services/DotnetService.cs | 16 ++++++--- src/ViewModels/MainViewModel.cs | 16 ++++----- 5 files changed, 88 insertions(+), 60 deletions(-) diff --git a/src/Dots.csproj b/src/Dots.csproj index 5d23fcf..28c9665 100644 --- a/src/Dots.csproj +++ b/src/Dots.csproj @@ -67,58 +67,27 @@ - - - - - + + + + + - + - - - - - - - - - + + + + + + + + + \ No newline at end of file diff --git a/src/Helpers/Extensions.cs b/src/Helpers/Extensions.cs index 5061ec6..4d33b98 100644 --- a/src/Helpers/Extensions.cs +++ b/src/Helpers/Extensions.cs @@ -7,10 +7,13 @@ using System; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; +using System.Net.Http; using System.Reflection; using System.Runtime.InteropServices; using System.Text; +using System.Threading; using System.Threading.Tasks; namespace Dots.Helpers; @@ -145,4 +148,52 @@ public static void OpenFilePath(this string path) Process.Start("open", path); return; } + + + //credits https://gist.github.com/dalexsoto/9fd3c5bdbe9f61a717d47c5843384d11 + public static async Task DownloadDataAsync(this HttpClient client, string requestUrl, Stream destination, IProgress progress = null, CancellationToken cancellationToken = default(CancellationToken)) + { + using (var response = await client.GetAsync(requestUrl, HttpCompletionOption.ResponseHeadersRead)) + { + var contentLength = response.Content.Headers.ContentLength; + using (var download = await response.Content.ReadAsStreamAsync()) + { + // no progress... no contentLength... very sad + if (progress is null || !contentLength.HasValue) + { + await download.CopyToAsync(destination); + return; + } + // Such progress and contentLength much reporting Wow! + var progressWrapper = new Progress(totalBytes => progress.Report(GetProgressPercentage(totalBytes, contentLength.Value))); + await download.CopyToAsync(destination, 81920, progressWrapper, cancellationToken); + } + } + + float GetProgressPercentage(float totalBytes, float currentBytes) => (totalBytes / currentBytes) * 100f; + } + + static async Task CopyToAsync(this Stream source, Stream destination, int bufferSize, IProgress progress = null, CancellationToken cancellationToken = default(CancellationToken)) + { + if (bufferSize < 0) + throw new ArgumentOutOfRangeException(nameof(bufferSize)); + if (source is null) + throw new ArgumentNullException(nameof(source)); + if (!source.CanRead) + throw new InvalidOperationException($"'{nameof(source)}' is not readable."); + if (destination == null) + throw new ArgumentNullException(nameof(destination)); + if (!destination.CanWrite) + throw new InvalidOperationException($"'{nameof(destination)}' is not writable."); + + var buffer = new byte[bufferSize]; + long totalBytesRead = 0; + int bytesRead; + while ((bytesRead = await source.ReadAsync(buffer, 0, buffer.Length, cancellationToken).ConfigureAwait(false)) != 0) + { + await destination.WriteAsync(buffer, 0, bytesRead, cancellationToken).ConfigureAwait(false); + totalBytesRead += bytesRead; + progress?.Report(totalBytesRead); + } + } } \ No newline at end of file diff --git a/src/Models/ProgressTask.cs b/src/Models/ProgressTask.cs index 8d67ca9..02928f2 100644 --- a/src/Models/ProgressTask.cs +++ b/src/Models/ProgressTask.cs @@ -9,8 +9,8 @@ namespace Dots.Models; public class ProgressTask { + public string Title { get; set; } public string Url { get; set; } - public int Progress { get; set; } public CancellationTokenSource CancellationTokenSource { get; set; } - public Task DownloadTask { get; set; } + public IProgress Progress { get; set; } } diff --git a/src/Services/DotnetService.cs b/src/Services/DotnetService.cs index 8ce314a..6e44430 100644 --- a/src/Services/DotnetService.cs +++ b/src/Services/DotnetService.cs @@ -191,10 +191,18 @@ public async ValueTask Download(Sdk sdk, bool toDesktop = false) return path; } using var client = new HttpClient(); - var response = await client.GetByteArrayAsync(info.Url); + var response = client.GetByteArrayAsync(info.Url); + //progress + var progress = new ProgressTask(); + progress.Progress = 0; + progress.Title = $"Downloading {sdk.Data.Sdk.Version}"; + progress.Url = info.Url.ToString(); + progress.CancellationTokenSource = new CancellationTokenSource(); + progress.DownloadTask = response; + await File.WriteAllBytesAsync(path, response); - sdk.ProgressTask = + sdk.ProgressTask = new ProgressTask if (toDesktop) @@ -325,14 +333,14 @@ public async Task Uninstall(Sdk sdk, string setupPath = "") string[] files = Directory.GetFiles(path, filename, SearchOption.AllDirectories); - if(!files.IsNullOrEmpty()) + if (!files.IsNullOrEmpty()) { var result = await Cli.Wrap(files.First()).WithArguments(" /uninstall /quiet /qn /norestart").WithValidation(CommandResultValidation.None).ExecuteAsync(); return result.ExitCode == 0; } else { - + var setupInLocalDirectory = Path.Combine(Constants.AppDataPath, filename); if (!string.IsNullOrEmpty(setupPath)) { diff --git a/src/ViewModels/MainViewModel.cs b/src/ViewModels/MainViewModel.cs index 6f009df..80f9f2d 100644 --- a/src/ViewModels/MainViewModel.cs +++ b/src/ViewModels/MainViewModel.cs @@ -70,7 +70,7 @@ public bool SetSelectedSdk(Sdk sdk) { showDetails = false; } - else if(SelectedSdk is null) + else if (SelectedSdk is null) { showDetails = true; } @@ -131,7 +131,7 @@ void FilterSdks(string query) { _query = query; Sdks.Search(_query); - + var filteredCollection = _baseSdks.Where(s => s.Data.Sdk.Version.ToLowerInvariant().Contains(query.ToLowerInvariant()) || s.Path.ToLowerInvariant().Contains(query.ToLowerInvariant())).ToList(); @@ -165,12 +165,12 @@ async Task OpenOrDownload(Sdk sdk) sdk.IsDownloading = true; if (sdk.Installed) { - sdk.StatusMessage = "Opening..."; + sdk.StatusMessage = Constants.OpeningText; await _dotnet.OpenFolder(sdk); } else { - sdk.StatusMessage = "Downloading..."; + sdk.StatusMessage = Constants.DownloadingText; var path = await _dotnet.Download(sdk, true); await _dotnet.OpenFolder(path); } @@ -190,10 +190,10 @@ async Task InstallOrUninstall(Sdk sdk) try { sdk.IsInstalling = true; - + if (sdk.Installed) { - sdk.StatusMessage = "Uninstalling..."; + sdk.StatusMessage = Constants.UninstallingText; var result = await _dotnet.Uninstall(sdk); if (result) { @@ -205,7 +205,7 @@ async Task InstallOrUninstall(Sdk sdk) var path = await _dotnet.Download(sdk); if (!string.IsNullOrEmpty(path)) { - sdk.StatusMessage = "Installing..."; + sdk.StatusMessage = Constants.InstallingText; var result = await _dotnet.Install(path); if (result) { @@ -235,7 +235,7 @@ void ToggleOnline() Sdks.Search(_query); IsBusy = (!ShowOnline && !ShowInstalled); - if(!Sdks.View.Contains(SelectedSdk)) + if (!Sdks.View.Contains(SelectedSdk)) { SelectedSdk = null; } From a31f8fad844b2045c02d3c27c1a553ca92bb1d80 Mon Sep 17 00:00:00 2001 From: Johnny Date: Wed, 31 Jan 2024 21:27:14 +0100 Subject: [PATCH 3/6] initial progress implementation #23 --- src/MainWindow.axaml | 9 ++++++--- src/Models/ProgressTask.cs | 7 +++++-- src/Models/SDK.cs | 5 +++-- src/ViewModels/MainViewModel.cs | 1 + 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/MainWindow.axaml b/src/MainWindow.axaml index c202892..d157bee 100644 --- a/src/MainWindow.axaml +++ b/src/MainWindow.axaml @@ -294,9 +294,12 @@ - Progress { get; set; } + public IProgress Progress { get; set; } + + [ObservableProperty] + float _value; } diff --git a/src/Models/SDK.cs b/src/Models/SDK.cs index 5118938..f8a2936 100644 --- a/src/Models/SDK.cs +++ b/src/Models/SDK.cs @@ -41,7 +41,7 @@ public partial class Sdk : ObservableObject [ObservableProperty] [JsonIgnore] - public double _progress; + double _progress; [JsonIgnore] public bool IsBusy => _isDownloading || _isInstalling; @@ -49,8 +49,9 @@ public partial class Sdk : ObservableObject [JsonIgnore] public string VersionDisplay { get; set; } + [ObservableProperty] [JsonIgnore] - public ProgressTask ProgressTask { get; set; } + ProgressTask _progressTask; } diff --git a/src/ViewModels/MainViewModel.cs b/src/ViewModels/MainViewModel.cs index 80f9f2d..e913954 100644 --- a/src/ViewModels/MainViewModel.cs +++ b/src/ViewModels/MainViewModel.cs @@ -202,6 +202,7 @@ async Task InstallOrUninstall(Sdk sdk) } else { + sdk.StatusMessage = Constants.DownloadingText; var path = await _dotnet.Download(sdk); if (!string.IsNullOrEmpty(path)) { From 60a20c8fc1201e20d6d90e274412213c26bc20db Mon Sep 17 00:00:00 2001 From: Johnny Date: Wed, 31 Jan 2024 21:30:19 +0100 Subject: [PATCH 4/6] support for unofficial sdk releases - detect more sdks from the release-index and match with local sdks - new filter ui --- src/Dots.csproj | 2 +- src/MainWindow.axaml | 1348 +++++++++++++++---------------- src/MainWindow.axaml.cs | 8 +- src/Models/SDK.cs | 2 +- src/Services/DotnetService.cs | 119 +-- src/ViewModels/MainViewModel.cs | 86 +- 6 files changed, 788 insertions(+), 777 deletions(-) diff --git a/src/Dots.csproj b/src/Dots.csproj index 28c9665..072b5a6 100644 --- a/src/Dots.csproj +++ b/src/Dots.csproj @@ -86,7 +86,7 @@ - + diff --git a/src/MainWindow.axaml b/src/MainWindow.axaml index d157bee..b00f859 100644 --- a/src/MainWindow.axaml +++ b/src/MainWindow.axaml @@ -1,62 +1,68 @@ - - + + + + + + - - + + @@ -64,679 +70,671 @@ - - + + - - - - - - + + + + + - - + + + + + + + + + + - - + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + @@ -745,24 +743,20 @@ HorizontalAlignment="Center" /> - - - - + + + + diff --git a/src/MainWindow.axaml.cs b/src/MainWindow.axaml.cs index a68fd38..bc61e69 100644 --- a/src/MainWindow.axaml.cs +++ b/src/MainWindow.axaml.cs @@ -3,13 +3,14 @@ using Avalonia.Media; using Dots.Helpers; using Dots.Models; +using Dots.Services; using System.Reactive.Linq; namespace Dots { public partial class MainWindow : Window { - MainViewModel _vm = new MainViewModel(new Services.DotnetService(), new Helpers.ErrorPopupHelper()); + MainViewModel _vm = new MainViewModel(new DotnetService(), new ErrorPopupHelper()); AboutWindow _aboutWindow = new AboutWindow(); bool _aboutWindowOpen = false; @@ -109,5 +110,10 @@ private void PathTextBlock_Tapped(object? sender, Avalonia.Input.TappedEventArgs var path = ((TextBlock)sender).Text; path.OpenFilePath(); } + + private void Filter_Tapped(object? sender, Avalonia.Input.TappedEventArgs e) + { + FilterButton.Flyout.Hide(); + } } } \ No newline at end of file diff --git a/src/Models/SDK.cs b/src/Models/SDK.cs index f8a2936..c0e33b7 100644 --- a/src/Models/SDK.cs +++ b/src/Models/SDK.cs @@ -15,7 +15,7 @@ public partial class Sdk : ObservableObject //UI public string ColorHex { get; set; } - public string Group => Data.Sdk.Version.First().ToString(); + public string Group => VersionDisplay.First().ToString(); [JsonIgnore] public IBrush Color => SolidColorBrush.Parse(ColorHex); diff --git a/src/Services/DotnetService.cs b/src/Services/DotnetService.cs index 6e44430..adc6354 100644 --- a/src/Services/DotnetService.cs +++ b/src/Services/DotnetService.cs @@ -25,18 +25,21 @@ public class DotnetService ReleaseIndex[] _releaseIndex; Dictionary _releases = new(); + public DotnetService() + { + } + public async Task> GetSdks(bool force = false) { var result = new List(); var index = await GetReleaseIndex(force); var releaseInfos = new List(); - var installed = GetInstalledSdks(force); + await GetInstalledSdks(force); foreach (var item in index) { var infos = await GetReleaseInfos(item.ChannelVersion, force); releaseInfos.AddRange(infos); } - int i = 0; foreach (var release in releaseInfos) { var sdk = new Sdk() @@ -46,10 +49,46 @@ public async Task> GetSdks(bool force = false) Path = _installedSdks.FirstOrDefault(x => x.Version == release.Sdk.Version)?.Path ?? string.Empty, VersionDisplay = release.Sdk.Version, }; - i++; result.Add(sdk); + + if (release.Sdks is not null) + { + foreach (var subSdk in release.Sdks) + { + var sub = new Sdk() + { + Data = release, + ColorHex = ColorHelper.GenerateHexColor(release.Sdk.Version.First().ToString()), + Path = _installedSdks.FirstOrDefault(x => x.Version == subSdk.Version)?.Path ?? string.Empty, + VersionDisplay = subSdk.Version, + }; + + if (result.FirstOrDefault(s => s.VersionDisplay == subSdk.VersionDisplay) is null) + { + result.Add(sub); + } + + } + } + } + + foreach(var installed in _installedSdks) + { + if(result.FirstOrDefault(x => x.VersionDisplay == installed.Version) is null) + { + result.Add( + new Sdk() + { + Data = null, + VersionDisplay = installed.Version, + Path = installed.Path , + ColorHex = ColorHelper.GenerateHexColor(installed.Version.First().ToString()), + } + ); + } } - return result; + + return result.OrderByDescending(x => x.VersionDisplay).ToList(); } async Task GetReleaseIndex(bool force = false) @@ -108,7 +147,7 @@ async Task GetReleaseInfos(string channel, bool force = false) } - public async ValueTask> GetInstalledSdks(bool force = false) + async ValueTask> GetInstalledSdks(bool force = false) { try { @@ -151,7 +190,7 @@ public async ValueTask> GetInstalledSdks(bool force = false) catch (Exception ex) { Debug.WriteLine(ex); - ////Analytics.TrackEvent("GetInstalledSdks", new Dictionary() { { "Error", ex.Message } }); + //Analytics.TrackEvent("GetInstalledSdks", new Dictionary() { { "Error", ex.Message } }); return null; } @@ -190,29 +229,35 @@ public async ValueTask Download(Sdk sdk, bool toDesktop = false) } return path; } - using var client = new HttpClient(); - var response = client.GetByteArrayAsync(info.Url); - //progress + var progress = new ProgressTask(); - progress.Progress = 0; progress.Title = $"Downloading {sdk.Data.Sdk.Version}"; progress.Url = info.Url.ToString(); progress.CancellationTokenSource = new CancellationTokenSource(); - progress.DownloadTask = response; - await File.WriteAllBytesAsync(path, response); + var p = new Progress(); + p.ProgressChanged += (s, e) => + { + progress.Value = e; + }; + progress.Progress = p; - sdk.ProgressTask = new ProgressTask + sdk.ProgressTask = progress; + + // Use the provided extension method + using var file = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.None); + using var client = new HttpClient(); + await client.DownloadDataAsync(info.Url.ToString(), file, p); if (toDesktop) { - //copy to desktop var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); var filename = Path.Combine(desktop, sdkFile); - await File.WriteAllBytesAsync(filename, response); - return desktop; + await File.WriteAllBytesAsync(Path.Combine(desktop, sdkFile), await File.ReadAllBytesAsync(path)); + path = desktop; } + return path; } return null; @@ -225,48 +270,6 @@ public async ValueTask Download(Sdk sdk, bool toDesktop = false) } } - void CreateProgressTask() - { - try - { - downloadProgress.DownloadTask = Task.Run(async () => - { - using (var response = await client.GetAsync(url, HttpCompletionOption.ResponseHeadersRead, cancellationToken)) - using (var fileStream = new FileStream("downloadedFile.txt", FileMode.Create, FileAccess.Write)) - { - var contentLength = response.Content.Headers.ContentLength; - var buffer = new byte[8192]; - var bytesRead = default(int); - var totalBytesRead = default(long); - - while ((bytesRead = await response.Content.ReadAsync(buffer, 0, buffer.Length, cancellationToken)) > 0) - { - await fileStream.WriteAsync(buffer, 0, bytesRead, cancellationToken); - totalBytesRead += bytesRead; - - if (contentLength.HasValue) - downloadProgress.Progress = (int)((double)totalBytesRead / contentLength.Value * 100); - - Console.WriteLine($"{url} - {downloadProgress.Progress}%"); - } - } - }, cancellationToken); - - await downloadProgress.DownloadTask; - downloads.Remove(downloadProgress); - } - catch (TaskCanceledException) - { - Console.WriteLine($"{url} download was canceled."); - downloads.Remove(downloadProgress); - } - catch (Exception ex) - { - Console.WriteLine($"{url} download failed: {ex.Message}"); - downloads.Remove(downloadProgress); - } - } - public async ValueTask Install(string exe) { try diff --git a/src/ViewModels/MainViewModel.cs b/src/ViewModels/MainViewModel.cs index e913954..c9bb107 100644 --- a/src/ViewModels/MainViewModel.cs +++ b/src/ViewModels/MainViewModel.cs @@ -26,6 +26,7 @@ public MainViewModel(DotnetService dotnet, ErrorPopupHelper errorHelper) _dotnet = dotnet; _errorHelper = errorHelper; _progressTasks = new ObservableCollection(); + SelectedFilterIcon = LucideIcons.ListFilter; } string _query = ""; @@ -47,21 +48,23 @@ public MainViewModel(DotnetService dotnet, ErrorPopupHelper errorHelper) [ObservableProperty] ObservableView _sdks; - [ObservableProperty] string _lastUpdated; [ObservableProperty] - bool _showOnline = true; + bool _showDetails = false; [ObservableProperty] - bool _showInstalled = true; + ObservableCollection _progressTasks; [ObservableProperty] - bool _showDetails = false; + string _selectedFilterIcon; + + bool _showOnline = true; + bool _showInstalled = true; [ObservableProperty] - ObservableCollection _progressTasks; + bool _emptyData; public bool SetSelectedSdk(Sdk sdk) { @@ -74,11 +77,13 @@ public bool SetSelectedSdk(Sdk sdk) { showDetails = true; } - else if (sdk is not null && sdk.Data.Sdk.Version == SelectedSdk.Data.Sdk.Version) + else if (sdk is not null && sdk.VersionDisplay == SelectedSdk.VersionDisplay) { showDetails = !ShowDetails; } ShowDetails = showDetails; + EmptyData = sdk?.Data is null; + if (sdk?.VersionDisplay == SelectedSdk?.VersionDisplay) { SelectedSdk = null; @@ -151,8 +156,40 @@ void FilterSdks(string query) [RelayCommand] void ToggleSelection() + { } + + [RelayCommand] + void ApplyFilter(string f) { - SelectionEnabled = !SelectionEnabled; + int filter = int.Parse(f); + //0 all + //1 online + //2 installed + if(filter == 0) + { + _showOnline = true; + _showInstalled = true; + SelectedFilterIcon = LucideIcons.ListFilter; + } + else if (filter == 1) + { + _showInstalled = false; + _showOnline = true; + SelectedFilterIcon = LucideIcons.Cloudy; + } + else if(filter == 2) + { + _showOnline = false; + _showInstalled = true; + SelectedFilterIcon = LucideIcons.HardDrive; + } + Sdks.Search(" "); + Sdks.Search(_query); + + if (!Sdks.View.Contains(SelectedSdk)) + { + SelectedSdk = null; + } } public ICommand MyTestCommand { get; set; } @@ -228,35 +265,6 @@ async Task InstallOrUninstall(Sdk sdk) } } - [RelayCommand] - void ToggleOnline() - { - ShowOnline = !ShowOnline; - Sdks.Search(" "); - Sdks.Search(_query); - IsBusy = (!ShowOnline && !ShowInstalled); - - if (!Sdks.View.Contains(SelectedSdk)) - { - SelectedSdk = null; - } - } - - [RelayCommand] - void ToggleInstalled() - { - ShowInstalled = !ShowInstalled; - Sdks.Search(" "); - Sdks.Search(_query); - IsBusy = (!ShowOnline && !ShowInstalled); - if (!Sdks.View.Contains(SelectedSdk)) - { - SelectedSdk = null; - } - } - - - [RelayCommand] void ToggleMultiSelection() { @@ -269,15 +277,15 @@ void OpenSettings() void Sdks_FilterHandler(object sender, ObservableView.Filtering.FilterEventArgs e) { - if (ShowOnline && ShowInstalled) + if (_showOnline && _showInstalled) { e.IsAllowed = true; } - else if (ShowOnline && !ShowInstalled) + else if (_showOnline && !_showInstalled) { e.IsAllowed = !e.Item.Installed; } - else if (!ShowOnline && ShowInstalled) + else if (!_showOnline && _showInstalled) { e.IsAllowed = e.Item.Installed; } From 69cd0888c1df26a834ecb12f35d92b4b49034cbc Mon Sep 17 00:00:00 2001 From: Johnny Date: Wed, 31 Jan 2024 21:34:56 +0100 Subject: [PATCH 5/6] =?UTF-8?q?cleanup=20=F0=9F=A7=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/MainWindow.axaml | 5 +++-- src/MainWindow.axaml.cs | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/MainWindow.axaml b/src/MainWindow.axaml index b00f859..37c2117 100644 --- a/src/MainWindow.axaml +++ b/src/MainWindow.axaml @@ -123,6 +123,7 @@ Width="30" Height="30" />