From 63cb4cec2f38e0f1b8a10b4e3b4d278aeeb618a4 Mon Sep 17 00:00:00 2001 From: Christian <6939810+chkr1011@users.noreply.github.com> Date: Wed, 9 Nov 2022 21:53:39 +0100 Subject: [PATCH 01/22] Update nugets --- Source/Common/ViewLocator.cs | 9 ++- Source/Controls/AutoGrid.cs | 2 +- .../BufferEditor/BufferEditor.axaml.cs | 2 +- .../BufferPreview/BufferPreviewView.axaml.cs | 2 +- .../CertificatePicker.axaml.cs | 5 +- Source/Controls/HexBox.axaml.cs | 2 +- Source/MQTTnetApp.csproj | 21 ++--- Source/Main/MainView.axaml.cs | 6 ++ .../Connection/ConnectionOptionsView.axaml | 16 ++-- Source/Styles/Expander.axaml | 80 +++++++++---------- Source/Styles/ToolBar.axaml | 1 + 11 files changed, 81 insertions(+), 65 deletions(-) diff --git a/Source/Common/ViewLocator.cs b/Source/Common/ViewLocator.cs index 969d8d5..bc8f0b1 100644 --- a/Source/Common/ViewLocator.cs +++ b/Source/Common/ViewLocator.cs @@ -10,8 +10,13 @@ sealed class ViewLocator : IDataTemplate { readonly Dictionary _viewTypeCache = new(); - public IControl Build(object viewModel) + public IControl Build(object? viewModel) { + if (viewModel == null) + { + return new TextBlock(); + } + var viewModelTypeName = viewModel.GetType().FullName!; if (!_viewTypeCache.TryGetValue(viewModelTypeName, out var viewType)) @@ -44,7 +49,7 @@ public IControl Build(object viewModel) }; } - public bool Match(object data) + public bool Match(object? data) { return data is BaseViewModel; } diff --git a/Source/Controls/AutoGrid.cs b/Source/Controls/AutoGrid.cs index 5136421..b4c08c8 100644 --- a/Source/Controls/AutoGrid.cs +++ b/Source/Controls/AutoGrid.cs @@ -24,7 +24,7 @@ public static void SetIsNextRow(AvaloniaObject element, bool value) element.SetValue(IsNextRowProperty, value); } - protected override void ChildrenChanged(object sender, NotifyCollectionChangedEventArgs e) + protected override void ChildrenChanged(object? sender, NotifyCollectionChangedEventArgs e) { base.ChildrenChanged(sender, e); diff --git a/Source/Controls/BufferEditor/BufferEditor.axaml.cs b/Source/Controls/BufferEditor/BufferEditor.axaml.cs index c029bdd..37f9ca8 100644 --- a/Source/Controls/BufferEditor/BufferEditor.axaml.cs +++ b/Source/Controls/BufferEditor/BufferEditor.axaml.cs @@ -146,7 +146,7 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) SyncBufferFormat(); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/Source/Controls/BufferPreview/BufferPreviewView.axaml.cs b/Source/Controls/BufferPreview/BufferPreviewView.axaml.cs index 40cb31d..891e82b 100644 --- a/Source/Controls/BufferPreview/BufferPreviewView.axaml.cs +++ b/Source/Controls/BufferPreview/BufferPreviewView.axaml.cs @@ -138,7 +138,7 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) ReadBuffer(); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/Source/Controls/CertificatePicker/CertificatePicker.axaml.cs b/Source/Controls/CertificatePicker/CertificatePicker.axaml.cs index 37f866d..70101f5 100644 --- a/Source/Controls/CertificatePicker/CertificatePicker.axaml.cs +++ b/Source/Controls/CertificatePicker/CertificatePicker.axaml.cs @@ -39,9 +39,8 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) _pickButton = (Button)this.GetTemplateChild("PART_PickButton"); _pickButton.Click += OnPickButtonClicked; } - - - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/Source/Controls/HexBox.axaml.cs b/Source/Controls/HexBox.axaml.cs index 2a319d8..e349c44 100644 --- a/Source/Controls/HexBox.axaml.cs +++ b/Source/Controls/HexBox.axaml.cs @@ -49,7 +49,7 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) UpdateValues(); } - protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) + protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) { base.OnPropertyChanged(change); diff --git a/Source/MQTTnetApp.csproj b/Source/MQTTnetApp.csproj index 89a6e20..2b5e594 100644 --- a/Source/MQTTnetApp.csproj +++ b/Source/MQTTnetApp.csproj @@ -26,19 +26,20 @@ - - - - - - - + + + + + + + + - - + + - + diff --git a/Source/Main/MainView.axaml.cs b/Source/Main/MainView.axaml.cs index 8cda027..3b3c211 100644 --- a/Source/Main/MainView.axaml.cs +++ b/Source/Main/MainView.axaml.cs @@ -21,6 +21,12 @@ void InitializeComponent() void OnActivatePageRequested(object? sender, EventArgs e) { var sidebar = this.FindControl("Sidebar"); + + if (sidebar == null) + { + return; + } + foreach (TabItem tabItem in sidebar.Items) { if (ReferenceEquals(sender, tabItem.Content)) diff --git a/Source/Pages/Connection/ConnectionOptionsView.axaml b/Source/Pages/Connection/ConnectionOptionsView.axaml index 42b3073..0830f39 100644 --- a/Source/Pages/Connection/ConnectionOptionsView.axaml +++ b/Source/Pages/Connection/ConnectionOptionsView.axaml @@ -11,10 +11,16 @@ x:Class="MQTTnetApp.Pages.Connection.ConnectionOptionsView"> + + + + - @@ -152,8 +158,7 @@ - + diff --git a/Source/Styles/Expander.axaml b/Source/Styles/Expander.axaml index c4d6802..2d27f21 100644 --- a/Source/Styles/Expander.axaml +++ b/Source/Styles/Expander.axaml @@ -8,47 +8,47 @@ + Value="5" /> - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/Styles/ToolBar.axaml b/Source/Styles/ToolBar.axaml index 894a084..92a20dd 100644 --- a/Source/Styles/ToolBar.axaml +++ b/Source/Styles/ToolBar.axaml @@ -102,6 +102,7 @@ --> - - - - - - - + + + + @@ -44,7 +31,7 @@ - + + Design.Height="450" + Design.Width="800"> + + + + @@ -124,7 +122,7 @@ @@ -136,7 +134,7 @@ - + diff --git a/Source/Pages/TopicExplorer/TopicExplorerPageView.axaml.cs b/Source/Pages/TopicExplorer/TopicExplorerPageView.axaml.cs index e24309d..5df6e00 100644 --- a/Source/Pages/TopicExplorer/TopicExplorerPageView.axaml.cs +++ b/Source/Pages/TopicExplorer/TopicExplorerPageView.axaml.cs @@ -3,7 +3,7 @@ namespace mqttMultimeter.Pages.TopicExplorer; -public class TopicExplorerPageView : UserControl +public sealed partial class TopicExplorerPageView : UserControl { public TopicExplorerPageView() { diff --git a/Source/Pages/TopicExplorer/TopicExplorerPageViewModel.cs b/Source/Pages/TopicExplorer/TopicExplorerPageViewModel.cs index 8f79e64..c68103d 100644 --- a/Source/Pages/TopicExplorer/TopicExplorerPageViewModel.cs +++ b/Source/Pages/TopicExplorer/TopicExplorerPageViewModel.cs @@ -181,7 +181,7 @@ Task OnMqttMessageReceived(MqttApplicationMessageReceivedEventArgs arguments) var topic = arguments.ApplicationMessage.Topic; var path = topic.Split("/"); - return Dispatcher.UIThread.InvokeAsync(() => InsertNode(path, arguments.ApplicationMessage)); + return Dispatcher.UIThread.InvokeAsync(() => InsertNode(path, arguments.ApplicationMessage)).GetTask(); } static void SetExpandedState(TopicExplorerTreeNodeViewModel node, bool value) diff --git a/Source/Pages/TopicExplorer/TopicExplorerTreeNodeView.axaml b/Source/Pages/TopicExplorer/TopicExplorerTreeNodeView.axaml index 3d0d15c..c907891 100644 --- a/Source/Pages/TopicExplorer/TopicExplorerTreeNodeView.axaml +++ b/Source/Pages/TopicExplorer/TopicExplorerTreeNodeView.axaml @@ -1,13 +1,12 @@  + + + - + (); diff --git a/Source/Styles/Sidebar.axaml b/Source/Styles/Sidebar.axaml index 4dd9160..8b92392 100644 --- a/Source/Styles/Sidebar.axaml +++ b/Source/Styles/Sidebar.axaml @@ -16,10 +16,7 @@ RowDefinitions="*"> - + - - - - - - - - - + + + + + + + + - - - + + + From 97e8aa127a8751e3e6f95c72558f6193171b80da Mon Sep 17 00:00:00 2001 From: Christian <6939810+chkr1011@users.noreply.github.com> Date: Sun, 25 Jun 2023 12:38:22 +0200 Subject: [PATCH 03/22] Remove not needed libraries --- Source/App.axaml.cs | 2 +- Source/Pages/Info/InfoPageView.axaml.cs | 2 +- Source/Services/Mqtt/MqttClientService.cs | 3 ++- Source/Services/State/StateService.cs | 11 +++-------- Source/mqttMultimeter.csproj | 1 - 5 files changed, 7 insertions(+), 12 deletions(-) diff --git a/Source/App.axaml.cs b/Source/App.axaml.cs index d36f186..269a064 100644 --- a/Source/App.axaml.cs +++ b/Source/App.axaml.cs @@ -31,7 +31,7 @@ public sealed class App : Application public App() { - var serviceProvider = new ServiceCollection().AddLogging() + var serviceProvider = new ServiceCollection() // Services .AddSingleton() .AddSingleton() diff --git a/Source/Pages/Info/InfoPageView.axaml.cs b/Source/Pages/Info/InfoPageView.axaml.cs index bc7a380..4fba280 100644 --- a/Source/Pages/Info/InfoPageView.axaml.cs +++ b/Source/Pages/Info/InfoPageView.axaml.cs @@ -19,7 +19,7 @@ void InitializeComponent() { AvaloniaXamlLoader.Load(this); - var licenses = this.FindControl("Licenses"); + var licenses = this.FindControl("Licenses")!; licenses.Text = ReadEmbeddedMarkdown(); } diff --git a/Source/Services/Mqtt/MqttClientService.cs b/Source/Services/Mqtt/MqttClientService.cs index 2443a3e..76f1f67 100644 --- a/Source/Services/Mqtt/MqttClientService.cs +++ b/Source/Services/Mqtt/MqttClientService.cs @@ -65,7 +65,8 @@ public async Task Connect(ConnectionItemViewModel item) .WithCredentials(item.SessionOptions.UserName, item.SessionOptions.Password) .WithRequestProblemInformation(item.SessionOptions.RequestProblemInformation) .WithRequestResponseInformation(item.SessionOptions.RequestResponseInformation) - .WithKeepAlivePeriod(TimeSpan.FromSeconds(item.SessionOptions.KeepAliveInterval)); + .WithKeepAlivePeriod(TimeSpan.FromSeconds(item.SessionOptions.KeepAliveInterval)) + .WithoutPacketFragmentation(); // We do not need this optimization is this type of client. It will also increase compatibility. if (item.SessionOptions.SessionExpiryInterval > 0) { diff --git a/Source/Services/State/StateService.cs b/Source/Services/State/StateService.cs index 4409554..ede0c17 100644 --- a/Source/Services/State/StateService.cs +++ b/Source/Services/State/StateService.cs @@ -4,7 +4,6 @@ using System.IO; using System.Text.Json.Nodes; using System.Threading.Tasks; -using Microsoft.Extensions.Logging; using mqttMultimeter.Services.Data; namespace mqttMultimeter.Services.State; @@ -12,16 +11,13 @@ namespace mqttMultimeter.Services.State; public sealed class StateService { readonly JsonSerializerService _jsonSerializerService; - readonly ILogger _logger; - readonly Dictionary _state = new(); bool _isLoaded; - public StateService(JsonSerializerService jsonSerializerService, ILogger logger) + public StateService(JsonSerializerService jsonSerializerService) { _jsonSerializerService = jsonSerializerService ?? throw new ArgumentNullException(nameof(jsonSerializerService)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); } public event EventHandler? Saving; @@ -62,7 +58,6 @@ public bool TryGet(string key, out TData? data) } catch (Exception exception) { - // TODO: Use proper logging framework. Debug.WriteLine(exception); } @@ -78,7 +73,7 @@ public async Task Write() foreach (var state in _state) { var path = Path.Combine(GeneratePath(), state.Key + ".json"); - _logger.LogInformation("Writing state to \'{Path}\'", path); + Debug.WriteLine("Writing state to \'{Path}\'", path); var json = _jsonSerializerService.Serialize(state.Value); await File.WriteAllTextAsync(path, json).ConfigureAwait(false); @@ -88,7 +83,7 @@ public async Task Write() static string GeneratePath() { var path = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile); - + // We use ".MQTTnetApp" instead of ".mqttMultimeter" because the app name was changed // and the state should be still working when starting the app with the new name! path = Path.Combine(path, ".MQTTnetApp", "State"); diff --git a/Source/mqttMultimeter.csproj b/Source/mqttMultimeter.csproj index e96a8a5..077d7a9 100644 --- a/Source/mqttMultimeter.csproj +++ b/Source/mqttMultimeter.csproj @@ -37,7 +37,6 @@ - From bd520ef1f2b9cb1cbef7e94b7dd4675da217b6d8 Mon Sep 17 00:00:00 2001 From: Christian <6939810+chkr1011@users.noreply.github.com> Date: Sun, 2 Jul 2023 17:47:48 +0200 Subject: [PATCH 04/22] Update mqttMultimeter.csproj --- Source/mqttMultimeter.csproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Source/mqttMultimeter.csproj b/Source/mqttMultimeter.csproj index 077d7a9..9b5b8c5 100644 --- a/Source/mqttMultimeter.csproj +++ b/Source/mqttMultimeter.csproj @@ -28,13 +28,13 @@ - + - - - - - + + + + + From 6a0a1a543dcca455ccf9d9a281a342a21bb91c9b Mon Sep 17 00:00:00 2001 From: Christian <6939810+chkr1011@users.noreply.github.com> Date: Sat, 22 Jul 2023 11:17:50 +0200 Subject: [PATCH 05/22] Fix breaking changes --- Source/Assets/VectorIcons.axaml | 3 + .../Controls/BufferEditor/BufferEditor.axaml | 43 ++++-- .../BufferEditor/BufferEditor.axaml.cs | 142 +++++++++++------- .../BufferPreview/BufferPreviewView.axaml.cs | 50 ++++-- .../CertificatePicker.axaml.cs | 33 ++-- Source/Main/MainView.axaml.cs | 7 +- Source/Pages/Inflight/InflightPageView.axaml | 6 +- .../Pages/Inflight/InflightPageView.axaml.cs | 84 ++++++++++- .../Pages/Inflight/InflightPageViewModel.cs | 70 ++------- Source/Pages/Publish/PublishItemView.axaml | 13 +- .../TopicExplorerTreeNodeView.axaml.cs | 4 +- Source/Styles/Text.axaml | 5 + Source/mqttMultimeter.csproj | 18 +-- 13 files changed, 302 insertions(+), 176 deletions(-) diff --git a/Source/Assets/VectorIcons.axaml b/Source/Assets/VectorIcons.axaml index bc8422e..f0f5adf 100644 --- a/Source/Assets/VectorIcons.axaml +++ b/Source/Assets/VectorIcons.axaml @@ -56,4 +56,7 @@ M2.75 5C2.33579 5 2 5.33579 2 5.75C2 6.16421 2.33579 6.5 2.75 6.5H21.25C21.6642 6.5 22 6.16421 22 5.75C22 5.33579 21.6642 5 21.25 5H2.75Z M2.75 11.5C2.33579 11.5 2 11.8358 2 12.25C2 12.6642 2.33579 13 2.75 13H19C20.3807 13 21.5 14.1193 21.5 15.5C21.5 16.8807 20.3807 18 19 18H14.5607L15.2803 17.2803C15.5732 16.9874 15.5732 16.5126 15.2803 16.2197C14.9874 15.9268 14.5126 15.9268 14.2197 16.2197L12.2197 18.2197C11.9268 18.5126 11.9268 18.9874 12.2197 19.2803L14.2197 21.2803C14.5126 21.5732 14.9874 21.5732 15.2803 21.2803C15.5732 20.9874 15.5732 20.5126 15.2803 20.2197L14.5607 19.5H19C21.2091 19.5 23 17.7091 23 15.5C23 13.2909 21.2091 11.5 19 11.5H2.75Z M2 18.75C2 18.3358 2.33579 18 2.75 18H9.25C9.66421 18 10 18.3358 10 18.75C10 19.1642 9.66421 19.5 9.25 19.5H2.75C2.33579 19.5 2 19.1642 2 18.75Z M10.9093922,2.78216375 C11.9491636,2.20625071 13.2471955,2.54089334 13.8850247,3.52240345 L13.9678229,3.66023048 L21.7267791,17.6684928 C21.9115773,18.0021332 22.0085303,18.3772743 22.0085303,18.7586748 C22.0085303,19.9495388 21.0833687,20.9243197 19.9125791,21.003484 L19.7585303,21.0086748 L4.24277801,21.0086748 C3.86146742,21.0086748 3.48641186,20.9117674 3.15282824,20.7270522 C2.11298886,20.1512618 1.7079483,18.8734454 2.20150311,17.8120352 L2.27440063,17.668725 L10.0311968,3.66046274 C10.2357246,3.291099 10.5400526,2.98673515 10.9093922,2.78216375 Z M20.4146132,18.3952808 L12.6556571,4.3870185 C12.4549601,4.02467391 11.9985248,3.89363262 11.6361802,4.09432959 C11.5438453,4.14547244 11.4637001,4.21532637 11.4006367,4.29899869 L11.3434484,4.38709592 L3.58665221,18.3953582 C3.385998,18.7577265 3.51709315,19.2141464 3.87946142,19.4148006 C3.96285732,19.4609794 4.05402922,19.4906942 4.14802472,19.5026655 L4.24277801,19.5086748 L19.7585303,19.5086748 C20.1727439,19.5086748 20.5085303,19.1728883 20.5085303,18.7586748 C20.5085303,18.6633247 20.4903516,18.5691482 20.455275,18.4811011 L20.4146132,18.3952808 L12.6556571,4.3870185 L20.4146132,18.3952808 Z M12.0004478,16.0017852 C12.5519939,16.0017852 12.9991104,16.4489016 12.9991104,17.0004478 C12.9991104,17.5519939 12.5519939,17.9991104 12.0004478,17.9991104 C11.4489016,17.9991104 11.0017852,17.5519939 11.0017852,17.0004478 C11.0017852,16.4489016 11.4489016,16.0017852 12.0004478,16.0017852 Z M11.9962476,8.49954934 C12.3759432,8.49924613 12.689964,8.78114897 12.7399193,9.14718469 L12.7468472,9.24894974 L12.750448,13.7505438 C12.7507788,14.1647572 12.4152611,14.5008121 12.0010476,14.5011439 C11.621352,14.5014471 11.3073312,14.2195442 11.257376,13.8535085 L11.250448,13.7517435 L11.2468472,9.25014944 C11.2465164,8.83593601 11.5820341,8.49988112 11.9962476,8.49954934 Z + + M10,2.75 C14.0041,2.75 17.25,5.99594 17.25,10 C17.25,11.6236562 16.7162402,13.1225957 15.8146692,14.3310347 L15.6295,14.5688 L20.5303,19.4697 C20.8232,19.7626 20.8232,20.2374 20.5303,20.5303 C20.2936778,20.7670111 19.938142,20.8124333 19.6558506,20.6665667 L19.5538,20.6029 L19.4697,20.5303 L14.5688,15.6295 C13.3219,16.6427 11.7319,17.25 10,17.25 C5.99593,17.25 2.75,14.0041 2.75,10 C2.75,5.99594 5.99593,2.75 10,2.75 Z M10,4.25 C6.82436,4.25 4.25,6.82436 4.25,10 C4.25,13.1756 6.82436,15.75 10,15.75 C13.1756,15.75 15.75,13.1756 15.75,10 C15.75,6.82436 13.1756,4.25 10,4.25 Z M12.75,9.25 C13.1642,9.25 13.5,9.58579 13.5,10 C13.5,10.4142 13.1642,10.75 12.75,10.75 L7.25,10.75 C6.83578,10.75 6.5,10.4142 6.5,10 C6.5,9.58579 6.83578,9.25 7.25,9.25 L12.75,9.25 Z + M10,2.75 C14.0041,2.75 17.25,5.99594 17.25,10 C17.25,11.7319 16.6427,13.3219 15.6295,14.5688 L20.5303,19.4697 C20.8232,19.7626 20.8232,20.2374 20.5303,20.5303 C20.2641,20.7966 19.8474,20.8208 19.5538,20.6029 L19.4697,20.5303 L14.5688,15.6295 C13.3219,16.6427 11.7319,17.25 10,17.25 C5.99593,17.25 2.75,14.0041 2.75,10 C2.75,5.99594 5.99593,2.75 10,2.75 Z M10,4.25 C6.82436,4.25 4.25,6.82436 4.25,10 C4.25,13.1756 6.82436,15.75 10,15.75 C13.1756,15.75 15.75,13.1756 15.75,10 C15.75,6.82436 13.1756,4.25 10,4.25 Z M10,6.5 C10.3796833,6.5 10.6934889,6.78215687 10.7431531,7.14823019 L10.75,7.25 L10.75,9.25 L12.75,9.25 C13.1642,9.25 13.5,9.58579 13.5,10 C13.5,10.3796833 13.2178347,10.6934889 12.8517677,10.7431531 L12.75,10.75 L10.75,10.75 L10.75,12.75 C10.75,13.1642 10.4142,13.5 10,13.5 C9.62029833,13.5 9.30650806,13.2178347 9.25684649,12.8517677 L9.25,12.75 L9.25,10.75 L7.25,10.75 C6.83578,10.75 6.5,10.4142 6.5,10 C6.5,9.6203075 6.78214847,9.30650958 7.14822809,9.25684668 L7.25,9.25 L9.25,9.25 L9.25,7.25 C9.25,6.83579 9.58578,6.5 10,6.5 Z \ No newline at end of file diff --git a/Source/Controls/BufferEditor/BufferEditor.axaml b/Source/Controls/BufferEditor/BufferEditor.axaml index 630d6c4..0965dd0 100644 --- a/Source/Controls/BufferEditor/BufferEditor.axaml +++ b/Source/Controls/BufferEditor/BufferEditor.axaml @@ -39,9 +39,14 @@ - - - + + + + - - - + + + + + - + + + + + diff --git a/Source/Controls/BufferEditor/BufferEditor.axaml.cs b/Source/Controls/BufferEditor/BufferEditor.axaml.cs index 18efca8..5717ab9 100644 --- a/Source/Controls/BufferEditor/BufferEditor.axaml.cs +++ b/Source/Controls/BufferEditor/BufferEditor.axaml.cs @@ -1,18 +1,16 @@ using System; using System.Collections.Generic; using System.IO; -using System.Linq; -using System.Threading; using System.Xml.Linq; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Interactivity; +using Avalonia.Platform.Storage; using Avalonia.Threading; using AvaloniaEdit; using AvaloniaEdit.TextMate; using mqttMultimeter.Extensions; -using mqttMultimeter.Main; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using TextMateSharp.Grammars; @@ -21,30 +19,34 @@ namespace mqttMultimeter.Controls; public sealed class BufferEditor : TemplatedControl { - static readonly List FileDialogFilters = new() + static readonly List FileDialogFilters = new() { - new FileDialogFilter + new FilePickerFileType("JSON files") { - Name = "Text files", - Extensions = new List + Patterns = new List { - "txt" + "*.json" } }, - new FileDialogFilter + new FilePickerFileType("Text files") { - Name = "JSON files", - Extensions = new List + Patterns = new List { - "json" + "*.txt" } }, - new FileDialogFilter + new FilePickerFileType("XML files") { - Name = "XML files", - Extensions = new List + Patterns = new List { - "xml" + "*.xml" + } + }, + new FilePickerFileType("All files") + { + Patterns = new List + { + "*" } } }; @@ -141,6 +143,18 @@ protected override void OnApplyTemplate(TemplateAppliedEventArgs e) _reformatButton = (Button)this.GetTemplateChild("ReformatButton"); _reformatButton.Click += OnReformat; + var increaseFontSizeButton = (Button)this.GetTemplateChild("IncreaseFontSizeButton"); + increaseFontSizeButton.Click += (_, __) => + { + _textEditor.FontSize += 0.5; + }; + + var decreaseFontSizeButton = (Button)this.GetTemplateChild("DecreaseFontSizeButton"); + decreaseFontSizeButton.Click += (_, __) => + { + _textEditor.FontSize -= 0.5; + }; + SyncText(); SyncGrammar(); SyncBufferFormat(); @@ -172,7 +186,8 @@ void OnCopyToClipboard(object? sender, RoutedEventArgs e) { if (!string.IsNullOrEmpty(Buffer)) { - //Application.Current?.Clipboard?.SetTextAsync(Buffer); + var clipboard = TopLevel.GetTopLevel(this)?.Clipboard; + _ = clipboard?.SetTextAsync(Buffer); } } @@ -180,25 +195,32 @@ void OnLoadFromFile(object? sender, RoutedEventArgs e) { Dispatcher.UIThread.InvokeAsync(async () => { - var openFileDialog = new OpenFileDialog(); - openFileDialog.Filters!.AddRange(FileDialogFilters); + var filePickerOptions = new FilePickerOpenOptions + { + FileTypeFilter = FileDialogFilters + }; - var fileName = (await openFileDialog.ShowAsync(MainWindow.Instance))?.FirstOrDefault(); - if (!string.IsNullOrEmpty(fileName)) + var files = await TopLevel.GetTopLevel(this)!.StorageProvider.OpenFilePickerAsync(filePickerOptions); + if (files.Count == 0) { - try - { - Buffer = await File.ReadAllTextAsync(fileName, CancellationToken.None); - } - catch (FileNotFoundException) - { - // Ignore this case! - } - catch (Exception exception) + return; + } + + try + { + using (var stream = new StreamReader(await files[0].OpenReadAsync())) { - App.ShowException(exception); + Buffer = await stream.ReadToEndAsync(); } } + catch (FileNotFoundException) + { + // Ignore this case! + } + catch (Exception exception) + { + App.ShowException(exception); + } }); } @@ -230,29 +252,47 @@ void OnReformat(object? sender, RoutedEventArgs e) void OnSaveToFile(object? sender, RoutedEventArgs e) { - var saveFileDialog = new SaveFileDialog(); - saveFileDialog.Filters!.AddRange(FileDialogFilters); - - // TODO: Not working! - if (IsJson) - { - saveFileDialog.DefaultExtension = ".json"; - } - else if (IsXml) - { - saveFileDialog.DefaultExtension = ".xml"; - } - else - { - saveFileDialog.DefaultExtension = ".txt"; - } - Dispatcher.UIThread.InvokeAsync(async () => { - var fileName = await saveFileDialog.ShowAsync(MainWindow.Instance); - if (!string.IsNullOrEmpty(fileName)) + try + { + var filePickerOptions = new FilePickerSaveOptions + { + FileTypeChoices = FileDialogFilters + }; + + // TODO: Not working! + if (IsJson) + { + filePickerOptions.DefaultExtension = ".json"; + } + else if (IsXml) + { + filePickerOptions.DefaultExtension = ".xml"; + } + else + { + filePickerOptions.DefaultExtension = ".txt"; + } + + var file = await TopLevel.GetTopLevel(this)!.StorageProvider.SaveFilePickerAsync(filePickerOptions); + if (file == null) + { + return; + } + + await using (var stream = new StreamWriter(await file.OpenWriteAsync())) + { + await stream.WriteAsync(Buffer ?? string.Empty); + } + } + catch (FileNotFoundException) + { + // Ignore this case! + } + catch (Exception exception) { - await File.WriteAllTextAsync(fileName, Buffer ?? string.Empty, CancellationToken.None); + App.ShowException(exception); } }); } diff --git a/Source/Controls/BufferPreview/BufferPreviewView.axaml.cs b/Source/Controls/BufferPreview/BufferPreviewView.axaml.cs index 0ad9426..e1b99f7 100644 --- a/Source/Controls/BufferPreview/BufferPreviewView.axaml.cs +++ b/Source/Controls/BufferPreview/BufferPreviewView.axaml.cs @@ -6,18 +6,17 @@ using System.Text; using System.Text.Json; using System.Text.Json.Nodes; -using System.Threading; using System.Xml.Linq; using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Interactivity; +using Avalonia.Platform.Storage; using Avalonia.Threading; using AvaloniaEdit; using AvaloniaEdit.TextMate; using MessagePack; using mqttMultimeter.Extensions; -using mqttMultimeter.Main; using mqttMultimeter.Services.Data; using mqttMultimeter.Text; using TextMateSharp.Grammars; @@ -162,28 +161,49 @@ void OnCopyToClipboard(object? sender, RoutedEventArgs e) { if (!string.IsNullOrEmpty(_content)) { - //Application.Current?.Clipboard?.SetTextAsync(_content); + var clipboard = TopLevel.GetTopLevel(this)?.Clipboard; + _ = clipboard?.SetTextAsync(_content); } } void OnSaveToFile(object? sender, RoutedEventArgs e) { - var saveFileDialog = new SaveFileDialog(); - saveFileDialog.Filters!.Add(new FileDialogFilter + Dispatcher.UIThread.InvokeAsync(async () => { - Name = "Binary files", - Extensions = new List + try { - "bin" + var filePickerOptions = new FilePickerSaveOptions + { + FileTypeChoices = new List + { + new("Binary files") + { + Patterns = new[] + { + "*.bin" + } + } + } + }; + + var file = await TopLevel.GetTopLevel(this)!.StorageProvider.SaveFilePickerAsync(filePickerOptions); + if (file == null) + { + return; + } + + await using (var stream = await file.OpenWriteAsync()) + { + await stream.WriteAsync(Buffer ?? Array.Empty()); + } } - }); - - Dispatcher.UIThread.InvokeAsync(async () => - { - var fileName = await saveFileDialog.ShowAsync(MainWindow.Instance); - if (!string.IsNullOrEmpty(fileName)) + catch (FileNotFoundException) + { + // Ignore this case! + } + catch (Exception exception) { - await File.WriteAllBytesAsync(fileName, Buffer ?? Array.Empty(), CancellationToken.None); + App.ShowException(exception); } }); } diff --git a/Source/Controls/CertificatePicker/CertificatePicker.axaml.cs b/Source/Controls/CertificatePicker/CertificatePicker.axaml.cs index ae014cb..96fa088 100644 --- a/Source/Controls/CertificatePicker/CertificatePicker.axaml.cs +++ b/Source/Controls/CertificatePicker/CertificatePicker.axaml.cs @@ -1,13 +1,11 @@ -using System.Collections.Generic; -using System.Linq; -using Avalonia; +using Avalonia; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Data; using Avalonia.Interactivity; +using Avalonia.Platform.Storage; using Avalonia.Threading; using mqttMultimeter.Extensions; -using mqttMultimeter.Main; namespace mqttMultimeter.Controls; @@ -51,31 +49,30 @@ void OnPickButtonClicked(object? sender, RoutedEventArgs e) { Dispatcher.UIThread.InvokeAsync(async () => { - var openFileDialog = new OpenFileDialog + var filePickerOptions = new FilePickerOpenOptions { - Title = "Choose certificate", - Filters = new List + AllowMultiple = false, + FileTypeFilter = new[] { - new() + new FilePickerFileType("Certificates") { - Extensions = + Patterns = new[] { - "pem", - "crt", - "pfx" - }, - Name = "Certificates" + "*.pem", + "*.crt", + "*.pfx" + } } } }; - - var filenames = await openFileDialog.ShowAsync(MainWindow.Instance); - if (filenames?.Length == 0) + + var files = await TopLevel.GetTopLevel(this)!.StorageProvider.OpenFilePickerAsync(filePickerOptions); + if (files.Count == 0) { return; } - Path = filenames?.FirstOrDefault() ?? string.Empty; + Path = files[0].Path.LocalPath; }); } } \ No newline at end of file diff --git a/Source/Main/MainView.axaml.cs b/Source/Main/MainView.axaml.cs index 413cbcc..ef1cca5 100644 --- a/Source/Main/MainView.axaml.cs +++ b/Source/Main/MainView.axaml.cs @@ -27,8 +27,13 @@ void OnActivatePageRequested(object? sender, EventArgs e) return; } - foreach (TabItem tabItem in sidebar.Items) + foreach (TabItem? tabItem in sidebar.Items) { + if (tabItem == null) + { + continue; + } + if (ReferenceEquals(sender, tabItem.Content)) { sidebar.SelectedItem = tabItem; diff --git a/Source/Pages/Inflight/InflightPageView.axaml b/Source/Pages/Inflight/InflightPageView.axaml index f0726ea..3bd7f1a 100644 --- a/Source/Pages/Inflight/InflightPageView.axaml +++ b/Source/Pages/Inflight/InflightPageView.axaml @@ -37,13 +37,13 @@ diff --git a/Source/Pages/Inflight/InflightPageView.axaml.cs b/Source/Pages/Inflight/InflightPageView.axaml.cs index f76f62b..eb93871 100644 --- a/Source/Pages/Inflight/InflightPageView.axaml.cs +++ b/Source/Pages/Inflight/InflightPageView.axaml.cs @@ -1,10 +1,29 @@ -using Avalonia.Controls; +using System; +using System.Collections.Generic; +using System.IO; +using Avalonia.Controls; +using Avalonia.Interactivity; using Avalonia.Markup.Xaml; +using Avalonia.Platform.Storage; +using Avalonia.Threading; namespace mqttMultimeter.Pages.Inflight; public sealed partial class InflightPageView : UserControl { + const string ExportDialogTitle = "Export Inflight items"; + + static readonly List ExportDialogFilter = new() + { + new FilePickerFileType("MQTT Inflight item exports") + { + Patterns = new[] + { + "*.mqtt_inflight" + } + } + }; + public InflightPageView() { InitializeComponent(); @@ -14,4 +33,67 @@ void InitializeComponent() { AvaloniaXamlLoader.Load(this); } + + void OnExportItems(object? _, RoutedEventArgs __) + { + Dispatcher.UIThread.InvokeAsync(async () => + { + try + { + var filePickerOptions = new FilePickerSaveOptions + { + Title = ExportDialogTitle, + FileTypeChoices = ExportDialogFilter + }; + + var file = await TopLevel.GetTopLevel(this)!.StorageProvider.SaveFilePickerAsync(filePickerOptions); + if (file == null) + { + return; + } + + await ((InflightPageViewModel)DataContext!).ExportItems(file.Path.LocalPath); + } + catch (FileNotFoundException) + { + // Ignore this case! + } + catch (Exception exception) + { + App.ShowException(exception); + } + }); + } + + void OnImportItems(object? _, RoutedEventArgs __) + { + Dispatcher.UIThread.InvokeAsync(async () => + { + try + { + var filePickerOptions = new FilePickerOpenOptions + { + AllowMultiple = false, + Title = ExportDialogTitle, + FileTypeFilter = ExportDialogFilter + }; + + var files = await TopLevel.GetTopLevel(this)!.StorageProvider.OpenFilePickerAsync(filePickerOptions); + if (files.Count == 0) + { + return; + } + + await ((InflightPageViewModel)DataContext!).ImportItems(files[0].Path.LocalPath); + } + catch (FileNotFoundException) + { + // Ignore this case! + } + catch (Exception exception) + { + App.ShowException(exception); + } + }); + } } \ No newline at end of file diff --git a/Source/Pages/Inflight/InflightPageViewModel.cs b/Source/Pages/Inflight/InflightPageViewModel.cs index e3fb637..8267979 100644 --- a/Source/Pages/Inflight/InflightPageViewModel.cs +++ b/Source/Pages/Inflight/InflightPageViewModel.cs @@ -1,17 +1,13 @@ using System; -using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; -using System.Linq; using System.Reactive.Linq; using System.Threading; using System.Threading.Tasks; -using Avalonia.Controls; using Avalonia.Threading; using DynamicData; using mqttMultimeter.Common; using mqttMultimeter.Controls; -using mqttMultimeter.Main; using mqttMultimeter.Pages.Inflight.Export; using mqttMultimeter.Services.Mqtt; using MQTTnet; @@ -22,17 +18,6 @@ namespace mqttMultimeter.Pages.Inflight; public sealed class InflightPageViewModel : BasePageViewModel { - const string ExportDialogTitle = "Export Inflight items"; - - static readonly FileDialogFilter ExportDialogFilter = new() - { - Name = "MQTT Inflight item exports", - Extensions = new List - { - "mqtt_inflight" - } - }; - readonly InflightPageItemExportService _exportService; readonly ReadOnlyObservableCollection _items; readonly SourceList _itemsSource = new(); @@ -91,15 +76,16 @@ public Task AppendMessage(MqttApplicationMessage message) var newItem = CreateItemViewModel(message); return Dispatcher.UIThread.InvokeAsync(() => - { - _itemsSource.Add(newItem); - - // TODO: Move to configuration. - if (_itemsSource.Count > 1000) { - _itemsSource.RemoveAt(0); - } - }).GetTask(); + _itemsSource.Add(newItem); + + // TODO: Move to configuration. + if (_itemsSource.Count > 1000) + { + _itemsSource.RemoveAt(0); + } + }) + .GetTask(); } public void ClearItems() @@ -107,45 +93,19 @@ public void ClearItems() _itemsSource.Clear(); } - public async Task ExportItems() + public Task ExportItems(string path) { - var saveFileDialog = new SaveFileDialog - { - Title = ExportDialogTitle - }; - - saveFileDialog.Filters?.Add(ExportDialogFilter); - - var fileName = await saveFileDialog.ShowAsync(MainWindow.Instance); - if (string.IsNullOrEmpty(fileName)) - { - return; - } - - await _exportService.Export(this, fileName); + return _exportService.Export(this, path); } - public async Task ImportItems() + public Task ImportItems(string path) { - var openFileDialog = new OpenFileDialog + if (!File.Exists(path)) { - Title = ExportDialogTitle - }; - - openFileDialog.Filters?.Add(ExportDialogFilter); - - var fileName = (await openFileDialog.ShowAsync(MainWindow.Instance))?.FirstOrDefault(); - if (string.IsNullOrEmpty(fileName)) - { - return; - } - - if (!File.Exists(fileName)) - { - return; + return Task.CompletedTask; } - await _exportService.Import(this, fileName); + return _exportService.Import(this, path); } Func BuildFilter(string? searchText) diff --git a/Source/Pages/Publish/PublishItemView.axaml b/Source/Pages/Publish/PublishItemView.axaml index 7fece1a..10a5b88 100644 --- a/Source/Pages/Publish/PublishItemView.axaml +++ b/Source/Pages/Publish/PublishItemView.axaml @@ -57,10 +57,11 @@ + Content="Content type" + Classes="caption" /> @@ -125,7 +126,7 @@ Content="Message expiry interval" /> @@ -142,7 +143,7 @@ Grid.Row="3" Value="{Binding TopicAlias}" Minimum="0" - Classes="value" + Classes="code_text value" Maximum="65535" /> diff --git a/Source/Pages/TopicExplorer/TopicExplorerTreeNodeView.axaml.cs b/Source/Pages/TopicExplorer/TopicExplorerTreeNodeView.axaml.cs index 60b013a..8fac7f4 100644 --- a/Source/Pages/TopicExplorer/TopicExplorerTreeNodeView.axaml.cs +++ b/Source/Pages/TopicExplorer/TopicExplorerTreeNodeView.axaml.cs @@ -29,18 +29,16 @@ void OnDataContextChanged(object? sender, EventArgs e) void OnMessagesChanged(object? sender, EventArgs eventArgs) { - Control control = this; + Control? control = this; while (control is not TreeViewItem) { control = control.GetVisualParent(); - if (control == null) { break; } } - if (control != null) { var viewModel = (TopicExplorerTreeNodeViewModel)control.DataContext!; diff --git a/Source/Styles/Text.axaml b/Source/Styles/Text.axaml index b6cac53..fe61ca2 100644 --- a/Source/Styles/Text.axaml +++ b/Source/Styles/Text.axaml @@ -35,6 +35,11 @@ + + \ No newline at end of file From 3ffc38dbff25adc14cbe62d3e93075caed14bdc3 Mon Sep 17 00:00:00 2001 From: Christian <6939810+chkr1011@users.noreply.github.com> Date: Sun, 18 Feb 2024 15:11:43 +0100 Subject: [PATCH 13/22] Improve error box layout. --- Source/Controls/ErrorBox/ErrorBox.axaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/Controls/ErrorBox/ErrorBox.axaml b/Source/Controls/ErrorBox/ErrorBox.axaml index b662248..33b1e96 100644 --- a/Source/Controls/ErrorBox/ErrorBox.axaml +++ b/Source/Controls/ErrorBox/ErrorBox.axaml @@ -27,6 +27,8 @@ Date: Sun, 18 Feb 2024 15:11:55 +0100 Subject: [PATCH 14/22] Update nugets. --- Source/mqttMultimeter.csproj | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/mqttMultimeter.csproj b/Source/mqttMultimeter.csproj index 30b6f6c..d3842c5 100644 --- a/Source/mqttMultimeter.csproj +++ b/Source/mqttMultimeter.csproj @@ -28,16 +28,16 @@ - - - - - - - - + + + + + + + + - + From ede5c0e630f643245a72a8b85542d43d70bf846a Mon Sep 17 00:00:00 2001 From: Christian <6939810+chkr1011@users.noreply.github.com> Date: Sun, 18 Feb 2024 15:28:12 +0100 Subject: [PATCH 15/22] Fix typos. --- Source/Pages/Connection/ConnectionItemView.axaml | 2 +- Source/Pages/Info/InfoPageView.axaml | 2 +- Source/Pages/Publish/PublishItemView.axaml | 2 +- Source/Pages/Subscriptions/SubscriptionItemView.axaml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Pages/Connection/ConnectionItemView.axaml b/Source/Pages/Connection/ConnectionItemView.axaml index ff0df86..293d5b2 100644 --- a/Source/Pages/Connection/ConnectionItemView.axaml +++ b/Source/Pages/Connection/ConnectionItemView.axaml @@ -95,7 +95,7 @@ - + diff --git a/Source/Pages/Info/InfoPageView.axaml b/Source/Pages/Info/InfoPageView.axaml index 8afeee3..511f362 100644 --- a/Source/Pages/Info/InfoPageView.axaml +++ b/Source/Pages/Info/InfoPageView.axaml @@ -152,7 +152,7 @@ - + diff --git a/Source/Pages/Subscriptions/SubscriptionItemView.axaml b/Source/Pages/Subscriptions/SubscriptionItemView.axaml index 096d185..0025e83 100644 --- a/Source/Pages/Subscriptions/SubscriptionItemView.axaml +++ b/Source/Pages/Subscriptions/SubscriptionItemView.axaml @@ -145,7 +145,7 @@ - + From 6fe31c25e51dfee1ac6cde8e7499eae9703a01ce Mon Sep 17 00:00:00 2001 From: Christian <6939810+chkr1011@users.noreply.github.com> Date: Sun, 18 Feb 2024 14:48:43 +0100 Subject: [PATCH 16/22] Fix margins and font in server page. --- Source/Pages/Connection/ConnectionOptionsView.axaml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Source/Pages/Connection/ConnectionOptionsView.axaml b/Source/Pages/Connection/ConnectionOptionsView.axaml index d87cfef..bb37cef 100644 --- a/Source/Pages/Connection/ConnectionOptionsView.axaml +++ b/Source/Pages/Connection/ConnectionOptionsView.axaml @@ -75,7 +75,7 @@ Content="{Binding ServerOptions.SelectedTransport.HostDisplayValue}" /> + Classes="value code_text" />