Version 3.0.362

This commit is contained in:
Anja 2023-04-05 15:02:10 +02:00
parent cba4da9357
commit 4ff3307997
128 changed files with 3954 additions and 3193 deletions

View file

@ -77,7 +77,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" /> <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.NETCore.Platforms" Version="7.0.0" /> <PackageReference Include="Microsoft.NETCore.Platforms" Version="7.0.1" />
<PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0" /> <PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0" />
<PackageReference Include="MonkeyCache"> <PackageReference Include="MonkeyCache">
<Version>1.6.3</Version> <Version>1.6.3</Version>
@ -86,7 +86,7 @@
<Version>1.6.3</Version> <Version>1.6.3</Version>
</PackageReference> </PackageReference>
<PackageReference Include="NETStandard.Library" Version="2.0.3" /> <PackageReference Include="NETStandard.Library" Version="2.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="PCLCrypto" Version="2.0.147" /> <PackageReference Include="PCLCrypto" Version="2.0.147" />
<PackageReference Include="PCLStorage" Version="1.0.2" /> <PackageReference Include="PCLStorage" Version="1.0.2" />
<PackageReference Include="PInvoke.BCrypt" Version="0.7.124" /> <PackageReference Include="PInvoke.BCrypt" Version="0.7.124" />
@ -185,7 +185,7 @@
<Version>1.0.0.16</Version> <Version>1.0.0.16</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.AndroidX.RecyclerView"> <PackageReference Include="Xamarin.AndroidX.RecyclerView">
<Version>1.2.1.9</Version> <Version>1.3.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.Auth" Version="1.7.0" /> <PackageReference Include="Xamarin.Auth" Version="1.7.0" />
<PackageReference Include="Xamarin.Build.Download" Version="0.11.4" /> <PackageReference Include="Xamarin.Build.Download" Version="0.11.4" />
@ -195,9 +195,9 @@
<PackageReference Include="Xamarin.Essentials"> <PackageReference Include="Xamarin.Essentials">
<Version>1.7.5</Version> <Version>1.7.5</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2545" /> <PackageReference Include="Xamarin.Forms" Version="5.0.0.2578" />
<PackageReference Include="Xamarin.Forms.AppLinks"> <PackageReference Include="Xamarin.Forms.AppLinks">
<Version>5.0.0.2545</Version> <Version>5.0.0.2578</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.Forms.GoogleMaps"> <PackageReference Include="Xamarin.Forms.GoogleMaps">
<Version>5.0.0</Version> <Version>5.0.0</Version>

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

File diff suppressed because it is too large Load diff

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>361</string> <string>362</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.361</string> <string>3.0.362</string>
</dict> </dict>
</plist> </plist>

View file

@ -120,7 +120,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Bcl.Build" Version="1.0.21" /> <PackageReference Include="Microsoft.Bcl.Build" Version="1.0.21" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" /> <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.NETCore.Platforms" Version="7.0.0" /> <PackageReference Include="Microsoft.NETCore.Platforms" Version="7.0.1" />
<PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0" /> <PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0" />
<PackageReference Include="MonkeyCache"> <PackageReference Include="MonkeyCache">
<Version>1.6.3</Version> <Version>1.6.3</Version>
@ -129,7 +129,7 @@
<Version>1.6.3</Version> <Version>1.6.3</Version>
</PackageReference> </PackageReference>
<PackageReference Include="NETStandard.Library" Version="2.0.3" /> <PackageReference Include="NETStandard.Library" Version="2.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="PCLCrypto" Version="2.0.147" /> <PackageReference Include="PCLCrypto" Version="2.0.147" />
<PackageReference Include="PCLStorage" Version="1.0.2" /> <PackageReference Include="PCLStorage" Version="1.0.2" />
<PackageReference Include="Plugin.BluetoothLE"> <PackageReference Include="Plugin.BluetoothLE">
@ -220,7 +220,7 @@
<Version>0.7.124</Version> <Version>0.7.124</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.Forms"> <PackageReference Include="Xamarin.Forms">
<Version>5.0.0.2545</Version> <Version>5.0.0.2578</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -338,9 +338,9 @@ namespace TINK
/// <summary> /// <summary>
/// Service container to manage geolocation services. /// Service container to manage geolocation services.
/// </summary> /// </summary>
public static IServicesContainer<IGeolocation> LocationServicesContainer { get; } public static IServicesContainer<IGeolocationService> LocationServicesContainer { get; }
= new ServicesContainerMutableT<IGeolocation>( = new ServicesContainerMutableT<IGeolocationService>(
new HashSet<IGeolocation> { new HashSet<IGeolocationService> {
new LastKnownGeolocationService(DependencyService.Get<IGeolodationDependent>()), new LastKnownGeolocationService(DependencyService.Get<IGeolodationDependent>()),
new SimulatedGeolocationService(DependencyService.Get<IGeolodationDependent>()), new SimulatedGeolocationService(DependencyService.Get<IGeolodationDependent>()),
new GeolocationAccuracyMediumService(DependencyService.Get<IGeolodationDependent>()), new GeolocationAccuracyMediumService(DependencyService.Get<IGeolodationDependent>()),

View file

@ -22,7 +22,7 @@
<Folder Include="Services\BluetoothLock\Crypto\" /> <Folder Include="Services\BluetoothLock\Crypto\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Serilog" Version="2.12.0" /> <PackageReference Include="Serilog" Version="2.12.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -77,7 +77,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" /> <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.NETCore.Platforms" Version="7.0.0" /> <PackageReference Include="Microsoft.NETCore.Platforms" Version="7.0.1" />
<PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0" /> <PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0" />
<PackageReference Include="MonkeyCache"> <PackageReference Include="MonkeyCache">
<Version>1.6.3</Version> <Version>1.6.3</Version>
@ -86,7 +86,7 @@
<Version>1.6.3</Version> <Version>1.6.3</Version>
</PackageReference> </PackageReference>
<PackageReference Include="NETStandard.Library" Version="2.0.3" /> <PackageReference Include="NETStandard.Library" Version="2.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="PCLCrypto" Version="2.0.147" /> <PackageReference Include="PCLCrypto" Version="2.0.147" />
<PackageReference Include="PCLStorage" Version="1.0.2" /> <PackageReference Include="PCLStorage" Version="1.0.2" />
<PackageReference Include="PInvoke.BCrypt" Version="0.7.124" /> <PackageReference Include="PInvoke.BCrypt" Version="0.7.124" />
@ -185,7 +185,7 @@
<Version>1.0.0.16</Version> <Version>1.0.0.16</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.AndroidX.RecyclerView"> <PackageReference Include="Xamarin.AndroidX.RecyclerView">
<Version>1.2.1.9</Version> <Version>1.3.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.Auth" Version="1.7.0" /> <PackageReference Include="Xamarin.Auth" Version="1.7.0" />
<PackageReference Include="Xamarin.Build.Download" Version="0.11.4" /> <PackageReference Include="Xamarin.Build.Download" Version="0.11.4" />
@ -195,9 +195,9 @@
<PackageReference Include="Xamarin.Essentials"> <PackageReference Include="Xamarin.Essentials">
<Version>1.7.5</Version> <Version>1.7.5</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2545" /> <PackageReference Include="Xamarin.Forms" Version="5.0.0.2578" />
<PackageReference Include="Xamarin.Forms.AppLinks"> <PackageReference Include="Xamarin.Forms.AppLinks">
<Version>5.0.0.2545</Version> <Version>5.0.0.2578</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.Forms.GoogleMaps"> <PackageReference Include="Xamarin.Forms.GoogleMaps">
<Version>5.0.0</Version> <Version>5.0.0</Version>

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

File diff suppressed because it is too large Load diff

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>361</string> <string>362</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.361</string> <string>3.0.362</string>
</dict> </dict>
</plist> </plist>

View file

@ -1,7 +1,7 @@
{ {
"images" : [ "images" : [
{ {
"filename" : "StationMarkerOpenBlue.svg", "filename" : "StationMarkerOpenBlue.pdf",
"idiom" : "universal" "idiom" : "universal"
}, },
{ {

View file

@ -0,0 +1,69 @@
%PDF-1.5
%µí®û
4 0 obj
<< /Length 5 0 R
/Filter /FlateDecode
>>
stream
xœm<EFBFBD>An1E÷>(c8FŽP<C5BD>”dÑ,ÒÞ_*¶‡E”j¤™ÿÌüïÅóÁñÅÇ£< a÷Ajð.~nðùEpû-ÜPIÂ÷€S[A©b8œáYJw`ÁÆ2Ü™z‰ÿNÃêð ÜQ&Å8>},nT¡zLû ¢I»ÎŒ:v•ZQ]w£]÷€ûìî<C3AC>¡2ªy,ÀŒ$=YÑ°á Ô¹Í&BÕe©%Næ6;néc:mȦ¸žšœ„LK^7•ô<E280A2>%^+þWúZ.åaqV²
endstream
endobj
5 0 obj
206
endobj
3 0 obj
<<
/ExtGState <<
/a0 << /CA 1 /ca 1 >>
>>
>>
endobj
2 0 obj
<< /Type /Page % 1
/Parent 1 0 R
/MediaBox [ 0 0 29.393326 37.5 ]
/Contents 4 0 R
/Group <<
/Type /Group
/S /Transparency
/I true
/CS /DeviceRGB
>>
/Resources 3 0 R
>>
endobj
1 0 obj
<< /Type /Pages
/Kids [ 2 0 R ]
/Count 1
>>
endobj
6 0 obj
<< /Producer (cairo 1.17.4 (https://cairographics.org))
/Creator <FEFF0049006E006B0073006300610070006500200031002E0031002E00320020002800680074007400700073003A002F002F0069006E006B00730063006100700065002E006F007200670029>
/CreationDate (D:20230323095234+01'00)
>>
endobj
7 0 obj
<< /Type /Catalog
/Pages 1 0 R
>>
endobj
xref
0 8
0000000000 65535 f
0000000617 00000 n
0000000392 00000 n
0000000320 00000 n
0000000015 00000 n
0000000298 00000 n
0000000682 00000 n
0000000965 00000 n
trailer
<< /Size 8
/Root 7 0 R
/Info 6 0 R
>>
startxref
1017
%%EOF

View file

@ -1,7 +1,7 @@
{ {
"images" : [ "images" : [
{ {
"filename" : "StationMarkerOpenGreen.svg", "filename" : "StationMarkerOpenGreen.pdf",
"idiom" : "universal" "idiom" : "universal"
}, },
{ {

View file

@ -1,7 +1,7 @@
{ {
"images" : [ "images" : [
{ {
"filename" : "StationMarkerOpenLightBlue.svg", "filename" : "StationMarkerOpenLightBlue.pdf",
"idiom" : "universal" "idiom" : "universal"
}, },
{ {

View file

@ -0,0 +1,69 @@
%PDF-1.5
%µí®û
4 0 obj
<< /Length 5 0 R
/Filter /FlateDecode
>>
stream
xœm<EFBFBD>An1E÷>(c8FŽP<C5BD>”dÑ,ÒÞ_*¶‡E”j¤™ÿÌüïÅóÁñÅÇ£< a÷Ajð.~nðùEpû-ÜPIÂ÷€S[A©b8œáYJw`ÁÆ2Ü™z‰ÿNÃêð ÜQ&Å8>},nT¡zLû ¢I»ÎŒ:v•ZQ]w£]÷€ûìî<C3AC>¡2ªy,ÀŒ$=YÑ°á Ô¹Í&BÕe©%Næ6;néc:mȦ¸žšœ„LK^7•ô<E280A2>%^+þWúZ.åaqV²
endstream
endobj
5 0 obj
206
endobj
3 0 obj
<<
/ExtGState <<
/a0 << /CA 1 /ca 1 >>
>>
>>
endobj
2 0 obj
<< /Type /Page % 1
/Parent 1 0 R
/MediaBox [ 0 0 29.393326 37.5 ]
/Contents 4 0 R
/Group <<
/Type /Group
/S /Transparency
/I true
/CS /DeviceRGB
>>
/Resources 3 0 R
>>
endobj
1 0 obj
<< /Type /Pages
/Kids [ 2 0 R ]
/Count 1
>>
endobj
6 0 obj
<< /Producer (cairo 1.17.4 (https://cairographics.org))
/Creator <FEFF0049006E006B0073006300610070006500200031002E0031002E00320020002800680074007400700073003A002F002F0069006E006B00730063006100700065002E006F007200670029>
/CreationDate (D:20230323095234+01'00)
>>
endobj
7 0 obj
<< /Type /Catalog
/Pages 1 0 R
>>
endobj
xref
0 8
0000000000 65535 f
0000000617 00000 n
0000000392 00000 n
0000000320 00000 n
0000000015 00000 n
0000000298 00000 n
0000000682 00000 n
0000000965 00000 n
trailer
<< /Size 8
/Root 7 0 R
/Info 6 0 R
>>
startxref
1017
%%EOF

View file

@ -1,7 +1,7 @@
{ {
"images" : [ "images" : [
{ {
"filename" : "StationMarkerOpenRed.svg", "filename" : "StationMarkerOpenRed.pdf",
"idiom" : "universal" "idiom" : "universal"
}, },
{ {

View file

@ -0,0 +1,69 @@
%PDF-1.5
%µí®û
4 0 obj
<< /Length 5 0 R
/Filter /FlateDecode
>>
stream
xœm<EFBFBD>An1E÷>(c8FŽP<C5BD>”dÑ,ÒÞ_*¶‡E”j¤™ÿÌüïÅóÁñÅÇ£< a÷Ajð.~nðùEpû-ÜPIÂ÷€S[A©b8œáYJw`ÁÆ2Ü™z‰ÿNÃêð ÜQ&Å8>},nT¡zLû ¢I»ÎŒ:v•ZQ]w£]÷€ûìî<C3AC>¡2ªy,ÀŒ$=YÑ°á Ô¹Í&BÕe©%Næ6;néc:mȦ¸žšœ„LK^7•ô<E280A2>%^+þWúZ.åaqV²
endstream
endobj
5 0 obj
206
endobj
3 0 obj
<<
/ExtGState <<
/a0 << /CA 1 /ca 1 >>
>>
>>
endobj
2 0 obj
<< /Type /Page % 1
/Parent 1 0 R
/MediaBox [ 0 0 29.393326 37.5 ]
/Contents 4 0 R
/Group <<
/Type /Group
/S /Transparency
/I true
/CS /DeviceRGB
>>
/Resources 3 0 R
>>
endobj
1 0 obj
<< /Type /Pages
/Kids [ 2 0 R ]
/Count 1
>>
endobj
6 0 obj
<< /Producer (cairo 1.17.4 (https://cairographics.org))
/Creator <FEFF0049006E006B0073006300610070006500200031002E0031002E00320020002800680074007400700073003A002F002F0069006E006B00730063006100700065002E006F007200670029>
/CreationDate (D:20230323095234+01'00)
>>
endobj
7 0 obj
<< /Type /Catalog
/Pages 1 0 R
>>
endobj
xref
0 8
0000000000 65535 f
0000000617 00000 n
0000000392 00000 n
0000000320 00000 n
0000000015 00000 n
0000000298 00000 n
0000000682 00000 n
0000000965 00000 n
trailer
<< /Size 8
/Root 7 0 R
/Info 6 0 R
>>
startxref
1017
%%EOF

View file

@ -121,7 +121,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Bcl.Build" Version="1.0.21" /> <PackageReference Include="Microsoft.Bcl.Build" Version="1.0.21" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" /> <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.NETCore.Platforms" Version="7.0.0" /> <PackageReference Include="Microsoft.NETCore.Platforms" Version="7.0.1" />
<PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0" /> <PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0" />
<PackageReference Include="MonkeyCache"> <PackageReference Include="MonkeyCache">
<Version>1.6.3</Version> <Version>1.6.3</Version>
@ -130,7 +130,7 @@
<Version>1.6.3</Version> <Version>1.6.3</Version>
</PackageReference> </PackageReference>
<PackageReference Include="NETStandard.Library" Version="2.0.3" /> <PackageReference Include="NETStandard.Library" Version="2.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="PCLCrypto" Version="2.0.147" /> <PackageReference Include="PCLCrypto" Version="2.0.147" />
<PackageReference Include="PCLStorage" Version="1.0.2" /> <PackageReference Include="PCLStorage" Version="1.0.2" />
<PackageReference Include="Plugin.BluetoothLE"> <PackageReference Include="Plugin.BluetoothLE">
@ -221,7 +221,7 @@
<Version>0.7.124</Version> <Version>0.7.124</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.Forms"> <PackageReference Include="Xamarin.Forms">
<Version>5.0.0.2545</Version> <Version>5.0.0.2578</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -294,25 +294,25 @@
<ImageAsset Include="Media.xcassets\LaunchImages.launchimage\Contents.json"> <ImageAsset Include="Media.xcassets\LaunchImages.launchimage\Contents.json">
<Visible>false</Visible> <Visible>false</Visible>
</ImageAsset> </ImageAsset>
<ImageAsset Include="Media.xcassets\Open_Blue.imageset\StationMarkerOpenBlue.svg"> <ImageAsset Include="Media.xcassets\Open_Blue.imageset\StationMarkerOpenBlue.pdf">
<Visible>false</Visible> <Visible>false</Visible>
</ImageAsset> </ImageAsset>
<ImageAsset Include="Media.xcassets\Open_Blue.imageset\Contents.json"> <ImageAsset Include="Media.xcassets\Open_Blue.imageset\Contents.json">
<Visible>false</Visible> <Visible>false</Visible>
</ImageAsset> </ImageAsset>
<ImageAsset Include="Media.xcassets\Open_Green.imageset\StationMarkerOpenGreen.svg"> <ImageAsset Include="Media.xcassets\Open_Green.imageset\StationMarkerOpenGreen.pdf">
<Visible>false</Visible> <Visible>false</Visible>
</ImageAsset> </ImageAsset>
<ImageAsset Include="Media.xcassets\Open_Green.imageset\Contents.json"> <ImageAsset Include="Media.xcassets\Open_Green.imageset\Contents.json">
<Visible>false</Visible> <Visible>false</Visible>
</ImageAsset> </ImageAsset>
<ImageAsset Include="Media.xcassets\Open_LightBlue.imageset\StationMarkerOpenLightBlue.svg"> <ImageAsset Include="Media.xcassets\Open_LightBlue.imageset\StationMarkerOpenLightBlue.pdf">
<Visible>false</Visible> <Visible>false</Visible>
</ImageAsset> </ImageAsset>
<ImageAsset Include="Media.xcassets\Open_LightBlue.imageset\Contents.json"> <ImageAsset Include="Media.xcassets\Open_LightBlue.imageset\Contents.json">
<Visible>false</Visible> <Visible>false</Visible>
</ImageAsset> </ImageAsset>
<ImageAsset Include="Media.xcassets\Open_Red.imageset\StationMarkerOpenRed.svg"> <ImageAsset Include="Media.xcassets\Open_Red.imageset\StationMarkerOpenRed.pdf">
<Visible>false</Visible> <Visible>false</Visible>
</ImageAsset> </ImageAsset>
<ImageAsset Include="Media.xcassets\Open_Red.imageset\Contents.json"> <ImageAsset Include="Media.xcassets\Open_Red.imageset\Contents.json">

View file

@ -336,9 +336,9 @@ namespace TINK
/// <summary> /// <summary>
/// Service container to manage geolocation services. /// Service container to manage geolocation services.
/// </summary> /// </summary>
public static IServicesContainer<IGeolocation> LocationServicesContainer { get; } public static IServicesContainer<IGeolocationService> LocationServicesContainer { get; }
= new ServicesContainerMutableT<IGeolocation>( = new ServicesContainerMutableT<IGeolocationService>(
new HashSet<IGeolocation> { new HashSet<IGeolocationService> {
new LastKnownGeolocationService(DependencyService.Get<IGeolodationDependent>()), new LastKnownGeolocationService(DependencyService.Get<IGeolodationDependent>()),
new SimulatedGeolocationService(DependencyService.Get<IGeolodationDependent>()), new SimulatedGeolocationService(DependencyService.Get<IGeolodationDependent>()),
new GeolocationAccuracyMediumService(DependencyService.Get<IGeolodationDependent>()), new GeolocationAccuracyMediumService(DependencyService.Get<IGeolodationDependent>()),

View file

@ -43,7 +43,6 @@
WidthRequest="320" WidthRequest="320"
HeightRequest="800" HeightRequest="800"
x:Name="MyMap" x:Name="MyMap"
MyLocationEnabled="True"
MapType="Street"> MapType="Street">
<maps:Map.Behaviors> <maps:Map.Behaviors>
<bindings:BindingPinsBehavior Value="{Binding Pins}"/> <bindings:BindingPinsBehavior Value="{Binding Pins}"/>

View file

@ -31,9 +31,6 @@ namespace TINK.View.Map
public MapPage() public MapPage()
{ {
InitializeComponent(); InitializeComponent();
MyMap.UiSettings.MyLocationButtonEnabled = true;
} }
/// <summary> /// <summary>
@ -211,6 +208,24 @@ namespace TINK.View.Map
isInitializationStarted = false; isInitializationStarted = false;
return; return;
} }
try
{
Log.ForContext<MapPage>().Verbose("Setting map settings.");
//show current user position (blue dot) and enable button for centering map manually.
MyMap.UiSettings.MyLocationButtonEnabled = MapPageViewModel.IsLocationPermissionGranted;
MyMap.IsShowingUser = MapPageViewModel.IsLocationPermissionGranted;
//disable +/- buttons
MyMap.UiSettings.ZoomControlsEnabled = false;
}
catch (Exception exception)
{
Log.ForContext<MapPage>().Verbose("Setting map settings failed. {Exception}", exception);
isInitializationStarted = false;
return;
}
} }
/// <summary> /// <summary>

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

File diff suppressed because it is too large Load diff

View file

@ -77,7 +77,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" /> <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.NETCore.Platforms" Version="7.0.0" /> <PackageReference Include="Microsoft.NETCore.Platforms" Version="7.0.1" />
<PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0" /> <PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0" />
<PackageReference Include="MonkeyCache"> <PackageReference Include="MonkeyCache">
<Version>1.6.3</Version> <Version>1.6.3</Version>
@ -86,7 +86,7 @@
<Version>1.6.3</Version> <Version>1.6.3</Version>
</PackageReference> </PackageReference>
<PackageReference Include="NETStandard.Library" Version="2.0.3" /> <PackageReference Include="NETStandard.Library" Version="2.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="PCLCrypto" Version="2.0.147" /> <PackageReference Include="PCLCrypto" Version="2.0.147" />
<PackageReference Include="PCLStorage" Version="1.0.2" /> <PackageReference Include="PCLStorage" Version="1.0.2" />
<PackageReference Include="PInvoke.BCrypt" Version="0.7.124" /> <PackageReference Include="PInvoke.BCrypt" Version="0.7.124" />
@ -185,7 +185,7 @@
<Version>1.0.0.16</Version> <Version>1.0.0.16</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.AndroidX.RecyclerView"> <PackageReference Include="Xamarin.AndroidX.RecyclerView">
<Version>1.2.1.9</Version> <Version>1.3.0</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.Auth" Version="1.7.0" /> <PackageReference Include="Xamarin.Auth" Version="1.7.0" />
<PackageReference Include="Xamarin.Build.Download" Version="0.11.4" /> <PackageReference Include="Xamarin.Build.Download" Version="0.11.4" />
@ -195,9 +195,9 @@
<PackageReference Include="Xamarin.Essentials"> <PackageReference Include="Xamarin.Essentials">
<Version>1.7.5</Version> <Version>1.7.5</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2545" /> <PackageReference Include="Xamarin.Forms" Version="5.0.0.2578" />
<PackageReference Include="Xamarin.Forms.AppLinks"> <PackageReference Include="Xamarin.Forms.AppLinks">
<Version>5.0.0.2545</Version> <Version>5.0.0.2578</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.Forms.GoogleMaps"> <PackageReference Include="Xamarin.Forms.GoogleMaps">
<Version>5.0.0</Version> <Version>5.0.0</Version>

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>361</string> <string>362</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>3.0.361</string> <string>3.0.362</string>
</dict> </dict>
</plist> </plist>

View file

@ -121,7 +121,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.Bcl.Build" Version="1.0.21" /> <PackageReference Include="Microsoft.Bcl.Build" Version="1.0.21" />
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" /> <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="Microsoft.NETCore.Platforms" Version="7.0.0" /> <PackageReference Include="Microsoft.NETCore.Platforms" Version="7.0.1" />
<PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0" /> <PackageReference Include="Microsoft.Win32.Primitives" Version="4.3.0" />
<PackageReference Include="MonkeyCache"> <PackageReference Include="MonkeyCache">
<Version>1.6.3</Version> <Version>1.6.3</Version>
@ -130,7 +130,7 @@
<Version>1.6.3</Version> <Version>1.6.3</Version>
</PackageReference> </PackageReference>
<PackageReference Include="NETStandard.Library" Version="2.0.3" /> <PackageReference Include="NETStandard.Library" Version="2.0.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="PCLCrypto" Version="2.0.147" /> <PackageReference Include="PCLCrypto" Version="2.0.147" />
<PackageReference Include="PCLStorage" Version="1.0.2" /> <PackageReference Include="PCLStorage" Version="1.0.2" />
<PackageReference Include="Plugin.BluetoothLE"> <PackageReference Include="Plugin.BluetoothLE">
@ -221,7 +221,7 @@
<Version>0.7.124</Version> <Version>0.7.124</Version>
</PackageReference> </PackageReference>
<PackageReference Include="Xamarin.Forms"> <PackageReference Include="Xamarin.Forms">
<Version>5.0.0.2545</Version> <Version>5.0.0.2578</Version>
</PackageReference> </PackageReference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -345,9 +345,9 @@ namespace TINK
/// <summary> /// <summary>
/// Service container to manage geolocation services. /// Service container to manage geolocation services.
/// </summary> /// </summary>
public static IServicesContainer<IGeolocation> LocationServicesContainer { get; } public static IServicesContainer<IGeolocationService> LocationServicesContainer { get; }
= new ServicesContainerMutableT<IGeolocation>( = new ServicesContainerMutableT<IGeolocationService>(
new HashSet<IGeolocation> { new HashSet<IGeolocationService> {
new LastKnownGeolocationService(DependencyService.Get<IGeolodationDependent>()), new LastKnownGeolocationService(DependencyService.Get<IGeolodationDependent>()),
new SimulatedGeolocationService(DependencyService.Get<IGeolodationDependent>()), new SimulatedGeolocationService(DependencyService.Get<IGeolodationDependent>()),
new GeolocationAccuracyMediumService(DependencyService.Get<IGeolodationDependent>()), new GeolocationAccuracyMediumService(DependencyService.Get<IGeolodationDependent>()),

View file

@ -41,7 +41,6 @@
WidthRequest="320" WidthRequest="320"
HeightRequest="800" HeightRequest="800"
x:Name="MyMap" x:Name="MyMap"
MyLocationEnabled="True"
MapType="Street"> MapType="Street">
<maps:Map.Behaviors> <maps:Map.Behaviors>
<bindings:BindingPinsBehavior Value="{Binding Pins}"/> <bindings:BindingPinsBehavior Value="{Binding Pins}"/>

View file

@ -31,9 +31,6 @@ namespace TINK.View.Map
public MapPage() public MapPage()
{ {
InitializeComponent(); InitializeComponent();
MyMap.UiSettings.MyLocationButtonEnabled = true;
} }
/// <summary> /// <summary>
@ -211,6 +208,25 @@ namespace TINK.View.Map
isInitializationStarted = false; isInitializationStarted = false;
return; return;
} }
try
{
Log.ForContext<MapPage>().Verbose("Setting map settings.");
//show current user position (blue dot) and enable button for centering map manually.
MyMap.UiSettings.MyLocationButtonEnabled = MapPageViewModel.IsLocationPermissionGranted;
MyMap.IsShowingUser = MapPageViewModel.IsLocationPermissionGranted;
//disable +/- buttons
MyMap.UiSettings.ZoomControlsEnabled = false;
}
catch (Exception exception)
{
Log.ForContext<MapPage>().Verbose("Setting map settings failed. {Exception}", exception);
isInitializationStarted = false;
return;
}
} }
/// <summary> /// <summary>

View file

@ -1,6 +1,6 @@
namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
{ {
public interface IBikeInfoMutable : BikeInfoNS.BC.IBikeInfoMutable public interface IBikeInfoMutable : BC.IBikeInfoMutable
{ {
ILockInfoMutable LockInfo { get; } ILockInfoMutable LockInfo { get; }
} }

View file

@ -1,4 +1,5 @@
using System; using System;
using TINK.Services.Geolocation;
namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
{ {
@ -20,6 +21,14 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
byte[] Seed { get; } byte[] Seed { get; }
/// <summary> Timestamp of the last locking state change.</summary>
DateTime? LastLockingStateChange { get; }
/// <summary>
/// Gets or sets the current location of the bike, null if location is unknown.
/// </summary>
IGeolocation Location { get; set; }
/// <summary> /// <summary>
/// Gets the version info of the locks. /// Gets the version info of the locks.
/// </summary> /// </summary>

View file

@ -1,4 +1,5 @@
using System; using System;
using TINK.Services.Geolocation;
namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
{ {
@ -7,16 +8,24 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
/// <summary> Lock info object. </summary> /// <summary> Lock info object. </summary>
private LockInfo LockInfo { get; set; } private LockInfo LockInfo { get; set; }
/// <summary>
/// Delegate to create time stamp.
/// </summary>
private Func<DateTime> _nowDelegate;
/// <summary> Constructs a bluetooth lock info object. </summary> /// <summary> Constructs a bluetooth lock info object. </summary>
/// <param name="id">Id of lock must always been known when constructing an lock info object.</param> /// <param name="id">Id of lock must always been known when constructing an lock info object.</param>
/// <param name="nowDelegate">Delegate to create time stamp if null DateTime.Now is used.</param>
public LockInfoMutable( public LockInfoMutable(
int id, int id,
Guid guid, Guid guid,
byte[] userKey, byte[] userKey,
byte[] adminKey, byte[] adminKey,
byte[] seed, byte[] seed,
LockingState state) LockingState state,
Func<DateTime> nowDelegate = null)
{ {
_nowDelegate = nowDelegate ?? (() => DateTime.Now);
LockInfo = new LockInfo.Builder() { Id = id, Guid = guid, UserKey = userKey, AdminKey = adminKey, Seed = seed, State = state }.Build(); LockInfo = new LockInfo.Builder() { Id = id, Guid = guid, UserKey = userKey, AdminKey = adminKey, Seed = seed, State = state }.Build();
} }
@ -35,12 +44,34 @@ namespace TINK.Model.Bikes.BikeInfoNS.BluetoothLock
public byte[] AdminKey => LockInfo.AdminKey; public byte[] AdminKey => LockInfo.AdminKey;
/// <summary>
/// Gets or sets the locking state.
/// </summary>
public LockingState State public LockingState State
{ {
get => LockInfo.State; get => LockInfo.State;
set => LockInfo = new LockInfo.Builder(LockInfo) { State = value }.Build(); set
{
if (LockInfo.State == value)
{
// State does not change, nothing to do.
return;
}
Location = null; // Invalidate location.
LastLockingStateChange = _nowDelegate(); // Get time stamp when state change happened.
LockInfo = new LockInfo.Builder(LockInfo) { State = value }.Build();
}
} }
/// <summary> Gets the timestamp of the last locking state change.</summary>
public DateTime? LastLockingStateChange { get; private set; }
/// <summary>
/// Gets or sets the current location of the bike, null if location is unknown.
/// </summary>
public IGeolocation Location { get; set; }
/// <summary> Holds the percentage of lock battery.</summary> /// <summary> Holds the percentage of lock battery.</summary>
public double BatteryPercentage { get; set; } = double.NaN; public double BatteryPercentage { get; set; } = double.NaN;

View file

@ -1,7 +1,10 @@
using System; using System;
namespace TINK.Model namespace TINK.Model
{ {
/// <summary>
/// Holds a exact position.
/// </summary>
public interface IPosition : IEquatable<IPosition> public interface IPosition : IEquatable<IPosition>
{ {
double Latitude { get; } double Latitude { get; }

View file

@ -409,7 +409,7 @@ namespace TINK.Model.Settings
return targetDictionary.Union(new Dictionary<string, string> return targetDictionary.Union(new Dictionary<string, string>
{ {
{ typeof(IGeolocation).Name, activeGeolocationService }, { typeof(IGeolocationService).Name, activeGeolocationService },
}).ToDictionary(key => key.Key, value => value.Value); }).ToDictionary(key => key.Key, value => value.Value);
} }
@ -419,7 +419,7 @@ namespace TINK.Model.Settings
public static string GetActiveGeolocationService(this IDictionary<string, string> settingsJSON) public static string GetActiveGeolocationService(this IDictionary<string, string> settingsJSON)
{ {
// Get uri of corpi server. // Get uri of corpi server.
if (!settingsJSON.TryGetValue(typeof(IGeolocation).Name, out string activeGeolocationService) if (!settingsJSON.TryGetValue(typeof(IGeolocationService).Name, out string activeGeolocationService)
|| string.IsNullOrEmpty(activeGeolocationService)) || string.IsNullOrEmpty(activeGeolocationService))
{ {
// File holds no entry. // File holds no entry.

View file

@ -176,7 +176,7 @@ namespace TINK.Model
string merchantId, string merchantId,
IBluetoothLE bluetoothService, IBluetoothLE bluetoothService,
ILocationPermission locationPermissionsService, ILocationPermission locationPermissionsService,
IServicesContainer<IGeolocation> locationServicesContainer, IServicesContainer<IGeolocationService> locationServicesContainer,
ILocksService locksService, ILocksService locksService,
ISmartDevice device, ISmartDevice device,
ISpecialFolder specialFolder, ISpecialFolder specialFolder,
@ -406,7 +406,7 @@ namespace TINK.Model
public LocksServicesContainerMutable LocksServices { get; set; } public LocksServicesContainerMutable LocksServices { get; set; }
/// <summary> Holds available app themes.</summary> /// <summary> Holds available app themes.</summary>
public IServicesContainer<IGeolocation> GeolocationServices { get; } public IServicesContainer<IGeolocationService> GeolocationServices { get; }
/// <summary> Holds the flavor of the app, i.e. specifies if app is sharee.bike, Mein konrad or Lastenrad Bayern.</summary> /// <summary> Holds the flavor of the app, i.e. specifies if app is sharee.bike, Mein konrad or Lastenrad Bayern.</summary>
public AppFlavor Flavor { get; private set; } public AppFlavor Flavor { get; private set; }

View file

@ -672,16 +672,21 @@ namespace TINK.Model
new Version(3, 0, 356), new Version(3, 0, 356),
AppResources.ChangeLog3_0_231 AppResources.ChangeLog3_0_231
}, },
{ {
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), new Version(3, 0, 361),
AppResources.ChangeLog_3_0_361_MK_SB, AppResources.ChangeLog_3_0_361_MK_SB,
new List<AppFlavor> { AppFlavor.MeinKonrad, AppFlavor.ShareeBike } new List<AppFlavor> { AppFlavor.MeinKonrad, AppFlavor.ShareeBike }
}, },
{
new Version(3, 0, 362),
AppResources.ChangeLog_3_0_362_MK_SB,
new List<AppFlavor> { AppFlavor.MeinKonrad, AppFlavor.ShareeBike }
},
}; };
/// <summary> Manges the whats new information.</summary> /// <summary> Manges the whats new information.</summary>

View file

@ -88,7 +88,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Close lock &amp; return bike. /// Looks up a localized string similar to Close lock &amp; end rental.
/// </summary> /// </summary>
public static string ActionCloseAndReturn { public static string ActionCloseAndReturn {
get { get {
@ -97,7 +97,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Feedback about the App. /// Looks up a localized string similar to Feedback about the app.
/// </summary> /// </summary>
public static string ActionContactMailAppReleated { public static string ActionContactMailAppReleated {
get { get {
@ -115,7 +115,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Give Feedback. /// Looks up a localized string similar to Give feedback.
/// </summary> /// </summary>
public static string ActionGiveFeedback { public static string ActionGiveFeedback {
get { get {
@ -142,7 +142,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Register. /// Looks up a localized string similar to Register for free.
/// </summary> /// </summary>
public static string ActionLoginRegister { public static string ActionLoginRegister {
get { get {
@ -187,7 +187,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Return bike. /// Looks up a localized string similar to End rental.
/// </summary> /// </summary>
public static string ActionReturn { public static string ActionReturn {
get { get {
@ -331,7 +331,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to No web error on updating locking status.. /// Looks up a localized string similar to Internet must be available for updating lock status. Please establish an Internet connection!.
/// </summary> /// </summary>
public static string ActivityTextErrorNoWebUpdateingLockstate { public static string ActivityTextErrorNoWebUpdateingLockstate {
get { get {
@ -466,7 +466,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Loading reserved/ booked bikes.... /// Looks up a localized string similar to Loading reserved/rented bikes....
/// </summary> /// </summary>
public static string ActivityTextMyBikesLoadingBikes { public static string ActivityTextMyBikesLoadingBikes {
get { get {
@ -565,7 +565,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Returning bike.... /// Looks up a localized string similar to Ending rental....
/// </summary> /// </summary>
public static string ActivityTextReturningBike { public static string ActivityTextReturningBike {
get { get {
@ -610,7 +610,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Starting bike return.... /// Looks up a localized string similar to Starting end rental....
/// </summary> /// </summary>
public static string ActivityTextStartReturningBike { public static string ActivityTextStartReturningBike {
get { get {
@ -766,6 +766,21 @@ namespace TINK.MultilingualResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to Some terms have been standardized, e.g:&lt;br/&gt;
///- what used to be called &apos;return bike&apos; is now always called &apos;end rental&apos;.&lt;br/&gt;
///- The &apos;operator&apos; is the group of people responsible for the bike fleet, who will be contacted if necessary.&lt;br/&gt;
///&lt;br/&gt;
///Also:&lt;br/&gt;
///- Minor bug fixes&lt;br/&gt;
///- Package updates.
/// </summary>
public static string ChangeLog_3_0_362_MK_SB {
get {
return ResourceManager.GetString("ChangeLog_3_0_362_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>
@ -960,7 +975,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Feedback dialog added which is shown after returning bike.. /// Looks up a localized string similar to Feedback dialog added which is shown after ending rental..
/// </summary> /// </summary>
public static string ChangeLog3_0_227 { public static string ChangeLog3_0_227 {
get { get {
@ -1017,7 +1032,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Hard- and software information send to backend when returning bike.. /// Looks up a localized string similar to Hard- and software information send to backend when ending rental..
/// </summary> /// </summary>
public static string ChangeLog3_0_237 { public static string ChangeLog3_0_237 {
get { get {
@ -1387,6 +1402,17 @@ namespace TINK.MultilingualResources {
} }
} }
/// <summary>
/// Looks up a localized string similar to We could not assign the bike to any station. For this we need your location information while you are standing right next to the bike. Only then your rental can be terminated!
///
///Approach the bike, turn on Bluetooth and Location services and try again..
/// </summary>
public static string Error_ReturnBike_Station_Location_Message {
get {
return ResourceManager.GetString("Error_ReturnBike_Station_Location_Message", resourceCulture);
}
}
/// <summary> /// <summary>
/// Looks up a localized string similar to Failed to query available bikes.. /// Looks up a localized string similar to Failed to query available bikes..
/// </summary> /// </summary>
@ -1415,12 +1441,13 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Unfortunately, it is still not possible to establish a connection between your mobile device and the bike lock. Please contact customer support. /// Looks up a localized string similar to It is still not possible to establish a connection between your mobile device and the bike lock. Please contact operator!
/// ///
///As a last resort, please close the lock by hand AND contact customer support so that they can terminate your chargeable rental. To do this: ///Alternative:
///1. close the app, ///1. close app,
///2. press the button at the top of the lock briefly and quickly release it as soon as it starts flashing, ///2. press the button at the top of the lock briefly and release it as soon as it starts flashing,
///3. wait until the lock is completely closed and remains closed.. ///3. make sure that the lock is completely closed and remains closed.
///4. send e-mail to operator (otherwise your chargeable rental will continue!): Problem description, Drop-off station..
/// </summary> /// </summary>
public static string ErrorBookedSearchMessageEscalationLevel2 { public static string ErrorBookedSearchMessageEscalationLevel2 {
get { get {
@ -1457,7 +1484,7 @@ namespace TINK.MultilingualResources {
/// <summary> /// <summary>
/// Looks up a localized string similar to Lock cannot be closed until bike is near. /// Looks up a localized string similar to Lock cannot be closed until bike is near.
///Please try again to close bike or report bike to support!. ///Please try again to close bike or report bike to operator!.
/// </summary> /// </summary>
public static string ErrorCloseLockOutOfReachStateReservedMessage { public static string ErrorCloseLockOutOfReachStateReservedMessage {
get { get {
@ -1493,7 +1520,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Please try to lock again or report bike to support! /// Looks up a localized string similar to Please try to lock again or report bike to operator!
///{0}. ///{0}.
/// </summary> /// </summary>
public static string ErrorCloseLockUnkErrorMessage { public static string ErrorCloseLockUnkErrorMessage {
@ -1512,7 +1539,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Internet must be reachable to connect to lock of rented bike.. /// Looks up a localized string similar to Internet must be reachable to connect to lock of rented bike. Please establish an Internet connection!.
/// </summary> /// </summary>
public static string ErrorConnectLockRentedBikeNoWebMessage { public static string ErrorConnectLockRentedBikeNoWebMessage {
get { get {
@ -1521,7 +1548,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Internet must be reachable to connect to lock of reserved bike.. /// Looks up a localized string similar to Internet must be reachable to connect to lock of reserved bike. Please establish an Internet connection!.
/// </summary> /// </summary>
public static string ErrorConnectLockReservedBikeNoWebMessage { public static string ErrorConnectLockReservedBikeNoWebMessage {
get { get {
@ -1539,7 +1566,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Please turn Location on, otherwise lock cannot be connected.. /// Looks up a localized string similar to Please turn location services on, otherwise lock cannot be connected..
/// </summary> /// </summary>
public static string ErrorFindLockLocationOff { public static string ErrorFindLockLocationOff {
get { get {
@ -1611,11 +1638,11 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to The lock could not be opened correctly. Please try again. /// Looks up a localized string similar to The lock could not be opened correctly. Try again!
/// ///
///Attention! Your rental has already started. ///Attention! Your rental has already started.
/// ///If the lock still won&apos;t open, make sure the lock is closed and end rental.
///If the lock still won&apos;t open, make sure the lock is closed and return the bike. Please report it to the support!. ///Important: Send an email to the operator (otherwise your paid rental will continue!) with: Problem description, bike number, drop-off station..
/// </summary> /// </summary>
public static string ErrorOpenLockBoldStatusIsUnknownMessage { public static string ErrorOpenLockBoldStatusIsUnknownMessage {
get { get {
@ -1678,10 +1705,20 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Returning bike at an unknown location is not possible. /// Looks up a localized string similar to End rental at an unknown location is not possible.
///Bike can be returned if ///Getting geolocation failed..
/// </summary>
public static string ErrorReturnBikeLockClosedGetGPSExceptionMessage {
get {
return ResourceManager.GetString("ErrorReturnBikeLockClosedGetGPSExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to End rental at an unknown location is not possible.
///Rental can be ended if
///- location information is available when closing lock ///- location information is available when closing lock
///- bike is in reach and location information is available when pressing button &quot;Return bike&quot;. ///- bike is in reach and location information is available when pressing button &quot;End rental&quot;.
/// </summary> /// </summary>
public static string ErrorReturnBikeLockClosedNoGPSMessage { public static string ErrorReturnBikeLockClosedNoGPSMessage {
get { get {
@ -1690,8 +1727,18 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Returning bike at an unknown location is not possible. /// Looks up a localized string similar to End rental at an unknown location is not possible.
///Bike can only be returned if bike is in reach and location information is available.. ///Start getting geolocation failed..
/// </summary>
public static string ErrorReturnBikeLockClosedStartGetGPSExceptionMessage {
get {
return ResourceManager.GetString("ErrorReturnBikeLockClosedStartGetGPSExceptionMessage", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to End rental at an unknown location is not possible.
///Rental can only be ended if bike is in reach and location information is available..
/// </summary> /// </summary>
public static string ErrorReturnBikeLockOpenNoGPSMessage { public static string ErrorReturnBikeLockOpenNoGPSMessage {
get { get {
@ -1700,7 +1747,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Returning bike outside of station is not possible. Distance to station {0} is {1} m.. /// Looks up a localized string similar to End rental outside of station is not possible. Distance to station {0} is {1} m..
/// </summary> /// </summary>
public static string ErrorReturnBikeNotAtStationMessage { public static string ErrorReturnBikeNotAtStationMessage {
get { get {
@ -1709,7 +1756,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Internet must be available when returning the bike.. /// Looks up a localized string similar to Internet must be available when ending rental. Please establish an Internet connection!.
/// </summary> /// </summary>
public static string ErrorReturnBikeNoWebMessage { public static string ErrorReturnBikeNoWebMessage {
get { get {
@ -1718,7 +1765,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Connection error when returning the bike!. /// Looks up a localized string similar to Connection error when ending rental..
/// </summary> /// </summary>
public static string ErrorReturnBikeNoWebTitle { public static string ErrorReturnBikeNoWebTitle {
get { get {
@ -1727,7 +1774,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Error returning bike!. /// Looks up a localized string similar to Error at ending rental!.
/// </summary> /// </summary>
public static string ErrorReturnBikeTitle { public static string ErrorReturnBikeTitle {
get { get {
@ -1763,7 +1810,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Opening mail app failed.. /// Looks up a localized string similar to Opening mail app failed. Make sure you have a mail app installed on your mobile device!.
/// </summary> /// </summary>
public static string ErrorSupportmailMailingFailed { public static string ErrorSupportmailMailingFailed {
get { get {
@ -1772,7 +1819,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Opening phone app failed.. /// Looks up a localized string similar to Opening phone app failed. Make sure you have a phone app installed on your mobile device!.
/// </summary> /// </summary>
public static string ErrorSupportmailPhoningFailed { public static string ErrorSupportmailPhoningFailed {
get { get {
@ -1781,7 +1828,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to The rental of bike No. {0} has failed.. /// Looks up a localized string similar to The rental of bike {0} has failed..
/// </summary> /// </summary>
public static string ExceptionTextRentingBikeFailedGeneral { public static string ExceptionTextRentingBikeFailedGeneral {
get { get {
@ -1790,7 +1837,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to The rental of bike No. {0} has failed, the bike is currently unavailable.{1}. /// Looks up a localized string similar to The rental of bike {0} has failed, the bike is currently unavailable. {1}.
/// </summary> /// </summary>
public static string ExceptionTextRentingBikeFailedUnavailalbe { public static string ExceptionTextRentingBikeFailedUnavailalbe {
get { get {
@ -1799,7 +1846,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to The reservation of bike no. {0} has failed.. /// Looks up a localized string similar to The reservation of bike {0} has failed..
/// </summary> /// </summary>
public static string ExceptionTextReservationBikeFailedGeneral { public static string ExceptionTextReservationBikeFailedGeneral {
get { get {
@ -1808,7 +1855,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to The reservation of bike No. {0} has failed, the bike is currently unavailable.{1}. /// Looks up a localized string similar to The reservation of bike {0} has failed, the bike is currently unavailable. {1}.
/// </summary> /// </summary>
public static string ExceptionTextReservationBikeFailedUnavailalbe { public static string ExceptionTextReservationBikeFailedUnavailalbe {
get { get {
@ -1826,7 +1873,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Is WIFI available/ mobile network available and mobile data activated / ... ?. /// Looks up a localized string similar to Is WIFI/mobile network available and mobile data activated?.
/// </summary> /// </summary>
public static string ExceptionTextWebConnectFailureException { public static string ExceptionTextWebConnectFailureException {
get { get {
@ -1900,7 +1947,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Contact Operator.. /// Looks up a localized string similar to Contact operator..
/// </summary> /// </summary>
public static string MarkingBikeSharingOperatorNoOperatorInfoAvailable { public static string MarkingBikeSharingOperatorNoOperatorInfoAvailable {
get { get {
@ -2153,7 +2200,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to At least 8 characters. /// Looks up a localized string similar to At least eight characters.
/// </summary> /// </summary>
public static string MarkingLoginPasswordLabel { public static string MarkingLoginPasswordLabel {
get { get {
@ -2198,7 +2245,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to There are currently no bicycles reserved/booked on user {0}.. /// Looks up a localized string similar to There are currently no bikes reserved/rented by user {0}..
/// </summary> /// </summary>
public static string MarkingMyBikesNoBikesReservedRented { public static string MarkingMyBikesNoBikesReservedRented {
get { get {
@ -2207,7 +2254,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Oops, there is no internet connection.. /// Looks up a localized string similar to Oops, there is no Internet connection..
/// </summary> /// </summary>
public static string MarkingNoNetworkConnection { public static string MarkingNoNetworkConnection {
get { get {
@ -2243,7 +2290,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Bike successfully returned!. /// Looks up a localized string similar to Rental successfully ended!.
/// </summary> /// </summary>
public static string MarkingReturnBikeMainMessage { public static string MarkingReturnBikeMainMessage {
get { get {
@ -2270,7 +2317,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Show/ hide. /// Looks up a localized string similar to Show/hide.
/// </summary> /// </summary>
public static string MarkingShowHideBikesOfType { public static string MarkingShowHideBikesOfType {
get { get {
@ -2505,7 +2552,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Rental fees. /// Looks up a localized string similar to Rental charges.
/// </summary> /// </summary>
public static string MessageBikesManagementTariffDescriptionFeeEuroPerHour { public static string MessageBikesManagementTariffDescriptionFeeEuroPerHour {
get { get {
@ -2532,7 +2579,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Max. fee. /// Looks up a localized string similar to Max. charges.
/// </summary> /// </summary>
public static string MessageBikesManagementTariffDescriptionMaxFeeEuroPerDay { public static string MessageBikesManagementTariffDescriptionMaxFeeEuroPerDay {
get { get {
@ -2606,7 +2653,7 @@ namespace TINK.MultilingualResources {
/// <summary> /// <summary>
/// Looks up a localized string similar to This version of the {0} App is not compatible with server detected. /// Looks up a localized string similar to This version of the {0} App is not compatible with server detected.
///Please contact the support for help.. ///Please contact operator for help..
/// </summary> /// </summary>
public static string MessageCopriVersionIsOutdated { public static string MessageCopriVersionIsOutdated {
get { get {
@ -2663,7 +2710,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Error Start Query Location!. /// Looks up a localized string similar to Error start query location!.
/// </summary> /// </summary>
public static string MessageErrorQueryLocationStartTitle { public static string MessageErrorQueryLocationStartTitle {
get { get {
@ -2672,7 +2719,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Error Query Location!. /// Looks up a localized string similar to Error query location!.
/// </summary> /// </summary>
public static string MessageErrorQueryLocationTitle { public static string MessageErrorQueryLocationTitle {
get { get {
@ -2781,7 +2828,7 @@ namespace TINK.MultilingualResources {
/// <summary> /// <summary>
/// Looks up a localized string similar to Session has expired. /// Looks up a localized string similar to Session has expired.
///Please login to app once again.. ///Please log in again..
/// </summary> /// </summary>
public static string MessageMapPageErrorAuthcookieUndefined { public static string MessageMapPageErrorAuthcookieUndefined {
get { get {
@ -2790,7 +2837,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to An error occurred switching from cargo bikes/ city bikes. /// Looks up a localized string similar to An error occurred switching between cargo and city bikes.
///{0}. ///{0}.
/// </summary> /// </summary>
public static string MessageMapPageErrorSwitch { public static string MessageMapPageErrorSwitch {
@ -2818,7 +2865,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Are you enjoying the {0}-App?. /// Looks up a localized string similar to Are you enjoying the {0}-app?.
/// </summary> /// </summary>
public static string MessageRateMail { public static string MessageRateMail {
get { get {
@ -2845,7 +2892,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to A rental of bike {0} was rejected because the maximum allowed number of {1} reservations/ rentals had already been made.. /// Looks up a localized string similar to A rental of bike {0} was rejected because the maximum allowed number of {1} reservations/rentals had already been made..
/// </summary> /// </summary>
public static string MessageRentingBikeErrorTooManyReservationsRentals { public static string MessageRentingBikeErrorTooManyReservationsRentals {
get { get {
@ -2854,7 +2901,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to A reservation of bike {0} was rejected because the maximum allowed number of {1} reservations/ rentals had already been made.. /// Looks up a localized string similar to A reservation of bike {0} was rejected because the maximum allowed number of {1} reservations/rentals had already been made..
/// </summary> /// </summary>
public static string MessageReservationBikeErrorTooManyReservationsRentals { public static string MessageReservationBikeErrorTooManyReservationsRentals {
get { get {
@ -2926,7 +2973,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to {0}-App Releated Request. /// Looks up a localized string similar to {0}-app releated request.
/// </summary> /// </summary>
public static string MiscContactMailAppReleatedSubject { public static string MiscContactMailAppReleatedSubject {
get { get {
@ -2971,7 +3018,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Close lock and return bike {0}?. /// Looks up a localized string similar to Close lock and end rental of bike {0}?.
/// </summary> /// </summary>
public static string QuestionCloseLockAndReturnBike { public static string QuestionCloseLockAndReturnBike {
get { get {
@ -2998,7 +3045,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Return bike {0}?. /// Looks up a localized string similar to End rental of bike {0}?.
/// </summary> /// </summary>
public static string QuestionReturnBike { public static string QuestionReturnBike {
get { get {
@ -3036,7 +3083,7 @@ namespace TINK.MultilingualResources {
/// <summary> /// <summary>
/// Looks up a localized string similar to I hereby consent to the transmission of my log file. /// Looks up a localized string similar to I hereby consent to the transmission of my log file.
/// ///
///The log file contains your app usage data as well as system information. The data will only be used for diagnostic purposes or to improve the app.. ///The log file contains your app usage data as well as system information. The data will only be used for diagnostic purposes or to improve the app and then deleted..
/// </summary> /// </summary>
public static string QuestionSupportmailAttachment { public static string QuestionSupportmailAttachment {
get { get {
@ -3045,7 +3092,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to Does your request/ comment relate to the {0}-app or to a more general subject?. /// Looks up a localized string similar to Does your request/comment relate to the {0}-app or to a more general subject?.
/// </summary> /// </summary>
public static string QuestionSupportmailSubject { public static string QuestionSupportmailSubject {
get { get {
@ -3135,7 +3182,7 @@ namespace TINK.MultilingualResources {
} }
/// <summary> /// <summary>
/// Looks up a localized string similar to The remaining power of the bike battery was low recently. Please check it on the bike display before riding. The bike can be returned within 5 minutes free of charge.. /// Looks up a localized string similar to The remaining power of the bike battery was low recently. Please check it on the bike display before riding. The rental can be canceled within 5 minutes free of charge..
/// </summary> /// </summary>
public static string StatusTextLowBatteryLevel { public static string StatusTextLowBatteryLevel {
get { get {

View file

@ -43,7 +43,7 @@
<value>Radstandorte</value> <value>Radstandorte</value>
</data> </data>
<data name="MessageLoginWelcome" xml:space="preserve"> <data name="MessageLoginWelcome" xml:space="preserve">
<value>Benutzer {0} erfolgreich angemeldet.</value> <value>Nutzer {0} erfolgreich angemeldet.</value>
</data> </data>
<data name="MessageLoginWelcomeTitle" xml:space="preserve"> <data name="MessageLoginWelcomeTitle" xml:space="preserve">
<value>Willkommen!</value> <value>Willkommen!</value>
@ -58,13 +58,13 @@
<value>Angemeldet als {0} bei {1}.</value> <value>Angemeldet als {0} bei {1}.</value>
</data> </data>
<data name="MarkingLoggedInStateInfoNotLoggedIn" xml:space="preserve"> <data name="MarkingLoggedInStateInfoNotLoggedIn" xml:space="preserve">
<value>Kein Benutzer angemeldet.</value> <value>Kein Nutzer angemeldet.</value>
</data> </data>
<data name="MessageAppVersionIsOutdated" xml:space="preserve"> <data name="MessageAppVersionIsOutdated" xml:space="preserve">
<value>Diese Version der {0} App ist veraltet. Bitte auf aktuelle Version aktualisieren.</value> <value>Diese Version der {0} App ist veraltet. Bitte auf aktuelle Version aktualisieren.</value>
</data> </data>
<data name="QuestionSupportmailSubject" xml:space="preserve"> <data name="QuestionSupportmailSubject" xml:space="preserve">
<value>Betrifft die Anfrage/ Anmerkung die {0}-App oder ein allgemeines Thema?</value> <value>Betrifft die Anfrage/Anmerkung die {0}-App oder ein allgemeines Thema?</value>
</data> </data>
<data name="QuestionSupportmailAnswerApp" xml:space="preserve"> <data name="QuestionSupportmailAnswerApp" xml:space="preserve">
<value>{0}-App Anfrage</value> <value>{0}-App Anfrage</value>
@ -100,22 +100,22 @@
<value>Tarife</value> <value>Tarife</value>
</data> </data>
<data name="ErrorCloseLockBoldBlockedMessage" xml:space="preserve"> <data name="ErrorCloseLockBoldBlockedMessage" xml:space="preserve">
<value>Schloss ist blockiert. Bitte sicherstellen, dass keine Speiche oder ein anderer Gegenstand das Schloss blockiert und Vorgang wiederholen.</value> <value>Schloss ist blockiert. Bitte stellen Sie sicher, dass keine Speiche oder ein anderer Gegenstand das Schloss blockiert und wiederholen Sie den Vorgang.</value>
</data> </data>
<data name="ErrorCloseLockMovingMessage" xml:space="preserve"> <data name="ErrorCloseLockMovingMessage" xml:space="preserve">
<value>Schloss kann erst geschlossen werden, wenn Rad nicht mehr bewegt wird. Bitte Rad abstellen und Vorgang wiederholen.</value> <value>Schloss kann erst geschlossen werden, wenn Rad nicht mehr bewegt wird. Bitte Rad abstellen und Vorgang wiederholen.</value>
</data> </data>
<data name="ErrorBookedSearchMessage" xml:space="preserve"> <data name="ErrorBookedSearchMessage" xml:space="preserve">
<value>Ihr mobiles Gerät verbindet sich nicht mit dem Fahrradschloss. Bitte treten Sie möglichst nah an das Rad heran und probieren Sie es erneut. </value> <value>Ihr mobiles Gerät verbindet sich nicht mit dem Schloss. Bitte treten Sie möglichst nah an das Rad heran und probieren Sie es erneut. </value>
</data> </data>
<data name="ErrorReservedSearchMessage" xml:space="preserve"> <data name="ErrorReservedSearchMessage" xml:space="preserve">
<value>Ihr mobiles Gerät verbindet sich nicht mit dem Fahrradschloss. Bitte treten Sie möglichst nah an das Rad heran und probieren Sie es erneut. </value> <value>Ihr mobiles Gerät verbindet sich nicht mit dem Schloss. Bitte treten Sie möglichst nah an das Rad heran und probieren Sie es erneut. </value>
</data> </data>
<data name="ActivityTextBikesAtStationGetBikes" xml:space="preserve"> <data name="ActivityTextBikesAtStationGetBikes" xml:space="preserve">
<value>Lade Räder an Station...</value> <value>Lade Räder an Station...</value>
</data> </data>
<data name="ActivityTextMyBikesLoadingBikes" xml:space="preserve"> <data name="ActivityTextMyBikesLoadingBikes" xml:space="preserve">
<value>Lade meine Räder...</value> <value>Lade reservierte/gemietete Räder...</value>
</data> </data>
<data name="ActivityTextSearchBikes" xml:space="preserve"> <data name="ActivityTextSearchBikes" xml:space="preserve">
<value>Suche Schlösser...</value> <value>Suche Schlösser...</value>
@ -127,29 +127,29 @@
<value>Lade Stationen und Räder...</value> <value>Lade Stationen und Räder...</value>
</data> </data>
<data name="ErrorReturnBikeNotAtStationMessage" xml:space="preserve"> <data name="ErrorReturnBikeNotAtStationMessage" xml:space="preserve">
<value>Rückgabe ausserhalb von Station nicht möglich. Entfernung zur Station {0} ist {1} m.</value> <value>Rückgabe außerhalb einer Station nicht möglich. Entfernung zur nächsten Station {0} beträgt {1} m.</value>
</data> </data>
<data name="ErrorReturnBikeTitle" xml:space="preserve"> <data name="ErrorReturnBikeTitle" xml:space="preserve">
<value>Fehler bei Radrückgabe!</value> <value>Fehler beim Beenden der Miete!</value>
</data> </data>
<data name="ErrorReturnBikeLockClosedNoGPSMessage" xml:space="preserve"> <data name="ErrorReturnBikeLockClosedNoGPSMessage" xml:space="preserve">
<value>Fahrradrückgabe an unbekanntem Standort nicht möglich. <value>Beenden der Miete an unbekanntem Standort nicht möglich.
Eine Radrückgabe ist möglich, wenn Ein Mietende ist möglich, wenn
- beim Schliessen des Schlosses Standortinformation verfügbar ist - beim Schließen des Schlosses Standortinformation verfügbar ist
- beim Drücken von "Rad zurückgeben" das Rad in Reichweite ist und Standortinformation verfügbar ist.</value> - beim Drücken von "Miete beenden" das Rad in Reichweite ist und Standortinformation verfügbar ist</value>
</data> </data>
<data name="ErrorReturnBikeLockOpenNoGPSMessage" xml:space="preserve"> <data name="ErrorReturnBikeLockOpenNoGPSMessage" xml:space="preserve">
<value>Fahrradrückgabe an unbekanntem Standort nicht möglich. <value>Beenden der Miete an unbekanntem Standort nicht möglich.
Eine Radrückgabe ist nur möglich, wenn das Rad in Reichweite ist und Standortinformation verfügbar ist.</value> Mietende ist nur möglich, wenn das Rad in Reichweite ist und Standortinformation verfügbar ist.</value>
</data> </data>
<data name="ErrorSupportmailCreateAttachment" xml:space="preserve"> <data name="ErrorSupportmailCreateAttachment" xml:space="preserve">
<value>Mailanhang konnte nich erzeugt werden.</value> <value>Anhang konnte nich erzeugt werden.</value>
</data> </data>
<data name="ErrorSupportmailMailingFailed" xml:space="preserve"> <data name="ErrorSupportmailMailingFailed" xml:space="preserve">
<value>Mailapp konnte nicht geöffnet werden.</value> <value>Mailapp konnte nicht geöffnet werden. Stellen Sie sicher, dass auf Ihrem mobilen Gerät eine Mailapp installiert und eingerichtet ist!</value>
</data> </data>
<data name="ErrorSupportmailPhoningFailed" xml:space="preserve"> <data name="ErrorSupportmailPhoningFailed" xml:space="preserve">
<value>Telefonapp konnte nicht geöffnet werden.</value> <value>Telefonapp konnte nicht geöffnet werden. Stellen Sie sicher, dass auf Ihrem mobilen Gerät eine Telefonapp installiert ist!</value>
</data> </data>
<data name="MessageAnswerOk" xml:space="preserve"> <data name="MessageAnswerOk" xml:space="preserve">
<value>OK</value> <value>OK</value>
@ -158,7 +158,7 @@ Eine Radrückgabe ist nur möglich, wenn das Rad in Reichweite ist und Standorti
<value>Fragen? Hinweise?</value> <value>Fragen? Hinweise?</value>
</data> </data>
<data name="MessageRateMail" xml:space="preserve"> <data name="MessageRateMail" xml:space="preserve">
<value>Gefällt die {0}-App?</value> <value>Gefällt Ihnen die {0}-App?</value>
</data> </data>
<data name="MessageWaring" xml:space="preserve"> <data name="MessageWaring" xml:space="preserve">
<value>Warnung</value> <value>Warnung</value>
@ -172,14 +172,14 @@ Eine Radrückgabe ist nur möglich, wenn das Rad in Reichweite ist und Standorti
<data name="QuestionSupportmailAttachment" xml:space="preserve"> <data name="QuestionSupportmailAttachment" xml:space="preserve">
<value>Hiermit stimme ich der Übermittlung meiner Protokolldatei zu. <value>Hiermit stimme ich der Übermittlung meiner Protokolldatei zu.
Die Protokolldatei enthält Ihre App-Nutzungsdaten sowie Systeminformationen. Die Daten werden ausschließlich für Diagnosezwecke bzw. Verbesserung der App verwendet.</value> Die Protokolldatei enthält Ihre App-Nutzungsdaten sowie Systeminformationen. Die Daten werden ausschließlich für Diagnosezwecke bzw. Verbesserung der App verwendet und werden anschließend gelöscht.</value>
</data> </data>
<data name="QuestionTitle" xml:space="preserve"> <data name="QuestionTitle" xml:space="preserve">
<value>Frage</value> <value>Frage</value>
</data> </data>
<data name="MessageMapPageErrorAuthcookieUndefined" xml:space="preserve"> <data name="MessageMapPageErrorAuthcookieUndefined" xml:space="preserve">
<value>Sitzung ist abgelaufen. <value>Sitzung ist abgelaufen.
Bitte erneut in App anmelden.</value> Bitte melden Sie sich erneut an.</value>
</data> </data>
<data name="StatusTextReservationExpiredCodeMaxReservationTime" xml:space="preserve"> <data name="StatusTextReservationExpiredCodeMaxReservationTime" xml:space="preserve">
<value>Code ist {0}, max. Reservierungszeit von {1} Min. abgelaufen. <value>Code ist {0}, max. Reservierungszeit von {1} Min. abgelaufen.
@ -209,7 +209,7 @@ Bitte erneut in App anmelden.</value>
</value> </value>
</data> </data>
<data name="StatusTextAvailable" xml:space="preserve"> <data name="StatusTextAvailable" xml:space="preserve">
<value>Frei.</value> <value>Verfügbar.</value>
</data> </data>
<data name="StatusTextBookedCodeLocationSince" xml:space="preserve"> <data name="StatusTextBookedCodeLocationSince" xml:space="preserve">
<value>Code {0}, Standort {1}, gemietet seit {2}. <value>Code {0}, Standort {1}, gemietet seit {2}.
@ -234,7 +234,7 @@ Bitte erneut in App anmelden.</value>
<value>Passwort vergessen</value> <value>Passwort vergessen</value>
</data> </data>
<data name="ActionLoginRegister" xml:space="preserve"> <data name="ActionLoginRegister" xml:space="preserve">
<value>Registrieren</value> <value>Kostenlos registrieren</value>
</data> </data>
<data name="MarkingLoginEmailAddressLabel" xml:space="preserve"> <data name="MarkingLoginEmailAddressLabel" xml:space="preserve">
<value>E-Mail</value> <value>E-Mail</value>
@ -243,7 +243,7 @@ Bitte erneut in App anmelden.</value>
<value>E-Mail</value> <value>E-Mail</value>
</data> </data>
<data name="MarkingLoginPasswordLabel" xml:space="preserve"> <data name="MarkingLoginPasswordLabel" xml:space="preserve">
<value>Mindestens 8 Zeichen</value> <value>Mindestens acht Zeichen</value>
</data> </data>
<data name="MarkingLoginPasswordPlaceholder" xml:space="preserve"> <data name="MarkingLoginPasswordPlaceholder" xml:space="preserve">
<value>Passwort</value> <value>Passwort</value>
@ -270,45 +270,45 @@ Bitte erneut in App anmelden.</value>
<value>Fehler bei der Anmeldung!</value> <value>Fehler bei der Anmeldung!</value>
</data> </data>
<data name="MessageLoginRecoverPassword" xml:space="preserve"> <data name="MessageLoginRecoverPassword" xml:space="preserve">
<value>Bitte mit dem Internet verbinden zum Wiederherstellen des Passworts.</value> <value>Zur Wiederherstellung des Passworts bitte mit dem Internet verbinden.</value>
</data> </data>
<data name="MessageLoginRegisterNoNet" xml:space="preserve"> <data name="MessageLoginRegisterNoNet" xml:space="preserve">
<value>Bitte mit dem Internet verbinden zum Registrieren.</value> <value>Zur Registrierung bitte mit dem Internet verbinden.</value>
</data> </data>
<data name="MessageTitleHint" xml:space="preserve"> <data name="MessageTitleHint" xml:space="preserve">
<value>Hinweis</value> <value>Hinweis</value>
</data> </data>
<data name="ErrorOpenLockStillClosedMessage" xml:space="preserve"> <data name="ErrorOpenLockStillClosedMessage" xml:space="preserve">
<value>Nach Versuch Schloss zu öffnen wird Status geschlossen zurückgemeldet.</value> <value>Nach Versuch das Schloss zu öffnen, wird Status "geschlossen" zurückgemeldet.</value>
</data> </data>
<data name="ErrorOpenLockOutOfReachMessage" xml:space="preserve"> <data name="ErrorOpenLockOutOfReachMessage" xml:space="preserve">
<value>Schloss kann erst geöffnet werden, wenn Rad in der Nähe ist.</value> <value>Schloss kann erst geöffnet werden, wenn Rad in der Nähe ist.</value>
</data> </data>
<data name="ErrorCloseLockOutOfReachMessage" xml:space="preserve"> <data name="ErrorCloseLockOutOfReachMessage" xml:space="preserve">
<value>Schloss kann erst geschlossen werden, wenn das Rad in der Nähe ist. </value> <value>Schloss kann erst geschlossen werden, wenn Rad in der Nähe ist. </value>
</data> </data>
<data name="ErrorCloseLockOutOfReachStateReservedMessage" xml:space="preserve"> <data name="ErrorCloseLockOutOfReachStateReservedMessage" xml:space="preserve">
<value>Schloss kann erst geschlossen werden, wenn das Rad in der Nähe ist. <value>Schloss kann erst geschlossen werden, wenn Rad in der Nähe ist.
Bitte Schließen nochmals versuchen oder Rad dem Support melden!</value> Bitte Schließen nochmals versuchen oder Rad dem Betreiber melden!</value>
</data> </data>
<data name="ErrorCloseLockTitle" xml:space="preserve"> <data name="ErrorCloseLockTitle" xml:space="preserve">
<value>Schloss kann nicht geschlossen werden!</value> <value>Schloss kann nicht geschlossen werden!</value>
</data> </data>
<data name="ErrorCloseLockStillOpenMessage" xml:space="preserve"> <data name="ErrorCloseLockStillOpenMessage" xml:space="preserve">
<value>Nach Versuch Schloss zu schließen wird Status geöffnet zurückgemeldet.</value> <value>Nach Versuch Schloss zu schließen, wird Status "offen" zurückgemeldet.</value>
</data> </data>
<data name="ErrorCloseLockUnexpectedStateMessage" xml:space="preserve"> <data name="ErrorCloseLockUnexpectedStateMessage" xml:space="preserve">
<value>Schloss meldet Status "{0}".</value> <value>Schloss meldet Status "{0}".</value>
</data> </data>
<data name="ErrorCloseLockUnkErrorMessage" xml:space="preserve"> <data name="ErrorCloseLockUnkErrorMessage" xml:space="preserve">
<value>Bitte schließen nochmals versuchen oder Rad dem Support melden! <value>Bitte Schließen nochmals versuchen oder Rad dem Betreiber melden!
{0}</value> {0}</value>
</data> </data>
<data name="MessageBikesManagementLocationPermission" xml:space="preserve"> <data name="MessageBikesManagementLocationPermission" xml:space="preserve">
<value>Bitte Standortfreigabe erlauben, damit Fahrradschloss/ Schlösser verwaltet werden können.</value> <value>Bitte Standortfreigabe erlauben, damit Schloss/-schlösser verwaltet werden können.</value>
</data> </data>
<data name="MessageBikesManagementLocationPermissionOpenDialog" xml:space="preserve"> <data name="MessageBikesManagementLocationPermissionOpenDialog" xml:space="preserve">
<value>Bitte Standortfreigabe erlauben, damit Fahrradschloss/ Schlösser verwaltet werden können. <value>Bitte Standortfreigabe erlauben, damit Radschloss/-schlösser verwaltet werden können.
Freigabedialog öffen?</value> Freigabedialog öffen?</value>
</data> </data>
<data name="MessageCenterMapLocationPermissionOpenDialog" xml:space="preserve"> <data name="MessageCenterMapLocationPermissionOpenDialog" xml:space="preserve">
@ -316,7 +316,7 @@ Freigabedialog öffen?</value>
Freigabedialog öffen?</value> Freigabedialog öffen?</value>
</data> </data>
<data name="MessageBikesManagementLocationActivation" xml:space="preserve"> <data name="MessageBikesManagementLocationActivation" xml:space="preserve">
<value>Bitte Standort aktivieren, damit Fahrradschloss gefunden werden kann!</value> <value>Bitte Standort aktivieren, damit Schloss gefunden werden kann!</value>
</data> </data>
<data name="MessageAnswerNo" xml:space="preserve"> <data name="MessageAnswerNo" xml:space="preserve">
<value>Nein</value> <value>Nein</value>
@ -325,7 +325,7 @@ Freigabedialog öffen?</value>
<value>Ja</value> <value>Ja</value>
</data> </data>
<data name="MessageBikesManagementBluetoothActivation" xml:space="preserve"> <data name="MessageBikesManagementBluetoothActivation" xml:space="preserve">
<value>Bitte Bluetooth aktivieren, damit Fahrradschloss/ Schlösser verwaltet werden können.</value> <value>Bitte Bluetooth aktivieren, damit Schloss/-schlösser verwaltet werden können.</value>
</data> </data>
<data name="ActionSearchLock" xml:space="preserve"> <data name="ActionSearchLock" xml:space="preserve">
<value>Schloss suchen</value> <value>Schloss suchen</value>
@ -334,28 +334,28 @@ Freigabedialog öffen?</value>
<value>Einen Moment bitte...</value> <value>Einen Moment bitte...</value>
</data> </data>
<data name="ActivityTextOpeningLock" xml:space="preserve"> <data name="ActivityTextOpeningLock" xml:space="preserve">
<value>&lt;h4&gt;&lt;b&gt;Schloss öffnet.&lt;br/&gt;Bitte warten Sie bis es komplett geöffnet ist.&lt;/b&gt;&lt;/h4&gt;</value> <value>&lt;h4&gt;&lt;b&gt;Schloss öffnet.&lt;br/&gt;Bitte warten Sie, bis es komplett geöffnet ist.&lt;/b&gt;&lt;/h4&gt;</value>
</data> </data>
<data name="ActivityTextStartingUpdater" xml:space="preserve"> <data name="ActivityTextStartingUpdater" xml:space="preserve">
<value>Starte Aktualisierung...</value> <value>Aktualisiere...</value>
</data> </data>
<data name="ActivityTextStartingUpdatingLockingState" xml:space="preserve"> <data name="ActivityTextStartingUpdatingLockingState" xml:space="preserve">
<value>Aktualisiere Schlossstatus...</value> <value>Aktualisiere Schlossstatus...</value>
</data> </data>
<data name="ActivityTextReadingChargingLevel" xml:space="preserve"> <data name="ActivityTextReadingChargingLevel" xml:space="preserve">
<value>Lese Akkustatus...</value> <value>Lese Akkustand...</value>
</data> </data>
<data name="ActivityTextErrorStatusUpdateingLockstate" xml:space="preserve"> <data name="ActivityTextErrorStatusUpdateingLockstate" xml:space="preserve">
<value>Statusfehler beim Aktualisieren des Schlossstatusses.</value> <value>Statusfehler beim Aktualisieren des Schlossstatus.</value>
</data> </data>
<data name="ActivityTextErrorConnectionUpdateingLockstate" xml:space="preserve"> <data name="ActivityTextErrorConnectionUpdateingLockstate" xml:space="preserve">
<value>Verbingungsfehler beim Aktualisieren des Schlossstatusses.</value> <value>Verbingungsfehler beim Aktualisieren des Schlossstatus.</value>
</data> </data>
<data name="ActivityTextErrorNoWebUpdateingLockstate" xml:space="preserve"> <data name="ActivityTextErrorNoWebUpdateingLockstate" xml:space="preserve">
<value>Kein Netz beim Aktualisieren des Schlossstatusses.</value> <value>Um den Schlossstatus zu aktualisieren, wird Internet benötigt. Bitte stellen Sie eine Internetverbindung her!</value>
</data> </data>
<data name="ActivityTextClosingLock" xml:space="preserve"> <data name="ActivityTextClosingLock" xml:space="preserve">
<value>&lt;h4&gt;&lt;b&gt;Schloss schließt.&lt;br/&gt;Bitte warten Sie bis es komplett geschlossen ist.&lt;/b&gt;&lt;/h4&gt;</value> <value>&lt;h4&gt;&lt;b&gt;Schloss schließt.&lt;br/&gt;Bitte warten Sie, bis es komplett geschlossen ist.&lt;/b&gt;&lt;/h4&gt;</value>
</data> </data>
<data name="ChangeLog3_0_203" xml:space="preserve"> <data name="ChangeLog3_0_203" xml:space="preserve">
<value>Aktualisierrt auf aktuelle Schloss-Firmware.</value> <value>Aktualisierrt auf aktuelle Schloss-Firmware.</value>
@ -378,10 +378,10 @@ Zielplatform Android 11.</value>
<value>Reserviere Rad...</value> <value>Reserviere Rad...</value>
</data> </data>
<data name="ActivityTextErrorReadingChargingLevelGeneral" xml:space="preserve"> <data name="ActivityTextErrorReadingChargingLevelGeneral" xml:space="preserve">
<value>Akkustatus kann nicht gelesen werden.</value> <value>Akkustand kann nicht gelesen werden.</value>
</data> </data>
<data name="ActivityTextErrorReadingChargingLevelOutOfReach" xml:space="preserve"> <data name="ActivityTextErrorReadingChargingLevelOutOfReach" xml:space="preserve">
<value>Akkustatus kann erst gelesen werden, wenn Rad in der Nähe ist.</value> <value>Akkuladestand kann erst gelesen werden, wenn Rad in der Nähe ist.</value>
</data> </data>
<data name="ActivityTextRentingBike" xml:space="preserve"> <data name="ActivityTextRentingBike" xml:space="preserve">
<value>Miete Rad...</value> <value>Miete Rad...</value>
@ -393,10 +393,10 @@ Zielplatform Android 11.</value>
<value>Fehler beim Mieten des Rads!</value> <value>Fehler beim Mieten des Rads!</value>
</data> </data>
<data name="MessageRentingBikeErrorTooManyReservationsRentals" xml:space="preserve"> <data name="MessageRentingBikeErrorTooManyReservationsRentals" xml:space="preserve">
<value>Eine Miete des Rads {0} wurde abgelehnt, weil die maximal erlaubte Anzahl von {1} Reservierungen/ Buchungen bereits getätigt wurden.</value> <value>Eine Miete des Rads {0} wurde abgelehnt, weil die maximal erlaubte Anzahl von {1} Reservierungen/Mieten bereits getätigt wurden.</value>
</data> </data>
<data name="MessageReservationBikeErrorTooManyReservationsRentals" xml:space="preserve"> <data name="MessageReservationBikeErrorTooManyReservationsRentals" xml:space="preserve">
<value>Eine Reservierung des Rads {0} wurde abgelehnt, weil die maximal erlaubte Anzahl von {1} Reservierungen/ Buchungen bereits getätigt wurden.</value> <value>Eine Reservierung des Rads {0} wurde abgelehnt, weil die maximal erlaubte Anzahl von {1} Reservierungen/Mieten bereits getätigt wurden.</value>
</data> </data>
<data name="MessageErrorLockIsClosedThreeLines" xml:space="preserve"> <data name="MessageErrorLockIsClosedThreeLines" xml:space="preserve">
<value>Achtung: Schloss wird geschlossen! <value>Achtung: Schloss wird geschlossen!
@ -408,16 +408,16 @@ Zielplatform Android 11.</value>
{0}</value> {0}</value>
</data> </data>
<data name="ExceptionTextRentingBikeFailedGeneral" xml:space="preserve"> <data name="ExceptionTextRentingBikeFailedGeneral" xml:space="preserve">
<value>Die Miete des Fahrads Nr. {0} ist fehlgeschlagen.</value> <value>Die Miete des Rads {0} ist fehlgeschlagen.</value>
</data> </data>
<data name="ExceptionTextRentingBikeFailedUnavailalbe" xml:space="preserve"> <data name="ExceptionTextRentingBikeFailedUnavailalbe" xml:space="preserve">
<value>Die Miete des Rads Nr. {0} ist fehlgeschlagen, das Rad ist momentan nicht erreichbar.{1}</value> <value>Die Miete des Rads {0} ist fehlgeschlagen, das Rad ist momentan nicht erreichbar.{1}</value>
</data> </data>
<data name="ExceptionTextReservationBikeFailedGeneral" xml:space="preserve"> <data name="ExceptionTextReservationBikeFailedGeneral" xml:space="preserve">
<value>Die Reservierung des Fahrads Nr. {0} ist fehlgeschlagen.</value> <value>Die Reservierung des Rads {0} ist fehlgeschlagen.</value>
</data> </data>
<data name="ExceptionTextReservationBikeFailedUnavailalbe" xml:space="preserve"> <data name="ExceptionTextReservationBikeFailedUnavailalbe" xml:space="preserve">
<value>Die Reservierung des Rads Nr. {0} ist fehlgeschlagen, das Rad ist momentan nicht erreichbar.{1}</value> <value>Die Reservierung des Rads {0} ist fehlgeschlagen, das Rad ist momentan nicht erreichbar.{1}</value>
</data> </data>
<data name="ChangeLog3_0_208" xml:space="preserve"> <data name="ChangeLog3_0_208" xml:space="preserve">
<value>Kleinere Fehlerbehebungen.</value> <value>Kleinere Fehlerbehebungen.</value>
@ -430,8 +430,8 @@ Zielplatform Android 11.</value>
</data> </data>
<data name="MarkingBikeInfoErrorStateDisposableClosedDetected" xml:space="preserve"> <data name="MarkingBikeInfoErrorStateDisposableClosedDetected" xml:space="preserve">
<value>Ungülitiger Status von Rad {0} erkannt. <value>Ungülitiger Status von Rad {0} erkannt.
Ein nicht reserviertes oder gemietetes Rad sollte immer getrennt sein . Ein nicht reserviertes oder gemietetes Rad sollte immer getrennt sein.
Bitte App neu starten um Rad Infos zu bekommen.</value> Bitte App neu starten, um Radinfos zu bekommen.</value>
</data> </data>
<data name="MarkingBikeInfoErrorStateUnknownDetected" xml:space="preserve"> <data name="MarkingBikeInfoErrorStateUnknownDetected" xml:space="preserve">
<value>Ungültiger Mietstatus von Rad {0} erkannt. <value>Ungültiger Mietstatus von Rad {0} erkannt.
@ -442,13 +442,13 @@ Bitte App neu starten um Rad Infos zu bekommen.</value>
<value>Reservierung aufheben...</value> <value>Reservierung aufheben...</value>
</data> </data>
<data name="QuestionCancelReservation" xml:space="preserve"> <data name="QuestionCancelReservation" xml:space="preserve">
<value>Reservierung für Fahrrad {0} aufheben?</value> <value>Reservierung für Rad {0} aufheben?</value>
</data> </data>
<data name="ChangeLog3_0_209" xml:space="preserve"> <data name="ChangeLog3_0_209" xml:space="preserve">
<value>Kleinere Fehlerbehebung: Verbindung wird getrennt, sobald Rad verfügbar ist.</value> <value>Kleinere Fehlerbehebung: Verbindung wird getrennt, sobald Rad verfügbar ist.</value>
</data> </data>
<data name="QuestionReserveBike" xml:space="preserve"> <data name="QuestionReserveBike" xml:space="preserve">
<value>Fahrrad {0} kostenlos für {1} Min. reservieren?</value> <value>Rad {0} kostenlos für {1} Min. reservieren?</value>
</data> </data>
<data name="ActivityTextErrorDeserializationException" xml:space="preserve"> <data name="ActivityTextErrorDeserializationException" xml:space="preserve">
<value>Verbindungsfehler: Deserialisierung fehlgeschlagen.</value> <value>Verbindungsfehler: Deserialisierung fehlgeschlagen.</value>
@ -469,7 +469,7 @@ Bitte App neu starten um Rad Infos zu bekommen.</value>
<value>Abo-Preis</value> <value>Abo-Preis</value>
</data> </data>
<data name="MessageBikesManagementTariffDescriptionFeeEuroPerHour" xml:space="preserve"> <data name="MessageBikesManagementTariffDescriptionFeeEuroPerHour" xml:space="preserve">
<value>Mietgebühren</value> <value>Mietkosten</value>
</data> </data>
<data name="MessageBikesManagementTariffDescriptionFreeTimePerSession" xml:space="preserve"> <data name="MessageBikesManagementTariffDescriptionFreeTimePerSession" xml:space="preserve">
<value>Gratis Nutzung</value> <value>Gratis Nutzung</value>
@ -524,7 +524,7 @@ Bitte App neu starten um Rad Infos zu bekommen.</value>
</data> </data>
<data name="MessageCopriVersionIsOutdated" xml:space="preserve"> <data name="MessageCopriVersionIsOutdated" xml:space="preserve">
<value>Diese Version der {0} App ist nicht kompatibel mit dem erkannten Server. <value>Diese Version der {0} App ist nicht kompatibel mit dem erkannten Server.
Bitte kontaktieren sie den Support!</value> Bitte kontaktieren sie den Betreiber!</value>
</data> </data>
<data name="ChangeLog3_0_224" xml:space="preserve"> <data name="ChangeLog3_0_224" xml:space="preserve">
<value>Aktualisiert auf aktuelle Serverversion.</value> <value>Aktualisiert auf aktuelle Serverversion.</value>
@ -539,7 +539,7 @@ Bitte kontaktieren sie den Support!</value>
<value>Verbindungsfehler. Statusbeschreibung: {0}.</value> <value>Verbindungsfehler. Statusbeschreibung: {0}.</value>
</data> </data>
<data name="ActivityTextErrorWebExceptionGeneralError" xml:space="preserve"> <data name="ActivityTextErrorWebExceptionGeneralError" xml:space="preserve">
<value>Verbindungsfehler. Status statucode: {0}.</value> <value>Verbindungsfehler. Statuscode: {0}.</value>
</data> </data>
<data name="ChangeLog3_0_227" xml:space="preserve"> <data name="ChangeLog3_0_227" xml:space="preserve">
<value>Seite zur Eingabe von Rückmeldungen hinzugefügt, der nach Rückgabe eines Rads angezeigt wird.</value> <value>Seite zur Eingabe von Rückmeldungen hinzugefügt, der nach Rückgabe eines Rads angezeigt wird.</value>
@ -548,7 +548,7 @@ Bitte kontaktieren sie den Support!</value>
<value>Offline.</value> <value>Offline.</value>
</data> </data>
<data name="ActivityTextException" xml:space="preserve"> <data name="ActivityTextException" xml:space="preserve">
<value>Cache Daten.</value> <value>Cache genutzt.</value>
</data> </data>
<data name="ErrorReturnSubmitFeedbackMessage" xml:space="preserve"> <data name="ErrorReturnSubmitFeedbackMessage" xml:space="preserve">
<value>Ihre Rückmeldung konnte nicht an den Server übermittelt werden.</value> <value>Ihre Rückmeldung konnte nicht an den Server übermittelt werden.</value>
@ -573,7 +573,7 @@ Fehlerhandling verbessert.</value>
<value>Veraltetes Objekt durch aktuelles ersetzt.</value> <value>Veraltetes Objekt durch aktuelles ersetzt.</value>
</data> </data>
<data name="ErrorOpenLockTitle" xml:space="preserve"> <data name="ErrorOpenLockTitle" xml:space="preserve">
<value>Fehler beim Schloss Öffnen!</value> <value>Fehler beim Öffnen des Schlosses!</value>
</data> </data>
<data name="ChangeLog3_0_236" xml:space="preserve"> <data name="ChangeLog3_0_236" xml:space="preserve">
<value>Anzeige von Stationsnamen statt Nummern. <value>Anzeige von Stationsnamen statt Nummern.
@ -602,7 +602,7 @@ Layout Anzeige Radnamen und nummern verbessert.</value>
<value>{0} &lt;u&gt;kontaktieren&lt;/u&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 Rä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>
</data> </data>
<data name="MarkingContactNoStationInfoAvailableNoButton" xml:space="preserve"> <data name="MarkingContactNoStationInfoAvailableNoButton" xml:space="preserve">
<value>Betreiber kontaktieren?</value> <value>Betreiber kontaktieren?</value>
@ -611,7 +611,7 @@ Layout Anzeige Radnamen und nummern verbessert.</value>
<value>Auf der Kontaktseite werden Kontaktinformationen betreiberspezifisch angezeigt.</value> <value>Auf der Kontaktseite werden Kontaktinformationen betreiberspezifisch angezeigt.</value>
</data> </data>
<data name="MarkingSelectStationPage" xml:space="preserve"> <data name="MarkingSelectStationPage" xml:space="preserve">
<value>Station Auswählen</value> <value>Station auswählen</value>
</data> </data>
<data name="ActionSelectStation" xml:space="preserve"> <data name="ActionSelectStation" xml:space="preserve">
<value>Station auswählen</value> <value>Station auswählen</value>
@ -629,7 +629,7 @@ Layout Anzeige Radnamen und nummern verbessert.</value>
<value>Betreiber: {0}.</value> <value>Betreiber: {0}.</value>
</data> </data>
<data name="MarkingBikeSharingOperatorNoOperatorInfoAvailable" xml:space="preserve"> <data name="MarkingBikeSharingOperatorNoOperatorInfoAvailable" xml:space="preserve">
<value>Betreiber Kontaktieren.</value> <value>Betreiber kontaktieren.</value>
</data> </data>
<data name="MiniSurveyAskForAnswer" xml:space="preserve"> <data name="MiniSurveyAskForAnswer" xml:space="preserve">
<value>Bitte eine Antwort auswählen.</value> <value>Bitte eine Antwort auswählen.</value>
@ -669,23 +669,23 @@ Kleinere Verbesserungen.</value>
<value>Start Standortabfrage...</value> <value>Start Standortabfrage...</value>
</data> </data>
<data name="QuestionCloseLockAndReturnBike" xml:space="preserve"> <data name="QuestionCloseLockAndReturnBike" xml:space="preserve">
<value>Fahrrad {0} abschließen und zurückgeben?</value> <value>Rad {0} abschließen und Miete beenden?</value>
</data> </data>
<data name="QuestionReturnBike" xml:space="preserve"> <data name="QuestionReturnBike" xml:space="preserve">
<value>Fahrrad {0} zurückgeben? <value>Miete von Rad {0} beenden?
</value> </value>
</data> </data>
<data name="ActivityTextReturningBike" xml:space="preserve"> <data name="ActivityTextReturningBike" xml:space="preserve">
<value>Gebe Rad zurück...</value> <value>Beende Miete...</value>
</data> </data>
<data name="QuestionOpenLockAndBookBike" xml:space="preserve"> <data name="QuestionOpenLockAndBookBike" xml:space="preserve">
<value>Fahrrad {0} mieten und Schloss öffnen?</value> <value>Rad {0} mieten und Schloss öffnen?</value>
</data> </data>
<data name="ErrorReturnBikeNoWebMessage" xml:space="preserve"> <data name="ErrorReturnBikeNoWebMessage" xml:space="preserve">
<value>Internet muss erreichbar sein beim Zurückgeben des Rads.</value> <value>Um die Miete zu beenden, wird Internet benötigt. Bitte stellen Sie eine Internetverbindung her!</value>
</data> </data>
<data name="ErrorReturnBikeNoWebTitle" xml:space="preserve"> <data name="ErrorReturnBikeNoWebTitle" xml:space="preserve">
<value>Verbingungsfehler beim Zurückgeben des Rads!</value> <value>Verbingungsfehler beim Beenden der Miete!</value>
</data> </data>
<data name="ChangeLog3_0_244" xml:space="preserve"> <data name="ChangeLog3_0_244" xml:space="preserve">
<value>Abschließen von Rad und Radrückgabe beschleunigt.</value> <value>Abschließen von Rad und Radrückgabe beschleunigt.</value>
@ -730,20 +730,20 @@ Anzeige von Statusinformationen erweitert.
Fehlerbehebung: Supportmails können wieder verschickt werden.</value> Fehlerbehebung: Supportmails können wieder verschickt werden.</value>
</data> </data>
<data name="MessageMapPageErrorSwitch" xml:space="preserve"> <data name="MessageMapPageErrorSwitch" xml:space="preserve">
<value>Beim Umschalten zwischen Lasten-/ Stadträdern ist ein Fehler aufgetreten. <value>Beim Umschalten zwischen Lasten- und Stadträdern ist ein Fehler aufgetreten.
{0}</value> {0}</value>
</data> </data>
<data name="MessageErrorSelectBikeNoBikeFound" xml:space="preserve"> <data name="MessageErrorSelectBikeNoBikeFound" xml:space="preserve">
<value>Kein Fahrrad mit Id {0} gefunden.</value> <value>Kein Rad mit ID {0} gefunden.</value>
</data> </data>
<data name="MessageErrorSelectBikeTitle" xml:space="preserve"> <data name="MessageErrorSelectBikeTitle" xml:space="preserve">
<value>Fehler beim Rad Wählen!</value> <value>Fehler beim Auswählen des Rads!</value>
</data> </data>
<data name="ChangeLog3_0_277" xml:space="preserve"> <data name="ChangeLog3_0_277" xml:space="preserve">
<value>Fehlerbehebung: App schließt sich nicht mehr auf Fahrrad Wählen-Seite.</value> <value>Fehlerbehebung: App schließt sich nicht mehr auf Fahrrad Wählen-Seite.</value>
</data> </data>
<data name="ErrorBookedSearchMessageEscalationLevel1" xml:space="preserve"> <data name="ErrorBookedSearchMessageEscalationLevel1" xml:space="preserve">
<value>Ihr mobiles Gerät verbindet sich immer noch nicht mit dem Fahrradschloss. Bitte starten Sie die App oder sogar Ihr mobiles Gerät neu und wiederholen Sie den Vorgang.</value> <value>Ihr mobiles Gerät verbindet sich immer noch nicht mit dem Schloss. Bitte starten Sie die App oder sogar Ihr mobiles Gerät neu und wiederholen Sie den Vorgang.</value>
</data> </data>
<data name="MessageAnswerCancel" xml:space="preserve"> <data name="MessageAnswerCancel" xml:space="preserve">
<value>Abbrechen</value> <value>Abbrechen</value>
@ -755,12 +755,13 @@ Fehlerbehebung: Supportmails können wieder verschickt werden.</value>
<value>Fehler beim Verbinden mit Schloss!</value> <value>Fehler beim Verbinden mit Schloss!</value>
</data> </data>
<data name="ErrorBookedSearchMessageEscalationLevel2" xml:space="preserve"> <data name="ErrorBookedSearchMessageEscalationLevel2" xml:space="preserve">
<value>Es kann leider weiterhin keine Verbindung zwischen Ihrem mobilen Gerät und dem Fahrradschloss aufgebaut werden. Bitte kontaktieren Sie den Kundensupport. <value>Es kann weiterhin keine Verbindung zwischen Ihrem mobilen Gerät und dem Schloss aufgebaut werden. Rufen Sie den Betreiber an!
Als aller letzten Ausweg das Schloss bitte per Hand schließen UND den Kundensupport zu kontaktieren, damit dieser Ihre kostenpflichtige Miete beenden kann. Dazu: Alternativ:
1. App schließen, 1. App schließen,
2. auf den Knopf oben am Schloss kurz drücken und schnell loslassen sobald bis dieser zu blinken beginnt, 2. auf den Knopf oben am Schloss kurz drücken und sofort loslassen, sobald Knopf zu blinken beginnt,
3. warten, bis das Schloss vollständig geschlossen ist und geschlossen bleibt. </value> 3. sicherstellen, dass das Schloss vollständig geschlossen ist und geschlossen bleibt.
4. E-Mail an Betreiber schicken (ansonsten läuft Ihre kostenpflichtige Miete weiter!): Problembeschreibung, Rad-ID, Abgabestation.</value>
</data> </data>
<data name="ChangeLog3_0_278" xml:space="preserve"> <data name="ChangeLog3_0_278" xml:space="preserve">
<value>Hinweise hinzugefügt, um das Schließen des Schlosses zu erleichtern, falls dies nicht beim ersten Versuch gelingt.</value> <value>Hinweise hinzugefügt, um das Schließen des Schlosses zu erleichtern, falls dies nicht beim ersten Versuch gelingt.</value>
@ -778,16 +779,16 @@ Als aller letzten Ausweg das Schloss bitte per Hand schließen UND den Kundensup
<value>Schloss kann erst gefunden werden, wenn reserviertes Rad in der Nähe ist.</value> <value>Schloss kann erst gefunden werden, wenn reserviertes Rad in der Nähe ist.</value>
</data> </data>
<data name="MessageErrorConnectTitle" xml:space="preserve"> <data name="MessageErrorConnectTitle" xml:space="preserve">
<value>Fehler bei Verbinden mit Schloss!</value> <value>Fehler beim Verbinden mit Schloss!</value>
</data> </data>
<data name="ErrorConnectLockGeneralErrorMessage" xml:space="preserve"> <data name="ErrorConnectLockGeneralErrorMessage" xml:space="preserve">
<value>Kommunikationsfehler bei Schlosssuche.</value> <value>Kommunikationsfehler bei Schlosssuche.</value>
</data> </data>
<data name="ErrorConnectLockRentedBikeNoWebMessage" xml:space="preserve"> <data name="ErrorConnectLockRentedBikeNoWebMessage" xml:space="preserve">
<value>Internet muss erreichbar sein um Verbindung mit Schloss für gemietetes Rad herzustellen.</value> <value>Internet muss erreichbar sein, um Verbindung mit Schloss für gemietetes Rad herzustellen. Bitte stellen Sie eine Internetverbindung her!</value>
</data> </data>
<data name="ErrorConnectLockReservedBikeNoWebMessage" xml:space="preserve"> <data name="ErrorConnectLockReservedBikeNoWebMessage" xml:space="preserve">
<value>Internet muss erreichbar sein um Verbindung mit Schloss für reserviertes Rad herzustellen.</value> <value>Internet muss erreichbar sein, um Verbindung mit Schloss für reserviertes Rad herzustellen. Bitte stellen Sie eine Internetverbindung her!</value>
</data> </data>
<data name="ErrorFindLockReservedBikeNoStausMessage" xml:space="preserve"> <data name="ErrorFindLockReservedBikeNoStausMessage" xml:space="preserve">
<value>Schlossstatus des reservierten Rads konnte nicht ermittelt werden.</value> <value>Schlossstatus des reservierten Rads konnte nicht ermittelt werden.</value>
@ -796,12 +797,12 @@ Als aller letzten Ausweg das Schloss bitte per Hand schließen UND den Kundensup
<value>Bitte Bluetooth anschalten, anderenfalls ist eine Verbindung mit dem Schloss nicht möglich.</value> <value>Bitte Bluetooth anschalten, anderenfalls ist eine Verbindung mit dem Schloss nicht möglich.</value>
</data> </data>
<data name="ErrorFindLockLocationPermissionMissing" xml:space="preserve"> <data name="ErrorFindLockLocationPermissionMissing" xml:space="preserve">
<value>Bitte Standort-Zugriffsfreigabe erteilen, anderenfalls ist eine Verbindung mit dem Schloss nicht möglich. <value>Bitte Standortfreigabe erteilen, anderenfalls ist eine Verbindung mit dem Schloss nicht möglich.
</value> </value>
</data> </data>
<data name="ErrorFindLockLocationOff" xml:space="preserve"> <data name="ErrorFindLockLocationOff" xml:space="preserve">
<value>Bitte Standortbestimmung aktivieren, anderenfalls ist eine Verbindung mit dem Schloss nicht möglich.</value> <value>Bitte Standortdienste aktivieren, anderenfalls ist eine Verbindung mit dem Schloss nicht möglich.</value>
</data> </data>
<data name="ChangeLog3_0_280" xml:space="preserve"> <data name="ChangeLog3_0_280" xml:space="preserve">
<value>Fehlermeldungen verbessert für die Fälle, dass <value>Fehlermeldungen verbessert für die Fälle, dass
@ -810,14 +811,14 @@ Als aller letzten Ausweg das Schloss bitte per Hand schließen UND den Kundensup
- die Standorterkennung deaktiviert ist.</value> - die Standorterkennung deaktiviert ist.</value>
</data> </data>
<data name="ErrorReservedSearchMessageEscalationLevel1" xml:space="preserve"> <data name="ErrorReservedSearchMessageEscalationLevel1" xml:space="preserve">
<value>Ihr mobiles Gerät verbindet sich immer noch nicht mit dem Fahrradschloss. Bitte starten Sie die App oder sogar Ihr mobiles Gerät neu und wiederholen Sie den Vorgang.</value> <value>Ihr mobiles Gerät verbindet sich weiterhin nicht mit dem Schloss. Bitte starten Sie die App oder sogar Ihr mobiles Gerät neu und wiederholen Sie den Vorgang.</value>
</data> </data>
<data name="ChangeLog3_0_282" xml:space="preserve"> <data name="ChangeLog3_0_282" xml:space="preserve">
<value>Freigabe-Erlaubnisanfragen unter iOS ausführlicher formuliert. <value>Freigabe-Erlaubnisanfragen unter iOS ausführlicher formuliert.
Hinweise, um das Verbinden Schlosses zu erleichtern, falls dies nicht beim ersten Versuch gelingt, erweitert.</value> Hinweise, um das Verbinden Schlosses zu erleichtern, falls dies nicht beim ersten Versuch gelingt, erweitert.</value>
</data> </data>
<data name="ExceptionTextSessionExpired" xml:space="preserve"> <data name="ExceptionTextSessionExpired" xml:space="preserve">
<value>Die Sitzung ist abgelaufen. Bitte neu anmelden.</value> <value>Die Sitzung ist abgelaufen. Bitte melden Sie sich erneut an.</value>
</data> </data>
<data name="ActivityTextAuthcookieNotDefinedException" xml:space="preserve"> <data name="ActivityTextAuthcookieNotDefinedException" xml:space="preserve">
<value>Auth. abgelaufen</value> <value>Auth. abgelaufen</value>
@ -829,17 +830,17 @@ Hinweise, um das Verbinden Schlosses zu erleichtern, falls dies nicht beim erste
<value>Abmelden</value> <value>Abmelden</value>
</data> </data>
<data name="MessageAccountPageManagePersonalData" xml:space="preserve"> <data name="MessageAccountPageManagePersonalData" xml:space="preserve">
<value>Persönliche Daten Verwalten</value> <value>Persönliche Daten verwalten</value>
</data> </data>
<data name="ChangeLog3_0_285" xml:space="preserve"> <data name="ChangeLog3_0_285" xml:space="preserve">
<value>Framework aktualisiert. <value>Framework aktualisiert.
Activity Indicator zu Konto-Verwaltungsseiten hinzugefügt und Logging erweitert.</value> Activity Indicator zu Konto-Verwaltungsseiten hinzugefügt und Logging erweitert.</value>
</data> </data>
<data name="ActivityTextStartReturningBike" xml:space="preserve"> <data name="ActivityTextStartReturningBike" xml:space="preserve">
<value>Starte Rückgabe...</value> <value>Starte Miete beenden...</value>
</data> </data>
<data name="ExceptionTextWebConnectFailureException" xml:space="preserve"> <data name="ExceptionTextWebConnectFailureException" xml:space="preserve">
<value>Ist WLAN verfügbar/ Mobilfunknetz vefügbar und mobile Daten aktiviert / ... ?</value> <value>Ist WLAN/Mobilfunknetz vefügbar und mobile Daten aktiviert?</value>
</data> </data>
<data name="ChangeLog3_0_289" xml:space="preserve"> <data name="ChangeLog3_0_289" xml:space="preserve">
<value>Flyout-Menü Überschift verschönert.</value> <value>Flyout-Menü Überschift verschönert.</value>
@ -867,7 +868,7 @@ Kleinere Fehlerbehebungen.
<value>Protokollierungsstufe</value> <value>Protokollierungsstufe</value>
</data> </data>
<data name="MarkingShowHideBikesOfType" xml:space="preserve"> <data name="MarkingShowHideBikesOfType" xml:space="preserve">
<value>Ausblenden/ Einblenden</value> <value>Ein-/Ausblenden</value>
</data> </data>
<data name="MarkingVerboseErrorMessage" xml:space="preserve"> <data name="MarkingVerboseErrorMessage" xml:space="preserve">
<value>Ausführliche Fehlermeldungen</value> <value>Ausführliche Fehlermeldungen</value>
@ -904,7 +905,7 @@ Kleinere Fehlerbehebungen.
<value>Neues Schloss unterstützt.</value> <value>Neues Schloss unterstützt.</value>
</data> </data>
<data name="ActionGiveFeedback" xml:space="preserve"> <data name="ActionGiveFeedback" xml:space="preserve">
<value>Rückmeldung Geben</value> <value>Rückmeldung geben</value>
</data> </data>
<data name="ActionContactMailAppReleated" xml:space="preserve"> <data name="ActionContactMailAppReleated" xml:space="preserve">
<value>Rückmeldung zur App</value> <value>Rückmeldung zur App</value>
@ -929,7 +930,7 @@ Kleinere Fehlerbehebungen.
<value>Verbingungsfehler beim Aufheben der Reservierung!</value> <value>Verbingungsfehler beim Aufheben der Reservierung!</value>
</data> </data>
<data name="MessageOpeningLockErrorConnectionTitle" xml:space="preserve"> <data name="MessageOpeningLockErrorConnectionTitle" xml:space="preserve">
<value>Verbindungsfehler beim Schlossöffnen!</value> <value>Verbindungsfehler beim Öffnen des Schlosses!</value>
</data> </data>
<data name="ActivityTextSubmittingFeedback" xml:space="preserve"> <data name="ActivityTextSubmittingFeedback" xml:space="preserve">
<value>Sende Rückmeldung...</value> <value>Sende Rückmeldung...</value>
@ -950,13 +951,13 @@ Kleinere Fehlerbehebungen.
<value>Rad ist in Ordnung</value> <value>Rad ist in Ordnung</value>
</data> </data>
<data name="MarkingReturnBikeErrorDescriptionInputPlaceholder" xml:space="preserve"> <data name="MarkingReturnBikeErrorDescriptionInputPlaceholder" xml:space="preserve">
<value>Bitte Zustand/ Defekt hier beschreiben.</value> <value>Bitte Zustand/Defekt hier beschreiben.</value>
</data> </data>
<data name="MarkingReturnBikeFeedbackInputPlaceholder" xml:space="preserve"> <data name="MarkingReturnBikeFeedbackInputPlaceholder" xml:space="preserve">
<value>Bei Bedarf bitte hier Rückmeldung eingeben.</value> <value>Bei Bedarf bitte hier Rückmeldung eingeben.</value>
</data> </data>
<data name="MarkingReturnBikeMainMessage" xml:space="preserve"> <data name="MarkingReturnBikeMainMessage" xml:space="preserve">
<value>Fahrrad erfolgreich zurückgegeben!</value> <value>Rad erfolgreich zurückgegeben!</value>
</data> </data>
<data name="MarkingDriveBatteryTitel" xml:space="preserve"> <data name="MarkingDriveBatteryTitel" xml:space="preserve">
<value>Aktueller Akkuladestand:</value> <value>Aktueller Akkuladestand:</value>
@ -965,10 +966,10 @@ Kleinere Fehlerbehebungen.
<value>Für Mein konrad Nutzer: Anzeige des Akkuladestands für E-Bikes und Abfrage des Ladestands nach Radrückgabe.</value> <value>Für Mein konrad Nutzer: Anzeige des Akkuladestands für E-Bikes und Abfrage des Ladestands nach Radrückgabe.</value>
</data> </data>
<data name="StatusTextLowBatteryLevel" xml:space="preserve"> <data name="StatusTextLowBatteryLevel" xml:space="preserve">
<value>Die verbleibende Ladung des Fahrradakkus war zuletzt niedrig. Bitte überprüfen Sie diese vor der Fahrt auf dem Fahrraddisplay. Das Rad kann innerhalb 5 Minuten kostenlos zurückgegeben werden.</value> <value>Die verbleibende Ladung des Fahrradakkus war zuletzt niedrig. Bitte überprüfen Sie diese vor der Fahrt auf dem Fahrraddisplay. Die Miete kann innerhalb 5 Minuten kostenlos abgebrochen werden.</value>
</data> </data>
<data name="StatusTextCopriLock" xml:space="preserve"> <data name="StatusTextCopriLock" xml:space="preserve">
<value>Zur Fahrpause schließen Sie das Fahrradschloss manuell, nicht über die App. Zum Beenden der kostenpflichtigen Miete schieben Sie das Rad in eine zugelassene Station und bestätigen das Mietende in der App; das Schloss schließt automatisch.</value> <value>Zur Fahrpause schließen Sie das Schloss manuell, nicht über die App. Zum Beenden der kostenpflichtigen Miete schieben Sie das Rad in eine zugelassene Station und bestätigen das Mietende in der App; das Schloss schließt automatisch.</value>
</data> </data>
<data name="ChangeLog3_0_335" xml:space="preserve"> <data name="ChangeLog3_0_335" xml:space="preserve">
<value>Sharee.bike Design verbessert.</value> <value>Sharee.bike Design verbessert.</value>
@ -977,7 +978,7 @@ Kleinere Fehlerbehebungen.
<value>Für Lastenrad Bayern Nutzende: Akkuladestand für E-Bikes wird angezeigt.</value> <value>Für Lastenrad Bayern Nutzende: Akkuladestand für E-Bikes wird angezeigt.</value>
</data> </data>
<data name="ChangeLog3_0_337_MK" xml:space="preserve"> <data name="ChangeLog3_0_337_MK" xml:space="preserve">
<value>Sie werden nun informiert, wenn die Ladung des Fahrradakkus zuletzt als sehr niedrig angegeben wurde. Um die Zuverlässigkeit der Akkustandanzeige in der App zu gewährleisten, geben Sie bitte am Ende Ihrer Fahrt mit einem E-Lastenrad den aktuellen Ladestand in die App ein.</value> <value>Sie werden nun informiert, wenn die Ladung des Radakkus zuletzt als sehr niedrig angegeben wurde. Um die Zuverlässigkeit der Akkustandanzeige in der App zu gewährleisten, geben Sie bitte am Ende Ihrer Fahrt mit einem E-Lastenrad den aktuellen Ladestand in die App ein.</value>
</data> </data>
<data name="ChangeLog3_0_337_SB" xml:space="preserve"> <data name="ChangeLog3_0_337_SB" xml:space="preserve">
<value>Die App hat ein neues Design! --- Sie sind Beta-Tester? Geben Sie uns jederzeit hilfreiche Rückmeldung über 'Kontakt - Rückmeldung zur App'. Sie sind noch kein Beta-Tester? Werden Sie es und erhalten Sie tolle neue Features vor allen anderen!</value> <value>Die App hat ein neues Design! --- Sie sind Beta-Tester? Geben Sie uns jederzeit hilfreiche Rückmeldung über 'Kontakt - Rückmeldung zur App'. Sie sind noch kein Beta-Tester? Werden Sie es und erhalten Sie tolle neue Features vor allen anderen!</value>
@ -1012,7 +1013,7 @@ Außerdem: Kleine Grafiken lassen auf einen Blick erkennen um was für einen Rad
<value>Einwilligung</value> <value>Einwilligung</value>
</data> </data>
<data name="PlaceholderFindBike" xml:space="preserve"> <data name="PlaceholderFindBike" xml:space="preserve">
<value>Fahrrad-Nummer hier eingeben</value> <value>Rad-Nummer hier eingeben</value>
</data> </data>
<data name="ChangeLog3_0_339_MK" xml:space="preserve"> <data name="ChangeLog3_0_339_MK" xml:space="preserve">
<value>Die Lastenräder aus den Vororten zeigen nun ihre Heimatstation im Namen an. Diese Räder müssen dort wieder abgeben werden! <value>Die Lastenräder aus den Vororten zeigen nun ihre Heimatstation im Namen an. Diese Räder müssen dort wieder abgeben werden!
@ -1109,10 +1110,10 @@ Probieren Sie es aus!</value>
<value>Zum Aktualisieren ziehen.</value> <value>Zum Aktualisieren ziehen.</value>
</data> </data>
<data name="MarkingBikesAtStationNoBikesAvailable" xml:space="preserve"> <data name="MarkingBikesAtStationNoBikesAvailable" xml:space="preserve">
<value>Momentan sind keine Fahrräder an dieser Station verfügbar.</value> <value>Momentan sind keine Räder an dieser Station verfügbar.</value>
</data> </data>
<data name="MarkingMyBikesNoBikesReservedRented" xml:space="preserve"> <data name="MarkingMyBikesNoBikesReservedRented" xml:space="preserve">
<value>Momentan sind keine Fahrräder auf Benutzer {0} reserviert/ gebucht.</value> <value>Momentan sind keine Räder von Nutzer {0} reserviert/gemietet.</value>
</data> </data>
<data name="MessageTitleInformation" xml:space="preserve"> <data name="MessageTitleInformation" xml:space="preserve">
<value>Information</value> <value>Information</value>
@ -1125,7 +1126,8 @@ Probieren Sie es aus!</value>
Achtung! Ihre Miete hat bereits begonnen. Achtung! Ihre Miete hat bereits begonnen.
Wenn sich das Schloss weiterhin nicht öffnen lässt, vergewissern Sie sich, dass das Schloss geschlossen ist und geben Sie das Rad zurück. Bitte melden Sie es dem Support!</value> Wenn sich das Schloss weiterhin nicht öffnen lässt, vergewissern Sie sich, dass das Schloss geschlossen ist und geben Sie das Rad zurück.
Wichtig: Schicken Sie eine E-Mail an den Betreiber (ansonsten läuft Ihre kostenpflichtige Miete weiter!): Problembeschreibung, Radnummer, Abgabestation.</value>
</data> </data>
<data name="ErrorOpenLockStillClosedTitle" xml:space="preserve"> <data name="ErrorOpenLockStillClosedTitle" xml:space="preserve">
<value>Schloss kann nicht geöffnet werden!</value> <value>Schloss kann nicht geöffnet werden!</value>
@ -1143,4 +1145,26 @@ Wenn sich das Schloss weiterhin nicht öffnen lässt, vergewissern Sie sich, das
<data name="ChangeLog_3_0_361_MK_SB" xml:space="preserve"> <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> <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> </data>
<data name="ErrorReturnBikeLockClosedStartGetGPSExceptionMessage" xml:space="preserve">
<value>Beenden der Miete an unbekanntem Standort is nicht möglich.
Fehler beim Start der Standortabfrage!</value>
</data>
<data name="ErrorReturnBikeLockClosedGetGPSExceptionMessage" xml:space="preserve">
<value>Beenden der Miete an unbekanntem Standort is nicht möglich.
Fehler bei der Standortabfrage!</value>
</data>
<data name="Error_ReturnBike_Station_Location_Message" xml:space="preserve">
<value>Wir konnten das Rad keiner Station zuordnen. Dazu benötigen wir Ihre Standortinformationen, während Sie direkt neben dem Rad stehen. Nur dann kann Ihre Miete beendet werden!
Treten Sie an das Rad heran, schalten Sie Bluetooth und Standortdienste ein und versuchen Sie es erneut.</value>
</data>
<data name="ChangeLog_3_0_362_MK_SB" xml:space="preserve">
<value>Einige Bezeichnungen wurden vereinheitlicht, z.B:&lt;br/&gt;
- was bisher unter 'Rad zurückgeben' lief, heißt nun immer 'Miete beenden'.&lt;br/&gt;
- der 'Betreiber' ist die für die Radflotte zuständige Personengruppe, zu der bei Bedarf Kontakt aufgenommen wird.&lt;br/&gt;
&lt;br/&gt;
Außerdem:&lt;br/&gt;
- Kleinere Fehlerbehebungen&lt;br/&gt;
- Paketaktualisierungen</value>
</data>
</root> </root>

View file

@ -127,7 +127,7 @@
<value>Close lock</value> <value>Close lock</value>
</data> </data>
<data name="ActionCloseAndReturn" xml:space="preserve"> <data name="ActionCloseAndReturn" xml:space="preserve">
<value>Close lock &amp; return bike</value> <value>Close lock &amp; end rental</value>
</data> </data>
<data name="ActionOpen" xml:space="preserve"> <data name="ActionOpen" xml:space="preserve">
<value>Open lock</value> <value>Open lock</value>
@ -142,7 +142,7 @@
<value>Reserve bike</value> <value>Reserve bike</value>
</data> </data>
<data name="ActionReturn" xml:space="preserve"> <data name="ActionReturn" xml:space="preserve">
<value>Return bike</value> <value>End rental</value>
</data> </data>
<data name="ActivityTextMapLoadingStationsAndBikes" xml:space="preserve"> <data name="ActivityTextMapLoadingStationsAndBikes" xml:space="preserve">
<value>Loading Stations and Bikes...</value> <value>Loading Stations and Bikes...</value>
@ -160,29 +160,29 @@
<value>Your mobile device does not connect to the bike lock. Please step as close as possible to the bike and try again.</value> <value>Your mobile device does not connect to the bike lock. Please step as close as possible to the bike and try again.</value>
</data> </data>
<data name="ErrorReturnBikeLockClosedNoGPSMessage" xml:space="preserve"> <data name="ErrorReturnBikeLockClosedNoGPSMessage" xml:space="preserve">
<value>Returning bike at an unknown location is not possible. <value>End rental at an unknown location is not possible.
Bike can be returned if Rental can be ended if
- location information is available when closing lock - location information is available when closing lock
- bike is in reach and location information is available when pressing button "Return bike"</value> - bike is in reach and location information is available when pressing button "End rental"</value>
</data> </data>
<data name="ErrorReturnBikeLockOpenNoGPSMessage" xml:space="preserve"> <data name="ErrorReturnBikeLockOpenNoGPSMessage" xml:space="preserve">
<value>Returning bike at an unknown location is not possible. <value>End rental at an unknown location is not possible.
Bike can only be returned if bike is in reach and location information is available.</value> Rental can only be ended if bike is in reach and location information is available.</value>
</data> </data>
<data name="ErrorReturnBikeNotAtStationMessage" xml:space="preserve"> <data name="ErrorReturnBikeNotAtStationMessage" xml:space="preserve">
<value>Returning bike outside of station is not possible. Distance to station {0} is {1} m.</value> <value>End rental outside of station is not possible. Distance to station {0} is {1} m.</value>
</data> </data>
<data name="ErrorReturnBikeTitle" xml:space="preserve"> <data name="ErrorReturnBikeTitle" xml:space="preserve">
<value>Error returning bike!</value> <value>Error at ending rental!</value>
</data> </data>
<data name="ErrorSupportmailCreateAttachment" xml:space="preserve"> <data name="ErrorSupportmailCreateAttachment" xml:space="preserve">
<value>Attachment could not be created.</value> <value>Attachment could not be created.</value>
</data> </data>
<data name="ErrorSupportmailMailingFailed" xml:space="preserve"> <data name="ErrorSupportmailMailingFailed" xml:space="preserve">
<value>Opening mail app failed.</value> <value>Opening mail app failed. Make sure you have a mail app installed on your mobile device!</value>
</data> </data>
<data name="ErrorSupportmailPhoningFailed" xml:space="preserve"> <data name="ErrorSupportmailPhoningFailed" xml:space="preserve">
<value>Opening phone app failed.</value> <value>Opening phone app failed. Make sure you have a phone app installed on your mobile device!</value>
</data> </data>
<data name="MarkingAbout" xml:space="preserve"> <data name="MarkingAbout" xml:space="preserve">
<value>Legal Information</value> <value>Legal Information</value>
@ -243,13 +243,13 @@ Bike can only be returned if bike is in reach and location information is avail
</data> </data>
<data name="MessageMapPageErrorAuthcookieUndefined" xml:space="preserve"> <data name="MessageMapPageErrorAuthcookieUndefined" xml:space="preserve">
<value>Session has expired. <value>Session has expired.
Please login to app once again.</value> Please log in again.</value>
</data> </data>
<data name="MessagePhoneMail" xml:space="preserve"> <data name="MessagePhoneMail" xml:space="preserve">
<value>Urgent questions?</value> <value>Urgent questions?</value>
</data> </data>
<data name="MessageRateMail" xml:space="preserve"> <data name="MessageRateMail" xml:space="preserve">
<value>Are you enjoying the {0}-App?</value> <value>Are you enjoying the {0}-app?</value>
</data> </data>
<data name="MessageWaring" xml:space="preserve"> <data name="MessageWaring" xml:space="preserve">
<value>Warning</value> <value>Warning</value>
@ -269,10 +269,10 @@ Please login to app once again.</value>
<data name="QuestionSupportmailAttachment" xml:space="preserve"> <data name="QuestionSupportmailAttachment" xml:space="preserve">
<value>I hereby consent to the transmission of my log file. <value>I hereby consent to the transmission of my log file.
The log file contains your app usage data as well as system information. The data will only be used for diagnostic purposes or to improve the app.</value> The log file contains your app usage data as well as system information. The data will only be used for diagnostic purposes or to improve the app and then deleted.</value>
</data> </data>
<data name="QuestionSupportmailSubject" xml:space="preserve"> <data name="QuestionSupportmailSubject" xml:space="preserve">
<value>Does your request/ comment relate to the {0}-app or to a more general subject?</value> <value>Does your request/comment relate to the {0}-app or to a more general subject?</value>
</data> </data>
<data name="QuestionTitle" xml:space="preserve"> <data name="QuestionTitle" xml:space="preserve">
<value>Question</value> <value>Question</value>
@ -284,7 +284,7 @@ The log file contains your app usage data as well as system information. The dat
<value>Centering map...</value> <value>Centering map...</value>
</data> </data>
<data name="ActivityTextMyBikesLoadingBikes" xml:space="preserve"> <data name="ActivityTextMyBikesLoadingBikes" xml:space="preserve">
<value>Loading reserved/ booked bikes...</value> <value>Loading reserved/rented bikes...</value>
</data> </data>
<data name="ActivityTextSearchBikes" xml:space="preserve"> <data name="ActivityTextSearchBikes" xml:space="preserve">
<value>Searching locks...</value> <value>Searching locks...</value>
@ -338,7 +338,7 @@ The log file contains your app usage data as well as system information. The dat
<value>Password forgotten</value> <value>Password forgotten</value>
</data> </data>
<data name="ActionLoginRegister" xml:space="preserve"> <data name="ActionLoginRegister" xml:space="preserve">
<value>Register</value> <value>Register for free</value>
</data> </data>
<data name="MarkingLoginEmailAddressLabel" xml:space="preserve"> <data name="MarkingLoginEmailAddressLabel" xml:space="preserve">
<value>E-mail</value> <value>E-mail</value>
@ -357,7 +357,7 @@ The log file contains your app usage data as well as system information. The dat
</value> </value>
</data> </data>
<data name="MarkingLoginPasswordLabel" xml:space="preserve"> <data name="MarkingLoginPasswordLabel" xml:space="preserve">
<value>At least 8 characters</value> <value>At least eight characters</value>
</data> </data>
<data name="MarkingLoginPasswordPlaceholder" xml:space="preserve"> <data name="MarkingLoginPasswordPlaceholder" xml:space="preserve">
<value>Password</value> <value>Password</value>
@ -394,7 +394,7 @@ The log file contains your app usage data as well as system information. The dat
</data> </data>
<data name="ErrorCloseLockOutOfReachStateReservedMessage" xml:space="preserve"> <data name="ErrorCloseLockOutOfReachStateReservedMessage" xml:space="preserve">
<value>Lock cannot be closed until bike is near. <value>Lock cannot be closed until bike is near.
Please try again to close bike or report bike to support!</value> Please try again to close bike or report bike to operator!</value>
</data> </data>
<data name="ErrorCloseLockTitle" xml:space="preserve"> <data name="ErrorCloseLockTitle" xml:space="preserve">
<value>Lock can not be closed!</value> <value>Lock can not be closed!</value>
@ -406,7 +406,7 @@ Please try again to close bike or report bike to support!</value>
<value>Lock reports state "{0}".</value> <value>Lock reports state "{0}".</value>
</data> </data>
<data name="ErrorCloseLockUnkErrorMessage" xml:space="preserve"> <data name="ErrorCloseLockUnkErrorMessage" xml:space="preserve">
<value>Please try to lock again or report bike to support! <value>Please try to lock again or report bike to operator!
{0}</value> {0}</value>
</data> </data>
<data name="MessageBikesManagementLocationPermission" xml:space="preserve"> <data name="MessageBikesManagementLocationPermission" xml:space="preserve">
@ -457,7 +457,7 @@ Open sharing dialog?</value>
<value>Connection error on updating locking status.</value> <value>Connection error on updating locking status.</value>
</data> </data>
<data name="ActivityTextErrorNoWebUpdateingLockstate" xml:space="preserve"> <data name="ActivityTextErrorNoWebUpdateingLockstate" xml:space="preserve">
<value>No web error on updating locking status.</value> <value>Internet must be available for updating lock status. Please establish an Internet connection!</value>
</data> </data>
<data name="ActivityTextClosingLock" xml:space="preserve"> <data name="ActivityTextClosingLock" xml:space="preserve">
<value>&lt;h4&gt;&lt;b&gt;Lock is closing.&lt;br/&gt;Please wait until it is completely closed.&lt;/b&gt;&lt;/h4&gt;</value> <value>&lt;h4&gt;&lt;b&gt;Lock is closing.&lt;br/&gt;Please wait until it is completely closed.&lt;/b&gt;&lt;/h4&gt;</value>
@ -501,10 +501,10 @@ Targets Android 11.</value>
<value>Error when renting the bike!</value> <value>Error when renting the bike!</value>
</data> </data>
<data name="MessageRentingBikeErrorTooManyReservationsRentals" xml:space="preserve"> <data name="MessageRentingBikeErrorTooManyReservationsRentals" xml:space="preserve">
<value>A rental of bike {0} was rejected because the maximum allowed number of {1} reservations/ rentals had already been made.</value> <value>A rental of bike {0} was rejected because the maximum allowed number of {1} reservations/rentals had already been made.</value>
</data> </data>
<data name="MessageReservationBikeErrorTooManyReservationsRentals" xml:space="preserve"> <data name="MessageReservationBikeErrorTooManyReservationsRentals" xml:space="preserve">
<value>A reservation of bike {0} was rejected because the maximum allowed number of {1} reservations/ rentals had already been made.</value> <value>A reservation of bike {0} was rejected because the maximum allowed number of {1} reservations/rentals had already been made.</value>
</data> </data>
<data name="MessageErrorLockIsClosedThreeLines" xml:space="preserve"> <data name="MessageErrorLockIsClosedThreeLines" xml:space="preserve">
<value>Attention: Lock is closed! <value>Attention: Lock is closed!
@ -516,16 +516,16 @@ Targets Android 11.</value>
{0}</value> {0}</value>
</data> </data>
<data name="ExceptionTextRentingBikeFailedGeneral" xml:space="preserve"> <data name="ExceptionTextRentingBikeFailedGeneral" xml:space="preserve">
<value>The rental of bike No. {0} has failed.</value> <value>The rental of bike {0} has failed.</value>
</data> </data>
<data name="ExceptionTextRentingBikeFailedUnavailalbe" xml:space="preserve"> <data name="ExceptionTextRentingBikeFailedUnavailalbe" xml:space="preserve">
<value>The rental of bike No. {0} has failed, the bike is currently unavailable.{1}</value> <value>The rental of bike {0} has failed, the bike is currently unavailable. {1}</value>
</data> </data>
<data name="ExceptionTextReservationBikeFailedGeneral" xml:space="preserve"> <data name="ExceptionTextReservationBikeFailedGeneral" xml:space="preserve">
<value>The reservation of bike no. {0} has failed.</value> <value>The reservation of bike {0} has failed.</value>
</data> </data>
<data name="ExceptionTextReservationBikeFailedUnavailalbe" xml:space="preserve"> <data name="ExceptionTextReservationBikeFailedUnavailalbe" xml:space="preserve">
<value>The reservation of bike No. {0} has failed, the bike is currently unavailable.{1}</value> <value>The reservation of bike {0} has failed, the bike is currently unavailable. {1}</value>
</data> </data>
<data name="ChangeLog3_0_208" xml:space="preserve"> <data name="ChangeLog3_0_208" xml:space="preserve">
<value>Minor fixes.</value> <value>Minor fixes.</value>
@ -581,7 +581,7 @@ Please restart app in order to get bike info.</value>
<value>€/hour</value> <value>€/hour</value>
</data> </data>
<data name="MessageBikesManagementTariffDescriptionFeeEuroPerHour" xml:space="preserve"> <data name="MessageBikesManagementTariffDescriptionFeeEuroPerHour" xml:space="preserve">
<value>Rental fees</value> <value>Rental charges</value>
</data> </data>
<data name="MessageBikesManagementTariffDescriptionFreeTimePerSession" xml:space="preserve"> <data name="MessageBikesManagementTariffDescriptionFreeTimePerSession" xml:space="preserve">
<value>Free use</value> <value>Free use</value>
@ -590,7 +590,7 @@ Please restart app in order to get bike info.</value>
<value>hour(s)/day</value> <value>hour(s)/day</value>
</data> </data>
<data name="MessageBikesManagementTariffDescriptionMaxFeeEuroPerDay" xml:space="preserve"> <data name="MessageBikesManagementTariffDescriptionMaxFeeEuroPerDay" xml:space="preserve">
<value>Max. fee</value> <value>Max. charges</value>
</data> </data>
<data name="MessageBikesManagementTariffDescriptionTariffHeader" xml:space="preserve"> <data name="MessageBikesManagementTariffDescriptionTariffHeader" xml:space="preserve">
<value>Tariff</value> <value>Tariff</value>
@ -633,7 +633,7 @@ Please restart app in order to get bike info.</value>
</data> </data>
<data name="MessageCopriVersionIsOutdated" xml:space="preserve"> <data name="MessageCopriVersionIsOutdated" xml:space="preserve">
<value>This version of the {0} App is not compatible with server detected. <value>This version of the {0} App is not compatible with server detected.
Please contact the support for help.</value> Please contact operator for help.</value>
</data> </data>
<data name="ChangeLog3_0_224" xml:space="preserve"> <data name="ChangeLog3_0_224" xml:space="preserve">
<value>Updated for latest server version.</value> <value>Updated for latest server version.</value>
@ -647,7 +647,7 @@ Please contact the support for help.</value>
<value>Connection error. Status description: {0}.</value> <value>Connection error. Status description: {0}.</value>
</data> </data>
<data name="ChangeLog3_0_227" xml:space="preserve"> <data name="ChangeLog3_0_227" xml:space="preserve">
<value>Feedback dialog added which is shown after returning bike.</value> <value>Feedback dialog added which is shown after ending rental.</value>
</data> </data>
<data name="ActivityTextConnectionStateOffline" xml:space="preserve"> <data name="ActivityTextConnectionStateOffline" xml:space="preserve">
<value>Offline.</value> <value>Offline.</value>
@ -681,11 +681,11 @@ Error handling improved.</value>
<value>Ensure that no obstacle prevents lock from opening and try again.</value> <value>Ensure that no obstacle prevents lock from opening and try again.</value>
</data> </data>
<data name="ErrorOpenLockBoldStatusIsUnknownMessage" xml:space="preserve"> <data name="ErrorOpenLockBoldStatusIsUnknownMessage" xml:space="preserve">
<value>The lock could not be opened correctly. Please try again. <value>The lock could not be opened correctly. Try again!
Attention! Your rental has already started. Attention! Your rental has already started.
If the lock still won't open, make sure the lock is closed and end rental.
If the lock still won't open, make sure the lock is closed and return the bike. Please report it to the support!</value> Important: Send an email to the operator (otherwise your paid rental will continue!) with: Problem description, bike number, drop-off station.</value>
</data> </data>
<data name="ErrorOpenLockStillClosedTitle" xml:space="preserve"> <data name="ErrorOpenLockStillClosedTitle" xml:space="preserve">
<value>Lock can not be opened!</value> <value>Lock can not be opened!</value>
@ -696,7 +696,7 @@ Error message when opening lock fails improved.
Layout of bike names and id display improved.</value> Layout of bike names and id display improved.</value>
</data> </data>
<data name="ChangeLog3_0_237" xml:space="preserve"> <data name="ChangeLog3_0_237" xml:space="preserve">
<value>Hard- and software information send to backend when returning bike.</value> <value>Hard- and software information send to backend when ending rental.</value>
</data> </data>
<data name="ChangeLog3_0_239" xml:space="preserve"> <data name="ChangeLog3_0_239" xml:space="preserve">
<value>Bugfix: Bike description is displayed correctly again.</value> <value>Bugfix: Bike description is displayed correctly again.</value>
@ -741,7 +741,7 @@ Layout of bike names and id display improved.</value>
<value>Operator: {0}.</value> <value>Operator: {0}.</value>
</data> </data>
<data name="MarkingBikeSharingOperatorNoOperatorInfoAvailable" xml:space="preserve"> <data name="MarkingBikeSharingOperatorNoOperatorInfoAvailable" xml:space="preserve">
<value>Contact Operator.</value> <value>Contact operator.</value>
</data> </data>
<data name="MiniSurveyAskForAnswer" xml:space="preserve"> <data name="MiniSurveyAskForAnswer" xml:space="preserve">
<value>Select an answer please.</value> <value>Select an answer please.</value>
@ -775,28 +775,28 @@ Minor fixes.</value>
<value>Closing the lock and ending the rental is not possible.</value> <value>Closing the lock and ending the rental is not possible.</value>
</data> </data>
<data name="MessageErrorQueryLocationStartTitle" xml:space="preserve"> <data name="MessageErrorQueryLocationStartTitle" xml:space="preserve">
<value>Error Start Query Location!</value> <value>Error start query location!</value>
</data> </data>
<data name="MessageErrorQueryLocationTitle" xml:space="preserve"> <data name="MessageErrorQueryLocationTitle" xml:space="preserve">
<value>Error Query Location!</value> <value>Error query location!</value>
</data> </data>
<data name="QuestionCloseLockAndReturnBike" xml:space="preserve"> <data name="QuestionCloseLockAndReturnBike" xml:space="preserve">
<value>Close lock and return bike {0}?</value> <value>Close lock and end rental of bike {0}?</value>
</data> </data>
<data name="ActivityTextReturningBike" xml:space="preserve"> <data name="ActivityTextReturningBike" xml:space="preserve">
<value>Returning bike...</value> <value>Ending rental...</value>
</data> </data>
<data name="QuestionReturnBike" xml:space="preserve"> <data name="QuestionReturnBike" xml:space="preserve">
<value>Return bike {0}?</value> <value>End rental of bike {0}?</value>
</data> </data>
<data name="ChangeLog3_0_244" xml:space="preserve"> <data name="ChangeLog3_0_244" xml:space="preserve">
<value>Closing lock and returning bike speeded up.</value> <value>Closing lock and returning bike speeded up.</value>
</data> </data>
<data name="ErrorReturnBikeNoWebMessage" xml:space="preserve"> <data name="ErrorReturnBikeNoWebMessage" xml:space="preserve">
<value>Internet must be available when returning the bike.</value> <value>Internet must be available when ending rental. Please establish an Internet connection!</value>
</data> </data>
<data name="ErrorReturnBikeNoWebTitle" xml:space="preserve"> <data name="ErrorReturnBikeNoWebTitle" xml:space="preserve">
<value>Connection error when returning the bike!</value> <value>Connection error when ending rental.</value>
</data> </data>
<data name="ChangeLog3_0_249" xml:space="preserve"> <data name="ChangeLog3_0_249" xml:space="preserve">
<value>Third-party components updated.</value> <value>Third-party components updated.</value>
@ -838,7 +838,7 @@ Display of status information extended.
Bugfix: Sending support mails works again. </value> Bugfix: Sending support mails works again. </value>
</data> </data>
<data name="MessageMapPageErrorSwitch" xml:space="preserve"> <data name="MessageMapPageErrorSwitch" xml:space="preserve">
<value>An error occurred switching from cargo bikes/ city bikes. <value>An error occurred switching between cargo and city bikes.
{0}</value> {0}</value>
</data> </data>
<data name="MessageErrorSelectBikeNoBikeFound" xml:space="preserve"> <data name="MessageErrorSelectBikeNoBikeFound" xml:space="preserve">
@ -863,12 +863,13 @@ Bugfix: Sending support mails works again. </value>
<value>Error when connecting with lock!</value> <value>Error when connecting with lock!</value>
</data> </data>
<data name="ErrorBookedSearchMessageEscalationLevel2" xml:space="preserve"> <data name="ErrorBookedSearchMessageEscalationLevel2" xml:space="preserve">
<value>Unfortunately, it is still not possible to establish a connection between your mobile device and the bike lock. Please contact customer support. <value>It is still not possible to establish a connection between your mobile device and the bike lock. Please contact operator!
As a last resort, please close the lock by hand AND contact customer support so that they can terminate your chargeable rental. To do this: Alternative:
1. close the app, 1. close app,
2. press the button at the top of the lock briefly and quickly release it as soon as it starts flashing, 2. press the button at the top of the lock briefly and release it as soon as it starts flashing,
3. wait until the lock is completely closed and remains closed.</value> 3. make sure that the lock is completely closed and remains closed.
4. send e-mail to operator (otherwise your chargeable rental will continue!): Problem description, Drop-off station.</value>
</data> </data>
<data name="ChangeLog3_0_278" xml:space="preserve"> <data name="ChangeLog3_0_278" xml:space="preserve">
<value>Hints added to ease closing of lock in case closing does not succeed on first try.</value> <value>Hints added to ease closing of lock in case closing does not succeed on first try.</value>
@ -892,10 +893,10 @@ As a last resort, please close the lock by hand AND contact customer support so
<value>Communication error during lock search.</value> <value>Communication error during lock search.</value>
</data> </data>
<data name="ErrorConnectLockRentedBikeNoWebMessage" xml:space="preserve"> <data name="ErrorConnectLockRentedBikeNoWebMessage" xml:space="preserve">
<value>Internet must be reachable to connect to lock of rented bike.</value> <value>Internet must be reachable to connect to lock of rented bike. Please establish an Internet connection!</value>
</data> </data>
<data name="ErrorConnectLockReservedBikeNoWebMessage" xml:space="preserve"> <data name="ErrorConnectLockReservedBikeNoWebMessage" xml:space="preserve">
<value>Internet must be reachable to connect to lock of reserved bike.</value> <value>Internet must be reachable to connect to lock of reserved bike. Please establish an Internet connection!</value>
</data> </data>
<data name="ErrorFindLockReservedBikeNoStausMessage" xml:space="preserve"> <data name="ErrorFindLockReservedBikeNoStausMessage" xml:space="preserve">
<value>Lock status of the reserved bike could not be determined.</value> <value>Lock status of the reserved bike could not be determined.</value>
@ -907,7 +908,7 @@ As a last resort, please close the lock by hand AND contact customer support so
<value>Please grant location permissions, otherwise lock cannot be connected.</value> <value>Please grant location permissions, otherwise lock cannot be connected.</value>
</data> </data>
<data name="ErrorFindLockLocationOff" xml:space="preserve"> <data name="ErrorFindLockLocationOff" xml:space="preserve">
<value>Please turn Location on, otherwise lock cannot be connected.</value> <value>Please turn location services on, otherwise lock cannot be connected.</value>
</data> </data>
<data name="ChangeLog3_0_280" xml:space="preserve"> <data name="ChangeLog3_0_280" xml:space="preserve">
<value>Errormessages improved for szenarios when <value>Errormessages improved for szenarios when
@ -942,10 +943,10 @@ Hints to ease connecting to lock in case connecting does not succeed on first tr
Activity indicator added account management pages and logging extended.</value> Activity indicator added account management pages and logging extended.</value>
</data> </data>
<data name="ActivityTextStartReturningBike" xml:space="preserve"> <data name="ActivityTextStartReturningBike" xml:space="preserve">
<value>Starting bike return...</value> <value>Starting end rental...</value>
</data> </data>
<data name="ExceptionTextWebConnectFailureException" xml:space="preserve"> <data name="ExceptionTextWebConnectFailureException" xml:space="preserve">
<value>Is WIFI available/ mobile network available and mobile data activated / ... ?</value> <value>Is WIFI/mobile network available and mobile data activated?</value>
</data> </data>
<data name="ChangeLog3_0_289" xml:space="preserve"> <data name="ChangeLog3_0_289" xml:space="preserve">
<value>Flyout menu header improved.</value> <value>Flyout menu header improved.</value>
@ -972,7 +973,7 @@ Minor bugfixes.</value>
<value>Logging level</value> <value>Logging level</value>
</data> </data>
<data name="MarkingShowHideBikesOfType" xml:space="preserve"> <data name="MarkingShowHideBikesOfType" xml:space="preserve">
<value>Show/ hide</value> <value>Show/hide</value>
</data> </data>
<data name="MarkingVerboseErrorMessage" xml:space="preserve"> <data name="MarkingVerboseErrorMessage" xml:space="preserve">
<value>Verbose error messages</value> <value>Verbose error messages</value>
@ -1009,13 +1010,13 @@ Minor bugfixes.</value>
<value>Support for new lock type added.</value> <value>Support for new lock type added.</value>
</data> </data>
<data name="ActionGiveFeedback" xml:space="preserve"> <data name="ActionGiveFeedback" xml:space="preserve">
<value>Give Feedback</value> <value>Give feedback</value>
</data> </data>
<data name="ActionContactMailAppReleated" xml:space="preserve"> <data name="ActionContactMailAppReleated" xml:space="preserve">
<value>Feedback about the App</value> <value>Feedback about the app</value>
</data> </data>
<data name="MiscContactMailAppReleatedSubject" xml:space="preserve"> <data name="MiscContactMailAppReleatedSubject" xml:space="preserve">
<value>{0}-App Releated Request</value> <value>{0}-app releated request</value>
<comment>Subject of contact mail to ("Feedback about the app").</comment> <comment>Subject of contact mail to ("Feedback about the app").</comment>
</data> </data>
<data name="MessageReservingBikeErrorConnectionTitle" xml:space="preserve"> <data name="MessageReservingBikeErrorConnectionTitle" xml:space="preserve">
@ -1061,7 +1062,7 @@ Minor bugfixes.</value>
<value>Please enter feedback here if needed.</value> <value>Please enter feedback here if needed.</value>
</data> </data>
<data name="MarkingReturnBikeMainMessage" xml:space="preserve"> <data name="MarkingReturnBikeMainMessage" xml:space="preserve">
<value>Bike successfully returned!</value> <value>Rental successfully ended!</value>
</data> </data>
<data name="MarkingDriveBatteryTitel" xml:space="preserve"> <data name="MarkingDriveBatteryTitel" xml:space="preserve">
<value>Current battery level:</value> <value>Current battery level:</value>
@ -1070,7 +1071,7 @@ Minor bugfixes.</value>
<value>For Mein konrad users: Battery charging level is displayed for ebikes and is queried after return of bike.</value> <value>For Mein konrad users: Battery charging level is displayed for ebikes and is queried after return of bike.</value>
</data> </data>
<data name="StatusTextLowBatteryLevel" xml:space="preserve"> <data name="StatusTextLowBatteryLevel" xml:space="preserve">
<value>The remaining power of the bike battery was low recently. Please check it on the bike display before riding. The bike can be returned within 5 minutes free of charge.</value> <value>The remaining power of the bike battery was low recently. Please check it on the bike display before riding. The rental can be canceled within 5 minutes free of charge.</value>
</data> </data>
<data name="StatusTextCopriLock" xml:space="preserve"> <data name="StatusTextCopriLock" xml:space="preserve">
<value>At pausing ride, you close the bike lock manually, not via the app. To end the chargeable rental, slide the bike into an authorized station and confirm the end of the rental in the app; the lock closes automatically.</value> <value>At pausing ride, you close the bike lock manually, not via the app. To end the chargeable rental, slide the bike into an authorized station and confirm the end of the rental in the app; the lock closes automatically.</value>
@ -1215,7 +1216,7 @@ Try it out!</value>
<value>There are currently no bicycles available at this station.</value> <value>There are currently no bicycles available at this station.</value>
</data> </data>
<data name="MarkingMyBikesNoBikesReservedRented" xml:space="preserve"> <data name="MarkingMyBikesNoBikesReservedRented" xml:space="preserve">
<value>There are currently no bicycles reserved/booked on user {0}.</value> <value>There are currently no bikes reserved/rented by user {0}.</value>
</data> </data>
<data name="MessageTitleInformation" xml:space="preserve"> <data name="MessageTitleInformation" xml:space="preserve">
<value>Information</value> <value>Information</value>
@ -1228,9 +1229,31 @@ Try it out!</value>
<value>Minor improvements.</value> <value>Minor improvements.</value>
</data> </data>
<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"> <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> <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> </data>
<data name="ErrorReturnBikeLockClosedStartGetGPSExceptionMessage" xml:space="preserve">
<value>End rental at an unknown location is not possible.
Start getting geolocation failed.</value>
</data>
<data name="ErrorReturnBikeLockClosedGetGPSExceptionMessage" xml:space="preserve">
<value>End rental at an unknown location is not possible.
Getting geolocation failed.</value>
</data>
<data name="Error_ReturnBike_Station_Location_Message" xml:space="preserve">
<value>We could not assign the bike to any station. For this we need your location information while you are standing right next to the bike. Only then your rental can be terminated!
Approach the bike, turn on Bluetooth and Location services and try again.</value>
</data>
<data name="ChangeLog_3_0_362_MK_SB" xml:space="preserve">
<value>Some terms have been standardized, e.g:&lt;br/&gt;
- what used to be called 'return bike' is now always called 'end rental'.&lt;br/&gt;
- The 'operator' is the group of people responsible for the bike fleet, who will be contacted if necessary.&lt;br/&gt;
&lt;br/&gt;
Also:&lt;br/&gt;
- Minor bug fixes&lt;br/&gt;
- Package updates</value>
</data>
</root> </root>

View file

@ -19,8 +19,9 @@
<target state="final">Schloss schließen</target> <target state="final">Schloss schließen</target>
</trans-unit> </trans-unit>
<trans-unit id="ActionCloseAndReturn" translate="yes" xml:space="preserve"> <trans-unit id="ActionCloseAndReturn" translate="yes" xml:space="preserve">
<source>Close lock &amp; return bike</source> <source>Close lock &amp; end rental</source>
<target state="final">Schloss schließen &amp; Miete beenden</target> <target state="needs-review-translation">Schloss schließen &amp; Miete beenden</target>
<note from="MultilingualUpdate" annotates="source" priority="2">Please verify the translations accuracy as the source string was updated after it was translated.</note>
</trans-unit> </trans-unit>
<trans-unit id="ActionOpen" translate="yes" xml:space="preserve"> <trans-unit id="ActionOpen" translate="yes" xml:space="preserve">
<source>Open lock</source> <source>Open lock</source>
@ -39,8 +40,9 @@
<target state="final">Rad reservieren</target> <target state="final">Rad reservieren</target>
</trans-unit> </trans-unit>
<trans-unit id="ActionReturn" translate="yes" xml:space="preserve"> <trans-unit id="ActionReturn" translate="yes" xml:space="preserve">
<source>Return bike</source> <source>End rental</source>
<target state="final">Miete beenden</target> <target state="needs-review-translation">Miete beenden</target>
<note from="MultilingualUpdate" annotates="source" priority="2">Please verify the translations accuracy as the source string was updated after it was translated.</note>
</trans-unit> </trans-unit>
<trans-unit id="MarkingMapPage" translate="yes" xml:space="preserve"> <trans-unit id="MarkingMapPage" translate="yes" xml:space="preserve">
<source>Bike Locations</source> <source>Bike Locations</source>
@ -48,7 +50,7 @@
</trans-unit> </trans-unit>
<trans-unit id="MessageLoginWelcome" translate="yes" xml:space="preserve"> <trans-unit id="MessageLoginWelcome" translate="yes" xml:space="preserve">
<source>User {0} successfully logged in.</source> <source>User {0} successfully logged in.</source>
<target state="final">Benutzer {0} erfolgreich angemeldet.</target> <target state="translated">Nutzer {0} erfolgreich angemeldet.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageLoginWelcomeTitle" translate="yes" xml:space="preserve"> <trans-unit id="MessageLoginWelcomeTitle" translate="yes" xml:space="preserve">
<source>Welcome!</source> <source>Welcome!</source>
@ -68,15 +70,15 @@
</trans-unit> </trans-unit>
<trans-unit id="MarkingLoggedInStateInfoNotLoggedIn" translate="yes" xml:space="preserve"> <trans-unit id="MarkingLoggedInStateInfoNotLoggedIn" translate="yes" xml:space="preserve">
<source>No user logged in.</source> <source>No user logged in.</source>
<target state="final">Kein Benutzer angemeldet.</target> <target state="translated">Kein Nutzer angemeldet.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageAppVersionIsOutdated" translate="yes" xml:space="preserve"> <trans-unit id="MessageAppVersionIsOutdated" translate="yes" xml:space="preserve">
<source>This version of the {0} App is outdated. Please update to the latest version.</source> <source>This version of the {0} App is outdated. Please update to the latest version.</source>
<target state="final">Diese Version der {0} App ist veraltet. Bitte auf aktuelle Version aktualisieren.</target> <target state="final">Diese Version der {0} App ist veraltet. Bitte auf aktuelle Version aktualisieren.</target>
</trans-unit> </trans-unit>
<trans-unit id="QuestionSupportmailSubject" translate="yes" xml:space="preserve"> <trans-unit id="QuestionSupportmailSubject" translate="yes" xml:space="preserve">
<source>Does your request/ comment relate to the {0}-app or to a more general subject?</source> <source>Does your request/comment relate to the {0}-app or to a more general subject?</source>
<target state="final">Betrifft die Anfrage/ Anmerkung die {0}-App oder ein allgemeines Thema?</target> <target state="translated">Betrifft die Anfrage/Anmerkung die {0}-App oder ein allgemeines Thema?</target>
</trans-unit> </trans-unit>
<trans-unit id="QuestionSupportmailAnswerApp" translate="yes" xml:space="preserve"> <trans-unit id="QuestionSupportmailAnswerApp" translate="yes" xml:space="preserve">
<source>{0} app request</source> <source>{0} app request</source>
@ -124,7 +126,7 @@
</trans-unit> </trans-unit>
<trans-unit id="ErrorCloseLockBoldBlockedMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorCloseLockBoldBlockedMessage" translate="yes" xml:space="preserve">
<source>Lock is blocked. Please ensure that no spoke or any other obstacle prevents the lock from closing and try again.</source> <source>Lock is blocked. Please ensure that no spoke or any other obstacle prevents the lock from closing and try again.</source>
<target state="translated">Schloss ist blockiert. Bitte sicherstellen, dass keine Speiche oder ein anderer Gegenstand das Schloss blockiert und Vorgang wiederholen.</target> <target state="translated">Schloss ist blockiert. Bitte stellen Sie sicher, dass keine Speiche oder ein anderer Gegenstand das Schloss blockiert und wiederholen Sie den Vorgang.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorCloseLockMovingMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorCloseLockMovingMessage" translate="yes" xml:space="preserve">
<source>Lock can only be closed if bike is not moving. Please park bike and try again.</source> <source>Lock can only be closed if bike is not moving. Please park bike and try again.</source>
@ -132,19 +134,19 @@
</trans-unit> </trans-unit>
<trans-unit id="ErrorBookedSearchMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorBookedSearchMessage" translate="yes" xml:space="preserve">
<source>Your mobile device does not connect to the bike lock. Please step as close as possible to the bike and try again.</source> <source>Your mobile device does not connect to the bike lock. Please step as close as possible to the bike and try again.</source>
<target state="translated">Ihr mobiles Gerät verbindet sich nicht mit dem Fahrradschloss. Bitte treten Sie möglichst nah an das Rad heran und probieren Sie es erneut. </target> <target state="translated">Ihr mobiles Gerät verbindet sich nicht mit dem Schloss. Bitte treten Sie möglichst nah an das Rad heran und probieren Sie es erneut. </target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorReservedSearchMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorReservedSearchMessage" translate="yes" xml:space="preserve">
<source>Your mobile device does not connect to the bike lock. Please step as close as possible to the bike and try again.</source> <source>Your mobile device does not connect to the bike lock. Please step as close as possible to the bike and try again.</source>
<target state="translated">Ihr mobiles Gerät verbindet sich nicht mit dem Fahrradschloss. Bitte treten Sie möglichst nah an das Rad heran und probieren Sie es erneut. </target> <target state="translated">Ihr mobiles Gerät verbindet sich nicht mit dem Schloss. Bitte treten Sie möglichst nah an das Rad heran und probieren Sie es erneut. </target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextBikesAtStationGetBikes" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextBikesAtStationGetBikes" translate="yes" xml:space="preserve">
<source>Loading bikes located at station...</source> <source>Loading bikes located at station...</source>
<target state="translated">Lade Räder an Station...</target> <target state="translated">Lade Räder an Station...</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextMyBikesLoadingBikes" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextMyBikesLoadingBikes" translate="yes" xml:space="preserve">
<source>Loading reserved/ booked bikes...</source> <source>Loading reserved/rented bikes...</source>
<target state="translated">Lade meine Räder...</target> <target state="translated">Lade reservierte/gemietete Räder...</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextSearchBikes" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextSearchBikes" translate="yes" xml:space="preserve">
<source>Searching locks...</source> <source>Searching locks...</source>
@ -159,40 +161,40 @@
<target state="translated">Lade Stationen und Räder...</target> <target state="translated">Lade Stationen und Räder...</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorReturnBikeNotAtStationMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorReturnBikeNotAtStationMessage" translate="yes" xml:space="preserve">
<source>Returning bike outside of station is not possible. Distance to station {0} is {1} m.</source> <source>End rental outside of station is not possible. Distance to station {0} is {1} m.</source>
<target state="translated">Rückgabe ausserhalb von Station nicht möglich. Entfernung zur Station {0} ist {1} m.</target> <target state="translated">Rückgabe außerhalb einer Station nicht möglich. Entfernung zur nächsten Station {0} beträgt {1} m.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorReturnBikeTitle" translate="yes" xml:space="preserve"> <trans-unit id="ErrorReturnBikeTitle" translate="yes" xml:space="preserve">
<source>Error returning bike!</source> <source>Error at ending rental!</source>
<target state="translated">Fehler bei Radrückgabe!</target> <target state="translated">Fehler beim Beenden der Miete!</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorReturnBikeLockClosedNoGPSMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorReturnBikeLockClosedNoGPSMessage" translate="yes" xml:space="preserve">
<source>Returning bike at an unknown location is not possible. <source>End rental at an unknown location is not possible.
Bike can be returned if Rental can be ended if
- location information is available when closing lock - location information is available when closing lock
- bike is in reach and location information is available when pressing button "Return bike"</source> - bike is in reach and location information is available when pressing button "End rental"</source>
<target state="translated">Fahrradrückgabe an unbekanntem Standort nicht möglich. <target state="translated">Beenden der Miete an unbekanntem Standort nicht möglich.
Eine Radrückgabe ist möglich, wenn Ein Mietende ist möglich, wenn
- beim Schliessen des Schlosses Standortinformation verfügbar ist - beim Schließen des Schlosses Standortinformation verfügbar ist
- beim Drücken von "Rad zurückgeben" das Rad in Reichweite ist und Standortinformation verfügbar ist.</target> - beim Drücken von "Miete beenden" das Rad in Reichweite ist und Standortinformation verfügbar ist</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorReturnBikeLockOpenNoGPSMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorReturnBikeLockOpenNoGPSMessage" translate="yes" xml:space="preserve">
<source>Returning bike at an unknown location is not possible. <source>End rental at an unknown location is not possible.
Bike can only be returned if bike is in reach and location information is available.</source> Rental can only be ended if bike is in reach and location information is available.</source>
<target state="translated">Fahrradrückgabe an unbekanntem Standort nicht möglich. <target state="translated">Beenden der Miete an unbekanntem Standort nicht möglich.
Eine Radrückgabe ist nur möglich, wenn das Rad in Reichweite ist und Standortinformation verfügbar ist.</target> Mietende ist nur möglich, wenn das Rad in Reichweite ist und Standortinformation verfügbar ist.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorSupportmailCreateAttachment" translate="yes" xml:space="preserve"> <trans-unit id="ErrorSupportmailCreateAttachment" translate="yes" xml:space="preserve">
<source>Attachment could not be created.</source> <source>Attachment could not be created.</source>
<target state="translated">Mailanhang konnte nich erzeugt werden.</target> <target state="translated">Anhang konnte nich erzeugt werden.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorSupportmailMailingFailed" translate="yes" xml:space="preserve"> <trans-unit id="ErrorSupportmailMailingFailed" translate="yes" xml:space="preserve">
<source>Opening mail app failed.</source> <source>Opening mail app failed. Make sure you have a mail app installed on your mobile device!</source>
<target state="translated">Mailapp konnte nicht geöffnet werden.</target> <target state="translated">Mailapp konnte nicht geöffnet werden. Stellen Sie sicher, dass auf Ihrem mobilen Gerät eine Mailapp installiert und eingerichtet ist!</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorSupportmailPhoningFailed" translate="yes" xml:space="preserve"> <trans-unit id="ErrorSupportmailPhoningFailed" translate="yes" xml:space="preserve">
<source>Opening phone app failed.</source> <source>Opening phone app failed. Make sure you have a phone app installed on your mobile device!</source>
<target state="translated">Telefonapp konnte nicht geöffnet werden.</target> <target state="translated">Telefonapp konnte nicht geöffnet werden. Stellen Sie sicher, dass auf Ihrem mobilen Gerät eine Telefonapp installiert ist!</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageAnswerOk" translate="yes" xml:space="preserve"> <trans-unit id="MessageAnswerOk" translate="yes" xml:space="preserve">
<source>OK</source> <source>OK</source>
@ -203,8 +205,8 @@ Eine Radrückgabe ist nur möglich, wenn das Rad in Reichweite ist und Standorti
<target state="translated">Fragen? Hinweise?</target> <target state="translated">Fragen? Hinweise?</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageRateMail" translate="yes" xml:space="preserve"> <trans-unit id="MessageRateMail" translate="yes" xml:space="preserve">
<source>Are you enjoying the {0}-App?</source> <source>Are you enjoying the {0}-app?</source>
<target state="translated">Gefällt die {0}-App?</target> <target state="translated">Gefällt Ihnen die {0}-App?</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageWaring" translate="yes" xml:space="preserve"> <trans-unit id="MessageWaring" translate="yes" xml:space="preserve">
<source>Warning</source> <source>Warning</source>
@ -221,10 +223,10 @@ Eine Radrückgabe ist nur möglich, wenn das Rad in Reichweite ist und Standorti
<trans-unit id="QuestionSupportmailAttachment" translate="yes" xml:space="preserve"> <trans-unit id="QuestionSupportmailAttachment" translate="yes" xml:space="preserve">
<source>I hereby consent to the transmission of my log file. <source>I hereby consent to the transmission of my log file.
The log file contains your app usage data as well as system information. The data will only be used for diagnostic purposes or to improve the app.</source> The log file contains your app usage data as well as system information. The data will only be used for diagnostic purposes or to improve the app and then deleted.</source>
<target state="translated">Hiermit stimme ich der Übermittlung meiner Protokolldatei zu. <target state="translated">Hiermit stimme ich der Übermittlung meiner Protokolldatei zu.
Die Protokolldatei enthält Ihre App-Nutzungsdaten sowie Systeminformationen. Die Daten werden ausschließlich für Diagnosezwecke bzw. Verbesserung der App verwendet.</target> Die Protokolldatei enthält Ihre App-Nutzungsdaten sowie Systeminformationen. Die Daten werden ausschließlich für Diagnosezwecke bzw. Verbesserung der App verwendet und werden anschließend gelöscht.</target>
</trans-unit> </trans-unit>
<trans-unit id="QuestionTitle" translate="yes" xml:space="preserve"> <trans-unit id="QuestionTitle" translate="yes" xml:space="preserve">
<source>Question</source> <source>Question</source>
@ -232,9 +234,9 @@ Die Protokolldatei enthält Ihre App-Nutzungsdaten sowie Systeminformationen. Di
</trans-unit> </trans-unit>
<trans-unit id="MessageMapPageErrorAuthcookieUndefined" translate="yes" xml:space="preserve"> <trans-unit id="MessageMapPageErrorAuthcookieUndefined" translate="yes" xml:space="preserve">
<source>Session has expired. <source>Session has expired.
Please login to app once again.</source> Please log in again.</source>
<target state="translated">Sitzung ist abgelaufen. <target state="translated">Sitzung ist abgelaufen.
Bitte erneut in App anmelden.</target> Bitte melden Sie sich erneut an.</target>
</trans-unit> </trans-unit>
<trans-unit id="StatusTextReservationExpiredCodeMaxReservationTime" translate="yes" xml:space="preserve"> <trans-unit id="StatusTextReservationExpiredCodeMaxReservationTime" translate="yes" xml:space="preserve">
<source>Code {0}, max. reservation time of {1} min. expired.</source> <source>Code {0}, max. reservation time of {1} min. expired.</source>
@ -273,7 +275,7 @@ Bitte erneut in App anmelden.</target>
</trans-unit> </trans-unit>
<trans-unit id="StatusTextAvailable" translate="yes" xml:space="preserve"> <trans-unit id="StatusTextAvailable" translate="yes" xml:space="preserve">
<source>Available.</source> <source>Available.</source>
<target state="translated">Frei.</target> <target state="translated">Verfügbar.</target>
</trans-unit> </trans-unit>
<trans-unit id="StatusTextBookedCodeLocationSince" translate="yes" xml:space="preserve"> <trans-unit id="StatusTextBookedCodeLocationSince" translate="yes" xml:space="preserve">
<source>Code {0}, location {1}, rented since {2}.</source> <source>Code {0}, location {1}, rented since {2}.</source>
@ -304,8 +306,9 @@ Bitte erneut in App anmelden.</target>
<target state="translated">Passwort vergessen</target> <target state="translated">Passwort vergessen</target>
</trans-unit> </trans-unit>
<trans-unit id="ActionLoginRegister" translate="yes" xml:space="preserve"> <trans-unit id="ActionLoginRegister" translate="yes" xml:space="preserve">
<source>Register</source> <source>Register for free</source>
<target state="translated">Registrieren</target> <target state="needs-review-translation">Kostenlos registrieren</target>
<note from="MultilingualUpdate" annotates="source" priority="2">Please verify the translations accuracy as the source string was updated after it was translated.</note>
</trans-unit> </trans-unit>
<trans-unit id="MarkingLoginEmailAddressLabel" translate="yes" xml:space="preserve"> <trans-unit id="MarkingLoginEmailAddressLabel" translate="yes" xml:space="preserve">
<source>E-mail</source> <source>E-mail</source>
@ -316,8 +319,8 @@ Bitte erneut in App anmelden.</target>
<target state="translated">E-Mail</target> <target state="translated">E-Mail</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingLoginPasswordLabel" translate="yes" xml:space="preserve"> <trans-unit id="MarkingLoginPasswordLabel" translate="yes" xml:space="preserve">
<source>At least 8 characters</source> <source>At least eight characters</source>
<target state="translated">Mindestens 8 Zeichen</target> <target state="translated">Mindestens acht Zeichen</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingLoginPasswordPlaceholder" translate="yes" xml:space="preserve"> <trans-unit id="MarkingLoginPasswordPlaceholder" translate="yes" xml:space="preserve">
<source>Password</source> <source>Password</source>
@ -354,11 +357,11 @@ Bitte erneut in App anmelden.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageLoginRecoverPassword" translate="yes" xml:space="preserve"> <trans-unit id="MessageLoginRecoverPassword" translate="yes" xml:space="preserve">
<source>Please connect to Internet to recover the password.</source> <source>Please connect to Internet to recover the password.</source>
<target state="translated">Bitte mit dem Internet verbinden zum Wiederherstellen des Passworts.</target> <target state="translated">Zur Wiederherstellung des Passworts bitte mit dem Internet verbinden.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageLoginRegisterNoNet" translate="yes" xml:space="preserve"> <trans-unit id="MessageLoginRegisterNoNet" translate="yes" xml:space="preserve">
<source>Please connect to Internet to register.</source> <source>Please connect to Internet to register.</source>
<target state="translated">Bitte mit dem Internet verbinden zum Registrieren.</target> <target state="translated">Zur Registrierung bitte mit dem Internet verbinden.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageTitleHint" translate="yes" xml:space="preserve"> <trans-unit id="MessageTitleHint" translate="yes" xml:space="preserve">
<source>Hint</source> <source>Hint</source>
@ -366,7 +369,7 @@ Bitte erneut in App anmelden.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorOpenLockStillClosedMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorOpenLockStillClosedMessage" translate="yes" xml:space="preserve">
<source>After try to open lock state closed is reported.</source> <source>After try to open lock state closed is reported.</source>
<target state="translated">Nach Versuch Schloss zu öffnen wird Status geschlossen zurückgemeldet.</target> <target state="translated">Nach Versuch das Schloss zu öffnen, wird Status "geschlossen" zurückgemeldet.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorOpenLockOutOfReachMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorOpenLockOutOfReachMessage" translate="yes" xml:space="preserve">
<source>Lock cannot be opened until bike is near.</source> <source>Lock cannot be opened until bike is near.</source>
@ -374,13 +377,13 @@ Bitte erneut in App anmelden.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorCloseLockOutOfReachMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorCloseLockOutOfReachMessage" translate="yes" xml:space="preserve">
<source>Lock cannot be closed until bike is near.</source> <source>Lock cannot be closed until bike is near.</source>
<target state="translated">Schloss kann erst geschlossen werden, wenn das Rad in der Nähe ist. </target> <target state="translated">Schloss kann erst geschlossen werden, wenn Rad in der Nähe ist. </target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorCloseLockOutOfReachStateReservedMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorCloseLockOutOfReachStateReservedMessage" translate="yes" xml:space="preserve">
<source>Lock cannot be closed until bike is near. <source>Lock cannot be closed until bike is near.
Please try again to close bike or report bike to support!</source> Please try again to close bike or report bike to operator!</source>
<target state="translated">Schloss kann erst geschlossen werden, wenn das Rad in der Nähe ist. <target state="translated">Schloss kann erst geschlossen werden, wenn Rad in der Nähe ist.
Bitte Schließen nochmals versuchen oder Rad dem Support melden!</target> Bitte Schließen nochmals versuchen oder Rad dem Betreiber melden!</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorCloseLockTitle" translate="yes" xml:space="preserve"> <trans-unit id="ErrorCloseLockTitle" translate="yes" xml:space="preserve">
<source>Lock can not be closed!</source> <source>Lock can not be closed!</source>
@ -388,26 +391,26 @@ Bitte Schließen nochmals versuchen oder Rad dem Support melden!</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorCloseLockStillOpenMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorCloseLockStillOpenMessage" translate="yes" xml:space="preserve">
<source>After try to close lock state open is reported.</source> <source>After try to close lock state open is reported.</source>
<target state="translated">Nach Versuch Schloss zu schließen wird Status geöffnet zurückgemeldet.</target> <target state="translated">Nach Versuch Schloss zu schließen, wird Status "offen" zurückgemeldet.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorCloseLockUnexpectedStateMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorCloseLockUnexpectedStateMessage" translate="yes" xml:space="preserve">
<source>Lock reports state "{0}".</source> <source>Lock reports state "{0}".</source>
<target state="translated">Schloss meldet Status "{0}".</target> <target state="translated">Schloss meldet Status "{0}".</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorCloseLockUnkErrorMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorCloseLockUnkErrorMessage" translate="yes" xml:space="preserve">
<source>Please try to lock again or report bike to support! <source>Please try to lock again or report bike to operator!
{0}</source> {0}</source>
<target state="translated">Bitte schließen nochmals versuchen oder Rad dem Support melden! <target state="translated">Bitte Schließen nochmals versuchen oder Rad dem Betreiber melden!
{0}</target> {0}</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageBikesManagementLocationPermission" translate="yes" xml:space="preserve"> <trans-unit id="MessageBikesManagementLocationPermission" translate="yes" xml:space="preserve">
<source>Please allow location sharing so that bike lock/locks can be managed.</source> <source>Please allow location sharing so that bike lock/locks can be managed.</source>
<target state="translated">Bitte Standortfreigabe erlauben, damit Fahrradschloss/ Schlösser verwaltet werden können.</target> <target state="translated">Bitte Standortfreigabe erlauben, damit Schloss/-schlösser verwaltet werden können.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageBikesManagementLocationPermissionOpenDialog" translate="yes" xml:space="preserve"> <trans-unit id="MessageBikesManagementLocationPermissionOpenDialog" translate="yes" xml:space="preserve">
<source>Please allow location sharing so that bike lock/locks can be managed. <source>Please allow location sharing so that bike lock/locks can be managed.
Open sharing dialog?</source> Open sharing dialog?</source>
<target state="translated">Bitte Standortfreigabe erlauben, damit Fahrradschloss/ Schlösser verwaltet werden können. <target state="translated">Bitte Standortfreigabe erlauben, damit Radschloss/-schlösser verwaltet werden können.
Freigabedialog öffen?</target> Freigabedialog öffen?</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageCenterMapLocationPermissionOpenDialog" translate="yes" xml:space="preserve"> <trans-unit id="MessageCenterMapLocationPermissionOpenDialog" translate="yes" xml:space="preserve">
@ -418,7 +421,7 @@ Freigabedialog öffen?</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageBikesManagementLocationActivation" translate="yes" xml:space="preserve"> <trans-unit id="MessageBikesManagementLocationActivation" translate="yes" xml:space="preserve">
<source>Please activate location so that bike lock can be found!</source> <source>Please activate location so that bike lock can be found!</source>
<target state="translated">Bitte Standort aktivieren, damit Fahrradschloss gefunden werden kann!</target> <target state="translated">Bitte Standort aktivieren, damit Schloss gefunden werden kann!</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageAnswerNo" translate="yes" xml:space="preserve"> <trans-unit id="MessageAnswerNo" translate="yes" xml:space="preserve">
<source>No</source> <source>No</source>
@ -430,7 +433,7 @@ Freigabedialog öffen?</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageBikesManagementBluetoothActivation" translate="yes" xml:space="preserve"> <trans-unit id="MessageBikesManagementBluetoothActivation" translate="yes" xml:space="preserve">
<source>Please enable Bluetooth to manage bike lock/locks.</source> <source>Please enable Bluetooth to manage bike lock/locks.</source>
<target state="translated">Bitte Bluetooth aktivieren, damit Fahrradschloss/ Schlösser verwaltet werden können.</target> <target state="translated">Bitte Bluetooth aktivieren, damit Schloss/-schlösser verwaltet werden können.</target>
</trans-unit> </trans-unit>
<trans-unit id="ActionSearchLock" translate="yes" xml:space="preserve"> <trans-unit id="ActionSearchLock" translate="yes" xml:space="preserve">
<source>Search lock</source> <source>Search lock</source>
@ -442,11 +445,11 @@ Freigabedialog öffen?</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextOpeningLock" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextOpeningLock" translate="yes" xml:space="preserve">
<source><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Lock is opening.&lt;br/&gt;Please wait until it is completely open.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></source> <source><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Lock is opening.&lt;br/&gt;Please wait until it is completely open.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></source>
<target state="translated"><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Schloss öffnet.&lt;br/&gt;Bitte warten Sie bis es komplett geöffnet ist.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></target> <target state="translated"><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Schloss öffnet.&lt;br/&gt;Bitte warten Sie, bis es komplett geöffnet ist.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextStartingUpdater" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextStartingUpdater" translate="yes" xml:space="preserve">
<source>Updating...</source> <source>Updating...</source>
<target state="translated">Starte Aktualisierung...</target> <target state="translated">Aktualisiere...</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextStartingUpdatingLockingState" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextStartingUpdatingLockingState" translate="yes" xml:space="preserve">
<source>Updating lock state...</source> <source>Updating lock state...</source>
@ -454,23 +457,23 @@ Freigabedialog öffen?</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextReadingChargingLevel" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextReadingChargingLevel" translate="yes" xml:space="preserve">
<source>Reading charging level...</source> <source>Reading charging level...</source>
<target state="translated">Lese Akkustatus...</target> <target state="translated">Lese Akkustand...</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextErrorStatusUpdateingLockstate" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextErrorStatusUpdateingLockstate" translate="yes" xml:space="preserve">
<source>Status error on updating lock state.</source> <source>Status error on updating lock state.</source>
<target state="translated">Statusfehler beim Aktualisieren des Schlossstatusses.</target> <target state="translated">Statusfehler beim Aktualisieren des Schlossstatus.</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextErrorConnectionUpdateingLockstate" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextErrorConnectionUpdateingLockstate" translate="yes" xml:space="preserve">
<source>Connection error on updating locking status.</source> <source>Connection error on updating locking status.</source>
<target state="translated">Verbingungsfehler beim Aktualisieren des Schlossstatusses.</target> <target state="translated">Verbingungsfehler beim Aktualisieren des Schlossstatus.</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextErrorNoWebUpdateingLockstate" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextErrorNoWebUpdateingLockstate" translate="yes" xml:space="preserve">
<source>No web error on updating locking status.</source> <source>Internet must be available for updating lock status. Please establish an Internet connection!</source>
<target state="translated">Kein Netz beim Aktualisieren des Schlossstatusses.</target> <target state="translated">Um den Schlossstatus zu aktualisieren, wird Internet benötigt. Bitte stellen Sie eine Internetverbindung her!</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextClosingLock" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextClosingLock" translate="yes" xml:space="preserve">
<source><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Lock is closing.&lt;br/&gt;Please wait until it is completely closed.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></source> <source><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Lock is closing.&lt;br/&gt;Please wait until it is completely closed.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></source>
<target state="translated"><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Schloss schließt.&lt;br/&gt;Bitte warten Sie bis es komplett geschlossen ist.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></target> <target state="translated"><bpt id="1">&lt;h4&gt;</bpt><bpt id="2">&lt;b&gt;</bpt>Schloss schließt.&lt;br/&gt;Bitte warten Sie, bis es komplett geschlossen ist.<ept id="2">&lt;/b&gt;</ept><ept id="1">&lt;/h4&gt;</ept></target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_203" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_203" translate="yes" xml:space="preserve">
<source>Updated to latest lock firmware.</source> <source>Updated to latest lock firmware.</source>
@ -502,11 +505,11 @@ Zielplatform Android 11.</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextErrorReadingChargingLevelGeneral" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextErrorReadingChargingLevelGeneral" translate="yes" xml:space="preserve">
<source>Battery status cannot be read.</source> <source>Battery status cannot be read.</source>
<target state="translated">Akkustatus kann nicht gelesen werden.</target> <target state="translated">Akkustand kann nicht gelesen werden.</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextErrorReadingChargingLevelOutOfReach" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextErrorReadingChargingLevelOutOfReach" translate="yes" xml:space="preserve">
<source>Battery status can only be read when bike is nearby.</source> <source>Battery status can only be read when bike is nearby.</source>
<target state="translated">Akkustatus kann erst gelesen werden, wenn Rad in der Nähe ist.</target> <target state="translated">Akkuladestand kann erst gelesen werden, wenn Rad in der Nähe ist.</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextRentingBike" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextRentingBike" translate="yes" xml:space="preserve">
<source>Renting bike...</source> <source>Renting bike...</source>
@ -521,12 +524,12 @@ Zielplatform Android 11.</target>
<target state="translated">Fehler beim Mieten des Rads!</target> <target state="translated">Fehler beim Mieten des Rads!</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageRentingBikeErrorTooManyReservationsRentals" translate="yes" xml:space="preserve"> <trans-unit id="MessageRentingBikeErrorTooManyReservationsRentals" translate="yes" xml:space="preserve">
<source>A rental of bike {0} was rejected because the maximum allowed number of {1} reservations/ rentals had already been made.</source> <source>A rental of bike {0} was rejected because the maximum allowed number of {1} reservations/rentals had already been made.</source>
<target state="translated">Eine Miete des Rads {0} wurde abgelehnt, weil die maximal erlaubte Anzahl von {1} Reservierungen/ Buchungen bereits getätigt wurden.</target> <target state="translated">Eine Miete des Rads {0} wurde abgelehnt, weil die maximal erlaubte Anzahl von {1} Reservierungen/Mieten bereits getätigt wurden.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageReservationBikeErrorTooManyReservationsRentals" translate="yes" xml:space="preserve"> <trans-unit id="MessageReservationBikeErrorTooManyReservationsRentals" translate="yes" xml:space="preserve">
<source>A reservation of bike {0} was rejected because the maximum allowed number of {1} reservations/ rentals had already been made.</source> <source>A reservation of bike {0} was rejected because the maximum allowed number of {1} reservations/rentals had already been made.</source>
<target state="translated">Eine Reservierung des Rads {0} wurde abgelehnt, weil die maximal erlaubte Anzahl von {1} Reservierungen/ Buchungen bereits getätigt wurden.</target> <target state="translated">Eine Reservierung des Rads {0} wurde abgelehnt, weil die maximal erlaubte Anzahl von {1} Reservierungen/Mieten bereits getätigt wurden.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageErrorLockIsClosedThreeLines" translate="yes" xml:space="preserve"> <trans-unit id="MessageErrorLockIsClosedThreeLines" translate="yes" xml:space="preserve">
<source>Attention: Lock is closed! <source>Attention: Lock is closed!
@ -543,20 +546,20 @@ Zielplatform Android 11.</target>
{0}</target> {0}</target>
</trans-unit> </trans-unit>
<trans-unit id="ExceptionTextRentingBikeFailedGeneral" translate="yes" xml:space="preserve"> <trans-unit id="ExceptionTextRentingBikeFailedGeneral" translate="yes" xml:space="preserve">
<source>The rental of bike No. {0} has failed.</source> <source>The rental of bike {0} has failed.</source>
<target state="translated">Die Miete des Fahrads Nr. {0} ist fehlgeschlagen.</target> <target state="translated">Die Miete des Rads {0} ist fehlgeschlagen.</target>
</trans-unit> </trans-unit>
<trans-unit id="ExceptionTextRentingBikeFailedUnavailalbe" translate="yes" xml:space="preserve"> <trans-unit id="ExceptionTextRentingBikeFailedUnavailalbe" translate="yes" xml:space="preserve">
<source>The rental of bike No. {0} has failed, the bike is currently unavailable.{1}</source> <source>The rental of bike {0} has failed, the bike is currently unavailable. {1}</source>
<target state="translated">Die Miete des Rads Nr. {0} ist fehlgeschlagen, das Rad ist momentan nicht erreichbar.{1}</target> <target state="translated">Die Miete des Rads {0} ist fehlgeschlagen, das Rad ist momentan nicht erreichbar.{1}</target>
</trans-unit> </trans-unit>
<trans-unit id="ExceptionTextReservationBikeFailedGeneral" translate="yes" xml:space="preserve"> <trans-unit id="ExceptionTextReservationBikeFailedGeneral" translate="yes" xml:space="preserve">
<source>The reservation of bike no. {0} has failed.</source> <source>The reservation of bike {0} has failed.</source>
<target state="translated">Die Reservierung des Fahrads Nr. {0} ist fehlgeschlagen.</target> <target state="translated">Die Reservierung des Rads {0} ist fehlgeschlagen.</target>
</trans-unit> </trans-unit>
<trans-unit id="ExceptionTextReservationBikeFailedUnavailalbe" translate="yes" xml:space="preserve"> <trans-unit id="ExceptionTextReservationBikeFailedUnavailalbe" translate="yes" xml:space="preserve">
<source>The reservation of bike No. {0} has failed, the bike is currently unavailable.{1}</source> <source>The reservation of bike {0} has failed, the bike is currently unavailable. {1}</source>
<target state="translated">Die Reservierung des Rads Nr. {0} ist fehlgeschlagen, das Rad ist momentan nicht erreichbar.{1}</target> <target state="translated">Die Reservierung des Rads {0} ist fehlgeschlagen, das Rad ist momentan nicht erreichbar.{1}</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_208" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_208" translate="yes" xml:space="preserve">
<source>Minor fixes.</source> <source>Minor fixes.</source>
@ -575,8 +578,8 @@ Zielplatform Android 11.</target>
Bike should always be disconnected when not reserved or rented. Bike should always be disconnected when not reserved or rented.
Please restart app in order to get bike info.</source> Please restart app in order to get bike info.</source>
<target state="translated">Ungülitiger Status von Rad {0} erkannt. <target state="translated">Ungülitiger Status von Rad {0} erkannt.
Ein nicht reserviertes oder gemietetes Rad sollte immer getrennt sein . Ein nicht reserviertes oder gemietetes Rad sollte immer getrennt sein.
Bitte App neu starten um Rad Infos zu bekommen.</target> Bitte App neu starten, um Radinfos zu bekommen.</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingBikeInfoErrorStateUnknownDetected" translate="yes" xml:space="preserve"> <trans-unit id="MarkingBikeInfoErrorStateUnknownDetected" translate="yes" xml:space="preserve">
<source>Unknown status for bike {0} detected.</source> <source>Unknown status for bike {0} detected.</source>
@ -590,7 +593,7 @@ Bitte App neu starten um Rad Infos zu bekommen.</target>
</trans-unit> </trans-unit>
<trans-unit id="QuestionCancelReservation" translate="yes" xml:space="preserve"> <trans-unit id="QuestionCancelReservation" translate="yes" xml:space="preserve">
<source>Cancel reservation for bike {0}?</source> <source>Cancel reservation for bike {0}?</source>
<target state="translated">Reservierung für Fahrrad {0} aufheben?</target> <target state="translated">Reservierung für Rad {0} aufheben?</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_209" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_209" translate="yes" xml:space="preserve">
<source>Minor fix: Bikes are disconnected as soon as becoming disposable.</source> <source>Minor fix: Bikes are disconnected as soon as becoming disposable.</source>
@ -598,7 +601,7 @@ Bitte App neu starten um Rad Infos zu bekommen.</target>
</trans-unit> </trans-unit>
<trans-unit id="QuestionReserveBike" translate="yes" xml:space="preserve"> <trans-unit id="QuestionReserveBike" translate="yes" xml:space="preserve">
<source>Reserve bike {0} free of charge for {1} min?</source> <source>Reserve bike {0} free of charge for {1} min?</source>
<target state="translated">Fahrrad {0} kostenlos für {1} Min. reservieren?</target> <target state="translated">Rad {0} kostenlos für {1} Min. reservieren?</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextErrorDeserializationException" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextErrorDeserializationException" translate="yes" xml:space="preserve">
<source>Connection error: Deserialization failed.</source> <source>Connection error: Deserialization failed.</source>
@ -625,16 +628,17 @@ Bitte App neu starten um Rad Infos zu bekommen.</target>
<target state="translated">Abo-Preis</target> <target state="translated">Abo-Preis</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageBikesManagementTariffDescriptionFeeEuroPerHour" translate="yes" xml:space="preserve"> <trans-unit id="MessageBikesManagementTariffDescriptionFeeEuroPerHour" translate="yes" xml:space="preserve">
<source>Rental fees</source> <source>Rental charges</source>
<target state="translated">Mietgebühren</target> <target state="translated">Mietkosten</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageBikesManagementTariffDescriptionFreeTimePerSession" translate="yes" xml:space="preserve"> <trans-unit id="MessageBikesManagementTariffDescriptionFreeTimePerSession" translate="yes" xml:space="preserve">
<source>Free use</source> <source>Free use</source>
<target state="translated">Gratis Nutzung</target> <target state="translated">Gratis Nutzung</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageBikesManagementTariffDescriptionMaxFeeEuroPerDay" translate="yes" xml:space="preserve"> <trans-unit id="MessageBikesManagementTariffDescriptionMaxFeeEuroPerDay" translate="yes" xml:space="preserve">
<source>Max. fee</source> <source>Max. charges</source>
<target state="translated">Max. Gebühr</target> <target state="needs-review-translation">Max. Gebühr</target>
<note from="MultilingualUpdate" annotates="source" priority="2">Please verify the translations accuracy as the source string was updated after it was translated.</note>
</trans-unit> </trans-unit>
<trans-unit id="MessageBikesManagementTariffDescriptionEuroPerHour" translate="yes" xml:space="preserve"> <trans-unit id="MessageBikesManagementTariffDescriptionEuroPerHour" translate="yes" xml:space="preserve">
<source>€/hour</source> <source>€/hour</source>
@ -698,9 +702,9 @@ Bitte App neu starten um Rad Infos zu bekommen.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageCopriVersionIsOutdated" translate="yes" xml:space="preserve"> <trans-unit id="MessageCopriVersionIsOutdated" translate="yes" xml:space="preserve">
<source>This version of the {0} App is not compatible with server detected. <source>This version of the {0} App is not compatible with server detected.
Please contact the support for help.</source> Please contact operator for help.</source>
<target state="translated">Diese Version der {0} App ist nicht kompatibel mit dem erkannten Server. <target state="translated">Diese Version der {0} App ist nicht kompatibel mit dem erkannten Server.
Bitte kontaktieren sie den Support!</target> Bitte kontaktieren sie den Betreiber!</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_224" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_224" translate="yes" xml:space="preserve">
<source>Updated for latest server version.</source> <source>Updated for latest server version.</source>
@ -721,11 +725,12 @@ Bitte kontaktieren sie den Support!</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextErrorWebExceptionGeneralError" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextErrorWebExceptionGeneralError" translate="yes" xml:space="preserve">
<source>Connection error. Status code: {0}.</source> <source>Connection error. Status code: {0}.</source>
<target state="translated">Verbindungsfehler. Status statucode: {0}.</target> <target state="translated">Verbindungsfehler. Statuscode: {0}.</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_227" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_227" translate="yes" xml:space="preserve">
<source>Feedback dialog added which is shown after returning bike.</source> <source>Feedback dialog added which is shown after ending rental.</source>
<target state="translated">Seite zur Eingabe von Rückmeldungen hinzugefügt, der nach Rückgabe eines Rads angezeigt wird.</target> <target state="needs-review-translation">Seite zur Eingabe von Rückmeldungen hinzugefügt, der nach Rückgabe eines Rads angezeigt wird.</target>
<note from="MultilingualUpdate" annotates="source" priority="2">Please verify the translations accuracy as the source string was updated after it was translated.</note>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextConnectionStateOffline" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextConnectionStateOffline" translate="yes" xml:space="preserve">
<source>Offline.</source> <source>Offline.</source>
@ -733,7 +738,7 @@ Bitte kontaktieren sie den Support!</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextException" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextException" translate="yes" xml:space="preserve">
<source>Cache used.</source> <source>Cache used.</source>
<target state="translated">Cache Daten.</target> <target state="translated">Cache genutzt.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorReturnSubmitFeedbackMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorReturnSubmitFeedbackMessage" translate="yes" xml:space="preserve">
<source>Your feedback could not be send to server successfully.</source> <source>Your feedback could not be send to server successfully.</source>
@ -767,7 +772,7 @@ Fehlerhandling verbessert.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorOpenLockTitle" translate="yes" xml:space="preserve"> <trans-unit id="ErrorOpenLockTitle" translate="yes" xml:space="preserve">
<source>Error while opening lock!</source> <source>Error while opening lock!</source>
<target state="translated">Fehler beim Schloss Öffnen!</target> <target state="translated">Fehler beim Öffnen des Schlosses!</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_236" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_236" translate="yes" xml:space="preserve">
<source>Stations names instead descriptions shown on page title. <source>Stations names instead descriptions shown on page title.
@ -778,8 +783,9 @@ Fehlermeldung beim Öffnen von Schloss verbessert.
Layout Anzeige Radnamen und nummern verbessert.</target> Layout Anzeige Radnamen und nummern verbessert.</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_237" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_237" translate="yes" xml:space="preserve">
<source>Hard- and software information send to backend when returning bike.</source> <source>Hard- and software information send to backend when ending rental.</source>
<target state="translated">Hard- und software information werden an Backend übermittelt bei Radrückgabe.</target> <target state="needs-review-translation">Hard- und software information werden an Backend übermittelt bei Radrückgabe.</target>
<note from="MultilingualUpdate" annotates="source" priority="2">Please verify the translations accuracy as the source string was updated after it was translated.</note>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_239" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_239" translate="yes" xml:space="preserve">
<source>Bugfix: Bike description is displayed correctly again.</source> <source>Bugfix: Bike description is displayed correctly again.</source>
@ -807,7 +813,7 @@ Layout Anzeige Radnamen und nummern verbessert.</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>
<target state="translated">Bitte Anmelden um Fahrräder zu reservieren! <bpt id="1">&lt;font color="blue"&gt;</bpt><bpt id="2">&lt;u&gt;</bpt>Hier<ept id="2">&lt;/u&gt;</ept><ept id="1">&lt;/font&gt;</ept> tippen, um auf Anmeldeseite zu wechseln.</target> <target state="translated">Bitte Anmelden, um Räder zu reservieren! <bpt id="1">&lt;font color="blue"&gt;</bpt><bpt id="2">&lt;u&gt;</bpt>Hier<ept id="2">&lt;/u&gt;</ept><ept id="1">&lt;/font&gt;</ept> tippen, um auf Anmeldeseite zu wechseln.</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingContactNoStationInfoAvailableNoButton" translate="yes" xml:space="preserve"> <trans-unit id="MarkingContactNoStationInfoAvailableNoButton" translate="yes" xml:space="preserve">
<source>Contact operator?</source> <source>Contact operator?</source>
@ -819,7 +825,7 @@ Layout Anzeige Radnamen und nummern verbessert.</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingSelectStationPage" translate="yes" xml:space="preserve"> <trans-unit id="MarkingSelectStationPage" translate="yes" xml:space="preserve">
<source>Select Station</source> <source>Select Station</source>
<target state="translated">Station Auswählen</target> <target state="translated">Station auswählen</target>
</trans-unit> </trans-unit>
<trans-unit id="ActionSelectStation" translate="yes" xml:space="preserve"> <trans-unit id="ActionSelectStation" translate="yes" xml:space="preserve">
<source>Select station</source> <source>Select station</source>
@ -842,8 +848,8 @@ Layout Anzeige Radnamen und nummern verbessert.</target>
<target state="translated">Betreiber: {0}.</target> <target state="translated">Betreiber: {0}.</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingBikeSharingOperatorNoOperatorInfoAvailable" translate="yes" xml:space="preserve"> <trans-unit id="MarkingBikeSharingOperatorNoOperatorInfoAvailable" translate="yes" xml:space="preserve">
<source>Contact Operator.</source> <source>Contact operator.</source>
<target state="translated">Betreiber Kontaktieren.</target> <target state="translated">Betreiber kontaktieren.</target>
</trans-unit> </trans-unit>
<trans-unit id="MiniSurveyAskForAnswer" translate="yes" xml:space="preserve"> <trans-unit id="MiniSurveyAskForAnswer" translate="yes" xml:space="preserve">
<source>Select an answer please.</source> <source>Select an answer please.</source>
@ -868,16 +874,18 @@ Kleinere Verbesserungen.</target>
<target state="translated">Abfrage Standort...</target> <target state="translated">Abfrage Standort...</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageErrorQueryLocationTitle" translate="yes" xml:space="preserve"> <trans-unit id="MessageErrorQueryLocationTitle" translate="yes" xml:space="preserve">
<source>Error Query Location!</source> <source>Error query location!</source>
<target state="translated">Fehler bei Standortabfrage!</target> <target state="needs-review-translation">Fehler bei Standortabfrage!</target>
<note from="MultilingualUpdate" annotates="source" priority="2">Please verify the translations accuracy as the source string was updated after it was translated.</note>
</trans-unit> </trans-unit>
<trans-unit id="MessageErrorQueryLocationMessage" translate="yes" xml:space="preserve"> <trans-unit id="MessageErrorQueryLocationMessage" translate="yes" xml:space="preserve">
<source>Closing the lock and ending the rental is not possible.</source> <source>Closing the lock and ending the rental is not possible.</source>
<target state="translated">Schloss schließen und Miete beenden ist nicht möglich.</target> <target state="translated">Schloss schließen und Miete beenden ist nicht möglich.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageErrorQueryLocationStartTitle" translate="yes" xml:space="preserve"> <trans-unit id="MessageErrorQueryLocationStartTitle" translate="yes" xml:space="preserve">
<source>Error Start Query Location!</source> <source>Error start query location!</source>
<target state="translated">Fehler beim Start der Standortabfrage!</target> <target state="needs-review-translation">Fehler beim Start der Standortabfrage!</target>
<note from="MultilingualUpdate" annotates="source" priority="2">Please verify the translations accuracy as the source string was updated after it was translated.</note>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextErrorQueryLocationWhenAny" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextErrorQueryLocationWhenAny" translate="yes" xml:space="preserve">
<source>No location info available. Activate your device's location services.</source> <source>No location info available. Activate your device's location services.</source>
@ -896,29 +904,29 @@ Kleinere Verbesserungen.</target>
<target state="translated">Start Standortabfrage...</target> <target state="translated">Start Standortabfrage...</target>
</trans-unit> </trans-unit>
<trans-unit id="QuestionCloseLockAndReturnBike" translate="yes" xml:space="preserve"> <trans-unit id="QuestionCloseLockAndReturnBike" translate="yes" xml:space="preserve">
<source>Close lock and return bike {0}?</source> <source>Close lock and end rental of bike {0}?</source>
<target state="translated">Fahrrad {0} abschließen und zurückgeben?</target> <target state="translated">Rad {0} abschließen und Miete beenden?</target>
</trans-unit> </trans-unit>
<trans-unit id="QuestionReturnBike" translate="yes" xml:space="preserve"> <trans-unit id="QuestionReturnBike" translate="yes" xml:space="preserve">
<source>Return bike {0}?</source> <source>End rental of bike {0}?</source>
<target state="translated">Fahrrad {0} zurückgeben? <target state="translated">Miete von Rad {0} beenden?
</target> </target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextReturningBike" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextReturningBike" translate="yes" xml:space="preserve">
<source>Returning bike...</source> <source>Ending rental...</source>
<target state="translated">Gebe Rad zurück...</target> <target state="translated">Beende Miete...</target>
</trans-unit> </trans-unit>
<trans-unit id="QuestionOpenLockAndBookBike" translate="yes" xml:space="preserve"> <trans-unit id="QuestionOpenLockAndBookBike" translate="yes" xml:space="preserve">
<source>Rent bike {0} and open lock?</source> <source>Rent bike {0} and open lock?</source>
<target state="translated">Fahrrad {0} mieten und Schloss öffnen?</target> <target state="translated">Rad {0} mieten und Schloss öffnen?</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorReturnBikeNoWebMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorReturnBikeNoWebMessage" translate="yes" xml:space="preserve">
<source>Internet must be available when returning the bike.</source> <source>Internet must be available when ending rental. Please establish an Internet connection!</source>
<target state="translated">Internet muss erreichbar sein beim Zurückgeben des Rads.</target> <target state="translated">Um die Miete zu beenden, wird Internet benötigt. Bitte stellen Sie eine Internetverbindung her!</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorReturnBikeNoWebTitle" translate="yes" xml:space="preserve"> <trans-unit id="ErrorReturnBikeNoWebTitle" translate="yes" xml:space="preserve">
<source>Connection error when returning the bike!</source> <source>Connection error when ending rental.</source>
<target state="translated">Verbingungsfehler beim Zurückgeben des Rads!</target> <target state="translated">Verbingungsfehler beim Beenden der Miete!</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_244" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_244" translate="yes" xml:space="preserve">
<source>Closing lock and returning bike speeded up.</source> <source>Closing lock and returning bike speeded up.</source>
@ -981,18 +989,18 @@ Anzeige von Statusinformationen erweitert.
Fehlerbehebung: Supportmails können wieder verschickt werden.</target> Fehlerbehebung: Supportmails können wieder verschickt werden.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageMapPageErrorSwitch" translate="yes" xml:space="preserve"> <trans-unit id="MessageMapPageErrorSwitch" translate="yes" xml:space="preserve">
<source>An error occurred switching from cargo bikes/ city bikes. <source>An error occurred switching between cargo and city bikes.
{0}</source> {0}</source>
<target state="translated">Beim Umschalten zwischen Lasten-/ Stadträdern ist ein Fehler aufgetreten. <target state="translated">Beim Umschalten zwischen Lasten- und Stadträdern ist ein Fehler aufgetreten.
{0}</target> {0}</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageErrorSelectBikeNoBikeFound" translate="yes" xml:space="preserve"> <trans-unit id="MessageErrorSelectBikeNoBikeFound" translate="yes" xml:space="preserve">
<source>No bike with id {0} found.</source> <source>No bike with id {0} found.</source>
<target state="translated">Kein Fahrrad mit Id {0} gefunden.</target> <target state="translated">Kein Rad mit ID {0} gefunden.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageErrorSelectBikeTitle" translate="yes" xml:space="preserve"> <trans-unit id="MessageErrorSelectBikeTitle" translate="yes" xml:space="preserve">
<source>Error Selecting Bike!</source> <source>Error Selecting Bike!</source>
<target state="translated">Fehler beim Rad Wählen!</target> <target state="translated">Fehler beim Auswählen des Rads!</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_277" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_277" translate="yes" xml:space="preserve">
<source>Bugfix: No more closing of app on Select Bike page.</source> <source>Bugfix: No more closing of app on Select Bike page.</source>
@ -1000,7 +1008,7 @@ Fehlerbehebung: Supportmails können wieder verschickt werden.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorBookedSearchMessageEscalationLevel1" translate="yes" xml:space="preserve"> <trans-unit id="ErrorBookedSearchMessageEscalationLevel1" translate="yes" xml:space="preserve">
<source>Your mobile device still does not connect to the bike lock. Please restart the app or even your mobile device and repeat the process.</source> <source>Your mobile device still does not connect to the bike lock. Please restart the app or even your mobile device and repeat the process.</source>
<target state="translated">Ihr mobiles Gerät verbindet sich immer noch nicht mit dem Fahrradschloss. Bitte starten Sie die App oder sogar Ihr mobiles Gerät neu und wiederholen Sie den Vorgang.</target> <target state="translated">Ihr mobiles Gerät verbindet sich immer noch nicht mit dem Schloss. Bitte starten Sie die App oder sogar Ihr mobiles Gerät neu und wiederholen Sie den Vorgang.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageAnswerCancel" translate="yes" xml:space="preserve"> <trans-unit id="MessageAnswerCancel" translate="yes" xml:space="preserve">
<source>Cancel</source> <source>Cancel</source>
@ -1015,18 +1023,20 @@ Fehlerbehebung: Supportmails können wieder verschickt werden.</target>
<target state="translated">Fehler beim Verbinden mit Schloss!</target> <target state="translated">Fehler beim Verbinden mit Schloss!</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorBookedSearchMessageEscalationLevel2" translate="yes" xml:space="preserve"> <trans-unit id="ErrorBookedSearchMessageEscalationLevel2" translate="yes" xml:space="preserve">
<source>Unfortunately, it is still not possible to establish a connection between your mobile device and the bike lock. Please contact customer support. <source>It is still not possible to establish a connection between your mobile device and the bike lock. Please contact operator!
As a last resort, please close the lock by hand AND contact customer support so that they can terminate your chargeable rental. To do this: Alternative:
1. close the app, 1. close app,
2. press the button at the top of the lock briefly and quickly release it as soon as it starts flashing, 2. press the button at the top of the lock briefly and release it as soon as it starts flashing,
3. wait until the lock is completely closed and remains closed.</source> 3. make sure that the lock is completely closed and remains closed.
<target state="translated">Es kann leider weiterhin keine Verbindung zwischen Ihrem mobilen Gerät und dem Fahrradschloss aufgebaut werden. Bitte kontaktieren Sie den Kundensupport. 4. send e-mail to operator (otherwise your chargeable rental will continue!): Problem description, Drop-off station.</source>
<target state="translated">Es kann weiterhin keine Verbindung zwischen Ihrem mobilen Gerät und dem Schloss aufgebaut werden. Rufen Sie den Betreiber an!
Als aller letzten Ausweg das Schloss bitte per Hand schließen UND den Kundensupport zu kontaktieren, damit dieser Ihre kostenpflichtige Miete beenden kann. Dazu: Alternativ:
1. App schließen, 1. App schließen,
2. auf den Knopf oben am Schloss kurz drücken und schnell loslassen sobald bis dieser zu blinken beginnt, 2. auf den Knopf oben am Schloss kurz drücken und sofort loslassen, sobald Knopf zu blinken beginnt,
3. warten, bis das Schloss vollständig geschlossen ist und geschlossen bleibt. </target> 3. sicherstellen, dass das Schloss vollständig geschlossen ist und geschlossen bleibt.
4. E-Mail an Betreiber schicken (ansonsten läuft Ihre kostenpflichtige Miete weiter!): Problembeschreibung, Rad-ID, Abgabestation.</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_278" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_278" translate="yes" xml:space="preserve">
<source>Hints added to ease closing of lock in case closing does not succeed on first try.</source> <source>Hints added to ease closing of lock in case closing does not succeed on first try.</source>
@ -1050,19 +1060,19 @@ Als aller letzten Ausweg das Schloss bitte per Hand schließen UND den Kundensup
</trans-unit> </trans-unit>
<trans-unit id="MessageErrorConnectTitle" translate="yes" xml:space="preserve"> <trans-unit id="MessageErrorConnectTitle" translate="yes" xml:space="preserve">
<source>Error when connecting to lock!</source> <source>Error when connecting to lock!</source>
<target state="translated">Fehler bei Verbinden mit Schloss!</target> <target state="translated">Fehler beim Verbinden mit Schloss!</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorConnectLockGeneralErrorMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorConnectLockGeneralErrorMessage" translate="yes" xml:space="preserve">
<source>Communication error during lock search.</source> <source>Communication error during lock search.</source>
<target state="translated">Kommunikationsfehler bei Schlosssuche.</target> <target state="translated">Kommunikationsfehler bei Schlosssuche.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorConnectLockRentedBikeNoWebMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorConnectLockRentedBikeNoWebMessage" translate="yes" xml:space="preserve">
<source>Internet must be reachable to connect to lock of rented bike.</source> <source>Internet must be reachable to connect to lock of rented bike. Please establish an Internet connection!</source>
<target state="translated">Internet muss erreichbar sein um Verbindung mit Schloss für gemietetes Rad herzustellen.</target> <target state="translated">Internet muss erreichbar sein, um Verbindung mit Schloss für gemietetes Rad herzustellen. Bitte stellen Sie eine Internetverbindung her!</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorConnectLockReservedBikeNoWebMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorConnectLockReservedBikeNoWebMessage" translate="yes" xml:space="preserve">
<source>Internet must be reachable to connect to lock of reserved bike.</source> <source>Internet must be reachable to connect to lock of reserved bike. Please establish an Internet connection!</source>
<target state="translated">Internet muss erreichbar sein um Verbindung mit Schloss für reserviertes Rad herzustellen.</target> <target state="translated">Internet muss erreichbar sein, um Verbindung mit Schloss für reserviertes Rad herzustellen. Bitte stellen Sie eine Internetverbindung her!</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorFindLockReservedBikeNoStausMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorFindLockReservedBikeNoStausMessage" translate="yes" xml:space="preserve">
<source>Lock status of the reserved bike could not be determined.</source> <source>Lock status of the reserved bike could not be determined.</source>
@ -1074,13 +1084,13 @@ Als aller letzten Ausweg das Schloss bitte per Hand schließen UND den Kundensup
</trans-unit> </trans-unit>
<trans-unit id="ErrorFindLockLocationPermissionMissing" translate="yes" xml:space="preserve"> <trans-unit id="ErrorFindLockLocationPermissionMissing" translate="yes" xml:space="preserve">
<source>Please grant location permissions, otherwise lock cannot be connected.</source> <source>Please grant location permissions, otherwise lock cannot be connected.</source>
<target state="translated">Bitte Standort-Zugriffsfreigabe erteilen, anderenfalls ist eine Verbindung mit dem Schloss nicht möglich. <target state="translated">Bitte Standortfreigabe erteilen, anderenfalls ist eine Verbindung mit dem Schloss nicht möglich.
</target> </target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorFindLockLocationOff" translate="yes" xml:space="preserve"> <trans-unit id="ErrorFindLockLocationOff" translate="yes" xml:space="preserve">
<source>Please turn Location on, otherwise lock cannot be connected.</source> <source>Please turn location services on, otherwise lock cannot be connected.</source>
<target state="translated">Bitte Standortbestimmung aktivieren, anderenfalls ist eine Verbindung mit dem Schloss nicht möglich.</target> <target state="translated">Bitte Standortdienste aktivieren, anderenfalls ist eine Verbindung mit dem Schloss nicht möglich.</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_280" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_280" translate="yes" xml:space="preserve">
<source>Errormessages improved for szenarios when <source>Errormessages improved for szenarios when
@ -1094,7 +1104,7 @@ Als aller letzten Ausweg das Schloss bitte per Hand schließen UND den Kundensup
</trans-unit> </trans-unit>
<trans-unit id="ErrorReservedSearchMessageEscalationLevel1" translate="yes" xml:space="preserve"> <trans-unit id="ErrorReservedSearchMessageEscalationLevel1" translate="yes" xml:space="preserve">
<source>Your mobile device still does not connect to the bike lock. Please restart the app or even your mobile device and repeat the process.</source> <source>Your mobile device still does not connect to the bike lock. Please restart the app or even your mobile device and repeat the process.</source>
<target state="translated">Ihr mobiles Gerät verbindet sich immer noch nicht mit dem Fahrradschloss. Bitte starten Sie die App oder sogar Ihr mobiles Gerät neu und wiederholen Sie den Vorgang.</target> <target state="translated">Ihr mobiles Gerät verbindet sich weiterhin nicht mit dem Schloss. Bitte starten Sie die App oder sogar Ihr mobiles Gerät neu und wiederholen Sie den Vorgang.</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_282" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_282" translate="yes" xml:space="preserve">
<source>Permission requests messages on iOS formulated in more detail. <source>Permission requests messages on iOS formulated in more detail.
@ -1104,7 +1114,7 @@ Hinweise, um das Verbinden Schlosses zu erleichtern, falls dies nicht beim erste
</trans-unit> </trans-unit>
<trans-unit id="ExceptionTextSessionExpired" translate="yes" xml:space="preserve"> <trans-unit id="ExceptionTextSessionExpired" translate="yes" xml:space="preserve">
<source>The session has expired. Please register again.</source> <source>The session has expired. Please register again.</source>
<target state="translated">Die Sitzung ist abgelaufen. Bitte neu anmelden.</target> <target state="translated">Die Sitzung ist abgelaufen. Bitte melden Sie sich erneut an.</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextAuthcookieNotDefinedException" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextAuthcookieNotDefinedException" translate="yes" xml:space="preserve">
<source>Auth. expired</source> <source>Auth. expired</source>
@ -1120,7 +1130,7 @@ Hinweise, um das Verbinden Schlosses zu erleichtern, falls dies nicht beim erste
</trans-unit> </trans-unit>
<trans-unit id="MessageAccountPageManagePersonalData" translate="yes" xml:space="preserve"> <trans-unit id="MessageAccountPageManagePersonalData" translate="yes" xml:space="preserve">
<source>Manage personal data</source> <source>Manage personal data</source>
<target state="translated">Persönliche Daten Verwalten</target> <target state="translated">Persönliche Daten verwalten</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_285" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_285" translate="yes" xml:space="preserve">
<source>Framework updated. <source>Framework updated.
@ -1129,12 +1139,12 @@ Activity indicator added account management pages and logging extended.</source>
Activity Indicator zu Konto-Verwaltungsseiten hinzugefügt und Logging erweitert.</target> Activity Indicator zu Konto-Verwaltungsseiten hinzugefügt und Logging erweitert.</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextStartReturningBike" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextStartReturningBike" translate="yes" xml:space="preserve">
<source>Starting bike return...</source> <source>Starting end rental...</source>
<target state="translated">Starte Rückgabe...</target> <target state="translated">Starte Miete beenden...</target>
</trans-unit> </trans-unit>
<trans-unit id="ExceptionTextWebConnectFailureException" translate="yes" xml:space="preserve"> <trans-unit id="ExceptionTextWebConnectFailureException" translate="yes" xml:space="preserve">
<source>Is WIFI available/ mobile network available and mobile data activated / ... ?</source> <source>Is WIFI/mobile network available and mobile data activated?</source>
<target state="translated">Ist WLAN verfügbar/ Mobilfunknetz vefügbar und mobile Daten aktiviert / ... ?</target> <target state="translated">Ist WLAN/Mobilfunknetz vefügbar und mobile Daten aktiviert?</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_289" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_289" translate="yes" xml:space="preserve">
<source>Flyout menu header improved.</source> <source>Flyout menu header improved.</source>
@ -1172,8 +1182,8 @@ Kleinere Fehlerbehebungen.
<target state="translated">Protokollierungsstufe</target> <target state="translated">Protokollierungsstufe</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingShowHideBikesOfType" translate="yes" xml:space="preserve"> <trans-unit id="MarkingShowHideBikesOfType" translate="yes" xml:space="preserve">
<source>Show/ hide</source> <source>Show/hide</source>
<target state="translated">Ausblenden/ Einblenden</target> <target state="translated">Ein-/Ausblenden</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingVerboseErrorMessage" translate="yes" xml:space="preserve"> <trans-unit id="MarkingVerboseErrorMessage" translate="yes" xml:space="preserve">
<source>Verbose error messages</source> <source>Verbose error messages</source>
@ -1224,17 +1234,19 @@ Kleinere Fehlerbehebungen.
<target state="translated">Neues Schloss unterstützt.</target> <target state="translated">Neues Schloss unterstützt.</target>
</trans-unit> </trans-unit>
<trans-unit id="ActionGiveFeedback" translate="yes" xml:space="preserve"> <trans-unit id="ActionGiveFeedback" translate="yes" xml:space="preserve">
<source>Give Feedback</source> <source>Give feedback</source>
<target state="translated">Rückmeldung Geben</target> <target state="translated">Rückmeldung geben</target>
</trans-unit> </trans-unit>
<trans-unit id="ActionContactMailAppReleated" translate="yes" xml:space="preserve"> <trans-unit id="ActionContactMailAppReleated" translate="yes" xml:space="preserve">
<source>Feedback about the App</source> <source>Feedback about the app</source>
<target state="translated">Rückmeldung zur App</target> <target state="needs-review-translation">Rückmeldung zur App</target>
<note from="MultilingualUpdate" annotates="source" priority="2">Please verify the translations accuracy as the source string was updated after it was translated.</note>
</trans-unit> </trans-unit>
<trans-unit id="MiscContactMailAppReleatedSubject" translate="yes" xml:space="preserve"> <trans-unit id="MiscContactMailAppReleatedSubject" translate="yes" xml:space="preserve">
<source>{0}-App Releated Request</source> <source>{0}-app releated request</source>
<target state="translated">{0}-App Anfrage</target> <target state="needs-review-translation">{0}-App Anfrage</target>
<note from="MultilingualBuild" annotates="source" priority="2">Subject of contact mail to ("Feedback about the app").</note> <note from="MultilingualBuild" annotates="source" priority="2">Subject of contact mail to ("Feedback about the app").</note>
<note from="MultilingualUpdate" annotates="source" priority="2">Please verify the translations accuracy as the source string was updated after it was translated.</note>
</trans-unit> </trans-unit>
<trans-unit id="MessageReservingBikeErrorConnectionTitle" translate="yes" xml:space="preserve"> <trans-unit id="MessageReservingBikeErrorConnectionTitle" translate="yes" xml:space="preserve">
<source>Connection error when reserving the bike!</source> <source>Connection error when reserving the bike!</source>
@ -1258,7 +1270,7 @@ Kleinere Fehlerbehebungen.
</trans-unit> </trans-unit>
<trans-unit id="MessageOpeningLockErrorConnectionTitle" translate="yes" xml:space="preserve"> <trans-unit id="MessageOpeningLockErrorConnectionTitle" translate="yes" xml:space="preserve">
<source>Connection error when opening the lock!</source> <source>Connection error when opening the lock!</source>
<target state="translated">Verbindungsfehler beim Schlossöffnen!</target> <target state="translated">Verbindungsfehler beim Öffnen des Schlosses!</target>
</trans-unit> </trans-unit>
<trans-unit id="ActivityTextSubmittingFeedback" translate="yes" xml:space="preserve"> <trans-unit id="ActivityTextSubmittingFeedback" translate="yes" xml:space="preserve">
<source>Submitting feedback...</source> <source>Submitting feedback...</source>
@ -1286,15 +1298,15 @@ Kleinere Fehlerbehebungen.
</trans-unit> </trans-unit>
<trans-unit id="MarkingReturnBikeErrorDescriptionInputPlaceholder" translate="yes" xml:space="preserve"> <trans-unit id="MarkingReturnBikeErrorDescriptionInputPlaceholder" translate="yes" xml:space="preserve">
<source>Please describe condition/defect here.</source> <source>Please describe condition/defect here.</source>
<target state="translated">Bitte Zustand/ Defekt hier beschreiben.</target> <target state="translated">Bitte Zustand/Defekt hier beschreiben.</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingReturnBikeFeedbackInputPlaceholder" translate="yes" xml:space="preserve"> <trans-unit id="MarkingReturnBikeFeedbackInputPlaceholder" translate="yes" xml:space="preserve">
<source>Please enter feedback here if needed.</source> <source>Please enter feedback here if needed.</source>
<target state="translated">Bei Bedarf bitte hier Rückmeldung eingeben.</target> <target state="translated">Bei Bedarf bitte hier Rückmeldung eingeben.</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingReturnBikeMainMessage" translate="yes" xml:space="preserve"> <trans-unit id="MarkingReturnBikeMainMessage" translate="yes" xml:space="preserve">
<source>Bike successfully returned!</source> <source>Rental successfully ended!</source>
<target state="translated">Fahrrad erfolgreich zurückgegeben!</target> <target state="translated">Rad erfolgreich zurückgegeben!</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingDriveBatteryTitel" translate="yes" xml:space="preserve"> <trans-unit id="MarkingDriveBatteryTitel" translate="yes" xml:space="preserve">
<source>Current battery level:</source> <source>Current battery level:</source>
@ -1305,12 +1317,12 @@ Kleinere Fehlerbehebungen.
<target state="translated">Für Mein konrad Nutzer: Anzeige des Akkuladestands für E-Bikes und Abfrage des Ladestands nach Radrückgabe.</target> <target state="translated">Für Mein konrad Nutzer: Anzeige des Akkuladestands für E-Bikes und Abfrage des Ladestands nach Radrückgabe.</target>
</trans-unit> </trans-unit>
<trans-unit id="StatusTextLowBatteryLevel" translate="yes" xml:space="preserve"> <trans-unit id="StatusTextLowBatteryLevel" translate="yes" xml:space="preserve">
<source>The remaining power of the bike battery was low recently. Please check it on the bike display before riding. The bike can be returned within 5 minutes free of charge.</source> <source>The remaining power of the bike battery was low recently. Please check it on the bike display before riding. The rental can be canceled within 5 minutes free of charge.</source>
<target state="translated">Die verbleibende Ladung des Fahrradakkus war zuletzt niedrig. Bitte überprüfen Sie diese vor der Fahrt auf dem Fahrraddisplay. Das Rad kann innerhalb 5 Minuten kostenlos zurückgegeben werden.</target> <target state="translated">Die verbleibende Ladung des Fahrradakkus war zuletzt niedrig. Bitte überprüfen Sie diese vor der Fahrt auf dem Fahrraddisplay. Die Miete kann innerhalb 5 Minuten kostenlos abgebrochen werden.</target>
</trans-unit> </trans-unit>
<trans-unit id="StatusTextCopriLock" translate="yes" xml:space="preserve"> <trans-unit id="StatusTextCopriLock" translate="yes" xml:space="preserve">
<source>At pausing ride, you close the bike lock manually, not via the app. To end the chargeable rental, slide the bike into an authorized station and confirm the end of the rental in the app; the lock closes automatically.</source> <source>At pausing ride, you close the bike lock manually, not via the app. To end the chargeable rental, slide the bike into an authorized station and confirm the end of the rental in the app; the lock closes automatically.</source>
<target state="translated">Zur Fahrpause schließen Sie das Fahrradschloss manuell, nicht über die App. Zum Beenden der kostenpflichtigen Miete schieben Sie das Rad in eine zugelassene Station und bestätigen das Mietende in der App; das Schloss schließt automatisch.</target> <target state="translated">Zur Fahrpause schließen Sie das Schloss manuell, nicht über die App. Zum Beenden der kostenpflichtigen Miete schieben Sie das Rad in eine zugelassene Station und bestätigen das Mietende in der App; das Schloss schließt automatisch.</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_335" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_335" translate="yes" xml:space="preserve">
<source>Sharee.bike design improved.</source> <source>Sharee.bike design improved.</source>
@ -1322,7 +1334,7 @@ Kleinere Fehlerbehebungen.
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_337_MK" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_337_MK" translate="yes" xml:space="preserve">
<source>You will now be informed if the charge of the bike battery was last indicated as very low. To ensure the reliability of the battery level indicator in the app, please enter the current charge level in the app at the end of your ride with an e-bike.</source> <source>You will now be informed if the charge of the bike battery was last indicated as very low. To ensure the reliability of the battery level indicator in the app, please enter the current charge level in the app at the end of your ride with an e-bike.</source>
<target state="translated">Sie werden nun informiert, wenn die Ladung des Fahrradakkus zuletzt als sehr niedrig angegeben wurde. Um die Zuverlässigkeit der Akkustandanzeige in der App zu gewährleisten, geben Sie bitte am Ende Ihrer Fahrt mit einem E-Lastenrad den aktuellen Ladestand in die App ein.</target> <target state="translated">Sie werden nun informiert, wenn die Ladung des Radakkus zuletzt als sehr niedrig angegeben wurde. Um die Zuverlässigkeit der Akkustandanzeige in der App zu gewährleisten, geben Sie bitte am Ende Ihrer Fahrt mit einem E-Lastenrad den aktuellen Ladestand in die App ein.</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_337_SB" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_337_SB" translate="yes" xml:space="preserve">
<source>The app has a new design! --- You are a beta tester? Give us helpful feedback anytime via Contact - Feedback about the App. Not a beta tester yet? Become one and get great new features before anyone else!</source> <source>The app has a new design! --- You are a beta tester? Give us helpful feedback anytime via Contact - Feedback about the App. Not a beta tester yet? Become one and get great new features before anyone else!</source>
@ -1374,7 +1386,7 @@ Außerdem: Kleine Grafiken lassen auf einen Blick erkennen um was für einen Rad
</trans-unit> </trans-unit>
<trans-unit id="PlaceholderFindBike" translate="yes" xml:space="preserve"> <trans-unit id="PlaceholderFindBike" translate="yes" xml:space="preserve">
<source>Enter bike number here</source> <source>Enter bike number here</source>
<target state="translated">Fahrrad-Nummer hier eingeben</target> <target state="translated">Rad-Nummer hier eingeben</target>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog3_0_339_MK" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog3_0_339_MK" translate="yes" xml:space="preserve">
<source>The cargo bikes from the suburbs now show their home station in their name. These bikes must be returned there! <source>The cargo bikes from the suburbs now show their home station in their name. These bikes must be returned there!
@ -1518,11 +1530,11 @@ Probieren Sie es aus!</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingBikesAtStationNoBikesAvailable" translate="yes" xml:space="preserve"> <trans-unit id="MarkingBikesAtStationNoBikesAvailable" translate="yes" xml:space="preserve">
<source>There are currently no bicycles available at this station.</source> <source>There are currently no bicycles available at this station.</source>
<target state="translated">Momentan sind keine Fahrräder an dieser Station verfügbar.</target> <target state="translated">Momentan sind keine Räder an dieser Station verfügbar.</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingMyBikesNoBikesReservedRented" translate="yes" xml:space="preserve"> <trans-unit id="MarkingMyBikesNoBikesReservedRented" translate="yes" xml:space="preserve">
<source>There are currently no bicycles reserved/booked on user {0}.</source> <source>There are currently no bikes reserved/rented by user {0}.</source>
<target state="translated">Momentan sind keine Fahrräder auf Benutzer {0} reserviert/ gebucht.</target> <target state="translated">Momentan sind keine Räder von Nutzer {0} reserviert/gemietet.</target>
</trans-unit> </trans-unit>
<trans-unit id="MessageTitleInformation" translate="yes" xml:space="preserve"> <trans-unit id="MessageTitleInformation" translate="yes" xml:space="preserve">
<source>Information</source> <source>Information</source>
@ -1533,16 +1545,17 @@ Probieren Sie es aus!</target>
<target state="translated">Kleine Verbesserungen.</target> <target state="translated">Kleine Verbesserungen.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorOpenLockBoldStatusIsUnknownMessage" translate="yes" xml:space="preserve"> <trans-unit id="ErrorOpenLockBoldStatusIsUnknownMessage" translate="yes" xml:space="preserve">
<source>The lock could not be opened correctly. Please try again. <source>The lock could not be opened correctly. Try again!
Attention! Your rental has already started. Attention! Your rental has already started.
If the lock still won't open, make sure the lock is closed and end rental.
If the lock still won't open, make sure the lock is closed and return the bike. Please report it to the support!</source> Important: Send an email to the operator (otherwise your paid rental will continue!) with: Problem description, bike number, drop-off station.</source>
<target state="translated">Das Schloss konnte nicht korrekt geöffnet werden. Bitte versuchen Sie es erneut. <target state="translated">Das Schloss konnte nicht korrekt geöffnet werden. Bitte versuchen Sie es erneut.
Achtung! Ihre Miete hat bereits begonnen. Achtung! Ihre Miete hat bereits begonnen.
Wenn sich das Schloss weiterhin nicht öffnen lässt, vergewissern Sie sich, dass das Schloss geschlossen ist und geben Sie das Rad zurück. Bitte melden Sie es dem Support!</target> Wenn sich das Schloss weiterhin nicht öffnen lässt, vergewissern Sie sich, dass das Schloss geschlossen ist und geben Sie das Rad zurück.
Wichtig: Schicken Sie eine E-Mail an den Betreiber (ansonsten läuft Ihre kostenpflichtige Miete weiter!): Problembeschreibung, Radnummer, Abgabestation.</target>
</trans-unit> </trans-unit>
<trans-unit id="ErrorOpenLockStillClosedTitle" translate="yes" xml:space="preserve"> <trans-unit id="ErrorOpenLockStillClosedTitle" translate="yes" xml:space="preserve">
<source>Lock can not be opened!</source> <source>Lock can not be opened!</source>
@ -1553,8 +1566,9 @@ Wenn sich das Schloss weiterhin nicht öffnen lässt, vergewissern Sie sich, das
<target state="translated">Stellen Sie sicher, dass kein Hindernis das Öffnen des Schlosses verhindert und versuchen Sie es erneut.</target> <target state="translated">Stellen Sie sicher, dass kein Hindernis das Öffnen des Schlosses verhindert und versuchen Sie es erneut.</target>
</trans-unit> </trans-unit>
<trans-unit id="MarkingNoNetworkConnection" translate="yes" xml:space="preserve"> <trans-unit id="MarkingNoNetworkConnection" translate="yes" xml:space="preserve">
<source>Oops, there is no internet connection.</source> <source>Oops, there is no Internet connection.</source>
<target state="translated">Ups, es ist keine Internetverbindung vorhanden.</target> <target state="needs-review-translation">Ups, es ist keine Internetverbindung vorhanden.</target>
<note from="MultilingualUpdate" annotates="source" priority="2">Please verify the translations accuracy as the source string was updated after it was translated.</note>
</trans-unit> </trans-unit>
<trans-unit id="ChangeLog_3_0_358_MK_SB" translate="yes" xml:space="preserve"> <trans-unit id="ChangeLog_3_0_358_MK_SB" translate="yes" xml:space="preserve">
<source>New functions:<bpt id="1">&lt;ul&gt;</bpt><bpt id="2">&lt;li&gt;</bpt>If your device is not connected to the Internet, this is now displayed at the top.<ept id="2">&lt;/li&gt;</ept><bpt id="3">&lt;li&gt;</bpt>You can now update your bike view by dragging from top to bottom. Especially useful after you reconnect to the Internet.<ept id="3">&lt;/li&gt;</ept><ept id="1">&lt;/ul&gt;</ept> <source>New functions:<bpt id="1">&lt;ul&gt;</bpt><bpt id="2">&lt;li&gt;</bpt>If your device is not connected to the Internet, this is now displayed at the top.<ept id="2">&lt;/li&gt;</ept><bpt id="3">&lt;li&gt;</bpt>You can now update your bike view by dragging from top to bottom. Especially useful after you reconnect to the Internet.<ept id="3">&lt;/li&gt;</ept><ept id="1">&lt;/ul&gt;</ept>
@ -1566,6 +1580,42 @@ Wenn sich das Schloss weiterhin nicht öffnen lässt, vergewissern Sie sich, das
<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> <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> <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> </trans-unit>
<trans-unit id="ErrorReturnBikeLockClosedStartGetGPSExceptionMessage" translate="yes" xml:space="preserve">
<source>End rental at an unknown location is not possible.
Start getting geolocation failed.</source>
<target state="translated">Beenden der Miete an unbekanntem Standort is nicht möglich.
Fehler beim Start der Standortabfrage!</target>
</trans-unit>
<trans-unit id="ErrorReturnBikeLockClosedGetGPSExceptionMessage" translate="yes" xml:space="preserve">
<source>End rental at an unknown location is not possible.
Getting geolocation failed.</source>
<target state="translated">Beenden der Miete an unbekanntem Standort is nicht möglich.
Fehler bei der Standortabfrage!</target>
</trans-unit>
<trans-unit id="Error_ReturnBike_Station_Location_Message" translate="yes" xml:space="preserve">
<source>We could not assign the bike to any station. For this we need your location information while you are standing right next to the bike. Only then your rental can be terminated!
Approach the bike, turn on Bluetooth and Location services and try again.</source>
<target state="translated">Wir konnten das Rad keiner Station zuordnen. Dazu benötigen wir Ihre Standortinformationen, während Sie direkt neben dem Rad stehen. Nur dann kann Ihre Miete beendet werden!
Treten Sie an das Rad heran, schalten Sie Bluetooth und Standortdienste ein und versuchen Sie es erneut.</target>
</trans-unit>
<trans-unit id="ChangeLog_3_0_362_MK_SB" translate="yes" xml:space="preserve">
<source>Some terms have been standardized, e.g:&lt;br/&gt;
- what used to be called 'return bike' is now always called 'end rental'.&lt;br/&gt;
- The 'operator' is the group of people responsible for the bike fleet, who will be contacted if necessary.&lt;br/&gt;
&lt;br/&gt;
Also:&lt;br/&gt;
- Minor bug fixes&lt;br/&gt;
- Package updates</source>
<target state="translated">Einige Bezeichnungen wurden vereinheitlicht, z.B:&lt;br/&gt;
- was bisher unter 'Rad zurückgeben' lief, heißt nun immer 'Miete beenden'.&lt;br/&gt;
- der 'Betreiber' ist die für die Radflotte zuständige Personengruppe, zu der bei Bedarf Kontakt aufgenommen wird.&lt;br/&gt;
&lt;br/&gt;
Außerdem:&lt;br/&gt;
- Kleinere Fehlerbehebungen&lt;br/&gt;
- Paketaktualisierungen</target>
</trans-unit>
</group> </group>
</body> </body>
</file> </file>

View file

@ -0,0 +1,36 @@
using System;
namespace TINK.Services.Geolocation
{
public class Geolocation : IGeolocation
{
private Geolocation() { }
public DateTimeOffset Timestamp { get; private set; }
public double Latitude { get; private set; }
public double Longitude { get; private set; }
public double? Accuracy { get; private set; }
public class Builder
{
public DateTimeOffset Timestamp { get; set; }
public double Latitude { get; set; }
public double Longitude { get; set; }
public double? Accuracy { get; set; }
public Geolocation Build()
=> new Geolocation() {
Timestamp = Timestamp,
Latitude = Latitude,
Longitude = Longitude,
Accuracy = Accuracy};
}
}
}

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog; using Serilog;
@ -7,7 +7,7 @@ using Xamarin.Essentials;
namespace TINK.Services.Geolocation namespace TINK.Services.Geolocation
{ {
public abstract class GeolocationService : IGeolocation public abstract class GeolocationService : IGeolocationService
{ {
/// <summary> Timeout for geolocation request operations.</summary> /// <summary> Timeout for geolocation request operations.</summary>
private const int GEOLOCATIONREQUEST_TIMEOUT_MS = 5000; private const int GEOLOCATIONREQUEST_TIMEOUT_MS = 5000;
@ -31,14 +31,14 @@ namespace TINK.Services.Geolocation
/// <summary> Gets the current location.</summary> /// <summary> Gets the current location.</summary>
/// <param name="cancellationToken">Token to cancel request for geolocation.</param> /// <param name="cancellationToken">Token to cancel request for geolocation.</param>
/// <param name="timeStamp">Time when geolocation is of interest. Is used to determine whether cached geoloation can be used or not.</param> /// <param name="timeStamp">Time when geolocation is of interest. Is used to determine whether cached geoloation can be used or not.</param>
public async Task<Location> GetAsync(CancellationToken? cancellationToken = null, DateTime? timeStamp = null) public async Task<IGeolocation> GetAsync(CancellationToken? cancellationToken = null, DateTime? timeStamp = null)
{ {
try try
{ {
var request = new GeolocationRequest(Accuracy, TimeSpan.FromMilliseconds(GEOLOCATIONREQUEST_TIMEOUT_MS)); var request = new GeolocationRequest(Accuracy, TimeSpan.FromMilliseconds(GEOLOCATIONREQUEST_TIMEOUT_MS));
return cancellationToken.HasValue return cancellationToken.HasValue
? await Xamarin.Essentials.Geolocation.GetLocationAsync(request, cancellationToken.Value) ? (await Xamarin.Essentials.Geolocation.GetLocationAsync(request, cancellationToken.Value)).ToGeolocation()
: await Xamarin.Essentials.Geolocation.GetLocationAsync(request); : (await Xamarin.Essentials.Geolocation.GetLocationAsync(request)).ToGeolocation();
} }
catch (FeatureNotSupportedException fnsEx) catch (FeatureNotSupportedException fnsEx)
{ {

View file

@ -1,21 +1,15 @@
using System; using System;
using System.Threading;
using System.Threading.Tasks;
using TINK.Model.Device;
using Xamarin.Essentials;
namespace TINK.Services.Geolocation namespace TINK.Services.Geolocation
{ {
/// <summary> Query geolocation. </summary> public interface IGeolocation
public interface IGeolocation : IGeolodationDependent
{ {
/// <summary> Gets the current location.</summary>
/// <param name="cancellationToken">Token to cancel request for geolocation. If null request can not be cancels and times out after GeolocationService.GEOLOCATIONREQUEST_TIMEOUT_MS if geolocation is not available.</param>
/// <param name="timeStamp">Time when geolocation is of interest. Is used to determine for some implementations whether cached geoloation can be used or not.</param>
/// <returns></returns>
Task<Location> GetAsync(CancellationToken? cancellationToken = null, DateTime? timeStamp = null);
/// <summary> If true location data returned is simulated.</summary> double Latitude { get; }
bool IsSimulation { get; }
double Longitude { get; }
double? Accuracy { get; }
DateTimeOffset Timestamp { get; }
} }
} }

View file

@ -0,0 +1,21 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using TINK.Model.Device;
using Xamarin.Essentials;
namespace TINK.Services.Geolocation
{
/// <summary> Query geolocation. </summary>
public interface IGeolocationService : IGeolodationDependent
{
/// <summary> Gets the current location.</summary>
/// <param name="cancellationToken">Token to cancel request for geolocation. If null request can not be cancels and times out after GeolocationService.GEOLOCATIONREQUEST_TIMEOUT_MS if geolocation is not available.</param>
/// <param name="timeStamp">Time when geolocation is of interest. Is used to determine for some implementations whether cached geoloation can be used or not.</param>
/// <returns></returns>
Task<IGeolocation> GetAsync(CancellationToken? cancellationToken = null, DateTime? timeStamp = null);
/// <summary> If true location data returned is simulated.</summary>
bool IsSimulation { get; }
}
}

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Serilog; using Serilog;
@ -7,7 +7,7 @@ using Xamarin.Essentials;
namespace TINK.Services.Geolocation namespace TINK.Services.Geolocation
{ {
public class LastKnownGeolocationService : IGeolocation public class LastKnownGeolocationService : IGeolocationService
{ {
private IGeolodationDependent Dependent { get; } private IGeolodationDependent Dependent { get; }
@ -19,12 +19,12 @@ namespace TINK.Services.Geolocation
/// <summary> Gets the current location.</summary> /// <summary> Gets the current location.</summary>
/// <param name="cancelationToken">Token to cancel request for geolocation.</param> /// <param name="cancelationToken">Token to cancel request for geolocation.</param>
/// <param name="timeStamp">Time when geolocation is of interest. Is used to determine whether cached geoloation can be used or not.</param> /// <param name="timeStamp">Time when geolocation is of interest. Is used to determine whether cached geoloation can be used or not.</param>
public async Task<Location> GetAsync(CancellationToken? cancelationToken = null, DateTime? timeStamp = null) public async Task<IGeolocation> GetAsync(CancellationToken? cancelationToken = null, DateTime? timeStamp = null)
{ {
Location location; IGeolocation location;
try try
{ {
location = await Xamarin.Essentials.Geolocation.GetLastKnownLocationAsync(); location = (await Xamarin.Essentials.Geolocation.GetLastKnownLocationAsync()).ToGeolocation();
} }
catch (FeatureNotSupportedException fnsEx) catch (FeatureNotSupportedException fnsEx)
{ {

View file

@ -0,0 +1,21 @@
using Xamarin.Essentials;
namespace TINK.Services.Geolocation
{
public static class LocationHelper
{
/// <summary>
/// Converts Xamarin.Essentials Location object to Geolocatin object.
/// </summary>
/// <param name="location"></param>
/// <returns></returns>
public static IGeolocation ToGeolocation(this Location location)
=> new Geolocation.Builder
{
Latitude = location.Latitude,
Longitude = location.Longitude,
Accuracy = location.Accuracy,
Timestamp = location.Timestamp,
}.Build();
}
}

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using TINK.Model.Device; using TINK.Model.Device;
@ -6,7 +6,7 @@ using Xamarin.Essentials;
namespace TINK.Services.Geolocation namespace TINK.Services.Geolocation
{ {
public class SimulatedGeolocationService : IGeolocation public class SimulatedGeolocationService : IGeolocationService
{ {
private IGeolodationDependent Dependent { get; } private IGeolodationDependent Dependent { get; }
@ -18,9 +18,13 @@ namespace TINK.Services.Geolocation
/// <summary> Gets the current location.</summary> /// <summary> Gets the current location.</summary>
/// <param name="cancelToken">Token to cancel request for geolocation.</param> /// <param name="cancelToken">Token to cancel request for geolocation.</param>
/// <param name="timeStamp">Time when geolocation is of interest. Is used to determine whether cached geoloation can be used or not.</param> /// <param name="timeStamp">Time when geolocation is of interest. Is used to determine whether cached geoloation can be used or not.</param>
public async Task<Location> GetAsync(CancellationToken? cancelToken = null, DateTime? timeStamp = null) public async Task<IGeolocation> GetAsync(CancellationToken? cancelToken = null, DateTime? timeStamp = null)
{ {
return await Task.FromResult(new Location(47.976634, 7.825490) { Accuracy = 0, Timestamp = timeStamp ?? DateTime.Now }); ; return await Task.FromResult(new Geolocation.Builder {
Latitude = 47.976634,
Longitude = 7.825490,
Accuracy = 0,
Timestamp = timeStamp ?? DateTime.Now }.Build()); ;
} }
/// <summary> If true location data returned is simulated.</summary> /// <summary> If true location data returned is simulated.</summary>

View file

@ -26,7 +26,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="MonkeyCache" Version="1.6.3" /> <PackageReference Include="MonkeyCache" Version="1.6.3" />
<PackageReference Include="MonkeyCache.FileStore" Version="1.6.3" /> <PackageReference Include="MonkeyCache.FileStore" Version="1.6.3" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Plugin.BLE" Version="2.1.3" /> <PackageReference Include="Plugin.BLE" Version="2.1.3" />
<PackageReference Include="Plugin.BluetoothLE" Version="6.3.0.19" /> <PackageReference Include="Plugin.BluetoothLE" Version="6.3.0.19" />
<PackageReference Include="Plugin.Permissions" Version="6.0.1" /> <PackageReference Include="Plugin.Permissions" Version="6.0.1" />
@ -45,7 +45,7 @@
<PackageReference Include="Xam.Plugin.Connectivity" Version="3.2.0" /> <PackageReference Include="Xam.Plugin.Connectivity" Version="3.2.0" />
<PackageReference Include="Xam.Plugins.Messaging" Version="5.2.0" /> <PackageReference Include="Xam.Plugins.Messaging" Version="5.2.0" />
<PackageReference Include="Xamarin.Essentials" Version="1.7.5" /> <PackageReference Include="Xamarin.Essentials" Version="1.7.5" />
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2545" /> <PackageReference Include="Xamarin.Forms" Version="5.0.0.2578" />
<PackageReference Include="Xamarin.Forms.GoogleMaps" Version="5.0.0" /> <PackageReference Include="Xamarin.Forms.GoogleMaps" Version="5.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -1,4 +1,4 @@
using System; using System;
using TINK.Model.Connector; using TINK.Model.Connector;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Model.User; using TINK.Model.User;
@ -17,7 +17,7 @@ namespace TINK.ViewModel.Bikes.Bike
public static BikeViewModelBase Create( public static BikeViewModelBase Create(
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocationService,
ILocksService lockService, ILocksService lockService,
Action<string> bikeRemoveDelegate, Action<string> bikeRemoveDelegate,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
@ -34,7 +34,7 @@ namespace TINK.ViewModel.Bikes.Bike
return new BluetoothLock.BikeViewModel( return new BluetoothLock.BikeViewModel(
isConnectedDelegate, isConnectedDelegate,
connectorFactory, connectorFactory,
geolocation, geolocationService,
lockService, lockService,
bikeRemoveDelegate, bikeRemoveDelegate,
viewUpdateManager, viewUpdateManager,

View file

@ -27,7 +27,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
/// <summary> Notifies GUI about changes. </summary> /// <summary> Notifies GUI about changes. </summary>
public override event PropertyChangedEventHandler PropertyChanged; public override event PropertyChangedEventHandler PropertyChanged;
private IGeolocation Geolocation { get; } private IGeolocationService GeolocationService { get; }
private ILocksService LockService { get; } private ILocksService LockService { get; }
@ -91,7 +91,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
public BikeViewModel( public BikeViewModel(
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocationService,
ILocksService lockService, ILocksService lockService,
Action<string> bikeRemoveDelegate, Action<string> bikeRemoveDelegate,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
@ -117,7 +117,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
selectedBike, selectedBike,
isConnectedDelegate, isConnectedDelegate,
connectorFactory, connectorFactory,
geolocation, geolocationService,
lockService, lockService,
viewUpdateManager, viewUpdateManager,
smartDevice, smartDevice,
@ -129,8 +129,8 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
viewService, viewService,
bikesViewModel); bikesViewModel);
Geolocation = geolocation GeolocationService = geolocationService
?? throw new ArgumentException($"Can not instantiate {this.GetType().Name}-object. Parameter {nameof(geolocation)} can not be null."); ?? throw new ArgumentException($"Can not instantiate {this.GetType().Name}-object. Parameter {nameof(geolocationService)} can not be null.");
LockService = lockService LockService = lockService
?? throw new ArgumentException($"Can not instantiate {this.GetType().Name}-object. Parameter {nameof(lockService)} can not be null."); ?? throw new ArgumentException($"Can not instantiate {this.GetType().Name}-object. Parameter {nameof(lockService)} can not be null.");
@ -156,7 +156,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
Bike, Bike,
IsConnectedDelegate, IsConnectedDelegate,
ConnectorFactory, ConnectorFactory,
Geolocation, GeolocationService,
LockService, LockService,
ViewUpdateManager, ViewUpdateManager,
SmartDevice, SmartDevice,
@ -208,7 +208,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
// No state change occurred (same instance is returned). // No state change occurred (same instance is returned).
return; return;
} }
RaisePropertyChangedEvent( RaisePropertyChangedEvent(
lastHandler, lastHandler,
lastStateText, lastStateText,

View file

@ -1,4 +1,4 @@
using System; using System;
using TINK.Model.Connector; using TINK.Model.Connector;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.Model.User; using TINK.Model.User;
@ -22,7 +22,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
bool isCopriButtonVisible, bool isCopriButtonVisible,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice, ISmartDevice smartDevice,
@ -30,14 +30,14 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IBikesViewModel bikesViewModel, IBikesViewModel bikesViewModel,
IUser activeUser) : base(selectedBike, buttonText, isCopriButtonVisible, isConnectedDelegate, connectorFactory, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser) IUser activeUser) : base(selectedBike, buttonText, isCopriButtonVisible, isConnectedDelegate, connectorFactory, viewUpdateManager, smartDevice, viewService, bikesViewModel, activeUser)
{ {
Geolocation = geolocation GeolocationService = geolocation
?? throw new ArgumentException($"Can not construct {GetType().Name}-object. Parameter {nameof(geolocation)} must not be null."); ?? throw new ArgumentException($"Can not construct {GetType().Name}-object. Parameter {nameof(geolocation)} must not be null.");
LockService = lockService LockService = lockService
?? throw new ArgumentException($"Can not construct {GetType().Name}-object. Parameter {nameof(lockService)} must not be null."); ?? throw new ArgumentException($"Can not construct {GetType().Name}-object. Parameter {nameof(lockService)} must not be null.");
} }
protected IGeolocation Geolocation { get; } protected IGeolocationService GeolocationService { get; }
protected ILocksService LockService { get; } protected ILocksService LockService { get; }

View file

@ -15,7 +15,6 @@ using TINK.Services.BluetoothLock;
using TINK.Services.BluetoothLock.Exception; using TINK.Services.BluetoothLock.Exception;
using TINK.Services.Geolocation; using TINK.Services.Geolocation;
using TINK.View; using TINK.View;
using Xamarin.Essentials;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{ {
@ -27,7 +26,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IBikeInfoMutable selectedBike, IBikeInfoMutable selectedBike,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice, ISmartDevice smartDevice,
@ -62,24 +61,69 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{ {
BikesViewModel.IsIdle = false; BikesViewModel.IsIdle = false;
var ctsLocation = new CancellationTokenSource(); var ctsLocation = new CancellationTokenSource();
Task<Location> currentLocationTask = null; Task<IGeolocation> currentLocationTask = null;
var timeStamp = DateTime.Now;
// Try getting geolocation which was requested when closing lock.
IGeolocation currentLocation = SelectedBike.LockInfo.Location;
var lastConfimredLockStateTimeStamp = SelectedBike.LockInfo.LastLockingStateChange;
// Check if bike is around. // Check if bike is around.
var deviceState = LockService[SelectedBike.LockInfo.Id].GetDeviceState(); var deviceState = LockService[SelectedBike.LockInfo.Id].GetDeviceState();
if (deviceState == DeviceState.Connected)
// Check if
// - geolocation is already available
// - or if bike is in reach so that geolocation makes sense
if (currentLocation == null && deviceState != DeviceState.Connected)
{ {
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart; // Bluetooth is in reach // Geolocation information is missing and can not be queried.
Log.ForContext<BookedClosed>().Information("User selected booked bike {bike} but returning failed. COPRI returned an error.", SelectedBike);
await ViewService.DisplayAlert(
AppResources.ErrorReturnBikeTitle,
AppResources.Error_ReturnBike_Station_Location_Message,
AppResources.MessageAnswerOk);
// Disconnect lock.
BikesViewModel.ActionText = AppResources.ActivityTextDisconnectingLock;
try
{
SelectedBike.LockInfo.State = await LockService.DisconnectAsync(SelectedBike.LockInfo.Id, SelectedBike.LockInfo.Guid);
}
catch (Exception exception)
{
Log.ForContext<BookedClosed>().Error("Lock can not be disconnected. {Exception}", exception);
BikesViewModel.ActionText = AppResources.ActivityTextErrorDisconnect;
}
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
}
// Check if quering geolocation is required.
if (currentLocation == null)
{
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart;
// Start getting geolocation. // Start getting geolocation.
try try
{ {
currentLocationTask = Geolocation.GetAsync(ctsLocation.Token, timeStamp); currentLocationTask = GeolocationService.GetAsync(ctsLocation.Token, DateTime.Now);
} }
catch (Exception ex) catch (Exception ex)
{ {
// No location information available. // No location information available.
Log.ForContext<BookedClosed>().Information("Getting geolocation when returning bike {Bike} failed. {Exception}", SelectedBike, ex); Log.ForContext<BookedClosed>().Information("Getting geolocation when returning bike {Bike} failed. {Exception}", SelectedBike, ex);
await ViewService.DisplayAlert(
AppResources.ErrorReturnBikeTitle,
AppResources.ErrorReturnBikeLockClosedStartGetGPSExceptionMessage,
AppResources.MessageAnswerOk);
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return this;
} }
} }
@ -119,10 +163,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease; BikesViewModel.ActionText = AppResources.ActivityTextOneMomentPlease;
await ViewUpdateManager().StopUpdatePeridically(); await ViewUpdateManager().StopUpdatePeridically();
// Check if bike is around. // Get geolocation if
Location currentLocation = null; // - geolocation was not available when closing lock
// - bike is around (lock is connected via bluetooth)
LocationDto currentLocationDto = null; LocationDto currentLocationDto = null;
if (deviceState == DeviceState.Connected) if (currentLocation == null)
{ {
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation; BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation;
try try
@ -134,24 +179,32 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{ {
// No location information available. // No location information available.
Log.ForContext<BookedClosed>().Information("Returning closed bike {Bike} is not possible. Cancel geolocation query failed. {Exception}", SelectedBike, ex); Log.ForContext<BookedClosed>().Information("Returning closed bike {Bike} is not possible. Cancel geolocation query failed. {Exception}", SelectedBike, ex);
await ViewService.DisplayAlert(
AppResources.ErrorReturnBikeTitle,
AppResources.ErrorReturnBikeLockClosedGetGPSExceptionMessage,
AppResources.MessageAnswerOk);
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdater;
await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true;
return this;
} }
currentLocationDto = currentLocation != null lastConfimredLockStateTimeStamp = DateTime.Now;
? new LocationDto.Builder
{
Latitude = currentLocation.Latitude,
Longitude = currentLocation.Longitude,
Accuracy = currentLocation.Accuracy ?? double.NaN,
Age = timeStamp.Subtract(currentLocation.Timestamp.DateTime),
}.Build()
: null;
}
else
{
// Bluetooth out of reach. Lock state is no more known.
SelectedBike.LockInfo.State = LockingState.UnknownDisconnected;
} }
currentLocationDto = currentLocation != null
? new LocationDto.Builder
{
Latitude = currentLocation.Latitude,
Longitude = currentLocation.Longitude,
Accuracy = currentLocation.Accuracy ?? double.NaN,
Age = lastConfimredLockStateTimeStamp is DateTime lastLockState ? lastLockState.Subtract(currentLocation.Timestamp.DateTime) : TimeSpan.MaxValue,
}.Build()
: null;
BikesViewModel.ActionText = AppResources.ActivityTextReturningBike; BikesViewModel.ActionText = AppResources.ActivityTextReturningBike;
IsConnected = IsConnectedDelegate(); IsConnected = IsConnectedDelegate();
@ -229,7 +282,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
Log.ForContext<BookedClosed>().Information("User returned bike {bike} successfully.", SelectedBike); Log.ForContext<BookedClosed>().Information("User returned bike {bike} successfully.", SelectedBike);
@ -289,7 +342,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
#endif #endif
if (bookingFinished != null && bookingFinished.MiniSurvey.Questions.Count > 0) if (bookingFinished != null && bookingFinished.MiniSurvey.Questions.Count > 0)
@ -302,7 +355,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
/// <summary> Open bike and update COPRI lock state. </summary> /// <summary> Open bike and update COPRI lock state. </summary>
@ -384,7 +437,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
@ -454,7 +507,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
} }
} }

View file

@ -24,7 +24,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IBikeInfoMutable selectedBike, IBikeInfoMutable selectedBike,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice, ISmartDevice smartDevice,
@ -240,7 +240,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
} }
} }

View file

@ -16,7 +16,6 @@ using TINK.Services.BluetoothLock.Exception;
using TINK.Services.Geolocation; using TINK.Services.Geolocation;
using TINK.Services.Logging; using TINK.Services.Logging;
using TINK.View; using TINK.View;
using Xamarin.Essentials;
namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
{ {
@ -27,7 +26,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IBikeInfoMutable selectedBike, IBikeInfoMutable selectedBike,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice, ISmartDevice smartDevice,
@ -66,11 +65,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Start getting geolocation. // Start getting geolocation.
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart; BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart;
var ctsLocation = new CancellationTokenSource(); var ctsLocation = new CancellationTokenSource();
Task<Location> currentLocationTask = null; Task<IGeolocation> currentLocationTask = null;
var timeStamp = DateTime.Now; var timeStamp = DateTime.Now;
try try
{ {
currentLocationTask = Geolocation.GetAsync(ctsLocation.Token, timeStamp); currentLocationTask = GeolocationService.GetAsync(ctsLocation.Token, timeStamp);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -88,7 +87,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Ask whether to really return bike? // Ask whether to really return bike?
@ -168,7 +167,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Close lock // Close lock
@ -255,7 +254,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Check locking state. // Check locking state.
@ -307,12 +306,12 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Get geolocation information. // Get geolocation information.
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation; BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation;
Location currentLocation = null; IGeolocation currentLocation = null;
try try
{ {
var task = await Task.WhenAny(new List<Task> { currentLocationTask }); var task = await Task.WhenAny(new List<Task> { currentLocationTask });
@ -335,7 +334,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Notify COPRI about end of rental: "request=booking_update ... "&state=available" ... &lock_state=locked ..." // Notify COPRI about end of rental: "request=booking_update ... "&state=available" ... &lock_state=locked ..."
@ -428,7 +427,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
Log.ForContext<BookedOpen>().Information("User returned bike {bike} successfully.", SelectedBike); Log.ForContext<BookedOpen>().Information("User returned bike {bike} successfully.", SelectedBike);
@ -488,7 +487,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
#endif #endif
@ -501,7 +500,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
/// <summary> Close lock in order to pause ride and update COPRI lock state.</summary> /// <summary> Close lock in order to pause ride and update COPRI lock state.</summary>
@ -518,11 +517,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Start getting geolocation. // Start getting geolocation.
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart; BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart;
var ctsLocation = new CancellationTokenSource(); var ctsLocation = new CancellationTokenSource();
Task<Location> currentLocationTask = null; Task<IGeolocation> currentLocationTask = null;
var timeStamp = DateTime.Now; var timeStamp = DateTime.Now;
try try
{ {
currentLocationTask = Geolocation.GetAsync(ctsLocation.Token, timeStamp); currentLocationTask = GeolocationService.GetAsync(ctsLocation.Token, timeStamp);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -606,12 +605,12 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Get geoposition. // Get geoposition.
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation; BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation;
Location currentLocation = null; IGeolocation currentLocation = null;
try try
{ {
await Task.WhenAny(new List<Task> { currentLocationTask }); await Task.WhenAny(new List<Task> { currentLocationTask });
@ -625,6 +624,9 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = AppResources.ActivityTextErrorQueryLocationWhenAny; BikesViewModel.ActionText = AppResources.ActivityTextErrorQueryLocationWhenAny;
} }
// Keep geolocation where closing action occurred.
SelectedBike.LockInfo.Location = currentLocation;
// Lock list to avoid multiple taps while copri action is pending. // Lock list to avoid multiple taps while copri action is pending.
BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState; BikesViewModel.ActionText = AppResources.ActivityTextStartingUpdatingLockingState;
@ -673,7 +675,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
} }
} }

View file

@ -26,7 +26,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IBikeInfoMutable selectedBike, IBikeInfoMutable selectedBike,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice, ISmartDevice smartDevice,
@ -136,7 +136,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
@ -206,7 +206,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
/// <summary> Close lock in order to pause ride and update COPRI lock state.</summary> /// <summary> Close lock in order to pause ride and update COPRI lock state.</summary>
@ -220,11 +220,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Start getting geolocation. // Start getting geolocation.
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart; BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart;
var ctsLocation = new CancellationTokenSource(); var ctsLocation = new CancellationTokenSource();
Task<Location> currentLocationTask = null; Task<IGeolocation> currentLocationTask = null;
var timeStamp = DateTime.Now; var timeStamp = DateTime.Now;
try try
{ {
currentLocationTask = Geolocation.GetAsync(ctsLocation.Token, timeStamp); currentLocationTask = GeolocationService.GetAsync(ctsLocation.Token, timeStamp);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -307,12 +307,12 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Get geoposition. // Get geoposition.
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation; BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation;
Location currentLocation = null; IGeolocation currentLocation = null;
try try
{ {
await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask }); await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask });
@ -374,7 +374,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
} }
} }

View file

@ -25,7 +25,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IBikeInfoMutable selectedBike, IBikeInfoMutable selectedBike,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice, ISmartDevice smartDevice,
@ -160,7 +160,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
SelectedBike.LockInfo.State = result?.State?.GetLockingState() ?? LockingState.UnknownDisconnected; SelectedBike.LockInfo.State = result?.State?.GetLockingState() ?? LockingState.UnknownDisconnected;
@ -174,7 +174,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
SelectedBike.LockInfo.Guid = result?.Guid ?? new Guid(); SelectedBike.LockInfo.Guid = result?.Guid ?? new Guid();
@ -212,7 +212,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
Log.ForContext<DisposableDisconnected>().Information("User selected recently requested bike {bike} in order to book.", SelectedBike); Log.ForContext<DisposableDisconnected>().Information("User selected recently requested bike {bike} in order to book.", SelectedBike);
@ -254,7 +254,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Unlock bike. // Unlock bike.
@ -323,7 +323,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
if (SelectedBike.LockInfo.State != LockingState.Open) if (SelectedBike.LockInfo.State != LockingState.Open)
@ -334,7 +334,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
@ -404,7 +404,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
/// <summary> Requst is not supported, button should be disabled. </summary> /// <summary> Requst is not supported, button should be disabled. </summary>

View file

@ -37,7 +37,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IBikeInfoMutable selectedBike, IBikeInfoMutable selectedBike,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice, ISmartDevice smartDevice,
@ -142,7 +142,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Disconnect lock. // Disconnect lock.
@ -162,7 +162,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Lock list to avoid multiple taps while copri action is pending. // Lock list to avoid multiple taps while copri action is pending.
@ -255,7 +255,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Update status text and unlock list of bikes because no more action is pending. // Update status text and unlock list of bikes because no more action is pending.
BikesViewModel.ActionText = string.Empty; // Todo: Move this statement in front of finally block because in catch block BikesViewModel.ActionText is already set to empty. BikesViewModel.ActionText = string.Empty; // Todo: Move this statement in front of finally block because in catch block BikesViewModel.ActionText is already set to empty.
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
Log.ForContext<DisposableOpen>().Information("User reserved bike {bike} successfully.", SelectedBike); Log.ForContext<DisposableOpen>().Information("User reserved bike {bike} successfully.", SelectedBike);
@ -267,7 +267,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Update status text and unlock list of bikes because no more action is pending. // Update status text and unlock list of bikes because no more action is pending.
BikesViewModel.ActionText = string.Empty; // Todo: Move this statement in front of finally block because in catch block BikesViewModel.ActionText is already set to empty. BikesViewModel.ActionText = string.Empty; // Todo: Move this statement in front of finally block because in catch block BikesViewModel.ActionText is already set to empty.
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
/// <summary> Requst is not supported, button should be disabled. </summary> /// <summary> Requst is not supported, button should be disabled. </summary>

View file

@ -30,7 +30,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IBikeInfoMutable selectedBike, IBikeInfoMutable selectedBike,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice, ISmartDevice smartDevice,
@ -131,7 +131,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
Log.ForContext<BikesViewModel>().Information("User canceled reservation of bike {l_oId} successfully.", SelectedBike.Id); Log.ForContext<BikesViewModel>().Information("User canceled reservation of bike {l_oId} successfully.", SelectedBike.Id);
@ -153,7 +153,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
/// <summary> Open lock and book bike. </summary> /// <summary> Open lock and book bike. </summary>
@ -219,7 +219,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Unlock bike. // Unlock bike.
@ -288,7 +288,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
if (SelectedBike.LockInfo.State != LockingState.Open) if (SelectedBike.LockInfo.State != LockingState.Open)
@ -299,7 +299,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
@ -369,7 +369,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
} }
} }

View file

@ -24,7 +24,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IBikeInfoMutable selectedBike, IBikeInfoMutable selectedBike,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice, ISmartDevice smartDevice,
@ -124,7 +124,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
Log.ForContext<ReservedDisconnected>().Information("User canceled reservation of bike {l_oId} successfully.", SelectedBike.Id); Log.ForContext<ReservedDisconnected>().Information("User canceled reservation of bike {l_oId} successfully.", SelectedBike.Id);
@ -133,7 +133,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
/// <summary> Connect to reserved bike ask whether to book bike bike or not and if yes open lock. </summary> /// <summary> Connect to reserved bike ask whether to book bike bike or not and if yes open lock. </summary>
@ -340,7 +340,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
Log.ForContext<ReservedDisconnected>().Information("User selected recently requested bike {bike} in order to book.", SelectedBike); Log.ForContext<ReservedDisconnected>().Information("User selected recently requested bike {bike} in order to book.", SelectedBike);
@ -382,7 +382,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Unlock bike. // Unlock bike.
@ -451,7 +451,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
if (SelectedBike.LockInfo.State != LockingState.Open) if (SelectedBike.LockInfo.State != LockingState.Open)
@ -462,7 +462,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
@ -534,7 +534,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
} }
} }

View file

@ -29,7 +29,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IBikeInfoMutable selectedBike, IBikeInfoMutable selectedBike,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice, ISmartDevice smartDevice,
@ -152,7 +152,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
Log.ForContext<ReservedOpen>().Information("User booked bike {bike} successfully.", SelectedBike); Log.ForContext<ReservedOpen>().Information("User booked bike {bike} successfully.", SelectedBike);
@ -162,7 +162,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Close lock and cancel reservation. // Close lock and cancel reservation.
@ -220,7 +220,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
BikesViewModel.ActionText = AppResources.ActivityTextCancelingReservation; BikesViewModel.ActionText = AppResources.ActivityTextCancelingReservation;
@ -268,7 +268,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
Log.ForContext<ReservedOpen>().Information("User canceled reservation of bike {l_oId} successfully.", SelectedBike.Id); Log.ForContext<ReservedOpen>().Information("User canceled reservation of bike {l_oId} successfully.", SelectedBike.Id);
@ -290,7 +290,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again. await ViewUpdateManager().StartUpdateAyncPeridically(); // Restart polling again.
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; // Unlock GUI BikesViewModel.IsIdle = true; // Unlock GUI
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
/// <summary> Manage sound/ alarm settings. </summary> /// <summary> Manage sound/ alarm settings. </summary>
@ -364,7 +364,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
exception.Message, exception.Message,
"OK"); "OK");
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Switch off alarm. // Switch off alarm.
@ -395,7 +395,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
exception.Message, exception.Message,
"OK"); "OK");
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
finally finally
{ {

View file

@ -26,7 +26,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
IBikeInfoMutable selectedBike, IBikeInfoMutable selectedBike,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice, ISmartDevice smartDevice,
@ -132,7 +132,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel; BikesViewModel.ActionText = AppResources.ActivityTextReadingChargingLevel;
@ -202,7 +202,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
/// <summary> Close lock in order to pause ride and update COPRI lock state.</summary> /// <summary> Close lock in order to pause ride and update COPRI lock state.</summary>
@ -220,11 +220,11 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
// Start getting geolocation. // Start getting geolocation.
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart; BikesViewModel.ActionText = AppResources.ActivityTextQueryLocationStart;
var ctsLocation = new CancellationTokenSource(); var ctsLocation = new CancellationTokenSource();
Task<Location> currentLocationTask = null; Task<IGeolocation> currentLocationTask = null;
var timeStamp = DateTime.Now; var timeStamp = DateTime.Now;
try try
{ {
currentLocationTask = Geolocation.GetAsync(ctsLocation.Token, timeStamp); currentLocationTask = GeolocationService.GetAsync(ctsLocation.Token, timeStamp);
} }
catch (Exception ex) catch (Exception ex)
{ {
@ -307,12 +307,12 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
// Get geoposition. // Get geoposition.
BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation; BikesViewModel.ActionText = AppResources.ActivityTextQueryLocation;
Location currentLocation = null; IGeolocation currentLocation = null;
try try
{ {
await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask }); await Task.WhenAny(new List<Task> { currentLocationTask ?? Task.CompletedTask });
@ -374,7 +374,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock.RequestHandler
await ViewUpdateManager().StartUpdateAyncPeridically(); await ViewUpdateManager().StartUpdateAyncPeridically();
BikesViewModel.ActionText = string.Empty; BikesViewModel.ActionText = string.Empty;
BikesViewModel.IsIdle = true; BikesViewModel.IsIdle = true;
return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, Geolocation, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser); return RequestHandlerFactory.Create(SelectedBike, IsConnectedDelegate, ConnectorFactory, GeolocationService, LockService, ViewUpdateManager, SmartDevice, ViewService, BikesViewModel, ActiveUser);
} }
} }
} }

View file

@ -1,4 +1,4 @@
using System; using System;
using Serilog; using Serilog;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Model.Connector; using TINK.Model.Connector;
@ -18,7 +18,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
/// <param name="selectedBike"></param> /// <param name="selectedBike"></param>
/// <param name="isConnectedDelegate"></param> /// <param name="isConnectedDelegate"></param>
/// <param name="connectorFactory"></param> /// <param name="connectorFactory"></param>
/// <param name="bikeRemoveDelegate"></param> /// <param name="geolocation"></param>
/// <param name="viewUpdateManager"></param> /// <param name="viewUpdateManager"></param>
/// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param> /// <param name="smartDevice">Provides info about the smart device (phone, tablet, ...)</param>
/// <param name="viewService"></param> /// <param name="viewService"></param>
@ -28,7 +28,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
Model.Bikes.BikeInfoNS.BC.IBikeInfoMutable selectedBike, Model.Bikes.BikeInfoNS.BC.IBikeInfoMutable selectedBike,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
Func<IPollingUpdateTaskManager> viewUpdateManager, Func<IPollingUpdateTaskManager> viewUpdateManager,
ISmartDevice smartDevice, ISmartDevice smartDevice,
@ -36,7 +36,7 @@ namespace TINK.ViewModel.Bikes.Bike.BluetoothLock
IBikesViewModel bikesViewModel, IBikesViewModel bikesViewModel,
IUser activeUser) IUser activeUser)
{ {
if (!(selectedBike is Model.Bikes.BikeInfoNS.BluetoothLock.IBikeInfoMutable selectedBluetoothLockBike)) if (!(selectedBike is IBikeInfoMutable selectedBluetoothLockBike))
return null; return null;
switch (selectedBluetoothLockBike.State.Value) switch (selectedBluetoothLockBike.State.Value)

View file

@ -36,7 +36,7 @@ namespace TINK.ViewModel.Bikes
/// <summary> Provides a connector object.</summary> /// <summary> Provides a connector object.</summary>
protected Func<bool, IConnector> ConnectorFactory { get; } protected Func<bool, IConnector> ConnectorFactory { get; }
protected IGeolocation Geolocation { get; } protected IGeolocationService GeolocationService { get; }
/// <summary> Provides a connector object.</summary> /// <summary> Provides a connector object.</summary>
protected ILocksService LockService { get; } protected ILocksService LockService { get; }
@ -99,7 +99,7 @@ namespace TINK.ViewModel.Bikes
string runtimPlatform, string runtimPlatform,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
TINK.Settings.PollingParameters polling, TINK.Settings.PollingParameters polling,
Action<SendOrPostCallback, object> postAction, Action<SendOrPostCallback, object> postAction,
@ -123,7 +123,7 @@ namespace TINK.ViewModel.Bikes
ConnectorFactory = connectorFactory ConnectorFactory = connectorFactory
?? throw new ArgumentException("Can not instantiate bikes page view model- object. No connector available."); ?? throw new ArgumentException("Can not instantiate bikes page view model- object. No connector available.");
Geolocation = geolocation GeolocationService = geolocation
?? throw new ArgumentException("Can not instantiate bikes page view model- object. No geolocation object available."); ?? throw new ArgumentException("Can not instantiate bikes page view model- object. No geolocation object available.");
LockService = lockService LockService = lockService
@ -182,7 +182,7 @@ namespace TINK.ViewModel.Bikes
var bikeViewModel = BikeViewModelFactory.Create( var bikeViewModel = BikeViewModelFactory.Create(
IsConnectedDelegate, IsConnectedDelegate,
ConnectorFactory, ConnectorFactory,
Geolocation, GeolocationService,
LockService, LockService,
(id) => Remove(id), (id) => Remove(id),
() => m_oViewUpdateManager, () => m_oViewUpdateManager,

View file

@ -79,7 +79,7 @@ namespace TINK.ViewModel.BikesAtStation
IStation selectedStation, IStation selectedStation,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
PollingParameters polling, PollingParameters polling,
Action<string> openUrlInExternalBrowser, Action<string> openUrlInExternalBrowser,
@ -306,7 +306,7 @@ namespace TINK.ViewModel.BikesAtStation
} }
} }
if (Geolocation.IsGeolcationEnabled == false) if (GeolocationService.IsGeolcationEnabled == false)
{ {
await ViewService.DisplayAlert( await ViewService.DisplayAlert(
AppResources.MessageTitleHint, AppResources.MessageTitleHint,

View file

@ -22,7 +22,6 @@ using TINK.MultilingualResources;
using TINK.Repository; using TINK.Repository;
using TINK.Services.Geolocation; using TINK.Services.Geolocation;
using TINK.Model.State; using TINK.Model.State;
using TINK.ViewModel.Map;
namespace TINK.ViewModel.Contact namespace TINK.ViewModel.Contact
{ {
@ -86,7 +85,7 @@ namespace TINK.ViewModel.Contact
/// <summary> False if user tabed on station marker to show bikes at a given station.</summary> /// <summary> False if user tabed on station marker to show bikes at a given station.</summary>
private bool isMapPageEnabled = false; private bool isMapPageEnabled = false;
IGeolocation GeolocationService { get; } IGeolocationService GeolocationService { get; }
/// <summary> False if user tabed on station marker to show bikes at a given station.</summary> /// <summary> False if user tabed on station marker to show bikes at a given station.</summary>
public bool IsMapPageEnabled public bool IsMapPageEnabled
@ -111,7 +110,7 @@ namespace TINK.ViewModel.Contact
ITinkApp tinkApp, ITinkApp tinkApp,
ILocationPermission permissionsService, ILocationPermission permissionsService,
Plugin.BLE.Abstractions.Contracts.IBluetoothLE bluetoothService, Plugin.BLE.Abstractions.Contracts.IBluetoothLE bluetoothService,
IGeolocation geolocationService, IGeolocationService geolocationService,
Action<MapSpan> moveToRegionDelegate, Action<MapSpan> moveToRegionDelegate,
IViewService viewService, IViewService viewService,
INavigation navigation) INavigation navigation)
@ -162,7 +161,7 @@ namespace TINK.ViewModel.Contact
/// <summary> /// <summary>
/// One time setup: Sets pins into map and connects to events. /// One time setup: Sets pins into map and connects to events.
/// </summary> /// </summary>
private async void InitializePins(StationDictionary stations) private void InitializePins(StationDictionary stations)
{ {
// Add pins to stations. // Add pins to stations.
Log.ForContext<SelectStationPageViewModel>().Debug($"Request to draw {stations.Count} pins."); Log.ForContext<SelectStationPageViewModel>().Debug($"Request to draw {stations.Count} pins.");
@ -309,7 +308,7 @@ namespace TINK.ViewModel.Contact
{ {
ActionText = AppResources.ActivityTextCenterMap; ActionText = AppResources.ActivityTextCenterMap;
Location currentLocation = null; IGeolocation currentLocation = null;
try try
{ {
currentLocation = TinkApp.CenterMapToCurrentLocation currentLocation = TinkApp.CenterMapToCurrentLocation
@ -428,7 +427,7 @@ namespace TINK.ViewModel.Contact
public static void MoveAndScale( public static void MoveAndScale(
Action<MapSpan> moveToRegionDelegate, Action<MapSpan> moveToRegionDelegate,
Uri activeUri, Uri activeUri,
Location currentLocation = null) IGeolocation currentLocation = null)
{ {
if (currentLocation != null) if (currentLocation != null)
{ {

View file

@ -124,7 +124,7 @@ namespace TINK.ViewModel.FindBike
string runtimPlatform, string runtimPlatform,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
IEnumerable<IStation> stations, IEnumerable<IStation> stations,
PollingParameters polling, PollingParameters polling,
@ -331,7 +331,7 @@ namespace TINK.ViewModel.FindBike
} }
// Location state // Location state
if (Geolocation.IsGeolcationEnabled == false) if (GeolocationService.IsGeolcationEnabled == false)
{ {
await ViewService.DisplayAlert( await ViewService.DisplayAlert(
AppResources.MessageTitleHint, AppResources.MessageTitleHint,

View file

@ -27,13 +27,6 @@ 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;
#if !TRYNOTBACKSTYLE #if !TRYNOTBACKSTYLE
#endif #endif
@ -63,8 +56,6 @@ namespace TINK.ViewModel.Map
/// </summary> /// </summary>
private ILocationPermission PermissionsService { get; } private ILocationPermission PermissionsService { get; }
private IGeolocation Geolocation { get; }
/// <summary> /// <summary>
/// Service to manage bluetooth stack. /// Service to manage bluetooth stack.
/// </summary> /// </summary>
@ -110,7 +101,7 @@ namespace TINK.ViewModel.Map
/// <summary> False if user tabed on station marker to show bikes at a given station.</summary> /// <summary> False if user tabed on station marker to show bikes at a given station.</summary>
private bool isMapPageEnabled = false; private bool isMapPageEnabled = false;
IGeolocation GeolocationService { get; } IGeolocationService GeolocationService { get; }
/// <summary> False if user tabed on station marker to show bikes at a given station.</summary> /// <summary> False if user tabed on station marker to show bikes at a given station.</summary>
public bool IsMapPageEnabled public bool IsMapPageEnabled
@ -135,7 +126,7 @@ namespace TINK.ViewModel.Map
ITinkApp tinkApp, ITinkApp tinkApp,
ILocationPermission permissionsService, ILocationPermission permissionsService,
Plugin.BLE.Abstractions.Contracts.IBluetoothLE bluetoothService, Plugin.BLE.Abstractions.Contracts.IBluetoothLE bluetoothService,
IGeolocation geolocationService, IGeolocationService geolocationService,
Action<MapSpan> moveToRegionDelegate, Action<MapSpan> moveToRegionDelegate,
IViewService viewService, IViewService viewService,
INavigation navigation) INavigation navigation)
@ -197,6 +188,27 @@ namespace TINK.ViewModel.Map
set { m_oNavigationMasterDetail = value; } set { m_oNavigationMasterDetail = value; }
} }
#endif #endif
/// <summary>
/// Counts the number of reserved or occupied bikes -> visualized in MyBikes-Icon
/// </summary>
public void GetMyBikesCount(BikeCollection bikesAll)
{
int MyBikesCount = 0;
Log.ForContext<MapPageViewModel>().Debug($"Number of reserved or rented bikes is extracted.");
if (bikesAll != null)
{
foreach (var bike in bikesAll)
{
if (bike.State.Value.IsOccupied())
{
MyBikesCount = MyBikesCount + 1;
continue;
}
}
}
MyBikesCountText = MyBikesCount > 0 ? string.Format(MyBikesCount.ToString()) : string.Empty;
}
public Command<PinClickedEventArgs> PinClickedCommand => new Command<PinClickedEventArgs>( public Command<PinClickedEventArgs> PinClickedCommand => new Command<PinClickedEventArgs>(
args => args =>
@ -243,7 +255,6 @@ 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++)
{ {
@ -253,11 +264,6 @@ namespace TINK.ViewModel.Map
: "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
{ {
@ -273,8 +279,6 @@ namespace TINK.ViewModel.Map
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++)
{ {
@ -343,6 +347,10 @@ namespace TINK.ViewModel.Map
IsProcessWithRunningProcessView = true; IsProcessWithRunningProcessView = true;
IsNavBarVisible = false; IsNavBarVisible = false;
// Get and expose status of location permission
GetLocationPermissionStatus();
// Process map page. // Process map page.
Polling = TinkApp.Polling; Polling = TinkApp.Polling;
@ -350,7 +358,7 @@ namespace TINK.ViewModel.Map
$"{(Polling != null && Polling.IsActivated ? $"Map page is appearing. Update periode is {Polling.Periode.TotalSeconds} sec." : "Map page is appearing. Polling is off.")}" + $"{(Polling != null && Polling.IsActivated ? $"Map page is appearing. Update periode is {Polling.Periode.TotalSeconds} sec." : "Map page is appearing. Polling is off.")}" +
$"Current UI language is {Thread.CurrentThread.CurrentUICulture.Name}."); $"Current UI language is {Thread.CurrentThread.CurrentUICulture.Name}.");
// Update map page filter // Update map page filter
ActiveFilterMap = TinkApp.GroupFilterMapPage; ActiveFilterMap = TinkApp.GroupFilterMapPage;
ActionText = AppResources.ActivityTextMapLoadingStationsAndBikes; ActionText = AppResources.ActivityTextMapLoadingStationsAndBikes;
@ -393,6 +401,9 @@ namespace TINK.ViewModel.Map
Log.ForContext<MapPageViewModel>().Verbose("Update pins color done."); Log.ForContext<MapPageViewModel>().Verbose("Update pins color done.");
// Load MyBikes Count -> MyBikes Icon/Button
GetMyBikesCount(resultStationsAndBikes.Response.Bikes);
// Move and scale before getting stations and bikes which takes some time. // Move and scale before getting stations and bikes which takes some time.
ActionText = AppResources.ActivityTextCenterMap; ActionText = AppResources.ActivityTextCenterMap;
@ -460,6 +471,22 @@ namespace TINK.ViewModel.Map
} }
} }
/// <summary>
/// IsLocationPermissionGranted = true, if Location Permissions granted.
/// </summary>
private async void GetLocationPermissionStatus()
{
Log.ForContext<MapPageViewModel>().Verbose("Check Location permissions.");
var status = await PermissionsService.CheckStatusAsync();
IsLocationPermissionGranted = status == Status.Granted ? true : false;
Log.ForContext<MapPageViewModel>().Verbose("Location permissions: {0}.", status);
}
/// <summary>
/// Exposes IsLocationPermissionGranted.
/// </summary>
public bool IsLocationPermissionGranted{ get; set;}
/// <summary> /// <summary>
/// Invoked when the auth cookie is not defined. /// Invoked when the auth cookie is not defined.
/// </summary> /// </summary>
@ -536,7 +563,7 @@ namespace TINK.ViewModel.Map
/// </summary> /// </summary>
private async Task<Model.Map.IMapSpan> GetFromLocationService(Status status) private async Task<Model.Map.IMapSpan> GetFromLocationService(Status status)
{ {
Location currentLocation = null; IGeolocation currentLocation = null;
try try
{ {
currentLocation = await GeolocationService.GetAsync(); currentLocation = await GeolocationService.GetAsync();
@ -627,6 +654,9 @@ namespace TINK.ViewModel.Map
Log.ForContext<MapPageViewModel>().Error("Getting bikes and stations in polling context failed with exception {Exception}.", exception); Log.ForContext<MapPageViewModel>().Error("Getting bikes and stations in polling context failed with exception {Exception}.", exception);
} }
// Load MyBikes Count -> MyBikes Icon/Button
GetMyBikesCount(resultStationsAndBikes.Response.Bikes);
// Check if there are alreay any pins to the map. // Check if there are alreay any pins to the map.
// If no initialze pins. // If no initialze pins.
if (Pins.Count <= 0) if (Pins.Count <= 0)

View file

@ -76,7 +76,7 @@ namespace TINK.ViewModel.MyBikes
string runtimPlatform, string runtimPlatform,
Func<bool> isConnectedDelegate, Func<bool> isConnectedDelegate,
Func<bool, IConnector> connectorFactory, Func<bool, IConnector> connectorFactory,
IGeolocation geolocation, IGeolocationService geolocation,
ILocksService lockService, ILocksService lockService,
IEnumerable<IStation> stations, IEnumerable<IStation> stations,
PollingParameters p_oPolling, PollingParameters p_oPolling,
@ -194,7 +194,7 @@ namespace TINK.ViewModel.MyBikes
} }
// Location state // Location state
if (Geolocation.IsGeolcationEnabled == false) if (GeolocationService.IsGeolcationEnabled == false)
{ {
await ViewService.DisplayAlert( await ViewService.DisplayAlert(
AppResources.MessageTitleHint, AppResources.MessageTitleHint,

View file

@ -65,7 +65,7 @@ namespace TINK.ViewModel
/// <summary> Reference on the tink app instance. </summary> /// <summary> Reference on the tink app instance. </summary>
private ITinkApp TinkApp { get; } private ITinkApp TinkApp { get; }
IServicesContainer<IGeolocation> GeoloctionServicesContainer { get; } IServicesContainer<IGeolocationService> GeoloctionServicesContainer { get; }
/// <summary> Constructs a settings page view model object.</summary> /// <summary> Constructs a settings page view model object.</summary>
/// <param name="tinkApp"> Reference to tink app model.</param> /// <param name="tinkApp"> Reference to tink app model.</param>
@ -73,7 +73,7 @@ namespace TINK.ViewModel
/// <param name="viewService">Interface to view</param> /// <param name="viewService">Interface to view</param>
public SettingsPageViewModel( public SettingsPageViewModel(
ITinkApp tinkApp, ITinkApp tinkApp,
IServicesContainer<IGeolocation> geoloctionServicesContainer, IServicesContainer<IGeolocationService> geoloctionServicesContainer,
IViewService viewService) IViewService viewService)
{ {
TinkApp = tinkApp TinkApp = tinkApp

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using TINK.Services.Geolocation; using TINK.Services.Geolocation;
@ -6,10 +6,10 @@ using Xamarin.Essentials;
namespace TestFramework.Model.Services.Geolocation namespace TestFramework.Model.Services.Geolocation
{ {
public class GeolocationMock : IGeolocation public class GeolocationMock : IGeolocationService
{ {
public Task<Location> GetAsync(CancellationToken? cancelToken = null, DateTime? timeStamp = null) public Task<IGeolocation> GetAsync(CancellationToken? cancelToken = null, DateTime? timeStamp = null)
{ {
throw new NotImplementedException(); throw new NotImplementedException();
} }

View file

@ -1,10 +1,13 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using NSubstitute; using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using Plugin.BLE.Abstractions.Contracts;
using TINK.Services.BluetoothLock; using TINK.Services.BluetoothLock;
using TINK.Services.BluetoothLock.BLE; using TINK.Services.BluetoothLock.BLE;
using TINK.Services.BluetoothLock.Exception;
using TINK.Services.BluetoothLock.Tdo; using TINK.Services.BluetoothLock.Tdo;
namespace TestLockItBLE.Services.BluetoothLock.BLE namespace TestLockItBLE.Services.BluetoothLock.BLE
@ -64,5 +67,77 @@ namespace TestLockItBLE.Services.BluetoothLock.BLE
await disconnectedDevice.Received().ReconnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>()); await disconnectedDevice.Received().ReconnectAsync(Arg.Any<LockInfoAuthTdo>(), Arg.Any<TimeSpan>());
} }
[Test]
public void TestConnect_Connected_InvalidArgs()
{
var device = Substitute.For<IDevice>();
var adapter = Substitute.For<IAdapter>();
var cipher = Substitute.For<TINK.Model.Device.ICipher>();
var exception = Assert.Throws<AggregateException>(
() => { var lockIt = LockItEventBased.Authenticate(device, null, adapter, cipher).Result; },
"If connected no auth is requied.");
Assert.That(exception.InnerExceptions.Count > 0);
Assert.That(exception.InnerExceptions[0], Is.InstanceOf<BluetoothDisconnectedException>());
}
[Test]
public void TestConnect_Connected()
{
var device = Substitute.For<IDevice>();
var adapter = Substitute.For<IAdapter>();
var cipher = Substitute.For<TINK.Model.Device.ICipher>();
var auth = Substitute.For<ICharacteristic>();
var lockControl = Substitute.For<IService>();
var authTdo = new LockInfoAuthTdo.Builder
{
Id = 12,
K_seed = new byte[] { (byte)'i', (byte)'V', (byte)'F', (byte)'m', (byte)'u', (byte)'T', (byte)'n', (byte)'K', (byte)'q', (byte)'E', (byte)'Y', (byte)'h', (byte)'m', (byte)'T', (byte)'l', (byte)'e' },
K_u = new byte[16]
}.Build();
device.State.Returns(Plugin.BLE.Abstractions.DeviceState.Connected);
device.GetServiceAsync(Arg.Any<Guid>(), Arg.Any<CancellationToken>()).Returns(Task.FromResult(lockControl));
lockControl.GetCharacteristicAsync(Arg.Any<Guid>()).Returns(Task.FromResult(auth));
auth.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true)); // Write COPRI seed to lock
auth.ReadAsync(Arg.Any<CancellationToken>()).Returns(Task.FromResult(new byte[8])); // Read lock seed
cipher.Decrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[3]);
cipher.Encrypt(Arg.Any<byte[]>(), Arg.Any<byte[]>()).Returns(new byte[16]);
auth.WriteAsync(Arg.Any<byte[]>()).Returns(Task.FromResult(true)); // Write COPRI seed to lock
device.Name.Returns("Origin");
Assert.AreEqual(
"Origin",
LockItEventBased.Authenticate(device, authTdo, adapter, cipher).Result.Name,
"If connected no auth is requied.");
}
[Test]
public void TestAuth()
{
var authTdo = new LockInfoAuthTdo.Builder
{
Id = 12,
K_seed = new byte[] { (byte)'c', (byte)'b', (byte)'z', (byte)'b', (byte)'y', (byte)'I', (byte)'q', (byte)'j', (byte)'v', (byte)'L', (byte)'V', (byte)'I', (byte)'t', (byte)'C', (byte)'B', (byte)'I' },
K_u = new byte[16]
}.Build();
var device = Substitute.For<IDevice>();
var adapter = Substitute.For<IAdapter>();
var cipher = Substitute.For<TINK.Model.Device.ICipher>();
// Use factory to create LockIt-object.
var exception = Assert.Throws<AggregateException>(
() => { var lockIt = LockItEventBased.Authenticate(device, authTdo, adapter, cipher).Result; },
"If connected no auth is requied.");
Assert.That(exception.InnerExceptions.Count > 0);
Assert.That(exception.InnerExceptions[0], Is.InstanceOf<BluetoothDisconnectedException>());
}
} }
} }

View file

@ -12,7 +12,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="NSubstitute" Version="5.0.0" /> <PackageReference Include="NSubstitute" Version="5.0.0" />
<PackageReference Include="NUnit" Version="3.13.3" /> <PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" /> <PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
</ItemGroup> </ItemGroup>

View file

@ -13,7 +13,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="nunit" Version="3.13.3" /> <PackageReference Include="nunit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" /> <PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
</ItemGroup> </ItemGroup>

View file

@ -1,7 +1,8 @@
using System; using System;
using System.Linq; using System.Linq;
using NUnit.Framework; using NUnit.Framework;
using TINK.Model.Bikes.BikeInfoNS.BluetoothLock; using TINK.Model.Bikes.BikeInfoNS.BluetoothLock;
using TINK.Services.Geolocation;
namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
{ {
@ -62,5 +63,60 @@ namespace TestTINKLib.Fixtures.ObjectTests.Bike.BluetoothLock
Assert.IsTrue((new byte[] { 1, 12 }).SequenceEqual(lockInfo.Seed)); Assert.IsTrue((new byte[] { 1, 12 }).SequenceEqual(lockInfo.Seed));
Assert.AreEqual(LockingState.Closed, lockInfo.State); Assert.AreEqual(LockingState.Closed, lockInfo.State);
} }
[Test]
public void TestLastLockingStateChange()
=> Assert.That(
new LockInfoMutable(1, new Guid(), null, null, null, LockingState.Open, () => new DateTime(2023, 03, 13)).LastLockingStateChange,
Is.Null);
[Test]
public void TestLastLockingStateChangeCangeCtor()
{
var lockInfo = new LockInfoMutable(1, new Guid(), null, null, null, LockingState.Open, () => new DateTime(2023, 03, 13));
lockInfo.State = LockingState.Closed;
Assert.That(
lockInfo.LastLockingStateChange,
Is.EqualTo(new DateTime(2023, 03, 13)));
}
[Test]
public void TestLocationCtor()
=> Assert.That(
new LockInfoMutable(1, new Guid(), null, null, null, LockingState.Open, () => new DateTime(2023, 03, 13)).Location,
Is.Null);
[Test]
public void TestLocation()
{
var lockInfo = new LockInfoMutable(1, new Guid(), null, null, null, LockingState.Open, () => new DateTime(2023, 03, 13));
lockInfo.Location = new Geolocation.Builder { Latitude = 47.99, Longitude = 7.78}.Build();
// Veryfy that location is kept because bike might be returned later.
Assert.That(
lockInfo.Location.Latitude,
Is.EqualTo(47.99).Within(0.001));
Assert.That(
lockInfo.Location.Longitude,
Is.EqualTo(7.78).Within(0.001));
}
[Test]
public void TestLocationStateChange()
{
var lockInfo = new LockInfoMutable(1, new Guid(), null, null, null, LockingState.Open, () => new DateTime(2023, 03, 13));
lockInfo.Location = new Geolocation.Builder { Latitude = 47.99, Longitude = 7.78 }.Build();
lockInfo.State = LockingState.Closed;
// Veryfy that location is kept because bike might be returned later.
Assert.That(
lockInfo.Location,
Is.Null);
}
} }
} }

View file

@ -1,7 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using Rhino.Mocks;
using TINK.Model.Connector; using TINK.Model.Connector;
using TINK.Model.Services.CopriApi; using TINK.Model.Services.CopriApi;
using TINK.Repository; using TINK.Repository;
@ -87,15 +87,14 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector.Query
[Test] [Test]
public async Task TestGetStations_StationsFromCache() public async Task TestGetStations_StationsFromCache()
{ {
var server = MockRepository.GenerateMock<ICachedCopriServer>(); var server = Substitute.For<ICachedCopriServer>();
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
server.Stub(x => x.GetStations(Arg<bool>.Matches(fromCache => fromCache == false))).Return(Task.Run(() => new Result<StationsAvailableResponse>(
typeof(CopriCallsMonkeyStore), typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL), JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
new GeneralData(), new GeneralData(),
new System.Exception("Bang when getting stations...")))); new System.Exception("Bang when getting stations..."))));
server.Stub(x => x.GetBikesAvailable(Arg<bool>.Matches(fromCache => fromCache == true))).Return(Task.Run(() => new Result<BikesAvailableResponse>( server.GetBikesAvailable(true).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsMonkeyStore), typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE), JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
new GeneralData()))); new GeneralData())));
@ -111,20 +110,20 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector.Query
[Test] [Test]
public async Task TestGetStations_BikesAvailableFromCache() public async Task TestGetStations_BikesAvailableFromCache()
{ {
var server = MockRepository.GenerateMock<ICachedCopriServer>(); var server = Substitute.For<ICachedCopriServer>();
server.Stub(x => x.GetStations(Arg<bool>.Matches(fromCache => fromCache == false))).Return(Task.Run(() => new Result<StationsAvailableResponse>( server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
typeof(CopriCallsHttps), typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLEMPTY), JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLEMPTY),
new GeneralData()))); new GeneralData())));
server.Stub(x => x.GetBikesAvailable(Arg<bool>.Matches(fromCache => fromCache == false))).Return(Task.Run(() => new Result<BikesAvailableResponse>( server.GetBikesAvailable(false).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsMonkeyStore), typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE), JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
new GeneralData(), new GeneralData(),
new System.Exception("Bang when getting bikes...")))); new System.Exception("Bang when getting bikes..."))));
server.Stub(x => x.GetStations(Arg<bool>.Matches(fromCache => fromCache == true))).Return(Task.Run(() => new Result<StationsAvailableResponse>( server.GetStations(true).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
typeof(CopriCallsMonkeyStore), typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL), JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
new GeneralData()))); new GeneralData())));
@ -141,21 +140,18 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector.Query
[Test] [Test]
public async Task TestGetStations() public async Task TestGetStations()
{ {
var server = MockRepository.GenerateMock<ICachedCopriServer>(); var server = Substitute.For<ICachedCopriServer>();
server.Stub(x => x.GetStations(Arg<bool>.Matches(fromCache => fromCache == false))).Return(Task.Run(() => new Result<StationsAvailableResponse>( server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
typeof(CopriCallsHttps), typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL), JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
new GeneralData()))); new GeneralData())));
server.Stub(x => x.GetBikesAvailable(Arg<bool>.Matches(fromCache => fromCache == false))).Return(Task.Run(() => new Result<BikesAvailableResponse>( server.GetBikesAvailable(false).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsHttps), typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE), JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
new GeneralData()))); new GeneralData())));
server.Stub(x => x.AddToCache(Arg<Result<StationsAvailableResponse>>.Is.Anything));
server.Stub(x => x.AddToCache(Arg<Result<BikesAvailableResponse>>.Is.Anything));
var result = await new CachedQuery(server).GetBikesAndStationsAsync(); var result = await new CachedQuery(server).GetBikesAndStationsAsync();
Assert.AreEqual(3, result.Response.StationsAll.Count); Assert.AreEqual(3, result.Response.StationsAll.Count);
@ -167,15 +163,13 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector.Query
[Test] [Test]
public async Task TestGetBikes() public async Task TestGetBikes()
{ {
var server = MockRepository.GenerateMock<ICachedCopriServer>(); var server = Substitute.For<ICachedCopriServer>();
server.Stub(x => x.GetBikesAvailable()).Return(Task.Run(() => new Result<BikesAvailableResponse>( server.GetBikesAvailable().Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsHttps), typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE), JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
new GeneralData()))); new GeneralData())));
server.Stub(x => x.AddToCache(Arg<Result<BikesAvailableResponse>>.Is.Anything));
var result = await new CachedQuery(server).GetBikesAsync(); var result = await new CachedQuery(server).GetBikesAsync();
Assert.AreEqual(1, result.Response.Count); Assert.AreEqual(1, result.Response.Count);
@ -186,7 +180,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector.Query
[Test] [Test]
public async Task TestGetBikesOccupied() public async Task TestGetBikesOccupied()
{ {
var server = MockRepository.GenerateMock<ICachedCopriServer>(); var server = Substitute.For<ICachedCopriServer>();
var result = await new CachedQuery(server).GetBikesOccupiedAsync(); var result = await new CachedQuery(server).GetBikesOccupiedAsync();

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using NSubstitute; using NSubstitute;
@ -294,5 +294,346 @@ namespace TestShareeLib.Model.Connector
bikesResponse.Response.Count, bikesResponse.Response.Count,
Is.EqualTo(1)); Is.EqualTo(1));
} }
private const string BIKESAVAILABLE = @"{
""copri_version"" : ""4.1.0.0"",
""bikes"" : {},
""response_state"" : ""OK"",
""apiserver"" : ""https://app.tink-konstanz.de"",
""authcookie"" : """",
""response"" : ""bikes_available"",
""bikes"" : {
""2352"" : {
""description"" : ""Cargo Long"",
""state"" : ""available"",
""bike"" : ""1"",
""gps"" : { ""latitude"": ""47.669888"", ""longitude"": ""9.167749"" },
""station"" : ""9""
}
}
}";
private const string BIKESAVAILABLEEMPTY = @"{
""copri_version"" : ""4.1.0.0"",
""bikes"" : {},
""response_state"" : ""OK"",
""apiserver"" : ""https://app.tink-konstanz.de"",
""authcookie"" : """",
""response"" : ""bikes_available"",
""bikes"" : {
}
}";
private const string BIKESOCCUPIED = @"{
""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"",
""debuglevel"" : ""2"",
""user_group"" : [ ""TINK"" ],
""user_id"" : ""javaminister@gmail.com"",
""response"" : ""user_bikes_occupied"",
""response_state"" : ""OK"",
""response_text"" : ""Die Liste der reservierten und gebuchten Fahrräder wurde erfolgreich geladen"",
""apiserver"" : ""https://tinkwwp.copri-bike.de"",
""bikes_occupied"" : {
""89004"" : {
""start_time"" : ""2018-01-27 17:33:00.989464+01"",
""station"" : ""9"",
""unit_price"" : ""2.00"",
""tariff_description"": {
""free_hours"" : ""0.5"",
""name"" : ""TINK Tarif"",
""max_eur_per_day"" : ""9.00""
},
""timeCode"" : ""2061"",
""description"" : ""Cargo Long"",
""bike"" : ""4"",
""total_price"" : ""20.00"",
""state"" : ""requested"",
""real_hours"" : ""66.05"",
""bike_group"" : [ ""TINK"" ],
""now_time"" : ""2018-01-30 11:36:45"",
""request_time"" : ""2018-01-27 17:33:00.989464+01"",
""computed_hours"" : ""10.0""
}
}
}";
private const string STATIONSALL = @"{
""copri_version"" : ""4.1.0.0"",
""stations"" : {
""5"" : {
""station"" : ""5"",
""bike_soll"" : ""0"",
""bike_ist"" : ""7"",
""station_group"" : [ ""TINK"" ],
""gps"" : { ""latitude"": ""47.66756"", ""longitude"": ""9.16477"" },
""state"" : ""available"",
""description"" : """"
},
""13"" : {
""station"" : ""13"",
""bike_soll"" : ""4"",
""bike_ist"" : ""1"",
""station_group"" : [ ""TINK"" ],
""gps"" : { ""latitude"": ""47.657756"", ""longitude"": ""9.176084"" },
""state"" : ""available"",
""description"" : """"
},
""30"" : {
""station"" : ""30"",
""bike_soll"" : ""5"",
""bike_ist"" : ""0"",
""station_group"" : [ ""TINK"", ""Konrad"" ],
""gps"" : { ""latitude"": ""47.657766"", ""longitude"": ""9.176094"" },
""state"" : ""available"",
""description"" : ""Test für Stadtradstation""
}
},
""user_group"" : [ ""Konrad"", ""TINK"" ],
""response_state"" : ""OK"",
""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"",
""debuglevel"" : ""2"",
""response"" : ""stations_all"",
""user_id"" : ""javaminister@gmail.com"",
""apiserver"" : ""https://tinkwwp.copri-bike.de""
}";
private const string STATIONSALLEMPTY = @"{
""copri_version"" : ""4.1.0.0"",
""stations"" : {
},
""user_group"" : [ ""Konrad"", ""TINK"" ],
""response_state"" : ""OK"",
""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"",
""debuglevel"" : ""2"",
""response"" : ""stations_all"",
""user_id"" : ""javaminister@gmail.com"",
""apiserver"" : ""https://tinkwwp.copri-bike.de""
}";
[Test]
public async Task TestGetStations_StationsFromCache()
{
var server = Substitute.For<ICachedCopriServer>();
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
new GeneralData(),
new System.Exception("Bang when getting stations..."))));
server.GetBikesAvailable(true).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
new GeneralData())));
server.GetBikesOccupied(true).Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
new GeneralData())));
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
Assert.AreEqual(3, result.Response.StationsAll.Count);
Assert.AreEqual(2, result.Response.Bikes.Count);
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
Assert.AreEqual("Bang when getting stations...", result.Exception.Message);
}
[Test]
public async Task TestGetStations_BikesAvailableFromCache()
{
var server = Substitute.For<ICachedCopriServer>();
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLEMPTY),
new GeneralData())));
server.GetBikesAvailable(false).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
new GeneralData(),
new System.Exception("Bang when getting bikes..."))));
server.GetBikesOccupied(true).Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
new GeneralData())));
server.GetStations(true).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
new GeneralData())));
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
Assert.AreEqual(3, result.Response.StationsAll.Count);
Assert.AreEqual(2, result.Response.Bikes.Count);
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
Assert.AreEqual("Bang when getting bikes...", result.Exception.Message);
}
[Test]
public async Task TestGetStations_BikesOccupiedFromCache()
{
var server = Substitute.For<ICachedCopriServer>();
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALLEMPTY),
new GeneralData())));
server.GetBikesAvailable(false).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLEEMPTY),
new GeneralData())));
server.GetBikesOccupied(false).Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
new GeneralData(),
new System.Exception("Bang when getting bikes occupied..."))));
server.GetBikesAvailable(true).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
new GeneralData())));
server.GetStations(true).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
new GeneralData())));
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
Assert.AreEqual(3, result.Response.StationsAll.Count);
Assert.AreEqual(2, result.Response.Bikes.Count);
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
Assert.AreEqual("Bang when getting bikes occupied...", result.Exception.Message);
}
[Test]
public async Task TestGetStations()
{
var server = Substitute.For<ICachedCopriServer>();
server.GetStations(false).Returns(Task.Run(() => new Result<StationsAvailableResponse>(
typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL),
new GeneralData())));
server.GetBikesAvailable(false).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
new GeneralData())));
server.GetBikesOccupied(false).Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
new GeneralData())));
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
Assert.AreEqual(3, result.Response.StationsAll.Count);
Assert.AreEqual(2, result.Response.Bikes.Count);
Assert.AreEqual(typeof(CopriCallsHttps), result.Source);
Assert.IsNull(result.Exception);
}
[Test]
public async Task TestGetBikes_BikesAvailableFromCache()
{
var server = Substitute.For<ICachedCopriServer>();
server.GetBikesAvailable().Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
new GeneralData(),
new System.Exception("Bang, bikes avail..."))));
server.GetBikesOccupied(true).Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
new GeneralData())));
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAsync();
Assert.AreEqual(2, result.Response.Count);
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
Assert.AreEqual("Bang, bikes avail...", result.Exception.Message);
}
[Test]
public async Task TestGetBikes_BikesOccupiedFromCache()
{
var server = Substitute.For<ICachedCopriServer>();
server.GetBikesAvailable(false).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLEEMPTY),
new GeneralData())));
server.GetBikesOccupied(false).Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
new GeneralData(),
new System.Exception("Bang, error bikes occupied"))));
server.GetBikesAvailable(true).Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsMonkeyStore),
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
new GeneralData())));
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAsync();
Assert.AreEqual(2, result.Response.Count);
Assert.AreEqual(typeof(CopriCallsMonkeyStore), result.Source);
Assert.AreEqual("Bang, error bikes occupied", result.Exception.Message);
}
[Test]
public async Task TestGetBikes()
{
var server = Substitute.For<ICachedCopriServer>();
server.GetBikesAvailable().Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE),
new GeneralData())));
server.GetBikesOccupied().Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
new GeneralData())));
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAsync();
Assert.AreEqual(2, result.Response.Count);
Assert.AreEqual(typeof(CopriCallsHttps), result.Source);
Assert.IsNull(result.Exception);
}
[Test]
public async Task TestGetBikesOccupied()
{
var server = Substitute.For<ICachedCopriServer>();
server.GetBikesAvailable().Returns(Task.Run(() => new Result<BikesAvailableResponse>(
typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<BikesAvailableResponse>("{}"),
new GeneralData())));
server.GetBikesOccupied().Returns(Task.Run(() => new Result<BikesReservedOccupiedResponse>(
typeof(CopriCallsHttps),
JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED),
new GeneralData())));
var result = await new CachedQueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesOccupiedAsync();
Assert.AreEqual(1, result.Response.Count);
Assert.AreEqual(typeof(CopriCallsHttps), result.Source);
Assert.IsNull(result.Exception);
}
} }
} }

View file

@ -1,8 +1,9 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using NSubstitute;
using NSubstitute.ReceivedExtensions;
using NUnit.Framework; using NUnit.Framework;
using Rhino.Mocks;
using TINK.Model.Connector; using TINK.Model.Connector;
using TINK.Repository; using TINK.Repository;
using TINK.Repository.Exception; using TINK.Repository.Exception;
@ -17,9 +18,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
[Test] [Test]
public void TestDoLogout() public void TestDoLogout()
{ {
var l_oServer = MockRepository.GenerateStub<ICopriServer>(); var l_oServer = Substitute.For<ICopriServer>();
l_oServer.Stub(x => x.DoAuthoutAsync()).Return(Task.Run(() => JsonConvert.DeserializeObject<AuthorizationoutResponse>("{ \"response_state\" : \"OK\", \"authcookie\" : \"1\"}"))); l_oServer.DoAuthoutAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<AuthorizationoutResponse>("{ \"response_state\" : \"OK\", \"authcookie\" : \"1\"}")));
var l_oCmd = new CommandLoggedIn(l_oServer, "MeinKeks", "EMehl", () => DateTime.Now); var l_oCmd = new CommandLoggedIn(l_oServer, "MeinKeks", "EMehl", () => DateTime.Now);
@ -28,7 +29,8 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
l_oCmd.DoLogout().Wait(); l_oCmd.DoLogout().Wait();
l_oServer.AssertWasCalled(x => x.DoAuthoutAsync());
l_oServer.Received().DoAuthoutAsync();
Assert.IsNotNull(l_oEventArgs); Assert.IsNotNull(l_oEventArgs);
} }
@ -36,9 +38,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
[Test] [Test]
public void TestDoLogout_AuthcookieNotDefined() public void TestDoLogout_AuthcookieNotDefined()
{ {
var l_oServer = MockRepository.GenerateStub<ICopriServer>(); var l_oServer = Substitute.For<ICopriServer>();
l_oServer.Stub(x => x.DoAuthoutAsync()).Throw(new AuthcookieNotDefinedException("Testing action", JsonConvert.DeserializeObject<ResponseBase>(@"{ ""response_state"" : ""Some inner error description""}"))); l_oServer.When(x => x.DoAuthoutAsync()).Throw(new AuthcookieNotDefinedException("Testing action", JsonConvert.DeserializeObject<ResponseBase>(@"{ ""response_state"" : ""Some inner error description""}")));
var l_oCmd = new CommandLoggedIn(l_oServer, "MeinKeks", "EMehl", () => DateTime.Now); var l_oCmd = new CommandLoggedIn(l_oServer, "MeinKeks", "EMehl", () => DateTime.Now);
@ -47,7 +49,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
l_oCmd.DoLogout().Wait(); l_oCmd.DoLogout().Wait();
l_oServer.AssertWasCalled(x => x.DoAuthoutAsync()); l_oServer.Received().DoAuthoutAsync();
Assert.IsNotNull(l_oEventArgs); Assert.IsNotNull(l_oEventArgs);
} }
@ -55,9 +57,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
[Test] [Test]
public void TestDoLogout_Exception() public void TestDoLogout_Exception()
{ {
var l_oServer = MockRepository.GenerateStub<ICopriServer>(); var l_oServer = Substitute.For<ICopriServer>();
l_oServer.Stub(x => x.DoAuthoutAsync()).Throw(new System.Exception("Sometheing went wrong.")); l_oServer.When(x => x.DoAuthoutAsync()).Throw(new System.Exception("Sometheing went wrong."));
var l_oCmd = new CommandLoggedIn(l_oServer, "MeinKeks", "EMehl", () => DateTime.Now); var l_oCmd = new CommandLoggedIn(l_oServer, "MeinKeks", "EMehl", () => DateTime.Now);
@ -66,7 +68,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
Assert.Throws<AggregateException>(() => l_oCmd.DoLogout().Wait()); Assert.Throws<AggregateException>(() => l_oCmd.DoLogout().Wait());
l_oServer.AssertWasCalled(x => x.DoAuthoutAsync()); l_oServer.Received().DoAuthoutAsync();
Assert.IsNull(l_oEventArgs); Assert.IsNull(l_oEventArgs);
} }
} }

View file

@ -1,6 +1,6 @@
using System; using System;
using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using Rhino.Mocks;
using TINK.Model.Connector; using TINK.Model.Connector;
using TINK.Model.Services.CopriApi; using TINK.Model.Services.CopriApi;
using TINK.Repository; using TINK.Repository;
@ -16,7 +16,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
[Test] [Test]
public void TestCommandFactory() public void TestCommandFactory()
{ {
var l_oCopri = MockRepository.GenerateStub<ICachedCopriServer>(); var l_oCopri = Substitute.For<ICachedCopriServer>();
// Construct not logged in version of connector. // Construct not logged in version of connector.
var l_oCommand = new TINK.Model.Connector.Connector( var l_oCommand = new TINK.Model.Connector.Connector(
@ -36,7 +36,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
[Test] [Test]
public void TestCommandFactory_LoggedIn() public void TestCommandFactory_LoggedIn()
{ {
var l_oCopri = MockRepository.GenerateStub<ICachedCopriServer>(); var l_oCopri = Substitute.For<ICachedCopriServer>();
var l_oCommand = new TINK.Model.Connector.Connector( var l_oCommand = new TINK.Model.Connector.Connector(
new System.Uri("http://1.2.3.4"), new System.Uri("http://1.2.3.4"),
@ -55,7 +55,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
[Test] [Test]
public void TestQueryFactory_CachedServer() public void TestQueryFactory_CachedServer()
{ {
var l_oCopri = MockRepository.GenerateStub<ICachedCopriServer>(); var l_oCopri = Substitute.For<ICachedCopriServer>();
var l_oQuery = new TINK.Model.Connector.Connector( var l_oQuery = new TINK.Model.Connector.Connector(
new Uri("http://1.2.3.4"), new Uri("http://1.2.3.4"),
@ -74,7 +74,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
[Test] [Test]
public void TestQueryFactory_LoggedIn() public void TestQueryFactory_LoggedIn()
{ {
var l_oCopri = MockRepository.GenerateStub<ICachedCopriServer>(); var l_oCopri = Substitute.For<ICachedCopriServer>();
var l_oQuery = new TINK.Model.Connector.Connector( var l_oQuery = new TINK.Model.Connector.Connector(
new System.Uri("http://1.2.3.4"), new System.Uri("http://1.2.3.4"),

View file

@ -1,6 +1,6 @@
using System; using System;
using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using Rhino.Mocks;
using TINK.Model.Connector; using TINK.Model.Connector;
using TINK.Repository; using TINK.Repository;
@ -15,7 +15,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
[Test] [Test]
public void TestCommandFactory() public void TestCommandFactory()
{ {
var l_oCopri = MockRepository.GenerateStub<ICopriServer>(); var l_oCopri = Substitute.For<ICopriServer>();
// Construct not logged in version of connector. // Construct not logged in version of connector.
var l_oCommand = new ConnectorCache( var l_oCommand = new ConnectorCache(
@ -34,7 +34,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
[Test] [Test]
public void TestCommandFactory_LoggedIn() public void TestCommandFactory_LoggedIn()
{ {
var l_oCopri = MockRepository.GenerateStub<ICopriServer>(); var l_oCopri = Substitute.For<ICopriServer>();
var l_oCommand = new ConnectorCache( var l_oCommand = new ConnectorCache(
new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)),
@ -52,7 +52,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
[Test] [Test]
public void TestQueryFactory_CachedServer() public void TestQueryFactory_CachedServer()
{ {
var l_oCopri = MockRepository.GenerateStub<ICopriServer>(); var l_oCopri = Substitute.For<ICopriServer>();
var l_oQuery = new ConnectorCache( var l_oQuery = new ConnectorCache(
new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)),
@ -70,7 +70,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
[Test] [Test]
public void TestQueryFactory_LoggedIn() public void TestQueryFactory_LoggedIn()
{ {
var l_oCopri = MockRepository.GenerateStub<ICopriServer>(); var l_oCopri = Substitute.For<ICopriServer>();
var l_oQuery = new ConnectorCache( var l_oQuery = new ConnectorCache(
new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)), new AppContextInfo("MyMerchId", "MyApp", new Version(1, 2)),

View file

@ -1,7 +1,7 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using Rhino.Mocks;
using TINK.Repository; using TINK.Repository;
using TINK.Repository.Response; using TINK.Repository.Response;
@ -71,10 +71,10 @@ namespace TestTINKLib.Fixtures.ObjectTests.Query
[Test] [Test]
public async Task TestGetStations() public async Task TestGetStations()
{ {
var server = MockRepository.GenerateMock<ICopriServer>(); var server = Substitute.For<ICopriServer>();
server.Stub(x => x.GetStationsAsync()).Return(Task.Run(() => JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL))); server.GetStationsAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL)));
server.Stub(x => x.GetBikesAvailableAsync()).Return(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE))); server.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE)));
var result = await new TINK.Model.Connector.Query(server).GetBikesAndStationsAsync(); var result = await new TINK.Model.Connector.Query(server).GetBikesAndStationsAsync();
@ -87,9 +87,9 @@ namespace TestTINKLib.Fixtures.ObjectTests.Query
[Test] [Test]
public async Task TestGetBikes() public async Task TestGetBikes()
{ {
var server = MockRepository.GenerateMock<ICopriServer>(); var server = Substitute.For<ICopriServer>();
server.Stub(x => x.GetBikesAvailableAsync()).Return(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE))); server.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE)));
var result = await new TINK.Model.Connector.Query(server).GetBikesAsync(); var result = await new TINK.Model.Connector.Query(server).GetBikesAsync();
@ -101,7 +101,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Query
[Test] [Test]
public async Task TestGetBikesOccupied() public async Task TestGetBikesOccupied()
{ {
var server = MockRepository.GenerateMock<ICopriServer>(); var server = Substitute.For<ICopriServer>();
var result = await new TINK.Model.Connector.Query(server).GetBikesOccupiedAsync(); var result = await new TINK.Model.Connector.Query(server).GetBikesOccupiedAsync();

View file

@ -1,9 +1,8 @@
using System; using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using Newtonsoft.Json; using Newtonsoft.Json;
using NSubstitute; using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using Rhino.Mocks;
using TINK.Model.Connector; using TINK.Model.Connector;
using TINK.Repository; using TINK.Repository;
using TINK.Repository.Response; using TINK.Repository.Response;
@ -108,11 +107,11 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
[Test] [Test]
public async Task TestGetStations() public async Task TestGetStations()
{ {
var server = MockRepository.GenerateMock<ICopriServer>(); var server = Substitute.For<ICopriServer>();
server.Stub(x => x.GetStationsAsync()).Return(Task.Run(() => JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL))); server.GetStationsAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<StationsAvailableResponse>(STATIONSALL)));
server.Stub(x => x.GetBikesAvailableAsync()).Return(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE))); server.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE)));
server.Stub(x => x.GetBikesOccupiedAsync()).Return(Task.Run(() => JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED))); server.GetBikesOccupiedAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED)));
var result = await new QueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync(); var result = await new QueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAndStationsAsync();
@ -125,10 +124,10 @@ namespace TestTINKLib.Fixtures.ObjectTests.Connector
[Test] [Test]
public async Task TestGetBikes() public async Task TestGetBikes()
{ {
var server = MockRepository.GenerateMock<ICopriServer>(); var server = Substitute.For<ICopriServer>();
server.Stub(x => x.GetBikesAvailableAsync()).Return(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE))); server.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesAvailableResponse>(BIKESAVAILABLE)));
server.Stub(x => x.GetBikesOccupiedAsync()).Return(Task.Run(() => JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED))); server.GetBikesOccupiedAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject<BikesReservedOccupiedResponse>(BIKESOCCUPIED)));
var result = await new QueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAsync(); var result = await new QueryLoggedIn(server, "123", "a@b", () => DateTime.Now).GetBikesAsync();

View file

@ -1,7 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using Rhino.Mocks;
using TINK.Model.State; using TINK.Model.State;
@ -28,8 +28,8 @@ namespace TestTINKLib
public void TestConstructCopy() public void TestConstructCopy()
{ {
// State is available. // State is available.
var l_oSource = MockRepository.GenerateStub<IStateInfo>(); var l_oSource = Substitute.For<IStateInfo>();
l_oSource.Stub(x => x.Value).Return(InUseStateEnum.Disposable); l_oSource.Value.Returns(InUseStateEnum.Disposable);
var l_oState = new StateInfoMutable(state: l_oSource); var l_oState = new StateInfoMutable(state: l_oSource);
@ -39,11 +39,11 @@ namespace TestTINKLib
Assert.IsNull(l_oState.Code); Assert.IsNull(l_oState.Code);
// State is requested. // State is requested.
l_oSource = MockRepository.GenerateStub<IStateInfo>(); l_oSource = Substitute.For<IStateInfo>();
l_oSource.Stub(x => x.Value).Return(InUseStateEnum.Reserved); l_oSource.Value.Returns(InUseStateEnum.Reserved);
l_oSource.Stub(x => x.From).Return(new DateTime(2018, 1, 4, 17, 26, 0)); l_oSource.From.Returns(new DateTime(2018, 1, 4, 17, 26, 0));
l_oSource.Stub(x => x.MailAddress).Return("who@the"); l_oSource.MailAddress.Returns("who@the");
l_oSource.Stub(x => x.Code).Return("323"); l_oSource.Code.Returns("323");
l_oState = new StateInfoMutable(() => new DateTime(2018, 1, 4, 17, 30, 1), l_oSource); l_oState = new StateInfoMutable(() => new DateTime(2018, 1, 4, 17, 30, 1), l_oSource);
@ -54,11 +54,11 @@ namespace TestTINKLib
Assert.AreEqual("323", l_oState.Code); Assert.AreEqual("323", l_oState.Code);
// State is booked. // State is booked.
l_oSource = MockRepository.GenerateStub<IStateInfo>(); l_oSource = Substitute.For<IStateInfo>();
l_oSource.Stub(x => x.Value).Return(InUseStateEnum.Booked); l_oSource.Value.Returns(InUseStateEnum.Booked);
l_oSource.Stub(x => x.From).Return(new DateTime(2018, 1, 4, 17, 00, 0)); l_oSource.From.Returns(new DateTime(2018, 1, 4, 17, 00, 0));
l_oSource.Stub(x => x.MailAddress).Return("who@the"); l_oSource.MailAddress.Returns("who@the");
l_oSource.Stub(x => x.Code).Return("323"); l_oSource.Code.Returns("323");
l_oState = new StateInfoMutable(() => new DateTime(2018, 1, 4, 17, 30, 1), l_oSource); l_oState = new StateInfoMutable(() => new DateTime(2018, 1, 4, 17, 30, 1), l_oSource);
@ -185,4 +185,4 @@ namespace TestTINKLib
Assert.IsNull(l_oState.Code); Assert.IsNull(l_oState.Code);
} }
} }
} }

View file

@ -43,7 +43,7 @@ namespace TestShareeLib.UseCases.Login
merchantId: "MyMerchId", merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(), bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: permissions, locationPermissionsService: permissions,
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocation>>(), locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: locksService, // Cipher locksService: locksService, // Cipher
device: device, device: device,
specialFolder: specialFolder, specialFolder: specialFolder,

View file

@ -48,7 +48,7 @@ namespace TestTINKLib.Fixtures.UseCases.Logout
merchantId: "MyMerchId", merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(), bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: permissions, locationPermissionsService: permissions,
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocation>>(), locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: locksService, // Cipher locksService: locksService, // Cipher
device: device, device: device,
specialFolder: specialFolder, specialFolder: specialFolder,

View file

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks;
using NSubstitute; using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using Plugin.BLE.Abstractions.Contracts; using Plugin.BLE.Abstractions.Contracts;
@ -8,8 +9,11 @@ using TestFramework.Model.Services.Geolocation;
using TestFramework.Model.User.Account; using TestFramework.Model.User.Account;
using TestFramework.Services.BluetoothLock; using TestFramework.Services.BluetoothLock;
using TINK.Model; using TINK.Model;
using TINK.Model.Bikes;
using TINK.Model.Connector; using TINK.Model.Connector;
using TINK.Model.Settings; using TINK.Model.Settings;
using TINK.Model.Station;
using TINK.Model.User;
using TINK.Repository; using TINK.Repository;
using TINK.Services; using TINK.Services;
using TINK.Services.Geolocation; using TINK.Services.Geolocation;
@ -23,6 +27,24 @@ namespace TestTINKLib.Fixtures.UseCases.SelectStation
[TestFixture] [TestFixture]
public class TestTinkApp public class TestTinkApp
{ {
/// <summary>
/// Get all bikes at a given station from copri.
/// </summary>
private static async Task<BikeCollectionMutable> GetBikesAtStation(
User user,
TINK.Model.Connector.IConnector connector,
IEnumerable<IStation> stations,
string selectedStationId)
{
var l_oBikesAtStation = new BikeCollectionMutable();
var l_oBikesAvailable = (await connector.Query.GetBikesAsync()).Response;
l_oBikesAtStation.Update(l_oBikesAvailable.GetAtStation(selectedStationId), stations);
return l_oBikesAtStation;
}
[Test] [Test]
public void TestBikesAtStation_AccountStoreMock_NoUser_CopriMock_Set2() public void TestBikesAtStation_AccountStoreMock_NoUser_CopriMock_Set2()
{ {
@ -51,7 +73,7 @@ namespace TestTINKLib.Fixtures.UseCases.SelectStation
merchantId: MERCH_ID, merchantId: MERCH_ID,
bluetoothService: Substitute.For<IBluetoothLE>(), bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(), locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocation>>(), locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: new LocksServiceMock(), // Cipher locksService: new LocksServiceMock(), // Cipher
device: new DeviceMock(), device: new DeviceMock(),
specialFolder: new SpecialFolderMock(), specialFolder: new SpecialFolderMock(),
@ -60,25 +82,25 @@ namespace TestTINKLib.Fixtures.UseCases.SelectStation
currentVersion: new Version(3, 2, 0, 115), currentVersion: new Version(3, 2, 0, 115),
lastVersion: new Version(3, 0, 173)); // Current app version. Must be larger or equal 3.0.173 to lastVersion: new Version(3, 0, 173)); // Current app version. Must be larger or equal 3.0.173 to
Assert.AreEqual(0, TestHelper.GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.Count); Assert.AreEqual(0, GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.Count);
l_oTinkApp.SelectedStation = new TINK.Model.Station.Station("5", new List<string>(), null); l_oTinkApp.SelectedStation = new TINK.Model.Station.Station("5", new List<string>(), null);
Assert.AreEqual(3, TestHelper.GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.Count); Assert.AreEqual(3, GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.Count);
Assert.AreEqual("25", TestHelper.GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.GetById("25").Id); Assert.AreEqual("25", GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.GetById("25").Id);
Assert.AreEqual("11", TestHelper.GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.GetById("11").Id); Assert.AreEqual("11", GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.GetById("11").Id);
Assert.AreEqual("2", TestHelper.GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.GetById("2").Id); Assert.AreEqual("2", GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.GetById("2").Id);
l_oTinkApp.SelectedStation = new TINK.Model.Station.Station("10", new List<string>(), null); l_oTinkApp.SelectedStation = new TINK.Model.Station.Station("10", new List<string>(), null);
Assert.AreEqual( Assert.AreEqual(
1, 1,
TestHelper.GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.Count); GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.Count);
Assert.AreEqual("18", TestHelper.GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.GetById("18").Id); Assert.AreEqual("18", GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.GetById("18").Id);
l_oTinkApp.SelectedStation = new TINK.Model.Station.Station("91345", new List<string>(), null); l_oTinkApp.SelectedStation = new TINK.Model.Station.Station("91345", new List<string>(), null);
Assert.AreEqual(0, TestHelper.GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.Count); Assert.AreEqual(0, GetBikesAtStation(l_oTinkApp.ActiveUser, l_oConnector, l_oTinkApp.Stations, l_oTinkApp.SelectedStation.Id).Result.Count);
} }
} }
} }

View file

@ -1,7 +1,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using Rhino.Mocks;
using TINK.Model.Connector; using TINK.Model.Connector;
using TINK.Model.User.Account; using TINK.Model.User.Account;
@ -14,11 +14,11 @@ namespace TestTINKLib.Fixtures.ObjectTests.User.Account
[Test] [Test]
public void TestDoFilter_NoUserLoggedIn() public void TestDoFilter_NoUserLoggedIn()
{ {
var l_oAccount = MockRepository.GenerateMock<IAccount>(); var l_oAccount = Substitute.For<IAccount>();
l_oAccount.Stub((x) => x.Mail).Return("a@b"); l_oAccount.Mail.Returns("a@b");
l_oAccount.Stub((x) => x.SessionCookie).Return(""); // User is not logged in l_oAccount.SessionCookie.Returns(""); // User is not logged in
l_oAccount.Stub((x) => x.Group).Return(new List<string> { $"HOM_{FilterHelper.CARGOBIKE}", "HOM_117025" }); l_oAccount.Group.Returns(new List<string> { $"HOM_{FilterHelper.CARGOBIKE}", "HOM_117025" });
var l_oSource = new List<string> { $"HOM_{FilterHelper.CARGOBIKE}", $"HOM_{FilterHelper.CITYBIKE}", "HOM_117025" }; var l_oSource = new List<string> { $"HOM_{FilterHelper.CARGOBIKE}", $"HOM_{FilterHelper.CITYBIKE}", "HOM_117025" };
@ -33,11 +33,11 @@ namespace TestTINKLib.Fixtures.ObjectTests.User.Account
[Test] [Test]
public void TestDoFilter() public void TestDoFilter()
{ {
var l_oAccount = MockRepository.GenerateMock<IAccount>(); var l_oAccount = Substitute.For<IAccount>();
l_oAccount.Stub((x) => x.Mail).Return("a@b"); l_oAccount.Mail.Returns("a@b");
l_oAccount.Stub((x) => x.SessionCookie).Return("123"); l_oAccount.SessionCookie.Returns("123");
l_oAccount.Stub((x) => x.Group).Return(new List<string> { $"HOM_{FilterHelper.CARGOBIKE}", "HOM_117025" }); l_oAccount.Group.Returns(new List<string> { $"HOM_{FilterHelper.CARGOBIKE}", "HOM_117025" });
var l_oSource = new List<string> { $"HOM_{FilterHelper.CARGOBIKE}", $"HOM_{FilterHelper.CITYBIKE}", "HOM_117025" }; var l_oSource = new List<string> { $"HOM_{FilterHelper.CARGOBIKE}", $"HOM_{FilterHelper.CITYBIKE}", "HOM_117025" };

View file

@ -26,11 +26,11 @@ namespace TestTINKLib.Fixtures.Connector.Request
Assert.IsNull( Assert.IsNull(
l_oCopri.GetBikesAvailableAsync().Result.bikes.Values.FirstOrDefault(x => x.state != "available"), l_oCopri.GetBikesAvailableAsync().Result.bikes.Values.FirstOrDefault(x => x.state != "available"),
"Bikes available must return bikes which are all of state available."); "Bikes available must end rentals which are all of state available.");
Assert.IsNull( Assert.IsNull(
l_oCopri.GetBikesOccupiedAsync().Result.bikes_occupied.Values.FirstOrDefault(x => x.state == "available"), l_oCopri.GetBikesOccupiedAsync().Result.bikes_occupied.Values.FirstOrDefault(x => x.state == "available"),
"Bikes occupied must return bikes which are either reserved or booked."); "Bikes occupied must end rentals which are either reserved or booked.");
} }
} }
} }

View file

@ -1,4 +1,5 @@
using Newtonsoft.Json; using System.Linq;
using Newtonsoft.Json;
using NUnit.Framework; using NUnit.Framework;
using TINK.Repository; using TINK.Repository;
using TINK.Repository.Response; using TINK.Repository.Response;
@ -82,5 +83,158 @@ namespace TestShareeLib.Repository
() => response.DeserializeResponse<ResponseBase>(version => new System.Exception("Ho")).copri_version, () => response.DeserializeResponse<ResponseBase>(version => new System.Exception("Ho")).copri_version,
Throws.InstanceOf<System.Exception>()); Throws.InstanceOf<System.Exception>());
} }
[Test]
public void TestDeserializeObjectBikesAvailableValidResponse()
{
const string VALID_RESPONSE = @"
{
""shareejson"": {
""authcookie"": 0,
""apiserver"": ""https://tinkwwp.copri-bike.de"",
""response"": ""bikes_available"",
""bikes"": {
""3399"": {
""description"": ""Cargo Trike"",
""bike"": ""26"",
""state"": ""available"",
""gps"" : { ""latitude"": ""47.6586936667"", ""longitude"": ""9.16863116667"" },
""station"" : ""4""
},
},
""response_state"": ""OK"",
""copri_version"" : ""4.1.0.0""
}
}
";
// Ensure that answer holds a valid bike.
var l_oBike = CopriCallsStatic.DeserializeResponse<BikesAvailableResponse>(VALID_RESPONSE).bikes.FirstOrDefault().Value;
Assert.NotNull(l_oBike, "Response must contain at leas one bike.");
Assert.Greater(l_oBike.description.Length, 0, "Bike despcription must never be empty.");
Assert.AreEqual(l_oBike.bike, "26");
Assert.That(
l_oBike.station,
Is.EqualTo("4"),
"Station index must never be negative");
Assert.AreEqual("available", l_oBike.state);
Assert.That(l_oBike.gps, Is.Not.Null, "Gps position must never be empty.");
}
[Test]
public void TestDeserializeObjectBikesAvailableValidResponse_NoDescription()
{
const string INVALID_RESPONSE = @"
{
""shareejson"": {
""authcookie"": 0,
""apiserver"": ""https://tinkwwp.copri-bike.de"",
""response"": ""bikes_available"",
""bikes"": {
""3399"": {
""bike"": 26,
""state"": ""available"",
""gps"" : { ""latitude"": ""47.6586936667"", ""longitude"": ""9.16863116667"" },
""station"" : 4
},
},
""response_state"": ""OK"",
""copri_version"" : ""4.1.0.0"",
}
}
";
// Ensure that answer holds a valid bike.
var l_oBike = CopriCallsStatic.DeserializeResponse<BikesAvailableResponse>(INVALID_RESPONSE).bikes.FirstOrDefault().Value;
Assert.NotNull(l_oBike, "Response must contain at leas one bike.");
Assert.IsNull(l_oBike.description);
Assert.That(l_oBike.bike, Is.Not.Null);
Assert.That(l_oBike.station, Is.Not.Null);
Assert.AreEqual("available", l_oBike.state);
Assert.That(l_oBike.gps, Is.Not.Null, "Gps position must never be empty.");
}
[Test]
public void TestDeserializeObjectBikesAvailableValidResponse_NoBikeId()
{
const string VALID_RESPONSE = @"
{
""shareejson"": {
""authcookie"": 0,
""apiserver"": ""https://tinkwwp.copri-bike.de"",
""response"": ""bikes_available"",
""bikes"": {
""3399"": {
""description"": ""Cargo Trike"",
""state"": ""available"",
""gps"" : { ""latitude"": ""47.6586936667"", ""longitude"": ""9.16863116667"" },
""station"" : ""4""
},
},
""response_state"": ""OK"",
""copri_version"" : ""4.1.0.0"",
}
}";
// Ensure that answer holds a valid bike.
var l_oBike = CopriCallsStatic.DeserializeResponse<BikesAvailableResponse>(VALID_RESPONSE).bikes.FirstOrDefault().Value;
Assert.NotNull(l_oBike, "Response must contain at leas one bike.");
Assert.Greater(l_oBike.description.Length, 0, "Bike despcription must never be empty.");
Assert.That(l_oBike.bike, Is.Null);
Assert.That(l_oBike.station, Is.Not.Null);
Assert.AreEqual("available", l_oBike.state);
Assert.That(l_oBike.gps, Is.Not.Null, "Gps position must never be empty.");
}
[Test]
public void TestDeserializeObjectBikesOccupiedValidResponse()
{
const string VALID_RESPONSE = @"
{
""shareejson"": {
""response_state"": ""OK"",
""bikes_occupied"": {
""87781"": {
""timeCode"": ""3630"",
""state"": ""occupied"",
""station"" : ""5"",
""description"": ""Cargo Long"",
""start_time"": ""2017-11-28 11:01:51.637747+01"",
""bike"": ""8""
},
""87782"": {
""timeCode"": ""2931"",
""state"": ""occupied"",
""station"" : ""4"",
""description"": ""Cargo Long"",
""start_time"": ""2017-11-28 13:06:55.147368+01"",
""bike"": ""7""
}
},
""authcookie"": ""b76b97e43a2d76b8499f32e6dd597af8"",
""response"": ""user_bikes_occupied"",
""apiserver"": ""https://tinkwwp.copri-bike.de"",
""copri_version"" : ""4.1.0.0"",
}
}";
// Ensure that answer holds a valid bike.
var l_oBike = CopriCallsStatic.DeserializeResponse<BikesReservedOccupiedResponse>(VALID_RESPONSE).bikes_occupied.FirstOrDefault().Value;
Assert.NotNull(l_oBike, "Response must contain at leas one bike.");
Assert.Greater(l_oBike.description.Length, 0, "Bike despcription must never be empty.");
Assert.That(l_oBike.bike, Is.Not.Null);
Assert.That(l_oBike.station, Is.Not.Null);
Assert.Greater(l_oBike.state.Length, 0, "State info must never be null or empty.");
// Todo: Requested bikes do not have a gps position. What is about booked bikes?
// Assert.Greater(l_oBike.gps.Length, 0, "Gps position must never be empty.");
Assert.Greater(l_oBike.start_time.Length, 0, "Time when request/ booking was performed must never be null or empty.");
Assert.Greater(l_oBike.timeCode.Length, 0, "Booking code must never be null or empty.");
}
} }
} }

View file

@ -1,4 +1,4 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using NUnit.Framework; using NUnit.Framework;
using TINK.Services; using TINK.Services;
@ -64,5 +64,35 @@ namespace TestShareeLib.Services
private class MyTypeB { } private class MyTypeB { }
private class MyTypeC { } private class MyTypeC { }
[Test]
public void TestCtor2()
{
var container = new ServicesContainerMutableT<object>(new List<object> { new MyTypeA(), new MyTypeB() }, typeof(MyTypeB).FullName);
Assert.That(container.Active.GetType().FullName, Is.EqualTo("TestShareeLib.Services.TestServicesContainerMutable+MyTypeB"));
}
[Test]
public void TestCtorExceptionDupes()
{
Assert.That(() => new ServicesContainerMutableT<object>(new List<object> { new MyTypeA(), new MyTypeB(), new MyTypeA() }, typeof(MyTypeB).FullName), Throws.InstanceOf<Exception>());
}
[Test]
public void TestCtorExceptionActiveNotFound()
{
Assert.That(() => new ServicesContainerMutableT<object>(new List<object> { new MyTypeA(), new MyTypeB() }, "MyTypeF"), Throws.InstanceOf<ArgumentException>());
}
[Test]
public void TestSetActive2()
{
var container = new ServicesContainerMutableT<object>(new List<object> { new MyTypeA(), new MyTypeB() }, typeof(MyTypeB).FullName);
container.SetActive(typeof(MyTypeA).FullName);
Assert.That(container.Active.GetType().FullName, Is.EqualTo("TestShareeLib.Services.TestServicesContainerMutable+MyTypeA"));
}
} }
} }

View file

@ -29,7 +29,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="NSubstitute" Version="5.0.0" /> <PackageReference Include="NSubstitute" Version="5.0.0" />
<PackageReference Include="NUnit" Version="3.13.3" /> <PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" /> <PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
<PackageReference Include="Xamarin.Essentials" Version="1.7.5" /> <PackageReference Include="Xamarin.Essentials" Version="1.7.5" />
</ItemGroup> </ItemGroup>

View file

@ -4,7 +4,6 @@ using System.Threading.Tasks;
using NSubstitute; using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using Plugin.BLE.Abstractions.Contracts; using Plugin.BLE.Abstractions.Contracts;
using Rhino.Mocks;
using TestFramework.Model.Device; using TestFramework.Model.Device;
using TestFramework.Model.Services.Geolocation; using TestFramework.Model.Services.Geolocation;
using TestFramework.Model.User.Account; using TestFramework.Model.User.Account;
@ -51,7 +50,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
merchantId: MERCH_ID, merchantId: MERCH_ID,
bluetoothService: Substitute.For<IBluetoothLE>(), bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(), locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocation>>(), locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: new LocksServiceMock(), // Cipher locksService: new LocksServiceMock(), // Cipher
device: new DeviceMock(), device: new DeviceMock(),
specialFolder: new SpecialFolderMock(), specialFolder: new SpecialFolderMock(),
@ -62,7 +61,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown. whatsNewShownInVersion: null); // Whats new page was never shown.
var viewService = MockRepository.GenerateStub<IViewService>(); var viewService = Substitute.For<IViewService>();
var settingsPageViewModel = new AccountPageViewModel( var settingsPageViewModel = new AccountPageViewModel(
tinkApp, tinkApp,
@ -96,7 +95,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
merchantId: MERCH_ID, merchantId: MERCH_ID,
bluetoothService: Substitute.For<IBluetoothLE>(), bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(), locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocation>>(), locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: new LocksServiceMock(), // Cipher locksService: new LocksServiceMock(), // Cipher
device: new DeviceMock(), device: new DeviceMock(),
specialFolder: new SpecialFolderMock(), specialFolder: new SpecialFolderMock(),
@ -107,7 +106,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown. whatsNewShownInVersion: null); // Whats new page was never shown.
var viewService = MockRepository.GenerateStub<IViewService>(); var viewService = Substitute.For<IViewService>();
var settingsPageViewModel = new AccountPageViewModel( var settingsPageViewModel = new AccountPageViewModel(
tinkApp, tinkApp,
@ -140,7 +139,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
merchantId: "MyMerchId", merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(), bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(), locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocation>>(), locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: new LocksServiceMock(), // Cipher locksService: new LocksServiceMock(), // Cipher
device: new DeviceMock(), device: new DeviceMock(),
specialFolder: new SpecialFolderMock(), specialFolder: new SpecialFolderMock(),
@ -151,7 +150,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown. whatsNewShownInVersion: null); // Whats new page was never shown.
var viewService = MockRepository.GenerateStub<IViewService>(); var viewService = Substitute.For<IViewService>();
var settingsPageViewModel = new AccountPageViewModel( var settingsPageViewModel = new AccountPageViewModel(
tinkApp, tinkApp,
(uri) => { }, (uri) => { },
@ -183,7 +182,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
merchantId: "MyMerchId", merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(), bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(), locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocation>>(), locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: new LocksServiceMock(), // Cipher locksService: new LocksServiceMock(), // Cipher
device: new DeviceMock(), device: new DeviceMock(),
specialFolder: new SpecialFolderMock(), specialFolder: new SpecialFolderMock(),
@ -194,7 +193,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown. whatsNewShownInVersion: null); // Whats new page was never shown.
var viewService = MockRepository.GenerateStub<IViewService>(); var viewService = Substitute.For<IViewService>();
var settingsPageViewModel = new AccountPageViewModel( var settingsPageViewModel = new AccountPageViewModel(
tinkApp, tinkApp,
(uri) => { }, (uri) => { },
@ -239,7 +238,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
merchantId: "MyMerchId", merchantId: "MyMerchId",
bluetoothService: Substitute.For<IBluetoothLE>(), bluetoothService: Substitute.For<IBluetoothLE>(),
locationPermissionsService: Substitute.For<ILocationPermission>(), locationPermissionsService: Substitute.For<ILocationPermission>(),
locationServicesContainer: Substitute.For<IServicesContainer<IGeolocation>>(), locationServicesContainer: Substitute.For<IServicesContainer<IGeolocationService>>(),
locksService: new LocksServiceMock(), // Cipher locksService: new LocksServiceMock(), // Cipher
device: new DeviceMock(), device: new DeviceMock(),
specialFolder: new SpecialFolderMock(), specialFolder: new SpecialFolderMock(),
@ -250,7 +249,7 @@ namespace TestTINKLib.Fixtures.ObjectTests.Account
lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to lastVersion: new Version(3, 0, 173), // Current app version. Must be larger or equal 3.0.173 to
whatsNewShownInVersion: null); // Whats new page was never shown. whatsNewShownInVersion: null); // Whats new page was never shown.
var viewService = MockRepository.GenerateStub<IViewService>(); var viewService = Substitute.For<IViewService>();
var settingsPageViewModel = new AccountPageViewModel( var settingsPageViewModel = new AccountPageViewModel(
tinkApp, tinkApp,
(uri) => { }, (uri) => { },

View file

@ -1,6 +1,6 @@
using System; using System;
using NSubstitute;
using NUnit.Framework; using NUnit.Framework;
using Rhino.Mocks;
using TINK.Model.Device; using TINK.Model.Device;
using TINK.ViewModel; using TINK.ViewModel;
using TINK.ViewModel.Bikes; using TINK.ViewModel.Bikes;
@ -23,12 +23,12 @@ namespace UITest.Fixtures.ViewModel
null, null,
null, null,
null, null,
NSubstitute.Substitute.For<ISmartDevice>(), Substitute.For<ISmartDevice>(),
null, null,
bike, bike,
user, user,
new MyBikeInUseStateInfoProvider(), new MyBikeInUseStateInfoProvider(),
MockRepository.GenerateStub<IBikesViewModel>(), Substitute.For<IBikesViewModel>(),
url => { })); url => { }));
@ -47,12 +47,12 @@ namespace UITest.Fixtures.ViewModel
null, null,
null, null,
null, null,
NSubstitute.Substitute.For<ISmartDevice>(), Substitute.For<ISmartDevice>(),
null, null,
bike, bike,
user, user,
new MyBikeInUseStateInfoProvider(), new MyBikeInUseStateInfoProvider(),
MockRepository.GenerateStub<IBikesViewModel>(), Substitute.For<IBikesViewModel>(),
url => { })); url => { }));
Assert.AreEqual("Code 4asdfA, location Station 3, still 7 min. reserved.", l_oViewModel.StateText); Assert.AreEqual("Code 4asdfA, location Station 3, still 7 min. reserved.", l_oViewModel.StateText);
@ -72,12 +72,12 @@ namespace UITest.Fixtures.ViewModel
null, null,
null, null,
null, null,
NSubstitute.Substitute.For<ISmartDevice>(), Substitute.For<ISmartDevice>(),
null, null,
bike, bike,
user, user,
new MyBikeInUseStateInfoProvider(), new MyBikeInUseStateInfoProvider(),
MockRepository.GenerateStub<IBikesViewModel>(), Substitute.For<IBikesViewModel>(),
url => { })); url => { }));
Assert.AreEqual( Assert.AreEqual(

Some files were not shown because too many files have changed in this diff Show more