From 83111d56427bc023134273872416726c01f88213 Mon Sep 17 00:00:00 2001 From: Christoph Hofmann Date: Fri, 19 Jan 2024 22:36:31 +0100 Subject: [PATCH] Fixed issue with sitemap rendering Signed-off-by: Christoph Hofmann --- .../Contracts/IOpenHABClient.cs | 1 + src/openHAB.Core.Client/OpenHABClient.cs | 58 ++- src/openHAB.Core/Services/SitemapService.cs | 76 +++- src/openHAB.Windows/App.xaml.cs | 25 +- src/openHAB.Windows/MainWindow.xaml | 311 +++++++++++++++- src/openHAB.Windows/MainWindow.xaml.cs | 119 ++++++ src/openHAB.Windows/View/MainPage.xaml | 303 +-------------- src/openHAB.Windows/View/MainPage.xaml.cs | 109 +----- src/openHAB.Windows/View/SettingsPage.xaml | 349 ++++++++++-------- src/openHAB.Windows/View/SettingsPage.xaml.cs | 2 - src/openHAB.Windows/View/SitemapPage.xaml | 30 +- src/openHAB.Windows/View/SitemapPage.xaml.cs | 63 ++-- .../ViewModel/MainViewModel.cs | 4 +- .../ViewModel/SitemapViewModel.cs | 151 ++++---- 14 files changed, 897 insertions(+), 704 deletions(-) diff --git a/src/openHAB.Core.Client/Contracts/IOpenHABClient.cs b/src/openHAB.Core.Client/Contracts/IOpenHABClient.cs index 78a024e2..2150eed3 100644 --- a/src/openHAB.Core.Client/Contracts/IOpenHABClient.cs +++ b/src/openHAB.Core.Client/Contracts/IOpenHABClient.cs @@ -61,5 +61,6 @@ public interface IOpenHABClient /// Starts listening to server events. /// void StartItemUpdates(System.Threading.CancellationToken token); + Task GetSitemap(string sitemapLink, OpenHABVersion version); } } diff --git a/src/openHAB.Core.Client/OpenHABClient.cs b/src/openHAB.Core.Client/OpenHABClient.cs index 04b9ba3f..dab9668d 100644 --- a/src/openHAB.Core.Client/OpenHABClient.cs +++ b/src/openHAB.Core.Client/OpenHABClient.cs @@ -80,7 +80,18 @@ public async Task> LoadItemsFromSitemap(string sitema if (version == OpenHABVersion.Two || version == OpenHABVersion.Three || version == OpenHABVersion.Four) { JObject jsonObject = JObject.Parse(resultString); - items = JsonConvert.DeserializeObject>(jsonObject["homepage"]["widgets"].ToString()); + + string content = string.Empty; + if (jsonObject["homepage"] == null) + { + content = jsonObject["widgets"].ToString(); + } + else + { + content = jsonObject["homepage"]["widgets"].ToString(); + } + + items = JsonConvert.DeserializeObject>(content); } else { @@ -105,6 +116,51 @@ public async Task> LoadItemsFromSitemap(string sitema } } + public async Task GetSitemap(string sitemapLink, OpenHABVersion version) + { + try + { + _logger.LogInformation($"Get sitemap by link '{sitemapLink}'"); + + HttpResponseMessage result = await _openHABHttpClient.Client(_connection).GetAsync(sitemapLink).ConfigureAwait(false); + if (!result.IsSuccessStatusCode) + { + _logger.LogError($"Http request for loading sitemap failed, ErrorCode:'{result.StatusCode}'"); + throw new OpenHABException($"{result.StatusCode} received from server"); + } + + string resultString = await result.Content.ReadAsStringAsync().ConfigureAwait(false); + + OpenHABSitemap sitemap = null; + if (version == OpenHABVersion.Two || version == OpenHABVersion.Three || version == OpenHABVersion.Four) + { + JObject jsonObject = JObject.Parse(resultString); + sitemap = JsonConvert.DeserializeObject(jsonObject["homepage"].ToString()); + } + else + { + string message = "openHAB version is not supported."; + _logger.LogError(message); + throw new OpenHABException(message); + } + + _logger.LogInformation($"Loaded '{sitemap.Name}' sitemap successfully from server"); + + return sitemap; + } + catch (ArgumentNullException ex) + { + _logger.LogError(ex, "GetSitemap failed."); + throw new OpenHABException("Invalid call", ex); + } + catch (Exception ex) + { + _logger.LogError(ex, "GetSitemap failed."); + throw new OpenHABException("Invalid call", ex); + } + } + + /// public async Task GetItemByName(string itemName) { diff --git a/src/openHAB.Core/Services/SitemapService.cs b/src/openHAB.Core/Services/SitemapService.cs index 91e6ef73..4d22e6c4 100644 --- a/src/openHAB.Core/Services/SitemapService.cs +++ b/src/openHAB.Core/Services/SitemapService.cs @@ -14,13 +14,22 @@ namespace openHAB.Core.Services { + /// + /// Service for managing sitemaps in openHAB. + /// public class SitemapService { - private readonly ISettingsService _settingsService; - private readonly IOpenHABClient _openHABClient; private readonly ILogger _logger; + private readonly IOpenHABClient _openHABClient; + private readonly ISettingsService _settingsService; private ServerInfo _serverInfo; + /// + /// Initializes a new instance of the class. + /// + /// The settings service. + /// The openHAB client. + /// The logger. public SitemapService(ISettingsService settingsService, IOpenHABClient openHABClient, ILogger logger) { _settingsService = settingsService; @@ -28,7 +37,45 @@ public SitemapService(ISettingsService settingsService, IOpenHABClient openHABCl _logger = logger; } - public async Task> GetSitemaps(CancellationToken loadCancellationToken) + /// + /// Gets the sitemap by URL. + /// + /// The sitemap URL. + /// The object representing the sitemap. + public async Task GetSitemapByUrlAsync(string sitemapUrl) + { + try + { + _serverInfo = await InitalizeConnectionAsync(); + if (_serverInfo == null) + { + return null; + } + _settingsService.ServerVersion = _serverInfo.Version; + + OpenHABSitemap sitemap = await _openHABClient.GetSitemap(sitemapUrl, _serverInfo.Version).ConfigureAwait(false); + return sitemap; + } + catch (OpenHABException ex) + { + _logger.LogError(ex, $"Loading sitemap {sitemapUrl} failed."); + StrongReferenceMessenger.Default.Send(new ConnectionErrorMessage(ex.Message)); + throw; + } + catch (Exception ex) + { + _logger.LogError(ex, "Load sitemap data failed."); + } + + return null; + } + + /// + /// Gets the list of sitemaps. + /// + /// The cancellation token for the load operation. + /// The list of objects representing the sitemaps. + public async Task> GetSitemapsAsync(CancellationToken loadCancellationToken) { try { @@ -73,12 +120,29 @@ public async Task> GetSitemaps(CancellationToken loadCancel return null; } + /// + /// Loads the items from a sitemap. + /// + /// The sitemap model. + /// The collection of objects representing the items. public async Task> LoadItemsFromSitemapAsync(OpenHABSitemap model) { ICollection widgetModels = await _openHABClient.LoadItemsFromSitemap(model.Link, _serverInfo.Version).ConfigureAwait(false); return widgetModels; } + /// + /// Sends a command to an item. + /// + /// The item to send the command to. + /// The command to send. + /// The object representing the result of the command. + public async Task> SendItemCommand(OpenHABItem item, string command) + { + HttpResponseResult result = await _openHABClient.SendCommand(item, command).ConfigureAwait(false); + return result; + } + private async Task InitalizeConnectionAsync() { Settings settings = _settingsService.Load(); @@ -108,11 +172,5 @@ private async Task InitalizeConnectionAsync() return serverInfo; } - - public async Task> SendItemCommand(OpenHABItem item, string command) - { - HttpResponseResult result = await _openHABClient.SendCommand(item, command).ConfigureAwait(false); - return result; - } } } diff --git a/src/openHAB.Windows/App.xaml.cs b/src/openHAB.Windows/App.xaml.cs index 1f522fea..ea04414e 100644 --- a/src/openHAB.Windows/App.xaml.cs +++ b/src/openHAB.Windows/App.xaml.cs @@ -5,6 +5,7 @@ using Microsoft.UI.Dispatching; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; +using Microsoft.UI.Xaml.Media; using Microsoft.Windows.AppLifecycle; using openHAB.Core.Notification.Contracts; using openHAB.Core.Services.Contracts; @@ -81,21 +82,21 @@ protected override async void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventA // Initialize MainWindow here MainWindow = new MainWindow(); + //Frame rootFrame = MainWindow.RootFrame; - Frame rootFrame = MainWindow.Content as Frame; - if (rootFrame == null) - { - // Create a Frame to act as the navigation context and navigate to the first page - rootFrame = new Frame(); + //if (rootFrame == null) + //{ + // // Create a Frame to act as the navigation context and navigate to the first page + // rootFrame = new Frame(); - // Place the frame in the current Window - MainWindow.Content = rootFrame; - } + // // Place the frame in the current Window + // MainWindow.Content = rootFrame; + //} - if (rootFrame.Content == null) - { - rootFrame.Navigate(typeof(MainPage), e.Arguments); - } + //if (rootFrame.Content == null) + //{ + // rootFrame.Navigate(typeof(MainPage), e.Arguments); + //} MainWindow.Activate(); } diff --git a/src/openHAB.Windows/MainWindow.xaml b/src/openHAB.Windows/MainWindow.xaml index 48a2b54c..ef6b0235 100644 --- a/src/openHAB.Windows/MainWindow.xaml +++ b/src/openHAB.Windows/MainWindow.xaml @@ -1,12 +1,319 @@  + Title="openHab" + x:Name="Window"> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/openHAB.Windows/MainWindow.xaml.cs b/src/openHAB.Windows/MainWindow.xaml.cs index 3a9a5212..4e8e3158 100644 --- a/src/openHAB.Windows/MainWindow.xaml.cs +++ b/src/openHAB.Windows/MainWindow.xaml.cs @@ -1,4 +1,17 @@ +using System; +using System.Threading.Tasks; +using CommunityToolkit.Mvvm.Messaging; +using CommunityToolkit.WinUI; +using Microsoft.Extensions.Logging; using Microsoft.UI.Xaml; +using Microsoft.UI.Xaml.Controls; +using openHAB.Common; +using openHAB.Core.Client.Messages; +using openHAB.Core.Client.Models; +using openHAB.Core.Messages; +using openHAB.Windows.Services; +using openHAB.Windows.View; +using openHAB.Windows.ViewModel; namespace openHAB.Windows { @@ -7,9 +20,115 @@ namespace openHAB.Windows /// public sealed partial class MainWindow : Window { + private ILogger _logger; + + /// + /// Gets the data context, for use in compiled bindings. + /// + public MainViewModel Vm + { + get; + private set; + } + + public Frame RootFrame => ContentFrame; + public MainWindow() { + _logger = DIService.Instance.GetService>(); + this.InitializeComponent(); + + Vm = DIService.Instance.GetService(); + Root.DataContext = Vm; + + StrongReferenceMessenger.Default.Register(this, async (recipient, msg) => await ShowErrorMessage(recipient, msg)); + StrongReferenceMessenger.Default.Register(this, async (recipient, msg) => await ShowInfoMessage(recipient, msg)); + + Vm.LoadSitemapsAndItemData(); + } + + private async Task ShowErrorMessage(object recipient, ConnectionErrorMessage message) + { + try + { + string errorMessage = null; + if (message == null || string.IsNullOrEmpty(message.ErrorMessage)) + { + errorMessage = AppResources.Values.GetString("MessageError"); + ErrorNotification.Message = errorMessage; + ErrorNotification.IsOpen = true; + } + else + { + errorMessage = message.ErrorMessage; + } + + await App.DispatcherQueue.EnqueueAsync(() => + { + ErrorNotification.Message = errorMessage; + ErrorNotification.IsOpen = true; + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Show error message failed."); + } + } + + private async Task ShowInfoMessage(object recipient, FireInfoMessage msg) + { + try + { + string message = null; + switch (msg.MessageType) + { + case MessageType.NotConfigured: + message = AppResources.Values.GetString("MessageNotConfigured"); + break; + + case MessageType.NotReachable: + message = AppResources.Values.GetString("MessagesNotReachable"); + break; + + default: + message = "Message not defined"; + break; + } + + await App.DispatcherQueue.EnqueueAsync(() => + { + InfoNotification.Message = message; + InfoNotification.IsOpen = true; + }); + } + catch (Exception ex) + { + _logger.LogError(ex, "Show info message failed."); + } + } + + private void SitemapNavigation_SelectionChanged( + NavigationView sender, + NavigationViewSelectionChangedEventArgs args) + { + if (args.IsSettingsSelected) + { + sender.AlwaysShowHeader = false; + ContentFrame.Navigate(typeof(SettingsPage)); + } + else + { + sender.AlwaysShowHeader = true; + SitemapViewModel sitemap = args.SelectedItem as SitemapViewModel; + ContentFrame.Navigate(typeof(SitemapPage), sitemap.Link); + } + } + + private void BreadcrumbBar_ItemClicked(BreadcrumbBar sender, BreadcrumbBarItemClickedEventArgs args) + { + OpenHABWidget widget = args.Item as OpenHABWidget; + this.Vm.SelectedSitemap.WidgetGoBack(widget); } } } diff --git a/src/openHAB.Windows/View/MainPage.xaml b/src/openHAB.Windows/View/MainPage.xaml index 63346abe..f4fb4d39 100644 --- a/src/openHAB.Windows/View/MainPage.xaml +++ b/src/openHAB.Windows/View/MainPage.xaml @@ -14,307 +14,8 @@ xmlns:model="using:openHAB.Core.Client.Models" mc:Ignorable="d" Name="Page"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/src/openHAB.Windows/View/MainPage.xaml.cs b/src/openHAB.Windows/View/MainPage.xaml.cs index 30cbf847..b75cc0af 100644 --- a/src/openHAB.Windows/View/MainPage.xaml.cs +++ b/src/openHAB.Windows/View/MainPage.xaml.cs @@ -6,11 +6,9 @@ using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using openHAB.Common; -using openHAB.Core; using openHAB.Core.Client.Messages; using openHAB.Core.Client.Models; using openHAB.Core.Messages; -using openHAB.Core.Model; using openHAB.Windows.Services; using openHAB.Windows.ViewModel; @@ -21,120 +19,15 @@ namespace openHAB.Windows.View /// public sealed partial class MainPage : Page { - private ILogger _logger; - - /// - /// Gets the data context, for use in compiled bindings. - /// - public MainViewModel Vm => DataContext as MainViewModel; /// /// Initializes a new instance of the class. /// public MainPage() { - DataContext = DIService.Instance.GetService(); - _logger = DIService.Instance.GetService>(); - InitializeComponent(); } - /// - protected override async void OnNavigatedTo(NavigationEventArgs e) - { - StrongReferenceMessenger.Default.Register(this, async (recipient, msg) => await ShowErrorMessage(recipient, msg)); - StrongReferenceMessenger.Default.Register(this, async (recipient, msg) => await ShowInfoMessage(recipient, msg)); - - await Vm.LoadSitemapsAndItemData().ConfigureAwait(false); - } - - /// - protected override void OnNavigatedFrom(NavigationEventArgs e) - { - StrongReferenceMessenger.Default.Unregister(this); - StrongReferenceMessenger.Default.Unregister(this); - - ErrorNotification.IsOpen = false; - InfoNotification.IsOpen = false; - } - -#pragma warning disable S1172 // Unused method parameters should be removed - - private async Task ShowErrorMessage(object recipient, ConnectionErrorMessage message) -#pragma warning restore S1172 // Unused method parameters should be removed - { - try - { - string errorMessage = null; - if (message == null || string.IsNullOrEmpty(message.ErrorMessage)) - { - errorMessage = AppResources.Values.GetString("MessageError"); - ErrorNotification.Message = errorMessage; - ErrorNotification.IsOpen = true; - } - else - { - errorMessage = message.ErrorMessage; - } - - await App.DispatcherQueue.EnqueueAsync(() => - { - ErrorNotification.Message = errorMessage; - ErrorNotification.IsOpen = true; - }); - } - catch (Exception ex) - { - _logger.LogError(ex, "Show error message failed."); - } - } - - private async Task ShowInfoMessage(object recipient, FireInfoMessage msg) - { - try - { - string message = null; - switch (msg.MessageType) - { - case MessageType.NotConfigured: - message = AppResources.Values.GetString("MessageNotConfigured"); - break; - - case MessageType.NotReachable: - message = AppResources.Values.GetString("MessagesNotReachable"); - break; - - default: - message = "Message not defined"; - break; - } - - await App.DispatcherQueue.EnqueueAsync(() => - { - InfoNotification.Message = message; - InfoNotification.IsOpen = true; - }); - } - catch (Exception ex) - { - _logger.LogError(ex, "Show info message failed."); - } - } - - private void SitemapNavigation_SelectionChanged( - Microsoft.UI.Xaml.Controls.NavigationView sender, - Microsoft.UI.Xaml.Controls.NavigationViewSelectionChangedEventArgs args) - { - if (args.IsSettingsSelected) - { - Frame.Navigate(typeof(SettingsPage)); - } - } - - private void BreadcrumbBar_ItemClicked(BreadcrumbBar sender, BreadcrumbBarItemClickedEventArgs args) - { - OpenHABWidget widget = args.Item as OpenHABWidget; - this.Vm.SelectedSitemap.WidgetGoBack(widget); - } + } } \ No newline at end of file diff --git a/src/openHAB.Windows/View/SettingsPage.xaml b/src/openHAB.Windows/View/SettingsPage.xaml index 43a4b1d1..f762dbc7 100644 --- a/src/openHAB.Windows/View/SettingsPage.xaml +++ b/src/openHAB.Windows/View/SettingsPage.xaml @@ -7,14 +7,44 @@ xmlns:core="using:Microsoft.Xaml.Interactions.Core" xmlns:interactivity="using:Microsoft.Xaml.Interactivity" xmlns:muxc="using:Microsoft.UI.Xaml.Controls" + xmlns:media="http://schemas.microsoft.com/winfx/2006/xaml/presentation" mc:Ignorable="d" + Background="Transparent" x:Name="SettingsView"> - - - + + + + + + + + + + + + + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/openHAB.Windows/View/SettingsPage.xaml.cs b/src/openHAB.Windows/View/SettingsPage.xaml.cs index 54b3e326..13469469 100644 --- a/src/openHAB.Windows/View/SettingsPage.xaml.cs +++ b/src/openHAB.Windows/View/SettingsPage.xaml.cs @@ -37,8 +37,6 @@ public SettingsPage() _appManager = DIService.Instance.GetService(); DataContext = _settingsViewModel; - - SettingOptionsListView.SelectedIndex = 0; } #region Page Navigation diff --git a/src/openHAB.Windows/View/SitemapPage.xaml b/src/openHAB.Windows/View/SitemapPage.xaml index 0b840ab3..8f574364 100644 --- a/src/openHAB.Windows/View/SitemapPage.xaml +++ b/src/openHAB.Windows/View/SitemapPage.xaml @@ -1,25 +1,23 @@ - - - - - + + - + - + Sitempap + diff --git a/src/openHAB.Windows/View/SitemapPage.xaml.cs b/src/openHAB.Windows/View/SitemapPage.xaml.cs index bec2df9b..759ae12b 100644 --- a/src/openHAB.Windows/View/SitemapPage.xaml.cs +++ b/src/openHAB.Windows/View/SitemapPage.xaml.cs @@ -1,11 +1,13 @@ using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.WinUI; +using Microsoft.Extensions.Logging; using Microsoft.UI.Dispatching; using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; using openHAB.Core.Client.Models; using openHAB.Core.Messages; using openHAB.Core.Services; +using openHAB.Windows.Services; using openHAB.Windows.ViewModel; namespace openHAB.Windows.View @@ -15,32 +17,20 @@ namespace openHAB.Windows.View /// public sealed partial class SitemapPage : Page { + private SitemapService _sitemapService; + private SitemapViewModel _viewModel; + + /// + /// Initializes a new instance of the class + /// . public SitemapPage() { this.InitializeComponent(); StrongReferenceMessenger.Default.Register(this, (obj, message) => OnSitemapChangedEvent(message)); - } - private void OnSitemapChangedEvent(SitemapChanged message) - { - if(message.Sitemap == null) - { - return; - } - - DataContext = new SitemapViewModel(message.Sitemap); - - if (ViewModel != null) - { - DispatcherQueue dispatcherQueue = DispatcherQueue.GetForCurrentThread(); - dispatcherQueue.EnqueueAsync(() => - { - ViewModel.LoadWidgets(); - WidgetNavigationService.ClearWidgetNavigation(); - }); - } + _sitemapService = DIService.Instance.GetService(); } /// @@ -48,22 +38,47 @@ private void OnSitemapChangedEvent(SitemapChanged message) /// public SitemapViewModel ViewModel { - get => DataContext as SitemapViewModel; + get => _viewModel; } - protected override void OnNavigatedTo(NavigationEventArgs e) + protected override void OnNavigatedFrom(NavigationEventArgs e) { - base.OnNavigatedTo(e); + base.OnNavigatedFrom(e); } - protected override void OnNavigatedFrom(NavigationEventArgs e) + protected async override void OnNavigatedTo(NavigationEventArgs e) { - base.OnNavigatedFrom(e); + base.OnNavigatedTo(e); + + string sitemapUrl = e.Parameter as string; + if (string.IsNullOrEmpty(sitemapUrl)) + { + return; + } + + OpenHABSitemap sitemap = await _sitemapService.GetSitemapByUrlAsync(sitemapUrl); + _viewModel = new SitemapViewModel(sitemap); + + DispatcherQueue dispatcherQueue = DispatcherQueue.GetForCurrentThread(); + await dispatcherQueue.EnqueueAsync(async () => + { + DataContext = _viewModel; + await ViewModel.LoadWidgetsAsync(); + WidgetNavigationService.ClearWidgetNavigation(); + }); } private void MasterListView_OnItemClick(object sender, ItemClickEventArgs e) { StrongReferenceMessenger.Default.Send(new WidgetClickedMessage(e.ClickedItem as OpenHABWidget)); } + + private void OnSitemapChangedEvent(SitemapChanged message) + { + if(message.Sitemap == null) + { + return; + } + } } } diff --git a/src/openHAB.Windows/ViewModel/MainViewModel.cs b/src/openHAB.Windows/ViewModel/MainViewModel.cs index e34a0809..65750dda 100644 --- a/src/openHAB.Windows/ViewModel/MainViewModel.cs +++ b/src/openHAB.Windows/ViewModel/MainViewModel.cs @@ -121,7 +121,7 @@ public SitemapViewModel SelectedSitemap settings.LastSitemap = _selectedSitemap.Name; _settingsService.Save(settings); - StrongReferenceMessenger.Default.Send(new SitemapChanged(value.Model)); + //StrongReferenceMessenger.Default.Send(new SitemapChanged(value.Model)); } SelectedMenuItem = value; @@ -206,7 +206,7 @@ private async Task LoadData(CancellationToken loadCancellationToken) return; } - List sitemaps = await _sitemapManager.GetSitemaps(loadCancellationToken); + List sitemaps = await _sitemapManager.GetSitemapsAsync(loadCancellationToken); if (sitemaps == null) { StrongReferenceMessenger.Default.Send(new FireInfoMessage(MessageType.NotConfigured)); diff --git a/src/openHAB.Windows/ViewModel/SitemapViewModel.cs b/src/openHAB.Windows/ViewModel/SitemapViewModel.cs index 77d3e90c..f74c80e1 100644 --- a/src/openHAB.Windows/ViewModel/SitemapViewModel.cs +++ b/src/openHAB.Windows/ViewModel/SitemapViewModel.cs @@ -6,13 +6,11 @@ using CommunityToolkit.Mvvm.Messaging; using CommunityToolkit.WinUI; using openHAB.Common; -using openHAB.Core; using openHAB.Core.Client.Common; using openHAB.Core.Client.Messages; using openHAB.Core.Client.Models; using openHAB.Core.Common; using openHAB.Core.Messages; -using openHAB.Core.Model; using openHAB.Core.Services; using openHAB.Windows.Services; @@ -86,6 +84,17 @@ public string Label } } + /// + /// Gets the link of the OpenHAB sitemap. + /// + public string Link + { + get + { + return Model.Link; + } + } + /// /// Gets the name of the OpenHAB sitemap. /// @@ -123,8 +132,7 @@ public ObservableCollection Widgets return; } - _widgets = value; - OnPropertyChanged(); + this.Set(ref _widgets, value); } } #endregion @@ -151,8 +159,8 @@ private async void ExecuteReloadSitemapCommand(object obj) #region Navigate To Sitemap Root Command - private ActionCommand _navigateToSitemapRootCommand; private bool _canExecuteReloadSitemap; + private ActionCommand _navigateToSitemapRootCommand; public ActionCommand NavigateToSitemapRoot => _navigateToSitemapRootCommand ?? (_navigateToSitemapRootCommand = new ActionCommand(ExecuteNavigateToSitemapRootCommand, CanExecuteNavigateToSitemapRootCommand)); @@ -164,7 +172,7 @@ private bool CanExecuteNavigateToSitemapRootCommand(object arg) private void ExecuteNavigateToSitemapRootCommand(object obj) { WidgetNavigationService.ClearWidgetNavigation(); - SetWidgetsOnScreen(Widgets); + SetWidgetsOnScreen(Widgets.ToList()); SelectedWidget = null; StrongReferenceMessenger.Default.Send(new WigetNavigation(SelectedWidget, null)); @@ -174,6 +182,19 @@ private void ExecuteNavigateToSitemapRootCommand(object obj) #region Events + private void DataOperationState(DataOperation operation) + { + switch (operation.State) + { + case OperationState.Started: + _canExecuteReloadSitemap = true; + break; + case OperationState.Completed: + _canExecuteReloadSitemap = false; + break; + } + } + private async void OnWidgetClickedAction(OpenHABWidget widget) { await OnWidgetClickedAsync(widget); @@ -191,64 +212,79 @@ private async Task TriggerItemCommand(TriggerCommandMessage message) } } - private void DataOperationState(DataOperation operation) - { - switch (operation.State) - { - case OperationState.Started: - _canExecuteReloadSitemap = true; - break; - case OperationState.Completed: - _canExecuteReloadSitemap = false; - break; - } - } - #endregion /// /// Loads widgets for sitemap. /// W /// Task for async processing. - public async Task LoadWidgets() + public async Task LoadWidgetsAsync() { - Widgets.Clear(); - CurrentWidgets.Clear(); + this.Widgets = new ObservableCollection(); + CurrentWidgets?.Clear(); ICollection widgetModels = await _sitemapService.LoadItemsFromSitemapAsync(Model).ConfigureAwait(false); widgetModels.ToList().ForEach(x => Widgets.Add(x)); - SetWidgetsOnScreen(this.Widgets); + SetWidgetsOnScreen(this.Widgets.ToList()); } public async Task ReloadSitemap() { - await App.DispatcherQueue.EnqueueAsync(async () => + CurrentWidgets?.Clear(); + StrongReferenceMessenger.Default.Send(new DataOperation(OperationState.Started)); + + if (SelectedWidget != null) + { + await LoadWidgetsAsync().ConfigureAwait(false); + OpenHABWidget widget = FindWidget(SelectedWidget.WidgetId, Widgets); + if (widget != null) + { + await OnWidgetClickedAsync(widget); + } + else + { + SelectedWidget = null; + WidgetNavigationService.ClearWidgetNavigation(); + } + } + else { - CurrentWidgets?.Clear(); - StrongReferenceMessenger.Default.Send(new DataOperation(OperationState.Started)); + await LoadWidgetsAsync().ConfigureAwait(false); + } - if (SelectedWidget != null) + StrongReferenceMessenger.Default.Send(new DataOperation(OperationState.Completed)); + ReloadSitemapCommand.InvokeCanExecuteChanged(null); + } + + public async Task SelectWidget() + { + if (SelectedWidget != null) + { + await LoadWidgetsAsync().ConfigureAwait(false); + OpenHABWidget widget = FindWidget(SelectedWidget.WidgetId, Widgets); + if (widget != null) { - await LoadWidgets().ConfigureAwait(false); - OpenHABWidget widget = FindWidget(SelectedWidget.WidgetId, Widgets); - if (widget != null) - { - await OnWidgetClickedAsync(widget); - } - else - { - SelectedWidget = null; - WidgetNavigationService.ClearWidgetNavigation(); - } + await OnWidgetClickedAsync(widget); } else { - await LoadWidgets().ConfigureAwait(false); + SelectedWidget = null; + WidgetNavigationService.ClearWidgetNavigation(); } + } + else + { + await LoadWidgetsAsync().ConfigureAwait(false); + } + } - StrongReferenceMessenger.Default.Send(new DataOperation(OperationState.Completed)); - ReloadSitemapCommand.InvokeCanExecuteChanged(null); + public async void SetWidgetsOnScreen(ICollection widgets) + { + await App.DispatcherQueue.EnqueueAsync(() => + { + CurrentWidgets.Clear(); + CurrentWidgets.AddRange(widgets); }); } @@ -301,7 +337,7 @@ await App.DispatcherQueue.EnqueueAsync(() => { OpenHABWidget lastWidget = SelectedWidget; SelectedWidget = widget; - if (SelectedWidget.LinkedPage == null || !SelectedWidget.LinkedPage.Widgets.Any()) + if (SelectedWidget?.LinkedPage == null || !SelectedWidget.LinkedPage.Widgets.Any()) { return; } @@ -312,36 +348,5 @@ await App.DispatcherQueue.EnqueueAsync(() => SetWidgetsOnScreen(SelectedWidget?.LinkedPage?.Widgets); }); } - - public async Task SelectWidget() - { - if (SelectedWidget != null) - { - await LoadWidgets().ConfigureAwait(false); - OpenHABWidget widget = FindWidget(SelectedWidget.WidgetId, Widgets); - if (widget != null) - { - await OnWidgetClickedAsync(widget); - } - else - { - SelectedWidget = null; - WidgetNavigationService.ClearWidgetNavigation(); - } - } - else - { - await LoadWidgets().ConfigureAwait(false); - } - } - - public async void SetWidgetsOnScreen(ICollection widgets) - { - await App.DispatcherQueue.EnqueueAsync(() => - { - CurrentWidgets.Clear(); - CurrentWidgets.AddRange(widgets); - }); - } } } \ No newline at end of file