From 8e84b6deda6876a2afb4e96a4c41c5f5bb52f499 Mon Sep 17 00:00:00 2001 From: Oliver Hauff Date: Wed, 14 Jul 2021 00:16:50 +0200 Subject: [PATCH] Continued implementing FindBike functionality by using MyBikes as template. --- TINK/TINK/View/FindBike/FindBikePage.xaml | 48 +++++- TINK/TINK/View/FindBike/FindBikePage.xaml.cs | 144 +++++++++++++++++- TINKLib/Model/Bikes/BikeCollectionMutable.cs | 2 +- .../FindBike/FindBikePageViewModel.cs | 88 +++++++++++ .../ViewModel/FindBike/FindBikeViewModel.cs | 7 - 5 files changed, 269 insertions(+), 20 deletions(-) create mode 100644 TINKLib/ViewModel/FindBike/FindBikePageViewModel.cs delete mode 100644 TINKLib/ViewModel/FindBike/FindBikeViewModel.cs diff --git a/TINK/TINK/View/FindBike/FindBikePage.xaml b/TINK/TINK/View/FindBike/FindBikePage.xaml index 93ddbdf..98c8206 100644 --- a/TINK/TINK/View/FindBike/FindBikePage.xaml +++ b/TINK/TINK/View/FindBike/FindBikePage.xaml @@ -1,12 +1,50 @@  + xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" + x:Class="TINK.View.FindBike.FindBikePage" + xmlns:local_bike="clr-namespace:TINK.View.Bike"> + + + + + - - + \ No newline at end of file diff --git a/TINK/TINK/View/FindBike/FindBikePage.xaml.cs b/TINK/TINK/View/FindBike/FindBikePage.xaml.cs index 57bd8af..4325277 100644 --- a/TINK/TINK/View/FindBike/FindBikePage.xaml.cs +++ b/TINK/TINK/View/FindBike/FindBikePage.xaml.cs @@ -1,14 +1,144 @@ -using Xamarin.Forms; +using Serilog; +using System; +using System.Threading; +using System.Threading.Tasks; +using TINK.ViewModel.FindBike; +using Xamarin.CommunityToolkit.Extensions; +using Xamarin.Forms; using Xamarin.Forms.Xaml; namespace TINK.View.FindBike { [XamlCompilation(XamlCompilationOptions.Compile)] - public partial class FindBikePage : ContentPage + public partial class FindBikePage : ContentPage, IViewService { - public FindBikePage () - { - InitializeComponent (); - } - } + /// Refernce to view model. + FindBikePageViewModel m_oViewModel = null; + + public FindBikePage () { } + + /// + /// Invoked when page is shown. + /// Starts update process. + /// + protected async override void OnAppearing() + { + if (m_oViewModel != null) + { + // No need to create view model, set binding context an items source if already done. + // If done twice tap events are fired multiple times (when hiding page using home button). + await m_oViewModel.OnAppearing(); + return; + } + + try + { + var model = App.ModelRoot; + + // Backup synchronization context when called from GUI-thread. + var synchronizationContext = SynchronizationContext.Current; + + m_oViewModel = new FindBikePageViewModel( + model.ActiveUser, + App.PermissionsService, + App.BluetoothService, + Device.RuntimePlatform, + () => model.GetIsConnected(), + (isConnected) => model.GetConnector(isConnected), + App.GeolocationServicesContainer.Active, + model.LocksServices.Active, + model.Polling, + (d, obj) => synchronizationContext.Post(d, obj), + model.SmartDevice, + this) + { + IsReportLevelVerbose = model.IsReportLevelVerbose + }; + } + catch (Exception exception) + { + Log.ForContext().Error("Displaying bikes at station page failed. {Exception}", exception); + await DisplayAlert("Fehler", $"Seite Fahrrad Wählen kann nicht angezeigt werden. ${exception.Message}", "OK"); + return; + + } + + InitializeComponent(); + + BindingContext = m_oViewModel; + FindBikeListView.ItemsSource = m_oViewModel; + + await m_oViewModel.OnAppearing(); + } + + + /// + /// Displays alert message. + /// + /// Title of message. + /// Message to display. + /// Type of buttons. + public new async Task DisplayAlert(string p_strTitle, string p_strMessage, string p_strCancel) + => await App.Current.MainPage.DisplayAlert(p_strTitle, p_strMessage, p_strCancel); + + /// Displays alert message. + /// Title of message. + /// Message to display. + /// Detailed error description. + /// Type of buttons. + public async Task DisplayAdvancedAlert( + string title, + string message, + string details, + string cancel) + => await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel); + + /// Displays detailed alert message. + /// Title of message. + /// Message to display. + /// Detailed error description. + /// Text of accept button. + /// Text of cancel button. + /// True if user pressed accept. + public async Task DisplayAdvancedAlert(string title, string message, string details, string accept, string cancel) + => await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", accept, cancel); + + /// + /// Displays alert message. + /// + /// Title of message. + /// Message to display. + /// Text of accept button. + /// Text of button. + /// True if user pressed accept. + public new async Task DisplayAlert(string p_strTitle, string p_strMessage, string p_strAccept, string p_strCancel) + => await App.Current.MainPage.DisplayAlert(p_strTitle, p_strMessage, p_strAccept, p_strCancel); + +#if USEMASTERDETAIL || USEFLYOUT + public void ShowPage(ViewTypes p_oType, string p_strTitle = null) + => throw new NotImplementedException(); +#else + /// Shows a page. + /// Route of the page to show. + public async Task ShowPage(string route) => await Shell.Current.GoToAsync(route); +#endif + + /// Pushes a page onto the modal stack. + /// Page to display. + public Task PushModalAsync(ViewTypes p_oTypeOfPage) => throw new NotSupportedException(); + + /// Pops a page from the modal stack. + public Task PopModalAsync() => throw new NotSupportedException(); + + /// Pushes a page onto the stack. + /// Page to display. + public Task PushAsync(ViewTypes p_oTypeOfPage) => throw new NotSupportedException(); + +#if USCSHARP9 + public async Task DisplayUserFeedbackPopup() => await Navigation.ShowPopupAsync(new FeedbackPopup()); +#else + public async Task DisplayUserFeedbackPopup() => await Navigation.ShowPopupAsync(new FeedbackPopup()); +#endif + + } } \ No newline at end of file diff --git a/TINKLib/Model/Bikes/BikeCollectionMutable.cs b/TINKLib/Model/Bikes/BikeCollectionMutable.cs index 4383211..7367dd4 100644 --- a/TINKLib/Model/Bikes/BikeCollectionMutable.cs +++ b/TINKLib/Model/Bikes/BikeCollectionMutable.cs @@ -31,7 +31,7 @@ namespace TINK.Model.Bike // Needed to remove bikes which switched state and have to be removed from collection. var bikesToBeRemoved = this.Select(x => x.Id).ToList(); - foreach (var bikeInfo in (bikesAll ?? new List())) + foreach (var bikeInfo in bikesAll ?? new List()) { /// Check if bike has to be added to list of existing station. if (ContainsKey(bikeInfo.Id) == false) diff --git a/TINKLib/ViewModel/FindBike/FindBikePageViewModel.cs b/TINKLib/ViewModel/FindBike/FindBikePageViewModel.cs new file mode 100644 index 0000000..908c372 --- /dev/null +++ b/TINKLib/ViewModel/FindBike/FindBikePageViewModel.cs @@ -0,0 +1,88 @@ + +using Serilog; +using System; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Threading; +using System.Threading.Tasks; +using TINK.Model.Bike; +using TINK.Model.Connector; +using TINK.Model.User; +using TINK.View; +using TINK.Settings; +using TINK.Model.Bike.BluetoothLock; +using System.Collections.Generic; +using TINK.Services.BluetoothLock; +using TINK.Model.Services.Geolocation; +using System.Linq; +using TINK.Model; +using Xamarin.Forms; +using TINK.ViewModel.Bikes; +using TINK.Services.BluetoothLock.Tdo; +using Plugin.Permissions; +using Plugin.Permissions.Abstractions; +using Plugin.BLE.Abstractions.Contracts; +using TINK.MultilingualResources; +using TINK.Model.Device; + +namespace TINK.ViewModel.FindBike +{ + public class FindBikePageViewModel : BikesViewModel, INotifyCollectionChanged, INotifyPropertyChanged + { + /// + /// Constructs bike collection view model in case information about occupied bikes is available. + /// + /// Mail address of active user. + /// True if report level is verbose, false if not. + /// Holds object to query location permisions. + /// Holds object to query bluetooth state. + /// Specifies on which platform code is run. + /// Returns if mobile is connected to web or not. + /// Connects system to copri. + /// Service to control lock retrieve info. + /// Holds whether to poll or not and the periode leght is polling is on. + /// Executes actions on GUI thread. + /// Provides info about the smart device (phone, tablet, ...). + /// Interface to actuate methodes on GUI. + public FindBikePageViewModel( + User p_oUser, + IPermissions permissions, + IBluetoothLE bluetoothLE, + string runtimPlatform, + Func isConnectedDelegate, + Func connectorFactory, + IGeolocation geolocation, + ILocksService lockService, + PollingParameters polling, + Action postAction, + ISmartDevice smartDevice, + IViewService viewService) : base(p_oUser, permissions, bluetoothLE, runtimPlatform, isConnectedDelegate, connectorFactory, geolocation, lockService, polling, postAction, smartDevice, viewService, () => new MyBikeInUseStateInfoProvider()) + { + } + + /// + /// Invoked when page is shown. + /// Starts update process. + /// + public async Task OnAppearing() + { + // Get my bikes from COPRI + Log.ForContext().Information("User request to show page MyBikes/ page re-appearing"); + + ActionText = AppResources.ActivityTextMyBikesLoadingBikes; + + var bikes = await ConnectorFactory(IsConnected).Query.GetBikesAsync(); + + Exception = bikes.Exception; // Update communication error from query for bikes occupied. + + BikeIds = bikes.Response.Select(x => x.Id); + + ActionText = ""; + IsIdle = true; + } + + + public IEnumerable BikeIds { get; set; } + + } +} diff --git a/TINKLib/ViewModel/FindBike/FindBikeViewModel.cs b/TINKLib/ViewModel/FindBike/FindBikeViewModel.cs deleted file mode 100644 index 1e04f28..0000000 --- a/TINKLib/ViewModel/FindBike/FindBikeViewModel.cs +++ /dev/null @@ -1,7 +0,0 @@ - -namespace TINK.ViewModel.FindBike -{ - public class FindBikeViewModel - { - } -}