using System; using System.IO; using System.Text; using System.Threading; using System.Threading.Tasks; using Avalonia; using Avalonia.Controls.ApplicationLifetimes; using Avalonia.Platform.Storage; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; namespace SolutionParityChecker.App.ViewModels; public partial class MainWindowViewModel : ViewModelBase { public string SolutionFolderPath { get; set; } = string.Empty; public string SolutionFilePath { get; set; } = string.Empty; [ObservableProperty] private string? _fileText; [RelayCommand] private async Task OpenFile(CancellationToken token) { ErrorMessages?.Clear(); try { var file = await DoOpenFilePickerAsync(); if (file is null) return; // Limit the text file to 1MB so that the demo won't lag. if ((await file.GetBasicPropertiesAsync()).Size <= 1024 * 1024 * 1) { await using var readStream = await file.OpenReadAsync(); using var reader = new StreamReader(readStream); FileText = await reader.ReadToEndAsync(token); } else { throw new Exception("File exceeded 1MB limit."); } } catch (Exception e) { ErrorMessages?.Add(e.Message); } } [RelayCommand] private async Task SaveFile() { ErrorMessages?.Clear(); try { var file = await DoSaveFilePickerAsync(); if (file is null) return; // Limit the text file to 1MB so that the demo won't lag. if (FileText?.Length <= 1024 * 1024 * 1) { var stream = new MemoryStream(Encoding.Default.GetBytes((string)FileText)); await using var writeStream = await file.OpenWriteAsync(); await stream.CopyToAsync(writeStream); } else { throw new Exception("File exceeded 1MB limit."); } } catch (Exception e) { ErrorMessages?.Add(e.Message); } } private async Task DoOpenFilePickerAsync() { // For learning purposes, we opted to directly get the reference // for StorageProvider APIs here inside the ViewModel. // For your real-world apps, you should follow the MVVM principles // by making service classes and locating them with DI/IoC. // See IoCFileOps project for an example of how to accomplish this. if ( Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop || desktop.MainWindow?.StorageProvider is not { } provider ) throw new NullReferenceException("Missing StorageProvider instance."); var files = await provider.OpenFilePickerAsync( new FilePickerOpenOptions() { Title = "Open Text File", AllowMultiple = false } ); return files?.Count >= 1 ? files[0] : null; } private async Task DoSaveFilePickerAsync() { // For learning purposes, we opted to directly get the reference // for StorageProvider APIs here inside the ViewModel. // For your real-world apps, you should follow the MVVM principles // by making service classes and locating them with DI/IoC. // See DepInject project for a sample of how to accomplish this. if ( Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop || desktop.MainWindow?.StorageProvider is not { } provider ) throw new NullReferenceException("Missing StorageProvider instance."); return await provider.SaveFilePickerAsync( new FilePickerSaveOptions() { Title = "Save Text File" } ); } }