Version 3.0.353

This commit is contained in:
Anja 2022-12-07 16:54:52 +01:00
parent 5ea2e3b0ca
commit 85321580df
57 changed files with 1421 additions and 888 deletions

View file

@ -85,21 +85,21 @@ namespace TINK.Droid
} }
}; };
await Permissions.RequestAsync<BLEAndLocationPermissions>();
LoadApplication(new App()); LoadApplication(new App());
await Permissions.RequestAsync<BLEPermissions>();
await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
} }
//Bluetooth Permission on Android 12 "Detect Devices nearby" //Bluetooth Permission on Android 12 "Detect Devices nearby"
// https://stackoverflow.com/questions/71028853/xamarin-forms-ble-plugin-scan-issue-android-12 // https://stackoverflow.com/questions/71028853/xamarin-forms-ble-plugin-scan-issue-android-12
public class BLEAndLocationPermissions : BasePlatformPermission public class BLEPermissions : BasePlatformPermission
{ {
public override (string androidPermission, bool isRuntime)[] RequiredPermissions => new List<(string androidPermission, bool isRuntime)> public override (string androidPermission, bool isRuntime)[] RequiredPermissions => new List<(string androidPermission, bool isRuntime)>
{ {
(Android.Manifest.Permission.BluetoothScan, true), (Android.Manifest.Permission.BluetoothScan, true),
(Android.Manifest.Permission.BluetoothConnect, true), (Android.Manifest.Permission.BluetoothConnect, true),
(Android.Manifest.Permission.AccessFineLocation, true) //(Android.Manifest.Permission.AccessFineLocation, true)
}.ToArray(); }.ToArray();
} }

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.LastenradBayern" android:versionName="3.0.352" android:versionCode="352"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.LastenradBayern" android:versionName="3.0.353" android:versionCode="353">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" /> <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" />
<!-- Google Maps related permissions --> <!-- Google Maps related permissions -->
<!-- Permission to receive remote notifications from Google Play Services --> <!-- Permission to receive remote notifications from Google Play Services -->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -55,8 +55,8 @@
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>LastenradBayern</string> <string>LastenradBayern</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>352</string> <string>353</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.352</string> <string>3.0.353</string>
</dict> </dict>
</plist> </plist>

View file

@ -41,7 +41,7 @@ endobj
6 0 obj 6 0 obj
<< /Producer (cairo 1.17.4 (https://cairographics.org)) << /Producer (cairo 1.17.4 (https://cairographics.org))
/Creator <FEFF0049006E006B0073006300610070006500200031002E0031002E00320020002800680074007400700073003A002F002F0069006E006B00730063006100700065002E006F007200670029> /Creator <FEFF0049006E006B0073006300610070006500200031002E0031002E00320020002800680074007400700073003A002F002F0069006E006B00730063006100700065002E006F007200670029>
/CreationDate (D:20221124081702+01'00) /CreationDate (D:20221206105042+01'00)
>> >>
endobj endobj
7 0 obj 7 0 obj

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
@ -322,7 +322,7 @@ namespace TINK
if (_PermissionsService != null) if (_PermissionsService != null)
return _PermissionsService; return _PermissionsService;
_PermissionsService = new TINK.Services.Permissions.Essentials.Permissions(); _PermissionsService = new TINK.Services.Permissions.Essentials.LocationPermissions();
return _PermissionsService; return _PermissionsService;
} }
} }

View file

@ -96,7 +96,7 @@
</StackLayout> </StackLayout>
<!--While process is running--> <!--While process is running-->
<sharedGui:RunningProcessView <sharedGui:RunningProcessViewBay
IsVisible="{Binding IsRunning}" IsVisible="{Binding IsRunning}"
Grid.Row="1"/> Grid.Row="1"/>

View file

@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:maps="clr-namespace:Xamarin.Forms.GoogleMaps;assembly=Xamarin.Forms.GoogleMaps" 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:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
x:Class="TINK.View.Contact.SelectStationPage"> x:Class="TINK.View.Contact.SelectStationPage"
BackgroundColor="{DynamicResource Key=primary-back-title-color}">
<Shell.TitleView> <Shell.TitleView>
<Grid ColumnDefinitions="Auto, 1*"> <Grid ColumnDefinitions="Auto, 1*">
<Label Style="{StaticResource Label-Navbar}" <Label Style="{StaticResource Label-Navbar}"
@ -52,4 +53,4 @@
</StackLayout> </StackLayout>
</StackLayout> </StackLayout>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -56,7 +56,7 @@
</StackLayout> </StackLayout>
<!--While process is running--> <!--While process is running-->
<sharedGui:RunningProcessView <sharedGui:RunningProcessViewBay
Grid.Row="0" Grid.Row="0"
IsVisible="{Binding IsRunning}"/> IsVisible="{Binding IsRunning}"/>

View file

@ -53,7 +53,7 @@
</StackLayout> </StackLayout>
<!--While process is running--> <!--While process is running-->
<sharedGui:RunningProcessView <sharedGui:RunningProcessViewBay
Grid.Row="0" Grid.Row="0"
IsVisible="{Binding IsRunning}"/> IsVisible="{Binding IsRunning}"/>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -85,21 +85,21 @@ namespace TINK.Droid
} }
}; };
await Permissions.RequestAsync<BLEAndLocationPermissions>();
LoadApplication(new App()); LoadApplication(new App());
await Permissions.RequestAsync<BLEPermissions>();
await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
} }
//Bluetooth Permission on Android 12 "Detect Devices nearby" //Bluetooth Permission on Android 12 "Detect Devices nearby"
// https://stackoverflow.com/questions/71028853/xamarin-forms-ble-plugin-scan-issue-android-12 // https://stackoverflow.com/questions/71028853/xamarin-forms-ble-plugin-scan-issue-android-12
public class BLEAndLocationPermissions : BasePlatformPermission public class BLEPermissions : BasePlatformPermission
{ {
public override (string androidPermission, bool isRuntime)[] RequiredPermissions => new List<(string androidPermission, bool isRuntime)> public override (string androidPermission, bool isRuntime)[] RequiredPermissions => new List<(string androidPermission, bool isRuntime)>
{ {
(Android.Manifest.Permission.BluetoothScan, true), (Android.Manifest.Permission.BluetoothScan, true),
(Android.Manifest.Permission.BluetoothConnect, true), (Android.Manifest.Permission.BluetoothConnect, true),
(Android.Manifest.Permission.AccessFineLocation, true) //(Android.Manifest.Permission.AccessFineLocation, true)
}.ToArray(); }.ToArray();
} }

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.Meinkonrad" android:versionName="3.0.352" android:versionCode="352"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.Meinkonrad" android:versionName="3.0.353" android:versionCode="353">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" /> <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" />
<!-- Google Maps related permissions --> <!-- Google Maps related permissions -->
<!-- Permission to receive remote notifications from Google Play Services --> <!-- Permission to receive remote notifications from Google Play Services -->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -55,8 +55,8 @@
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>Mein konrad</string> <string>Mein konrad</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>352</string> <string>353</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.352</string> <string>3.0.353</string>
</dict> </dict>
</plist> </plist>

View file

@ -41,7 +41,7 @@ endobj
6 0 obj 6 0 obj
<< /Producer (cairo 1.17.4 (https://cairographics.org)) << /Producer (cairo 1.17.4 (https://cairographics.org))
/Creator <FEFF0049006E006B0073006300610070006500200031002E0031002E00320020002800680074007400700073003A002F002F0069006E006B00730063006100700065002E006F007200670029> /Creator <FEFF0049006E006B0073006300610070006500200031002E0031002E00320020002800680074007400700073003A002F002F0069006E006B00730063006100700065002E006F007200670029>
/CreationDate (D:20221124081702+01'00) /CreationDate (D:20221206105042+01'00)
>> >>
endobj endobj
7 0 obj 7 0 obj

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
@ -320,7 +320,7 @@ namespace TINK
if (_PermissionsService != null) if (_PermissionsService != null)
return _PermissionsService; return _PermissionsService;
_PermissionsService = new TINK.Services.Permissions.Essentials.Permissions(); _PermissionsService = new TINK.Services.Permissions.Essentials.LocationPermissions();
return _PermissionsService; return _PermissionsService;
} }
} }

View file

@ -7,7 +7,7 @@
xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View" xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
Shell.FlyoutBehavior="Disabled" Shell.FlyoutBehavior="Disabled"
Shell.NavBarIsVisible="{Binding IsIdle}"> Shell.NavBarIsVisible="{Binding IsIdle}">
<Shell.TitleView> <Shell.TitleView>
<Grid ColumnDefinitions="Auto, 1*"> <Grid ColumnDefinitions="Auto, 1*">
<Image Style="{StaticResource Image-Navbar}"/> <Image Style="{StaticResource Image-Navbar}"/>
@ -15,7 +15,7 @@
Text="{Binding Title}"/> Text="{Binding Title}"/>
</Grid> </Grid>
</Shell.TitleView> </Shell.TitleView>
<ContentPage.Resources> <ContentPage.Resources>
<ResourceDictionary> <ResourceDictionary>
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/> <local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
@ -24,36 +24,37 @@
<ContentPage.Content> <ContentPage.Content>
<Frame> <!--Grid for Bike(s) view and Running process in same row-->
<Grid>
<!--Grid for Bike(s) view and Running process in same row--> <Frame
<Grid> Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!--Bike(s) view--> <!-- Grid for Content -->
<StackLayout Grid.Row="0" <Grid
Orientation="Vertical"> RowDefinitions="Auto,1*,Auto,Auto">
<!--Title--> <!--Station-->
<Label <StackLayout
HorizontalOptions="Center" Grid.Row="0"
FontAttributes="Bold" Orientation="Vertical">
TextColor="{DynamicResource primary-back-title-color}"
Text="{Binding StationDetailText}"/>
<!--Line--> <!--Title-->
<BoxView <Label
HeightRequest="1" HorizontalOptions="Center"
Color="{DynamicResource primary-back-title-color}"/> FontAttributes="Bold"
</StackLayout> TextColor="{DynamicResource primary-back-title-color}"
Text="{Binding StationDetailText}"/>
<!--Bike(s)--> <!--Line-->
<ListView <BoxView
Grid.Row="1" HeightRequest="1"
Color="{DynamicResource primary-back-title-color}"/>
</StackLayout>
<!--Bike(s)-->
<ListView Grid.Row="1"
x:Name="BikesAtStationListView" x:Name="BikesAtStationListView"
SelectionMode="None" SelectionMode="None"
SelectedItem="{Binding SelectedBike}" SelectedItem="{Binding SelectedBike}"
@ -62,48 +63,62 @@
HasUnevenRows="True" HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"/> ItemTemplate="{StaticResource bikeTemplateSelector}"/>
<!--No Bikes--> <!--No Bikes-->
<Label <Label Grid.Row="1"
Grid.Row="1"
IsVisible="{Binding IsNoBikesAtStationVisible}" IsVisible="{Binding IsNoBikesAtStationVisible}"
Text="{Binding NoBikesAtStationText}"/> Text="{Binding NoBikesAtStationText}"/>
<!-- Contact and Login at end of page--> <!--Info text-->
<StackLayout <Label
Orientation="Vertical" Grid.Row="2"
Grid.Row="2"> Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
<!--Line--> <!-- Contact and Login at end of page-->
<BoxView HeightRequest="1" Color="{DynamicResource primary-back-title-color}"/> <StackLayout
Grid.Row="3"
Orientation="Vertical">
<!--Contact to operator--> <!--Line-->
<Label <BoxView
HeightRequest="1"
Color="{DynamicResource primary-back-title-color}"/>
<!--Contact to operator-->
<Label
TextType="Html" TextType="Html"
Text="{Binding ContactSupportHintText}"> Text="{Binding ContactSupportHintText}">
<Label.GestureRecognizers> <Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ContactSupportClickedCommand}"/> <TapGestureRecognizer Command="{Binding ContactSupportClickedCommand}"/>
</Label.GestureRecognizers> </Label.GestureRecognizers>
</Label> </Label>
<!--Login required--> <!--Login required-->
<Label <Label
IsVisible="{Binding IsLoginRequiredHintVisible}" IsVisible="{Binding IsLoginRequiredHintVisible}"
TextType="Html" TextType="Html"
Text="{Binding LoginRequiredHintText}"> Text="{Binding LoginRequiredHintText}">
<Label.GestureRecognizers> <Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding LoginRequiredHintClickedCommand}"/> <TapGestureRecognizer Command="{Binding LoginRequiredHintClickedCommand}"/>
</Label.GestureRecognizers> </Label.GestureRecognizers>
</Label> </Label>
</StackLayout>
<!--While process is running--> </StackLayout>
<sharedGui:RunningProcessView
</Grid>
</Frame>
<!--While process is running-->
<sharedGui:RunningProcessView
IsVisible="{Binding IsRunning}" IsVisible="{Binding IsRunning}"
Grid.Row="1"/> Grid.Row="0"/>
</Grid> </Grid>
</Frame>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -1,56 +1,137 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:maps="clr-namespace:Xamarin.Forms.GoogleMaps;assembly=Xamarin.Forms.GoogleMaps" 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:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
x:Class="TINK.View.Contact.SelectStationPage"> xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
<Shell.TitleView> x:Class="TINK.View.Contact.SelectStationPage"
<Grid ColumnDefinitions="Auto, 1*"> BackgroundColor="{DynamicResource Key=primary-back-title-color}">
<Image Style="{StaticResource Image-Navbar}"/>
<Label Style="{StaticResource Label-Navbar}" <Shell.TitleView>
<Grid ColumnDefinitions="Auto, 1*">
<Image Style="{StaticResource Image-Navbar}"/>
<Label Style="{StaticResource Label-Navbar}"
Text="{x:Static resources:AppResources.MarkingSelectStationPage}"/> Text="{x:Static resources:AppResources.MarkingSelectStationPage}"/>
</Grid> </Grid>
</Shell.TitleView> </Shell.TitleView>
<ContentPage.Content>
<StackLayout> <ContentPage.Content>
<Grid
IsEnabled="{Binding IsMapPageEnabled}" <!--Grid for Map with Buttons and Running process-->
VerticalOptions="FillAndExpand"> <Grid
<maps:Map WidthRequest="320" HeightRequest="800" RowDefinitions="3,46,1*,32"
x:Name="MyMap" ColumnDefinitions="1*,Auto,1*"
IsShowingUser="False" IsEnabled="{Binding IsMapPageEnabled}"
MapType="Street"> VerticalOptions="FillAndExpand">
<maps:Map.Behaviors>
<bindings:BindingPinsBehavior Value="{Binding Pins}"/> <!--Map-->
<bindings:PinClickedToCommandBehavior Command="{Binding PinClickedCommand}"/> <maps:Map
</maps:Map.Behaviors> Grid.RowSpan="3"
</maps:Map> Grid.ColumnSpan="3"
</Grid> WidthRequest="320"
<StackLayout HeightRequest="800"
Margin="6,3,6,6" x:Name="MyMap"
VerticalOptions="EndAndExpand" IsShowingUser="False"
Orientation="Horizontal"> MapType="Street">
<Label <maps:Map.Behaviors>
HeightRequest="24" <bindings:BindingPinsBehavior Value="{Binding Pins}"/>
Text="{Binding StatusInfoText}" <bindings:PinClickedToCommandBehavior Command="{Binding PinClickedCommand}"/>
FontSize="Small" </maps:Map.Behaviors>
VerticalOptions="Center" </maps:Map>
HorizontalOptions="FillAndExpand"/>
<ActivityIndicator IsRunning="{Binding IsRunning}" <!--Buttons for choosing bike type-->
IsVisible="{Binding IsRunning}" <Frame
HeightRequest="20" CornerRadius="13"
VerticalOptions="CenterAndExpand" Grid.Row="1"
HorizontalOptions="End"> Grid.Column="1"
<ActivityIndicator.WidthRequest> Margin="0"
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" /> Padding="0"
</ActivityIndicator.WidthRequest> BackgroundColor="{DynamicResource secondary-back-title-color}">
<ActivityIndicator.Color> <StackLayout
<OnPlatform x:TypeArguments="Color" Orientation="Horizontal"
Android="#D21113" iOS="#D21113" WinPhone="#D21113" /> Margin="0"
</ActivityIndicator.Color> Padding="0">
</ActivityIndicator> <Button
</StackLayout> x:Name="KonradButton"
</StackLayout> AutomationId ="FilterKonrad_button"
</ContentPage.Content> Text="{x:Static resources:AppResources.MarkingCityBike}"
</ContentPage> Command="{Binding OnToggleTinkToKonrad}"
IsVisible="false"
BackgroundColor="{Binding KonradColor}"
BorderColor="{Binding KonradColor}"
BorderWidth="0"
VerticalOptions="Center"
HorizontalOptions="Center"
WidthRequest="94"
HeightRequest="40"
BorderRadius="10"
Margin="3,0,0,0"
FontSize="Small"
FontAttributes="Bold"
TextColor="{Binding NoKonradColor}">
</Button>
<Button
x:Name="TINKButton"
AutomationId ="FilterTINK_button"
Text="{x:Static resources:AppResources.MarkingCargoBike}"
Command="{Binding OnToggleKonradToTink}"
IsVisible="false"
BackgroundColor="{Binding TinkColor}"
BorderColor="{Binding TinkColor}"
BorderWidth="0"
VerticalOptions="Center"
HorizontalOptions="Center"
WidthRequest="94"
HeightRequest="40"
BorderRadius="10"
Margin="0,0,3,0"
FontSize="Small"
FontAttributes="Bold"
TextColor="{Binding NoTinkColor}">
</Button>
</StackLayout>
</Frame>
<!--Center to currentLocation Button-->
<ImageButton
Grid.RowSpan="3"
Grid.ColumnSpan="3"
x:Name="CurrentLocation"
AutomationId ="currentLocaton_button"
Command="{Binding OnCurrentLocationButtonClicked}"
IsVisible="False"
BackgroundColor="Transparent"
BorderWidth="1"
BorderColor="LightGray"
VerticalOptions="End"
HorizontalOptions="Center"
Margin="0,0,0,12"
Source="Location_Button.png"
WidthRequest="40"
HeightRequest="40"
CornerRadius="20">
</ImageButton>
<!--Info text-->
<Label
Grid.Row="3"
Grid.ColumnSpan="3"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
TextColor="White"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
<!--While process is running-->
<sharedGui:RunningProcessView
IsVisible="{Binding IsRunning}"
Grid.RowSpan="4"
Grid.ColumnSpan="3"/>
</Grid>
</ContentPage.Content>
</ContentPage>

View file

@ -21,47 +21,61 @@
<ContentPage.Content> <ContentPage.Content>
<Frame> <!--Grid for Bike(s) view and Running process in same row-->
<Grid>
<!--Grid for Bike(s) view and Running process in same row--> <Frame
<Grid> Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--Search bike--> <Grid
<StackLayout Grid.Row="0"> RowDefinitions="1*,32">
<Entry
Placeholder="{x:Static resources:AppResources.PlaceholderFindBike}"
IsVisible="{Binding IsSelectBikeVisible}"
MaxLength="10"
CursorPosition="0"
Text="{Binding BikeIdUserInput}"/>
<Button <!--Search bike-->
Text="{x:Static resources:AppResources.MarkingFindBike}" <StackLayout Grid.Row="0">
IsEnabled="{Binding IsSelectBikeEnabled}" <Entry
IsVisible="{Binding IsSelectBikeVisible}" Placeholder="{x:Static resources:AppResources.PlaceholderFindBike}"
Command="{Binding OnSelectBikeRequest}"/> IsVisible="{Binding IsSelectBikeVisible}"
MaxLength="10"
CursorPosition="0"
Text="{Binding BikeIdUserInput}"/>
<ListView <Button
x:Name="FindBikeListView" Text="{x:Static resources:AppResources.MarkingFindBike}"
SelectionMode="None" IsEnabled="{Binding IsSelectBikeEnabled}"
SelectedItem="{Binding SelectedBike}" IsVisible="{Binding IsSelectBikeVisible}"
IsEnabled="{Binding IsIdle}" Command="{Binding OnSelectBikeRequest}"/>
IsVisible="{Binding IsBikesListVisible}"
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"/>
</StackLayout> <ListView
x:Name="FindBikeListView"
SelectionMode="None"
SelectedItem="{Binding SelectedBike}"
IsEnabled="{Binding IsIdle}"
IsVisible="{Binding IsBikesListVisible}"
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"/>
<!--While process is running--> </StackLayout>
<sharedGui:RunningProcessView
<!--Info text-->
<Label
Grid.Row="1"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
</Grid>
</Frame>
<!--While process is running-->
<sharedGui:RunningProcessView
Grid.Row="0" Grid.Row="0"
IsVisible="{Binding IsRunning}"/> IsVisible="{Binding IsRunning}"/>
</Grid> </Grid>
</Frame>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -5,9 +5,11 @@
xmlns:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings" xmlns:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
x:Class="TINK.View.Map.MapPage" x:Class="TINK.View.Map.MapPage"
xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
Shell.NavBarIsVisible="{Binding IsNavBarVisible}"
BackgroundColor="{DynamicResource Key=primary-back-title-color}"> BackgroundColor="{DynamicResource Key=primary-back-title-color}">
<Shell.TitleView> <Shell.TitleView >
<Grid ColumnDefinitions="Auto, 1*"> <Grid ColumnDefinitions="Auto, 1*">
<Image Style="{StaticResource Image-Navbar}"/> <Image Style="{StaticResource Image-Navbar}"/>
<Label Style="{StaticResource Label-Navbar}" <Label Style="{StaticResource Label-Navbar}"
@ -15,15 +17,17 @@
</Grid> </Grid>
</Shell.TitleView> </Shell.TitleView>
<!--Grid for Map with Buttons and Running process--> <ContentPage.Content>
<Grid
RowDefinitions="3,46,1*,Auto"
ColumnDefinitions="1*,Auto,1*"
IsEnabled="{Binding IsMapPageEnabled}"
VerticalOptions="FillAndExpand">
<!--Map--> <!--Grid for Map with Buttons and Running process-->
<maps:Map <Grid
RowDefinitions="3,46,1*,32"
ColumnDefinitions="1*,Auto,1*"
IsEnabled="{Binding IsMapPageEnabled}"
VerticalOptions="FillAndExpand">
<!--Map-->
<maps:Map
Grid.RowSpan="3" Grid.RowSpan="3"
Grid.ColumnSpan="3" Grid.ColumnSpan="3"
WidthRequest="320" WidthRequest="320"
@ -31,76 +35,75 @@
x:Name="MyMap" x:Name="MyMap"
IsShowingUser="False" IsShowingUser="False"
MapType="Street"> MapType="Street">
<maps:Map.Behaviors> <maps:Map.Behaviors>
<bindings:BindingPinsBehavior Value="{Binding Pins}"/> <bindings:BindingPinsBehavior Value="{Binding Pins}"/>
<bindings:PinClickedToCommandBehavior Command="{Binding PinClickedCommand}"/> <bindings:PinClickedToCommandBehavior Command="{Binding PinClickedCommand}"/>
</maps:Map.Behaviors> </maps:Map.Behaviors>
</maps:Map> </maps:Map>
<!--Buttons for choosing bike type--> <!--Buttons for choosing bike type-->
<Frame <Frame
CornerRadius="13" CornerRadius="13"
Grid.Row="1" Grid.Row="1"
Grid.Column="1" Grid.Column="1"
Margin="0" Margin="0"
Padding="0" Padding="0"
BackgroundColor="{DynamicResource secondary-back-title-color}"> IsVisible="{Binding IsNavBarVisible}"
<StackLayout BackgroundColor="{DynamicResource secondary-back-title-color}">
Orientation="Horizontal" <StackLayout
Margin="0" Orientation="Horizontal"
Padding="0"> Margin="0"
<Button Padding="0">
x:Name="KonradButton" <Button
AutomationId ="FilterKonrad_button" x:Name="KonradButton"
Text="{x:Static resources:AppResources.MarkingCityBike}" AutomationId ="FilterKonrad_button"
Command="{Binding OnToggleTinkToKonrad}" Text="{x:Static resources:AppResources.MarkingCityBike}"
IsVisible="{Binding IsToggleVisible}" Command="{Binding OnToggleTinkToKonrad}"
BackgroundColor="{Binding KonradColor}" IsVisible="{Binding IsToggleVisible}"
BorderColor="{Binding KonradColor}" BackgroundColor="{Binding KonradColor}"
BorderWidth="0" BorderColor="{Binding KonradColor}"
VerticalOptions="Center" BorderWidth="0"
HorizontalOptions="Center" VerticalOptions="Center"
WidthRequest="94" HorizontalOptions="Center"
HeightRequest="40" WidthRequest="94"
BorderRadius="10" HeightRequest="40"
Margin="3,0,0,0" BorderRadius="10"
FontSize="Small" Margin="3,0,0,0"
FontAttributes="Bold" FontSize="Small"
TextColor="{Binding NoKonradColor}"> FontAttributes="Bold"
</Button> TextColor="{Binding NoKonradColor}">
<Button </Button>
x:Name="TINKButton" <Button
AutomationId ="FilterTINK_button" x:Name="TINKButton"
Text="{x:Static resources:AppResources.MarkingCargoBike}" AutomationId ="FilterTINK_button"
Command="{Binding OnToggleKonradToTink}" Text="{x:Static resources:AppResources.MarkingCargoBike}"
IsVisible="{Binding IsToggleVisible}" Command="{Binding OnToggleKonradToTink}"
BackgroundColor="{Binding TinkColor}" IsVisible="{Binding IsToggleVisible}"
BorderColor="{Binding TinkColor}" BackgroundColor="{Binding TinkColor}"
BorderWidth="0" BorderColor="{Binding TinkColor}"
VerticalOptions="Center" BorderWidth="0"
HorizontalOptions="Center" VerticalOptions="Center"
WidthRequest="94" HorizontalOptions="Center"
HeightRequest="40" WidthRequest="94"
BorderRadius="10" HeightRequest="40"
Margin="0,0,3,0" BorderRadius="10"
FontSize="Small" Margin="0,0,3,0"
FontAttributes="Bold" FontSize="Small"
TextColor="{Binding NoTinkColor}"> FontAttributes="Bold"
</Button> TextColor="{Binding NoTinkColor}">
</StackLayout> </Button>
</Frame> </StackLayout>
</Frame>
<!--Center to currentLocation Button--> <!--Center to currentLocation Button-->
<ImageButton <ImageButton
Grid.Row="2" Grid.RowSpan="3"
Grid.ColumnSpan="3" Grid.ColumnSpan="3"
x:Name="CurrentLocation" x:Name="CurrentLocation"
AutomationId ="currentLocaton_button" AutomationId ="currentLocaton_button"
Command="{Binding OnCurrentLocationButtonClicked}" Command="{Binding OnCurrentLocationButtonClicked}"
IsVisible="True" IsVisible="True"
BackgroundColor="Transparent" BackgroundColor="GhostWhite"
BorderWidth="1"
BorderColor="LightGray"
VerticalOptions="End" VerticalOptions="End"
HorizontalOptions="Center" HorizontalOptions="Center"
Margin="0,0,0,12" Margin="0,0,0,12"
@ -108,29 +111,27 @@
WidthRequest="40" WidthRequest="40"
HeightRequest="40" HeightRequest="40"
CornerRadius="20"> CornerRadius="20">
</ImageButton> </ImageButton>
<!--While process is running--> <!--Info text-->
<!--Spinner--> <Label
<ActivityIndicator Grid.Row="3"
Grid.RowSpan="4" Grid.ColumnSpan="3"
Grid.ColumnSpan="3" Text="{Binding StatusInfoText}"
IsRunning="{Binding IsRunning}" IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
IsVisible="{Binding IsRunning}" TextColor="White"
Scale="2" FontSize="Small"
VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"/>
Color="{x:DynamicResource primary-back-title-color}"/>
<!--Info text--> <!--While process is running-->
<Label <sharedGui:RunningProcessView
Grid.Row="3" IsVisible="{Binding IsRunning}"
Grid.ColumnSpan="3" Grid.RowSpan="4"
Text="{Binding StatusInfoText}" Grid.ColumnSpan="3"/>
TextColor="White"
FontSize="Small"
HorizontalOptions="Center"
Padding="0,0,0,10"/>
</Grid> </Grid>
</ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="TINK.View.MyBikes.MyBikesPage" x:Class="TINK.View.MyBikes.MyBikesPage"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
@ -9,6 +10,7 @@
<Shell.TitleView> <Shell.TitleView>
<Grid ColumnDefinitions="Auto, 1*"> <Grid ColumnDefinitions="Auto, 1*">
<Image Style="{StaticResource Image-Navbar}"/>
<Label Style="{StaticResource Label-Navbar}" <Label Style="{StaticResource Label-Navbar}"
Text="{x:Static resources:AppResources.MarkingMyBikes}"/> Text="{x:Static resources:AppResources.MarkingMyBikes}"/>
</Grid> </Grid>
@ -22,21 +24,19 @@
<ContentPage.Content> <ContentPage.Content>
<Frame> <!--Grid for Bike(s) view and Running process in same row-->
<Grid>
<!--Grid for Bike(s) view and Running process in same row--> <Frame
<Grid> Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--Bike(s) view--> <!--Bike(s) view-->
<StackLayout Grid.Row="0" <Grid
VerticalOptions="CenterAndExpand" RowDefinitions="1*,32">
Orientation="Vertical">
<!--Bike(s)--> <!--Bike(s)-->
<ListView <ListView
Grid.Row="0"
x:Name="MyBikesListView" x:Name="MyBikesListView"
SelectionMode="None" SelectionMode="None"
SelectedItem="{Binding SelectedBike}" SelectedItem="{Binding SelectedBike}"
@ -47,19 +47,30 @@
<!--No Bikes--> <!--No Bikes-->
<Label <Label
Grid.Row="0"
IsVisible="{Binding IsNoBikesOccupiedVisible}" IsVisible="{Binding IsNoBikesOccupiedVisible}"
Text="{Binding NoBikesOccupiedText}"/> Text="{Binding NoBikesOccupiedText}"/>
</StackLayout> <!--Info text-->
<Label
Grid.Row="1"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
<!--While process is running--> </Grid>
<sharedGui:RunningProcessView
</Frame>
<!--While process is running-->
<sharedGui:RunningProcessView
Grid.Row="0" Grid.Row="0"
IsVisible="{Binding IsRunning}"/> IsVisible="{Binding IsRunning}"/>
</Grid> </Grid>
</Frame>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -33,6 +33,9 @@
<DependentUpon>RunningProcessView.xaml</DependentUpon> <DependentUpon>RunningProcessView.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="$(MSBuildThisFileDirectory)View\RunningProcessViewBay.xaml.cs">
<DependentUpon>RunningProcessViewBay.xaml</DependentUpon>
</Compile>
<Compile Include="$(MSBuildThisFileDirectory)View\VersionNumberView.xaml.cs"> <Compile Include="$(MSBuildThisFileDirectory)View\VersionNumberView.xaml.cs">
<DependentUpon>VersionNumberView.xaml</DependentUpon> <DependentUpon>VersionNumberView.xaml</DependentUpon>
</Compile> </Compile>
@ -58,4 +61,10 @@
<Generator>MSBuild:UpdateDesignTimeXaml</Generator> <Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource> </EmbeddedResource>
</ItemGroup> </ItemGroup>
<ItemGroup>
<EmbeddedResource Include="$(MSBuildThisFileDirectory)View\RunningProcessViewBay.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
</ItemGroup>
</Project> </Project>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms" <ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View" xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
@ -10,12 +10,14 @@
Text="{x:Static resources:AppResources.MarkingDriveBatteryTitel}"/> Text="{x:Static resources:AppResources.MarkingDriveBatteryTitel}"/>
<sharedGui:BarLevelView <sharedGui:BarLevelView
x:Name="BarLevelElement" x:Name="BarLevelElement"
HorizontalOptions="CenterAndExpand"
Current="{Binding CurrentText, Mode=TwoWay}" Current="{Binding CurrentText, Mode=TwoWay}"
Maximum="{Binding MaximumText}"/> Maximum="{Binding MaximumText}"/>
<Stepper <Stepper
x:Name="BarLevelStepper" x:Name="BarLevelStepper"
HorizontalOptions="CenterAndExpand"
Value ="{Binding CurrentText, Mode=TwoWay}" Value ="{Binding CurrentText, Mode=TwoWay}"
Maximum="{Binding MaximumText}"/> Maximum="{Binding MaximumText}"/>
</StackLayout> </StackLayout>
</ContentView.Content> </ContentView.Content>
</ContentView> </ContentView>

View file

@ -10,11 +10,13 @@
WidthRequest="50" WidthRequest="50"
HeightRequest="30" HeightRequest="30"
Aspect="AspectFit" Aspect="AspectFit"
HorizontalOptions="CenterAndExpand"
IsVisible="{Binding IsBatteryChargeLevelImageVisible}" IsVisible="{Binding IsBatteryChargeLevelImageVisible}"
Source="{Binding BatteryChargeLevelImageSourceString}"/> Source="{Binding BatteryChargeLevelImageSourceString}"/>
<!-- Text describing filling level batteries with 1...4 and 6..N bars --> <!-- Text describing filling level batteries with 1...4 and 6..N bars -->
<Label <Label
x:Name="BarLevelLabel" x:Name="BarLevelLabel"
HorizontalOptions="CenterAndExpand"
Text="{Binding BatteryChargeLevelBarsText}" Text="{Binding BatteryChargeLevelBarsText}"
IsVisible="{Binding IsBatteryChargeLevelLabelVisible}"/> IsVisible="{Binding IsBatteryChargeLevelLabelVisible}"/>
</StackLayout> </StackLayout>

View file

@ -3,46 +3,59 @@
xmlns="http://xamarin.com/schemas/2014/forms" xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ShareeSharedGuiLib.View.RunningProcessView"> x:Class="ShareeSharedGuiLib.View.RunningProcessView">
<ContentView.Content>
<ContentView.Content>
<!--Grid for different Opacity values--> <!--Grid for different Opacity values-->
<Grid> <Grid>
<Grid.RowDefinitions> <Grid.RowDefinitions>
<RowDefinition Height="*"/> <RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions> </Grid.RowDefinitions>
<!--Background White, half transparent--> <!--Background White, half transparent-->
<Frame <Frame
Grid.Row="0" Grid.Row="0"
Grid.RowSpan="2" HorizontalOptions="FillAndExpand"
BackgroundColor="White" VerticalOptions="FillAndExpand"
Opacity=".75" BackgroundColor="Gray"
CornerRadius="10"/> Opacity=".80"
CornerRadius="0"/>
<!--Show spinner and info text--> <!--Show spinner and info text-->
<!--Spinner--> <!--Background White-->
<ActivityIndicator <Frame
Grid.Row="0" Grid.Row="0"
IsRunning="{Binding IsRunning}" WidthRequest="240"
IsVisible="{Binding IsRunning}"
Scale="2"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
Color="{x:DynamicResource primary-back-title-color}"/>
<!--Info text-->
<Label
Grid.Row="1"
TextType="Html"
Text="{Binding StatusInfoText}"
FontSize="Small"
HorizontalOptions="Center" HorizontalOptions="Center"
HorizontalTextAlignment="Center" VerticalOptions="Center"
Padding="0,0,0,10"/> BackgroundColor="White"
Padding="10"
CornerRadius="10">
<StackLayout Orientation="Vertical">
<!--Spinner-->
<ActivityIndicator
IsRunning="{Binding IsRunning}"
Scale="2"
VerticalOptions="Center"
HorizontalOptions="Center"
Margin="20"
Color="{x:DynamicResource primary-back-title-color}"/>
<!--Info text-->
<Label
TextType="Html"
Text="{Binding StatusInfoText}"
FontSize="Small"
WidthRequest="200"
HorizontalOptions="CenterAndExpand"
HorizontalTextAlignment="Center"
Padding="0"/>
</StackLayout>
</Frame>
</Grid> </Grid>
</ContentView.Content> </ContentView.Content>
</ContentView> </ContentView>

View file

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="ShareeSharedGuiLib.View.RunningProcessViewBay">
<ContentView.Content>
<!--Grid for different Opacity values-->
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!--Background White, half transparent-->
<Frame
Grid.Row="0"
Grid.RowSpan="2"
BackgroundColor="White"
Opacity=".75"
CornerRadius="10"/>
<!--Show spinner and info text-->
<!--Spinner-->
<ActivityIndicator
Grid.Row="0"
IsRunning="{Binding IsRunning}"
IsVisible="{Binding IsRunning}"
Scale="2"
VerticalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand"
Color="{x:DynamicResource primary-back-title-color}"/>
<!--Info text-->
<Label
Grid.Row="1"
TextType="Html"
Text="{Binding StatusInfoText}"
FontSize="Small"
HorizontalOptions="Center"
HorizontalTextAlignment="Center"
Padding="0,0,0,10"/>
</Grid>
</ContentView.Content>
</ContentView>

View 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 ShareeSharedGuiLib.View
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class RunningProcessViewBay : ContentView
{
public RunningProcessViewBay()
{
InitializeComponent();
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

View file

@ -85,21 +85,21 @@ namespace TINK.Droid
} }
}; };
await Permissions.RequestAsync<BLEAndLocationPermissions>();
LoadApplication(new App()); LoadApplication(new App());
await Permissions.RequestAsync<BLEPermissions>();
await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
} }
//Bluetooth Permission on Android 12 "Detect Devices nearby" //Bluetooth Permission on Android 12 "Detect Devices nearby"
// https://stackoverflow.com/questions/71028853/xamarin-forms-ble-plugin-scan-issue-android-12 // https://stackoverflow.com/questions/71028853/xamarin-forms-ble-plugin-scan-issue-android-12
public class BLEAndLocationPermissions : BasePlatformPermission public class BLEPermissions : BasePlatformPermission
{ {
public override (string androidPermission, bool isRuntime)[] RequiredPermissions => new List<(string androidPermission, bool isRuntime)> public override (string androidPermission, bool isRuntime)[] RequiredPermissions => new List<(string androidPermission, bool isRuntime)>
{ {
(Android.Manifest.Permission.BluetoothScan, true), (Android.Manifest.Permission.BluetoothScan, true),
(Android.Manifest.Permission.BluetoothConnect, true), (Android.Manifest.Permission.BluetoothConnect, true),
(Android.Manifest.Permission.AccessFineLocation, true) //(Android.Manifest.Permission.AccessFineLocation, true)
}.ToArray(); }.ToArray();
} }

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.hauffware.sharee" android:versionName="3.0.352" android:versionCode="352"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.hauffware.sharee" android:versionName="3.0.353" android:versionCode="353">
<uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" /> <uses-sdk android:minSdkVersion="19" android:targetSdkVersion="31" />
<!-- Google Maps related permissions --> <!-- Google Maps related permissions -->
<!-- Permission to receive remote notifications from Google Play Services --> <!-- Permission to receive remote notifications from Google Play Services -->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View file

@ -55,8 +55,8 @@
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>sharee.bike</string> <string>sharee.bike</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>352</string> <string>353</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.352</string> <string>3.0.353</string>
</dict> </dict>
</plist> </plist>

View file

@ -41,7 +41,7 @@ endobj
6 0 obj 6 0 obj
<< /Producer (cairo 1.17.4 (https://cairographics.org)) << /Producer (cairo 1.17.4 (https://cairographics.org))
/Creator <FEFF0049006E006B0073006300610070006500200031002E0031002E00320020002800680074007400700073003A002F002F0069006E006B00730063006100700065002E006F007200670029> /Creator <FEFF0049006E006B0073006300610070006500200031002E0031002E00320020002800680074007400700073003A002F002F0069006E006B00730063006100700065002E006F007200670029>
/CreationDate (D:20221124081702+01'00) /CreationDate (D:20221206105042+01'00)
>> >>
endobj endobj
7 0 obj 7 0 obj

View file

@ -327,7 +327,7 @@ namespace TINK
if (_PermissionsService != null) if (_PermissionsService != null)
return _PermissionsService; return _PermissionsService;
_PermissionsService = new Services.Permissions.Essentials.Permissions(); _PermissionsService = new Services.Permissions.Essentials.LocationPermissions();
return _PermissionsService; return _PermissionsService;
} }
} }

View file

@ -21,39 +21,40 @@
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/> <local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
</ResourceDictionary> </ResourceDictionary>
</ContentPage.Resources> </ContentPage.Resources>
<ContentPage.Content> <ContentPage.Content>
<Frame> <!--Grid for Bike(s) view and Running process in same row-->
<Grid>
<!--Grid for Bike(s) view and Running process in same row--> <Frame
<Grid> Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!--Bike(s) view--> <!-- Grid for Content -->
<StackLayout Grid.Row="0" <Grid
Orientation="Vertical"> RowDefinitions="Auto,1*,Auto,Auto">
<!--Title--> <!--Station-->
<Label <StackLayout
HorizontalOptions="Center" Grid.Row="0"
FontAttributes="Bold" Orientation="Vertical">
TextColor="{DynamicResource primary-back-title-color}"
Text="{Binding StationDetailText}"/>
<!--Line--> <!--Title-->
<BoxView <Label
HeightRequest="1" HorizontalOptions="Center"
Color="{DynamicResource primary-back-title-color}"/> FontAttributes="Bold"
</StackLayout> TextColor="{DynamicResource primary-back-title-color}"
Text="{Binding StationDetailText}"/>
<!--Bike(s)--> <!--Line-->
<ListView <BoxView
Grid.Row="1" HeightRequest="1"
Color="{DynamicResource primary-back-title-color}"/>
</StackLayout>
<!--Bike(s)-->
<ListView Grid.Row="1"
x:Name="BikesAtStationListView" x:Name="BikesAtStationListView"
SelectionMode="None" SelectionMode="None"
SelectedItem="{Binding SelectedBike}" SelectedItem="{Binding SelectedBike}"
@ -63,47 +64,61 @@
ItemTemplate="{StaticResource bikeTemplateSelector}"/> ItemTemplate="{StaticResource bikeTemplateSelector}"/>
<!--No Bikes--> <!--No Bikes-->
<Label <Label Grid.Row="1"
Grid.Row="1"
IsVisible="{Binding IsNoBikesAtStationVisible}" IsVisible="{Binding IsNoBikesAtStationVisible}"
Text="{Binding NoBikesAtStationText}"/> Text="{Binding NoBikesAtStationText}"/>
<!-- Contact and Login at end of page--> <!--Info text-->
<StackLayout <Label
Orientation="Vertical" Grid.Row="2"
Grid.Row="2"> Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
<!--Line--> <!-- Contact and Login at end of page-->
<BoxView HeightRequest="1" Color="{DynamicResource primary-back-title-color}"/> <StackLayout
Grid.Row="3"
Orientation="Vertical">
<!--Contact to operator--> <!--Line-->
<Label <BoxView
HeightRequest="1"
Color="{DynamicResource primary-back-title-color}"/>
<!--Contact to operator-->
<Label
TextType="Html" TextType="Html"
Text="{Binding ContactSupportHintText}"> Text="{Binding ContactSupportHintText}">
<Label.GestureRecognizers> <Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ContactSupportClickedCommand}"/> <TapGestureRecognizer Command="{Binding ContactSupportClickedCommand}"/>
</Label.GestureRecognizers> </Label.GestureRecognizers>
</Label> </Label>
<!--Login required--> <!--Login required-->
<Label <Label
IsVisible="{Binding IsLoginRequiredHintVisible}" IsVisible="{Binding IsLoginRequiredHintVisible}"
TextType="Html" TextType="Html"
Text="{Binding LoginRequiredHintText}"> Text="{Binding LoginRequiredHintText}">
<Label.GestureRecognizers> <Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding LoginRequiredHintClickedCommand}"/> <TapGestureRecognizer Command="{Binding LoginRequiredHintClickedCommand}"/>
</Label.GestureRecognizers> </Label.GestureRecognizers>
</Label> </Label>
</StackLayout>
<!--While process is running--> </StackLayout>
<sharedGui:RunningProcessView
</Grid>
</Frame>
<!--While process is running-->
<sharedGui:RunningProcessView
IsVisible="{Binding IsRunning}" IsVisible="{Binding IsRunning}"
Grid.Row="1"/> Grid.Row="0"/>
</Grid>
</Grid>
</Frame>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -1,55 +1,136 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:maps="clr-namespace:Xamarin.Forms.GoogleMaps;assembly=Xamarin.Forms.GoogleMaps" 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:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
x:Class="TINK.View.Contact.SelectStationPage"> xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
<Shell.TitleView> x:Class="TINK.View.Contact.SelectStationPage"
<Grid ColumnDefinitions="Auto, 1*"> BackgroundColor="{DynamicResource Key=primary-back-title-color}">
<Label Style="{StaticResource Label-Navbar}"
<Shell.TitleView>
<Grid ColumnDefinitions="Auto, 1*">
<Label Style="{StaticResource Label-Navbar}"
Text="{x:Static resources:AppResources.MarkingSelectStationPage}"/> Text="{x:Static resources:AppResources.MarkingSelectStationPage}"/>
</Grid> </Grid>
</Shell.TitleView> </Shell.TitleView>
<ContentPage.Content>
<StackLayout> <ContentPage.Content>
<Grid
IsEnabled="{Binding IsMapPageEnabled}" <!--Grid for Map with Buttons and Running process-->
VerticalOptions="FillAndExpand"> <Grid
<maps:Map WidthRequest="320" HeightRequest="800" RowDefinitions="3,46,1*,32"
x:Name="MyMap" ColumnDefinitions="1*,Auto,1*"
IsShowingUser="False" IsEnabled="{Binding IsMapPageEnabled}"
MapType="Street"> VerticalOptions="FillAndExpand">
<maps:Map.Behaviors>
<bindings:BindingPinsBehavior Value="{Binding Pins}"/> <!--Map-->
<bindings:PinClickedToCommandBehavior Command="{Binding PinClickedCommand}"/> <maps:Map
</maps:Map.Behaviors> Grid.RowSpan="3"
</maps:Map> Grid.ColumnSpan="3"
</Grid> WidthRequest="320"
<StackLayout HeightRequest="800"
Margin="6,3,6,6" x:Name="MyMap"
VerticalOptions="EndAndExpand" IsShowingUser="False"
Orientation="Horizontal"> MapType="Street">
<Label <maps:Map.Behaviors>
HeightRequest="24" <bindings:BindingPinsBehavior Value="{Binding Pins}"/>
Text="{Binding StatusInfoText}" <bindings:PinClickedToCommandBehavior Command="{Binding PinClickedCommand}"/>
FontSize="Small" </maps:Map.Behaviors>
VerticalOptions="Center" </maps:Map>
HorizontalOptions="FillAndExpand"/>
<ActivityIndicator IsRunning="{Binding IsRunning}" <!--Buttons for choosing bike type-->
IsVisible="{Binding IsRunning}" <Frame
HeightRequest="20" CornerRadius="13"
VerticalOptions="CenterAndExpand" Grid.Row="1"
HorizontalOptions="End"> Grid.Column="1"
<ActivityIndicator.WidthRequest> Margin="0"
<OnPlatform x:TypeArguments="x:Double" iOS="40" Android="40" WinPhone="40" /> Padding="0"
</ActivityIndicator.WidthRequest> BackgroundColor="{DynamicResource secondary-back-title-color}">
<ActivityIndicator.Color> <StackLayout
<OnPlatform x:TypeArguments="Color" Orientation="Horizontal"
Android="#009899" iOS="#009899" WinPhone="#009899" /> Margin="0"
</ActivityIndicator.Color> Padding="0">
</ActivityIndicator> <Button
</StackLayout> x:Name="KonradButton"
</StackLayout> AutomationId ="FilterKonrad_button"
</ContentPage.Content> Text="{x:Static resources:AppResources.MarkingCityBike}"
</ContentPage> Command="{Binding OnToggleTinkToKonrad}"
IsVisible="false"
BackgroundColor="{Binding KonradColor}"
BorderColor="{Binding KonradColor}"
BorderWidth="0"
VerticalOptions="Center"
HorizontalOptions="Center"
WidthRequest="94"
HeightRequest="40"
BorderRadius="10"
Margin="3,0,0,0"
FontSize="Small"
FontAttributes="Bold"
TextColor="{Binding NoKonradColor}">
</Button>
<Button
x:Name="TINKButton"
AutomationId ="FilterTINK_button"
Text="{x:Static resources:AppResources.MarkingCargoBike}"
Command="{Binding OnToggleKonradToTink}"
IsVisible="false"
BackgroundColor="{Binding TinkColor}"
BorderColor="{Binding TinkColor}"
BorderWidth="0"
VerticalOptions="Center"
HorizontalOptions="Center"
WidthRequest="94"
HeightRequest="40"
BorderRadius="10"
Margin="0,0,3,0"
FontSize="Small"
FontAttributes="Bold"
TextColor="{Binding NoTinkColor}">
</Button>
</StackLayout>
</Frame>
<!--Center to currentLocation Button-->
<ImageButton
Grid.RowSpan="3"
Grid.ColumnSpan="3"
x:Name="CurrentLocation"
AutomationId ="currentLocaton_button"
Command="{Binding OnCurrentLocationButtonClicked}"
IsVisible="False"
BackgroundColor="Transparent"
BorderWidth="1"
BorderColor="LightGray"
VerticalOptions="End"
HorizontalOptions="Center"
Margin="0,0,0,12"
Source="Location_Button.png"
WidthRequest="40"
HeightRequest="40"
CornerRadius="20">
</ImageButton>
<!--Info text-->
<Label
Grid.Row="3"
Grid.ColumnSpan="3"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
TextColor="White"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
<!--While process is running-->
<sharedGui:RunningProcessView
IsVisible="{Binding IsRunning}"
Grid.RowSpan="4"
Grid.ColumnSpan="3"/>
</Grid>
</ContentPage.Content>
</ContentPage>

View file

@ -19,42 +19,56 @@
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/> <local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
</ResourceDictionary> </ResourceDictionary>
</ContentPage.Resources> </ContentPage.Resources>
<ContentPage.Content> <ContentPage.Content>
<Frame> <!--Grid for Bike(s) view and Running process in same row-->
<!--Grid for Bike(s) view and Running process in same row-->
<Grid> <Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--Search bike--> <Frame
<StackLayout Grid.Row="0"> Grid.Row="0">
<Entry
Placeholder="{x:Static resources:AppResources.PlaceholderFindBike}"
IsVisible="{Binding IsSelectBikeVisible}"
MaxLength="10"
CursorPosition="0"
Text="{Binding BikeIdUserInput}"/>
<Button <Grid
Text="{x:Static resources:AppResources.MarkingFindBike}" RowDefinitions="1*,32">
IsEnabled="{Binding IsSelectBikeEnabled}"
IsVisible="{Binding IsSelectBikeVisible}"
Command="{Binding OnSelectBikeRequest}"/>
<ListView <!--Search bike-->
x:Name="FindBikeListView" <StackLayout Grid.Row="0">
SelectionMode="None" <Entry
SelectedItem="{Binding SelectedBike}" Placeholder="{x:Static resources:AppResources.PlaceholderFindBike}"
IsEnabled="{Binding IsIdle}" IsVisible="{Binding IsSelectBikeVisible}"
IsVisible="{Binding IsBikesListVisible}" MaxLength="10"
HasUnevenRows="True" CursorPosition="0"
ItemTemplate="{StaticResource bikeTemplateSelector}"/> Text="{Binding BikeIdUserInput}"/>
</StackLayout> <Button
Text="{x:Static resources:AppResources.MarkingFindBike}"
IsEnabled="{Binding IsSelectBikeEnabled}"
IsVisible="{Binding IsSelectBikeVisible}"
Command="{Binding OnSelectBikeRequest}"/>
<ListView
x:Name="FindBikeListView"
SelectionMode="None"
SelectedItem="{Binding SelectedBike}"
IsEnabled="{Binding IsIdle}"
IsVisible="{Binding IsBikesListVisible}"
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"/>
</StackLayout>
<!--Info text-->
<Label
Grid.Row="1"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
</Grid>
</Frame>
<!--While process is running--> <!--While process is running-->
<sharedGui:RunningProcessView <sharedGui:RunningProcessView
@ -63,6 +77,6 @@
</Grid> </Grid>
</Frame>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -5,6 +5,8 @@
xmlns:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings" xmlns:bindings="clr-namespace:Xamarin.Forms.GoogleMaps.Bindings;assembly=Xamarin.Forms.GoogleMaps.Bindings"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
x:Class="TINK.View.Map.MapPage" x:Class="TINK.View.Map.MapPage"
xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
Shell.NavBarIsVisible="{Binding IsNavBarVisible}"
BackgroundColor="{DynamicResource Key=primary-back-title-color}"> BackgroundColor="{DynamicResource Key=primary-back-title-color}">
<Shell.TitleView > <Shell.TitleView >
@ -14,15 +16,17 @@
</Grid> </Grid>
</Shell.TitleView> </Shell.TitleView>
<!--Grid for Map with Buttons and Running process--> <ContentPage.Content>
<Grid
RowDefinitions="3,46,1*,Auto"
ColumnDefinitions="1*,Auto,1*"
IsEnabled="{Binding IsMapPageEnabled}"
VerticalOptions="FillAndExpand">
<!--Map--> <!--Grid for Map with Buttons and Running process-->
<maps:Map <Grid
RowDefinitions="3,46,1*,32"
ColumnDefinitions="1*,Auto,1*"
IsEnabled="{Binding IsMapPageEnabled}"
VerticalOptions="FillAndExpand">
<!--Map-->
<maps:Map
Grid.RowSpan="3" Grid.RowSpan="3"
Grid.ColumnSpan="3" Grid.ColumnSpan="3"
WidthRequest="320" WidthRequest="320"
@ -30,76 +34,75 @@
x:Name="MyMap" x:Name="MyMap"
IsShowingUser="False" IsShowingUser="False"
MapType="Street"> MapType="Street">
<maps:Map.Behaviors> <maps:Map.Behaviors>
<bindings:BindingPinsBehavior Value="{Binding Pins}"/> <bindings:BindingPinsBehavior Value="{Binding Pins}"/>
<bindings:PinClickedToCommandBehavior Command="{Binding PinClickedCommand}"/> <bindings:PinClickedToCommandBehavior Command="{Binding PinClickedCommand}"/>
</maps:Map.Behaviors> </maps:Map.Behaviors>
</maps:Map> </maps:Map>
<!--Buttons for choosing bike type-->
<Frame
CornerRadius="13"
Grid.Row="1"
Grid.Column="1"
Margin="0"
Padding="0"
BackgroundColor="{DynamicResource secondary-back-title-color}">
<StackLayout
Orientation="Horizontal"
Margin="0"
Padding="0">
<Button
x:Name="KonradButton"
AutomationId ="FilterKonrad_button"
Text="{x:Static resources:AppResources.MarkingCityBike}"
Command="{Binding OnToggleTinkToKonrad}"
IsVisible="{Binding IsToggleVisible}"
BackgroundColor="{Binding KonradColor}"
BorderColor="{Binding KonradColor}"
BorderWidth="0"
VerticalOptions="Center"
HorizontalOptions="Center"
WidthRequest="94"
HeightRequest="40"
BorderRadius="10"
Margin="3,0,0,0"
FontSize="Small"
FontAttributes="Bold"
TextColor="{Binding NoKonradColor}">
</Button>
<Button
x:Name="TINKButton"
AutomationId ="FilterTINK_button"
Text="{x:Static resources:AppResources.MarkingCargoBike}"
Command="{Binding OnToggleKonradToTink}"
IsVisible="{Binding IsToggleVisible}"
BackgroundColor="{Binding TinkColor}"
BorderColor="{Binding TinkColor}"
BorderWidth="0"
VerticalOptions="Center"
HorizontalOptions="Center"
WidthRequest="94"
HeightRequest="40"
BorderRadius="10"
Margin="0,0,3,0"
FontSize="Small"
FontAttributes="Bold"
TextColor="{Binding NoTinkColor}">
</Button>
</StackLayout>
</Frame>
<!--Center to currentLocation Button--> <!--Buttons for choosing bike type-->
<ImageButton <Frame
Grid.Row="2" CornerRadius="13"
Grid.Row="1"
Grid.Column="1"
Margin="0"
Padding="0"
IsVisible="{Binding IsNavBarVisible}"
BackgroundColor="{DynamicResource secondary-back-title-color}">
<StackLayout
Orientation="Horizontal"
Margin="0"
Padding="0">
<Button
x:Name="KonradButton"
AutomationId ="FilterKonrad_button"
Text="{x:Static resources:AppResources.MarkingCityBike}"
Command="{Binding OnToggleTinkToKonrad}"
IsVisible="{Binding IsToggleVisible}"
BackgroundColor="{Binding KonradColor}"
BorderColor="{Binding KonradColor}"
BorderWidth="0"
VerticalOptions="Center"
HorizontalOptions="Center"
WidthRequest="94"
HeightRequest="40"
BorderRadius="10"
Margin="3,0,0,0"
FontSize="Small"
FontAttributes="Bold"
TextColor="{Binding NoKonradColor}">
</Button>
<Button
x:Name="TINKButton"
AutomationId ="FilterTINK_button"
Text="{x:Static resources:AppResources.MarkingCargoBike}"
Command="{Binding OnToggleKonradToTink}"
IsVisible="{Binding IsToggleVisible}"
BackgroundColor="{Binding TinkColor}"
BorderColor="{Binding TinkColor}"
BorderWidth="0"
VerticalOptions="Center"
HorizontalOptions="Center"
WidthRequest="94"
HeightRequest="40"
BorderRadius="10"
Margin="0,0,3,0"
FontSize="Small"
FontAttributes="Bold"
TextColor="{Binding NoTinkColor}">
</Button>
</StackLayout>
</Frame>
<!--Center to currentLocation Button-->
<ImageButton
Grid.RowSpan="3"
Grid.ColumnSpan="3" Grid.ColumnSpan="3"
x:Name="CurrentLocation" x:Name="CurrentLocation"
AutomationId ="currentLocaton_button" AutomationId ="currentLocaton_button"
Command="{Binding OnCurrentLocationButtonClicked}" Command="{Binding OnCurrentLocationButtonClicked}"
IsVisible="True" IsVisible="True"
BackgroundColor="Transparent" BackgroundColor="GhostWhite"
BorderWidth="1"
BorderColor="LightGray"
VerticalOptions="End" VerticalOptions="End"
HorizontalOptions="Center" HorizontalOptions="Center"
Margin="0,0,0,12" Margin="0,0,0,12"
@ -107,30 +110,27 @@
WidthRequest="40" WidthRequest="40"
HeightRequest="40" HeightRequest="40"
CornerRadius="20"> CornerRadius="20">
</ImageButton> </ImageButton>
<!--While process is running--> <!--Info text-->
<!--Spinner--> <Label
<ActivityIndicator Grid.Row="3"
Grid.RowSpan="4" Grid.ColumnSpan="3"
Grid.ColumnSpan="3" Text="{Binding StatusInfoText}"
IsRunning="{Binding IsRunning}" IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
IsVisible="{Binding IsRunning}" TextColor="White"
Scale="2" FontSize="Small"
VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand"
HorizontalOptions="CenterAndExpand" VerticalOptions="CenterAndExpand"/>
Color="{x:DynamicResource primary-back-title-color}"/>
<!--Info text--> <!--While process is running-->
<Label <sharedGui:RunningProcessView
Grid.Row="3" IsVisible="{Binding IsRunning}"
Grid.ColumnSpan="3" Grid.RowSpan="4"
Text="{Binding StatusInfoText}" Grid.ColumnSpan="3"/>
TextColor="White"
FontSize="Small" </Grid>
HorizontalOptions="Center"
Padding="0,0,0,10"/> </ContentPage.Content>
</Grid>
</ContentPage> </ContentPage>

View file

@ -14,30 +14,28 @@
Text="{x:Static resources:AppResources.MarkingMyBikes}"/> Text="{x:Static resources:AppResources.MarkingMyBikes}"/>
</Grid> </Grid>
</Shell.TitleView> </Shell.TitleView>
<ContentPage.Resources> <ContentPage.Resources>
<ResourceDictionary> <ResourceDictionary>
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/> <local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
</ResourceDictionary> </ResourceDictionary>
</ContentPage.Resources> </ContentPage.Resources>
<ContentPage.Content> <ContentPage.Content>
<Frame> <!--Grid for Bike(s) view and Running process in same row-->
<Grid>
<!--Grid for Bike(s) view and Running process in same row--> <Frame
<Grid> Grid.Row="0">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!--Bike(s) view--> <!--Bike(s) view-->
<StackLayout Grid.Row="0" <Grid
VerticalOptions="CenterAndExpand" RowDefinitions="1*,32">
Orientation="Vertical">
<!--Bike(s)--> <!--Bike(s)-->
<ListView <ListView
Grid.Row="0"
x:Name="MyBikesListView" x:Name="MyBikesListView"
SelectionMode="None" SelectionMode="None"
SelectedItem="{Binding SelectedBike}" SelectedItem="{Binding SelectedBike}"
@ -48,19 +46,30 @@
<!--No Bikes--> <!--No Bikes-->
<Label <Label
Grid.Row="0"
IsVisible="{Binding IsNoBikesOccupiedVisible}" IsVisible="{Binding IsNoBikesOccupiedVisible}"
Text="{Binding NoBikesOccupiedText}"/> Text="{Binding NoBikesOccupiedText}"/>
</StackLayout>
<!--While process is running--> <!--Info text-->
<sharedGui:RunningProcessView <Label
Grid.Row="1"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsRunning, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
</Grid>
</Frame>
<!--While process is running-->
<sharedGui:RunningProcessView
Grid.Row="0" Grid.Row="0"
IsVisible="{Binding IsRunning}"/> IsVisible="{Binding IsRunning}"/>
</Grid> </Grid>
</Frame>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -652,6 +652,11 @@ namespace TINK.Model
AppResources.ChangeLog_MinorDesignImprovements, AppResources.ChangeLog_MinorDesignImprovements,
new List<AppFlavor> { AppFlavor.MeinKonrad, AppFlavor.ShareeBike } new List<AppFlavor> { AppFlavor.MeinKonrad, AppFlavor.ShareeBike }
}, },
{
new Version(3, 0, 353),
AppResources.ChangeLog_3_0_353_MK_SB,
new List<AppFlavor> { AppFlavor.MeinKonrad, AppFlavor.ShareeBike }
},
}; };
/// <summary> Manges the whats new information.</summary> /// <summary> Manges the whats new information.</summary>

View file

@ -259,7 +259,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to &lt;h4&gt;&lt;b&gt;Lock is closing.&lt;br/&gt;Please visually check if it is completely closed.&lt;/b&gt;&lt;/h4&gt;. /// Looks up a localized string similar to &lt;h4&gt;&lt;b&gt;Lock is closing.&lt;br/&gt;Please wait until it is completely closed.&lt;/b&gt;&lt;/h4&gt;.
/// </summary> /// </summary>
public static string ActivityTextClosingLock { public static string ActivityTextClosingLock {
get { get {
@ -349,7 +349,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to No location info available.. /// Looks up a localized string similar to No location info available. Activate your device&apos;s location services..
/// </summary> /// </summary>
public static string ActivityTextErrorQueryLocationWhenAny { public static string ActivityTextErrorQueryLocationWhenAny {
get { get {
@ -628,7 +628,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Updateing..... /// Looks up a localized string similar to Updating.....
/// </summary> /// </summary>
public static string ActivityTextUpdating { public static string ActivityTextUpdating {
get { get {
@ -725,6 +725,19 @@ namespace TINK.MultilingualResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Improvements in
///&lt;ul&gt;
///&lt;li/&gt;- Management of location services
///&lt;li/&gt;- Design of processes
///&lt;/ul&gt;.
/// </summary>
public static string ChangeLog_3_0_353_MK_SB {
get {
return ResourceManager.GetString("ChangeLog_3_0_353_MK_SB", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to We have fixed some bugs. Enjoy the ride!. /// Looks up a localized string similar to We have fixed some bugs. Enjoy the ride!.
/// </summary> /// </summary>
@ -2524,6 +2537,15 @@ namespace TINK.MultilingualResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Turn on your device&apos;s location services to center the map on your current location..
/// </summary>
public static string MessageErrorLocationIsOff {
get {
return ResourceManager.GetString("MessageErrorLocationIsOff", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Attention: Lock is closed! /// Looks up a localized string similar to Attention: Lock is closed!
///{0} ///{0}

View file

@ -334,7 +334,7 @@ Freigabedialog öffen?</value>
<value>Einen Moment bitte...</value> <value>Einen Moment bitte...</value>
</data> </data>
<data name="ActivityTextOpeningLock" xml:space="preserve"> <data name="ActivityTextOpeningLock" xml:space="preserve">
<value>&lt;h4&gt;&lt;b&gt;Schloss öffnet.&lt;br/&gt;Bitte warten Sie, bis es komplett geöffnet ist.&lt;/b&gt;&lt;/h4&gt;</value> <value>&lt;h4&gt;&lt;b&gt;Schloss öffnet.&lt;br/&gt;Bitte warten Sie bis es komplett geöffnet ist.&lt;/b&gt;&lt;/h4&gt;</value>
</data> </data>
<data name="ActivityTextStartingUpdater" xml:space="preserve"> <data name="ActivityTextStartingUpdater" xml:space="preserve">
<value>Starte Aktualisierung...</value> <value>Starte Aktualisierung...</value>
@ -355,7 +355,7 @@ Freigabedialog öffen?</value>
<value>Kein Netz beim Aktualisieren des Schlossstatusses.</value> <value>Kein Netz beim Aktualisieren des Schlossstatusses.</value>
</data> </data>
<data name="ActivityTextClosingLock" xml:space="preserve"> <data name="ActivityTextClosingLock" xml:space="preserve">
<value>&lt;h4&gt;&lt;b&gt;Schloss schließt.&lt;br/&gt;Bitte überprüfen Sie visuell, ob es komplett geschlossen ist.&lt;/b&gt;&lt;/h4&gt;</value> <value>&lt;h4&gt;&lt;b&gt;Schloss schließt.&lt;br/&gt;Bitte warten Sie bis es komplett geschlossen ist.&lt;/b&gt;&lt;/h4&gt;</value>
</data> </data>
<data name="ChangeLog3_0_203" xml:space="preserve"> <data name="ChangeLog3_0_203" xml:space="preserve">
<value>Aktualisierrt auf aktuelle Schloss-Firmware.</value> <value>Aktualisierrt auf aktuelle Schloss-Firmware.</value>
@ -666,7 +666,7 @@ Kleinere Verbesserungen.</value>
<value>Fehler beim Start der Standortabfrage!</value> <value>Fehler beim Start der Standortabfrage!</value>
</data> </data>
<data name="ActivityTextErrorQueryLocationWhenAny" xml:space="preserve"> <data name="ActivityTextErrorQueryLocationWhenAny" xml:space="preserve">
<value>Keine Standortinfo verfügbar.</value> <value>Keine Standortinfo verfügbar. Aktivieren Sie die Standortdienste Ihres Geräts.</value>
</data> </data>
<data name="ActivityTextErrorQueryLocationQuery" xml:space="preserve"> <data name="ActivityTextErrorQueryLocationQuery" xml:space="preserve">
<value>Standortabfrage nicht möglich.</value> <value>Standortabfrage nicht möglich.</value>
@ -1098,4 +1098,14 @@ Beim Login können Sie nun Ihr eingegebenes Passwort einsehen.&lt;br/&gt;
&lt;br/&gt; &lt;br/&gt;
Probieren Sie es aus!</value> Probieren Sie es aus!</value>
</data> </data>
<data name="MessageErrorLocationIsOff" xml:space="preserve">
<value>Schalten Sie die Standortdienste Ihres Geräts ein, um die Karte auf Ihren aktuellen Standort zu zentrieren.</value>
</data>
<data name="ChangeLog_3_0_353_MK_SB" xml:space="preserve">
<value>Verbesserungen im
&lt;ul&gt;
&lt;li/&gt;- Management der Standortdienste
&lt;li/&gt;- Design von Prozessen
&lt;/ul&gt;</value>
</data>
</root> </root>

View file

@ -460,7 +460,7 @@ Open sharing dialog?</value>
<value>No web error on updating locking status.</value> <value>No web error on updating locking status.</value>
</data> </data>
<data name="ActivityTextClosingLock" xml:space="preserve"> <data name="ActivityTextClosingLock" xml:space="preserve">
<value>&lt;h4&gt;&lt;b&gt;Lock is closing.&lt;br/&gt;Please visually check if it is completely closed.&lt;/b&gt;&lt;/h4&gt;</value> <value>&lt;h4&gt;&lt;b&gt;Lock is closing.&lt;br/&gt;Please wait until it is completely closed.&lt;/b&gt;&lt;/h4&gt;</value>
</data> </data>
<data name="ChangeLog3_0_203" xml:space="preserve"> <data name="ChangeLog3_0_203" xml:space="preserve">
<value>Updated to latest lock firmware.</value> <value>Updated to latest lock firmware.</value>
@ -662,7 +662,7 @@ Please contact the support for help.</value>
<value>Submitting feedback failed!</value> <value>Submitting feedback failed!</value>
</data> </data>
<data name="ActivityTextUpdating" xml:space="preserve"> <data name="ActivityTextUpdating" xml:space="preserve">
<value>Updateing....</value> <value>Updating....</value>
</data> </data>
<data name="ChangeLog3_0_231" xml:space="preserve"> <data name="ChangeLog3_0_231" xml:space="preserve">
<value>Minor improvements.</value> <value>Minor improvements.</value>
@ -756,7 +756,7 @@ Minor fixes.</value>
<value>Can not query location info.</value> <value>Can not query location info.</value>
</data> </data>
<data name="ActivityTextErrorQueryLocationWhenAny" xml:space="preserve"> <data name="ActivityTextErrorQueryLocationWhenAny" xml:space="preserve">
<value>No location info available.</value> <value>No location info available. Activate your device's location services.</value>
</data> </data>
<data name="ActivityTextQueryLocation" xml:space="preserve"> <data name="ActivityTextQueryLocation" xml:space="preserve">
<value>Query location...</value> <value>Query location...</value>
@ -1188,4 +1188,14 @@ When logging in, you can now view the password you entered. &lt;br/&gt;
&lt;br/&gt; &lt;br/&gt;
Try it out!</value> Try it out!</value>
</data> </data>
<data name="MessageErrorLocationIsOff" xml:space="preserve">
<value>Turn on your device's location services to center the map on your current location.</value>
</data>
<data name="ChangeLog_3_0_353_MK_SB" xml:space="preserve">
<value>Improvements in
&lt;ul&gt;
&lt;li/&gt;- Management of location services
&lt;li/&gt;- Design of processes
&lt;/ul&gt;</value>
</data>
</root> </root>

View file

@ -442,7 +442,7 @@ Freigabedialog öffen?</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextOpeningLock" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextOpeningLock" translate="yes" xml:space="preserve">
<source><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Lock is opening.&lt;br/&gt;Please wait until it is completely open.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></source> <source><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Lock is opening.&lt;br/&gt;Please wait until it is completely open.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></source>
<target state="translated"><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Schloss öffnet.&lt;br/&gt;Bitte warten Sie, bis es komplett geöffnet ist.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></target> <target state="translated"><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Schloss öffnet.&lt;br/&gt;Bitte warten Sie bis es komplett geöffnet ist.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextStartingUpdater" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextStartingUpdater" translate="yes" xml:space="preserve">
<source>Updating...</source> <source>Updating...</source>
@ -469,8 +469,8 @@ Freigabedialog öffen?</target>
<target state="translated">Kein Netz beim Aktualisieren des Schlossstatusses.</target> <target state="translated">Kein Netz beim Aktualisieren des Schlossstatusses.</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextClosingLock" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextClosingLock" translate="yes" xml:space="preserve">
<source><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Lock is closing.&lt;br/&gt;Please visually check if it is completely closed.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></source> <source><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Lock is closing.&lt;br/&gt;Please wait until it is completely closed.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></source>
<target state="translated"><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Schloss schließt.&lt;br/&gt;Bitte überprüfen Sie visuell, ob es komplett geschlossen ist.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></target> <target state="translated"><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Schloss schließt.&lt;br/&gt;Bitte warten Sie bis es komplett geschlossen ist.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_203" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_203" translate="yes" xml:space="preserve">
<source>Updated to latest lock firmware.</source> <source>Updated to latest lock firmware.</source>
@ -744,7 +744,7 @@ Bitte kontaktieren sie den Support!</target>
<target state="translated">Übermittlung der Rückmeldung fehlgeschlagen!</target> <target state="translated">Übermittlung der Rückmeldung fehlgeschlagen!</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextUpdating" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextUpdating" translate="yes" xml:space="preserve">
<source>Updateing....</source> <source>Updating....</source>
<target state="translated">Aktualisiere....</target> <target state="translated">Aktualisiere....</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_231" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_231" translate="yes" xml:space="preserve">
@ -892,8 +892,8 @@ Kleinere Verbesserungen.</target>
<target state="translated">Fehler beim Start der Standortabfrage!</target> <target state="translated">Fehler beim Start der Standortabfrage!</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextErrorQueryLocationWhenAny" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextErrorQueryLocationWhenAny" translate="yes" xml:space="preserve">
<source>No location info available.</source> <source>No location info available. Activate your device's location services.</source>
<target state="translated">Keine Standortinfo verfügbar.</target> <target state="translated">Keine Standortinfo verfügbar. Aktivieren Sie die Standortdienste Ihres Geräts.</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextErrorQueryLocationQuery" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextErrorQueryLocationQuery" translate="yes" xml:space="preserve">
<source>Can not query location info.</source> <source>Can not query location info.</source>
@ -1500,6 +1500,22 @@ Beim Login können Sie nun Ihr eingegebenes Passwort einsehen.&lt;br/&gt;
&lt;br/&gt; &lt;br/&gt;
Probieren Sie es aus!</target> Probieren Sie es aus!</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageErrorLocationIsOff" translate="yes" xml:space="preserve">
<source>Turn on your device's location services to center the map on your current location.</source>
<target state="translated">Schalten Sie die Standortdienste Ihres Geräts ein, um die Karte auf Ihren aktuellen Standort zu zentrieren.</target>
</trans-unit>
<trans-unit id="ChangeLog_3_0_353_MK_SB" translate="yes" xml:space="preserve">
<source>Improvements in
<bpt id="1">&lt;ul&gt;</bpt>
&lt;li/&gt;- Management of location services
&lt;li/&gt;- Design of processes
<ept id="1">&lt;/ul&gt;</ept></source>
<target state="translated">Verbesserungen im
<bpt id="1">&lt;ul&gt;</bpt>
&lt;li/&gt;- Management der Standortdienste
&lt;li/&gt;- Design von Prozessen
<ept id="1">&lt;/ul&gt;</ept></target>
</trans-unit>
</group> </group>
</body> </body>
</file> </file>

View file

@ -0,0 +1,80 @@
using System.Threading.Tasks;
using Xamarin.Essentials;
namespace TINK.Services.Permissions.Essentials
{
using XamPermission = Xamarin.Essentials.Permissions;
using XamPermissionStatus = PermissionStatus;
public class LocationPermissions : ILocationPermission
{
/// <summary> Checks the permission status.</summary>
/// <returns>Current permission status.</returns>
public async Task<Status> CheckStatusAsync()
{
var status = await XamPermission.CheckStatusAsync<XamPermission.LocationWhenInUse>();
if (status == XamPermissionStatus.Granted)
{
return Status.Granted;
}
if (status == XamPermissionStatus.Denied
&& DeviceInfo.Platform == DevicePlatform.iOS)
{
// Prompt the user to turn on in settings
// On iOS once a permission has been denied it may not be requested again from the application
return Status.DeniedRequiresSettingsUI;
}
if (XamPermission.ShouldShowRationale<XamPermission.LocationWhenInUse>())
{
// Prompt the user with additional information as to why the permission is needed
return Status.Denied;
}
switch (status)
{
case XamPermissionStatus.Unknown:
case XamPermissionStatus.Denied: // Map Denied to unknown because "denied means user did not allow access to location".
return Status.Unknown;
default:
// Comprises:
// - XamPermissionStatus.Restricted:
// - XamPermissionStatus.Disabled
// Perission XamPermissionStatus.Granted is handled above.
return Status.DeniedRequiresSettingsUI;
}
}
/// <summary> Requests location permission.</summary>
/// <returns>Permission status after request.</returns>
public async Task<Status> RequestAsync()
{
switch (await XamPermission.RequestAsync<XamPermission.LocationWhenInUse>())
{
case XamPermissionStatus.Unknown:
return Status.Unknown;
case XamPermissionStatus.Denied:
return Status.Denied;
case XamPermissionStatus.Granted:
return Status.Granted;
default:
// Comprises:
// - XamPermissionStatus.Restricted:
// - XamPermissionStatus.Disabled
return Status.DeniedRequiresSettingsUI;
}
}
/// <summary> Opens app settings dialog.</summary>
public bool OpenAppSettings()
{
AppInfo.ShowSettingsUI();
return true;
}
}
}

View file

@ -0,0 +1,59 @@
using System.Threading.Tasks;
namespace TINK.Services.Permissions.Plugin
{
using global::Plugin.Permissions;
public class LocationPermissions : ILocationPermission
{
/// <summary> Checks the permission status.</summary>
public async Task<Status> CheckStatusAsync()
{
switch (await CrossPermissions.Current.CheckPermissionStatusAsync<LocationPermission>())
{
case global::Plugin.Permissions.Abstractions.PermissionStatus.Denied:
return Status.Denied;
case global::Plugin.Permissions.Abstractions.PermissionStatus.Granted:
return Status.Granted;
case global::Plugin.Permissions.Abstractions.PermissionStatus.Unknown:
return Status.Unknown;
default:
// Comprises
// - PermissionStatus.Disabled and
// - PermissionStatus.Restricted.
return Status.DeniedRequiresSettingsUI;
}
}
/// <summary> Requests location permission.</summary>
/// <returns>Permission status after request.</returns>
public async Task<Status> RequestAsync()
{
switch (await CrossPermissions.Current.RequestPermissionAsync<LocationPermission>())
{
case global::Plugin.Permissions.Abstractions.PermissionStatus.Denied:
return Status.Denied;
case global::Plugin.Permissions.Abstractions.PermissionStatus.Granted:
return Status.Granted;
case global::Plugin.Permissions.Abstractions.PermissionStatus.Unknown:
return Status.Unknown;
default:
// Comprises
// - PermissionStatus.Disabled and
// - PermissionStatus.Restricted.
return Status.DeniedRequiresSettingsUI;
}
}
/// <summary> Opens app settings dialog.</summary>
public bool OpenAppSettings()
=> CrossPermissions.Current.OpenAppSettings();
}
}

View file

@ -244,15 +244,12 @@ namespace TINK.ViewModel.BikesAtStation
// Check location permissions. // Check location permissions.
if (bikesAtStation.GetLockIt().Count > 0 if (bikesAtStation.GetLockIt().Count > 0
&& RuntimePlatform == Device.Android) && RuntimePlatform == Device.Android
)
{ {
var status = await PermissionsService.CheckStatusAsync(); var status = await PermissionsService.CheckStatusAsync();
if (status != Status.Granted) if (status != Status.Granted)
{ {
var permissionResult = await PermissionsService.RequestAsync();
if (permissionResult != Status.Granted)
{
var dialogResult = await ViewService.DisplayAlert( var dialogResult = await ViewService.DisplayAlert(
AppResources.MessageTitleHint, AppResources.MessageTitleHint,
AppResources.MessageBikesManagementLocationPermissionOpenDialog, AppResources.MessageBikesManagementLocationPermissionOpenDialog,
@ -270,10 +267,11 @@ namespace TINK.ViewModel.BikesAtStation
IsIdle = true; IsIdle = true;
return; return;
} }
else if (dialogResult)
// Open permissions dialog. {
PermissionsService.OpenAppSettings(); // Open permissions dialog.
} PermissionsService.OpenAppSettings();
}
} }
if (Geolocation.IsGeolcationEnabled == false) if (Geolocation.IsGeolcationEnabled == false)

View file

@ -191,28 +191,32 @@ namespace TINK.ViewModel.Contact
} }
//Add blue dot for showing current location of user //Add blue dot for showing current location of user
Location currentLocation = null; var status = await PermissionsService.CheckStatusAsync();
try if (status == Status.Granted)
{ {
currentLocation = await GeolocationService.GetAsync(); Location currentLocation = null;
} try
catch (Exception ex)
{
Log.ForContext<MapPageViewModel>().Error("Getting location failed. {Exception}", ex);
}
if (currentLocation != null)
{
var currentLocationPin = new Pin()
{ {
Position = new Xamarin.Forms.GoogleMaps.Position(currentLocation.Latitude, currentLocation.Longitude), currentLocation = await GeolocationService.GetAsync();
Label = "currentLocationPin", }
Type = PinType.Place, catch (Exception ex)
Tag = "NotClickable", {
Icon = BitmapDescriptorFactory.FromBundle(currentLocationPinName) Log.ForContext<MapPageViewModel>().Error("Getting location failed. {Exception}", ex);
}; }
Pins.Add(currentLocationPin); if (currentLocation != null)
{
var currentLocationPin = new Pin()
{
Position = new Xamarin.Forms.GoogleMaps.Position(currentLocation.Latitude, currentLocation.Longitude),
Label = "currentLocationPin",
Type = PinType.Place,
Tag = "NotClickable",
Icon = BitmapDescriptorFactory.FromBundle(currentLocationPinName)
};
Pins.Add(currentLocationPin);
}
} }
} }
@ -313,17 +317,15 @@ namespace TINK.ViewModel.Contact
if (Pins.Count <= 0) if (Pins.Count <= 0)
{ {
ActionText = AppResources.ActivityTextRequestingLocationPermissions; // Move and scale before getting stations and bikes which takes some time.
if (TinkApp.CenterMapToCurrentLocation)
// Check location permission
var status = await PermissionsService.CheckStatusAsync();
if (TinkApp.CenterMapToCurrentLocation
&& !GeolocationService.IsSimulation
&& status != Status.Granted)
{ {
var permissionResult = await PermissionsService.RequestAsync(); ActionText = AppResources.ActivityTextRequestingLocationPermissions;
if (permissionResult != Status.Granted) // Check location permission
var status = await PermissionsService.CheckStatusAsync();
if (!GeolocationService.IsSimulation
&& status != Status.Granted)
{ {
var dialogResult = await ViewService.DisplayAlert( var dialogResult = await ViewService.DisplayAlert(
AppResources.MessageTitleHint, AppResources.MessageTitleHint,
@ -341,23 +343,25 @@ namespace TINK.ViewModel.Contact
return; return;
} }
} }
} if (status == Status.Granted)
{
ActionText = AppResources.ActivityTextCenterMap;
// Move and scale before getting stations and bikes which takes some time. Location currentLocation = null;
ActionText = AppResources.ActivityTextCenterMap; try
Location currentLocation = null; {
try currentLocation = TinkApp.CenterMapToCurrentLocation
{ ? await GeolocationService.GetAsync()
currentLocation = TinkApp.CenterMapToCurrentLocation : null;
? await GeolocationService.GetAsync() }
: null; catch (Exception ex)
} {
catch (Exception ex) Log.ForContext<SelectStationPageViewModel>().Error("Getting location failed. {Exception}", ex);
{ }
Log.ForContext<SelectStationPageViewModel>().Error("Getting location failed. {Exception}", ex);
}
MoveAndScale(m_oMoveToRegionDelegate, TinkApp.Uris.ActiveUri, currentLocation); MoveAndScale(m_oMoveToRegionDelegate, TinkApp.Uris.ActiveUri, currentLocation);
}
}
} }
ActionText = AppResources.ActivityTextMapLoadingStationsAndBikes; ActionText = AppResources.ActivityTextMapLoadingStationsAndBikes;

View file

@ -235,36 +235,63 @@ namespace TINK.ViewModel.FindBike
ActionText = AppResources.ActivityTextCheckBluetoothState; ActionText = AppResources.ActivityTextCheckBluetoothState;
if (bikeCollection.FirstOrDefault(x => x is BikeInfo btBike) != null if (bikeCollection.FirstOrDefault(x => x is BikeInfo btBike) != null
&& RuntimePlatform == Device.Android) //&& RuntimePlatform == Device.Android
)
{ {
// Check location permission // Check location permission
var status = await PermissionsService.CheckStatusAsync(); var status = await PermissionsService.CheckStatusAsync();
if (status != Status.Granted) if (status != Status.Granted)
{ {
var permissionResult = await PermissionsService.RequestAsync(); if (RuntimePlatform == Device.Android)
if (permissionResult != Status.Granted)
{ {
var dialogResult = await ViewService.DisplayAlert( var permissionResult = await PermissionsService.RequestAsync();
AppResources.MessageTitleHint,
AppResources.MessageBikesManagementLocationPermissionOpenDialog,
AppResources.MessageAnswerYes,
AppResources.MessageAnswerNo);
if (!dialogResult) if (permissionResult != Status.Granted)
{ {
// User decided not to give access to locations permissions. var dialogResult = await ViewService.DisplayAlert(
BikeCollection.Update(bikeCollection, Stations); AppResources.MessageTitleHint,
AppResources.MessageBikesManagementLocationPermissionOpenDialog,
AppResources.MessageAnswerYes,
AppResources.MessageAnswerNo);
await StartUpdateTask(() => UpdateTask()); if (!dialogResult)
{
// User decided not to give access to locations permissions.
BikeCollection.Update(bikeCollection, Stations);
ActionText = ""; await StartUpdateTask(() => UpdateTask());
IsIdle = true;
return; ActionText = "";
IsIdle = true;
return;
}
// Open permissions dialog.
PermissionsService.OpenAppSettings();
} }
}
else
{
var dialogResult = await ViewService.DisplayAlert(
AppResources.MessageTitleHint,
AppResources.MessageBikesManagementLocationPermissionOpenDialog,
AppResources.MessageAnswerYes,
AppResources.MessageAnswerNo);
// Open permissions dialog. if (!dialogResult)
PermissionsService.OpenAppSettings(); {
// User decided not to give access to locations permissions.
BikeCollection.Update(bikeCollection, Stations);
await StartUpdateTask(() => UpdateTask());
ActionText = "";
IsIdle = true;
return;
}
// Open permissions dialog.
PermissionsService.OpenAppSettings();
} }
} }

View file

@ -27,6 +27,7 @@ using TINK.Repository;
using TINK.Services.Geolocation; using TINK.Services.Geolocation;
using TINK.Model.State; using TINK.Model.State;
#if !TRYNOTBACKSTYLE #if !TRYNOTBACKSTYLE
#endif #endif
@ -55,6 +56,8 @@ namespace TINK.ViewModel.Map
/// </summary> /// </summary>
private ILocationPermission PermissionsService { get; } private ILocationPermission PermissionsService { get; }
private IGeolocation Geolocation { get; }
/// <summary> /// <summary>
/// Service to manage bluetooth stack. /// Service to manage bluetooth stack.
/// </summary> /// </summary>
@ -227,28 +230,32 @@ namespace TINK.ViewModel.Map
} }
//Add blue dot for showing current location of user //Add blue dot for showing current location of user
Location currentLocation = null; var status = await PermissionsService.CheckStatusAsync();
try if (status == Status.Granted)
{ {
currentLocation = await GeolocationService.GetAsync(); Location currentLocation = null;
} try
catch (Exception ex)
{
Log.ForContext<MapPageViewModel>().Error("Getting location failed. {Exception}", ex);
}
if (currentLocation != null)
{
var currentLocationPin = new Pin()
{ {
Position = new Xamarin.Forms.GoogleMaps.Position(currentLocation.Latitude, currentLocation.Longitude), currentLocation = await GeolocationService.GetAsync();
Label = "currentLocationPin", }
Type = PinType.Place, catch (Exception ex)
Tag = "NotClickable", {
Icon = BitmapDescriptorFactory.FromBundle(currentLocationPinName) Log.ForContext<MapPageViewModel>().Error("Getting location failed. {Exception}", ex);
}; }
Pins.Add(currentLocationPin); if (currentLocation != null)
{
var currentLocationPin = new Pin()
{
Position = new Xamarin.Forms.GoogleMaps.Position(currentLocation.Latitude, currentLocation.Longitude),
Label = "currentLocationPin",
Type = PinType.Place,
Tag = "NotClickable",
Icon = BitmapDescriptorFactory.FromBundle(currentLocationPinName)
};
Pins.Add(currentLocationPin);
}
} }
} }
@ -343,7 +350,14 @@ namespace TINK.ViewModel.Map
{ {
try try
{ {
//Request Location Permission on iOS
if(DeviceInfo.Platform == DevicePlatform.iOS)
{
var status = await PermissionsService.RequestAsync();
}
IsRunning = true; IsRunning = true;
IsNavBarVisible = false;
// Process map page. // Process map page.
Polling = TinkApp.Polling; Polling = TinkApp.Polling;
@ -354,9 +368,6 @@ namespace TINK.ViewModel.Map
// Update map page filter // Update map page filter
ActiveFilterMap = TinkApp.GroupFilterMapPage; ActiveFilterMap = TinkApp.GroupFilterMapPage;
ActionText = AppResources.ActivityTextRequestingLocationPermissions;
var status = await RequestLocationPermission();
ActionText = AppResources.ActivityTextMapLoadingStationsAndBikes; ActionText = AppResources.ActivityTextMapLoadingStationsAndBikes;
IsConnected = TinkApp.GetIsConnected(); IsConnected = TinkApp.GetIsConnected();
var resultStationsAndBikes = await TinkApp.GetConnector(IsConnected).Query.GetBikesAndStationsAsync(); var resultStationsAndBikes = await TinkApp.GetConnector(IsConnected).Query.GetBikesAndStationsAsync();
@ -394,11 +405,15 @@ namespace TINK.ViewModel.Map
// Get map display area // Get map display area
Model.Map.IMapSpan mapSpan = null; Model.Map.IMapSpan mapSpan = null;
if (TinkApp.CenterMapToCurrentLocation && status == Status.Granted) if (TinkApp.CenterMapToCurrentLocation)
{ {
// Get from smart device var status = await PermissionsService.CheckStatusAsync();
mapSpan = await GetFromLocationService(status); if (status == Status.Granted)
} {
// Get from smart device
mapSpan = await GetFromLocationService(status);
}
}
if (mapSpan == null) if (mapSpan == null)
{ {
@ -433,6 +448,7 @@ namespace TINK.ViewModel.Map
Exception = resultStationsAndBikes.Exception; Exception = resultStationsAndBikes.Exception;
ActionText = ""; ActionText = "";
IsRunning = false; IsRunning = false;
IsNavBarVisible = true;
IsMapPageEnabled = true; IsMapPageEnabled = true;
} }
catch (Exception l_oException) catch (Exception l_oException)
@ -440,6 +456,7 @@ namespace TINK.ViewModel.Map
Log.ForContext<MapPageViewModel>().Error($"An error occurred showing bike stations page.\r\n{l_oException.Message}"); Log.ForContext<MapPageViewModel>().Error($"An error occurred showing bike stations page.\r\n{l_oException.Message}");
IsRunning = false; IsRunning = false;
IsNavBarVisible = true;
await ViewService.DisplayAlert( await ViewService.DisplayAlert(
"Fehler", "Fehler",
@ -552,19 +569,15 @@ namespace TINK.ViewModel.Map
{ {
// Check location permission // Check location permission
var status = await PermissionsService.CheckStatusAsync(); var status = await PermissionsService.CheckStatusAsync();
if (TinkApp.CenterMapToCurrentLocation if (!GeolocationService.IsSimulation
&& !GeolocationService.IsSimulation // && DeviceInfo.Platform == DevicePlatform.Android
&& status != Status.Granted) && status != Status.Granted)
{ {
status = await PermissionsService.RequestAsync(); var dialogResult = await ViewService.DisplayAlert(
AppResources.MessageTitleHint,
if (status != Status.Granted) AppResources.MessageCenterMapLocationPermissionOpenDialog,
{ AppResources.MessageAnswerYes,
var dialogResult = await ViewService.DisplayAlert( AppResources.MessageAnswerNo);
AppResources.MessageTitleHint,
AppResources.MessageCenterMapLocationPermissionOpenDialog,
AppResources.MessageAnswerYes,
AppResources.MessageAnswerNo);
if (dialogResult) if (dialogResult)
{ {
@ -572,9 +585,9 @@ namespace TINK.ViewModel.Map
PermissionsService.OpenAppSettings(); PermissionsService.OpenAppSettings();
ActionText = ""; ActionText = "";
IsRunning = false; IsRunning = false;
IsNavBarVisible = true;
IsMapPageEnabled = true; IsMapPageEnabled = true;
} }
}
} }
return status; return status;
} }
@ -598,7 +611,7 @@ namespace TINK.ViewModel.Map
{ {
// Start task which periodically updates pins. // Start task which periodically updates pins.
return new PollingUpdateTaskManager( return new PollingUpdateTaskManager(
async () => () =>
{ {
try try
{ {
@ -660,6 +673,7 @@ namespace TINK.ViewModel.Map
null); null);
Log.ForContext<MapPageViewModel>().Verbose("Leaving update cycle."); Log.ForContext<MapPageViewModel>().Verbose("Leaving update cycle.");
return; return;
} }
}); });
@ -845,6 +859,21 @@ namespace TINK.ViewModel.Map
} }
} }
private bool isNavBarVisible = true;
public bool IsNavBarVisible
{
get => isNavBarVisible;
set
{
if (value == isNavBarVisible)
return;
Log.ForContext<MapPageViewModel>().Debug($"Switch value of {nameof(isNavBarVisible)} to {value}.");
isNavBarVisible = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsNavBarVisible)));
}
}
/// <summary> Holds information whether app is connected to web or not. </summary> /// <summary> Holds information whether app is connected to web or not. </summary>
private bool? isConnected = null; private bool? isConnected = null;
@ -895,6 +924,9 @@ namespace TINK.ViewModel.Map
{ {
try try
{ {
IsRunning = true;
ActionText = AppResources.ActivityTextCenterMap;
IsMapPageEnabled = false; IsMapPageEnabled = false;
Log.ForContext<MapPageViewModel>().Information($"Request to center to current position."); Log.ForContext<MapPageViewModel>().Information($"Request to center to current position.");
@ -913,127 +945,92 @@ namespace TINK.ViewModel.Map
TinkApp.UpdateConnector(); TinkApp.UpdateConnector();
// Check location permission // Check location permission
//ActionText = AppResources.ActivityTextRequestingLocationPermissions; var status = await RequestLocationPermission();
if (status == Status.Granted)
var status = await PermissionsService.CheckStatusAsync();
if (!GeolocationService.IsSimulation
&& status != Status.Granted)
{ {
status = await PermissionsService.RequestAsync(); // Move and scale.
Location currentLocation = null;
if (status != Status.Granted)
{
var dialogResult = await ViewService.DisplayAlert(
AppResources.MessageTitleHint,
AppResources.MessageCenterMapLocationPermissionOpenDialog,
AppResources.MessageAnswerYes,
AppResources.MessageAnswerNo);
if (dialogResult)
{
// User decided to give access to locations permissions.
PermissionsService.OpenAppSettings();
ActionText = "";
IsRunning = false;
IsMapPageEnabled = true;
return;
}
}
// Do not use property .State to get bluetooth state due
// to issue https://hausource.visualstudio.com/TINK/_workitems/edit/116 /
// see https://github.com/xabre/xamarin-bluetooth-le/issues/112#issuecomment-380994887
if (await BluetoothService.GetBluetoothState() != Plugin.BLE.Abstractions.Contracts.BluetoothState.On)
{
await ViewService.DisplayAlert(
AppResources.MessageTitleHint,
AppResources.MessageBikesManagementBluetoothActivation,
AppResources.MessageAnswerOk);
ActionText = "";
IsRunning = false;
IsMapPageEnabled = true;
return;
}
}
// Move and scale before getting stations and bikes which takes some time.
Location currentLocation = null;
try
{
currentLocation = await GeolocationService.GetAsync();
}
catch (Exception ex)
{
Log.ForContext<MapPageViewModel>().Error("Getting location failed. {Exception}", ex);
}
if (currentLocation != null)
{
IsRunning = true;
ActionText = AppResources.ActivityTextCenterMap;
TinkApp.UserMapSpan = MapSpan.FromCenterAndRadius(
new Xamarin.Forms.GoogleMaps.Position(currentLocation.Latitude, currentLocation.Longitude),
TinkApp.ActiveMapSpan.Radius);
TinkApp.Save();
MoveAndScale(m_oMoveToRegionDelegate, TinkApp.ActiveMapSpan);
//Pins.Clear();
//// Update stations
//ActionText = AppResources.ActivityTextMapLoadingStationsAndBikes;
//IsConnected = TinkApp.GetIsConnected();
//var resultStationsAndBikes = await TinkApp.GetConnector(IsConnected).Query.GetBikesAndStationsAsync();
//// Set pins to their positions on map.
//InitializePins(resultStationsAndBikes.Response.StationsAll);
//Log.ForContext<MapPageViewModel>().Verbose("Update of pins done...");
//// Update pin colors.
//Log.ForContext<MapPageViewModel>().Verbose("Starting update pins color...");
//var l_oColors = GetStationColors(
// Pins.Select(x => x.Tag.ToString()).ToList(),
// resultStationsAndBikes.Response.Bikes);
//// Update pins color form count of bikes located at station.
//UpdatePinsColor(l_oColors);
//Log.ForContext<MapPageViewModel>().Verbose("Update pins color done.");
try try
{ {
// Update bikes at station or my bikes depending on context. currentLocation = await GeolocationService.GetAsync();
await m_oViewUpdateManager.StartUpdateAyncPeridically(Polling);
} }
catch (Exception) catch (Exception ex)
{ {
// Excpetions are handled insde update task; Log.ForContext<MapPageViewModel>().Error("Getting location failed. {Exception}", ex);
}
if (currentLocation != null)
{
IsRunning = true;
ActionText = AppResources.ActivityTextCenterMap;
TinkApp.UserMapSpan = MapSpan.FromCenterAndRadius(
new Xamarin.Forms.GoogleMaps.Position(currentLocation.Latitude, currentLocation.Longitude),
TinkApp.ActiveMapSpan.Radius);
TinkApp.Save();
MoveAndScale(m_oMoveToRegionDelegate, TinkApp.ActiveMapSpan);
Pins.Clear();
// Update stations
IsConnected = TinkApp.GetIsConnected();
var resultStationsAndBikes = await TinkApp.GetConnector(IsConnected).Query.GetBikesAndStationsAsync();
// Set pins to their positions on map.
ActionText = AppResources.ActivityTextMapLoadingStationsAndBikes;
InitializePins(resultStationsAndBikes.Response.StationsAll);
Log.ForContext<MapPageViewModel>().Verbose("Update of pins done...");
// Update pin colors.
Log.ForContext<MapPageViewModel>().Verbose("Starting update pins color...");
var l_oColors = GetStationColors(
Pins.Select(x => x.Tag.ToString()).ToList(),
resultStationsAndBikes.Response.Bikes);
// Update pins color form count of bikes located at station.
UpdatePinsColor(l_oColors);
Log.ForContext<MapPageViewModel>().Verbose("Update pins color done.");
try
{
// Update bikes at station or my bikes depending on context.
await m_oViewUpdateManager.StartUpdateAyncPeridically(Polling);
}
catch (Exception)
{
// Excpetions are handled insde update task;
}
}
else
{
await ViewService.DisplayAlert(
AppResources.MessageTitleHint,
AppResources.MessageErrorLocationIsOff,
AppResources.MessageAnswerOk);
} }
}
else
{
ActionText = AppResources.ActivityTextErrorQueryLocationWhenAny;
} }
IsRunning = false; IsRunning = false;
IsMapPageEnabled = true; IsMapPageEnabled = true;
Log.ForContext<MapPageViewModel>().Information($"Center to current Position done."); Log.ForContext<MapPageViewModel>().Information($"Center to current Position done.");
ActionText = ""; ActionText = String.Empty;
} }
catch (Exception l_oException) catch (Exception l_oException)
{ {
Log.ForContext<MapPageViewModel>().Error("An error occurred while centering to current position."); Log.ForContext<MapPageViewModel>().Error("An error occurred while centering to current position.");
ActionText = ""; ActionText = String.Empty;
IsRunning = false;
await ViewService.DisplayAlert( await ViewService.DisplayAlert(
"Fehler", "Fehler",
AppResources.MessageMapPageErrorSwitch, AppResources.MessageMapPageErrorSwitch,
String.Format(AppResources.MessageMapPageErrorSwitch, l_oException.Message), String.Format(AppResources.MessageErrorQueryLocationMessage, l_oException.Message),
AppResources.MessageAnswerOk); AppResources.MessageAnswerOk);
IsMapPageEnabled = true; IsMapPageEnabled = true;
IsRunning = false;
} }
} }
@ -1080,6 +1077,7 @@ namespace TINK.ViewModel.Map
{ {
IsMapPageEnabled = false; IsMapPageEnabled = false;
IsRunning = true; IsRunning = true;
IsNavBarVisible = false;
Log.ForContext<MapPageViewModel>().Information($"Request to toggle to \"{selectedFilter}\"."); Log.ForContext<MapPageViewModel>().Information($"Request to toggle to \"{selectedFilter}\".");
@ -1101,76 +1099,42 @@ namespace TINK.ViewModel.Map
Pins.Clear(); Pins.Clear();
// Check location permission //// Move and scale before getting stations and bikes which takes some time.
//ActionText = AppResources.ActivityTextRequestingLocationPermissions; //if (TinkApp.CenterMapToCurrentLocation)
//{
// // Check location permission
// //ActionText = AppResources.ActivityTextRequestingLocationPermissions;
// var status = await RequestLocationPermission();
// if (status == Status.Granted)
// {
// //ActionText = AppResources.ActivityTextCenterMap;
var status = await PermissionsService.CheckStatusAsync(); // Location currentLocation = null;
if (TinkApp.CenterMapToCurrentLocation // try
&& !GeolocationService.IsSimulation // {
&& status != Status.Granted) // currentLocation = await GeolocationService.GetAsync();
{ // }
status = await PermissionsService.RequestAsync(); // catch (Exception ex)
// {
// Log.ForContext<MapPageViewModel>().Error("Getting location failed. {Exception}", ex);
// }
if (status != Status.Granted) // if (currentLocation != null)
{ // {
var dialogResult = await ViewService.DisplayAlert( // TinkApp.UserMapSpan = MapSpan.FromCenterAndRadius(
AppResources.MessageTitleHint, // new Xamarin.Forms.GoogleMaps.Position(currentLocation.Latitude, currentLocation.Longitude),
AppResources.MessageCenterMapLocationPermissionOpenDialog, // TinkApp.ActiveMapSpan.Radius);
AppResources.MessageAnswerYes,
AppResources.MessageAnswerNo);
if (dialogResult)
{
// User decided to give access to locations permissions.
PermissionsService.OpenAppSettings();
ActionText = "";
IsRunning = false;
IsMapPageEnabled = true;
return;
}
}
// Do not use property .State to get bluetooth state due // TinkApp.Save();
// to issue https://hausource.visualstudio.com/TINK/_workitems/edit/116 /
// see https://github.com/xabre/xamarin-bluetooth-le/issues/112#issuecomment-380994887
if (await BluetoothService.GetBluetoothState() != Plugin.BLE.Abstractions.Contracts.BluetoothState.On)
{
await ViewService.DisplayAlert(
AppResources.MessageTitleHint,
AppResources.MessageBikesManagementBluetoothActivation,
AppResources.MessageAnswerOk);
ActionText = "";
IsRunning = false;
IsMapPageEnabled = true;
return;
}
}
// Move and scale before getting stations and bikes which takes some time. // //MoveAndScale(m_oMoveToRegionDelegate, TinkApp.ActiveMapSpan);
if (TinkApp.CenterMapToCurrentLocation) // }
{ // else
//ActionText = AppResources.ActivityTextCenterMap; // {
// ActionText = AppResources.ActivityTextErrorQueryLocationWhenAny;
Location currentLocation = null; // }
try // }
{ //}
currentLocation = await GeolocationService.GetAsync();
}
catch (Exception ex)
{
Log.ForContext<MapPageViewModel>().Error("Getting location failed. {Exception}", ex);
}
if (currentLocation != null)
{
TinkApp.UserMapSpan = MapSpan.FromCenterAndRadius(
new Xamarin.Forms.GoogleMaps.Position(currentLocation.Latitude, currentLocation.Longitude),
TinkApp.ActiveMapSpan.Radius);
TinkApp.Save();
//MoveAndScale(m_oMoveToRegionDelegate, TinkApp.ActiveMapSpan);
}
}
// Update stations // Update stations
ActionText = AppResources.ActivityTextMapLoadingStationsAndBikes; ActionText = AppResources.ActivityTextMapLoadingStationsAndBikes;
@ -1204,6 +1168,7 @@ namespace TINK.ViewModel.Map
ActionText = ""; ActionText = "";
IsRunning = false; IsRunning = false;
IsNavBarVisible = true;
IsMapPageEnabled = true; IsMapPageEnabled = true;
Log.ForContext<MapPageViewModel>().Information($"Toggle to \"{selectedFilter}\" done."); Log.ForContext<MapPageViewModel>().Information($"Toggle to \"{selectedFilter}\" done.");
} }
@ -1212,6 +1177,7 @@ namespace TINK.ViewModel.Map
Log.ForContext<MapPageViewModel>().Error("An error occurred switching view Cargobike/ Citybike.{}"); Log.ForContext<MapPageViewModel>().Error("An error occurred switching view Cargobike/ Citybike.{}");
ActionText = ""; ActionText = "";
IsRunning = false; IsRunning = false;
IsNavBarVisible = true;
await ViewService.DisplayAlert( await ViewService.DisplayAlert(
"Fehler", "Fehler",

View file

@ -154,7 +154,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Starting bike return..."; bikesViewModel.ActionText = "Starting bike return...";
connector.Command.StartReturningBike(bike); // Notify about start connector.Command.StartReturningBike(bike); // Notify about start
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Query location..."; bikesViewModel.ActionText = "Query location...";
bikesViewModel.ActionText = "Returning bike..."; bikesViewModel.ActionText = "Returning bike...";
@ -226,7 +226,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Starting bike return..."; bikesViewModel.ActionText = "Starting bike return...";
connector.Command.StartReturningBike(bike); // Notify about start connector.Command.StartReturningBike(bike); // Notify about start
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
bike.LockInfo.State = LockingState.UnknownDisconnected; bike.LockInfo.State = LockingState.UnknownDisconnected;
@ -431,7 +431,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Starting bike return..."; bikesViewModel.ActionText = "Starting bike return...";
connector.Command.StartReturningBike(bike); // Notify about start connector.Command.StartReturningBike(bike); // Notify about start
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
bike.LockInfo.State = LockingState.UnknownDisconnected; bike.LockInfo.State = LockingState.UnknownDisconnected;
@ -503,7 +503,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Starting bike return..."; bikesViewModel.ActionText = "Starting bike return...";
connector.Command.StartReturningBike(bike); // Notify about start connector.Command.StartReturningBike(bike); // Notify about start
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
bike.LockInfo.State = LockingState.Open; bike.LockInfo.State = LockingState.Open;
@ -577,7 +577,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Starting bike return..."; bikesViewModel.ActionText = "Starting bike return...";
connector.Command.StartReturningBike(bike); // Notify about start connector.Command.StartReturningBike(bike); // Notify about start
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bike.LockInfo.State = LockingState.Open; bike.LockInfo.State = LockingState.Open;
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
@ -648,7 +648,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Starting bike return..."; bikesViewModel.ActionText = "Starting bike return...";
connector.Command.StartReturningBike(bike); // Notify about start connector.Command.StartReturningBike(bike); // Notify about start
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Query location..."; bikesViewModel.ActionText = "Query location...";
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
@ -720,7 +720,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Starting bike return..."; bikesViewModel.ActionText = "Starting bike return...";
connector.Command.StartReturningBike(bike); // Notify about start connector.Command.StartReturningBike(bike); // Notify about start
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Query location..."; bikesViewModel.ActionText = "Query location...";
bikesViewModel.ActionText = "Returning bike..."; bikesViewModel.ActionText = "Returning bike...";
@ -797,7 +797,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Starting bike return..."; bikesViewModel.ActionText = "Starting bike return...";
connector.Command.StartReturningBike(bike); // Notify about start connector.Command.StartReturningBike(bike); // Notify about start
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Query location..."; bikesViewModel.ActionText = "Query location...";
bikesViewModel.ActionText = "Returning bike..."; bikesViewModel.ActionText = "Returning bike...";
@ -873,7 +873,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Starting bike return..."; bikesViewModel.ActionText = "Starting bike return...";
connector.Command.StartReturningBike(bike); // Notify about start connector.Command.StartReturningBike(bike); // Notify about start
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Query location..."; bikesViewModel.ActionText = "Query location...";
bikesViewModel.ActionText = "Returning bike..."; bikesViewModel.ActionText = "Returning bike...";
@ -949,7 +949,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Starting bike return..."; bikesViewModel.ActionText = "Starting bike return...";
connector.Command.StartReturningBike(bike); // Notify about start connector.Command.StartReturningBike(bike); // Notify about start
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Query location..."; bikesViewModel.ActionText = "Query location...";
bikesViewModel.ActionText = "Returning bike..."; bikesViewModel.ActionText = "Returning bike...";
@ -1023,7 +1023,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "Starting bike return..."; bikesViewModel.ActionText = "Starting bike return...";
connector.Command.StartReturningBike(bike); // Notify about start connector.Command.StartReturningBike(bike); // Notify about start
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Query location..."; bikesViewModel.ActionText = "Query location...";
bikesViewModel.ActionText = "Returning bike..."; bikesViewModel.ActionText = "Returning bike...";
@ -1084,7 +1084,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Updating lock state..."; bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()); connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
@ -1144,7 +1144,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
viewService.DisplayAlert("Lock can not be closed!", "Lock cannot be closed until bike is near.", "OK"); viewService.DisplayAlert("Lock can not be closed!", "Lock cannot be closed until bike is near.", "OK");
@ -1204,7 +1204,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
viewService.DisplayAlert("Lock can not be closed!", "Exception message.", "OK"); viewService.DisplayAlert("Lock can not be closed!", "Exception message.", "OK");
@ -1265,7 +1265,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Updating lock state..."; bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()); connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
@ -1327,7 +1327,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Updating lock state..."; bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()); connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
@ -1390,7 +1390,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Updating lock state..."; bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()); connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());

View file

@ -779,7 +779,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Updating lock state..."; bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()); connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
@ -839,7 +839,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
viewService.DisplayAlert("Lock can not be closed!", "Lock cannot be closed until bike is near.", "OK"); viewService.DisplayAlert("Lock can not be closed!", "Lock cannot be closed until bike is near.", "OK");
@ -899,7 +899,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
viewService.DisplayAlert("Lock can not be closed!", "Exception message.", "OK"); viewService.DisplayAlert("Lock can not be closed!", "Exception message.", "OK");
@ -960,7 +960,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Updating lock state..."; bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()); connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
@ -1022,7 +1022,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Updating lock state..."; bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()); connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
@ -1085,7 +1085,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Updating lock state..."; bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()); connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());

View file

@ -91,7 +91,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks[0].CloseAsync(); locks[0].CloseAsync();
bikesViewModel.ActionText = "Disconnecting lock..."; bikesViewModel.ActionText = "Disconnecting lock...";
locks.DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>()); locks.DisconnectAsync(Arg.Any<int>(), Arg.Any<Guid>());
@ -154,7 +154,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks[0].CloseAsync(); locks[0].CloseAsync();
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
viewService.DisplayAlert("Lock can not be closed!", "Lock cannot be closed until bike is near.", "OK"); viewService.DisplayAlert("Lock can not be closed!", "Lock cannot be closed until bike is near.", "OK");
@ -217,7 +217,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks[0].CloseAsync(); locks[0].CloseAsync();
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
viewService.DisplayAlert("Lock can not be closed!", "Exception message.", "OK"); viewService.DisplayAlert("Lock can not be closed!", "Exception message.", "OK");

View file

@ -288,7 +288,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks[0].CloseAsync(); locks[0].CloseAsync();
bikesViewModel.ActionText = "Canceling reservation..."; bikesViewModel.ActionText = "Canceling reservation...";
connector.Command.DoCancelReservation(bike); connector.Command.DoCancelReservation(bike);
@ -360,7 +360,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks[0].CloseAsync(); locks[0].CloseAsync();
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
viewService.DisplayAlert( viewService.DisplayAlert(
@ -434,7 +434,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks[0].CloseAsync(); locks[0].CloseAsync();
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
viewService.DisplayAlert( viewService.DisplayAlert(
@ -512,7 +512,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks[0].CloseAsync(); locks[0].CloseAsync();
bikesViewModel.ActionText = "Canceling reservation..."; bikesViewModel.ActionText = "Canceling reservation...";
connector.Command.DoCancelReservation(bike); connector.Command.DoCancelReservation(bike);
@ -583,7 +583,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks[0].CloseAsync(); locks[0].CloseAsync();
bikesViewModel.ActionText = "Canceling reservation..."; bikesViewModel.ActionText = "Canceling reservation...";
connector.Command.DoCancelReservation(bike); connector.Command.DoCancelReservation(bike);
@ -654,7 +654,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel.Bikes.Bike.BluetoothLock.Re
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks[0].CloseAsync(); locks[0].CloseAsync();
bikesViewModel.ActionText = "Canceling reservation..."; bikesViewModel.ActionText = "Canceling reservation...";
connector.Command.DoCancelReservation(bike); connector.Command.DoCancelReservation(bike);

View file

@ -652,7 +652,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Updating lock state..."; bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()); connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
@ -708,7 +708,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
viewService.DisplayAlert("Lock can not be closed!", "Lock cannot be closed until bike is near.", "OK"); viewService.DisplayAlert("Lock can not be closed!", "Lock cannot be closed until bike is near.", "OK");
@ -768,7 +768,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = ""; bikesViewModel.ActionText = "";
viewService.DisplayAlert("Lock can not be closed!", "Exception message.", "OK"); viewService.DisplayAlert("Lock can not be closed!", "Exception message.", "OK");
@ -830,7 +830,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Updating lock state..."; bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()); connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
@ -892,7 +892,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Updating lock state..."; bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()); connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());
@ -955,7 +955,7 @@ namespace TestShareeLib.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bikesViewModel.Received(1).IsIdle = false; // GUI must be locked bikesViewModel.Received(1).IsIdle = false; // GUI must be locked
bikesViewModel.ActionText = "One moment please..."; bikesViewModel.ActionText = "One moment please...";
pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action pollingManager.StopUpdatePeridically(); // Polling must be stopped before any COPR and lock service action
bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please visually check if it is completely closed.</b></h4>"; bikesViewModel.ActionText = "<h4><b>Lock is closing.<br/>Please wait until it is completely closed.</b></h4>";
locks.Received()[0].CloseAsync(); // Lock must be closed locks.Received()[0].CloseAsync(); // Lock must be closed
bikesViewModel.ActionText = "Updating lock state..."; bikesViewModel.ActionText = "Updating lock state...";
connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>()); connector.Command.UpdateLockingStateAsync(bike, Arg.Any<LocationDto>());

View file

@ -389,7 +389,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
{ {
permissions.CheckStatusAsync(); permissions.CheckStatusAsync();
var glDummy = geolocation.Active.Received().IsGeolcationEnabled; var glDummy = geolocation.Active.Received().IsGeolcationEnabled;
permissions.RequestAsync(); // Ask user from permissions. // permissions.RequestAsync(); // Ask user from permissions (disabled, since no secondary request allowed).
viewService.DisplayAlert( viewService.DisplayAlert(
"Hint", "Hint",
"Please allow location sharing so that bike lock/locks can be managed.\r\nOpen sharing dialog?", "Please allow location sharing so that bike lock/locks can be managed.\r\nOpen sharing dialog?",
@ -398,7 +398,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
permissions.OpenAppSettings(); permissions.OpenAppSettings();
}); });
Assert.IsEmpty(bikesAtStation.StatusInfoText); Assert.IsTrue(new List<string> { "Updating...", string.Empty }.Contains(bikesAtStation.StatusInfoText));
// Verify list of bikes // Verify list of bikes
Assert.AreEqual(4, bikesAtStation.Count); Assert.AreEqual(4, bikesAtStation.Count);
@ -517,7 +517,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
{ {
permissions.CheckStatusAsync(); permissions.CheckStatusAsync();
var glDummy = geolocation.Active.Received().IsGeolcationEnabled; var glDummy = geolocation.Active.Received().IsGeolcationEnabled;
permissions.RequestAsync(); // Ask user from permissions. //permissions.RequestAsync(); // Ask user from permissions (disabled, since no secondary request allowed).
viewService.DisplayAlert( viewService.DisplayAlert(
"Hint", "Hint",
"Please allow location sharing so that bike lock/locks can be managed.\r\nOpen sharing dialog?", "Please allow location sharing so that bike lock/locks can be managed.\r\nOpen sharing dialog?",