From ca665f09a801bea919e9dde3618455ea7344003e Mon Sep 17 00:00:00 2001 From: Stone_Red <56473591+Stone-Red-Code@users.noreply.github.com> Date: Wed, 8 May 2024 16:07:30 +0200 Subject: [PATCH] Add import and export functionality --- src/ClipCMD/App.axaml.cs | 3 +- src/ClipCMD/Utilities/ImportExportService.cs | 79 ++++++++++++++++++++ src/ClipCMD/ViewModels/MainViewModel.cs | 9 ++- src/ClipCMD/Views/MainView.axaml | 4 +- 4 files changed, 90 insertions(+), 5 deletions(-) create mode 100644 src/ClipCMD/Utilities/ImportExportService.cs diff --git a/src/ClipCMD/App.axaml.cs b/src/ClipCMD/App.axaml.cs index 6092538..098574d 100644 --- a/src/ClipCMD/App.axaml.cs +++ b/src/ClipCMD/App.axaml.cs @@ -38,7 +38,8 @@ public partial class App : Application { desktop.MainWindow = new MainWindow(); ClipCmdCommandHandler clipCmdCommandHandler = new ClipCmdCommandHandler(desktop.MainWindow); - desktop.MainWindow.DataContext = new MainViewModel(clipCmdCommandHandler); + ImportExportService importExportService = new ImportExportService(desktop.MainWindow, clipCmdCommandHandler); + desktop.MainWindow.DataContext = new MainViewModel(clipCmdCommandHandler, importExportService); desktop.MainWindow.Closing += (sender, e) => { diff --git a/src/ClipCMD/Utilities/ImportExportService.cs b/src/ClipCMD/Utilities/ImportExportService.cs new file mode 100644 index 0000000..9a76cff --- /dev/null +++ b/src/ClipCMD/Utilities/ImportExportService.cs @@ -0,0 +1,79 @@ +using Avalonia.Controls; +using Avalonia.Platform.Storage; + +using ClipCmd.Models; + +using System.Collections.Generic; +using System.IO; +using System.Text.Json; +using System.Threading.Tasks; + +namespace ClipCmd.Utilities; + +public class ImportExportService(Window window, ClipCmdCommandHandler clipCmdCommandHandler) +{ + private readonly TopLevel topLevel = window; + + public async Task Import() + { + // Start async operation to open the dialog. + IReadOnlyList files = await topLevel.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions + { + Title = "Import ClipCMD commands", + AllowMultiple = false, + FileTypeFilter = [new FilePickerFileType("ccmd") + { + Patterns = ["*.ccmd"] + }] + }); + + if (files.Count < 1) + { + return; + } + + await using Stream stream = await files[0].OpenReadAsync(); + using StreamReader streamReader = new StreamReader(stream); + + string json = await streamReader.ReadToEndAsync(); + + clipCmdCommandHandler.ClearCommands(); + + Dictionary? commands = JsonSerializer.Deserialize>(json); + + if (commands is null) + { + return; + } + + foreach (KeyValuePair command in commands) + { + clipCmdCommandHandler.Commands.Add(command.Key, command.Value); + } + } + + public async Task Export() + { + // Start async operation to open the dialog. + IStorageFile? file = await topLevel.StorageProvider.SaveFilePickerAsync(new FilePickerSaveOptions + { + Title = "Export ClipCMD commands", + SuggestedFileName = "export.ccmd", + FileTypeChoices = [new FilePickerFileType("ccmd") + { + Patterns = ["*.ccmd"] + }] + }); + + if (file is null) + { + return; + } + + string json = JsonSerializer.Serialize(clipCmdCommandHandler.Commands); + + await using Stream stream = await file.OpenWriteAsync(); + using StreamWriter streamWriter = new StreamWriter(stream); + await streamWriter.WriteAsync(json); + } +} \ No newline at end of file diff --git a/src/ClipCMD/ViewModels/MainViewModel.cs b/src/ClipCMD/ViewModels/MainViewModel.cs index 9362d0b..f5c81d4 100644 --- a/src/ClipCMD/ViewModels/MainViewModel.cs +++ b/src/ClipCMD/ViewModels/MainViewModel.cs @@ -14,6 +14,7 @@ namespace ClipCmd.ViewModels; public class MainViewModel : ViewModelBase { private readonly ClipCmdCommandHandler clipCmdCommandHandler; + private readonly ImportExportService importExportService; public List Commands => [.. clipCmdCommandHandler.Commands.Keys.Select(x => new ClipCmdCommandItemViewModel(x, clipCmdCommandHandler))]; @@ -105,10 +106,13 @@ public class MainViewModel : ViewModelBase public ICommand AddCommand => ReactiveCommand.Create(Add); - public MainViewModel(ClipCmdCommandHandler clipCmdCommandHandler) + public ICommand ExportCommand => ReactiveCommand.Create(importExportService.Export); + public ICommand ImportCommand => ReactiveCommand.Create(importExportService.Import); + + public MainViewModel(ClipCmdCommandHandler clipCmdCommandHandler, ImportExportService importExportService) { this.clipCmdCommandHandler = clipCmdCommandHandler; - + this.importExportService = importExportService; clipCmdCommandHandler.Commands.CollectionChanged += (sender, e) => { this.RaisePropertyChanged(nameof(Commands)); @@ -119,6 +123,7 @@ public class MainViewModel : ViewModelBase public MainViewModel() { clipCmdCommandHandler = new ClipCmdCommandHandler(new()); + importExportService = new(new(), clipCmdCommandHandler); } private async void Add() diff --git a/src/ClipCMD/Views/MainView.axaml b/src/ClipCMD/Views/MainView.axaml index 28a2e0e..ba0d8f1 100644 --- a/src/ClipCMD/Views/MainView.axaml +++ b/src/ClipCMD/Views/MainView.axaml @@ -53,14 +53,14 @@ - -