Version 3.0.361

This commit is contained in:
Anja 2023-03-08 13:18:54 +01:00
parent faf68061f4
commit cba4da9357
88 changed files with 1119 additions and 1502 deletions

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.360" android:versionCode="360"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.LastenradBayern" android:versionName="3.0.361" android:versionCode="361">
<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 -->

View file

@ -14,7 +14,7 @@ namespace TINK.Droid
{ {
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.0.0.73")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.2.0.93")]
public partial class Resource public partial class Resource
{ {

View file

@ -56,8 +56,8 @@
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>LastenradBayern</string> <string>LastenradBayern</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>360</string> <string>361</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.360</string> <string>3.0.361</string>
</dict> </dict>
</plist> </plist>

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.360" android:versionCode="360"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.TeilRad.Meinkonrad" android:versionName="3.0.361" android:versionCode="361">
<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 -->

View file

@ -14,7 +14,7 @@ namespace TINK.Droid
{ {
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.0.0.73")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.2.0.93")]
public partial class Resource public partial class Resource
{ {

View file

@ -56,8 +56,8 @@
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>Mein konrad</string> <string>Mein konrad</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>360</string> <string>361</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.360</string> <string>3.0.361</string>
</dict> </dict>
</plist> </plist>

View file

@ -12,217 +12,231 @@
<ContentView.Resources> <ContentView.Resources>
<conv:StringNotNullOrEmptyToVisibleConverter x:Key="Label_Converter"/> <conv:StringNotNullOrEmptyToVisibleConverter x:Key="Label_Converter"/>
</ContentView.Resources> </ContentView.Resources>
<StackLayout <Frame
Padding="10"> Padding="10"
<Grid Padding="0,0,5,10"> Margin="0,5,0,5"
<Grid.ColumnDefinitions> HorizontalOptions="FillAndExpand"
<ColumnDefinition Width="Auto" /> VerticalOptions="FillAndExpand"
<ColumnDefinition Width="Auto" /> BackgroundColor="White">
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> <StackLayout
<!-- Icon of the bike --> Orientation="Vertical"
<Image Padding="10">
Source="{Binding DisplayedBikeImageSourceString}"
HeightRequest="80" <!-- Icons, Name, ID -->
Aspect="AspectFit" <Grid Padding="0,0,5,10"
HorizontalOptions="Start" ColumnDefinitions="Auto,Auto,*"
VerticalOptions="End" RowDefinitions="Auto,Auto">
Grid.Column="0"/>
<!-- Battery level --> <!-- Icon of the bike -->
<sharedGui:BarLevelView <Image
Current="{Binding CurrentChargeBars}" Grid.Column="0"
Maximum="{Binding MaxChargeBars}" Grid.Row="0"
Grid.Column="1" Grid.RowSpan="2"
VerticalOptions="End" Source="{Binding DisplayedBikeImageSourceString}"
IsVisible="{Binding IsBatteryChargeVisible}"/> HeightRequest="60"
<!-- Name of the bike --> Aspect="AspectFit"
<StackLayout Grid.Column="2"> HorizontalOptions="Start"
<Label VerticalOptions="End"/>
FontAttributes="Bold"
FontSize="Large" <!-- Battery level -->
HorizontalTextAlignment="Right" <sharedGui:BarLevelView
Text="{Binding Name}"/> Grid.Column="1"
Grid.Row="1"
Current="{Binding CurrentChargeBars}"
Maximum="{Binding MaxChargeBars}"
VerticalOptions="End"
IsVisible="{Binding IsBatteryChargeVisible}"/>
<!-- Name of the bike -->
<Label
Grid.Column="1"
Grid.ColumnSpan="2"
Grid.Row="0"
FontAttributes="Bold"
FontSize="Large"
HorizontalTextAlignment="Right"
Text="{Binding Name}"/>
<!-- Id of the bike --> <!-- Id of the bike -->
<Label <Label
FontAttributes="Bold" Grid.Column="2"
HorizontalTextAlignment="Right" Grid.Row="1"
IsVisible="{Binding DisplayId, Converter={StaticResource Label_Converter}}" FontAttributes="Bold"
Text="{Binding DisplayId}"/> HorizontalTextAlignment="Right"
</StackLayout> IsVisible="{Binding DisplayId, Converter={StaticResource Label_Converter}}"
</Grid> Text="{Binding DisplayId}"/>
<!-- Rental state -->
<Label </Grid>
Text="{Binding StateText}"
TextColor="{Binding StateColor}"/> <!-- Rental state -->
<Label <Label
Text="{Binding ErrorText}" Text="{Binding StateText}"
IsVisible="{Binding ErrorText, Converter={StaticResource Label_Converter}}" TextColor="{Binding StateColor}"/>
TextColor="Red"/> <Label
<!-- Low Battery level --> Text="{Binding ErrorText}"
<Label IsVisible="{Binding ErrorText, Converter={StaticResource Label_Converter}}"
x:Name="LowLevelLabel" TextColor="Red"/>
Text="{x:Static resources:AppResources.StatusTextLowBatteryLevel}"
FontSize="Small" <!-- Buttons -->
IsVisible="{Binding IsCurrentChargeLow}" /> <Button
<Button Text="{Binding ButtonText}"
Text="{Binding ButtonText}" IsVisible="{Binding IsButtonVisible}"
IsVisible="{Binding IsButtonVisible}" Command="{Binding OnButtonClicked}"/>
IsEnabled="{Binding IsIdle}" <Button
Command="{Binding OnButtonClicked}"/> Style="{StaticResource SecondaryButton}"
<Button Text="{Binding LockitButtonText}"
Style="{StaticResource SecondaryButton}" IsVisible="{Binding IsLockitButtonVisible}"
Text="{Binding LockitButtonText}" Command="{Binding OnLockitButtonClicked}"/>
IsVisible="{Binding IsLockitButtonVisible}" <!-- Rental description (tarif name, options and rental info -->
IsEnabled="{Binding IsIdle}" <Grid
Command="{Binding OnLockitButtonClicked}"/>
<!-- Rental description (tarif name, options and rental info -->
<Grid
RowSpacing="0" RowSpacing="0"
IsVisible="{Binding TariffDescription.Header, Converter={StaticResource Label_Converter}}"> IsVisible="{Binding TariffDescription.Header, Converter={StaticResource Label_Converter}}">
<Grid.RowDefinitions> <Grid.RowDefinitions>
<!-- start tarif- entries --> <!-- start tarif- entries -->
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<!-- start rental info --> <!-- start rental info -->
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
<RowDefinition Height="Auto" /> <RowDefinition Height="Auto" />
</Grid.RowDefinitions> </Grid.RowDefinitions>
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" /> <ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" /> <ColumnDefinition Width="*" />
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<!-- start tarif- entries (should be a CollectionView) --> <!-- start tarif- entries (should be a CollectionView) -->
<Label <Label
Text= "{x:Static resources:AppResources.MessageBikesManagementTariffDescriptionTariffHeader}" Text= "{x:Static resources:AppResources.MessageBikesManagementTariffDescriptionTariffHeader}"
IsVisible="{Binding TariffDescription.Header, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.Header, Converter={StaticResource Label_Converter}}"
Grid.Row="0" Grid.Row="0"
FontAttributes="Bold"/> FontAttributes="Bold"/>
<Label <Label
Text="{Binding TariffDescription.Header}" Text="{Binding TariffDescription.Header}"
IsVisible="{Binding TariffDescription.Header, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.Header, Converter={StaticResource Label_Converter}}"
Grid.Row="0" Grid.Row="0"
Grid.Column="1" Grid.Column="1"
FontAttributes="Bold"/> FontAttributes="Bold"/>
<Label <Label
Text= "{Binding TariffDescription.TarifEntry1.Description}" Text= "{Binding TariffDescription.TarifEntry1.Description}"
IsVisible="{Binding TariffDescription.TarifEntry1.Description, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry1.Description, Converter={StaticResource Label_Converter}}"
Grid.Row="1"/> Grid.Row="1"/>
<Label <Label
Text="{Binding TariffDescription.TarifEntry1.Value}" Text="{Binding TariffDescription.TarifEntry1.Value}"
IsVisible="{Binding TariffDescription.TarifEntry1.Value, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry1.Value, Converter={StaticResource Label_Converter}}"
Grid.Row="1" Grid.Row="1"
Grid.Column="1"/> Grid.Column="1"/>
<Label <Label
Text= "{Binding TariffDescription.TarifEntry2.Description}" Text= "{Binding TariffDescription.TarifEntry2.Description}"
IsVisible="{Binding TariffDescription.TarifEntry2.Description, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry2.Description, Converter={StaticResource Label_Converter}}"
Grid.Row="2"/> Grid.Row="2"/>
<Label <Label
Text="{Binding TariffDescription.TarifEntry2.Value}" Text="{Binding TariffDescription.TarifEntry2.Value}"
IsVisible="{Binding TariffDescription.TarifEntry2.Value, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry2.Value, Converter={StaticResource Label_Converter}}"
Grid.Row="2" Grid.Row="2"
Grid.Column="1"/> Grid.Column="1"/>
<Label <Label
Text= "{Binding TariffDescription.TarifEntry3.Description}" Text= "{Binding TariffDescription.TarifEntry3.Description}"
IsVisible="{Binding TariffDescription.TarifEntry3.Description, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry3.Description, Converter={StaticResource Label_Converter}}"
Grid.Row="3"/> Grid.Row="3"/>
<Label <Label
Text="{Binding TariffDescription.TarifEntry3.Value}" Text="{Binding TariffDescription.TarifEntry3.Value}"
IsVisible="{Binding TariffDescription.TarifEntry3.Value, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry3.Value, Converter={StaticResource Label_Converter}}"
Grid.Row="3" Grid.Row="3"
Grid.Column="1"/> Grid.Column="1"/>
<Label <Label
Text= "{Binding TariffDescription.TarifEntry4.Description}" Text= "{Binding TariffDescription.TarifEntry4.Description}"
IsVisible="{Binding TariffDescription.TarifEntry4.Description, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry4.Description, Converter={StaticResource Label_Converter}}"
Grid.Row="4"/> Grid.Row="4"/>
<Label <Label
Text="{Binding TariffDescription.TarifEntry4.Value}" Text="{Binding TariffDescription.TarifEntry4.Value}"
IsVisible="{Binding TariffDescription.TarifEntry4.Value, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry4.Value, Converter={StaticResource Label_Converter}}"
Grid.Row="4" Grid.Row="4"
Grid.Column="1"/> Grid.Column="1"/>
<Label <Label
Text= "{Binding TariffDescription.TarifEntry5.Description}" Text= "{Binding TariffDescription.TarifEntry5.Description}"
IsVisible="{Binding TariffDescription.TarifEntry5.Description, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry5.Description, Converter={StaticResource Label_Converter}}"
Grid.Row="5"/> Grid.Row="5"/>
<Label <Label
Text="{Binding TariffDescription.TarifEntry5.Value}" Text="{Binding TariffDescription.TarifEntry5.Value}"
IsVisible="{Binding TariffDescription.TarifEntry5.Value, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry5.Value, Converter={StaticResource Label_Converter}}"
Grid.Row="5" Grid.Row="5"
Grid.Column="1"/> Grid.Column="1"/>
<Label <Label
Text= "{Binding TariffDescription.TarifEntry6.Description}" Text= "{Binding TariffDescription.TarifEntry6.Description}"
IsVisible="{Binding TariffDescription.TarifEntry6.Description, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry6.Description, Converter={StaticResource Label_Converter}}"
Grid.Row="6"/> Grid.Row="6"/>
<Label <Label
Text="{Binding TariffDescription.TarifEntry6.Value}" Text="{Binding TariffDescription.TarifEntry6.Value}"
IsVisible="{Binding TariffDescription.TarifEntry6.Value, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry6.Value, Converter={StaticResource Label_Converter}}"
Grid.Row="6" Grid.Row="6"
Grid.Column="1"/> Grid.Column="1"/>
<Label <Label
Text= "{Binding TariffDescription.TarifEntry7.Description}" Text= "{Binding TariffDescription.TarifEntry7.Description}"
IsVisible="{Binding TariffDescription.TarifEntry7.Description, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry7.Description, Converter={StaticResource Label_Converter}}"
Grid.Row="7"/> Grid.Row="7"/>
<Label <Label
Text="{Binding TariffDescription.TarifEntry7.Value}" Text="{Binding TariffDescription.TarifEntry7.Value}"
IsVisible="{Binding TariffDescription.TarifEntry7.Value, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry7.Value, Converter={StaticResource Label_Converter}}"
Grid.Row="7" Grid.Row="7"
Grid.Column="1"/> Grid.Column="1"/>
<Label <Label
Text= "{Binding TariffDescription.TarifEntry8.Description}" Text= "{Binding TariffDescription.TarifEntry8.Description}"
IsVisible="{Binding TariffDescription.TarifEntry8.Description, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry8.Description, Converter={StaticResource Label_Converter}}"
Grid.Row="8"/> Grid.Row="8"/>
<Label <Label
Text="{Binding TariffDescription.TarifEntry8.Value}" Text="{Binding TariffDescription.TarifEntry8.Value}"
IsVisible="{Binding TariffDescription.TarifEntry8.Value, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry8.Value, Converter={StaticResource Label_Converter}}"
Grid.Row="8" Grid.Row="8"
Grid.Column="1"/> Grid.Column="1"/>
<Label <Label
Text= "{Binding TariffDescription.TarifEntry9.Description}" Text= "{Binding TariffDescription.TarifEntry9.Description}"
IsVisible="{Binding TariffDescription.TarifEntry9.Description, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry9.Description, Converter={StaticResource Label_Converter}}"
Grid.Row="9"/> Grid.Row="9"/>
<Label <Label
Text="{Binding TariffDescription.TarifEntry9.Value}" Text="{Binding TariffDescription.TarifEntry9.Value}"
IsVisible="{Binding TariffDescription.TarifEntry9.Value, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TarifEntry9.Value, Converter={StaticResource Label_Converter}}"
Grid.Row="9" Grid.Row="9"
Grid.Column="1"/> Grid.Column="1"/>
<!-- start tarif- entries (should be a CollectionView) --> <!-- start tarif- entries (should be a CollectionView) -->
<Label <Label
Text= "{Binding TariffDescription.InfoEntry1}" Text= "{Binding TariffDescription.InfoEntry1}"
IsVisible="{Binding TariffDescription.InfoEntry1, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.InfoEntry1, Converter={StaticResource Label_Converter}}"
Grid.Row="10" Grid.Row="10"
Grid.ColumnSpan="2"/> Grid.ColumnSpan="2"/>
<Label <Label
Text= "{Binding TariffDescription.InfoEntry2}" Text= "{Binding TariffDescription.InfoEntry2}"
IsVisible="{Binding TariffDescription.InfoEntry2, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.InfoEntry2, Converter={StaticResource Label_Converter}}"
Grid.Row="11" Grid.Row="11"
Grid.ColumnSpan="2"/> Grid.ColumnSpan="2"/>
<Label <Label
Text= "{Binding TariffDescription.InfoEntry3}" Text= "{Binding TariffDescription.InfoEntry3}"
IsVisible="{Binding TariffDescription.InfoEntry3, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.InfoEntry3, Converter={StaticResource Label_Converter}}"
Grid.Row="12" Grid.Row="12"
Grid.ColumnSpan="2"/> Grid.ColumnSpan="2"/>
<Label <Label
Text= "{Binding TariffDescription.InfoEntry4}" Text= "{Binding TariffDescription.InfoEntry4}"
IsVisible="{Binding TariffDescription.InfoEntry4, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.InfoEntry4, Converter={StaticResource Label_Converter}}"
Grid.Row="13" Grid.Row="13"
Grid.ColumnSpan="2"/> Grid.ColumnSpan="2"/>
<Label <Label
Text= "{Binding TariffDescription.TrackingInfoText}" Text= "{Binding TariffDescription.TrackingInfoText}"
IsVisible="{Binding TariffDescription.TrackingInfoText, Converter={StaticResource Label_Converter}}" IsVisible="{Binding TariffDescription.TrackingInfoText, Converter={StaticResource Label_Converter}}"
Grid.Row="14" Grid.Row="14"
Grid.ColumnSpan="2"/> Grid.ColumnSpan="2"/>
</Grid> </Grid>
</StackLayout> </StackLayout>
</ContentView> </Frame>
</ContentView>
</ViewCell> </ViewCell>

View file

@ -5,6 +5,7 @@
xmlns:local_bike="clr-namespace:TINK.View.Bike" xmlns:local_bike="clr-namespace:TINK.View.Bike"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View" xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
BackgroundColor="{DynamicResource background-color}"
Shell.FlyoutBehavior="Disabled" Shell.FlyoutBehavior="Disabled"
Shell.NavBarIsVisible="{Binding IsIdle}"> Shell.NavBarIsVisible="{Binding IsIdle}">
@ -16,6 +17,7 @@
</Grid> </Grid>
</Shell.TitleView> </Shell.TitleView>
<ContentPage.Resources> <ContentPage.Resources>
<ResourceDictionary> <ResourceDictionary>
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/> <local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
@ -26,109 +28,160 @@
<!--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 for Content -->
<Grid
Grid.Row="0"
RowSpacing="0"
RowDefinitions="Auto,1*,Auto">
<StackLayout Grid.Row="0" Spacing="0"> <StackLayout
Grid.Row="0"
Spacing="0"
Orientation="Vertical">
<!--No Network Connection--> <!--Station-->
<sharedGui:NotConnectedToNetView/> <StackLayout
BackgroundColor="{DynamicResource secondary-back-title-color}"
IsVisible="{Binding IsIdle}"
Padding="20,0,20,0">
<Frame> <!--Line-->
<BoxView
HeightRequest="1"
WidthRequest="400"
HorizontalOptions="Center"
Color="White"/>
<!-- Grid for Content --> <Grid
<Grid ColumnDefinitions="Auto,1*"
RowDefinitions="Auto,1*,Auto,Auto"> RowDefinitions="Auto"
Padding="0,0,0,5">
<!--Station--> <!--Station id-->
<StackLayout
Orientation="Vertical">
<!--Title-->
<Label
HorizontalOptions="Center"
FontAttributes="Bold"
TextColor="{DynamicResource primary-back-title-color}"
Text="{Binding StationDetailText}"/>
<!--Line-->
<BoxView
HeightRequest="1"
Color="{DynamicResource primary-back-title-color}"/>
</StackLayout>
<!--Bike(s)-->
<StackLayout
Spacing="0"
Grid.Row="1"
IsVisible="{Binding IsBikesListVisible}"
Orientation="Vertical">
<!--Hint for Outdated Data.-->
<sharedGui:HintForRefreshingPageView/>
<ListView
x:Name="BikesAtStationListView"
SelectionMode="None"
SelectedItem="{Binding SelectedBike}"
IsEnabled="{Binding IsIdle}"
HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"/>
</StackLayout>
<!--No Bikes-->
<Label <Label
IsVisible="{Binding IsNoBikesAtStationVisible}" Grid.Column="0"
Text="{Binding NoBikesAtStationText}"/> Grid.Row="0"
FontSize="Small"
<!--Info text--> HorizontalOptions="Start"
<Label TextColor="White"
Grid.Row="2" Text="{Binding StationDetailText}"/>
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
HorizontalOptions="CenterAndExpand"
VerticalOptions="CenterAndExpand"/>
<!-- Contact and Login at end of page-->
<StackLayout
Grid.Row="3"
Orientation="Vertical">
<!--Line-->
<BoxView
HeightRequest="1"
Color="{DynamicResource primary-back-title-color}"/>
<!--Contact to operator--> <!--Contact to operator-->
<Label <Label
TextType="Html" Grid.Column="1"
Text="{Binding ContactSupportHintText}"> Grid.Row="0"
TextType="Html"
FontSize="Small"
HorizontalOptions="End"
TextColor="White"
Text="{Binding ContactSupportHintText}">
<Label.GestureRecognizers> <Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ContactSupportClickedCommand}"/> <TapGestureRecognizer Command="{Binding ContactSupportClickedCommand}"/>
</Label.GestureRecognizers> </Label.GestureRecognizers>
</Label> </Label>
<!--Login required--> </Grid>
<Label
IsVisible="{Binding IsLoginRequiredHintVisible}"
TextType="Html"
Text="{Binding LoginRequiredHintText}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding LoginRequiredHintClickedCommand}"/>
</Label.GestureRecognizers>
</Label>
</StackLayout> </StackLayout>
</Grid> <!--No Network Connection-->
<sharedGui:NotConnectedToNetView/>
</Frame> <!--Bike(s)-->
<StackLayout
IsVisible="{Binding IsBikesListVisible}"
Spacing="0">
</StackLayout> <!--Hint for Outdated Data.-->
<sharedGui:HintForRefreshingPageView/>
<ListView
Grid.Row="1"
x:Name="BikesAtStationListView"
SelectionMode="None"
SelectedItem="{Binding SelectedBike}"
IsEnabled="{Binding IsIdle}"
HasUnevenRows="True"
SeparatorVisibility="None"
ItemTemplate="{StaticResource bikeTemplateSelector}"
IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"/>
</StackLayout>
</StackLayout>
<!--No Bikes-->
<Label
Grid.Row="1"
Margin="20"
IsVisible="{Binding IsNoBikesAtStationVisible}"
Text="{Binding NoBikesAtStationText}"/>
<!--Info at End of Page-->
<StackLayout
Grid.Row="2"
Orientation="Vertical"
Spacing="0"
Padding="20,0,20,0">
<!--Info text-->
<Label
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
TextColor="DimGray"
Padding="5"
HorizontalOptions="CenterAndExpand">
<Label.Triggers>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText.Length}" Value="0">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText}" Value="Offline.">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
</Label.Triggers>
</Label>
<!--Login-->
<StackLayout Spacing="0">
<StackLayout.Triggers>
<DataTrigger TargetType="StackLayout"
Binding="{Binding IsLoginRequiredHintVisible}"
Value="false">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
</StackLayout.Triggers>
<!--Line-->
<BoxView
HeightRequest="1"
WidthRequest="400"
HorizontalOptions="Center"
IsVisible="{Binding IsLoginRequiredHintVisible}"
Color="DimGray" />
<!--Login required-->
<Label
IsVisible="{Binding IsLoginRequiredHintVisible}"
TextType="Html"
TextColor="DimGray"
Text="{Binding LoginRequiredHintText}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding LoginRequiredHintClickedCommand}"/>
</Label.GestureRecognizers>
</Label>
</StackLayout>
</StackLayout>
</Grid>
<!--While process is running--> <!--While process is running-->
<sharedGui:RunningProcessView <sharedGui:RunningProcessView
@ -138,5 +191,5 @@
</Grid> </Grid>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -4,7 +4,8 @@
x:Class="TINK.View.FindBike.FindBikePage" x:Class="TINK.View.FindBike.FindBikePage"
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
xmlns:local_bike="clr-namespace:TINK.View.Bike" xmlns:local_bike="clr-namespace:TINK.View.Bike"
xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"> xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
BackgroundColor="{DynamicResource background-color}">
<Shell.TitleView> <Shell.TitleView>
<Grid ColumnDefinitions="Auto, 1*"> <Grid ColumnDefinitions="Auto, 1*">
@ -23,68 +24,88 @@
<!--Grid for Bike(s) view and Running process in same row--> <!--Grid for Bike(s) view and Running process in same row-->
<Grid> <Grid>
<StackLayout Grid.Row="0">
<!--No Network Connection--> <Grid
<sharedGui:NotConnectedToNetView/> RowDefinitions="1*,Auto"
RowSpacing="0"
Grid.Row="0">
<Frame> <StackLayout
Grid.Row="0"
Spacing="0"
Orientation="Vertical">
<Grid <!--No Network Connection-->
RowDefinitions="1*,32"> <sharedGui:NotConnectedToNetView/>
<!--Search bike--> <!--Search bike-->
<StackLayout> <StackLayout
<Entry BackgroundColor="White"
Placeholder="{x:Static resources:AppResources.PlaceholderFindBike}"
IsVisible="{Binding IsSelectBikeVisible}" IsVisible="{Binding IsSelectBikeVisible}"
MaxLength="10" Padding="20">
CursorPosition="0"
Text="{Binding BikeIdUserInput}"/>
<Button <Entry
Text="{x:Static resources:AppResources.MarkingFindBike}" Placeholder="{x:Static resources:AppResources.PlaceholderFindBike}"
IsEnabled="{Binding IsSelectBikeEnabled}" MaxLength="10"
IsVisible="{Binding IsSelectBikeVisible}" CursorPosition="0"
Command="{Binding OnSelectBikeRequest}"/> Text="{Binding BikeIdUserInput}"/>
<StackLayout <Button
Text="{x:Static resources:AppResources.MarkingFindBike}"
IsEnabled="{Binding IsSelectBikeEnabled}"
Command="{Binding OnSelectBikeRequest}"/>
</StackLayout>
<!-- Bike -->
<StackLayout
Spacing="0" Spacing="0"
IsVisible="{Binding IsBikesListVisible}" IsVisible="{Binding IsBikesListVisible}"
Orientation="Vertical"> Orientation="Vertical">
<!--Hint for Outdated Data.--> <!--Hint for Outdated Data.-->
<sharedGui:HintForRefreshingPageView/> <sharedGui:HintForRefreshingPageView/>
<ListView <ListView
x:Name="FindBikeListView" x:Name="FindBikeListView"
SelectionMode="None" SelectionMode="None"
SelectedItem="{Binding SelectedBike}" SelectedItem="{Binding SelectedBike}"
IsEnabled="{Binding IsIdle}" IsEnabled="{Binding IsIdle}"
HasUnevenRows="True" HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}" SeparatorVisibility="None"
IsPullToRefreshEnabled="True" ItemTemplate="{StaticResource bikeTemplateSelector}"
RefreshCommand="{Binding RefreshCommand}" IsPullToRefreshEnabled="True"
IsRefreshing="{Binding IsRefreshing}"/> RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"/>
</StackLayout> </StackLayout>
</StackLayout> </StackLayout>
<!--Info text--> <!--Info text-->
<Label <Label
Grid.Row="1" Grid.Row="1"
Text="{Binding StatusInfoText}" Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}" IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small" FontSize="Small"
HorizontalOptions="CenterAndExpand" Padding="5"
VerticalOptions="CenterAndExpand"/> TextColor="DimGray"
HorizontalOptions="CenterAndExpand">
<Label.Triggers>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText.Length}" Value="0">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText}" Value="Offline.">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
</Label.Triggers>
</Label>
</Grid> </Grid>
</Frame>
</StackLayout>
<!--While process is running--> <!--While process is running-->
<sharedGui:RunningProcessView <sharedGui:RunningProcessView
@ -94,5 +115,5 @@
</Grid> </Grid>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -7,7 +7,7 @@
x:Class="TINK.View.Map.MapPage" x:Class="TINK.View.Map.MapPage"
xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View" xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
Shell.NavBarIsVisible="{Binding IsNavBarVisible}" Shell.NavBarIsVisible="{Binding IsNavBarVisible}"
BackgroundColor="{DynamicResource Key=primary-back-title-color}"> BackgroundColor="{DynamicResource Key=background-color}">
<Shell.TitleView > <Shell.TitleView >
<Grid ColumnDefinitions="Auto, 1*"> <Grid ColumnDefinitions="Auto, 1*">
@ -17,6 +17,7 @@
</Grid> </Grid>
</Shell.TitleView> </Shell.TitleView>
<ContentPage.Content> <ContentPage.Content>
<!--Grid for Map with Buttons and Running process--> <!--Grid for Map with Buttons and Running process-->
@ -28,21 +29,22 @@
<sharedGui:NotConnectedToNetView/> <sharedGui:NotConnectedToNetView/>
<Grid Grid.Row="1" <Grid
RowDefinitions="3,46,1*,32" RowDefinitions="20,46,1*,Auto"
ColumnDefinitions="1*,Auto,1*" ColumnDefinitions="1*,Auto,1*"
IsEnabled="{Binding IsMapPageEnabled}" RowSpacing="0"
VerticalOptions="FillAndExpand"> IsEnabled="{Binding IsMapPageEnabled}"
VerticalOptions="FillAndExpand">
<!--Map--> <!--Map-->
<maps:Map <maps:Map
Grid.RowSpan="3" Grid.RowSpan="3"
Grid.ColumnSpan="3" Grid.ColumnSpan="3"
WidthRequest="320" WidthRequest="320"
HeightRequest="800" HeightRequest="800"
x:Name="MyMap" x:Name="MyMap"
MyLocationEnabled="True" MyLocationEnabled="True"
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}"/>
@ -51,68 +53,159 @@
<!--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"
IsVisible="{Binding IsNavBarVisible}" IsVisible="{Binding IsNavBarVisible}"
BackgroundColor="{DynamicResource secondary-back-title-color}"> BackgroundColor="{DynamicResource secondary-back-title-color}">
<StackLayout <StackLayout
Orientation="Horizontal" Orientation="Horizontal"
Margin="0" Margin="0"
Padding="0"> Padding="0">
<Button <Button
x:Name="KonradButton" x:Name="KonradButton"
AutomationId ="FilterKonrad_button" AutomationId ="FilterKonrad_button"
Text="{x:Static resources:AppResources.MarkingCityBike}" Text="{x:Static resources:AppResources.MarkingCityBike}"
Command="{Binding OnToggleTinkToKonrad}" Command="{Binding OnToggleTinkToKonrad}"
IsVisible="{Binding IsToggleVisible}" IsVisible="{Binding IsToggleVisible}"
BackgroundColor="{Binding KonradColor}" BackgroundColor="{Binding KonradColor}"
BorderColor="{Binding KonradColor}" BorderColor="{Binding KonradColor}"
BorderWidth="0" BorderWidth="0"
VerticalOptions="Center" VerticalOptions="Center"
HorizontalOptions="Center" HorizontalOptions="Center"
WidthRequest="94" WidthRequest="94"
HeightRequest="40" HeightRequest="40"
BorderRadius="10" CornerRadius="10"
Margin="3,0,0,0" Margin="3,0,0,0"
FontSize="Small" FontSize="Small"
FontAttributes="Bold" FontAttributes="Bold"
TextColor="{Binding NoKonradColor}"> TextColor="{Binding NoKonradColor}">
</Button> </Button>
<Button <Button
x:Name="TINKButton" x:Name="TINKButton"
AutomationId ="FilterTINK_button" AutomationId ="FilterTINK_button"
Text="{x:Static resources:AppResources.MarkingCargoBike}" Text="{x:Static resources:AppResources.MarkingCargoBike}"
Command="{Binding OnToggleKonradToTink}" Command="{Binding OnToggleKonradToTink}"
IsVisible="{Binding IsToggleVisible}" IsVisible="{Binding IsToggleVisible}"
BackgroundColor="{Binding TinkColor}" BackgroundColor="{Binding TinkColor}"
BorderColor="{Binding TinkColor}" BorderColor="{Binding TinkColor}"
BorderWidth="0" BorderWidth="0"
VerticalOptions="Center" VerticalOptions="Center"
HorizontalOptions="Center" HorizontalOptions="Center"
WidthRequest="94" WidthRequest="94"
HeightRequest="40" HeightRequest="40"
BorderRadius="10" CornerRadius="10"
Margin="0,0,3,0" Margin="0,0,3,0"
FontSize="Small" FontSize="Small"
FontAttributes="Bold" FontAttributes="Bold"
TextColor="{Binding NoTinkColor}"> TextColor="{Binding NoTinkColor}">
</Button> </Button>
</StackLayout> </StackLayout>
</Frame> </Frame>
<!--MyBikes-->
<Frame
Grid.Row="2"
Grid.Column="0"
Grid.ColumnSpan="3"
Margin="0,0,0,20"
Padding="0"
BackgroundColor="White"
HasShadow="True"
VerticalOptions="End"
HorizontalOptions="CenterAndExpand"
BorderColor="{DynamicResource primary-back-title-color}"
CornerRadius="10">
<Frame.Triggers>
<DataTrigger
TargetType="Frame"
Binding="{Binding Path=MyBikesCountText.Length}" Value="0">
<Setter Property="IsVisible" Value="false" />
</DataTrigger>
</Frame.Triggers>
<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnMyBikesButtonClicked}" />
</Frame.GestureRecognizers>
<Grid
RowDefinitions="18,Auto,1*"
ColumnDefinitions="Auto"
RowSpacing="0">
<Image
Grid.Row="1"
Margin="-5">
<Image.Source>
<FontImageSource
Glyph="{StaticResource IconMyBikes}"
Color="DimGray" FontFamily="FA-S"/>
</Image.Source>
</Image>
<BoxView
Grid.Row="0"
Grid.RowSpan="2"
BackgroundColor="{DynamicResource primary-back-title-color}"
WidthRequest="20"
HeightRequest="20"
CornerRadius="10"
HorizontalOptions="End"
VerticalOptions="Start"
Margin="5"/>
<Frame
Grid.Row="0"
Grid.RowSpan="2"
BackgroundColor="{DynamicResource primary-back-title-color}"
WidthRequest="20"
HeightRequest="20"
CornerRadius="50"
HasShadow="False"
HorizontalOptions="End"
VerticalOptions="Start"
Padding="0"
Margin="5">
<Label
Text="{Binding MyBikesCountText}"
FontSize="Medium"
FontAttributes="Bold"
VerticalOptions="Center"
HorizontalOptions="Center"
TextColor="White"
Padding="0"
Margin="-10"/>
</Frame>
<Label
Grid.Row="2"
Text="{x:Static resources:AppResources.MarkingMyBikes}"
FontSize="Micro"
TextColor="DimGray"
VerticalOptions="Center"
Margin="10,0,10,5"
Padding="0"/>
</Grid>
</Frame>
<!--Info text--> <!--Info text-->
<Label <Label
Grid.Row="3" Grid.Row="3"
Grid.ColumnSpan="3" Grid.ColumnSpan="3"
Text="{Binding StatusInfoText}" Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}" IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
TextColor="White" FontSize="Small"
FontSize="Small" TextColor="DimGray"
HorizontalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
VerticalOptions="CenterAndExpand"/> <Label.Triggers>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText.Length}" Value="0">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText}" Value="Offline.">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
</Label.Triggers>
</Label>
</Grid> </Grid>
@ -122,9 +215,8 @@
<sharedGui:RunningProcessView <sharedGui:RunningProcessView
IsVisible="{Binding IsProcessWithRunningProcessView}" IsVisible="{Binding IsProcessWithRunningProcessView}"
Grid.Row="0"/> Grid.Row="0"/>
</Grid> </Grid>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

View file

@ -175,16 +175,6 @@ namespace TINK.View.Map
return; return;
} }
try
{
ApplyCustomiOSStyling();
}
catch (Exception exception)
{
// Continue because styling is not essential.
Log.ForContext<MapPage>().Error("IOS specific styling of map page failed. {Exception}", exception);
}
try try
{ {
base.OnAppearing(); base.OnAppearing();
@ -250,22 +240,6 @@ namespace TINK.View.Map
Navigation); Navigation);
} }
/// <summary>
/// Applies iOS specific styling to branded Buttons.
/// </summary>
private void ApplyCustomiOSStyling()
{
if (Device.RuntimePlatform == Device.iOS)
{
TINKButton.BackgroundColor = Color.LightGray;
TINKButton.BorderColor = Color.Black;
TINKButton.Margin = new Thickness(10, 10, 10, 10);
KonradButton.BackgroundColor = Color.LightGray;
KonradButton.BorderColor = Color.Black;
KonradButton.Margin = new Thickness(10, 10, 10, 10);
}
}
/// <summary> /// <summary>
/// Invoked when pages is closed/ hidden. /// Invoked when pages is closed/ hidden.
/// Stops update process. /// Stops update process.

View file

@ -6,7 +6,9 @@
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View" xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
xmlns:local_bike="clr-namespace:TINK.View.Bike" xmlns:local_bike="clr-namespace:TINK.View.Bike"
Shell.FlyoutBehavior="{Binding FlyoutBehavior}"> BackgroundColor="{DynamicResource background-color}"
Shell.FlyoutBehavior="{Binding FlyoutBehavior}"
>
<Shell.TitleView> <Shell.TitleView>
<Grid ColumnDefinitions="Auto, 1*"> <Grid ColumnDefinitions="Auto, 1*">
@ -16,6 +18,7 @@
</Grid> </Grid>
</Shell.TitleView> </Shell.TitleView>
<ContentPage.Resources> <ContentPage.Resources>
<ResourceDictionary> <ResourceDictionary>
<local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/> <local_bike:BikeViewCellTemplateSelector x:Key="bikeTemplateSelector"/>
@ -27,59 +30,75 @@
<!--Grid for Bike(s) view and Running process in same row--> <!--Grid for Bike(s) view and Running process in same row-->
<Grid> <Grid>
<StackLayout Grid.Row="0"> <!--Bike(s) view-->
<Grid
RowDefinitions="1*,Auto"
RowSpacing="0"
Grid.Row="0">
<!--No Network Connection--> <StackLayout
<sharedGui:NotConnectedToNetView/> Grid.Row="0"
Spacing="0"
Orientation="Vertical">
<Frame> <!--No Network Connection-->
<sharedGui:NotConnectedToNetView/>
<!--Bike(s) view--> <!--Bike(s)-->
<Grid <StackLayout
RowDefinitions="1*,32">
<!--Bike(s)-->
<StackLayout
Spacing="0" Spacing="0"
IsVisible="{Binding IsBikesListVisible}" IsVisible="{Binding IsBikesListVisible}"
Orientation="Vertical"> Orientation="Vertical">
<!--Hint for Outdated Data.--> <!--Hint for Outdated Data.-->
<sharedGui:HintForRefreshingPageView/> <sharedGui:HintForRefreshingPageView/>
<ListView <ListView
x:Name="MyBikesListView" x:Name="MyBikesListView"
SelectionMode="None" SelectionMode="None"
SelectedItem="{Binding SelectedBike}" SelectedItem="{Binding SelectedBike}"
IsEnabled="{Binding IsIdle}" IsEnabled="{Binding IsIdle}"
HasUnevenRows="True" HasUnevenRows="True"
SeparatorVisibility="None"
ItemTemplate="{StaticResource bikeTemplateSelector}" ItemTemplate="{StaticResource bikeTemplateSelector}"
IsPullToRefreshEnabled="True" IsPullToRefreshEnabled="True"
RefreshCommand="{Binding RefreshCommand}" RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"/> IsRefreshing="{Binding IsRefreshing}"/>
</StackLayout> </StackLayout>
<!--No Bikes--> <!--No Bikes-->
<Label <Label
Grid.Row="0" Margin="20"
IsVisible="{Binding IsNoBikesOccupiedVisible}" IsVisible="{Binding IsNoBikesOccupiedVisible}"
Text="{Binding NoBikesOccupiedText}"/> Text="{Binding NoBikesOccupiedText}"/>
<!--Info text--> </StackLayout>
<Label
<!--Info text-->
<Label
Grid.Row="1" Grid.Row="1"
Text="{Binding StatusInfoText}" Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}" IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small" FontSize="Small"
HorizontalOptions="CenterAndExpand" TextColor="DimGray"
VerticalOptions="CenterAndExpand"/> Padding="5"
HorizontalOptions="CenterAndExpand">
<Label.Triggers>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText.Length}" Value="0">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText}" Value="Offline.">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
</Label.Triggers>
</Label>
</Grid> </Grid>
</Frame>
</StackLayout>
<!--While process is running--> <!--While process is running-->
<sharedGui:RunningProcessView <sharedGui:RunningProcessView
@ -89,5 +108,5 @@
</Grid> </Grid>
</ContentPage.Content> </ContentPage.Content>
</ContentPage> </ContentPage>

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.360" android:versionCode="360"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="internalOnly" package="com.hauffware.sharee" android:versionName="3.0.361" android:versionCode="361">
<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 -->

View file

@ -14,7 +14,7 @@ namespace TINK.Droid
{ {
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.0.0.73")] [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.2.0.93")]
public partial class Resource public partial class Resource
{ {

View file

@ -56,8 +56,8 @@
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>sharee.bike</string> <string>sharee.bike</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>360</string> <string>361</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.360</string> <string>3.0.361</string>
</dict> </dict>
</plist> </plist>

View file

@ -7,7 +7,7 @@
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View" xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
Shell.FlyoutBehavior="Disabled" Shell.FlyoutBehavior="Disabled"
BackgroundColor="#f6f6f6" BackgroundColor="{DynamicResource background-color}"
Shell.NavBarIsVisible="{Binding IsIdle}"> Shell.NavBarIsVisible="{Binding IsIdle}">
<Shell.TitleView> <Shell.TitleView>
@ -28,9 +28,11 @@
<!--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 for Content --> <!-- Grid for Content -->
<Grid Grid.Row="0" <Grid
RowDefinitions="Auto,1*,Auto"> Grid.Row="0"
RowSpacing="0"
RowDefinitions="Auto,1*,Auto">
<StackLayout <StackLayout
Grid.Row="0" Grid.Row="0"
Spacing="0" Spacing="0"
@ -38,22 +40,46 @@
<!--Station--> <!--Station-->
<StackLayout <StackLayout
BackgroundColor="{DynamicResource primary-back-title-color}"> BackgroundColor="{DynamicResource primary-back-title-color}"
IsVisible="{Binding IsIdle}"
Padding="20,0,20,0">
<!--Line--> <!--Line-->
<BoxView <BoxView
HeightRequest="1" HeightRequest="1"
WidthRequest="260" WidthRequest="400"
HorizontalOptions="Center" HorizontalOptions="Center"
Color="White"/> Color="White"/>
<!--Title--> <Grid
<Label ColumnDefinitions="Auto,1*"
HorizontalOptions="Center" RowDefinitions="Auto"
FontAttributes="Bold" Padding="0,0,0,5">
Padding="10,0,10,10"
TextColor="White" <!--Station id-->
Text="{Binding StationDetailText}"/> <Label
Grid.Column="0"
Grid.Row="0"
FontSize="Small"
HorizontalOptions="Start"
TextColor="White"
Text="{Binding StationDetailText}"/>
<!--Contact to operator-->
<Label
Grid.Column="1"
Grid.Row="0"
TextType="Html"
FontSize="Small"
HorizontalOptions="End"
TextColor="White"
Text="{Binding ContactSupportHintText}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ContactSupportClickedCommand}"/>
</Label.GestureRecognizers>
</Label>
</Grid>
</StackLayout> </StackLayout>
@ -68,73 +94,89 @@
<!--Hint for Outdated Data.--> <!--Hint for Outdated Data.-->
<sharedGui:HintForRefreshingPageView/> <sharedGui:HintForRefreshingPageView/>
<ListView Grid.Row="1" <ListView
x:Name="BikesAtStationListView" Grid.Row="1"
SelectionMode="None" x:Name="BikesAtStationListView"
SelectedItem="{Binding SelectedBike}" SelectionMode="None"
IsEnabled="{Binding IsIdle}" SelectedItem="{Binding SelectedBike}"
HasUnevenRows="True" IsEnabled="{Binding IsIdle}"
SeparatorVisibility="None" HasUnevenRows="True"
ItemTemplate="{StaticResource bikeTemplateSelector}" SeparatorVisibility="None"
IsPullToRefreshEnabled="True" ItemTemplate="{StaticResource bikeTemplateSelector}"
RefreshCommand="{Binding RefreshCommand}" IsPullToRefreshEnabled="True"
IsRefreshing="{Binding IsRefreshing}"/> RefreshCommand="{Binding RefreshCommand}"
IsRefreshing="{Binding IsRefreshing}"/>
</StackLayout> </StackLayout>
</StackLayout> </StackLayout>
<!--No Bikes--> <!--No Bikes-->
<Label Grid.Row="1" Padding="10" <Label
IsVisible="{Binding IsNoBikesAtStationVisible}" Grid.Row="1"
Text="{Binding NoBikesAtStationText}"/> Margin="20"
IsVisible="{Binding IsNoBikesAtStationVisible}"
Text="{Binding NoBikesAtStationText}"/>
<!--Info at End of Page-->
<StackLayout <StackLayout
Grid.Row="2" Grid.Row="2"
Orientation="Vertical" Orientation="Vertical"
BackgroundColor="{DynamicResource primary-back-title-color}" Spacing="0"
Padding="0,0,0,10"> Padding="20,0,20,0">
<!--Info text--> <!--Info text-->
<Label <Label
Text="{Binding StatusInfoText}" Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}" IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small" FontSize="Small"
Padding="10,5,10,0" TextColor="DimGray"
TextColor="White" Padding="5"
HorizontalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand">
VerticalOptions="CenterAndExpand"/> <Label.Triggers>
<DataTrigger
<!-- Contact and Login at end of page--> TargetType="Label"
<!--Line--> Binding="{Binding Path=StatusInfoText.Length}" Value="0">
<BoxView <Setter Property="HeightRequest" Value="0" />
HeightRequest="1" </DataTrigger>
WidthRequest="260" <DataTrigger
HorizontalOptions="Center" TargetType="Label"
Color="White"/> Binding="{Binding Path=StatusInfoText}" Value="Offline.">
<Setter Property="HeightRequest" Value="0" />
<!--Contact to operator--> </DataTrigger>
<Label </Label.Triggers>
TextType="Html"
Padding="10,5,10,0"
TextColor="White"
Text="{Binding ContactSupportHintText}">
<Label.GestureRecognizers>
<TapGestureRecognizer Command="{Binding ContactSupportClickedCommand}"/>
</Label.GestureRecognizers>
</Label> </Label>
<!--Login required--> <!--Login-->
<Label <StackLayout Spacing="0">
<StackLayout.Triggers>
<DataTrigger TargetType="StackLayout"
Binding="{Binding IsLoginRequiredHintVisible}"
Value="false">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
</StackLayout.Triggers>
<!--Line-->
<BoxView
HeightRequest="1"
WidthRequest="400"
HorizontalOptions="Center"
IsVisible="{Binding IsLoginRequiredHintVisible}"
Color="DimGray" />
<!--Login required-->
<Label
IsVisible="{Binding IsLoginRequiredHintVisible}" IsVisible="{Binding IsLoginRequiredHintVisible}"
TextType="Html" TextType="Html"
Padding="10,5,10,0" TextColor="DimGray"
TextColor="White"
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>
</StackLayout> </StackLayout>

View file

@ -19,8 +19,9 @@
<!--Grid for Map with Buttons and Running process--> <!--Grid for Map with Buttons and Running process-->
<Grid <Grid
RowDefinitions="3,46,1*,32" RowDefinitions="3,46,1*,Auto"
ColumnDefinitions="1*,Auto,1*" ColumnDefinitions="1*,Auto,1*"
RowSpacing="0"
IsEnabled="{Binding IsMapPageEnabled}" IsEnabled="{Binding IsMapPageEnabled}"
VerticalOptions="FillAndExpand"> VerticalOptions="FillAndExpand">
@ -114,14 +115,22 @@
<!--Info text--> <!--Info text-->
<Label <Label
Grid.Row="3" Grid.Row="3"
Grid.ColumnSpan="3" Grid.ColumnSpan="3"
Text="{Binding StatusInfoText}" Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}" IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
TextColor="White" FontSize="Small"
FontSize="Small" Padding="5"
HorizontalOptions="CenterAndExpand" TextColor="DimGray"
VerticalOptions="CenterAndExpand"/> HorizontalOptions="CenterAndExpand">
<Label.Triggers>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText.Length}" Value="0">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
</Label.Triggers>
</Label>
<!--While process is running--> <!--While process is running-->
<sharedGui:RunningProcessView <sharedGui:RunningProcessView

View file

@ -6,7 +6,7 @@
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
xmlns:local_bike="clr-namespace:TINK.View.Bike" xmlns:local_bike="clr-namespace:TINK.View.Bike"
xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View" xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
BackgroundColor="#f6f6f6"> BackgroundColor="{DynamicResource background-color}">
<Shell.TitleView> <Shell.TitleView>
<Grid ColumnDefinitions="Auto, 1*"> <Grid ColumnDefinitions="Auto, 1*">
@ -28,6 +28,7 @@
<Grid <Grid
RowDefinitions="1*,Auto" RowDefinitions="1*,Auto"
RowSpacing="0"
Grid.Row="0"> Grid.Row="0">
<StackLayout <StackLayout
@ -42,7 +43,7 @@
<StackLayout <StackLayout
BackgroundColor="White" BackgroundColor="White"
IsVisible="{Binding IsSelectBikeVisible}" IsVisible="{Binding IsSelectBikeVisible}"
Padding="10"> Padding="20">
<Entry <Entry
Placeholder="{x:Static resources:AppResources.PlaceholderFindBike}" Placeholder="{x:Static resources:AppResources.PlaceholderFindBike}"
@ -83,19 +84,27 @@
</StackLayout> </StackLayout>
<!--Info text--> <!--Info text-->
<StackLayout <Label
BackgroundColor="#f6f6f6" Grid.Row="1"
Padding="10,5,10,10"
Grid.Row="1">
<Label
Text="{Binding StatusInfoText}" Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}" IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small" FontSize="Small"
HorizontalOptions="CenterAndExpand" Padding="5"
VerticalOptions="CenterAndExpand"/> TextColor="DimGray"
HorizontalOptions="CenterAndExpand">
</StackLayout> <Label.Triggers>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText.Length}" Value="0">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText}" Value="Offline.">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
</Label.Triggers>
</Label>
</Grid> </Grid>

View file

@ -7,7 +7,7 @@
x:Class="TINK.View.Map.MapPage" x:Class="TINK.View.Map.MapPage"
xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View" xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
Shell.NavBarIsVisible="{Binding IsNavBarVisible}" Shell.NavBarIsVisible="{Binding IsNavBarVisible}"
BackgroundColor="{DynamicResource Key=primary-back-title-color}"> BackgroundColor="{DynamicResource Key=background-color}">
<Shell.TitleView > <Shell.TitleView >
<Grid ColumnDefinitions="Auto, 1*"> <Grid ColumnDefinitions="Auto, 1*">
@ -28,8 +28,9 @@
<sharedGui:NotConnectedToNetView/> <sharedGui:NotConnectedToNetView/>
<Grid <Grid
RowDefinitions="3,46,1*,32" RowDefinitions="20,46,1*,Auto"
ColumnDefinitions="1*,Auto,1*" ColumnDefinitions="1*,Auto,1*"
RowSpacing="0"
IsEnabled="{Binding IsMapPageEnabled}" IsEnabled="{Binding IsMapPageEnabled}"
VerticalOptions="FillAndExpand"> VerticalOptions="FillAndExpand">
@ -49,7 +50,7 @@
</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"
@ -57,11 +58,11 @@
Padding="0" Padding="0"
IsVisible="{Binding IsNavBarVisible}" IsVisible="{Binding IsNavBarVisible}"
BackgroundColor="{DynamicResource secondary-back-title-color}"> BackgroundColor="{DynamicResource secondary-back-title-color}">
<StackLayout <StackLayout
Orientation="Horizontal" Orientation="Horizontal"
Margin="0" Margin="0"
Padding="0"> Padding="0">
<Button <Button
x:Name="KonradButton" x:Name="KonradButton"
AutomationId ="FilterKonrad_button" AutomationId ="FilterKonrad_button"
Text="{x:Static resources:AppResources.MarkingCityBike}" Text="{x:Static resources:AppResources.MarkingCityBike}"
@ -74,13 +75,13 @@
HorizontalOptions="Center" HorizontalOptions="Center"
WidthRequest="94" WidthRequest="94"
HeightRequest="40" HeightRequest="40"
BorderRadius="10" CornerRadius="10"
Margin="3,0,0,0" Margin="3,0,0,0"
FontSize="Small" FontSize="Small"
FontAttributes="Bold" FontAttributes="Bold"
TextColor="{Binding NoKonradColor}"> TextColor="{Binding NoKonradColor}">
</Button> </Button>
<Button <Button
x:Name="TINKButton" x:Name="TINKButton"
AutomationId ="FilterTINK_button" AutomationId ="FilterTINK_button"
Text="{x:Static resources:AppResources.MarkingCargoBike}" Text="{x:Static resources:AppResources.MarkingCargoBike}"
@ -93,27 +94,118 @@
HorizontalOptions="Center" HorizontalOptions="Center"
WidthRequest="94" WidthRequest="94"
HeightRequest="40" HeightRequest="40"
BorderRadius="10" CornerRadius="10"
Margin="0,0,3,0" Margin="0,0,3,0"
FontSize="Small" FontSize="Small"
FontAttributes="Bold" FontAttributes="Bold"
TextColor="{Binding NoTinkColor}"> TextColor="{Binding NoTinkColor}">
</Button> </Button>
</StackLayout> </StackLayout>
</Frame> </Frame>
<!--Info text--> <!--MyBikes-->
<Label <Frame
Grid.Row="3" Grid.Row="2"
Grid.ColumnSpan="3" Grid.Column="0"
Text="{Binding StatusInfoText}" Grid.ColumnSpan="3"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}" Margin="0,0,0,20"
TextColor="White" Padding="0"
FontSize="Small" BackgroundColor="White"
HorizontalOptions="CenterAndExpand" HasShadow="True"
VerticalOptions="CenterAndExpand"/> VerticalOptions="End"
HorizontalOptions="CenterAndExpand"
BorderColor="{DynamicResource primary-back-title-color}"
CornerRadius="10">
<Frame.Triggers>
<DataTrigger
TargetType="Frame"
Binding="{Binding Path=MyBikesCountText.Length}" Value="0">
<Setter Property="IsVisible" Value="false" />
</DataTrigger>
</Frame.Triggers>
<Frame.GestureRecognizers>
<TapGestureRecognizer Command="{Binding OnMyBikesButtonClicked}" />
</Frame.GestureRecognizers>
<Grid
RowDefinitions="18,Auto,1*"
ColumnDefinitions="Auto"
RowSpacing="0">
<Image
Grid.Row="1"
Margin="-5">
<Image.Source>
<FontImageSource
Glyph="{StaticResource IconMyBikes}"
Color="DimGray" FontFamily="FA-S"/>
</Image.Source>
</Image>
<BoxView
Grid.Row="0"
Grid.RowSpan="2"
BackgroundColor="{DynamicResource primary-back-title-color}"
WidthRequest="20"
HeightRequest="20"
CornerRadius="10"
HorizontalOptions="End"
VerticalOptions="Start"
Margin="5"/>
<Frame
Grid.Row="0"
Grid.RowSpan="2"
BackgroundColor="{DynamicResource primary-back-title-color}"
WidthRequest="20"
HeightRequest="20"
CornerRadius="50"
HasShadow="False"
HorizontalOptions="End"
VerticalOptions="Start"
Padding="0"
Margin="5">
<Label
Text="{Binding MyBikesCountText}"
FontSize="Medium"
FontAttributes="Bold"
VerticalOptions="Center"
HorizontalOptions="Center"
TextColor="White"
Padding="0"
Margin="-10"/>
</Frame>
<Label
Grid.Row="2"
Text="{x:Static resources:AppResources.MarkingMyBikes}"
FontSize="Micro"
TextColor="DimGray"
VerticalOptions="Center"
Margin="10,0,10,5"
Padding="0"/>
</Grid>
</Frame>
</Grid> <!--Info text-->
<Label
Grid.Row="3"
Grid.ColumnSpan="3"
Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small"
TextColor="DimGray"
HorizontalOptions="CenterAndExpand">
<Label.Triggers>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText.Length}" Value="0">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText}" Value="Offline.">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
</Label.Triggers>
</Label>
</Grid>
</StackLayout> </StackLayout>

View file

@ -175,16 +175,6 @@ namespace TINK.View.Map
return; return;
} }
try
{
ApplyCustomiOSStyling();
}
catch (Exception exception)
{
// Continue because styling is not essential.
Log.ForContext<MapPage>().Error("IOS specific styling of map page failed. {Exception}", exception);
}
try try
{ {
base.OnAppearing(); base.OnAppearing();
@ -250,22 +240,6 @@ namespace TINK.View.Map
Navigation); Navigation);
} }
/// <summary>
/// Applies iOS specific styling to branded Buttons.
/// </summary>
private void ApplyCustomiOSStyling()
{
if (Device.RuntimePlatform == Device.iOS)
{
TINKButton.BackgroundColor = Color.LightGray;
TINKButton.BorderColor = Color.Black;
TINKButton.Margin = new Thickness(10, 10, 10, 10);
KonradButton.BackgroundColor = Color.LightGray;
KonradButton.BorderColor = Color.Black;
KonradButton.Margin = new Thickness(10, 10, 10, 10);
}
}
/// <summary> /// <summary>
/// Invoked when pages is closed/ hidden. /// Invoked when pages is closed/ hidden.
/// Stops update process. /// Stops update process.

View file

@ -6,7 +6,7 @@
xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib" xmlns:resources="clr-namespace:TINK.MultilingualResources;assembly=TINKLib"
xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View" xmlns:sharedGui="clr-namespace:ShareeSharedGuiLib.View"
xmlns:local_bike="clr-namespace:TINK.View.Bike" xmlns:local_bike="clr-namespace:TINK.View.Bike"
BackgroundColor="#f6f6f6" BackgroundColor="{DynamicResource background-color}"
Shell.FlyoutBehavior="{Binding FlyoutBehavior}"> Shell.FlyoutBehavior="{Binding FlyoutBehavior}">
<Shell.TitleView> <Shell.TitleView>
@ -30,6 +30,7 @@
<!--Bike(s) view--> <!--Bike(s) view-->
<Grid <Grid
RowDefinitions="1*,Auto" RowDefinitions="1*,Auto"
RowSpacing="0"
Grid.Row="0"> Grid.Row="0">
<StackLayout <StackLayout
@ -65,26 +66,34 @@
<!--No Bikes--> <!--No Bikes-->
<Label <Label
Padding="10" Margin="20"
IsVisible="{Binding IsNoBikesOccupiedVisible}" IsVisible="{Binding IsNoBikesOccupiedVisible}"
Text="{Binding NoBikesOccupiedText}"/> Text="{Binding NoBikesOccupiedText}"/>
</StackLayout> </StackLayout>
<!--Info text--> <!--Info text-->
<StackLayout <Label
BackgroundColor="#f6f6f6" Grid.Row="1"
Padding="10,5,10,10"
Grid.Row="1">
<Label
Text="{Binding StatusInfoText}" Text="{Binding StatusInfoText}"
IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}" IsVisible="{Binding Path=IsProcessWithRunningProcessView, Converter={StaticResource InvertedBoolConverter}}"
FontSize="Small" FontSize="Small"
HorizontalOptions="CenterAndExpand" TextColor="DimGray"
VerticalOptions="CenterAndExpand"/> Padding="5"
HorizontalOptions="CenterAndExpand">
</StackLayout> <Label.Triggers>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText.Length}" Value="0">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
<DataTrigger
TargetType="Label"
Binding="{Binding Path=StatusInfoText}" Value="Offline.">
<Setter Property="HeightRequest" Value="0" />
</DataTrigger>
</Label.Triggers>
</Label>
</Grid> </Grid>

View file

@ -676,6 +676,11 @@ namespace TINK.Model
new Version(3, 0, 360), new Version(3, 0, 360),
AppResources.ChangeLog_3_0_358_MK_SB, AppResources.ChangeLog_3_0_358_MK_SB,
new List<AppFlavor> { AppFlavor.MeinKonrad, AppFlavor.ShareeBike } new List<AppFlavor> { AppFlavor.MeinKonrad, AppFlavor.ShareeBike }
},
{
new Version(3, 0, 361),
AppResources.ChangeLog_3_0_361_MK_SB,
new List<AppFlavor> { AppFlavor.MeinKonrad, AppFlavor.ShareeBike }
}, },
}; };

View file

@ -757,6 +757,15 @@ namespace TINK.MultilingualResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to If you have reserved or rented a bike, this will now be shown to you as an icon on the map page. Clicking on it will take you directly to the &apos;My bikes&apos; page. We have also made small design changes..
/// </summary>
public static string ChangeLog_3_0_361_MK_SB {
get {
return ResourceManager.GetString("ChangeLog_3_0_361_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>
@ -1873,7 +1882,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Station id: {0}. /// Looks up a localized string similar to ID: {0}.
/// </summary> /// </summary>
public static string MarkingBikesAtStationStationId { public static string MarkingBikesAtStationStationId {
get { get {
@ -1945,7 +1954,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to &lt;font color=&quot;blue&quot;&gt;&lt;u&gt;Contact&lt;/u&gt;&lt;/font&gt; {0}.. /// Looks up a localized string similar to &lt;u&gt;Contact&lt;/u&gt; {0}..
/// </summary> /// </summary>
public static string MarkingContactSupport { public static string MarkingContactSupport {
get { get {

View file

@ -599,7 +599,7 @@ Layout Anzeige Radnamen und nummern verbessert.</value>
<value>Wahl eines Rads über die Radnummer hinzugefügt.</value> <value>Wahl eines Rads über die Radnummer hinzugefügt.</value>
</data> </data>
<data name="MarkingContactSupport" xml:space="preserve"> <data name="MarkingContactSupport" xml:space="preserve">
<value>{0} &lt;font color="blue"&gt;&lt;u&gt;kontaktieren&lt;/u&gt;&lt;/font&gt;.</value> <value>{0} &lt;u&gt;kontaktieren&lt;/u&gt;.</value>
</data> </data>
<data name="MarkingLoginRequiredToRerserve" xml:space="preserve"> <data name="MarkingLoginRequiredToRerserve" xml:space="preserve">
<value>Bitte Anmelden um Fahrräder zu reservieren! &lt;font color="blue"&gt;&lt;u&gt;Hier&lt;/u&gt;&lt;/font&gt; tippen, um auf Anmeldeseite zu wechseln.</value> <value>Bitte Anmelden um Fahrräder zu reservieren! &lt;font color="blue"&gt;&lt;u&gt;Hier&lt;/u&gt;&lt;/font&gt; tippen, um auf Anmeldeseite zu wechseln.</value>
@ -694,7 +694,7 @@ Kleinere Verbesserungen.</value>
<value>Komponenten von Fremdanbietern aktualisiert.</value> <value>Komponenten von Fremdanbietern aktualisiert.</value>
</data> </data>
<data name="MarkingBikesAtStationStationId" xml:space="preserve"> <data name="MarkingBikesAtStationStationId" xml:space="preserve">
<value>Stationskennung: {0}</value> <value>ID: {0}</value>
</data> </data>
<data name="ChangeLog3_0_250" xml:space="preserve"> <data name="ChangeLog3_0_250" xml:space="preserve">
<value>Anzeige Stationskennung. <value>Anzeige Stationskennung.
@ -1140,4 +1140,7 @@ Wenn sich das Schloss weiterhin nicht öffnen lässt, vergewissern Sie sich, das
<value>Neue Funktionen:&lt;ul&gt;&lt;li&gt;Wenn Ihr Gerät nicht mit dem Internet verbunden ist, wird dies nun oben angezeigt.&lt;/li&gt;&lt;li&gt;Sie können jetzt Ihre Fahrradansicht aktualisieren, indem Sie von oben nach unten ziehen. Das ist besonders nützlich, wenn Sie sich wieder mit dem Internet verbunden haben.&lt;/li&gt;&lt;/ul&gt; <value>Neue Funktionen:&lt;ul&gt;&lt;li&gt;Wenn Ihr Gerät nicht mit dem Internet verbunden ist, wird dies nun oben angezeigt.&lt;/li&gt;&lt;li&gt;Sie können jetzt Ihre Fahrradansicht aktualisieren, indem Sie von oben nach unten ziehen. Das ist besonders nützlich, wenn Sie sich wieder mit dem Internet verbunden haben.&lt;/li&gt;&lt;/ul&gt;
&lt;br/&gt;Außerdem:&lt;ul&gt;&lt;li&gt;Software Pakete wurde aktualisiert.&lt;/li&gt;&lt;li&gt;Kleinere Fehlerbehebungen.&lt;/li&gt;&lt;/ul&gt;</value> &lt;br/&gt;Außerdem:&lt;ul&gt;&lt;li&gt;Software Pakete wurde aktualisiert.&lt;/li&gt;&lt;li&gt;Kleinere Fehlerbehebungen.&lt;/li&gt;&lt;/ul&gt;</value>
</data> </data>
<data name="ChangeLog_3_0_361_MK_SB" xml:space="preserve">
<value>Wenn Sie ein Rad reserviert oder gemietet haben, wird dies Ihnen nun auf der Kartenseite als Symbol angezeigt. Ein Klick darauf führt Sie direkt zur Seite 'Meine Räder'. Wir haben außerdem kleine Designänderungen vorgenommen.</value>
</data>
</root> </root>

View file

@ -717,7 +717,7 @@ Layout of bike names and id display improved.</value>
<value>Contact operator?</value> <value>Contact operator?</value>
</data> </data>
<data name="MarkingContactSupport" xml:space="preserve"> <data name="MarkingContactSupport" xml:space="preserve">
<value>&lt;font color="blue"&gt;&lt;u&gt;Contact&lt;/u&gt;&lt;/font&gt; {0}.</value> <value>&lt;u&gt;Contact&lt;/u&gt; {0}.</value>
</data> </data>
<data name="MarkingLoginRequiredToRerserve" xml:space="preserve"> <data name="MarkingLoginRequiredToRerserve" xml:space="preserve">
<value>Please login to reserve bikes! Tap &lt;font color="blue"&gt;&lt;u&gt;here&lt;/u&gt;&lt;/font&gt; to switch to login page.</value> <value>Please login to reserve bikes! Tap &lt;font color="blue"&gt;&lt;u&gt;here&lt;/u&gt;&lt;/font&gt; to switch to login page.</value>
@ -802,7 +802,7 @@ Minor fixes.</value>
<value>Third-party components updated.</value> <value>Third-party components updated.</value>
</data> </data>
<data name="MarkingBikesAtStationStationId" xml:space="preserve"> <data name="MarkingBikesAtStationStationId" xml:space="preserve">
<value>Station id: {0}</value> <value>ID: {0}</value>
</data> </data>
<data name="ChangeLog3_0_250" xml:space="preserve"> <data name="ChangeLog3_0_250" xml:space="preserve">
<value>Station id displayed. <value>Station id displayed.
@ -1230,4 +1230,7 @@ Try it out!</value>
<data name="MarkingNoNetworkConnection" xml:space="preserve"> <data name="MarkingNoNetworkConnection" xml:space="preserve">
<value>Oops, there is no internet connection.</value> <value>Oops, there is no internet connection.</value>
</data> </data>
<data name="ChangeLog_3_0_361_MK_SB" xml:space="preserve">
<value>If you have reserved or rented a bike, this will now be shown to you as an icon on the map page. Clicking on it will take you directly to the 'My bikes' page. We have also made small design changes.</value>
</data>
</root> </root>

View file

@ -802,8 +802,8 @@ Layout Anzeige Radnamen und nummern verbessert.</target>
<target state="translated">Wahl eines Rads über die Radnummer hinzugefügt.</target> <target state="translated">Wahl eines Rads über die Radnummer hinzugefügt.</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingContactSupport" translate="yes" xml:space="preserve"> <trans-unit id="MarkingContactSupport" translate="yes" xml:space="preserve">
<source><bpt id="1">&lt;font color="blue"&gt;</bpt><bpt id="2">&lt;u&gt;</bpt>Contact<ept id="2">&lt;/u&gt;</ept><ept id="1">&lt;/font&gt;</ept> {0}.</source> <source><bpt id="1">&lt;u&gt;</bpt>Contact<ept id="1">&lt;/u&gt;</ept> {0}.</source>
<target state="translated">{0} <bpt id="1">&lt;font color="blue"&gt;</bpt><bpt id="2">&lt;u&gt;</bpt>kontaktieren<ept id="2">&lt;/u&gt;</ept><ept id="1">&lt;/font&gt;</ept>.</target> <target state="translated">{0} <bpt id="1">&lt;u&gt;</bpt>kontaktieren<ept id="1">&lt;/u&gt;</ept>.</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingLoginRequiredToRerserve" translate="yes" xml:space="preserve"> <trans-unit id="MarkingLoginRequiredToRerserve" translate="yes" xml:space="preserve">
<source>Please login to reserve bikes! Tap <bpt id="1">&lt;font color="blue"&gt;</bpt><bpt id="2">&lt;u&gt;</bpt>here<ept id="2">&lt;/u&gt;</ept><ept id="1">&lt;/font&gt;</ept> to switch to login page.</source> <source>Please login to reserve bikes! Tap <bpt id="1">&lt;font color="blue"&gt;</bpt><bpt id="2">&lt;u&gt;</bpt>here<ept id="2">&lt;/u&gt;</ept><ept id="1">&lt;/font&gt;</ept> to switch to login page.</source>
@ -929,8 +929,8 @@ Kleinere Verbesserungen.</target>
<target state="translated">Komponenten von Fremdanbietern aktualisiert.</target> <target state="translated">Komponenten von Fremdanbietern aktualisiert.</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingBikesAtStationStationId" translate="yes" xml:space="preserve"> <trans-unit id="MarkingBikesAtStationStationId" translate="yes" xml:space="preserve">
<source>Station id: {0}</source> <source>ID: {0}</source>
<target state="translated">Stationskennung: {0}</target> <target state="translated">ID: {0}</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_250" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_250" translate="yes" xml:space="preserve">
<source>Station id displayed. <source>Station id displayed.
@ -1562,6 +1562,10 @@ Wenn sich das Schloss weiterhin nicht öffnen lässt, vergewissern Sie sich, das
<target state="translated">Neue Funktionen:<bpt id="1">&lt;ul&gt;</bpt><bpt id="2">&lt;li&gt;</bpt>Wenn Ihr Gerät nicht mit dem Internet verbunden ist, wird dies nun oben angezeigt.<ept id="2">&lt;/li&gt;</ept><bpt id="3">&lt;li&gt;</bpt>Sie können jetzt Ihre Fahrradansicht aktualisieren, indem Sie von oben nach unten ziehen. Das ist besonders nützlich, wenn Sie sich wieder mit dem Internet verbunden haben.<ept id="3">&lt;/li&gt;</ept><ept id="1">&lt;/ul&gt;</ept> <target state="translated">Neue Funktionen:<bpt id="1">&lt;ul&gt;</bpt><bpt id="2">&lt;li&gt;</bpt>Wenn Ihr Gerät nicht mit dem Internet verbunden ist, wird dies nun oben angezeigt.<ept id="2">&lt;/li&gt;</ept><bpt id="3">&lt;li&gt;</bpt>Sie können jetzt Ihre Fahrradansicht aktualisieren, indem Sie von oben nach unten ziehen. Das ist besonders nützlich, wenn Sie sich wieder mit dem Internet verbunden haben.<ept id="3">&lt;/li&gt;</ept><ept id="1">&lt;/ul&gt;</ept>
&lt;br/&gt;Außerdem:<bpt id="4">&lt;ul&gt;</bpt><bpt id="5">&lt;li&gt;</bpt>Software Pakete wurde aktualisiert.<ept id="5">&lt;/li&gt;</ept><bpt id="6">&lt;li&gt;</bpt>Kleinere Fehlerbehebungen.<ept id="6">&lt;/li&gt;</ept><ept id="4">&lt;/ul&gt;</ept></target> &lt;br/&gt;Außerdem:<bpt id="4">&lt;ul&gt;</bpt><bpt id="5">&lt;li&gt;</bpt>Software Pakete wurde aktualisiert.<ept id="5">&lt;/li&gt;</ept><bpt id="6">&lt;li&gt;</bpt>Kleinere Fehlerbehebungen.<ept id="6">&lt;/li&gt;</ept><ept id="4">&lt;/ul&gt;</ept></target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog_3_0_361_MK_SB" translate="yes" xml:space="preserve">
<source>If you have reserved or rented a bike, this will now be shown to you as an icon on the map page. Clicking on it will take you directly to the 'My bikes' page. We have also made small design changes.</source>
<target state="translated">Wenn Sie ein Rad reserviert oder gemietet haben, wird dies Ihnen nun auf der Kartenseite als Symbol angezeigt. Ein Klick darauf führt Sie direkt zur Seite 'Meine Räder'. Wir haben außerdem kleine Designänderungen vorgenommen.</target>
</trans-unit>
</group> </group>
</body> </body>
</file> </file>

View file

@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Connector; using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Repository.Request; using TINK.Repository.Request;
using TINK.Repository.Response; using TINK.Repository.Response;

View file

@ -9,6 +9,9 @@
<!--Secondary color--> <!--Secondary color-->
<Color x:Key="secondary-back-title-color">#FF0020</Color> <Color x:Key="secondary-back-title-color">#FF0020</Color>
<!--Background color-->
<Color x:Key="background-color">#BEBEBE</Color>
<!--Attention color--> <!--Attention color-->
<Color x:Key="attention-color">#06D1B1</Color> <Color x:Key="attention-color">#06D1B1</Color>

View file

@ -6,6 +6,9 @@
<!--Main color--> <!--Main color-->
<Color x:Key="primary-back-title-color">#009899</Color> <Color x:Key="primary-back-title-color">#009899</Color>
<!--Background color-->
<Color x:Key="background-color">#BEBEBE</Color>
<!--Attention color--> <!--Attention color-->
<Color x:Key="attention-color">#FC870D</Color> <Color x:Key="attention-color">#FC870D</Color>

View file

@ -387,6 +387,11 @@ namespace TINK.ViewModel.Bikes
return Exception.GetShortErrorInfoText(IsReportLevelVerbose); return Exception.GetShortErrorInfoText(IsReportLevelVerbose);
} }
if (!IsConnected)
{
return AppResources.ActivityTextConnectionStateOffline;
}
return ActionText ?? string.Empty; return ActionText ?? string.Empty;
} }
} }

View file

@ -27,6 +27,11 @@ using TINK.Repository;
using TINK.Services.Geolocation; using TINK.Services.Geolocation;
using TINK.Model.State; using TINK.Model.State;
using TINK.ViewModel.Bikes; using TINK.ViewModel.Bikes;
using Location = Xamarin.Essentials.Location;
@ -238,31 +243,38 @@ namespace TINK.ViewModel.Map
{ {
Log.ForContext<MapPageViewModel>().Debug($"Starting update of stations pins color for {stationsColorList.Count} stations..."); Log.ForContext<MapPageViewModel>().Debug($"Starting update of stations pins color for {stationsColorList.Count} stations...");
int MyBikesCount = 0;
// Update colors of pins. // Update colors of pins.
for (int pinIndex = 0; pinIndex < stationsColorList.Count; pinIndex++) for (int pinIndex = 0; pinIndex < stationsColorList.Count; pinIndex++)
{ {
var indexPartPrefix = int.TryParse(Pins[pinIndex].Tag.ToString(), out int stationId) var indexPartPrefix = int.TryParse(Pins[pinIndex].Tag.ToString(), out int stationId)
&& stationId <= CUSTOM_ICONS_COUNT && stationId <= CUSTOM_ICONS_COUNT
? $"{stationId}" // there is a station marker with index letter for given station id ? $"{stationId}" // there is a station marker with index letter for given station id
: "Open"; // there is no station marker. Use open marker. : "Open"; // there is no station marker. Use open marker.
var colorPartPrefix = GetRessourceNameColorPart(stationsColorList[pinIndex]); var colorPartPrefix = GetRessourceNameColorPart(stationsColorList[pinIndex]);
if (colorPartPrefix == "Blue" || colorPartPrefix == "LightBlue")
{
MyBikesCount = MyBikesCount + 1;
};
var name = $"{indexPartPrefix.ToString().PadLeft(2, '0')}_{colorPartPrefix}{(DeviceInfo.Platform == DevicePlatform.Android ? ".png" : string.Empty)}"; var name = $"{indexPartPrefix.ToString().PadLeft(2, '0')}_{colorPartPrefix}{(DeviceInfo.Platform == DevicePlatform.Android ? ".png" : string.Empty)}";
try try
{ {
Pins[pinIndex].Icon = BitmapDescriptorFactory.FromBundle(name); Pins[pinIndex].Icon = BitmapDescriptorFactory.FromBundle(name);
} }
catch (Exception excption) catch (Exception excption)
{ {
Log.ForContext<MapPageViewModel>().Error("Station icon {name} can not be loaded. {@excption}.", name, excption); Log.ForContext<MapPageViewModel>().Error("Station icon {name} can not be loaded. {@excption}.", name, excption);
Pins[pinIndex].Label = stationId.ToString(); Pins[pinIndex].Label = stationId.ToString();
Pins[pinIndex].Icon = BitmapDescriptorFactory.DefaultMarker(stationsColorList[pinIndex]); Pins[pinIndex].Icon = BitmapDescriptorFactory.DefaultMarker(stationsColorList[pinIndex]);
} }
Pins[pinIndex].IsVisible = true; Pins[pinIndex].IsVisible = true;
} }
MyBikesCountText = MyBikesCount > 0 ? string.Format(MyBikesCount.ToString()) : string.Empty;
var pinsCount = Pins.Count; var pinsCount = Pins.Count;
for (int pinIndex = stationsColorList.Count; pinIndex < pinsCount; pinIndex++) for (int pinIndex = stationsColorList.Count; pinIndex < pinsCount; pinIndex++)
{ {
@ -273,6 +285,20 @@ namespace TINK.ViewModel.Map
Log.ForContext<MapPageViewModel>().Debug("Update of stations pins color done."); Log.ForContext<MapPageViewModel>().Debug("Update of stations pins color done.");
} }
/// <summary>
/// label for number of reserved/rented bikes;
/// </summary>
private string _myBikesCountText = string.Empty;
public string MyBikesCountText
{
get { return _myBikesCountText; }
set
{
_myBikesCountText = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MyBikesCountText)));
}
}
/// <summary> Gets the color related part of the ressrouce name.</summary> /// <summary> Gets the color related part of the ressrouce name.</summary>
/// <param name="color">Color to get name for.</param> /// <param name="color">Color to get name for.</param>
/// <returns>Resource name.</returns> /// <returns>Resource name.</returns>
@ -340,7 +366,7 @@ namespace TINK.ViewModel.Map
{ {
// Context switch should not be required because code is called from GUI thread // Context switch should not be required because code is called from GUI thread
// but a xf-issue requires call (see issue #594). // but a xf-issue requires call (see issue #594).
TinkApp.PostAction( async (x) => TinkApp.PostAction(async (x) =>
{ {
// Show COPRI message once. // Show COPRI message once.
await ViewService.DisplayAlert( await ViewService.DisplayAlert(
@ -376,11 +402,11 @@ namespace TINK.ViewModel.Map
{ {
var status = await PermissionsService.CheckStatusAsync(); var status = await PermissionsService.CheckStatusAsync();
if (status == Status.Granted) if (status == Status.Granted)
{ {
// Get from smart device // Get from smart device
mapSpan = await GetFromLocationService(status); mapSpan = await GetFromLocationService(status);
}
} }
}
if (mapSpan == null) if (mapSpan == null)
{ {
@ -462,16 +488,16 @@ namespace TINK.ViewModel.Map
{ {
if (Pins.Count > 0 && Pins.Count != stations.Count) if (Pins.Count > 0 && Pins.Count != stations.Count)
{ {
// Either // Either
// - user logged in/ logged out which might lead to more/ less stations beeing available // - user logged in/ logged out which might lead to more/ less stations beeing available
// - new stations were added/ existing ones remove // - new stations were added/ existing ones remove
Pins.Clear(); Pins.Clear();
} }
// Check if there are alreay any pins to the map // Check if there are alreay any pins to the map
// i.e detecte first call of member OnAppearing after construction // i.e detecte first call of member OnAppearing after construction
if (Pins.Count <= 0) if (Pins.Count <= 0)
{ {
Log.ForContext<MapPageViewModel>().Debug($"{(ActiveFilterMap.GetGroup().Any() ? $"Active map filter is {string.Join(",", ActiveFilterMap.GetGroup())}." : "Map filter is off.")}"); Log.ForContext<MapPageViewModel>().Debug($"{(ActiveFilterMap.GetGroup().Any() ? $"Active map filter is {string.Join(",", ActiveFilterMap.GetGroup())}." : "Map filter is off.")}");
// Map was not yet initialized. // Map was not yet initialized.
@ -546,15 +572,15 @@ namespace TINK.ViewModel.Map
AppResources.MessageAnswerYes, AppResources.MessageAnswerYes,
AppResources.MessageAnswerNo); AppResources.MessageAnswerNo);
if (dialogResult) if (dialogResult)
{ {
// User decided to give access to locations permissions. // User decided to give access to locations permissions.
PermissionsService.OpenAppSettings(); PermissionsService.OpenAppSettings();
ActionText = string.Empty; ActionText = string.Empty;
IsProcessWithRunningProcessView = false; IsProcessWithRunningProcessView = false;
IsNavBarVisible = true; IsNavBarVisible = true;
IsMapPageEnabled = true; IsMapPageEnabled = true;
} }
} }
return status; return status;
} }
@ -661,40 +687,40 @@ namespace TINK.ViewModel.Map
/// <param name="selectedStationId">Id of station user clicked on.</param> /// <param name="selectedStationId">Id of station user clicked on.</param>
public async void OnStationClicked(string selectedStationId) public async void OnStationClicked(string selectedStationId)
{ {
try try
{ {
Log.ForContext<MapPageViewModel>().Information($"User taped station {selectedStationId}."); Log.ForContext<MapPageViewModel>().Information($"User taped station {selectedStationId}.");
// Lock action to prevent multiple instances of "BikeAtStation" being opened. // Lock action to prevent multiple instances of "BikeAtStation" being opened.
IsMapPageEnabled = false; IsMapPageEnabled = false;
TinkApp.SelectedStation = TinkApp.Stations.FirstOrDefault(x => x.Id == selectedStationId) TinkApp.SelectedStation = TinkApp.Stations.FirstOrDefault(x => x.Id == selectedStationId)
?? new Station(selectedStationId, new List<string>(), null); // Station might not be in list StationDictinaly because this list is not updatd in background task. ?? new Station(selectedStationId, new List<string>(), null); // Station might not be in list StationDictinaly because this list is not updatd in background task.
#if TRYNOTBACKSTYLE #if TRYNOTBACKSTYLE
m_oNavigation.ShowPage( m_oNavigation.ShowPage(
typeof(BikesAtStationPage), typeof(BikesAtStationPage),
p_strStationName); p_strStationName);
#else #else
{
// Show page.
await ViewService.PushAsync(ViewTypes.BikesAtStation);
IsMapPageEnabled = true;
ActionText = string.Empty;
}
}
catch (Exception exception)
{ {
// Show page.
await ViewService.PushAsync(ViewTypes.BikesAtStation);
IsMapPageEnabled = true; IsMapPageEnabled = true;
ActionText = string.Empty; ActionText = string.Empty;
Log.ForContext<MapPageViewModel>().Error("Fehler beim Öffnen der Ansicht \"Fahrräder an Station\" aufgetreten. {Exception}", exception);
await ViewService.DisplayAlert(
"Fehler",
$"Fehler beim Öffnen der Ansicht \"Fahrräder an Station\" aufgetreten. {exception.Message}",
"OK");
} }
}
catch (Exception exception)
{
IsMapPageEnabled = true;
ActionText = string.Empty;
Log.ForContext<MapPageViewModel>().Error("Fehler beim Öffnen der Ansicht \"Fahrräder an Station\" aufgetreten. {Exception}", exception);
await ViewService.DisplayAlert(
"Fehler",
$"Fehler beim Öffnen der Ansicht \"Fahrräder an Station\" aufgetreten. {exception.Message}",
"OK");
}
#endif #endif
} }
@ -858,11 +884,44 @@ namespace TINK.ViewModel.Map
// An error occurred getting data from copri. // An error occurred getting data from copri.
return Exception.GetShortErrorInfoText(TinkApp.IsReportLevelVerbose); return Exception.GetShortErrorInfoText(TinkApp.IsReportLevelVerbose);
} }
if (!IsConnected)
{
return AppResources.ActivityTextConnectionStateOffline;
}
return ActionText ?? string.Empty; return ActionText ?? string.Empty;
} }
} }
/// <summary> Processes request to view my bikes.</summary>
public System.Windows.Input.ICommand OnMyBikesButtonClicked => new Xamarin.Forms.Command(async () =>
{
try
{
Log.ForContext<MapPageViewModel>().Information($"User clicked on MyBikesButton.");
// Lock action to prevent multiple instances of "BikeAtStation" being opened.
IsMapPageEnabled = false;
// Show page.
await ViewService.PushAsync(ViewTypes.MyBikesPage);
IsMapPageEnabled = true;
ActionText = string.Empty;
}
catch (Exception exception)
{
IsMapPageEnabled = true;
ActionText = string.Empty;
Log.ForContext<MapPageViewModel>().Error("Fehler beim Öffnen der Ansicht \"Meine Räder\" aufgetreten. {Exception}", exception);
await ViewService.DisplayAlert(
"Fehler",
$"Fehler beim Öffnen der Ansicht \"Meine Räder\" aufgetreten. {exception.Message}",
"OK");
}
});
/// <summary> Command object to bind login button to view model.</summary> /// <summary> Command object to bind login button to view model.</summary>
public System.Windows.Input.ICommand OnToggleTinkToKonrad => new Xamarin.Forms.Command(async () => await ToggleTinkToKonrad()); public System.Windows.Input.ICommand OnToggleTinkToKonrad => new Xamarin.Forms.Command(async () => await ToggleTinkToKonrad());

View file

@ -4,7 +4,6 @@ using System.Threading.Tasks;
using TestFramework.Repository; using TestFramework.Repository;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Connector; using TINK.Model.Connector;
using TINK.Model.Device;
using TINK.Model.Services.CopriApi; using TINK.Model.Services.CopriApi;
using TINK.Repository.Request; using TINK.Repository.Request;
using TINK.Repository.Response; using TINK.Repository.Response;

View file

@ -188,7 +188,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
cache.IsBikesAvailableExpired.Returns(true); cache.IsBikesAvailableExpired.Returns(true);
cache.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE))); cache.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE)));
https.GetBikesAvailableAsync().Returns<BikesAvailableResponse>(x => { throw new WebConnectFailureException("Bang...", new Exception()); }); https.GetBikesAvailableAsync().Returns<BikesAvailableResponse>(x => { throw new WebConnectFailureException("Bang...", new System.Exception()); });
var provider = new CopriProviderHttps( var provider = new CopriProviderHttps(
new Uri("http://1.2.3.4"), new Uri("http://1.2.3.4"),
@ -288,7 +288,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
cache.IsBikesOccupiedExpired.Returns(true); cache.IsBikesOccupiedExpired.Returns(true);
cache.GetBikesOccupiedAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED))); cache.GetBikesOccupiedAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED)));
https.GetBikesOccupiedAsync().Returns<BikesReservedOccupiedResponse>(x => { throw new WebConnectFailureException("Bang...", new Exception()); }); https.GetBikesOccupiedAsync().Returns<BikesReservedOccupiedResponse>(x => { throw new WebConnectFailureException("Bang...", new System.Exception()); });
var provider = new CopriProviderHttps( var provider = new CopriProviderHttps(
new Uri("http://1.2.3.4"), new Uri("http://1.2.3.4"),
@ -387,7 +387,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
cache.IsStationsExpired.Returns(true); cache.IsStationsExpired.Returns(true);
cache.GetStationsAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL))); cache.GetStationsAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL)));
https.GetStationsAsync().Returns<StationsAvailableResponse>(x => { throw new WebConnectFailureException("Bang...", new Exception()); }); https.GetStationsAsync().Returns<StationsAvailableResponse>(x => { throw new WebConnectFailureException("Bang...", new System.Exception()); });
var provider = new CopriProviderHttps( var provider = new CopriProviderHttps(
new Uri("http://1.2.3.4"), new Uri("http://1.2.3.4"),
@ -424,7 +424,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
try try
{ {
// Do not add if an excption occurred // Do not add if an excption occurred
provider.AddToCache(new Result<StationsAvailableResponse>(typeof(CopriCallsHttps), JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL), new GeneralData(), new Exception("Bang..."))); provider.AddToCache(new Result<StationsAvailableResponse>(typeof(CopriCallsHttps), JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL), new GeneralData(), new System.Exception("Bang...")));
stations = await provider.GetStations(true); stations = await provider.GetStations(true);
Assert.AreEqual(0, stations.Response.stations.Count); Assert.AreEqual(0, stations.Response.stations.Count);
@ -464,7 +464,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
try try
{ {
// Do not add if an excption occurred // Do not add if an excption occurred
provider.AddToCache(new Result<BikesAvailableResponse>(typeof(CopriCallsHttps), JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE), new GeneralData(), new Exception("Bang..."))); provider.AddToCache(new Result<BikesAvailableResponse>(typeof(CopriCallsHttps), JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE), new GeneralData(), new System.Exception("Bang...")));
bikes = await provider.GetBikesAvailable(true); bikes = await provider.GetBikesAvailable(true);
Assert.AreEqual(0, bikes.Response.bikes.Count); Assert.AreEqual(0, bikes.Response.bikes.Count);
@ -506,7 +506,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
try try
{ {
// Do not add if an excption occurred // Do not add if an excption occurred
provider.AddToCache(new Result<BikesReservedOccupiedResponse>(typeof(CopriCallsHttps), JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED), new GeneralData(), new Exception("Bang..."))); provider.AddToCache(new Result<BikesReservedOccupiedResponse>(typeof(CopriCallsHttps), JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED), new GeneralData(), new System.Exception("Bang...")));
bikes = await provider.GetBikesOccupied(true); bikes = await provider.GetBikesOccupied(true);
Assert.AreEqual(0, bikes.Response.bikes_occupied.Count); Assert.AreEqual(0, bikes.Response.bikes_occupied.Count);

View file

@ -1,4 +1,4 @@
using System; using System;
using NUnit.Framework; using NUnit.Framework;
using Serilog.Events; using Serilog.Events;
using TINK.Model.Services.CopriApi.ServerUris; using TINK.Model.Services.CopriApi.ServerUris;
@ -6,7 +6,7 @@ using TINK.Settings;
using TINK.ViewModel.Map; using TINK.ViewModel.Map;
using TINK.ViewModel.Settings; using TINK.ViewModel.Settings;
namespace TestTINKLib.Fixtures.ObjectTests.Settings namespace TestTINKLib.Fixtures.ObjectTests.SettingsNS
{ {
[TestFixture] [TestFixture]
public class TestSettings public class TestSettings

View file

@ -1,6 +1,7 @@
using System; using System;
using Newtonsoft.Json; using Newtonsoft.Json;
using NUnit.Framework; using NUnit.Framework;
using TestFramework;
using TINK.Model.State; using TINK.Model.State;

View file

@ -1,6 +1,7 @@
using System; using System;
using Newtonsoft.Json; using Newtonsoft.Json;
using NUnit.Framework; using NUnit.Framework;
using TestFramework;
using TINK.Model.State; using TINK.Model.State;

View file

@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NUnit.Framework; using NUnit.Framework;
using Rhino.Mocks;
using TestFramework.Model.Services.Geolocation; using TestFramework.Model.Services.Geolocation;
using TestFramework.Services.BluetoothLock; using TestFramework.Services.BluetoothLock;
using TINK.Model.Bikes.BikeInfoNS.BikeNS; using TINK.Model.Bikes.BikeInfoNS.BikeNS;
@ -42,8 +41,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
null, // viewUpdateManager null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(), NSubstitute.Substitute.For<ISmartDevice>(),
null /* viewService */ , null /* viewService */ ,
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
MockRepository.GenerateStub<IUser>()).GetType()); NSubstitute.Substitute.For<IUser>()).GetType());
// Verify handler for requested bike with state unknown. // Verify handler for requested bike with state unknown.
bike = new BikeInfoMutable( bike = new BikeInfoMutable(
@ -60,8 +59,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
null, // viewUpdateManager null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(), NSubstitute.Substitute.For<ISmartDevice>(),
null /* viewService */, null /* viewService */,
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
MockRepository.GenerateStub<IUser>()).GetType()); NSubstitute.Substitute.For<IUser>()).GetType());
// Verify handler for requested bike with state closed. // Verify handler for requested bike with state closed.
bike = new BikeInfoMutable( bike = new BikeInfoMutable(
@ -79,8 +78,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
null, // viewUpdateManager null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(), NSubstitute.Substitute.For<ISmartDevice>(),
null /* viewService */, null /* viewService */,
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
MockRepository.GenerateStub<IUser>()).GetType()); NSubstitute.Substitute.For<IUser>()).GetType());
// Verify handler for requested bike with state open. // Verify handler for requested bike with state open.
bike = new BikeInfoMutable( bike = new BikeInfoMutable(
@ -98,8 +97,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
null, // viewUpdateManager null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(), NSubstitute.Substitute.For<ISmartDevice>(),
null /* viewService */, null /* viewService */,
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
MockRepository.GenerateStub<IUser>()).GetType()); NSubstitute.Substitute.For<IUser>()).GetType());
// Verify handler for booked bike with state closed. // Verify handler for booked bike with state closed.
bike = new BikeInfoMutable( bike = new BikeInfoMutable(
@ -117,8 +116,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
null, // viewUpdateManager null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(), NSubstitute.Substitute.For<ISmartDevice>(),
null /* viewService */, null /* viewService */,
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
MockRepository.GenerateStub<IUser>()).GetType()); NSubstitute.Substitute.For<IUser>()).GetType());
// Verify handler for booked bike with state open. // Verify handler for booked bike with state open.
bike = new BikeInfoMutable( bike = new BikeInfoMutable(
@ -136,8 +135,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
null, // viewUpdateManager null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(), NSubstitute.Substitute.For<ISmartDevice>(),
null /* viewService */, null /* viewService */,
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
MockRepository.GenerateStub<IUser>()).GetType()); NSubstitute.Substitute.For<IUser>()).GetType());
// Verify handler for booked bike with state unknown. // Verify handler for booked bike with state unknown.
bike = new BikeInfoMutable( bike = new BikeInfoMutable(
@ -155,8 +154,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
null, // viewUpdateManager null, // viewUpdateManager
NSubstitute.Substitute.For<ISmartDevice>(), NSubstitute.Substitute.For<ISmartDevice>(),
null /* viewService */, null /* viewService */,
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
MockRepository.GenerateStub<IUser>()).GetType()); NSubstitute.Substitute.For<IUser>()).GetType());
} }
} }
} }

View file

@ -1,6 +1,5 @@
using System; using System;
using NUnit.Framework; using NUnit.Framework;
using Rhino.Mocks;
using TestFramework.Model.Services.Geolocation; using TestFramework.Model.Services.Geolocation;
using TestFramework.Services.BluetoothLock; using TestFramework.Services.BluetoothLock;
using TINK.Model.Bikes.BikeInfoNS.BC; using TINK.Model.Bikes.BikeInfoNS.BC;
@ -32,9 +31,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
NSubstitute.Substitute.For<ISmartDevice>(), NSubstitute.Substitute.For<ISmartDevice>(),
null, // viewService null, // viewService
new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", LockModel.ILockIt), new Drive(), DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "42"), "My Station Name"), new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", LockModel.ILockIt), new Drive(), DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "42"), "My Station Name"),
MockRepository.GenerateStub<IUser>(), // user NSubstitute.Substitute.For<IUser>(), // user
MockRepository.GenerateStub<IInUseStateInfoProvider>(), NSubstitute.Substitute.For<IInUseStateInfoProvider>(),
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
url => { }).GetType()); // stateInfoProvider url => { }).GetType()); // stateInfoProvider
} }
@ -53,9 +52,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
NSubstitute.Substitute.For<ISmartDevice>(), NSubstitute.Substitute.For<ISmartDevice>(),
null, // viewService null, // viewService
new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, "17", new TINK.Model.Bikes.BikeInfoNS.CopriLock.LockInfo.Builder { State = TINK.Model.Bikes.BikeInfoNS.CopriLock.LockingState.Closed }.Build()), "My Station Name"), new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.CopriLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", LockModel.ILockIt), new Drive(), TINK.Model.Bikes.BikeInfoNS.BC.DataSource.Copri, "17", new TINK.Model.Bikes.BikeInfoNS.CopriLock.LockInfo.Builder { State = TINK.Model.Bikes.BikeInfoNS.CopriLock.LockingState.Closed }.Build()), "My Station Name"),
MockRepository.GenerateStub<IUser>(), // user NSubstitute.Substitute.For<IUser>(), // user
MockRepository.GenerateStub<IInUseStateInfoProvider>(), NSubstitute.Substitute.For<IInUseStateInfoProvider>(),
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
url => { }).GetType()); // stateInfoProvider url => { }).GetType()); // stateInfoProvider
} }
@ -73,9 +72,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
NSubstitute.Substitute.For<ISmartDevice>(), NSubstitute.Substitute.For<ISmartDevice>(),
null, // viewService null, // viewService
new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", TINK.Model.Bikes.BikeInfoNS.BikeNS.LockModel.ILockIt), new Drive(), DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "42"), "My Station Name"), new TINK.Model.Bikes.BikeInfoNS.BC.BikeInfoMutable(new TINK.Model.Bikes.BikeInfoNS.BluetoothLock.BikeInfo(new TINK.Model.Bikes.BikeInfoNS.BikeNS.Bike("42", TINK.Model.Bikes.BikeInfoNS.BikeNS.LockModel.ILockIt), new Drive(), DataSource.Copri, 5200544, new Guid("00000000-0000-0000-0000-000000000001"), "42"), "My Station Name"),
MockRepository.GenerateStub<IUser>(), // user NSubstitute.Substitute.For<IUser>(), // user
MockRepository.GenerateStub<IInUseStateInfoProvider>(), NSubstitute.Substitute.For<IInUseStateInfoProvider>(),
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
url => { }), url => { }),
Is.Null); Is.Null);
} }

View file

@ -1109,7 +1109,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.ViewModel
await bikesAtStation.OnAppearingOrRefresh(); await bikesAtStation.OnAppearingOrRefresh();
//Assert.AreEqual("Offline.", bikesAtStation.StatusInfoText); Assert.AreEqual("Offline.", bikesAtStation.StatusInfoText);
// Verify list of bikes // Verify list of bikes
Assert.AreEqual(2, bikesAtStation.Count); // Count of bikes was 3. There is no more bike with id 26. Assert.AreEqual(2, bikesAtStation.Count); // Count of bikes was 3. There is no more bike with id 26.

View file

@ -1,11 +1,11 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using TINK.Model; using TINK.Model;
using TINK.Model.Connector; using TINK.Model.Connector;
using TINK.ViewModel.Settings; using TINK.ViewModel.Settings;
namespace TestTINKLib.Fixtures.ObjectTests.Settings namespace TestTINKLib.Fixtures.ObjectTests.SettingsNS
{ {
[TestFixture] [TestFixture]
public class TestGroupFilterSettings public class TestGroupFilterSettings
@ -21,4 +21,4 @@ namespace TestTINKLib.Fixtures.ObjectTests.Settings
Assert.AreEqual($"HOM_{FilterHelper.CARGOBIKE}", l_oResult.ToList()[0]); Assert.AreEqual($"HOM_{FilterHelper.CARGOBIKE}", l_oResult.ToList()[0]);
} }
} }
} }

View file

@ -1,8 +1,8 @@
using System; using System;
using NUnit.Framework; using NUnit.Framework;
using TINK.Settings; using TINK.Settings;
namespace TestTINKLib.Fixtures.ObjectTests.Settings namespace TestTINKLib.Fixtures.ObjectTests.SettingsNS
{ {
[TestFixture] [TestFixture]
public class TestPollingParameters public class TestPollingParameters

View file

@ -1,7 +1,8 @@
using System; using System;
using NSubstitute; using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using TINK.Model.Bikes.BikeInfoNS.BC; using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.ViewModel; using TINK.ViewModel;
namespace TestShareeLib.ViewModel namespace TestShareeLib.ViewModel
@ -124,5 +125,76 @@ namespace TestShareeLib.ViewModel
new AggregateException(new Exception("Oh yes"), new Exception("Oh no")).GetErrorMessage(), new AggregateException(new Exception("Oh yes"), new Exception("Oh no")).GetErrorMessage(),
Is.EqualTo("One or more errors occurred.\r\nOh yes\r\nOh no")); Is.EqualTo("One or more errors occurred.\r\nOh yes\r\nOh no"));
} }
[Test]
public void TestGetDisplayName_DefinedTypes()
{
var bike = Substitute.For<IBikeInfoMutable>();
bike.WheelType.Returns(WheelType.Two);
bike.TypeOfBike.Returns(TypeOfBike.City);
bike.Description.Returns("MeinStadtrad");
bike.Id.Returns("22");
Assert.AreEqual(
"MeinStadtrad",
bike.GetDisplayName());
Assert.AreEqual(
"22",
bike.GetDisplayId());
bike = Substitute.For<IBikeInfoMutable>();
bike.WheelType.Returns(WheelType.Two);
bike.TypeOfBike.Returns(TypeOfBike.City);
bike.Id.Returns("22");
bike.IsDemo.Returns(true);
bike.Description.Returns("MeinStadtrad");
Assert.AreEqual(
"MeinStadtrad",
bike.GetDisplayName());
Assert.AreEqual(
"22",
bike.GetDisplayId());
bike = Substitute.For<IBikeInfoMutable>();
bike.WheelType.Returns(WheelType.Trike);
bike.TypeOfBike.Returns(TypeOfBike.Cargo);
bike.Description.Returns("MeinCargoDreiradl");
bike.Id.Returns("22");
Assert.AreEqual(
"MeinCargoDreiradl",
bike.GetDisplayName());
Assert.AreEqual(
"22",
bike.GetDisplayId());
bike = Substitute.For<IBikeInfoMutable>();
bike.WheelType.Returns(WheelType.Two);
bike.TypeOfBike.Returns(TypeOfBike.Cargo);
bike.Description.Returns("MeinCargoALololong");
bike.Id.Returns("22");
Assert.AreEqual(
"MeinCargoALololong",
bike.GetDisplayName());
Assert.AreEqual(
"22",
bike.GetDisplayId());
}
[Test]
public void TestGetDisplayName_UndefinedTypes()
{
var bike = Substitute.For<IBikeInfoMutable>();
bike.WheelType.Returns(WheelType.Mono);
bike.TypeOfBike.Returns(TypeOfBike.Cargo);
bike.Description.Returns("SuperCargo");
bike.Id.Returns("22");
Assert.AreEqual(
"SuperCargo",
bike.GetDisplayName());
Assert.AreEqual(
"22",
bike.GetDisplayId());
}
} }
} }

View file

@ -1,50 +0,0 @@
using NUnit.Framework;
using System;
using TINK.Model.Bike.BluetoothLock;
using TINK.Model.State;
namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
{
[TestFixture]
public class TestBikeInfo
{
/// <summary>
/// Moved to TestShareeLib (.Net Core)
/// </summary>
[Test]
public void TestCtorCopyNull()
{
Assert.Throws<System.ArgumentException>(
() => new BikeInfo(null, null),
"Verify that no unspecific reference not set to... exception is thrown");
Assert.Throws<System.ArgumentException>(
() => new BikeInfo(new TINK.Model.Bike.BC.BikeInfo(12,1), null),
"Verify that no unspecific reference not set to... exception is thrown");
}
[Test]
public void TestCtorAvailable()
{
Assert.AreEqual (12,new BikeInfo(12, 13).Id);
Assert.AreEqual(13, new BikeInfo(12, 13).CurrentStation);
Assert.AreEqual(InUseStateEnum.Disposable, new BikeInfo(12, 13).State.Value);
}
[Test]
public void TestCtorRequested()
{
Assert.AreEqual(12, new BikeInfo(12, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", 13, dateTimeProvider: () => new DateTime(2019, 1, 1)).Id);
Assert.AreEqual(112, new BikeInfo(12, 112, new Guid(), null, null, null, new DateTime(2020,1,1), "a@b", 13, dateTimeProvider: () => new DateTime(2019, 1, 1)).LockInfo.Id);
Assert.AreEqual(InUseStateEnum.Reserved, new BikeInfo(12, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", 13, dateTimeProvider: () => new DateTime(2019, 1, 1)).State.Value);
}
[Test]
public void TestCtorBooked()
{
Assert.AreEqual(12, new BikeInfo(12, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", 13).Id);
Assert.AreEqual(112, new BikeInfo(12, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", 13).LockInfo.Id);
Assert.AreEqual(InUseStateEnum.Booked, new BikeInfo(12, 112, new Guid(), null, null, null, new DateTime(2020, 1, 1), "a@b", 13).State.Value);
}
}
}

View file

@ -1,155 +0,0 @@
using NUnit.Framework;
using System;
using TINK.Model.Bike.BluetoothLock;
namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
{
[TestFixture]
public class TestLockInfo
{
/// <summary>
/// Moved to TestShareeLib (.Net Core)
/// </summary>
[Test]
public void TestCtor()
{
Assert.AreEqual(
LockingState.Unknown,
new LockInfo.Builder { Id = 123 }.Build().State);
Assert.AreEqual(
123,
new LockInfo.Builder { Id = 123 }.Build().Id);
}
[Test]
public void TestEquals()
{
Assert.IsTrue(new LockInfo.Builder {
Id = 2,
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 1, 2 },
UserKey = new byte[] { 7, 2 },
AdminKey = new byte[] { 2, 1 },
State = LockingState.Closed}.Build() == new LockInfo.Builder {
Id = 2,
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 1, 2 },
UserKey = new byte[] { 7, 2 },
AdminKey = new byte[] { 2, 1 },
State = LockingState.Closed
}.Build());
}
[Test]
public void TestEqualsFalse()
{
Assert.IsFalse(new LockInfo.Builder
{
Id = 2,
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 1, 2 },
UserKey = new byte[] { 7, 2 },
AdminKey = new byte[] { 2, 1 },
State = LockingState.Closed
}.Build() == new LockInfo.Builder
{
Id = 3,
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 1, 2 },
UserKey = new byte[] { 7, 2 },
AdminKey = new byte[] { 2, 1 },
State = LockingState.Closed
}.Build());
Assert.IsFalse(new LockInfo.Builder
{
Id = 2,
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 1, 2 },
UserKey = new byte[] { 7, 2 },
AdminKey = new byte[] { 2, 1 },
State = LockingState.Closed
}.Build() == new LockInfo.Builder
{
Id = 2,
Guid = new Guid("1000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 1, 2 },
UserKey = new byte[] { 7, 2 },
AdminKey = new byte[] { 2, 1 },
State = LockingState.Closed
}.Build());
Assert.IsFalse(new LockInfo.Builder
{
Id = 2,
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 1, 2 },
UserKey = new byte[] { 7, 2 },
AdminKey = new byte[] { 2, 1 },
State = LockingState.Closed
}.Build() == new LockInfo.Builder
{
Id = 2,
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 5, 2 },
UserKey = new byte[] { 7, 2 },
AdminKey = new byte[] { 2, 1 },
State = LockingState.Closed
}.Build());
Assert.IsFalse(new LockInfo.Builder
{
Id = 2,
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 1, 2 },
UserKey = new byte[] { 7, 2 },
AdminKey = new byte[] { 2, 1 },
State = LockingState.Closed
}.Build() == new LockInfo.Builder
{
Id = 2,
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 1, 2 },
UserKey = new byte[] { 9, 2 },
AdminKey = new byte[] { 2, 1 },
State = LockingState.Closed
}.Build());
Assert.IsFalse(new LockInfo.Builder
{
Id = 2,
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 1, 2 },
UserKey = new byte[] { 7, 2 },
AdminKey = new byte[] { 2, 1 },
State = LockingState.Closed
}.Build() == new LockInfo.Builder
{
Id = 2,
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 1, 2 },
UserKey = new byte[] { 7, 2 },
AdminKey = new byte[] { 11, 1 },
State = LockingState.Closed
}.Build());
Assert.IsFalse(new LockInfo.Builder
{
Id = 2,
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 1, 2 },
UserKey = new byte[] { 7, 2 },
AdminKey = new byte[] { 2, 1 },
State = LockingState.Closed
}.Build() == new LockInfo.Builder
{
Id = 2,
Guid = new Guid("0000f00d-1212-efde-1523-785fef13d123"),
Seed = new byte[] { 1, 2 },
UserKey = new byte[] { 7, 2 },
AdminKey = new byte[] { 2, 1 },
State = LockingState.Open
}.Build());
}
}
}

View file

@ -1,56 +0,0 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using TINK.Model.Bike.BluetoothLock;
using TINK.Services.BluetoothLock.Tdo;
namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
{
/// <summary>
/// Moved to TestShareeLib (.Net Core)
/// </summary>
[TestFixture]
public class TestLockInfoHelper
{
[Test]
public void TestUpdateById_State()
{
var locksInfo = new List<LockInfo> {
new LockInfo.Builder { Id = 12, Seed = new byte[] { 3, 5 }, UserKey = new byte[] {2, 1 }, State = LockingState.Unknown }.Build(),
new LockInfo.Builder { Id = 14, Seed = new byte[] { 3, 1 }, UserKey = new byte[] {2, 7 }, State = LockingState.Open }.Build(),
new LockInfo.Builder { Id = 3, Seed = new byte[] { 1, 5 }, UserKey = new byte[] {2, 9 }, State = LockingState.Closed }.Build(),
};
var locksInfoTdo = new List<LockInfoTdo> {
new LockInfoTdo.Builder { Id =14, State = LockitLockingState.Closed}.Build()
};
var resultList = locksInfo.UpdateById(locksInfoTdo);
var result = resultList.FirstOrDefault(x => x.Id == 14);
Assert.NotNull(result, "Target element was removed.");
Assert.AreEqual(LockingState.Closed, result.State);
}
[Test]
public void TestUpdateById_Guid()
{
var locksInfo = new List<LockInfo> {
new LockInfo.Builder { Id = 12, Seed = new byte[] { 3, 5 }, UserKey = new byte[] {2, 1 }, State = LockingState.Unknown }.Build(),
new LockInfo.Builder { Id = 14, Seed = new byte[] { 3, 1 }, UserKey = new byte[] {2, 7 }, State = LockingState.Open }.Build(),
new LockInfo.Builder { Id = 3, Seed = new byte[] { 1, 5 }, UserKey = new byte[] {2, 9 }, State = LockingState.Closed }.Build(),
};
var locksInfoTdo = new List<LockInfoTdo> {
new LockInfoTdo.Builder { Id =14, Guid = new System.Guid("00000000-0000-0000-0000-e57e6b9aee16"), State = LockitLockingState.Open}.Build()
};
var resultList = locksInfo.UpdateById(locksInfoTdo);
var result = resultList.FirstOrDefault(x => x.Id == 14);
Assert.NotNull(result, "Target element was removed.");
Assert.AreEqual(new Guid("00000000-0000-0000-0000-e57e6b9aee16"), result.Guid);
}
}
}

View file

@ -1,39 +0,0 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using TINK.Model.Bike.BluetoothLock;
namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
{
/// <summary>
/// Moved to TestShareeLib (.Net Core)
/// </summary>
[TestFixture]
public class TestLockInfoMutable
{
[Test]
public void TestCtor()
{
var lockInfo = new LockInfoMutable(1, new Guid(), new byte[] { 1, 2, 3 }, new byte[] { 1, 23 }, new byte[] { 1, 12 }, LockingState.Closed);
Assert.AreEqual(1, lockInfo.Id);
Assert.AreEqual(new Guid(), lockInfo.Guid);
Assert.IsTrue((new byte[] { 1, 2, 3 }).SequenceEqual(lockInfo.UserKey));
Assert.IsTrue((new byte[] { 1, 23 }).SequenceEqual(lockInfo.AdminKey));
Assert.IsTrue((new byte[] { 1, 12 }).SequenceEqual(lockInfo.Seed));
Assert.AreEqual(LockingState.Closed, lockInfo.State);
}
[Test]
public void TestSetGuid()
{
var lockInfo = new LockInfoMutable(1, new Guid(), new byte[] { 1, 2, 3 }, new byte[] { 1, 23 }, new byte[] { 1, 12 }, LockingState.Closed);
lockInfo.Guid = new Guid("00000000-0000-0000-0000-e57e6b9aee16");
Assert.AreEqual(new Guid("00000000-0000-0000-0000-e57e6b9aee16"), lockInfo.Guid);
}
}
}

View file

@ -1,49 +0,0 @@
using NUnit.Framework;
namespace TestTINKLib.Fixtures.ObjectTests.Bike
{
using TINK.Model.Bike;
/// <summary>
/// Moved to TestShareeLib (.Net Core)
/// </summary>
[TestFixture]
public class TestBike
{
[Test]
public void TestConstruct()
{
var l_oBike = new Bike(43);
Assert.AreEqual(43, l_oBike.Id);
Assert.AreEqual(null, l_oBike.TypeOfBike);
Assert.AreEqual(null, l_oBike.WheelType);
l_oBike = new Bike(43, WheelType.Mono, TypeOfBike.Cargo);
Assert.AreEqual(43, l_oBike.Id);
Assert.AreEqual(TypeOfBike.Cargo, l_oBike.TypeOfBike);
Assert.AreEqual(WheelType.Mono, l_oBike.WheelType);
}
[Test]
public void TestCompare()
{
var l_oBike1 = new Bike(43);
Assert.AreEqual(43, l_oBike1.Id);
Assert.AreEqual(null, l_oBike1.TypeOfBike);
Assert.AreEqual(null, l_oBike1.WheelType);
var l_oBike2 = new Bike(42, WheelType.Two, TypeOfBike.Allround);
Assert.IsFalse(l_oBike1 == l_oBike2);
l_oBike2 = new Bike(43, WheelType.Mono, TypeOfBike.Allround);
Assert.IsFalse(l_oBike1 == l_oBike2);
l_oBike2 = new Bike(43, WheelType.Two, TypeOfBike.Cargo);
Assert.IsFalse(l_oBike1 == l_oBike2);
l_oBike2 = new Bike(43, null, null);
Assert.IsTrue(l_oBike1 == l_oBike2);
}
}
}

View file

@ -1,25 +0,0 @@
using NUnit.Framework;
using System;
using TINK.Model.Bike;
namespace TestTINKLib
{
/// <summary>
/// Moved to TestShareeLib (.Net Core)
/// </summary>
[TestFixture]
public class TestBikeCollection
{
/// <summary> Tests the member.</summary>
[Test]
public void TestConstruct()
{
var l_oColl = new BikeCollection();
Assert.AreEqual(0, l_oColl.Count);
Assert.IsNull(l_oColl.GetById(1));
}
}
}

View file

@ -1,78 +0,0 @@
using NUnit.Framework;
using System.Collections.Generic;
using TINK.Model;
using TINK.Model.Bike;
namespace TestTINKLib.Fixtures.ObjectTests.Bike
{
/// <summary>
/// Moved to TestShareeLib (.Net Core)
/// </summary>
[TestFixture]
public class TestBikeCollectionFilter
{
[Test]
public void TestGetAtStation()
{
var coll = new BikeCollection(
new Dictionary<int, TINK.Model.Bike.BC.BikeInfo>
{
{3, new TINK.Model.Bike.BC.BikeInfo(7, 3 /* Stadion id */) },
{7, new TINK.Model.Bike.BC.BikeInfo(8, 12 /* Stadion id */) },
{12, new TINK.Model.Bike.BC.BikeInfo(33, 12 /* Stadion id */) }
});
Assert.AreEqual(
0,
BikeCollectionFilter.GetAtStation(null, 12).Count);
Assert.AreEqual(
0,
coll.GetAtStation(null).Count);
Assert.AreEqual(
0,
coll.GetAtStation(22).Count);
Assert.AreEqual(
1,
coll.GetAtStation(3).Count);
Assert.AreEqual(
2,
coll.GetAtStation(12).Count);
}
[Test]
public void TestGetLockIt()
{
var coll = new BikeCollection(
new Dictionary<int, TINK.Model.Bike.BC.BikeInfo>
{
{7, new TINK.Model.Bike.BC.BikeInfo(8, 12 /* Stadion id */) },
{12, new TINK.Model.Bike.BC.BikeInfo(33, 12 /* Stadion id */) }
});
Assert.AreEqual(
0,
coll.GetLockIt().Count);
coll = new BikeCollection(
new Dictionary<int, TINK.Model.Bike.BC.BikeInfo>
{
{7, new TINK.Model.Bike.BC.BikeInfo(8, 12 /* Stadion id */) },
{11, new TINK.Model.Bike.BluetoothLock.BikeInfo(33, 12 /* Stadion id */) },
{12, new TINK.Model.Bike.BC.BikeInfo(33, 12 /* Stadion id */) }
});
Assert.AreEqual(
0,
BikeCollectionFilter.GetLockIt(null).Count);
Assert.AreEqual(
1,
coll.GetLockIt().Count);
}
}
}

View file

@ -1,93 +0,0 @@
using NUnit.Framework;
using System;
using System.Collections.Generic;
using TINK.Model.Bike;
using TINK.Model.State;
using BikeInfo = TINK.Model.Bike.BC.BikeInfo;
using BikeInfoMutable = TINK.Model.Bike.BC.BikeInfoMutable;
namespace TestTINKLib
{
/// <summary>
/// Moved to TestShareeLib (.Net Core)
/// </summary>
[TestFixture]
public class TestBikeCollectionMutable
{
/// <summary> Tests the member.</summary>
[Test]
public void TestAdd()
{
var l_oColl = new BikeCollectionMutable();
l_oColl.Add(new BikeInfoMutable(57, false, new List<string> { "TINK" }, WheelType.Two, TypeOfBike.Allround));
Assert.Throws<Exception>(() => l_oColl.Add(new BikeInfoMutable(57, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Cargo)));
}
[Test]
public void TestUpdate_Null()
{
var l_oBikeRequested = new BikeInfoMutable(20, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Allround);
l_oBikeRequested.State.Load(new StateInfo(() => DateTime.Now, DateTime.Now, "john@long", "1234"));
var l_oBikeColl = new BikeCollectionMutable
{
new BikeInfoMutable(63, false, new List<string> { "TINK" }, WheelType.Two, TypeOfBike.Allround),
new BikeInfoMutable(57, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Cargo),
l_oBikeRequested,
};
// Verify initial state
Assert.NotNull(l_oBikeColl.GetById("63"));
Assert.AreEqual(InUseStateEnum.Disposable, l_oBikeColl.GetById("57").State.Value);
Assert.AreEqual(InUseStateEnum.Reserved, l_oBikeColl.GetById("20").State.Value);
Assert.Null(l_oBikeColl.GetById("33"));
l_oBikeColl.Update(null);
// Verify modified state
Assert.Null(l_oBikeColl.GetById("63"));
Assert.Null(l_oBikeColl.GetById("57"));
Assert.Null(l_oBikeColl.GetById("20"));
Assert.Null(l_oBikeColl.GetById("33"));
}
[Test]
public void TestUpdate()
{
var l_oBikeRequested = new BikeInfoMutable(20, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Allround);
l_oBikeRequested.State.Load(new StateInfo(() => DateTime.Now, DateTime.Now, "john@long", "1234"));
var l_oBikeColl = new BikeCollectionMutable
{
new BikeInfoMutable(63, false, new List<string> { "TINK" }, WheelType.Two, TypeOfBike.Allround),
new BikeInfoMutable(57, false, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Cargo),
l_oBikeRequested,
};
// Verify initial state
Assert.NotNull(l_oBikeColl.GetById("63")); // Will be removed
Assert.AreEqual(InUseStateEnum.Disposable, l_oBikeColl.GetById("57").State.Value); // Will be requested
Assert.AreEqual(InUseStateEnum.Reserved, l_oBikeColl.GetById("20").State.Value); // Will be booked
Assert.Null(l_oBikeColl.GetById("33")); //
var l_oBikeResponse = new List<BikeInfo>
{
new BikeInfo("57", false, new [] { "TINK" }, WheelType.Trike, TypeOfBike.Allround, "Test description", 7, DateTime.Now, "john@long,", "1234"),
new BikeInfo("20", false, new [] {"TINK" }, WheelType.Trike, TypeOfBike.Allround, "Test description", 7, DateTime.Now, "john@long,", "1234"),
new BikeInfo("33", 7, false, new [] {"TINK" }, WheelType.Trike, TypeOfBike.Allround),
};
l_oBikeColl.Update(l_oBikeResponse);
// Verify modified state
Assert.Null(l_oBikeColl.GetById("63"));
Assert.AreEqual(InUseStateEnum.Booked, l_oBikeColl.GetById("57").State.Value);
Assert.AreEqual(InUseStateEnum.Booked, l_oBikeColl.GetById("20").State.Value);
Assert.NotNull(l_oBikeColl.GetById("33"));
}
}
}

View file

@ -1,67 +0,0 @@
using System;
using System.Collections.Generic;
using NUnit.Framework;
using TINK.Model.Bike;
using TINK.Model.State;
using BikeInfoMutable = TINK.Model.Bike.BC.BikeInfoMutable;
namespace TestTINKLib
{
/// <summary>
/// Moved to TestShareeLib (.Net Core)
/// </summary>
[TestFixture]
class TestBikeMutable
{
[Test]
public void TestConstruct()
{
var l_oBike = new BikeInfoMutable(
42,
false,
new List<string> { "TINK" },
WheelType.Two,
TypeOfBike.Cargo);
Assert.AreEqual(42, l_oBike.Id);
Assert.IsFalse(l_oBike.IsDemo);
Assert.AreEqual(WheelType.Two, l_oBike.WheelType);
Assert.AreEqual(TypeOfBike.Cargo, l_oBike.TypeOfBike);
Assert.AreEqual(InUseStateEnum.Disposable, l_oBike.State.Value);
Assert.IsNull(l_oBike.CurrentStation);
l_oBike = new BikeInfoMutable(
17,
true,
new List<string> { "TINK" },
WheelType.Mono,
TypeOfBike.Allround,
"Test description",
1);
Assert.AreEqual(17, l_oBike.Id);
Assert.IsTrue(l_oBike.IsDemo);
Assert.AreEqual(WheelType.Mono, l_oBike.WheelType);
Assert.AreEqual(TypeOfBike.Allround, l_oBike.TypeOfBike);
Assert.AreEqual(InUseStateEnum.Disposable, l_oBike.State.Value);
Assert.AreEqual(1, l_oBike.CurrentStation);
}
[Test]
public void TestToString()
{
var l_oBike = new BikeInfoMutable(3, false, new List<string> { "TINK" }, WheelType.Two, TypeOfBike.Cargo, p_oDateTimeProvider: () => new DateTime(1970, 1, 1));
Assert.AreEqual(
"Id=3, wheel(s)=Two, type=Cargo, demo=False, state=Disposable, location=On the road.",
l_oBike.ToString());
l_oBike = new BikeInfoMutable(3, true, new List<string> { "TINK" }, WheelType.Trike, TypeOfBike.Allround, "Test description", 5, p_oDateTimeProvider: () => new DateTime(1970, 1, 1));
Assert.AreEqual(
"Id=3, wheel(s)=Trike, type=Allround, demo=True, state=Disposable, location=Station 5.",
l_oBike.ToString());
}
}
}

View file

@ -1,69 +0,0 @@
using Newtonsoft.Json;
using NUnit.Framework;
using TINK.Repository.Response;
namespace TestTINKLib.Fixtures.ObjectTests.Bike
{
/// <summary>
/// Moved to TestShareeLib (.Net Core)
/// </summary>
[TestFixture]
public class TestBikesAvailableResponse
{
[Test]
public void TestDeserializeStationEmpty()
{
// Response for bike 231 is a real world answer.
var l_oBikes = JsonConvert.DeserializeObject<BikesAvailableResponse>(@"
{
""apiserver"" : ""https://app.tink-konstanz.de"",
""response"" : ""bikes_available"",
""bikes"" : {
""231"" : {
""bike"" : ""231"",
""description"" : ""Stadtrad"",
""system"" : ""BC"",
""bike_group"" : [ ""Konrad"" ],
""station"" : """",
""state"" : ""available"",
""gps"" : { ""latitude"": ""9.1594501"", ""longitude"": ""47.6749928"" }
}
},
""copri_version"" : ""4.1.0.0"",
""authcookie"" : """",
""response_state"" : ""OK""
}
");
Assert.IsNull(l_oBikes.bikes[231].station);
}
[Test]
public void TestDeserializeStationInfoMissing()
{
// Response for bike 231 might not be real world answer.
var l_oBikes = JsonConvert.DeserializeObject<BikesAvailableResponse>(@"
{
""apiserver"" : ""https://app.tink-konstanz.de"",
""response"" : ""bikes_available"",
""bikes"" : {
""231"" : {
""bike"" : ""231"",
""description"" : ""Stadtrad"",
""system"" : ""BC"",
""bike_group"" : [ ""Konrad"" ],
""state"" : ""available"",
""gps"" : { ""latitude"": ""9.1594501"", ""longitude"": ""47.6749928"" }
}
},
""copri_version"" : ""4.1.0.0"",
""authcookie"" : """",
""response_state"" : ""OK""
}
");
Assert.IsNull(l_oBikes.bikes[231].station);
}
}
}

View file

@ -1,44 +0,0 @@
using Newtonsoft.Json;
using NUnit.Framework;
using System;
using TINK.Model.State;
namespace TestTINKLib.Fixtures.Bike
{
/// <summary>
/// Moved to TestShareeLib (.Net Core)
/// </summary>
[TestFixture]
public class TestStateBookedInfoSerializeJSON
{
[Test]
public void TestSerializeJSON()
{
// Create object to test.
var l_oInfoSource = new StateOccupiedInfo(
new DateTime(2017, 09, 20, 23, 05, 0),
"Heinz@mueller",
"17 xxb");
// Serialize object and verify.
var l_oDetected = JsonConvert.SerializeObject(l_oInfoSource);
const string EXPECTED = @"
{
""From"":""2017 - 09 - 20T23: 05:00"",
""MailAddress"":""Heinz@mueller"",
""Code"":""17 xxb""
}";
Assert.AreEqual(
TestHelper.PrepareXmlForStringCompare(EXPECTED.Replace("\n", string.Empty).Replace("\r", string.Empty)),
TestHelper.PrepareXmlForStringCompare(l_oDetected.Replace("\n", string.Empty).Replace("\r", string.Empty)));
// Deserialize object and verify.
var l_oInfoTarget = JsonConvert.DeserializeObject<StateOccupiedInfo>(l_oDetected);
Assert.AreEqual(InUseStateEnum.Booked, l_oInfoTarget.Value);
Assert.AreEqual("Heinz@mueller", l_oInfoTarget.MailAddress);
Assert.AreEqual("17 xxb", l_oInfoTarget.Code);
Assert.AreEqual(new DateTime(2017, 9, 20, 23, 5, 0), l_oInfoTarget.From);
}
}
}

View file

@ -1,7 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NUnit.Framework; using NUnit.Framework;
using Rhino.Mocks;
using TestFramework.Model.User.Account; using TestFramework.Model.User.Account;
using TINK.Model.Bikes.BikeInfoNS.BikeNS; using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.Model.Bikes.BikeInfoNS.DriveNS; using TINK.Model.Bikes.BikeInfoNS.DriveNS;
@ -78,7 +77,7 @@ namespace UITest.Fixtures.ViewModel
l_oBike, l_oBike,
l_oUser, l_oUser,
new MyBikeInUseStateInfoProvider(), new MyBikeInUseStateInfoProvider(),
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
url => { }); url => { });
Assert.AreEqual("2", l_oViewModel.Name); Assert.AreEqual("2", l_oViewModel.Name);
@ -105,7 +104,7 @@ namespace UITest.Fixtures.ViewModel
bike, bike,
user, user,
new BikeAtStationInUseStateInfoProvider(), new BikeAtStationInUseStateInfoProvider(),
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
url => { })); url => { }));
Assert.AreEqual("Still 15 min. reserved.", l_oViewModel.StateText); Assert.AreEqual("Still 15 min. reserved.", l_oViewModel.StateText);
@ -128,7 +127,7 @@ namespace UITest.Fixtures.ViewModel
bike, bike,
user, user,
new BikeAtStationInUseStateInfoProvider(), new BikeAtStationInUseStateInfoProvider(),
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
url => { })); url => { }));
Assert.AreEqual("Code 4asdfA, still 7 min. reserved.", l_oViewModel.StateText); Assert.AreEqual("Code 4asdfA, still 7 min. reserved.", l_oViewModel.StateText);
@ -151,7 +150,7 @@ namespace UITest.Fixtures.ViewModel
bike, bike,
user, user,
new BikeAtStationInUseStateInfoProvider(), new BikeAtStationInUseStateInfoProvider(),
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
url => { })); url => { }));
Assert.AreEqual( Assert.AreEqual(
@ -188,7 +187,7 @@ namespace UITest.Fixtures.ViewModel
l_oStoreMock.Load().Result, l_oStoreMock.Load().Result,
"123456789"), // Device id "123456789"), // Device id
new BikeAtStationInUseStateInfoProvider(), new BikeAtStationInUseStateInfoProvider(),
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
url => { }); url => { });
Assert.AreEqual("Test description", l_oViewModel.Name); Assert.AreEqual("Test description", l_oViewModel.Name);
@ -227,7 +226,7 @@ namespace UITest.Fixtures.ViewModel
l_oStoreMock.Load().Result, l_oStoreMock.Load().Result,
"123456789"), "123456789"),
new BikeAtStationInUseStateInfoProvider(), new BikeAtStationInUseStateInfoProvider(),
MockRepository.GenerateStub<IBikesViewModel>(), NSubstitute.Substitute.For<IBikesViewModel>(),
url => { }); url => { });
Assert.AreEqual("Test description", l_oViewModel.Name); Assert.AreEqual("Test description", l_oViewModel.Name);

View file

@ -1,84 +0,0 @@
using NUnit.Framework;
using Rhino.Mocks;
using TINK.Model.Bikes.BikeInfoNS.BC;
using TINK.Model.Bikes.BikeInfoNS.BikeNS;
using TINK.ViewModel;
namespace UITest.Fixtures.ObjectTests.ViewModel
{
[TestFixture]
public class TestViewModelHelper
{
[Test]
public void TestGetDisplayName_DefinedTypes()
{
var l_oBike = MockRepository.GenerateStub<IBikeInfoMutable>();
l_oBike.Stub(x => x.WheelType).Return(WheelType.Two);
l_oBike.Stub(x => x.TypeOfBike).Return(TypeOfBike.City);
l_oBike.Stub(x => x.Description).Return("MeinStadtrad");
l_oBike.Stub(x => x.Id).Return("22");
Assert.AreEqual(
"MeinStadtrad",
l_oBike.GetDisplayName());
Assert.AreEqual(
"22",
l_oBike.GetDisplayId());
l_oBike = MockRepository.GenerateStub<IBikeInfoMutable>();
l_oBike.Stub(x => x.WheelType).Return(WheelType.Two);
l_oBike.Stub(x => x.TypeOfBike).Return(TypeOfBike.City);
l_oBike.Stub(x => x.Id).Return("22");
l_oBike.Stub(x => x.IsDemo).Return(true);
l_oBike.Stub(x => x.Description).Return("MeinStadtrad");
Assert.AreEqual(
"MeinStadtrad",
l_oBike.GetDisplayName());
Assert.AreEqual(
"22",
l_oBike.GetDisplayId());
l_oBike = MockRepository.GenerateStub<IBikeInfoMutable>();
l_oBike.Stub(x => x.WheelType).Return(WheelType.Trike);
l_oBike.Stub(x => x.TypeOfBike).Return(TypeOfBike.Cargo);
l_oBike.Stub(x => x.Description).Return("MeinCargoDreiradl");
l_oBike.Stub(x => x.Id).Return("22");
Assert.AreEqual(
"MeinCargoDreiradl",
l_oBike.GetDisplayName());
Assert.AreEqual(
"22",
l_oBike.GetDisplayId());
l_oBike = MockRepository.GenerateStub<IBikeInfoMutable>();
l_oBike.Stub(x => x.WheelType).Return(WheelType.Two);
l_oBike.Stub(x => x.TypeOfBike).Return(TypeOfBike.Cargo);
l_oBike.Stub(x => x.Description).Return("MeinCargoALololong");
l_oBike.Stub(x => x.Id).Return("22");
Assert.AreEqual(
"MeinCargoALololong",
l_oBike.GetDisplayName());
Assert.AreEqual(
"22",
l_oBike.GetDisplayId());
}
[Test]
public void TestGetDisplayName_UndefinedTypes()
{
var l_oBike = MockRepository.GenerateStub<IBikeInfoMutable>();
l_oBike.Stub(x => x.WheelType).Return(WheelType.Mono);
l_oBike.Stub(x => x.TypeOfBike).Return(TypeOfBike.Cargo);
l_oBike.Stub(x => x.Description).Return("SuperCargo");
l_oBike.Stub(x => x.Id).Return("22");
Assert.AreEqual(
"SuperCargo",
l_oBike.GetDisplayName());
Assert.AreEqual(
"22",
l_oBike.GetDisplayId());
}
}
}

View file

@ -40,84 +40,33 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Fixtures\ObjectTests\Services\BluetoothLock\Tdo\TestLockInfoAuthTdo.cs" />
<Compile Include="Fixtures\ObjectTests\Services\TestLocksServicesContainerMutable.cs" />
<Compile Include="Fixtures\ObjectTests\Services\TestServicesContainerMutable.cs" /> <Compile Include="Fixtures\ObjectTests\Services\TestServicesContainerMutable.cs" />
<Compile Include="Fixtures\ObjectTests\Settings\BluetoothLock\TestLockIt.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\Account\TestAccountPageViewModel.cs" /> <Compile Include="Fixtures\ObjectTests\ViewModel\Account\TestAccountPageViewModel.cs" />
<None Include="Fixtures\ObjectTests\Bike\BluetoothLock\TestLockInfo.cs" />
<None Include="Fixtures\ObjectTests\Bike\BluetoothLock\TestLockInfoHelper.cs" />
<None Include="Fixtures\ObjectTests\Bike\BluetoothLock\TestLockInfoMutable.cs" />
<None Include="Fixtures\ObjectTests\Bike\TestBike.cs" />
<None Include="Fixtures\ObjectTests\Bike\TestBikeCollection.cs" />
<None Include="Fixtures\ObjectTests\Bike\TestBikeCollectionFilter.cs" />
<None Include="Fixtures\ObjectTests\Bike\TestBikesAvailableResponse.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\CopriCallsHttpReference.cs" /> <Compile Include="Fixtures\ObjectTests\Connector\CopriCallsHttpReference.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\Exception\TestAuthcookieNotDefinedException.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\Filter\TestIntersectFilter.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\Filter\TestNullFilter.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\Query\TestCachedQuery.cs" /> <Compile Include="Fixtures\ObjectTests\Connector\Query\TestCachedQuery.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\Query\TestCachedQueryLoggedIn.cs" /> <Compile Include="Fixtures\ObjectTests\Connector\Query\TestCachedQueryLoggedIn.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\TestConnectorCache.cs" /> <Compile Include="Fixtures\ObjectTests\Connector\TestConnectorCache.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\TestCopriCallsHttps.cs" /> <Compile Include="Fixtures\ObjectTests\Connector\TestCopriCallsHttps.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\TestCopriCallsStatic.cs" /> <Compile Include="Fixtures\ObjectTests\Connector\TestCopriCallsStatic.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\Response\TestResponseHelper.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\TestCommandLoggedIn.cs" /> <Compile Include="Fixtures\ObjectTests\Connector\TestCommandLoggedIn.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\TestConnector.cs" /> <Compile Include="Fixtures\ObjectTests\Connector\TestConnector.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\TestCopriServerUriList.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\TestFilter.cs" /> <Compile Include="Fixtures\ObjectTests\Connector\TestFilter.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\Query\TestQuery.cs" /> <Compile Include="Fixtures\ObjectTests\Connector\Query\TestQuery.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\Query\TestQueryLoggedIn.cs" /> <Compile Include="Fixtures\ObjectTests\Connector\Query\TestQueryLoggedIn.cs" />
<Compile Include="Fixtures\ObjectTests\Logging\TestLoggingDirectoryManager.cs" />
<Compile Include="Fixtures\ObjectTests\Map\TestMapPageFilter.cs" />
<Compile Include="Fixtures\ObjectTests\Services\BluetoothLock\Crypto\TestCryptoHelper.cs" />
<Compile Include="Fixtures\ObjectTests\Services\BluetoothLock\TestLockItBaseService.cs" /> <Compile Include="Fixtures\ObjectTests\Services\BluetoothLock\TestLockItBaseService.cs" />
<Compile Include="Fixtures\ObjectTests\Services\BluetoothLock\TestLockServiceSimulation.cs" />
<Compile Include="Fixtures\ObjectTests\Settings\TestGroupFilterSettings.cs" />
<Compile Include="Fixtures\ObjectTests\Settings\TestPollingParameters.cs" />
<Compile Include="Fixtures\ObjectTests\Settings\TestSettings.cs" />
<Compile Include="Fixtures\ObjectTests\Station\TestNullStation.cs" />
<Compile Include="Fixtures\ObjectTests\TestFilterCollection.cs" />
<Compile Include="Fixtures\ObjectTests\TestFilterCollectionStore.cs" />
<Compile Include="Fixtures\ObjectTests\User\Account\TestAccount.cs" />
<Compile Include="Fixtures\ObjectTests\User\Account\TestAccountExtensions.cs" /> <Compile Include="Fixtures\ObjectTests\User\Account\TestAccountExtensions.cs" />
<None Include="Fixtures\ObjectTests\User\Account\TestStore.cs" /> <None Include="Fixtures\ObjectTests\User\Account\TestStore.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\Bikes\Bike\BluetoothLock\TestRequestHandlerFactory.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\Info\TestInfoViewModel.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\Map\TestMapPageFilter.cs" /> <Compile Include="Fixtures\ObjectTests\ViewModel\Map\TestMapPageFilter.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\Map\TestMapPageViewModel.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\Settings\TestFilterCollectionMutable.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\TestBikeAtStationInUseStateInfoProvider.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\TestBikeAtStationViewModel.cs" /> <Compile Include="Fixtures\ObjectTests\ViewModel\TestBikeAtStationViewModel.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\TestBikeViewModel.cs" /> <Compile Include="Fixtures\ObjectTests\ViewModel\TestBikeViewModel.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\TestBikeViewModelFactory.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\TestMyBikeInUseStateInfoProvider.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\TestMyBikePageViewModel.cs" /> <Compile Include="Fixtures\ObjectTests\ViewModel\TestMyBikePageViewModel.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\TestMyBikesPageViewModel.cs" /> <Compile Include="Fixtures\ObjectTests\ViewModel\TestMyBikesPageViewModel.cs" />
<Compile Include="Fixtures\ObjectTests\ViewModel\TestViewModelHelper.cs" />
<Compile Include="Fixtures\UseCases\ConnectedOffline\TestTinkApp.cs" /> <Compile Include="Fixtures\UseCases\ConnectedOffline\TestTinkApp.cs" />
<Compile Include="Fixtures\UseCases\TestHelper.cs" /> <Compile Include="Fixtures\UseCases\TestHelper.cs" />
<None Include="Fixtures\ObjectTests\Bike\TestBikeSerializeJSON.cs" /> <None Include="Fixtures\ObjectTests\Bike\TestBikeSerializeJSON.cs" />
<None Include="Fixtures\ObjectTests\Bike\TestBikeCollectionSerializeJSON.cs" />
<None Include="Fixtures\ObjectTests\Bike\TestStateBookedInfoSerializeJSON.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\TestCopriCallsMemory.cs.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\Response\TestBikesAvailableResponse.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\Response\TestBikesOccupiedResponse.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\Response\TestBookingResponse.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\Response\TestResponseBase.cs" />
<Compile Include="Fixtures\ObjectTests\Connector\Response\TestStationsAllResponse.cs" />
<Compile Include="Fixtures\ObjectTests\State\TestStateBookedInfo.cs" />
<Compile Include="Fixtures\ObjectTests\State\TestStateDisposableInfo.cs" />
<Compile Include="Fixtures\ObjectTests\State\TestStateInfoMutable.cs" /> <Compile Include="Fixtures\ObjectTests\State\TestStateInfoMutable.cs" />
<Compile Include="Fixtures\ObjectTests\State\TestStateInfoSerializeJSON.cs" />
<Compile Include="Fixtures\ObjectTests\State\TestStateRequestedInfo.cs" /> <Compile Include="Fixtures\ObjectTests\State\TestStateRequestedInfo.cs" />
<None Include="Fixtures\ObjectTests\Bike\TestBikeMutable.cs" />
<None Include="Fixtures\ObjectTests\Bike\TestBikeCollectionMutable.cs" />
<Compile Include="Fixtures\ObjectTests\State\TestStateRequestedInfoSerializeJSON.cs" />
<Compile Include="Fixtures\ObjectTests\Station\TestStation.cs" />
<Compile Include="Fixtures\UseCases\SelectStation\TestTinkApp.cs" /> <Compile Include="Fixtures\UseCases\SelectStation\TestTinkApp.cs" />
<Compile Include="Fixtures\ObjectTests\User\Account\TestValidator.cs" />
<Compile Include="Fixtures\ObjectTests\User\TestUser.cs" />
<Compile Include="Mocks\Bike\BikeCollectionMock.cs" /> <Compile Include="Mocks\Bike\BikeCollectionMock.cs" />
<Compile Include="Mocks\Connector\CopriCallsCacheMemory.cs" /> <Compile Include="Mocks\Connector\CopriCallsCacheMemory.cs" />
<Compile Include="Mocks\DateTimeMocker.cs" /> <Compile Include="Mocks\DateTimeMocker.cs" />
@ -185,7 +134,13 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Folder Include="Fixtures\ObjectTests\Connector\Exception\" />
<Folder Include="Fixtures\ObjectTests\Connector\Filter\" />
<Folder Include="Fixtures\ObjectTests\Connector\Response\" />
<Folder Include="Fixtures\ObjectTests\Connector\Updater\" /> <Folder Include="Fixtures\ObjectTests\Connector\Updater\" />
<Folder Include="Fixtures\ObjectTests\Services\BluetoothLock\Crypto\" />
<Folder Include="Fixtures\ObjectTests\Services\BluetoothLock\Tdo\" />
<Folder Include="Fixtures\ObjectTests\Settings\BluetoothLock\" />
<Folder Include="Fixtures\UseCases\Startup\" /> <Folder Include="Fixtures\UseCases\Startup\" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />