mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-07-11 21:46:31 +02:00
Initial version.
This commit is contained in:
parent
e4fb48f6ab
commit
10dbeb5a90
737 changed files with 61885 additions and 0 deletions
27
TINK/TINK/View/Account/AccountPage.xaml
Normal file
27
TINK/TINK/View/Account/AccountPage.xaml
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
mc:Ignorable="d"
|
||||
x:Class="TINK.View.Account.AccountPage">
|
||||
<ContentPage.Content>
|
||||
<Frame>
|
||||
<StackLayout>
|
||||
<Frame>
|
||||
<StackLayout>
|
||||
<Label Text="{Binding LoggedInInfo}" />
|
||||
<Label IsVisible="{Binding IsBookingStateInfoVisible}"
|
||||
Text="{Binding BookingStateInfo}" />
|
||||
<Button Text="Persönliche Daten Verwalten"
|
||||
Command="{Binding OnManageAccount}"
|
||||
IsEnabled="{Binding IsLogoutPossible}"/>
|
||||
<Button Text="Abmelden"
|
||||
Command="{Binding OnLogoutRequest}"
|
||||
IsEnabled="{Binding IsLogoutPossible}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
128
TINK/TINK/View/Account/AccountPage.xaml.cs
Normal file
128
TINK/TINK/View/Account/AccountPage.xaml.cs
Normal file
|
@ -0,0 +1,128 @@
|
|||
using TINK.ViewModel;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.View.MasterDetail;
|
||||
using System;
|
||||
using TINK.Model.Device;
|
||||
using TINK.ViewModel.Account;
|
||||
|
||||
namespace TINK.View.Account
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class AccountPage : ContentPage, IViewService, IDetailPage
|
||||
{
|
||||
/// <summary> Refernce to view model. </summary>
|
||||
AccountPageViewModel m_oViewModel = null;
|
||||
|
||||
/// <summary> Constructs a account page. </summary>
|
||||
public AccountPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
var l_oModel = App.ModelRoot;
|
||||
|
||||
m_oViewModel = new AccountPageViewModel(
|
||||
l_oModel,
|
||||
(url) => DependencyService.Get<IExternalBrowserService>().OpenUrl(url),
|
||||
this);
|
||||
|
||||
BindingContext = m_oViewModel;
|
||||
}
|
||||
|
||||
/// <summary> Displays altert message. </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strCancel">Type of buttons.</param>
|
||||
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);
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary> Displays alert message.</summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strAccept">Text of accept button.</param>
|
||||
/// <param name="p_strCancel">Text of button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public new async Task<bool> 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);
|
||||
|
||||
/// <summary>
|
||||
/// Displays an action sheet.
|
||||
/// </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strCancel">Text of button.</param>
|
||||
/// <param name="destruction"></param>
|
||||
/// <param name="p_oButtons">Buttons holding options to select.</param>
|
||||
/// <returns>Text selected</returns>
|
||||
public new async Task<string> DisplayActionSheet(String p_strTitle, String p_strCancel, String destruction, params String[] p_oButtons)
|
||||
=> await base.DisplayActionSheet(p_strTitle, p_strCancel, destruction, p_oButtons);
|
||||
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
=> m_oNavigation.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public Task PushModalAsync(ViewTypes p_oTypeOfPage)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
/// <summary> Pops a page from the modal stack. </summary>
|
||||
public Task PopModalAsync()
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
|
||||
/// <summary>Delegate to perform navigation.</summary>
|
||||
private INavigationMasterDetail m_oNavigation;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate to perform navigation.
|
||||
/// </summary>
|
||||
public INavigationMasterDetail NavigationMasterDetail
|
||||
{
|
||||
set { m_oNavigation = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when page is shown.
|
||||
/// Starts update process.
|
||||
/// </summary>
|
||||
protected async override void OnAppearing()
|
||||
=> await m_oViewModel.OnAppearing();
|
||||
/// <summary>
|
||||
/// Invoked when pages is closed/ hidden.
|
||||
/// Stops update process.
|
||||
/// </summary>
|
||||
protected async override void OnDisappearing()
|
||||
{
|
||||
if (m_oViewModel == null)
|
||||
{
|
||||
// View model might be null.
|
||||
return;
|
||||
}
|
||||
await m_oViewModel.OnDisappearing();
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public async Task PushAsync(ViewTypes p_oTypeOfPage)
|
||||
=> await Navigation.PushAsync((Page)Activator.CreateInstance(p_oTypeOfPage.GetViewType()));
|
||||
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
}
|
||||
}
|
90
TINK/TINK/View/Bike/BCBike.xaml
Normal file
90
TINK/TINK/View/Bike/BCBike.xaml
Normal file
|
@ -0,0 +1,90 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:conv="clr-namespace:TINK.View"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
|
||||
mc:Ignorable="d"
|
||||
x:Class="TINK.View.Bike.BCBike">
|
||||
<ContentView>
|
||||
<ContentView.Resources>
|
||||
<conv:StringNotNullOrEmptyToVisibleConverter x:Key="Label_Converter"/>
|
||||
</ContentView.Resources>
|
||||
<StackLayout
|
||||
Padding="10">
|
||||
<Label
|
||||
FontAttributes="Bold"
|
||||
Text="{Binding Name}"/>
|
||||
<Label
|
||||
Text="{Binding StateText}"
|
||||
TextColor="{Binding StateColor}"/>
|
||||
<Label
|
||||
Text="{Binding ErrorText}"
|
||||
IsVisible="{Binding ErrorText, Converter={StaticResource Label_Converter}}"
|
||||
TextColor="Red"/>
|
||||
<Button
|
||||
Text="{Binding ButtonText}"
|
||||
IsVisible="{Binding IsButtonVisible}"
|
||||
IsEnabled="{Binding IsIdle}"
|
||||
Command="{Binding OnButtonClicked}"/>
|
||||
<Grid
|
||||
IsVisible="{Binding TariffDescription.Header, Converter={StaticResource Label_Converter}}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
Text=
|
||||
"{Binding TariffDescription.Header}"
|
||||
Grid.ColumnSpan="3"
|
||||
FontAttributes="Bold"/>
|
||||
<Label
|
||||
Text="{x:Static resources:AppResources.MessageBikesManagementTariffDescriptionFreeTimePerSession}"
|
||||
IsVisible="{Binding TariffDescription.FreeTimePerSession, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="1"/>
|
||||
<Label
|
||||
Text="{Binding TariffDescription.FreeTimePerSession}"
|
||||
IsVisible="{Binding TariffDescription.FreeTimePerSession, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"/>
|
||||
<Label
|
||||
Text="{x:Static resources:AppResources.MessageBikesManagementTariffDescriptionFeeEuroPerHour}"
|
||||
IsVisible="{Binding TariffDescription.FeeEuroPerHour, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="2"/>
|
||||
<Label
|
||||
Text="{Binding TariffDescription.FeeEuroPerHour}"
|
||||
IsVisible="{Binding TariffDescription.FeeEuroPerHour, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"/>
|
||||
<Label
|
||||
Text="{x:Static resources:AppResources.MessageBikesManagementTariffDescriptionMaxFeeEuroPerDay}"
|
||||
IsVisible="{Binding TariffDescription.MaxFeeEuroPerDay, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="3"/>
|
||||
<Label
|
||||
Text="{Binding TariffDescription.MaxFeeEuroPerDay}"
|
||||
IsVisible="{Binding TariffDescription.MaxFeeEuroPerDay, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"/>
|
||||
<Label
|
||||
Text="{x:Static resources:AppResources.MessageBikesManagementTariffDescriptionAboEuroPerMonth}"
|
||||
IsVisible="{Binding TariffDescription.AboEuroPerMonth, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="4"/>
|
||||
<Label
|
||||
Text="{Binding TariffDescription.AboEuroPerMonth}"
|
||||
IsVisible="{Binding TariffDescription.AboEuroPerMonth, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"/>
|
||||
</Grid>
|
||||
</StackLayout>
|
||||
</ContentView>
|
||||
</ViewCell>
|
20
TINK/TINK/View/Bike/BCBike.xaml.cs
Normal file
20
TINK/TINK/View/Bike/BCBike.xaml.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.Bike
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class BCBike : ViewCell
|
||||
{
|
||||
public BCBike()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
}
|
26
TINK/TINK/View/Bike/BikeViewCellTemplateSelector.cs
Normal file
26
TINK/TINK/View/Bike/BikeViewCellTemplateSelector.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using Xamarin.Forms;
|
||||
|
||||
namespace TINK.View.Bike
|
||||
{
|
||||
/// <summary>
|
||||
/// Selects different templates for different bike types (BordComputer bikes, iLockIt bikes).
|
||||
/// </summary>
|
||||
public class BikeViewCellTemplateSelector : DataTemplateSelector
|
||||
{
|
||||
DataTemplate bCBike;
|
||||
DataTemplate iLockIBike;
|
||||
|
||||
public BikeViewCellTemplateSelector()
|
||||
{
|
||||
bCBike = new DataTemplate(typeof(BCBike));
|
||||
iLockIBike = new DataTemplate(typeof(ILockItBike));
|
||||
}
|
||||
|
||||
protected override DataTemplate OnSelectTemplate(object item, BindableObject container)
|
||||
{
|
||||
return item is TINK.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel
|
||||
? iLockIBike
|
||||
: bCBike;
|
||||
}
|
||||
}
|
||||
}
|
95
TINK/TINK/View/Bike/ILockItBike.xaml
Normal file
95
TINK/TINK/View/Bike/ILockItBike.xaml
Normal file
|
@ -0,0 +1,95 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ViewCell xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:conv="clr-namespace:TINK.View"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
|
||||
mc:Ignorable="d"
|
||||
x:Class="TINK.View.Bike.ILockItBike">
|
||||
<ContentView>
|
||||
<ContentView.Resources>
|
||||
<conv:StringNotNullOrEmptyToVisibleConverter x:Key="Label_Converter"/>
|
||||
</ContentView.Resources>
|
||||
<StackLayout
|
||||
Padding="10">
|
||||
<Label
|
||||
FontAttributes="Bold"
|
||||
Text="{Binding Name}"/>
|
||||
<Label
|
||||
Text="{Binding StateText}"
|
||||
TextColor="{Binding StateColor}"/>
|
||||
<Label
|
||||
Text="{Binding ErrorText}"
|
||||
IsVisible="{Binding ErrorText, Converter={StaticResource Label_Converter}}"
|
||||
TextColor="Red"/>
|
||||
<Button
|
||||
Text="{Binding ButtonText}"
|
||||
IsVisible="{Binding IsButtonVisible}"
|
||||
IsEnabled="{Binding IsIdle}"
|
||||
Command="{Binding OnButtonClicked}"/>
|
||||
<Button
|
||||
Text="{Binding LockitButtonText}"
|
||||
IsVisible="{Binding IsLockitButtonVisible}"
|
||||
IsEnabled="{Binding IsIdle}"
|
||||
Command="{Binding OnLockitButtonClicked}"/>
|
||||
<Grid
|
||||
IsVisible="{Binding TariffDescription.Header, Converter={StaticResource Label_Converter}}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
<RowDefinition Height="Auto" />
|
||||
</Grid.RowDefinitions>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="Auto" />
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Label
|
||||
Text=
|
||||
"{Binding TariffDescription.Header}"
|
||||
Grid.ColumnSpan="3"
|
||||
FontAttributes="Bold"/>
|
||||
<Label
|
||||
Text="{x:Static resources:AppResources.MessageBikesManagementTariffDescriptionFreeTimePerSession}"
|
||||
IsVisible="{Binding TariffDescription.FreeTimePerSession, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="1"/>
|
||||
<Label
|
||||
Text="{Binding TariffDescription.FreeTimePerSession}"
|
||||
IsVisible="{Binding TariffDescription.FreeTimePerSession, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"/>
|
||||
<Label
|
||||
Text="{x:Static resources:AppResources.MessageBikesManagementTariffDescriptionFeeEuroPerHour}"
|
||||
IsVisible="{Binding TariffDescription.FeeEuroPerHour, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="2"/>
|
||||
<Label
|
||||
Text="{Binding TariffDescription.FeeEuroPerHour}"
|
||||
IsVisible="{Binding TariffDescription.FeeEuroPerHour, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="2"
|
||||
Grid.Column="1"/>
|
||||
<Label
|
||||
Text="{x:Static resources:AppResources.MessageBikesManagementTariffDescriptionMaxFeeEuroPerDay}"
|
||||
IsVisible="{Binding TariffDescription.MaxFeeEuroPerDay, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="3"/>
|
||||
<Label
|
||||
Text="{Binding TariffDescription.MaxFeeEuroPerDay}"
|
||||
IsVisible="{Binding TariffDescription.MaxFeeEuroPerDay, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="3"
|
||||
Grid.Column="1"/>
|
||||
<Label
|
||||
Text="{x:Static resources:AppResources.MessageBikesManagementTariffDescriptionAboEuroPerMonth}"
|
||||
IsVisible="{Binding TariffDescription.AboEuroPerMonth, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="4"/>
|
||||
<Label
|
||||
Text="{Binding TariffDescription.AboEuroPerMonth}"
|
||||
IsVisible="{Binding TariffDescription.AboEuroPerMonth, Converter={StaticResource Label_Converter}}"
|
||||
Grid.Row="4"
|
||||
Grid.Column="1"/>
|
||||
</Grid>
|
||||
</StackLayout>
|
||||
</ContentView>
|
||||
</ViewCell>
|
44
TINK/TINK/View/Bike/ILockItBike.xaml.cs
Normal file
44
TINK/TINK/View/Bike/ILockItBike.xaml.cs
Normal file
|
@ -0,0 +1,44 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bikes.Bike.BluetoothLock;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.Bike
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class ILockItBike : ViewCell
|
||||
{
|
||||
public ILockItBike()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnBindingContextChanged()
|
||||
{
|
||||
base.OnBindingContextChanged();
|
||||
|
||||
if (Device.RuntimePlatform != Device.iOS)
|
||||
// Update of size is only required for iOS.
|
||||
return;
|
||||
|
||||
var viewModel = BindingContext as TINK.ViewModel.Bikes.Bike.BluetoothLock.BikeViewModel;
|
||||
if (viewModel == null)
|
||||
return;
|
||||
|
||||
viewModel.PropertyChanged += (sender, e) =>
|
||||
{
|
||||
if (e.PropertyName == nameof(TINK.ViewModel.Bikes.Bike.BC.RequestHandler.Base<IBikeInfoMutable>.IsButtonVisible)
|
||||
|| e.PropertyName == nameof(TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler.Base.IsLockitButtonVisible))
|
||||
{
|
||||
// Force update of view cell on iOS.
|
||||
// https://hausource.visualstudio.com/TINK/_workitems/edit/132
|
||||
ForceUpdateSize();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
59
TINK/TINK/View/BikesAtStation/BikesAtStationPage.xaml
Normal file
59
TINK/TINK/View/BikesAtStation/BikesAtStationPage.xaml
Normal file
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TINK.View.BikesAtStation.BikesAtStationPage"
|
||||
xmlns:local_bike="clr-namespace:TINK.View.Bike"
|
||||
Title="{Binding Title}">
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<ContentPage.Content>
|
||||
<Frame>
|
||||
<StackLayout>
|
||||
<ListView
|
||||
x:Name="BikesAtStationListView"
|
||||
SelectionMode="None"
|
||||
SelectedItem="{Binding SelectedBike}"
|
||||
IsEnabled="{Binding IsIdle}"
|
||||
IsVisible="{Binding IsBikesListVisible}"
|
||||
HasUnevenRows="True"
|
||||
ItemTemplate="{StaticResource bikeTemplateSelector}"/>
|
||||
<StackLayout
|
||||
VerticalOptions="EndAndExpand"
|
||||
Orientation="Horizontal">
|
||||
<Label
|
||||
IsVisible="{Binding IsNoBikesAtStationVisible}"
|
||||
VerticalOptions="EndAndExpand"
|
||||
Text="{Binding NoBikesAtStationText}"/>
|
||||
<Label
|
||||
IsVisible="{Binding IsLoginRequiredHintVisible}"
|
||||
FormattedText="{Binding LoginRequiredHintText}">
|
||||
<Label.GestureRecognizers>
|
||||
<TapGestureRecognizer Command="{Binding LoginRequiredHintClickedCommand}"/>
|
||||
</Label.GestureRecognizers>
|
||||
</Label>
|
||||
<Label
|
||||
HeightRequest="20"
|
||||
Text="{Binding StatusInfoText}"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="FillAndExpand"/>
|
||||
<ActivityIndicator IsRunning="{Binding IsRunning}"
|
||||
IsVisible="{Binding IsRunning}"
|
||||
HeightRequest="20"
|
||||
VerticalOptions="CenterAndExpand"
|
||||
HorizontalOptions="End">
|
||||
<ActivityIndicator.WidthRequest>
|
||||
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" />
|
||||
</ActivityIndicator.WidthRequest>
|
||||
<ActivityIndicator.Color>
|
||||
<OnPlatform x:TypeArguments="Color"
|
||||
iOS="#2499CE" WinPhone="#2499CE" />
|
||||
</ActivityIndicator.Color>
|
||||
</ActivityIndicator>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
207
TINK/TINK/View/BikesAtStation/BikesAtStationPage.xaml.cs
Normal file
207
TINK/TINK/View/BikesAtStation/BikesAtStationPage.xaml.cs
Normal file
|
@ -0,0 +1,207 @@
|
|||
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
using TINK.Model.Bike.BluetoothLock;
|
||||
|
||||
namespace TINK.View.BikesAtStation
|
||||
{
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Device;
|
||||
using TINK.View.MasterDetail;
|
||||
using TINK.ViewModel;
|
||||
using TINK.Model;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using System.Collections.Generic;
|
||||
using Serilog;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using Plugin.BLE;
|
||||
using TINK.ViewModel.BikesAtStation;
|
||||
using TINK.ViewModel.Bikes;
|
||||
using Xamarin.CommunityToolkit.Extensions;
|
||||
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class BikesAtStationPage : ContentPage, IViewService, IDetailPage
|
||||
{
|
||||
|
||||
private BikesAtStationPageViewModel m_oViewModel;
|
||||
#if TRYNOTBACKSTYLE
|
||||
public BikesAtStationPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
var l_oModel = App.ModelRoot;
|
||||
|
||||
var l_oViewModel = new BikesAtStationPageViewModel(
|
||||
l_oModel.BikesAtStation,
|
||||
l_oModel.ActiveUser,
|
||||
l_oModel.SelectedStation,
|
||||
this);
|
||||
|
||||
BindingContext = l_oViewModel;
|
||||
BikesAtStationListView.ItemsSource = l_oViewModel;
|
||||
}
|
||||
|
||||
#else
|
||||
public BikesAtStationPage()
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when page is shown.
|
||||
/// Starts update process.
|
||||
/// </summary>
|
||||
protected async override void OnAppearing()
|
||||
{
|
||||
if (m_oViewModel != null)
|
||||
{
|
||||
#if BACKSTYLE
|
||||
// Hide master- detail menu to force user to navigate using back button.
|
||||
m_oNavigation.IsGestureEnabled = false;
|
||||
#endif
|
||||
|
||||
// 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 BikesAtStationPageViewModel(
|
||||
model.ActiveUser,
|
||||
model.Permissions,
|
||||
CrossBluetoothLE.Current,
|
||||
Device.RuntimePlatform,
|
||||
model.SelectedStation,
|
||||
() => model.GetIsConnected(),
|
||||
(isConnected) => model.GetConnector(isConnected),
|
||||
model.Geolocation,
|
||||
model.LocksServices.Active,
|
||||
model.Polling,
|
||||
(url) => DependencyService.Get<IExternalBrowserService>().OpenUrl(url),
|
||||
(d, obj) => synchronizationContext.Post(d, obj),
|
||||
this);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<BikesAtStationPage>().Error("Displaying bikes at station page failed. {Exception}", exception);
|
||||
this.DisplayAlert("Fehler", $"Seite Räder an Station kann nicht angezeigt werden. ${exception.Message}", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
#if BACKSTYLE
|
||||
// Hide master- detail menu to force user to navigate using back button.
|
||||
m_oNavigation.IsGestureEnabled = false;
|
||||
#endif
|
||||
|
||||
BindingContext = m_oViewModel;
|
||||
BikesAtStationListView.ItemsSource = m_oViewModel;
|
||||
|
||||
await m_oViewModel.OnAppearing();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when pages is closed/ hidden.
|
||||
/// Stops update process.
|
||||
/// </summary>
|
||||
protected async override void OnDisappearing()
|
||||
{
|
||||
if (m_oViewModel != null)
|
||||
{
|
||||
// View model might be null.
|
||||
await m_oViewModel?.OnDisappearing();
|
||||
}
|
||||
|
||||
#if BACKSTYLE
|
||||
if (m_oNavigation!= null)
|
||||
m_oNavigation.IsGestureEnabled = true; // Enables master- detail menu navigation again when page is unloaded.
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strCancel">Type of buttons.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary>
|
||||
/// Displays alert message.
|
||||
/// </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strAccept">Text of accept button.</param>
|
||||
/// <param name="p_strCancel">Text of button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public new async Task<bool> DisplayAlert(string p_strTitle, string p_strMessage, string p_strAccept, string p_strCancel)
|
||||
{
|
||||
return await App.Current.MainPage.DisplayAlert(p_strTitle, p_strMessage, p_strAccept, p_strCancel);
|
||||
}
|
||||
|
||||
/// <summary> Creates and a page an shows it.</summary>
|
||||
/// <remarks> When user is not logged in navigation to Login page is supported.</remarks>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
m_oNavigation.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public Task PushModalAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary> Pops a page from the modal stack. </summary>
|
||||
public Task PopModalAsync()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public Task PushAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delegate to perform navigation.
|
||||
/// </summary>
|
||||
private INavigationMasterDetail m_oNavigation;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate to perform navigation.
|
||||
/// </summary>
|
||||
public INavigationMasterDetail NavigationMasterDetail
|
||||
{
|
||||
set { m_oNavigation = value; }
|
||||
}
|
||||
|
||||
public async Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => await Navigation.ShowPopupAsync<FeedbackPopup.Result>(new FeedbackPopup());
|
||||
}
|
||||
}
|
38
TINK/TINK/View/Contact/ContactPage.xaml
Normal file
38
TINK/TINK/View/Contact/ContactPage.xaml
Normal file
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
|
||||
x:Class="TINK.View.Contact.ContactPage"
|
||||
Title="Kontakt">
|
||||
<ContentPage.Content>
|
||||
<ScrollView>
|
||||
<Frame>
|
||||
<StackLayout x:Name="ContactPageView">
|
||||
<Frame>
|
||||
<StackLayout>
|
||||
<Label FormattedText="{Binding MaliAddressAndMotivationsText}"/>
|
||||
<Button Text="{Binding MailAddressText}"
|
||||
IsEnabled="{Binding IsSendMailAvailable}"
|
||||
Command="{Binding OnMailRequest}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
<Frame>
|
||||
<StackLayout>
|
||||
<Label FormattedText="{Binding PhoneContactText}"/>
|
||||
<Button Text="{Binding PhoneNumberText}"
|
||||
IsEnabled="{Binding IsDoPhoncallAvailable}"
|
||||
Command="{Binding OnPhoneRequest}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
<Frame>
|
||||
<StackLayout>
|
||||
<Label FormattedText="{Binding LikeTinkApp}"/>
|
||||
<Button Text="{x:Static resources:AppResources.ActionContactRate}"
|
||||
Command="{Binding OnRateRequest}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</ScrollView>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
68
TINK/TINK/View/Contact/ContactPage.xaml.cs
Normal file
68
TINK/TINK/View/Contact/ContactPage.xaml.cs
Normal file
|
@ -0,0 +1,68 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Device;
|
||||
using TINK.ViewModel.Info;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.Contact
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class ContactPage : ContentPage, IViewService
|
||||
|
||||
{
|
||||
public ContactPage ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
|
||||
ContactPageView.BindingContext = new ContactPageViewModel(
|
||||
App.ModelRoot.Uris.ActiveUri,
|
||||
() => App.CreateAttachment(),
|
||||
() => DependencyService.Get<IExternalBrowserService>().OpenUrl(DependencyService.Get<IAppInfo>().StoreUrl),
|
||||
this);
|
||||
}
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public Task PushModalAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary> Pops a page from the modal stack. </summary>
|
||||
public Task PopModalAsync()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public Task PushAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
}
|
||||
}
|
18
TINK/TINK/View/CopriWebView/ManageAccountPage.xaml
Normal file
18
TINK/TINK/View/CopriWebView/ManageAccountPage.xaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TINK.View.CopriWebView.ManageAccountPage">
|
||||
<ContentPage.Content>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<StackLayout>
|
||||
<WebView x:Name="ManageAccount"
|
||||
HeightRequest="1400"
|
||||
WidthRequest="1000"
|
||||
Source="{Binding Uri}" />
|
||||
</StackLayout>
|
||||
</Grid>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
42
TINK/TINK/View/CopriWebView/ManageAccountPage.xaml.cs
Normal file
42
TINK/TINK/View/CopriWebView/ManageAccountPage.xaml.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using TINK.Model.Device;
|
||||
using TINK.ViewModel.Login;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.CopriWebView
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class ManageAccountPage : ContentPage
|
||||
{
|
||||
public ManageAccountPage ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
|
||||
ManageAccount.Navigating += (sender, ev) =>
|
||||
{
|
||||
if (!ev.Url.ToUpper().EndsWith(".PDF"))
|
||||
{
|
||||
// Stay inside web view except for downloading pdf- files.
|
||||
return;
|
||||
}
|
||||
|
||||
DependencyService.Get<IExternalBrowserService>().OpenUrl(ev.Url);
|
||||
};
|
||||
|
||||
ManageAccount.Navigated += (sender, ev) =>
|
||||
{
|
||||
if (ev.Result == WebNavigationResult.Success) return;
|
||||
|
||||
ManageAccount.Source = new HtmlWebViewSource
|
||||
{
|
||||
Html = "<html><b>Kann persönliche Daten nicht anzeigen/ verwalten!</b><br>Verbindung mit Internet ok?</html>"
|
||||
};
|
||||
};
|
||||
|
||||
ManageAccount.BindingContext = new ManageAccountViewModel(
|
||||
App.ModelRoot.ActiveUser.SessionCookie,
|
||||
Model.TinkApp.MerchantId,
|
||||
App.ModelRoot.NextActiveUri.Host);
|
||||
}
|
||||
}
|
||||
}
|
18
TINK/TINK/View/CopriWebView/PasswordForgottenPage.xaml
Normal file
18
TINK/TINK/View/CopriWebView/PasswordForgottenPage.xaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TINK.View.CopriWebView.PasswordForgottenPage">
|
||||
<ContentPage.Content>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<StackLayout>
|
||||
<WebView x:Name="PasswordForgottenWebView"
|
||||
HeightRequest="1400"
|
||||
WidthRequest="1000"
|
||||
Source="{Binding Uri}" />
|
||||
</StackLayout>
|
||||
</Grid>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
30
TINK/TINK/View/CopriWebView/PasswordForgottenPage.xaml.cs
Normal file
30
TINK/TINK/View/CopriWebView/PasswordForgottenPage.xaml.cs
Normal file
|
@ -0,0 +1,30 @@
|
|||
|
||||
using TINK.ViewModel.CopriWebView;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.CopriWebView
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class PasswordForgottenPage : ContentPage
|
||||
{
|
||||
public PasswordForgottenPage ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
|
||||
PasswordForgottenWebView.Navigated += (sender, ev) =>
|
||||
{
|
||||
if (ev.Result == WebNavigationResult.Success) return;
|
||||
|
||||
PasswordForgottenWebView.Source = new HtmlWebViewSource
|
||||
{
|
||||
Html = "<html><b>Kann Passwort vergessen Seite nicht anzeigen!</b><br>Verbindung mit Internet ok?</html>"
|
||||
};
|
||||
};
|
||||
|
||||
PasswordForgottenWebView.BindingContext = new PasswordForgottonViewModel(
|
||||
Model.TinkApp.MerchantId,
|
||||
App.ModelRoot.NextActiveUri.Host);
|
||||
}
|
||||
}
|
||||
}
|
18
TINK/TINK/View/CopriWebView/RegisterPage.xaml
Normal file
18
TINK/TINK/View/CopriWebView/RegisterPage.xaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TINK.View.CopriWebView.RegisterPage">
|
||||
<ContentPage.Content>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
</Grid.RowDefinitions>
|
||||
<StackLayout>
|
||||
<WebView x:Name="RegisterView"
|
||||
HeightRequest="1400"
|
||||
WidthRequest="1000"
|
||||
Source="{Binding Uri}" />
|
||||
</StackLayout>
|
||||
</Grid>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
33
TINK/TINK/View/CopriWebView/RegisterPage.xaml.cs
Normal file
33
TINK/TINK/View/CopriWebView/RegisterPage.xaml.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
|
||||
using TINK.Model.Device;
|
||||
using TINK.ViewModel.CopriWebView;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.CopriWebView
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class RegisterPage : ContentPage
|
||||
{
|
||||
public RegisterPage()
|
||||
{
|
||||
DependencyService.Get<IWebView>().ClearCookies();
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
RegisterView.Navigated += (sender, ev) =>
|
||||
{
|
||||
if (ev.Result == WebNavigationResult.Success) return;
|
||||
|
||||
RegisterView.Source = new HtmlWebViewSource
|
||||
{
|
||||
Html = "<html><b>Kann Anmeldeseite nicht anzeigen</b>!<br>Verbindung mit Internet ok?</html>"
|
||||
};
|
||||
};
|
||||
|
||||
RegisterView.BindingContext = new RegisterPageViewModel(
|
||||
App.ModelRoot.NextActiveUri.Host);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
85
TINK/TINK/View/FeedbackPopup.xaml
Normal file
85
TINK/TINK/View/FeedbackPopup.xaml
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<xct:Popup xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:xct="http://xamarin.com/schemas/2020/toolkit"
|
||||
xmlns:local="clr-namespace:TINK.View"
|
||||
x:TypeArguments="local:FeedbackPopup+Result"
|
||||
x:Class="TINK.View.FeedbackPopup">
|
||||
<xct:Popup.Resources>
|
||||
<x:String x:Key="check_circle"></x:String>
|
||||
</xct:Popup.Resources>
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<!-- Head and title row -->
|
||||
<RowDefinition Height="auto"/>
|
||||
<!--- checkbox and input elements-->
|
||||
<RowDefinition Height="*"/>
|
||||
<!--- ok button-->
|
||||
<RowDefinition Height="auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Grid
|
||||
Padding="30"
|
||||
BackgroundColor="{DynamicResource primary-back-title-color}">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"/>
|
||||
<RowDefinition Height="auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Label
|
||||
HorizontalTextAlignment="Center"
|
||||
FontSize="Large"
|
||||
Text="Fahrrad erfolgreich zurückgegeben!"/>
|
||||
<Image Grid.Row="1">
|
||||
<Image.Source>
|
||||
<FontImageSource Size="Header" Glyph="{StaticResource check_circle}" FontFamily="FA-S"/>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
</Grid>
|
||||
<ScrollView Grid.Row="1">
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*" />
|
||||
</Grid.RowDefinitions>
|
||||
<StackLayout
|
||||
Orientation="Vertical">
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<CheckBox x:Name="brockenCheckBox" IsChecked="True"/>
|
||||
<Label
|
||||
Grid.Column="1"
|
||||
FontSize="Medium"
|
||||
Text="Rad ist in Ordnung"/>
|
||||
</Grid>
|
||||
<Editor
|
||||
Grid.Row="1"
|
||||
x:Name="feedbackMessage"
|
||||
AutoSize="TextChanges"
|
||||
Placeholder="Bei Bedarf bitte hier Rückmeldung eingeben."
|
||||
Text="">
|
||||
<Editor.Triggers>
|
||||
<DataTrigger TargetType="Editor"
|
||||
Binding="{Binding Source={x:Reference brockenCheckBox}, Path=IsChecked}"
|
||||
Value="true">
|
||||
<Setter Property="Placeholder"
|
||||
Value="Bei Bedarf bitte hier Rückmeldung eingeben." />
|
||||
</DataTrigger>
|
||||
<DataTrigger TargetType="Editor"
|
||||
Binding="{Binding Source={x:Reference brockenCheckBox}, Path=IsChecked}"
|
||||
Value="false">
|
||||
<Setter Property="Placeholder"
|
||||
Value="Bitte Zustand/ Defekt hier beschreiben." />
|
||||
</DataTrigger>
|
||||
</Editor.Triggers>
|
||||
</Editor>
|
||||
</StackLayout>
|
||||
</Grid>
|
||||
</ScrollView>
|
||||
<Button
|
||||
Grid.Row="2"
|
||||
Clicked="OnOkClicked"
|
||||
Text="OK"/>
|
||||
</Grid>
|
||||
</xct:Popup>
|
60
TINK/TINK/View/FeedbackPopup.xaml.cs
Normal file
60
TINK/TINK/View/FeedbackPopup.xaml.cs
Normal file
|
@ -0,0 +1,60 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.CommunityToolkit.UI.Views;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class FeedbackPopup : Popup<FeedbackPopup.Result>
|
||||
{
|
||||
public FeedbackPopup ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
}
|
||||
|
||||
protected override FeedbackPopup.Result GetLightDismissResult()
|
||||
{
|
||||
return new Result
|
||||
{
|
||||
Message = feedbackMessage.Text,
|
||||
IsBikeBroken = brockenCheckBox.IsChecked
|
||||
};
|
||||
}
|
||||
|
||||
private void OnOkClicked(object sender, EventArgs eventArgs)
|
||||
{
|
||||
var result = new Result
|
||||
{
|
||||
Message = feedbackMessage.Text,
|
||||
IsBikeBroken = brockenCheckBox.IsChecked
|
||||
};
|
||||
|
||||
base.Dismiss(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Feedback given by user when returning bike.
|
||||
/// </summary>
|
||||
public class Result : IViewService.IUserFeedback
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds whether bike is broken or not.
|
||||
/// </summary>
|
||||
public bool IsBikeBroken { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Holds either
|
||||
/// - general feedback
|
||||
/// - error description of broken bike
|
||||
/// or both.
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
29
TINK/TINK/View/FeesAndBikes/FeesAndBikesPage.xaml
Normal file
29
TINK/TINK/View/FeesAndBikes/FeesAndBikesPage.xaml
Normal file
|
@ -0,0 +1,29 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
|
||||
x:Class="TINK.View.Contact.FeesAndBikesPage">
|
||||
<!--Pages can be added as references or inline-->
|
||||
<ContentPage Title="{x:Static resources:AppResources.MarkingTabFees}">
|
||||
<ContentPage.Content>
|
||||
<StackLayout>
|
||||
<WebView
|
||||
x:Name="InfoRentBikeWebView"
|
||||
HeightRequest="1000"
|
||||
WidthRequest="1000"
|
||||
Source="{Binding RentBikeText}"/>
|
||||
</StackLayout>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
<ContentPage Title="{x:Static resources:AppResources.MarkingTabBikes}">
|
||||
<ContentPage.Content>
|
||||
<StackLayout>
|
||||
<WebView
|
||||
x:Name="InfoTypesOfBikesWebView"
|
||||
HeightRequest="1000"
|
||||
WidthRequest="1000"
|
||||
Source="{Binding TypesOfBikesText}"/>
|
||||
</StackLayout>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
</TabbedPage>
|
36
TINK/TINK/View/FeesAndBikes/FeesAndBikesPage.xaml.cs
Normal file
36
TINK/TINK/View/FeesAndBikes/FeesAndBikesPage.xaml.cs
Normal file
|
@ -0,0 +1,36 @@
|
|||
using TINK.ViewModel;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
using TINK.ViewModel.Contact;
|
||||
using TINK.Model;
|
||||
|
||||
namespace TINK.View.Contact
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class FeesAndBikesPage : TabbedPage
|
||||
{
|
||||
public HelpContactViewModel ViewModel { get; }
|
||||
|
||||
public FeesAndBikesPage ()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
ViewModel = new HelpContactViewModel(
|
||||
TINK.App.ModelRoot.NextActiveUri.Host,
|
||||
TINK.App.ModelRoot.IsSiteCachingOn);
|
||||
BindingContext = ViewModel;
|
||||
|
||||
/// Info about renting.
|
||||
InfoRentBikeWebView.Navigating += ViewModelHelper.OnNavigating;
|
||||
|
||||
/// Info about types of bikes.
|
||||
InfoTypesOfBikesWebView.Navigating += ViewModelHelper.OnNavigating;
|
||||
}
|
||||
|
||||
/// <summary> Called when page is shown. </summary>
|
||||
protected override void OnAppearing()
|
||||
{
|
||||
ViewModel.OnAppearing();
|
||||
}
|
||||
}
|
||||
}
|
47
TINK/TINK/View/Info/BikeInfo/BikeInfoCarouselPage.xaml
Normal file
47
TINK/TINK/View/Info/BikeInfo/BikeInfoCarouselPage.xaml
Normal file
|
@ -0,0 +1,47 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<CarouselPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TINK.View.Info.BikeInfo.BikeInfoCarouselPage">
|
||||
<CarouselPage.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ContentPage>
|
||||
<ContentPage.Padding>
|
||||
<OnPlatform x:TypeArguments="Thickness">
|
||||
<On Platform="iOS" Value="0,40,0,0" />
|
||||
</OnPlatform>
|
||||
</ContentPage.Padding>
|
||||
<ScrollView Orientation="Vertical">
|
||||
<StackLayout>
|
||||
<Label
|
||||
Text="{Binding Title}"
|
||||
FontSize="Medium"
|
||||
HorizontalOptions="Center"
|
||||
HorizontalTextAlignment="Center"
|
||||
VerticalOptions="EndAndExpand"
|
||||
VerticalTextAlignment="End"/>
|
||||
<Image
|
||||
IsVisible="{Binding IsImageVisble}"
|
||||
Source="{Binding Image}"
|
||||
Aspect="AspectFit"
|
||||
HorizontalOptions="FillAndExpand"
|
||||
VerticalOptions="FillAndExpand"/>
|
||||
<Label
|
||||
Text="{Binding DescriptionText}"
|
||||
HorizontalOptions="Center"
|
||||
HorizontalTextAlignment="Center"
|
||||
VerticalOptions="StartAndExpand"
|
||||
VerticalTextAlignment="Start"/>
|
||||
<Button
|
||||
Text="Schließen"
|
||||
IsVisible="{Binding IsCloseVisible}"
|
||||
Command="{Binding OnCloseRequest}"
|
||||
VerticalOptions="End"/>
|
||||
<ProgressBar
|
||||
VerticalOptions="End"
|
||||
Progress="{Binding ProgressValue}"/>
|
||||
</StackLayout>
|
||||
</ScrollView>
|
||||
</ContentPage>
|
||||
</DataTemplate>
|
||||
</CarouselPage.ItemTemplate>
|
||||
</CarouselPage>
|
103
TINK/TINK/View/Info/BikeInfo/BikeInfoCarouselPage.xaml.cs
Normal file
103
TINK/TINK/View/Info/BikeInfo/BikeInfoCarouselPage.xaml.cs
Normal file
|
@ -0,0 +1,103 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.View.MasterDetail;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Info.BikeInfo;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.Info.BikeInfo
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class BikeInfoCarouselPage : CarouselPage, IViewService, IDetailPage
|
||||
{
|
||||
public BikeInfoCarouselPage ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
|
||||
ItemsSource = new BikeInfoViewModel(
|
||||
resourceName => ImageSource.FromResource($"{ViewModelResourceHelper.RessourcePrefix}Images.{resourceName}"),
|
||||
this).CarouselItems;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays altert message.
|
||||
/// </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strCancel">Type of buttons.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary>
|
||||
/// Displays alert message.
|
||||
/// </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strAccept">Text of accept button.</param>
|
||||
/// <param name="p_strCancel">Text of button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public new async Task<bool> DisplayAlert(string p_strTitle, string p_strMessage, string p_strAccept, string p_strCancel)
|
||||
{
|
||||
return await App.Current.MainPage.DisplayAlert(p_strTitle, p_strMessage, p_strAccept, p_strCancel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
m_oNavigation.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public Task PushModalAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary> Pops a page from the modal stack. </summary>
|
||||
public Task PopModalAsync()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public Task PushAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delegate to perform navigation.
|
||||
/// </summary>
|
||||
private INavigationMasterDetail m_oNavigation;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate to perform navigation.
|
||||
/// </summary>
|
||||
public INavigationMasterDetail NavigationMasterDetail
|
||||
{
|
||||
set { m_oNavigation = value; }
|
||||
}
|
||||
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
}
|
||||
}
|
40
TINK/TINK/View/Info/InfoPage.xaml.cs~Backup1
Normal file
40
TINK/TINK/View/Info/InfoPage.xaml.cs~Backup1
Normal file
|
@ -0,0 +1,40 @@
|
|||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class InfoPage : ContentPage
|
||||
{
|
||||
public InfoPage ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
|
||||
#if __IOS__
|
||||
var resourcePrefix = "TINK.iOS.";
|
||||
#endif
|
||||
#if __ANDROID__
|
||||
var resourcePrefix = "TINK.Droid.";
|
||||
#endif
|
||||
#if WINDOWS_PHONE
|
||||
var resourcePrefix = "TINK.WinPhone.";
|
||||
#endif
|
||||
|
||||
Debug.WriteLine("Using this resource prefix: " + resourcePrefix);
|
||||
// note that the prefix includes the trailing period '.' that is required
|
||||
var assembly = typeof(InfoPage).GetTypeInfo().Assembly;
|
||||
Stream stream = assembly.GetManifestResourceStream
|
||||
(resourcePrefix + "HtmlResouces.Info.html");
|
||||
var l_oHtmlViewSource = new HtmlWebViewSource
|
||||
{
|
||||
Html = (new StreamReader(stream, Encoding.UTF8)).ReadToEnd()
|
||||
};
|
||||
InfoWebView.Source = l_oHtmlViewSource;
|
||||
}
|
||||
}
|
||||
}
|
20
TINK/TINK/View/Info/InfoPage.xaml.cs~HEAD
Normal file
20
TINK/TINK/View/Info/InfoPage.xaml.cs~HEAD
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.Info
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class InfoPage : ContentPage
|
||||
{
|
||||
public InfoPage ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
}
|
||||
}
|
||||
}
|
52
TINK/TINK/View/Info/InfoTabbedPage.xaml
Normal file
52
TINK/TINK/View/Info/InfoTabbedPage.xaml
Normal file
|
@ -0,0 +1,52 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TINK.View.Info.TabbedPageInfo"
|
||||
x:Name="TabbedInfoPage">
|
||||
<!--Pages can be added as references or inline-->
|
||||
<ContentPage Title="App">
|
||||
<ContentPage.Content>
|
||||
<StackLayout>
|
||||
<WebView
|
||||
x:Name="InfoLicenses"
|
||||
Source="{Binding InfoLicenses}"
|
||||
HeightRequest="1000"
|
||||
WidthRequest="1000" />
|
||||
</StackLayout>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
<ContentPage Title="Datenschutz">
|
||||
<ContentPage.Content>
|
||||
<StackLayout>
|
||||
<WebView
|
||||
x:Name="InfoDatenschutz"
|
||||
Source="{Binding InfoPrivacy}"
|
||||
HeightRequest="1000"
|
||||
WidthRequest="1000" />
|
||||
</StackLayout>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
<ContentPage Title="AGB">
|
||||
<ContentPage.Content>
|
||||
<StackLayout>
|
||||
<WebView
|
||||
x:Name="InfoABG"
|
||||
Source ="{Binding InfoAgb}"
|
||||
HeightRequest="1000"
|
||||
WidthRequest="1000" />
|
||||
</StackLayout>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
<ContentPage Title="Impressum">
|
||||
<ContentPage.Content>
|
||||
<StackLayout>
|
||||
<WebView
|
||||
x:Name="InfoImpressum"
|
||||
Source="{Binding InfoImpressum}"
|
||||
HeightRequest="1000"
|
||||
WidthRequest="1000" />
|
||||
</StackLayout>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
||||
</TabbedPage>
|
||||
|
36
TINK/TINK/View/Info/InfoTabbedPage.xaml.cs
Normal file
36
TINK/TINK/View/Info/InfoTabbedPage.xaml.cs
Normal file
|
@ -0,0 +1,36 @@
|
|||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Info;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.Info
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class TabbedPageInfo : TabbedPage
|
||||
{
|
||||
public InfoViewModel ViewModel { get; }
|
||||
|
||||
public TabbedPageInfo()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
ViewModel = new InfoViewModel(
|
||||
App.ModelRoot.NextActiveUri.Host,
|
||||
App.ModelRoot.IsSiteCachingOn,
|
||||
resourceName => ViewModelResourceHelper.GetSource(resourceName));
|
||||
TabbedInfoPage.BindingContext = ViewModel;
|
||||
|
||||
InfoLicenses.Navigating += ViewModelHelper.OnNavigating;
|
||||
InfoDatenschutz.Navigating += ViewModelHelper.OnNavigating;
|
||||
InfoABG.Navigating += ViewModelHelper.OnNavigating;
|
||||
|
||||
InfoImpressum.Navigating += ViewModelHelper.OnNavigating;
|
||||
}
|
||||
|
||||
/// <summary> Called when page is shown. </summary>
|
||||
protected override void OnAppearing()
|
||||
{
|
||||
ViewModel.OnAppearing();
|
||||
}
|
||||
}
|
||||
}
|
35
TINK/TINK/View/ListViewAttachedBehavior.cs
Normal file
35
TINK/TINK/View/ListViewAttachedBehavior.cs
Normal file
|
@ -0,0 +1,35 @@
|
|||
using System.Windows.Input;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace TINK.View
|
||||
{
|
||||
public static class ListViewAttachedBehavior
|
||||
{
|
||||
public static readonly BindableProperty CommandProperty =
|
||||
BindableProperty.CreateAttached(
|
||||
"Command",
|
||||
typeof(ICommand),
|
||||
typeof(ListViewAttachedBehavior),
|
||||
null,
|
||||
propertyChanged: OnCommandChanged);
|
||||
|
||||
static void OnCommandChanged(BindableObject view, object oldValue, object newValue)
|
||||
{
|
||||
var entry = view as ListView;
|
||||
if (entry == null)
|
||||
return;
|
||||
|
||||
entry.ItemTapped += (sender, e) =>
|
||||
{
|
||||
var command = (newValue as ICommand);
|
||||
if (command == null)
|
||||
return;
|
||||
|
||||
if (command.CanExecute(e.Item))
|
||||
{
|
||||
command.Execute(e.Item);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
53
TINK/TINK/View/Login/LoginPage.xaml
Normal file
53
TINK/TINK/View/Login/LoginPage.xaml
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
|
||||
x:Class="TINK.View.Login.LoginPage">
|
||||
<ScrollView>
|
||||
<Frame>
|
||||
<StackLayout x:Name="LoginPageView">
|
||||
<Frame>
|
||||
<StackLayout>
|
||||
<Label Text="{x:Static resources:AppResources.MarkingLoginEmailAddressLabel}"/>
|
||||
<Entry
|
||||
Placeholder="{x:Static resources:AppResources.MarkingLoginEmailAddressPlaceholder}"
|
||||
Keyboard="Email"
|
||||
AutomationId="mail_address_text"
|
||||
x:Name="EMailEntry"
|
||||
Text="{Binding MailAddress}"
|
||||
IsEnabled="{Binding IsLoggedOut}"/>
|
||||
<Label Text="{x:Static resources:AppResources.MarkingLoginPasswordLabel}"/>
|
||||
<Entry
|
||||
Placeholder="{x:Static resources:AppResources.MarkingLoginPasswordPlaceholder}"
|
||||
AutomationId="password_text"
|
||||
IsPassword="true"
|
||||
x:Name="PasswordEntry"
|
||||
Text="{Binding Password}"
|
||||
IsEnabled="{Binding IsLoggedOut}"/>
|
||||
<Button
|
||||
Text="{x:Static resources:AppResources.ActionLoginLogin}"
|
||||
AutomationId="login_button"
|
||||
Command="{Binding OnLoginRequest}"
|
||||
IsEnabled="{Binding IsLoginRequestAllowed}">
|
||||
</Button>
|
||||
<Button
|
||||
Text="{x:Static resources:AppResources.ActionLoginRegister}"
|
||||
AutomationId="register_button"
|
||||
Command="{Binding OnRegisterRequest}"
|
||||
IsVisible="{Binding IsWebViewElementsVisible}">
|
||||
</Button>
|
||||
<Label
|
||||
IsVisible="{Binding IsRegisterTargetsInfoVisible}"
|
||||
FormattedText="{Binding RegisterTargetsInfo}">
|
||||
</Label>
|
||||
<Button
|
||||
Text="{x:Static resources:AppResources.ActionLoginPasswordForgotten}"
|
||||
AutomationId="password_forgotten_button"
|
||||
Command="{Binding OnPasswordForgottonRequest}">
|
||||
</Button>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</ScrollView>
|
||||
</ContentPage>
|
98
TINK/TINK/View/Login/LoginPage.xaml.cs
Normal file
98
TINK/TINK/View/Login/LoginPage.xaml.cs
Normal file
|
@ -0,0 +1,98 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Device;
|
||||
using TINK.View.MasterDetail;
|
||||
using TINK.ViewModel;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.Login
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class LoginPage : ContentPage, IViewService, IDetailPage
|
||||
{
|
||||
public LoginPage ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
|
||||
var l_oModel = App.ModelRoot;
|
||||
#if !BACKSTYLE
|
||||
var l_oViewModel = new LoginPageViewModel(
|
||||
l_oModel,
|
||||
(url) => DependencyService.Get< IExternalBrowserService>().OpenUrl(url),
|
||||
this);
|
||||
|
||||
LoginPageView.BindingContext = l_oViewModel;
|
||||
#else
|
||||
LoginPageView.BindingContext = new LoginPageViewModel(l_oModel.ActiveUser, this, Navigation);
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays altert message.
|
||||
/// </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strCancel">Type of buttons.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
m_oNavigation.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public Task PushModalAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary> Pops a page from the modal stack. </summary>
|
||||
public Task PopModalAsync()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public async Task PushAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
await Navigation.PushAsync((Page)Activator.CreateInstance(p_oTypeOfPage.GetViewType()));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delegate to perform navigation.
|
||||
/// </summary>
|
||||
private INavigationMasterDetail m_oNavigation;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate to perform navigation.
|
||||
/// </summary>
|
||||
public INavigationMasterDetail NavigationMasterDetail
|
||||
{
|
||||
set { m_oNavigation = value; }
|
||||
}
|
||||
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
}
|
||||
}
|
69
TINK/TINK/View/Map/MapPage.xaml
Normal file
69
TINK/TINK/View/Map/MapPage.xaml
Normal file
|
@ -0,0 +1,69 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:maps="clr-namespace:Xamarin.Forms.GoogleMaps;assembly=Xamarin.Forms.GoogleMaps"
|
||||
xmlns:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings"
|
||||
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
|
||||
x:Class="TINK.View.Map.MapPage"
|
||||
Title="{x:Static resources:AppResources.MarkingMapPage}">
|
||||
<StackLayout>
|
||||
<Grid
|
||||
IsEnabled="{Binding IsMapPageEnabled}"
|
||||
VerticalOptions="FillAndExpand">
|
||||
<maps:Map WidthRequest="320" HeightRequest="800"
|
||||
x:Name="MyMap"
|
||||
IsShowingUser="False"
|
||||
MapType="Street">
|
||||
<maps:Map.Behaviors>
|
||||
<bindings:BindingPinsBehavior Value="{Binding Pins}"/>
|
||||
<bindings:PinClickedToCommandBehavior Command="{Binding PinClickedCommand}"/>
|
||||
</maps:Map.Behaviors>
|
||||
</maps:Map>
|
||||
<Button
|
||||
x:Name="TINKButton"
|
||||
AutomationId ="FilterTINK_button"
|
||||
Text="TINK"
|
||||
Command="{Binding OnToggleKonradToTink}"
|
||||
IsVisible="{Binding IsToggleVisible}"
|
||||
TextColor ="{Binding TinkColor}"
|
||||
VerticalOptions="Start"
|
||||
HorizontalOptions="StartAndExpand"
|
||||
WidthRequest="80">
|
||||
</Button>
|
||||
<Button
|
||||
x:Name="KonradButton"
|
||||
AutomationId ="FilterKonrad_button"
|
||||
Text="Konrad"
|
||||
Command="{Binding OnToggleTinkToKonrad}"
|
||||
IsVisible="{Binding IsToggleVisible}"
|
||||
TextColor="{Binding KonradColor}"
|
||||
VerticalOptions="Start"
|
||||
HorizontalOptions="EndAndExpand"
|
||||
WidthRequest="80">
|
||||
</Button>
|
||||
</Grid>
|
||||
<StackLayout
|
||||
Margin="6,3,6,6"
|
||||
VerticalOptions="EndAndExpand"
|
||||
Orientation="Horizontal">
|
||||
<Label
|
||||
HeightRequest="20"
|
||||
Text="{Binding StatusInfoText}"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="FillAndExpand"/>
|
||||
<ActivityIndicator IsRunning="{Binding IsRunning}"
|
||||
IsVisible="{Binding IsRunning}"
|
||||
HeightRequest="20"
|
||||
VerticalOptions="CenterAndExpand"
|
||||
HorizontalOptions="End">
|
||||
<ActivityIndicator.WidthRequest>
|
||||
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" />
|
||||
</ActivityIndicator.WidthRequest>
|
||||
<ActivityIndicator.Color>
|
||||
<OnPlatform x:TypeArguments="Color"
|
||||
iOS="#2499CE" WinPhone="#2499CE" />
|
||||
</ActivityIndicator.Color>
|
||||
</ActivityIndicator>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</ContentPage>
|
172
TINK/TINK/View/Map/MapPage.xaml.cs
Normal file
172
TINK/TINK/View/Map/MapPage.xaml.cs
Normal file
|
@ -0,0 +1,172 @@
|
|||
using Plugin.Connectivity;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.View.MasterDetail;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.Map
|
||||
{
|
||||
using TINK.Model.Services.CopriApi.ServerUris;
|
||||
using TINK.ViewModel.Map;
|
||||
using Xamarin.Forms.GoogleMaps;
|
||||
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class MapPage : ContentPage, IViewService, IDetailPage
|
||||
{
|
||||
/// <summary> View model to notify about whether page appears or hides. </summary>
|
||||
private MapPageViewModel m_oMapPageViewModel;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs map page instance.
|
||||
/// </summary>
|
||||
public MapPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays altert message.
|
||||
/// </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strCancel">Type of buttons.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary>
|
||||
/// Displays alert message.
|
||||
/// </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strAccept">Text of accept button.</param>
|
||||
/// <param name="p_strCancel">Text of button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public new async Task<bool> DisplayAlert(string p_strTitle, string p_strMessage, string p_strAccept, string p_strCancel)
|
||||
{
|
||||
return await App.Current.MainPage.DisplayAlert(p_strTitle, p_strMessage, p_strAccept, p_strCancel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
m_oNavigationMasterDetail.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to display.</param>
|
||||
public async Task PushModalAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
await Navigation.PushModalAsync((Page)Activator.CreateInstance(p_oTypeOfPage.GetViewType()));
|
||||
}
|
||||
|
||||
/// <summary> Pops a page from the modal stack. </summary>
|
||||
public async Task PopModalAsync()
|
||||
{
|
||||
await Navigation.PopModalAsync();
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public async Task PushAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
var page = Activator.CreateInstance(p_oTypeOfPage.GetViewType()) as IDetailPage;
|
||||
if (page == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
page.NavigationMasterDetail = m_oNavigationMasterDetail;
|
||||
|
||||
await Navigation.PushAsync((Page)page);
|
||||
}
|
||||
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
|
||||
/// <summary> Delegate to perform navigation. </summary>
|
||||
private INavigationMasterDetail m_oNavigationMasterDetail;
|
||||
|
||||
/// <summary> Delegate to perform navigation.</summary>
|
||||
public INavigationMasterDetail NavigationMasterDetail
|
||||
{
|
||||
set
|
||||
{
|
||||
m_oNavigationMasterDetail = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when page is shown.
|
||||
/// Starts update process.
|
||||
/// </summary>
|
||||
protected async override void OnAppearing()
|
||||
{
|
||||
// Pass reference to member Navigation to show bikes at station x dialog.
|
||||
#if TRYNOTBACKSTYLE
|
||||
m_oMapPageViewModel = new MapPageViewModel();
|
||||
#else
|
||||
m_oMapPageViewModel = new MapPageViewModel(
|
||||
App.ModelRoot,
|
||||
(mapspan) => MyMap.MoveToRegion(mapspan),
|
||||
this,
|
||||
Navigation);
|
||||
#endif
|
||||
|
||||
BindingContext = m_oMapPageViewModel;
|
||||
|
||||
if (Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
TINKButton.BackgroundColor = Color.LightGray;
|
||||
TINKButton.BorderColor = Color.Black;
|
||||
TINKButton.Margin = new Thickness(10, 10, 10, 10);
|
||||
KonradButton.BackgroundColor = Color.LightGray;
|
||||
KonradButton.BorderColor = Color.Black;
|
||||
KonradButton.Margin = new Thickness(10, 10, 10, 10);
|
||||
}
|
||||
|
||||
m_oMapPageViewModel.NavigationMasterDetail = m_oNavigationMasterDetail;
|
||||
|
||||
base.OnAppearing();
|
||||
|
||||
// Pre move and scanle maps to avoid initial display of map in Rome.
|
||||
MapPageViewModel.MoveAndScale(
|
||||
(mapSpan) => MyMap.MoveToRegion(mapSpan),
|
||||
App.ModelRoot.Uris.ActiveUri,
|
||||
App.ModelRoot.GroupFilterMapPage);
|
||||
|
||||
await m_oMapPageViewModel.OnAppearing();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when pages is closed/ hidden.
|
||||
/// Stops update process.
|
||||
/// </summary>
|
||||
protected override async void OnDisappearing()
|
||||
{
|
||||
if (m_oMapPageViewModel != null)
|
||||
{
|
||||
// View model might be null.
|
||||
await m_oMapPageViewModel?.OnDisappearing();
|
||||
}
|
||||
|
||||
base.OnDisappearing();
|
||||
}
|
||||
}
|
||||
}
|
53
TINK/TINK/View/MyBikes/MyBikesPage.xaml
Normal file
53
TINK/TINK/View/MyBikes/MyBikesPage.xaml
Normal file
|
@ -0,0 +1,53 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TINK.View.MyBikes.MyBikesPage"
|
||||
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
|
||||
xmlns:local_bike="clr-namespace:TINK.View.Bike"
|
||||
Title="{x:Static resources:AppResources.MarkingMyBikes}">
|
||||
<ContentPage.Resources>
|
||||
<ResourceDictionary>
|
||||
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
|
||||
</ResourceDictionary>
|
||||
</ContentPage.Resources>
|
||||
<ContentPage.Content>
|
||||
<Frame>
|
||||
<StackLayout>
|
||||
<ListView
|
||||
x:Name="MyBikesListView"
|
||||
SelectionMode="None"
|
||||
SelectedItem="{Binding SelectedBike}"
|
||||
IsEnabled="{Binding IsIdle}"
|
||||
IsVisible="{Binding IsBikesListVisible}"
|
||||
HasUnevenRows="True"
|
||||
ItemTemplate="{StaticResource bikeTemplateSelector}"/>
|
||||
<StackLayout
|
||||
VerticalOptions="EndAndExpand"
|
||||
Orientation="Horizontal">
|
||||
<Label
|
||||
IsVisible="{Binding IsNoBikesOccupiedVisible}"
|
||||
VerticalOptions="StartAndExpand"
|
||||
Text="{Binding NoBikesOccupiedText}"/>
|
||||
<Label
|
||||
HeightRequest="20"
|
||||
Text="{Binding StatusInfoText}"
|
||||
VerticalOptions="Center"
|
||||
HorizontalOptions="FillAndExpand"/>
|
||||
<ActivityIndicator IsRunning="{Binding IsRunning}"
|
||||
IsVisible="{Binding IsRunning}"
|
||||
HeightRequest="20"
|
||||
VerticalOptions="CenterAndExpand"
|
||||
HorizontalOptions="End">
|
||||
<ActivityIndicator.WidthRequest>
|
||||
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" />
|
||||
</ActivityIndicator.WidthRequest>
|
||||
<ActivityIndicator.Color>
|
||||
<OnPlatform x:TypeArguments="Color"
|
||||
iOS="#2499CE" WinPhone="#2499CE" />
|
||||
</ActivityIndicator.Color>
|
||||
</ActivityIndicator>
|
||||
</StackLayout>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
170
TINK/TINK/View/MyBikes/MyBikesPage.xaml.cs
Normal file
170
TINK/TINK/View/MyBikes/MyBikesPage.xaml.cs
Normal file
|
@ -0,0 +1,170 @@
|
|||
using Plugin.Connectivity;
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike.BluetoothLock;
|
||||
using TINK.View.MasterDetail;
|
||||
using TINK.ViewModel;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.MyBikes
|
||||
{
|
||||
using Plugin.Permissions.Abstractions;
|
||||
using Plugin.Permissions;
|
||||
using TINK.Model;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
using System.Collections.Generic;
|
||||
using Serilog;
|
||||
using Plugin.BLE;
|
||||
using TINK.Services.BluetoothLock;
|
||||
using TINK.ViewModel.MyBikes;
|
||||
using Xamarin.CommunityToolkit.Extensions;
|
||||
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class MyBikesPage : ContentPage, IViewService
|
||||
{
|
||||
/// <summary> Refernce to view model. </summary>
|
||||
MyBikesPageViewModel m_oViewModel = null;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a my bikes page.
|
||||
/// </summary>
|
||||
public MyBikesPage()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when page is shown.
|
||||
/// Starts update process.
|
||||
/// </summary>
|
||||
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 MyBikesPageViewModel(
|
||||
model.ActiveUser,
|
||||
model.Permissions,
|
||||
CrossBluetoothLE.Current,
|
||||
Device.RuntimePlatform,
|
||||
() => model.GetIsConnected(),
|
||||
(isConnected) => model.GetConnector(isConnected),
|
||||
model.Geolocation,
|
||||
model.LocksServices.Active,
|
||||
model.Polling,
|
||||
(d, obj) => synchronizationContext.Post(d, obj),
|
||||
this);
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<MyBikesPage>().Error("Displaying bikes at station page failed. {Exception}", exception);
|
||||
this.DisplayAlert("Fehler", $"Seite Räder an Station kann nicht angezeigt werden. ${exception.Message}", "OK");
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
BindingContext = m_oViewModel;
|
||||
MyBikesListView.ItemsSource = m_oViewModel;
|
||||
|
||||
await m_oViewModel.OnAppearing();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when pages is closed/ hidden.
|
||||
/// Stops update process.
|
||||
/// </summary>
|
||||
protected async override void OnDisappearing()
|
||||
{
|
||||
if (m_oViewModel == null)
|
||||
{
|
||||
// View model might be null (Example: Occured when page to querry for location permissions was opened)
|
||||
return;
|
||||
}
|
||||
|
||||
await m_oViewModel.OnDisappearing();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Displays altert message.
|
||||
/// </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strCancel">Type of buttons.</param>
|
||||
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);
|
||||
}
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
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);
|
||||
|
||||
/// <summary>
|
||||
/// Displays alert message.
|
||||
/// </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strAccept">Text of accept button.</param>
|
||||
/// <param name="p_strCancel">Text of button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public new async Task<bool> DisplayAlert(string p_strTitle, string p_strMessage, string p_strAccept, string p_strCancel)
|
||||
{
|
||||
return await App.Current.MainPage.DisplayAlert(p_strTitle, p_strMessage, p_strAccept, p_strCancel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public Task PushModalAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary> Pops a page from the modal stack. </summary>
|
||||
public Task PopModalAsync()
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public Task PushAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
public async Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => await Navigation.ShowPopupAsync<FeedbackPopup.Result>(new FeedbackPopup());
|
||||
}
|
||||
}
|
17
TINK/TINK/View/RootFlyout/RootPage.xaml
Normal file
17
TINK/TINK/View/RootFlyout/RootPage.xaml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<FlyoutPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TINK.View.Root.RootPage"
|
||||
xmlns:pages="clr-namespace:TINK.View.Root"
|
||||
xmlns:mappage="clr-namespace:TINK.View.Map">
|
||||
<FlyoutPage.Flyout>
|
||||
<pages:RootPageFlyout x:Name="FlyoutPage" />
|
||||
</FlyoutPage.Flyout>
|
||||
<FlyoutPage.Detail>
|
||||
<NavigationPage>
|
||||
<x:Arguments>
|
||||
<mappage:MapPage />
|
||||
</x:Arguments>
|
||||
</NavigationPage>
|
||||
</FlyoutPage.Detail>
|
||||
</FlyoutPage>
|
83
TINK/TINK/View/RootFlyout/RootPage.xaml.cs
Normal file
83
TINK/TINK/View/RootFlyout/RootPage.xaml.cs
Normal file
|
@ -0,0 +1,83 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.View.MasterDetail;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.Root
|
||||
{
|
||||
/// <summary>
|
||||
/// Mamages creation of detail pages if a flyout page menu entry is selected.
|
||||
/// Exposes flyout page style navigation which is used by detail pages.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Examples of use cases when detail pages do navigation:
|
||||
// - switch to map page after succesfully logging in/ logging out
|
||||
// - switch to login page form bikes at station page if not yet logged in
|
||||
/// </remarks>
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class RootPage : FlyoutPage, INavigationMasterDetail
|
||||
{
|
||||
public RootPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
FlyoutPage.ListView.ItemSelected += OnListViewItemSelected;
|
||||
|
||||
// Any type of split behaviour conflics with map shifting functionality (assuming FlyoutPage behaves same like MasterDetailPage).
|
||||
FlyoutLayoutBehavior = FlyoutLayoutBehavior.Popover;
|
||||
|
||||
var navigationPage = Detail as NavigationPage;
|
||||
if (navigationPage == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var detailPage = navigationPage.RootPage as IDetailPage;
|
||||
if (detailPage == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
detailPage.NavigationMasterDetail = this;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Is called if a flyout page menu entry is selected.
|
||||
/// Creates a new page.
|
||||
/// </summary>
|
||||
private void OnListViewItemSelected(object sender, SelectedItemChangedEventArgs e)
|
||||
{
|
||||
var item = e.SelectedItem as RootPageFlyoutMenuItem;
|
||||
if (item == null)
|
||||
return;
|
||||
|
||||
ShowPage(item.TargetType, item.Title);
|
||||
|
||||
IsPresented = false;
|
||||
FlyoutPage.ListView.SelectedItem = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows a detail page.
|
||||
/// </summary>
|
||||
/// <param name="typeOfPage">Type of page to show.</param>
|
||||
/// <param name="title">Title of page.</param>
|
||||
public void ShowPage(Type typeOfPage, string title)
|
||||
{
|
||||
var page = (Page)Activator.CreateInstance(typeOfPage);
|
||||
page.Title = title;
|
||||
|
||||
if (page is IDetailPage detailPage)
|
||||
{
|
||||
// Detail page needs reference to perform navigation.
|
||||
// Examples see above in xdoc of class.
|
||||
detailPage.NavigationMasterDetail = this;
|
||||
}
|
||||
|
||||
Detail = new NavigationPage(page);
|
||||
}
|
||||
}
|
||||
}
|
61
TINK/TINK/View/RootFlyout/RootPageFlyout.xaml
Normal file
61
TINK/TINK/View/RootFlyout/RootPageFlyout.xaml
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TINK.View.Root.RootPageFlyout"
|
||||
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
|
||||
xmlns:local="clr-namespace:TINK.View"
|
||||
IconImageSource="Icon-Small@2x"
|
||||
Title="sharee.bike">
|
||||
<StackLayout>
|
||||
<ListView x:Name="MenuItemsListView"
|
||||
SeparatorVisibility="None"
|
||||
HasUnevenRows="true"
|
||||
local:ListViewAttachedBehavior.Command="{Binding MenuItemSelected}"
|
||||
ItemsSource="{Binding MenuItems}">
|
||||
<ListView.Header>
|
||||
<Grid BackgroundColor="{DynamicResource Key=primary-back-title-color}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="10"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="10"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="30"/>
|
||||
<RowDefinition Height="80"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="10"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Label
|
||||
Grid.Column="1"
|
||||
Grid.Row="2"
|
||||
Text="{Binding MasterDetailMenuTitlte}"
|
||||
Style="{DynamicResource SubtitleStyle}"/>
|
||||
</Grid>
|
||||
</ListView.Header>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ViewCell>
|
||||
<Grid Padding="5,10">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="30"/>
|
||||
<ColumnDefinition Width="*" />
|
||||
</Grid.ColumnDefinitions>
|
||||
<Image>
|
||||
<Image.Source>
|
||||
<FontImageSource Glyph="{Binding GlyphCode}" Color="Black" FontFamily="FA-S"/>
|
||||
</Image.Source>
|
||||
</Image>
|
||||
<Label
|
||||
Grid.Column="1"
|
||||
Margin="10, 0, 0, 0"
|
||||
VerticalOptions="FillAndExpand"
|
||||
VerticalTextAlignment="Center"
|
||||
FontSize="18"
|
||||
Text="{Binding Title}"/>
|
||||
</Grid>
|
||||
</ViewCell>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackLayout>
|
||||
</ContentPage>
|
34
TINK/TINK/View/RootFlyout/RootPageFlyout.xaml.cs
Normal file
34
TINK/TINK/View/RootFlyout/RootPageFlyout.xaml.cs
Normal file
|
@ -0,0 +1,34 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model;
|
||||
using TINK.Services;
|
||||
using TINK.View.MasterDetail;
|
||||
using TINK.View.Themes;
|
||||
using TINK.ViewModel.Root;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.Root
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class RootPageFlyout : ContentPage
|
||||
{
|
||||
public ListView ListView;
|
||||
|
||||
public RootPageFlyout()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
BindingContext = new RootPageFlyoutViewModel();
|
||||
|
||||
ListView = MenuItemsListView;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
24
TINK/TINK/View/RootFlyout/RootPageFlyoutMenuItem.cs
Normal file
24
TINK/TINK/View/RootFlyout/RootPageFlyoutMenuItem.cs
Normal file
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace TINK.View.Root
|
||||
{
|
||||
|
||||
public class RootPageFlyoutMenuItem
|
||||
{
|
||||
public RootPageFlyoutMenuItem()
|
||||
{
|
||||
TargetType = typeof(RootPageFlyoutMenuItem);
|
||||
}
|
||||
public int Id { get; set; }
|
||||
|
||||
public string GlyphCode { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
|
||||
public Type TargetType { get; set; }
|
||||
}
|
||||
}
|
17
TINK/TINK/View/RootMasterDetail/MainPage.xaml
Normal file
17
TINK/TINK/View/RootMasterDetail/MainPage.xaml
Normal file
|
@ -0,0 +1,17 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<MasterDetailPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TINK.View.MainPage"
|
||||
xmlns:pages="clr-namespace:TINK.View"
|
||||
xmlns:mappage="clr-namespace:TINK.View.Map">
|
||||
<MasterDetailPage.Master>
|
||||
<pages:MasterPage x:Name="MasterPage" />
|
||||
</MasterDetailPage.Master>
|
||||
<MasterDetailPage.Detail>
|
||||
<NavigationPage>
|
||||
<x:Arguments>
|
||||
<mappage:MapPage />
|
||||
</x:Arguments>
|
||||
</NavigationPage>
|
||||
</MasterDetailPage.Detail>
|
||||
</MasterDetailPage>
|
81
TINK/TINK/View/RootMasterDetail/MainPage.xaml.cs
Normal file
81
TINK/TINK/View/RootMasterDetail/MainPage.xaml.cs
Normal file
|
@ -0,0 +1,81 @@
|
|||
using System;
|
||||
using TINK.View.Info.BikeInfo;
|
||||
using TINK.View.MasterDetail;
|
||||
using TINK.ViewModel.MasterDetail;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate to perform navigation.
|
||||
/// </summary>
|
||||
public delegate void ShowPageDelegate(Type p_oType, string p_strTitle = null);
|
||||
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class MainPage : MasterDetailPage, INavigationMasterDetail
|
||||
{
|
||||
public MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
MasterPage.ShowPageViewService = ShowPage;
|
||||
|
||||
// Any type of split behaviour conflics with map shifting functionality.
|
||||
MasterBehavior = MasterBehavior.Popover;
|
||||
|
||||
var navigationPage = Detail as NavigationPage;
|
||||
if (navigationPage == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var detailPage = navigationPage.RootPage as IDetailPage;
|
||||
if (detailPage == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
detailPage.NavigationMasterDetail = this;
|
||||
}
|
||||
|
||||
/// <summary> Creates and a page an shows it.</summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(
|
||||
Type p_oTypeOfPage,
|
||||
string p_strTitle = null)
|
||||
{
|
||||
if (p_oTypeOfPage == null)
|
||||
return;
|
||||
|
||||
var page = (Page)Activator.CreateInstance(p_oTypeOfPage);
|
||||
page.Title = p_strTitle ?? Helper.GetCaption(p_oTypeOfPage);
|
||||
|
||||
var l_oPage = page as IDetailPage;
|
||||
if (l_oPage != null)
|
||||
{
|
||||
l_oPage.NavigationMasterDetail = this;
|
||||
}
|
||||
|
||||
#if !BACKSTYLE
|
||||
// When bike info page is shown do not allow to close this carousel before all pages were displayed.
|
||||
IsGestureEnabled = p_oTypeOfPage != typeof(BikeInfoCarouselPage);
|
||||
|
||||
Detail = new NavigationPage(page);
|
||||
IsPresented = false;
|
||||
#else
|
||||
Detail.Navigation.PushAsync(page);
|
||||
IsPresented = false;
|
||||
|
||||
while (Detail.Navigation.NavigationStack.Count > 2)
|
||||
{
|
||||
// Ensure that stack does never contains more than 2 pages (root page + one child)
|
||||
// This can occure if from child via swipe onther child is opened.
|
||||
// Remove item after adding new one to avoid flickering.
|
||||
Detail.Navigation.RemovePage(Detail.Navigation.NavigationStack[1]);
|
||||
}
|
||||
#endif
|
||||
|
||||
MasterPage.ListView.SelectedItem = null;
|
||||
}
|
||||
}
|
||||
}
|
42
TINK/TINK/View/RootMasterDetail/MainPageMenuItem.cs
Normal file
42
TINK/TINK/View/RootMasterDetail/MainPageMenuItem.cs
Normal file
|
@ -0,0 +1,42 @@
|
|||
using System;
|
||||
using TINK.View.Map;
|
||||
using TINK.ViewModel.MasterDetail;
|
||||
|
||||
namespace TINK.View
|
||||
{
|
||||
public class MainPageMenuItem
|
||||
{
|
||||
public MainPageMenuItem()
|
||||
{
|
||||
TargetType = typeof(MapPage);
|
||||
}
|
||||
|
||||
public MainPageMenuItem(
|
||||
int p_iId,
|
||||
Type p_oTypeOfPage,
|
||||
string p_strTitle = null)
|
||||
{
|
||||
TargetType = p_oTypeOfPage;
|
||||
Id = p_iId;
|
||||
Title = p_strTitle ?? Helper.GetCaption(p_oTypeOfPage);
|
||||
}
|
||||
|
||||
public int Id
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public string Title
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
public Type TargetType
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
}
|
51
TINK/TINK/View/RootMasterDetail/MasterPage.xaml
Normal file
51
TINK/TINK/View/RootMasterDetail/MasterPage.xaml
Normal file
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
|
||||
x:Class="TINK.View.MasterPage"
|
||||
xmlns:local="clr-namespace:TINK.View"
|
||||
Icon="Icon-Small@2x"
|
||||
Title="TINK">
|
||||
<StackLayout>
|
||||
<ListView x:Name="MenuItemsListView"
|
||||
SeparatorVisibility="None"
|
||||
HasUnevenRows="true"
|
||||
local:ListViewAttachedBehavior.Command="{Binding MenuItemSelected}"
|
||||
SelectedItem="{Binding SelectedMenuItem}"
|
||||
ItemsSource="{Binding MenuItems}">
|
||||
<ListView.Header>
|
||||
<Grid BackgroundColor="{DynamicResource Key=primary-back-title-color}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="10"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
<ColumnDefinition Width="10"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="30"/>
|
||||
<RowDefinition Height="80"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="10"/>
|
||||
</Grid.RowDefinitions>
|
||||
<Label
|
||||
Grid.Column="1"
|
||||
Grid.Row="2"
|
||||
FontSize="Large"
|
||||
Text="{Binding MasterDetailMenuTitlte}"
|
||||
Style="{DynamicResource SubtitleStyle}"/>
|
||||
</Grid>
|
||||
</ListView.Header>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ViewCell>
|
||||
<StackLayout Padding="15,10" HorizontalOptions="FillAndExpand">
|
||||
<Label VerticalOptions="FillAndExpand"
|
||||
VerticalTextAlignment="Center"
|
||||
Text="{Binding Title}"
|
||||
FontSize="24"/>
|
||||
</StackLayout>
|
||||
</ViewCell>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackLayout>
|
||||
</ContentPage>
|
32
TINK/TINK/View/RootMasterDetail/MasterPage.xaml.cs
Normal file
32
TINK/TINK/View/RootMasterDetail/MasterPage.xaml.cs
Normal file
|
@ -0,0 +1,32 @@
|
|||
using TINK.ViewModel;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class MasterPage : ContentPage
|
||||
{
|
||||
public ListView ListView;
|
||||
|
||||
/// <summary>
|
||||
/// Master page view model
|
||||
/// </summary>
|
||||
private MasterPageViewModel m_oMasterPageViewModel;
|
||||
|
||||
/// <summary> Delegate to perform navigation between detail pages. </summary>
|
||||
public ShowPageDelegate ShowPageViewService { set => m_oMasterPageViewModel.ShowPageViewService = value; }
|
||||
|
||||
public MasterPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
m_oMasterPageViewModel = new MasterPageViewModel();
|
||||
|
||||
|
||||
|
||||
BindingContext = m_oMasterPageViewModel;
|
||||
ListView = MenuItemsListView;
|
||||
}
|
||||
}
|
||||
}
|
96
TINK/TINK/View/RootShell/AppShell.xaml
Normal file
96
TINK/TINK/View/RootShell/AppShell.xaml
Normal file
|
@ -0,0 +1,96 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Shell xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
|
||||
xmlns:mappage="clr-namespace:TINK.View.Map"
|
||||
xmlns:mybikes="clr-namespace:TINK.View.MyBikes"
|
||||
xmlns:account="clr-namespace:TINK.View.Account"
|
||||
xmlns:login="clr-namespace:TINK.View.Login"
|
||||
xmlns:settings="clr-namespace:TINK.View.Settings"
|
||||
xmlns:contact="clr-namespace:TINK.View.Contact"
|
||||
xmlns:info="clr-namespace:TINK.View.Info"
|
||||
xmlns:header="clr-namespace:TINK.View.RootShell"
|
||||
BackgroundColor="{DynamicResource Key=primary-back-title-color}"
|
||||
Title="Shell"
|
||||
x:Class="TINK.View.RootShell.AppShell">
|
||||
<Shell.FlyoutHeader>
|
||||
<header:FlyoutHeader/>
|
||||
</Shell.FlyoutHeader>
|
||||
|
||||
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
|
||||
<ShellContent
|
||||
Title="{x:Static resources:AppResources.MarkingMapPage}"
|
||||
ContentTemplate="{DataTemplate mappage:MapPage}">
|
||||
<ShellContent.FlyoutIcon>
|
||||
<FontImageSource Glyph="{StaticResource IconMap}" Color="Black" FontFamily="FA-S" />
|
||||
</ShellContent.FlyoutIcon>
|
||||
</ShellContent>
|
||||
</FlyoutItem>
|
||||
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
|
||||
<ShellContent
|
||||
Title="{x:Static resources:AppResources.MarkingMyBikes}"
|
||||
IsVisible="{Binding IsMyBikesPageVisible}"
|
||||
ContentTemplate="{DataTemplate mybikes:MyBikesPage}">
|
||||
<ShellContent.FlyoutIcon>
|
||||
<FontImageSource Glyph="{StaticResource IconMyBikes}" Color="Black" FontFamily="FA-S" />
|
||||
</ShellContent.FlyoutIcon>
|
||||
</ShellContent>
|
||||
</FlyoutItem>
|
||||
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
|
||||
<ShellContent
|
||||
Title="{x:Static resources:AppResources.MarkingAccount}"
|
||||
IsVisible="{Binding IsAccountPageVisible}"
|
||||
ContentTemplate="{DataTemplate account:AccountPage}">
|
||||
<ShellContent.FlyoutIcon>
|
||||
<FontImageSource Glyph="{StaticResource IconAccount}" Color="Black" FontFamily="FA-S" />
|
||||
</ShellContent.FlyoutIcon>
|
||||
</ShellContent>
|
||||
</FlyoutItem>
|
||||
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
|
||||
<ShellContent
|
||||
Title="{x:Static resources:AppResources.MarkingLogin}"
|
||||
IsVisible="{Binding IsLoginPageVisible}"
|
||||
ContentTemplate="{DataTemplate login:LoginPage}">
|
||||
<ShellContent.FlyoutIcon>
|
||||
<FontImageSource Glyph="{StaticResource IconLogin}" Color="Black" FontFamily="FA-S" />
|
||||
</ShellContent.FlyoutIcon>
|
||||
</ShellContent>
|
||||
</FlyoutItem>
|
||||
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
|
||||
<ShellContent
|
||||
Title="{x:Static resources:AppResources.MarkingSettings}"
|
||||
IsVisible="{Binding IsSettingsPageVisible}"
|
||||
ContentTemplate="{DataTemplate settings:SettingsPage}">
|
||||
<ShellContent.FlyoutIcon>
|
||||
<FontImageSource Glyph="{StaticResource IconSettings}" Color="Black" FontFamily="FA-S" />
|
||||
</ShellContent.FlyoutIcon>
|
||||
</ShellContent>
|
||||
</FlyoutItem>
|
||||
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
|
||||
<ShellContent
|
||||
Title="{x:Static resources:AppResources.MarkingFeesAndBikes}"
|
||||
ContentTemplate="{DataTemplate contact:FeesAndBikesPage}">
|
||||
<ShellContent.FlyoutIcon>
|
||||
<FontImageSource Glyph="{StaticResource IconFeesAndBikes}" Color="Black" FontFamily="FA-S" />
|
||||
</ShellContent.FlyoutIcon>
|
||||
</ShellContent>
|
||||
</FlyoutItem>
|
||||
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
|
||||
<ShellContent
|
||||
Title="{x:Static resources:AppResources.MarkingFeedbackAndContact}"
|
||||
ContentTemplate="{DataTemplate contact:ContactPage}">
|
||||
<ShellContent.FlyoutIcon>
|
||||
<FontImageSource Glyph="{StaticResource IconContact}" Color="Black" FontFamily="FA-S" />
|
||||
</ShellContent.FlyoutIcon>
|
||||
</ShellContent>
|
||||
</FlyoutItem>
|
||||
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
|
||||
<ShellContent
|
||||
Title="{Binding TabbedPageIngoTitle}"
|
||||
ContentTemplate="{DataTemplate info:TabbedPageInfo}">
|
||||
<ShellContent.FlyoutIcon>
|
||||
<FontImageSource Glyph="{StaticResource IconInfo}" Color="Black" FontFamily="FA-S" />
|
||||
</ShellContent.FlyoutIcon>
|
||||
</ShellContent>
|
||||
</FlyoutItem>
|
||||
</Shell>
|
17
TINK/TINK/View/RootShell/AppShell.xaml.cs
Normal file
17
TINK/TINK/View/RootShell/AppShell.xaml.cs
Normal file
|
@ -0,0 +1,17 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TINK.ViewModel.RootShell;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace TINK.View.RootShell
|
||||
{
|
||||
public partial class AppShell : Shell
|
||||
{
|
||||
public AppShell()
|
||||
{
|
||||
InitializeComponent();
|
||||
BindingContext = new AppShellViewModel();
|
||||
}
|
||||
}
|
||||
}
|
21
TINK/TINK/View/RootShell/FlyoutHeader.xaml
Normal file
21
TINK/TINK/View/RootShell/FlyoutHeader.xaml
Normal file
|
@ -0,0 +1,21 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
BackgroundColor="{DynamicResource Key=primary-back-title-color}"
|
||||
x:Class="TINK.View.RootShell.FlyoutHeader">
|
||||
<Grid Padding="5,10">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="*"/>
|
||||
<RowDefinition Height="30" />
|
||||
</Grid.RowDefinitions>
|
||||
<Image
|
||||
HeightRequest="140"
|
||||
Aspect="AspectFit"
|
||||
Source="sharee_no_background.png" />
|
||||
<Label
|
||||
HorizontalOptions="CenterAndExpand"
|
||||
FontSize="Large"
|
||||
Grid.Row="1"
|
||||
Text="{Binding MasterDetailMenuTitlte}"/>
|
||||
</Grid>
|
||||
</ContentView>
|
20
TINK/TINK/View/RootShell/FlyoutHeader.xaml.cs
Normal file
20
TINK/TINK/View/RootShell/FlyoutHeader.xaml.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.RootShell
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class FlyoutHeader : ContentView
|
||||
{
|
||||
public FlyoutHeader ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
}
|
||||
}
|
||||
}
|
33
TINK/TINK/View/Settings/AnyPermissionToVisibleConverter.cs
Normal file
33
TINK/TINK/View/Settings/AnyPermissionToVisibleConverter.cs
Normal file
|
@ -0,0 +1,33 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
using TINK.Model.User.Account;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace TINK.View.Settings
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Translates user permissions into visibility state.
|
||||
/// Used for container which holds a bunch of GUI elemets which migth all/ partly/ none be visible
|
||||
/// If all childs are invisible frame must be invisible as well. As soon as one child is visible frame must be visible as well.
|
||||
/// </summary>
|
||||
public class AnyPermissionToVisibleConverter : IValueConverter
|
||||
{
|
||||
/// <summary> Converts permission value into visible state.</summary>
|
||||
/// <param name="value">Permission value from view model used to derive whether object is visible or not.</param>
|
||||
/// <returns>Boolean value indicating whether object is visible or not.</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return ((Permissions)(value)) != Permissions.None;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return Permissions.None;
|
||||
}
|
||||
}
|
||||
}
|
38
TINK/TINK/View/Settings/PermissionToVisibleConverter.cs
Normal file
38
TINK/TINK/View/Settings/PermissionToVisibleConverter.cs
Normal file
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
using TINK.Model.User.Account;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace TINK.View.Settings
|
||||
{
|
||||
/// <summary> Translates user permissions into visibility state. </summary>
|
||||
public class PermissionToVisibleConverter : BindableObject, IValueConverter
|
||||
{
|
||||
static readonly BindableProperty VisibleFlagProperty =
|
||||
BindableProperty.Create(nameof(VisibleFlag), typeof(Permissions), typeof(BindableObject));
|
||||
|
||||
/// <summary> Property set from XAML determinig for which permission value object is visible.</summary>
|
||||
public Permissions VisibleFlag
|
||||
{
|
||||
get => (Permissions)GetValue(VisibleFlagProperty);
|
||||
set => SetValue(VisibleFlagProperty, value);
|
||||
}
|
||||
|
||||
/// <summary> Converts permission value into visible state.</summary>
|
||||
/// <param name="value">Permission value from view model used to derive whether object is visible or not.</param>
|
||||
/// <returns>Boolean value indicating whether object is visible or not.</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return ((Permissions)(value)).HasFlag(VisibleFlag);
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return Permissions.None;
|
||||
}
|
||||
}
|
||||
}
|
217
TINK/TINK/View/Settings/SettingsPage.xaml
Normal file
217
TINK/TINK/View/Settings/SettingsPage.xaml
Normal file
|
@ -0,0 +1,217 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TINK.View.Settings.SettingsPage"
|
||||
xmlns:conv="clr-namespace:TINK.View.Settings">
|
||||
|
||||
<ContentPage.Resources>
|
||||
<conv:AnyPermissionToVisibleConverter x:Key="Frame_Converter"/>
|
||||
<conv:PermissionToVisibleConverter x:Key="PickCopriServer_Converter" VisibleFlag="PickCopriServer"/>
|
||||
<conv:PermissionToVisibleConverter x:Key="ManagePolling_Converter" VisibleFlag="ManagePolling"/>
|
||||
<conv:PermissionToVisibleConverter x:Key="ManageCopriCacheExpiration_Converter" VisibleFlag="ManageCopriCacheExpiration"/>
|
||||
<conv:PermissionToVisibleConverter x:Key="PickLockServiceImplementation_Converter" VisibleFlag="PickLockServiceImplementation"/>
|
||||
<conv:PermissionToVisibleConverter x:Key="PickLocationServiceImplementation_Converter" VisibleFlag="PickLocationServiceImplementation"/>
|
||||
<conv:PermissionToVisibleConverter x:Key="PickLoggingLevel_Converter" VisibleFlag="PickLoggingLevel"/>
|
||||
<conv:PermissionToVisibleConverter x:Key="ShowDiagnostics_Converter" VisibleFlag="ShowDiagnostics"/>
|
||||
<conv:PermissionToVisibleConverter x:Key="SwitchSiteCaching_Converter" VisibleFlag="SwitchNoSiteCaching"/>
|
||||
</ContentPage.Resources>
|
||||
|
||||
<ContentPage.Content>
|
||||
<ScrollView>
|
||||
<Frame>
|
||||
<StackLayout>
|
||||
<!--
|
||||
<Button Text="Feedback" Clicked="OnFeedbackClickedAsync"/>
|
||||
-->
|
||||
<Frame>
|
||||
<StackLayout>
|
||||
<Label Text="Karte auf aktuelle Position ausrichten"/>
|
||||
<Switch IsToggled="{Binding CenterMapToCurrentLocation}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
<!-- Filter on view TINK/ Konrad -->
|
||||
<Frame IsVisible="{Binding IsGroupFilterVisible}">
|
||||
<StackLayout>
|
||||
<Label Text="Ausblenden/ Einblenden"/>
|
||||
<ListView
|
||||
HasUnevenRows="True"
|
||||
HeightRequest="120"
|
||||
x:Name="Filters">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<ViewCell IsEnabled="{Binding IsEnabled}">
|
||||
<StackLayout Orientation="Horizontal">
|
||||
<Label Text="{Binding Text}"/>
|
||||
<Switch IsToggled="{Binding IsActivated}"/>
|
||||
</StackLayout>
|
||||
</ViewCell>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
<Frame
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource Frame_Converter}}">
|
||||
<StackLayout>
|
||||
<!-- Themes -->
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
||||
Text="Theme"/>
|
||||
<Picker
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
||||
ItemsSource="{Binding Themes.ServicesTextList}"
|
||||
SelectedItem="{Binding Themes.ActiveText}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
<Frame
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource Frame_Converter}}">
|
||||
<!-- COPRI server selection -->
|
||||
<StackLayout>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
||||
Text="{Binding CopriServerUriList.CorpiServerUriDescription}"/>
|
||||
<Picker
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickCopriServer_Converter}}"
|
||||
ItemsSource="{Binding CopriServerUriList.ServerTextList}"
|
||||
SelectedItem="{Binding CopriServerUriList.NextActiveServerText}"/>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ManagePolling_Converter}}"
|
||||
Text="{Binding Polling.PollingText}"/>
|
||||
<Switch
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ManagePolling_Converter}}"
|
||||
IsToggled="{Binding Polling.IsActivated}"/>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ManagePolling_Converter}}"
|
||||
Text="{Binding Polling.PeriodeTotalSecondsText}"/>
|
||||
<Stepper
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ManagePolling_Converter}}"
|
||||
Minimum="5"
|
||||
Increment="5"
|
||||
Maximum="600"
|
||||
IsEnabled="{Binding Polling.IsActivated}"
|
||||
Value="{Binding Polling.PeriodeTotalSeconds}"/>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ManageCopriCacheExpiration_Converter}}"
|
||||
Text="Time after which COPRI-cache expires [s]"/>
|
||||
<Slider
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ManageCopriCacheExpiration_Converter}}"
|
||||
x:Name="expiresAfter"
|
||||
Minimum="0"
|
||||
Maximum="15"
|
||||
Value="{Binding ExpiresAfterTotalSeconds}"/>
|
||||
<Entry
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ManageCopriCacheExpiration_Converter}}"
|
||||
IsReadOnly="True"
|
||||
Text="{Binding ExpiresAfterTotalSecondsText}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
<Frame
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource Frame_Converter}}">
|
||||
<!-- Lock control -->
|
||||
<StackLayout>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickLockServiceImplementation_Converter}}"
|
||||
Text="Lock Control" />
|
||||
<Picker
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickLockServiceImplementation_Converter}}"
|
||||
ItemsSource="{Binding LocksServices.Services.ServicesTextList}"
|
||||
SelectedItem="{Binding LocksServices.Services.ActiveText}"/>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickLockServiceImplementation_Converter}}"
|
||||
Text="Bluetooth Connect Timeout [sec]"/>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickLockServiceImplementation_Converter}}"
|
||||
Text="{Binding LocksServices.ConnectTimeoutSecText}"/>
|
||||
<Stepper
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickLockServiceImplementation_Converter}}"
|
||||
Minimum="0.1"
|
||||
Increment="0.25"
|
||||
Maximum="60"
|
||||
Value="{Binding LocksServices.ConnectTimeoutSec}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
<Frame
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource Frame_Converter}}">
|
||||
<!-- Geolocation -->
|
||||
<StackLayout>
|
||||
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickLocationServiceImplementation_Converter}}"
|
||||
Text="Geolocation Control" />
|
||||
<Picker
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickLocationServiceImplementation_Converter}}"
|
||||
ItemsSource="{Binding GeolocationServices.ServicesTextList}"
|
||||
SelectedItem="{Binding GeolocationServices.ActiveText}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
<Frame
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource Frame_Converter}}">
|
||||
<!-- Web site caching -->
|
||||
<StackLayout>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource SwitchSiteCaching_Converter}}"
|
||||
Text="Caching von Websiten."/>
|
||||
<Switch
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource SwitchSiteCaching_Converter}}"
|
||||
IsToggled="{Binding IsSiteCachingOnDisplayValue}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
<Frame
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource Frame_Converter}}">
|
||||
<!-- Logging -->
|
||||
<StackLayout>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickLoggingLevel_Converter}}"
|
||||
Text="Logging level" />
|
||||
<Picker
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickLoggingLevel_Converter}}"
|
||||
ItemsSource="{Binding LoggingLevels}"
|
||||
SelectedItem="{Binding SelectedLoggingLevel}"/>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickLoggingLevel_Converter}}"
|
||||
Text="Logdatei in externen Pfad schreiben"/>
|
||||
<Switch
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource PickLoggingLevel_Converter}}"
|
||||
IsToggled="{Binding LogToExternalFolderDisplayValue}"
|
||||
IsEnabled="{Binding IsLogToExternalFolderVisible}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
<Frame
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource Frame_Converter}}">
|
||||
<!-- Display of parameters -->
|
||||
<StackLayout>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ShowDiagnostics_Converter}}"
|
||||
Text="Device Identifier" />
|
||||
<Entry
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ShowDiagnostics_Converter}}"
|
||||
IsEnabled="false"
|
||||
Text="{Binding DeviceIdentifier}"/>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ShowDiagnostics_Converter}}"
|
||||
Text="Copri Sitzungkeks"/>
|
||||
<Entry
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ShowDiagnostics_Converter}}"
|
||||
IsEnabled="false"
|
||||
Text="{Binding SessionCookie}"/>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ShowDiagnostics_Converter}}"
|
||||
Text="Interner Pfad (Einstell./ ggf. Logging)"/>
|
||||
<Editor
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ShowDiagnostics_Converter}}"
|
||||
IsEnabled="false"
|
||||
Text="{Binding InternalPath}"/>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ShowDiagnostics_Converter}}"
|
||||
Text="Externer Pfad (Mock/ ggf. Logging)"/>
|
||||
<Editor
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ShowDiagnostics_Converter}}"
|
||||
IsEnabled="false"
|
||||
Text="{Binding ExternalPath}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</ScrollView>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
135
TINK/TINK/View/Settings/SettingsPage.xaml.cs
Normal file
135
TINK/TINK/View/Settings/SettingsPage.xaml.cs
Normal file
|
@ -0,0 +1,135 @@
|
|||
using TINK.ViewModel;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.View.MasterDetail;
|
||||
using System;
|
||||
using TINK.Model.Device;
|
||||
using Xamarin.CommunityToolkit.Extensions;
|
||||
|
||||
namespace TINK.View.Settings
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class SettingsPage : ContentPage, IViewService, IDetailPage
|
||||
{
|
||||
/// <summary> Refernce to view model. </summary>
|
||||
SettingsPageViewModel m_oViewModel = null;
|
||||
|
||||
/// <summary> Constructs a settings page. </summary>
|
||||
public SettingsPage ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
|
||||
var l_oModel = App.ModelRoot;
|
||||
|
||||
m_oViewModel = new SettingsPageViewModel(
|
||||
l_oModel,
|
||||
this);
|
||||
|
||||
BindingContext = m_oViewModel;
|
||||
|
||||
Filters.ItemsSource = m_oViewModel.GroupFilter;
|
||||
}
|
||||
|
||||
/// <summary> Displays alert message. </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strCancel">Type of buttons.</param>
|
||||
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);
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary> Displays alert message.</summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strAccept">Text of accept button.</param>
|
||||
/// <param name="p_strCancel">Text of button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public new async Task<bool> 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);
|
||||
|
||||
/// <summary>
|
||||
/// Displays an action sheet.
|
||||
/// </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strCancel">Text of button.</param>
|
||||
/// <param name="destruction"></param>
|
||||
/// <param name="p_oButtons">Buttons holding options to select.</param>
|
||||
/// <returns>Text selected</returns>
|
||||
public new async Task<string> DisplayActionSheet(String p_strTitle, String p_strCancel, String destruction, params String[] p_oButtons)
|
||||
=> await base.DisplayActionSheet(p_strTitle, p_strCancel, destruction, p_oButtons);
|
||||
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
=> m_oNavigation.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public Task PushModalAsync(ViewTypes p_oTypeOfPage)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
/// <summary> Pops a page from the modal stack. </summary>
|
||||
public Task PopModalAsync()
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
/// <summary>Delegate to perform navigation.</summary>
|
||||
private INavigationMasterDetail m_oNavigation;
|
||||
|
||||
/// <summary>
|
||||
/// Delegate to perform navigation.
|
||||
/// </summary>
|
||||
public INavigationMasterDetail NavigationMasterDetail
|
||||
{
|
||||
set { m_oNavigation = value; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when pages is closed/ hidden.
|
||||
/// Stops update process.
|
||||
/// </summary>
|
||||
protected async override void OnDisappearing()
|
||||
{
|
||||
if (m_oViewModel == null)
|
||||
{
|
||||
// View model might be null.
|
||||
return;
|
||||
}
|
||||
|
||||
await m_oViewModel?.OnDisappearing();
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public async Task PushAsync(ViewTypes p_oTypeOfPage)
|
||||
=> await Navigation.PushAsync((Page)Activator.CreateInstance(p_oTypeOfPage.GetViewType()));
|
||||
|
||||
public async Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => await Navigation.ShowPopupAsync<FeedbackPopup.Result>(new FeedbackPopup());
|
||||
|
||||
#if USERFEEDBACKDLG_TRYOUT
|
||||
public async void OnFeedbackClickedAsync(object sender, EventArgs ev)
|
||||
{
|
||||
var result = await DisplayUserFeedbackPopup();
|
||||
|
||||
DisplayAlert(
|
||||
"Title",
|
||||
$"Bike broken: {result.IsBikeBroken}. Message: {result.Message}.",
|
||||
"OK");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
25
TINK/TINK/View/StringNotNullOrEmptyToVisibleConverter.cs
Normal file
25
TINK/TINK/View/StringNotNullOrEmptyToVisibleConverter.cs
Normal file
|
@ -0,0 +1,25 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace TINK.View
|
||||
{
|
||||
/// <summary> Converts a string into visible state. If string is null or empty element becomes invisible.</summary>
|
||||
public class StringNotNullOrEmptyToVisibleConverter : IValueConverter
|
||||
{
|
||||
/// <summary> Converts a string into visible state.</summary>
|
||||
/// <param name="value">Text value from view model used to derive whether object is visible or not.</param>
|
||||
/// <returns>Boolean value indicating whether object is visible or not.</returns>
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return (value != null && value is string text && !string.IsNullOrEmpty(text));
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
67
TINK/TINK/View/ViewTypesTypeProvider.cs
Normal file
67
TINK/TINK/View/ViewTypesTypeProvider.cs
Normal file
|
@ -0,0 +1,67 @@
|
|||
using System;
|
||||
using TINK.View.Contact;
|
||||
using TINK.View.CopriWebView;
|
||||
using TINK.View.Info;
|
||||
using TINK.View.Info.BikeInfo;
|
||||
using TINK.View.Login;
|
||||
using TINK.View.Map;
|
||||
using TINK.View.MyBikes;
|
||||
using TINK.View.Settings;
|
||||
using TINK.View.WhatsNew;
|
||||
using TINK.View.WhatsNew.Agb;
|
||||
using TINK.View.BikesAtStation;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace TINK.View
|
||||
{
|
||||
public static class ViewTypesTypeProvider
|
||||
{
|
||||
public static Type GetViewType(this ViewTypes viewType)
|
||||
{
|
||||
switch (viewType)
|
||||
{
|
||||
case ViewTypes.LoginPage:
|
||||
return typeof(LoginPage);
|
||||
|
||||
case ViewTypes.MapPage:
|
||||
return typeof(MapPage);
|
||||
|
||||
case ViewTypes.RegisterPage:
|
||||
return typeof(RegisterPage);
|
||||
|
||||
case ViewTypes.PasswordForgottenPage:
|
||||
return typeof(PasswordForgottenPage);
|
||||
|
||||
case ViewTypes.BikeInfoCarouselPage:
|
||||
return typeof(BikeInfoCarouselPage);
|
||||
|
||||
case ViewTypes.MyBikesPage:
|
||||
return typeof(MyBikesPage);
|
||||
|
||||
case ViewTypes.SettingsPage:
|
||||
return typeof(SettingsPage);
|
||||
|
||||
case ViewTypes.TabbedPageInfo:
|
||||
return typeof(TabbedPageInfo);
|
||||
|
||||
case ViewTypes.TabbedPageHelpContact:
|
||||
return typeof(FeesAndBikesPage);
|
||||
|
||||
case ViewTypes.ManageAccountPage:
|
||||
return typeof(ManageAccountPage);
|
||||
|
||||
case ViewTypes.AgbPage:
|
||||
return typeof(AgbPage);
|
||||
|
||||
case ViewTypes.WhatsNewPage:
|
||||
return typeof(WhatsNewPage);
|
||||
|
||||
case ViewTypes.BikesAtStation:
|
||||
return typeof(BikesAtStationPage);
|
||||
|
||||
default:
|
||||
return typeof(ContentPage);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
18
TINK/TINK/View/WhatsNew/Agb/AgbPage.xaml
Normal file
18
TINK/TINK/View/WhatsNew/Agb/AgbPage.xaml
Normal file
|
@ -0,0 +1,18 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TINK.View.WhatsNew.Agb.AgbPage">
|
||||
<ContentPage.Content>
|
||||
<Frame>
|
||||
<StackLayout>
|
||||
<WebView
|
||||
HeightRequest="1000"
|
||||
WidthRequest="500"
|
||||
Source="{Binding InfoAgb}"/>
|
||||
<Button Text="OK"
|
||||
Command="{Binding OnOk}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
71
TINK/TINK/View/WhatsNew/Agb/AgbPage.xaml.cs
Normal file
71
TINK/TINK/View/WhatsNew/Agb/AgbPage.xaml.cs
Normal file
|
@ -0,0 +1,71 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.WhatsNew.Agb;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.WhatsNew.Agb
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class AgbPage : ContentPage, IViewService
|
||||
{
|
||||
public AgbPage ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
|
||||
agbViewModel = new AgbViewModel(
|
||||
App.ModelRoot.NextActiveUri.Host,
|
||||
App.ModelRoot.IsSiteCachingOn,
|
||||
(resourceName) => ViewModelResourceHelper.GetSource(resourceName),
|
||||
this);
|
||||
|
||||
BindingContext = agbViewModel;
|
||||
}
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary> Invoked when page is shown. </summary>
|
||||
protected async override void OnAppearing()
|
||||
{
|
||||
await agbViewModel.OnAppearing();
|
||||
}
|
||||
|
||||
/// <summary> Reference to view model.</summary>
|
||||
AgbViewModel agbViewModel;
|
||||
|
||||
public async Task PopModalAsync()
|
||||
{
|
||||
await Navigation.PopModalAsync();
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public Task PushAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task PushModalAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
}
|
||||
}
|
42
TINK/TINK/View/WhatsNew/WhatsNewPage.xaml
Normal file
42
TINK/TINK/View/WhatsNew/WhatsNewPage.xaml
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
|
||||
x:Class="TINK.View.WhatsNew.WhatsNewPage">
|
||||
<ContentPage.Content>
|
||||
<ScrollView>
|
||||
<Frame>
|
||||
<StackLayout>
|
||||
<Label Text="{Binding WhatsNewTitle}"
|
||||
FontSize="Large"
|
||||
VerticalOptions="Start"
|
||||
HorizontalOptions="CenterAndExpand" />
|
||||
<Frame>
|
||||
<StackLayout>
|
||||
<Label
|
||||
Text="{Binding WhatsNewText}"
|
||||
TextType="Html"/>
|
||||
<Label FormattedText="{Binding AgbChangedText}"
|
||||
IsVisible="{Binding IsAgbChangedVisible}">
|
||||
<Label.GestureRecognizers>
|
||||
<TapGestureRecognizer Command="{Binding OnShowAgbTapped}"/>
|
||||
</Label.GestureRecognizers>
|
||||
</Label>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
<Frame IsVisible="{Binding IsFeedbackVisible}">
|
||||
<StackLayout>
|
||||
<Label Text="Gibts Verbesserungsvorschläge/ Probleme mit der App?"/>
|
||||
<Button Text="Verbesserungsmail schreiben"/>
|
||||
<Label Text="Die App läuft rund und tut was sie soll? Über eine Bewertung würden wir uns sehr freuen!"/>
|
||||
<Button Text="Bewertung abgeben"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
|
||||
<Button
|
||||
Text="OK"
|
||||
Command="{Binding OnOk}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
</ScrollView>
|
||||
</ContentPage.Content>
|
||||
</ContentPage>
|
87
TINK/TINK/View/WhatsNew/WhatsNewPage.xaml.cs
Normal file
87
TINK/TINK/View/WhatsNew/WhatsNewPage.xaml.cs
Normal file
|
@ -0,0 +1,87 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Device;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.WhatsNew
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class WhatsNewPage : ContentPage, IViewService
|
||||
{
|
||||
/// <summary> Holds a reference on the view model. </summary>
|
||||
private ViewModel.WhatsNew.WhatsNewViewModel WhatsNewViewModel;
|
||||
|
||||
/// <summary> Constructs whats new page.</summary>
|
||||
/// <param name="showMasterDetail">Action to invoke master detail page.</param>
|
||||
public WhatsNewPage(Action showMasterDetail)
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
WhatsNewViewModel = new ViewModel.WhatsNew.WhatsNewViewModel(
|
||||
DependencyService.Get<IAppInfo>().Version,
|
||||
App.ModelRoot.WhatsNew.WhatsNewText,
|
||||
App.ModelRoot.WhatsNew.IsShowAgbRequired,
|
||||
showMasterDetail,
|
||||
this);
|
||||
|
||||
BindingContext = WhatsNewViewModel;
|
||||
}
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
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);
|
||||
|
||||
public Task PopModalAsync()
|
||||
{
|
||||
throw new NotImplementedException(); ;
|
||||
}
|
||||
|
||||
/// <summary> Pushes a page onto the stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public Task PushAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task PushModalAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
await Navigation.PushModalAsync((Page)Activator.CreateInstance(p_oTypeOfPage.GetViewType()));
|
||||
}
|
||||
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when pages is closed/ hidden.
|
||||
/// /// </summary>
|
||||
protected override void OnDisappearing()
|
||||
{
|
||||
base.OnDisappearing();
|
||||
|
||||
if (WhatsNewViewModel == null)
|
||||
{
|
||||
// View model might be null.
|
||||
return;
|
||||
}
|
||||
|
||||
WhatsNewViewModel?.OnDisappearing(() =>
|
||||
{
|
||||
App.ModelRoot.SetWhatsNewWasShown();
|
||||
App.ModelRoot.Save();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue