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
- {
- }
-}