mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-06-22 22:07:28 +02:00
Code updated to 3.0.238
This commit is contained in:
parent
3302d80678
commit
9c6a1fa92b
257 changed files with 7763 additions and 2861 deletions
|
@ -17,6 +17,10 @@ using System.Threading;
|
|||
using TINK.Model.Settings;
|
||||
using Plugin.Permissions;
|
||||
using TINK.Services.BluetoothLock.Crypto;
|
||||
using TINK.Model.Services.Geolocation;
|
||||
using TINK.Services;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.Essentials;
|
||||
#if ARENDI
|
||||
using Arendi.BleLibrary.Local;
|
||||
#endif
|
||||
|
@ -45,38 +49,100 @@ namespace TINK
|
|||
// Root model already exists, nothing to do.
|
||||
return m_oModelRoot;
|
||||
}
|
||||
|
||||
|
||||
// Get folder where to read settings from
|
||||
var specialFolders = DependencyService.Get<ISpecialFolder>();
|
||||
var internalPersonalDir = specialFolders.GetInternalPersonalDir();
|
||||
|
||||
// Delete attachtment from previous session.
|
||||
DeleteAttachment(internalPersonalDir);
|
||||
|
||||
// Setup logger using default settings.
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.MinimumLevel.ControlledBy(new LoggingLevelSwitch { MinimumLevel = Model.Settings.Settings.DEFAULTLOGGINLEVEL })
|
||||
.WriteTo.Debug()
|
||||
.WriteTo.File(internalPersonalDir, Model.Logging.RollingInterval.Session)
|
||||
.CreateLogger();
|
||||
|
||||
// Subscribe to any unhandled/ unobserved exceptions.
|
||||
AppDomain.CurrentDomain.UnhandledException += (sender, unobservedTaskExceptionEventArgs) => { Log.Fatal("Unobserved task exception: {Exception}", unobservedTaskExceptionEventArgs.ExceptionObject); };
|
||||
TaskScheduler.UnobservedTaskException += (sender, unhandledExceptionEventArgs) => { Log.Fatal("Unhandled exception: {Exception}", unhandledExceptionEventArgs.Exception); };
|
||||
|
||||
// Restore last model state from json- file.
|
||||
Dictionary<string, string> settingsJSON = new Dictionary<string, string>();
|
||||
try
|
||||
{
|
||||
settingsJSON = JsonSettingsDictionary.Deserialize(specialFolders.GetInternalPersonalDir());
|
||||
settingsJSON = JsonSettingsDictionary.Deserialize(internalPersonalDir);
|
||||
}
|
||||
catch (Exception l_oException)
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.Error("Reading application settings from file failed.", l_oException);
|
||||
Log.Error("Reading application settings from file failed.", exception);
|
||||
}
|
||||
|
||||
var settings = new Model.Settings.Settings(
|
||||
JsonSettingsDictionary.GetGroupFilterMapPage(settingsJSON),
|
||||
JsonSettingsDictionary.GetGoupFilterSettings(settingsJSON),
|
||||
JsonSettingsDictionary.GetCopriHostUri(settingsJSON),
|
||||
JsonSettingsDictionary.GetPollingParameters(settingsJSON),
|
||||
JsonSettingsDictionary.GetMinimumLoggingLevel(settingsJSON),
|
||||
JsonSettingsDictionary.GetExpiresAfter(settingsJSON),
|
||||
JsonSettingsDictionary.GetActiveLockService(settingsJSON),
|
||||
JsonSettingsDictionary.GetConnectTimeout(settingsJSON),
|
||||
JsonSettingsDictionary.GetActiveGeolocationService(settingsJSON),
|
||||
JsonSettingsDictionary.GetCenterMapToCurrentLocation(settingsJSON),
|
||||
JsonSettingsDictionary.GetLogToExternalFolder(settingsJSON),
|
||||
JsonSettingsDictionary.GetIsSiteCachingOn(settingsJSON),
|
||||
JsonSettingsDictionary.GetActiveTheme(settingsJSON));
|
||||
Model.Settings.Settings settings;
|
||||
try
|
||||
{
|
||||
settings = new Model.Settings.Settings(
|
||||
JsonSettingsDictionary.GetGroupFilterMapPage(settingsJSON),
|
||||
JsonSettingsDictionary.GetGoupFilterSettings(settingsJSON),
|
||||
JsonSettingsDictionary.GetCopriHostUri(settingsJSON),
|
||||
JsonSettingsDictionary.GetPollingParameters(settingsJSON),
|
||||
JsonSettingsDictionary.GetMinimumLoggingLevel(settingsJSON),
|
||||
JsonSettingsDictionary.GetIsReportLevelVerbose(settingsJSON),
|
||||
JsonSettingsDictionary.GetExpiresAfter(settingsJSON),
|
||||
JsonSettingsDictionary.GetActiveLockService(settingsJSON),
|
||||
JsonSettingsDictionary.GetConnectTimeout(settingsJSON),
|
||||
JsonSettingsDictionary.GetActiveGeolocationService(settingsJSON),
|
||||
JsonSettingsDictionary.GetCenterMapToCurrentLocation(settingsJSON),
|
||||
JsonSettingsDictionary.GetLogToExternalFolder(settingsJSON),
|
||||
JsonSettingsDictionary.GetIsSiteCachingOn(settingsJSON),
|
||||
JsonSettingsDictionary.GetActiveTheme(settingsJSON));
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.Error("Deserializing application settings from dictionary failed.", exception);
|
||||
settings = new Model.Settings.Settings();
|
||||
}
|
||||
|
||||
var store = new Store(settings.ActiveUri.GetHashCode().ToString());
|
||||
var l_oAccount = new Account(store.Load());
|
||||
if (settings.MinimumLogEventLevel != Model.Settings.Settings.DEFAULTLOGGINLEVEL
|
||||
|| settings.LogToExternalFolder)
|
||||
{
|
||||
// Eigher
|
||||
// - logging is not set to default value or
|
||||
// - logging is performed to external folder.
|
||||
// Need to reconfigure.
|
||||
Log.CloseAndFlush(); // Close before modifying logger configuration. Otherwise a sharing vialation occurs.
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.MinimumLevel.ControlledBy(new LoggingLevelSwitch(settings.MinimumLogEventLevel))
|
||||
.WriteTo.Debug()
|
||||
.WriteTo.File(!settings.LogToExternalFolder ? internalPersonalDir : specialFolders.GetExternalFilesDir(), Model.Logging.RollingInterval.Session)
|
||||
.CreateLogger();
|
||||
}
|
||||
|
||||
// Get auth cookie
|
||||
Log.Debug("Get auth cookie.");
|
||||
IStore store = null;
|
||||
|
||||
var lastVersion = JsonSettingsDictionary.GetAppVersion(settingsJSON);
|
||||
if (lastVersion > new Version(3, 0, 173))
|
||||
GeolocationServicesContainer.SetActive(settings.ActiveGeolocationService);
|
||||
|
||||
if (new Version(0, 0, 0) < lastVersion
|
||||
&& lastVersion <= new Version(3, 0, 234))
|
||||
{
|
||||
// Version 3.0.245 and older used Xamarin.Auth.AccountStore to securely store data.
|
||||
// Later version s use Xamarin.Essentials Secure Storage.
|
||||
store = new StoreLegacy(settings.ActiveUri.GetHashCode().ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
// Either
|
||||
// - frist install or
|
||||
// - version whitch uses secure storage
|
||||
// detected.
|
||||
store = new Store();
|
||||
}
|
||||
|
||||
Barrel.ApplicationId = "TINKApp";
|
||||
|
||||
|
@ -85,17 +151,17 @@ namespace TINK
|
|||
var appInfoService = DependencyService.Get<IAppInfo>();
|
||||
|
||||
// Create new app instnace.
|
||||
Log.Debug("Constructing main model...");
|
||||
m_oModelRoot = new TinkApp(
|
||||
settings,
|
||||
store, // Manages user account
|
||||
(isConnected, activeUri, sessionCookie, mail, expiresAfter) => ConnectorFactory.Create(isConnected, activeUri, $"TINKApp/{appInfoService.Version}", sessionCookie, mail, expiresAfter),
|
||||
null, /* geolocationService */
|
||||
DependencyService.Get<IGeolodationDependent>(),
|
||||
(isConnected, activeUri, sessionCookie, mail, expiresAfter) => ConnectorFactory.Create(isConnected, activeUri, $"sharee.bike/{appInfoService.Version}", sessionCookie, mail, expiresAfter),
|
||||
GeolocationServicesContainer,
|
||||
null, /* locksService */
|
||||
DependencyService.Get<IDevice>(),
|
||||
DependencyService.Get<ISmartDevice>(),
|
||||
specialFolders,
|
||||
new Cipher(),
|
||||
CrossPermissions.Current,
|
||||
null, // Permissions, no more used.
|
||||
#if ARENDI
|
||||
DependencyService.Get<ICentral>(),
|
||||
#else
|
||||
|
@ -107,6 +173,7 @@ namespace TINK
|
|||
lastVersion: JsonSettingsDictionary.GetAppVersion(settingsJSON),
|
||||
whatsNewShownInVersion: JsonSettingsDictionary.GetWhatsNew(settingsJSON) ?? settingsJSON.GetAppVersion());
|
||||
|
||||
Log.Debug("Main model successfully constructed.");
|
||||
return m_oModelRoot;
|
||||
}
|
||||
}
|
||||
|
@ -123,7 +190,7 @@ namespace TINK
|
|||
MainPage = ModelRoot.WhatsNew.IsShowRequired
|
||||
? new View.WhatsNew.WhatsNewPage(() => MainPage = new View.MainPage()) // Show whats new info.
|
||||
: (Page) new View.MainPage(); // Just use TINKApp
|
||||
#elif USEFLYOU
|
||||
#elif USEFLYOUT
|
||||
// Use flyout page.
|
||||
MainPage = ModelRoot.WhatsNew.IsShowRequired
|
||||
? new View.WhatsNew.WhatsNewPage(() => MainPage = new View.Root.RootPage()) // Show whats new info.
|
||||
|
@ -138,12 +205,12 @@ namespace TINK
|
|||
}
|
||||
|
||||
/// <summary> Concatenates all log files to a single one. </summary>
|
||||
/// <returns>File name of attachment.</returns>
|
||||
/// <returns>Full file name of attachment.</returns>
|
||||
public static string CreateAttachment()
|
||||
{
|
||||
var l_oLogFiles = Log.Logger.GetLogFiles().ToArray();
|
||||
var sessionLogFiles = Log.Logger.GetLogFiles().ToArray();
|
||||
|
||||
if (l_oLogFiles.Length < 1)
|
||||
if (sessionLogFiles.Length < 1)
|
||||
{
|
||||
// Either
|
||||
// - there is no logging file
|
||||
|
@ -151,14 +218,14 @@ namespace TINK
|
|||
return string.Empty;
|
||||
}
|
||||
|
||||
var l_oLogPath = System.IO.Path.Combine(ModelRoot.LogFileParentFolder, ATTACHMENTTITLE);
|
||||
var fullLogFileName = System.IO.Path.Combine(ModelRoot.LogFileParentFolder, ATTACHMENTTITLE);
|
||||
|
||||
// Stop logging to avoid file access exception.
|
||||
Log.CloseAndFlush();
|
||||
|
||||
System.IO.File.WriteAllLines(
|
||||
l_oLogPath,
|
||||
l_oLogFiles.SelectMany(name =>
|
||||
fullLogFileName,
|
||||
sessionLogFiles.SelectMany(name =>
|
||||
(new List<string> { $"{{\"SessionFileName\":\"{name}\"}}" })
|
||||
.Concat(System.IO.File.ReadLines(name).ToArray())));
|
||||
|
||||
|
@ -169,33 +236,21 @@ namespace TINK
|
|||
.WriteTo.File(ModelRoot.LogFileParentFolder, Model.Logging.RollingInterval.Session)
|
||||
.CreateLogger();
|
||||
|
||||
return l_oLogPath;
|
||||
return fullLogFileName;
|
||||
}
|
||||
|
||||
/// <summary>Deletes an attachment if there is one.</summary>
|
||||
private static void DeleteAttachment()
|
||||
/// <param name="folder">Folder to delete, is null folder is queried from model.</param>
|
||||
private static void DeleteAttachment(string folder = null)
|
||||
{
|
||||
var l_oAttachment = System.IO.Path.Combine(ModelRoot.LogFileParentFolder, ATTACHMENTTITLE);
|
||||
if (!System.IO.File.Exists(l_oAttachment))
|
||||
var attachment = System.IO.Path.Combine(folder ?? ModelRoot.LogFileParentFolder, ATTACHMENTTITLE);
|
||||
if (!System.IO.File.Exists(attachment))
|
||||
{
|
||||
// No attachment found.
|
||||
return;
|
||||
}
|
||||
|
||||
System.IO.File.Delete(l_oAttachment);
|
||||
}
|
||||
|
||||
|
||||
/// <summary> TINK app starts up.</summary>
|
||||
protected override void OnStart()
|
||||
{
|
||||
DeleteAttachment();
|
||||
|
||||
Log.Logger = new LoggerConfiguration()
|
||||
.MinimumLevel.ControlledBy(new LoggingLevelSwitch { MinimumLevel = ModelRoot.Level.MinimumLevel })
|
||||
.WriteTo.Debug()
|
||||
.WriteTo.File(ModelRoot.LogFileParentFolder, Model.Logging.RollingInterval.Session)
|
||||
.CreateLogger();
|
||||
System.IO.File.Delete(attachment);
|
||||
}
|
||||
|
||||
protected override void OnSleep()
|
||||
|
@ -227,5 +282,26 @@ namespace TINK
|
|||
|
||||
return LogEventLevel.Error;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Service to manage permissions (location) of the app.
|
||||
/// </summary>
|
||||
public static Plugin.Permissions.Abstractions.IPermissions PermissionsService => CrossPermissions.Current;
|
||||
|
||||
/// <summary>
|
||||
/// Service to manage bluetooth stack.
|
||||
/// </summary>
|
||||
public static Plugin.BLE.Abstractions.Contracts.IBluetoothLE BluetoothService => Plugin.BLE.CrossBluetoothLE.Current;
|
||||
|
||||
/// <summary>
|
||||
/// Service container to manage geolocation services.
|
||||
/// </summary>
|
||||
public static IServicesContainer<IGeolocation> GeolocationServicesContainer { get; }
|
||||
= new Services.ServicesContainerMutable<Model.Services.Geolocation.IGeolocation>(
|
||||
new HashSet<Model.Services.Geolocation.IGeolocation> {
|
||||
new LastKnownGeolocationService(DependencyService.Get<IGeolodationDependent>()),
|
||||
new SimulatedGeolocationService(DependencyService.Get<IGeolodationDependent>()),
|
||||
new GeolocationService(DependencyService.Get<IGeolodationDependent>()) },
|
||||
typeof(LastKnownGeolocationService).FullName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,19 +7,19 @@ namespace TINK
|
|||
{
|
||||
public static class BackdoorMethodHelpers
|
||||
{
|
||||
public static void DoTapPage(string stationIndex )
|
||||
public static void DoTapPage(string stationId )
|
||||
{
|
||||
Serilog.Log.Information($"Request via backdoor to tap station {stationIndex}.");
|
||||
Serilog.Log.Information($"Request via backdoor to tap station {stationId}.");
|
||||
var currentPage = GetCurrentPage();
|
||||
var mapPageViewModel = (currentPage as MapPage)?.BindingContext as MapPageViewModel;
|
||||
if (mapPageViewModel == null)
|
||||
{
|
||||
Serilog.Log.Error($"Request via backdoor to tap station {stationIndex} aborted because current page is not of expected type {typeof(MapPage).Name}. Type detected is {currentPage.GetType().Name}.");
|
||||
Serilog.Log.Error($"Request via backdoor to tap station {stationId} aborted because current page is not of expected type {typeof(MapPage).Name}. Type detected is {currentPage.GetType().Name}.");
|
||||
return;
|
||||
}
|
||||
|
||||
Serilog.Log.Information($"Invoking member to tap.");
|
||||
mapPageViewModel?.OnStationClicked(int.Parse(stationIndex));
|
||||
mapPageViewModel?.OnStationClicked(stationId);
|
||||
}
|
||||
|
||||
/// <summary> Gets the current page assumed that app is master detail page.</summary>
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Connector;
|
||||
|
||||
namespace TINK.Model.User.Account
|
||||
{
|
||||
public class Store : IStore
|
||||
public class StoreLegacy : IStore
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds the name of the application.
|
||||
|
@ -21,12 +23,9 @@ namespace TINK.Model.User.Account
|
|||
/// <summary> Holds the id of the session. </summary>
|
||||
private const string KEY_DEBUGLEVEL = "DebugLevel";
|
||||
|
||||
private Store()
|
||||
{ }
|
||||
|
||||
public Store(string p_strCopriHostHash)
|
||||
public StoreLegacy(string copriHostHash)
|
||||
{
|
||||
m_strCopriHostHash = p_strCopriHostHash
|
||||
m_strCopriHostHash = copriHostHash
|
||||
?? throw new ArgumentException("Can not construct account object. Copri hash must not be null.");
|
||||
}
|
||||
|
||||
|
@ -36,26 +35,26 @@ namespace TINK.Model.User.Account
|
|||
/// Reads mail address and password from account store.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public IAccount Load()
|
||||
public async Task<IAccount> Load()
|
||||
{
|
||||
#if !WINDOWS_UWP
|
||||
#if !__IOS__
|
||||
var account = Xamarin.Auth.AccountStore.Create("System.Char[]").FindAccountsForService($"{M_STR_APPNAME}_{m_strCopriHostHash}").FirstOrDefault();
|
||||
var xamAccountStore = Xamarin.Auth.AccountStore.Create("System.Char[]").FindAccountsForService($"{M_STR_APPNAME}_{m_strCopriHostHash}").FirstOrDefault();
|
||||
#else
|
||||
var account = Xamarin.Auth.AccountStore.Create().FindAccountsForService($"{M_STR_APPNAME}_{m_strCopriHostHash}").FirstOrDefault();
|
||||
var xamAccountStore = Xamarin.Auth.AccountStore.Create().FindAccountsForService($"{M_STR_APPNAME}_{m_strCopriHostHash}").FirstOrDefault();
|
||||
#endif
|
||||
if (account == null)
|
||||
if (xamAccountStore == null)
|
||||
{
|
||||
// Nothing t do if account cannot be accessed.
|
||||
return new EmptyAccount();
|
||||
}
|
||||
|
||||
return new Account(
|
||||
account.Username,
|
||||
xamAccountStore.Username,
|
||||
string.Empty,
|
||||
account.Properties.ContainsKey(KEY_SESSIONID) ? account.Properties[KEY_SESSIONID] : null,
|
||||
account.Properties.ContainsKey(KEY_GROUP) ? TextToTypeHelper.GetGroup(account.Properties[KEY_GROUP]) : new List<string>(),
|
||||
account.Properties.ContainsKey(KEY_DEBUGLEVEL) && !string.IsNullOrEmpty(account.Properties[KEY_DEBUGLEVEL]) ? Permissions.Parse<Permissions>(account.Properties[KEY_DEBUGLEVEL]) : Permissions.None);
|
||||
xamAccountStore.Properties.ContainsKey(KEY_SESSIONID) ? xamAccountStore.Properties[KEY_SESSIONID] : null,
|
||||
xamAccountStore.Properties.ContainsKey(KEY_GROUP) && !string.IsNullOrEmpty(xamAccountStore.Properties[KEY_GROUP]) ? JsonConvert.DeserializeObject<IEnumerable<string>>(xamAccountStore.Properties[KEY_GROUP]) : new string[0],
|
||||
xamAccountStore.Properties.ContainsKey(KEY_DEBUGLEVEL) && !string.IsNullOrEmpty(xamAccountStore.Properties[KEY_DEBUGLEVEL]) ? Permissions.Parse<Permissions>(xamAccountStore.Properties[KEY_DEBUGLEVEL]) : Permissions.None);
|
||||
#else
|
||||
return new Account(
|
||||
string.Empty,
|
||||
|
@ -70,22 +69,22 @@ namespace TINK.Model.User.Account
|
|||
/// <summary>
|
||||
/// Writes mail address and password to account store.
|
||||
/// </summary>
|
||||
/// <param name="p_oAccount"></param>
|
||||
public void Save(IAccount p_oAccount)
|
||||
/// <param name="account"></param>
|
||||
public async Task Save(IAccount account)
|
||||
{
|
||||
#if !WINDOWS_UWP
|
||||
Xamarin.Auth.Account account = new Xamarin.Auth.Account
|
||||
Xamarin.Auth.Account xamAccount = new Xamarin.Auth.Account
|
||||
{
|
||||
Username = p_oAccount.Mail
|
||||
Username = account.Mail
|
||||
};
|
||||
|
||||
account.Properties.Add(KEY_SESSIONID, p_oAccount?.SessionCookie);
|
||||
account.Properties.Add(KEY_GROUP, p_oAccount?.Group?.GetGroup());
|
||||
account.Properties.Add(KEY_DEBUGLEVEL, p_oAccount.DebugLevel.ToString());
|
||||
xamAccount.Properties.Add(KEY_SESSIONID, account?.SessionCookie);
|
||||
xamAccount.Properties.Add(KEY_GROUP, JsonConvert.SerializeObject(account?.Group ?? new string[0]));
|
||||
xamAccount.Properties.Add(KEY_DEBUGLEVEL, account.DebugLevel.ToString());
|
||||
#if !__IOS__
|
||||
Xamarin.Auth.AccountStore.Create("System.Char[]").Save(account, $"{M_STR_APPNAME}_{m_strCopriHostHash}");
|
||||
Xamarin.Auth.AccountStore.Create("System.Char[]").Save(xamAccount, $"{M_STR_APPNAME}_{m_strCopriHostHash}");
|
||||
#else
|
||||
Xamarin.Auth.AccountStore.Create().Save(account, $"{M_STR_APPNAME}_{m_strCopriHostHash}");
|
||||
Xamarin.Auth.AccountStore.Create().Save(xamAccount, $"{M_STR_APPNAME}_{m_strCopriHostHash}");
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
@ -93,26 +92,25 @@ namespace TINK.Model.User.Account
|
|||
/// <summary>
|
||||
/// Deletes mail address and password from account store.
|
||||
/// </summary>
|
||||
public IAccount Delete(IAccount p_oAccount)
|
||||
public IAccount Delete(IAccount account)
|
||||
{
|
||||
#if !WINDOWS_UWP
|
||||
#if !__IOS__
|
||||
var account = Xamarin.Auth.AccountStore.Create("System.Char[]").FindAccountsForService($"{M_STR_APPNAME}_{m_strCopriHostHash}").FirstOrDefault();
|
||||
var xamAccountStore = Xamarin.Auth.AccountStore.Create("System.Char[]").FindAccountsForService($"{M_STR_APPNAME}_{m_strCopriHostHash}").FirstOrDefault();
|
||||
#else
|
||||
var account = Xamarin.Auth.AccountStore.Create().FindAccountsForService($"{M_STR_APPNAME}_{m_strCopriHostHash}").FirstOrDefault();
|
||||
var xamAccountStore = Xamarin.Auth.AccountStore.Create().FindAccountsForService($"{M_STR_APPNAME}_{m_strCopriHostHash}").FirstOrDefault();
|
||||
#endif
|
||||
if (account == null)
|
||||
if (xamAccountStore == null)
|
||||
{
|
||||
return new EmptyAccount();
|
||||
}
|
||||
#if !__IOS__
|
||||
Xamarin.Auth.AccountStore.Create("System.Char[]").Delete(account, $"{M_STR_APPNAME}_{m_strCopriHostHash}");
|
||||
Xamarin.Auth.AccountStore.Create("System.Char[]").Delete(xamAccountStore, $"{M_STR_APPNAME}_{m_strCopriHostHash}");
|
||||
#else
|
||||
Xamarin.Auth.AccountStore.Create().Delete(account, $"{M_STR_APPNAME}_{m_strCopriHostHash}");
|
||||
Xamarin.Auth.AccountStore.Create().Delete(xamAccountStore, $"{M_STR_APPNAME}_{m_strCopriHostHash}");
|
||||
#endif
|
||||
#endif
|
||||
return new EmptyAccount();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)BackdoorMethodHelpers.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Services\BluetoothLock\Arendi\Central.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModel\FeesAndBikes\HelpContactViewModel.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModel\RootShell\AppShellViewModel.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModel\RootFlyout\RootPageViewModel.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)View\Account\AccountPage.xaml.cs">
|
||||
|
@ -76,6 +75,7 @@
|
|||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)View\WhatsNew\WhatsNewPage.xaml.cs">
|
||||
<DependentUpon>WhatsNewPage.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Include="$(MSBuildThisFileDirectory)Model\User\Account\Store.cs" />
|
||||
<Compile Include="$(MSBuildThisFileDirectory)ViewModel\ViewModelResourceHelper.cs" />
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
using System.Threading.Tasks;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using System;
|
||||
using TINK.Model.Device;
|
||||
using TINK.ViewModel.Account;
|
||||
|
@ -10,7 +12,11 @@ using TINK.ViewModel.Account;
|
|||
namespace TINK.View.Account
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
public partial class AccountPage : ContentPage, IViewService, IDetailPage
|
||||
#else
|
||||
public partial class AccountPage : ContentPage, IViewService
|
||||
#endif
|
||||
{
|
||||
/// <summary> Refernce to view model. </summary>
|
||||
AccountPageViewModel m_oViewModel = null;
|
||||
|
@ -31,18 +37,18 @@ namespace TINK.View.Account
|
|||
}
|
||||
|
||||
/// <summary> Displays altert message. </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strCancel">Type of buttons.</param>
|
||||
public new async Task DisplayAlert(string p_strTitle, string p_strMessage, string p_strCancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(p_strTitle, p_strMessage, p_strCancel);
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAlert(string title, string message, string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, message, cancel);
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
public async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
|
@ -50,32 +56,48 @@ namespace TINK.View.Account
|
|||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary> Displays alert message.</summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strAccept">Text of accept button.</param>
|
||||
/// <param name="p_strCancel">Text of button.</param>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="accept">Text of accept button.</param>
|
||||
/// <param name="cancel">Text of button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public new async Task<bool> DisplayAlert(string p_strTitle, string p_strMessage, string p_strAccept, string p_strCancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(p_strTitle, p_strMessage, p_strAccept, p_strCancel);
|
||||
public new async Task<bool> DisplayAlert(string title, string message, string accept, string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, message, accept, cancel);
|
||||
|
||||
/// <summary> Displays detailed alert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="accept">Text of accept button.</param>
|
||||
/// <param name="cancel">Text of cancel button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public async Task<bool> DisplayAdvancedAlert(string title, string message, string details, string accept, string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", accept, cancel);
|
||||
|
||||
/// <summary>
|
||||
/// Displays an action sheet.
|
||||
/// </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strCancel">Text of button.</param>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="cancel">Text of button.</param>
|
||||
/// <param name="destruction"></param>
|
||||
/// <param name="p_oButtons">Buttons holding options to select.</param>
|
||||
/// <returns>Text selected</returns>
|
||||
public new async Task<string> DisplayActionSheet(String p_strTitle, String p_strCancel, String destruction, params String[] p_oButtons)
|
||||
=> await base.DisplayActionSheet(p_strTitle, p_strCancel, destruction, p_oButtons);
|
||||
public new async Task<string> DisplayActionSheet(String title, String cancel, String destruction, params String[] p_oButtons)
|
||||
=> await base.DisplayActionSheet(title, cancel, destruction, p_oButtons);
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
=> m_oNavigation.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
public void ShowPage(ViewTypes p_oType, string title = null)
|
||||
=> m_oNavigation.ShowPage(p_oType.GetViewType(), title);
|
||||
#else
|
||||
/// <summary> Shows a page.</summary>
|
||||
/// <param name="route">Route of the page to show.</param>
|
||||
public async Task ShowPage(string route) => await Shell.Current.GoToAsync(route);
|
||||
#endif
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
|
@ -86,6 +108,7 @@ namespace TINK.View.Account
|
|||
public Task PopModalAsync()
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
|
||||
/// <summary>Delegate to perform navigation.</summary>
|
||||
private INavigationMasterDetail m_oNavigation;
|
||||
|
@ -98,6 +121,7 @@ namespace TINK.View.Account
|
|||
set { m_oNavigation = value; }
|
||||
}
|
||||
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Invoked when page is shown.
|
||||
/// Starts update process.
|
||||
|
@ -122,7 +146,10 @@ namespace TINK.View.Account
|
|||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public async Task PushAsync(ViewTypes p_oTypeOfPage)
|
||||
=> await Navigation.PushAsync((Page)Activator.CreateInstance(p_oTypeOfPage.GetViewType()));
|
||||
|
||||
#if USCSHARP9
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
#else
|
||||
public Task<IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -15,7 +15,14 @@
|
|||
Padding="10">
|
||||
<Label
|
||||
FontAttributes="Bold"
|
||||
FontSize="Large"
|
||||
HorizontalTextAlignment="Center"
|
||||
Text="{Binding Name}"/>
|
||||
<Label
|
||||
FontAttributes="Bold"
|
||||
HorizontalTextAlignment="Center"
|
||||
IsVisible="{Binding DisplayId, Converter={StaticResource Label_Converter}}"
|
||||
Text="{Binding DisplayId}"/>
|
||||
<Label
|
||||
Text="{Binding StateText}"
|
||||
TextColor="{Binding StateColor}"/>
|
||||
|
|
|
@ -10,7 +10,9 @@ namespace TINK.View.BikesAtStation
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Device;
|
||||
using TINK.View.MasterDetail;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using TINK.ViewModel;
|
||||
using TINK.Model;
|
||||
using TINK.Services.BluetoothLock.Tdo;
|
||||
|
@ -23,7 +25,11 @@ namespace TINK.View.BikesAtStation
|
|||
using Xamarin.CommunityToolkit.Extensions;
|
||||
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
public partial class BikesAtStationPage : ContentPage, IViewService, IDetailPage
|
||||
#else
|
||||
public partial class BikesAtStationPage : ContentPage, IViewService
|
||||
#endif
|
||||
{
|
||||
|
||||
private BikesAtStationPageViewModel m_oViewModel;
|
||||
|
@ -78,23 +84,27 @@ namespace TINK.View.BikesAtStation
|
|||
|
||||
m_oViewModel = new BikesAtStationPageViewModel(
|
||||
model.ActiveUser,
|
||||
model.Permissions,
|
||||
CrossBluetoothLE.Current,
|
||||
App.PermissionsService,
|
||||
App.BluetoothService,
|
||||
Device.RuntimePlatform,
|
||||
model.SelectedStation,
|
||||
() => model.GetIsConnected(),
|
||||
(isConnected) => model.GetConnector(isConnected),
|
||||
model.Geolocation,
|
||||
App.GeolocationServicesContainer.Active,
|
||||
model.LocksServices.Active,
|
||||
model.Polling,
|
||||
(url) => DependencyService.Get<IExternalBrowserService>().OpenUrl(url),
|
||||
(d, obj) => synchronizationContext.Post(d, obj),
|
||||
this);
|
||||
model.SmartDevice,
|
||||
this)
|
||||
{
|
||||
IsReportLevelVerbose = model.IsReportLevelVerbose
|
||||
};
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<BikesAtStationPage>().Error("Displaying bikes at station page failed. {Exception}", exception);
|
||||
this.DisplayAlert("Fehler", $"Seite Räder an Station kann nicht angezeigt werden. ${exception.Message}", "OK");
|
||||
await DisplayAlert("Fehler", $"Seite Räder an Station kann nicht angezeigt werden. ${exception.Message}", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -130,12 +140,12 @@ namespace TINK.View.BikesAtStation
|
|||
}
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strCancel">Type of buttons.</param>
|
||||
public new async Task DisplayAlert(string p_strTitle, string p_strMessage, string p_strCancel)
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAlert(string title, string message, string cancel)
|
||||
{
|
||||
await App.Current.MainPage.DisplayAlert(p_strTitle, p_strMessage, p_strCancel);
|
||||
await App.Current.MainPage.DisplayAlert(title, message, cancel);
|
||||
}
|
||||
|
||||
/// <summary> Displays altert message.</summary>
|
||||
|
@ -143,7 +153,7 @@ namespace TINK.View.BikesAtStation
|
|||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
public async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
|
@ -153,23 +163,37 @@ namespace TINK.View.BikesAtStation
|
|||
/// <summary>
|
||||
/// Displays alert message.
|
||||
/// </summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
/// <param name="p_strAccept">Text of accept button.</param>
|
||||
/// <param name="p_strCancel">Text of button.</param>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="accept">Text of accept button.</param>
|
||||
/// <param name="cancel">Text of button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public new async Task<bool> DisplayAlert(string p_strTitle, string p_strMessage, string p_strAccept, string p_strCancel)
|
||||
{
|
||||
return await App.Current.MainPage.DisplayAlert(p_strTitle, p_strMessage, p_strAccept, p_strCancel);
|
||||
}
|
||||
public new async Task<bool> DisplayAlert(string title, string message, string accept, string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, message, accept, cancel);
|
||||
|
||||
/// <summary> Displays detailed alert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="accept">Text of accept button.</param>
|
||||
/// <param name="cancel">Text of cancel button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public async Task<bool> DisplayAdvancedAlert(string title, string message, string details, string accept, string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", accept, cancel);
|
||||
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
/// <summary> Creates and a page an shows it.</summary>
|
||||
/// <remarks> When user is not logged in navigation to Login page is supported.</remarks>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
m_oNavigation.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
}
|
||||
public void ShowPage(ViewTypes p_oType, string title = null)
|
||||
=> m_oNavigation.ShowPage(p_oType.GetViewType(), title);
|
||||
#else
|
||||
/// <summary> Shows a page.</summary>
|
||||
/// <param name="route">Route of the page to show.</param>
|
||||
public async Task ShowPage(string route) => await Shell.Current.GoToAsync(route);
|
||||
#endif
|
||||
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
|
@ -189,6 +213,7 @@ namespace TINK.View.BikesAtStation
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
/// <summary>
|
||||
/// Delegate to perform navigation.
|
||||
/// </summary>
|
||||
|
@ -202,6 +227,12 @@ namespace TINK.View.BikesAtStation
|
|||
set { m_oNavigation = value; }
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if USCSHARP9
|
||||
public async Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => await Navigation.ShowPopupAsync<FeedbackPopup.Result>(new FeedbackPopup());
|
||||
}
|
||||
}
|
||||
#else
|
||||
public async Task<IUserFeedback> DisplayUserFeedbackPopup() => await Navigation.ShowPopupAsync<FeedbackPopup.Result>(new FeedbackPopup());
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -27,21 +27,31 @@ namespace TINK.View.Contact
|
|||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
public async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
/// <summary> Displays detailed alert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="accept">Text of accept button.</param>
|
||||
/// <param name="cancel">Text of cancel button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public async Task<bool> DisplayAdvancedAlert(string title, string message, string details, string accept, string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", accept, cancel);
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
#else
|
||||
/// <summary> Shows a page.</summary>
|
||||
/// <param name="route">Route of the page to show.</param>
|
||||
public async Task ShowPage(string route) => await Shell.Current.GoToAsync(route);
|
||||
#endif
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
|
@ -62,7 +72,10 @@ namespace TINK.View.Contact
|
|||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#if USCSHARP9
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
#else
|
||||
public Task<IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -1,15 +1,10 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Xamarin.CommunityToolkit.UI.Views;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class FeedbackPopup : Popup<FeedbackPopup.Result>
|
||||
{
|
||||
public FeedbackPopup ()
|
||||
|
@ -40,7 +35,11 @@ namespace TINK.View
|
|||
/// <summary>
|
||||
/// Feedback given by user when returning bike.
|
||||
/// </summary>
|
||||
#if USCSHARP9
|
||||
public class Result : IViewService.IUserFeedback
|
||||
#else
|
||||
public class Result : IUserFeedback
|
||||
#endif
|
||||
{
|
||||
/// <summary>
|
||||
/// Holds whether bike is broken or not.
|
||||
|
@ -54,7 +53,6 @@ namespace TINK.View
|
|||
/// or both.
|
||||
/// </summary>
|
||||
public string Message { get; set; }
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
using TINK.ViewModel.Contact;
|
||||
using TINK.Model;
|
||||
|
||||
namespace TINK.View.Contact
|
||||
{
|
||||
|
@ -16,8 +15,10 @@ namespace TINK.View.Contact
|
|||
InitializeComponent();
|
||||
|
||||
ViewModel = new HelpContactViewModel(
|
||||
TINK.App.ModelRoot.NextActiveUri.Host,
|
||||
TINK.App.ModelRoot.IsSiteCachingOn);
|
||||
App.ModelRoot.NextActiveUri.Host,
|
||||
App.ModelRoot.IsSiteCachingOn,
|
||||
resourceName => ViewModelResourceHelper.GetSource(resourceName));
|
||||
|
||||
BindingContext = ViewModel;
|
||||
|
||||
/// Info about renting.
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using TINK.ViewModel;
|
||||
using TINK.ViewModel.Info.BikeInfo;
|
||||
using Xamarin.Forms;
|
||||
|
@ -9,9 +11,13 @@ using Xamarin.Forms.Xaml;
|
|||
namespace TINK.View.Info.BikeInfo
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class BikeInfoCarouselPage : CarouselPage, IViewService, IDetailPage
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
public partial class BikeInfoCarouselPage : CarouselPage, IViewService, IDetailPage
|
||||
#else
|
||||
public partial class BikeInfoCarouselPage : CarouselPage, IViewService
|
||||
#endif
|
||||
{
|
||||
public BikeInfoCarouselPage ()
|
||||
public BikeInfoCarouselPage ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
|
||||
|
@ -36,13 +42,23 @@ namespace TINK.View.Info.BikeInfo
|
|||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
public async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary> Displays detailed alert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="accept">Text of accept button.</param>
|
||||
/// <param name="cancel">Text of cancel button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public async Task<bool> DisplayAdvancedAlert(string title, string message, string details, string accept, string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", accept, cancel);
|
||||
|
||||
/// <summary>
|
||||
/// Displays alert message.
|
||||
/// </summary>
|
||||
|
@ -56,14 +72,19 @@ namespace TINK.View.Info.BikeInfo
|
|||
return await App.Current.MainPage.DisplayAlert(p_strTitle, p_strMessage, p_strAccept, p_strCancel);
|
||||
}
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
m_oNavigation.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
}
|
||||
=> m_oNavigation.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
#else
|
||||
/// <summary> Shows a page.</summary>
|
||||
/// <param name="route">Route of the page to show.</param>
|
||||
public async Task ShowPage(string route) => await Shell.Current.GoToAsync(route);
|
||||
#endif
|
||||
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
|
@ -85,6 +106,7 @@ namespace TINK.View.Info.BikeInfo
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
/// <summary>
|
||||
/// Delegate to perform navigation.
|
||||
/// </summary>
|
||||
|
@ -98,6 +120,11 @@ namespace TINK.View.Info.BikeInfo
|
|||
set { m_oNavigation = value; }
|
||||
}
|
||||
|
||||
#endif
|
||||
#if USCSHARP9
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
#else
|
||||
public Task<IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Device;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using TINK.ViewModel;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
@ -9,9 +11,13 @@ using Xamarin.Forms.Xaml;
|
|||
namespace TINK.View.Login
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class LoginPage : ContentPage, IViewService, IDetailPage
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
public partial class LoginPage : ContentPage, IViewService, IDetailPage
|
||||
#else
|
||||
public partial class LoginPage : ContentPage, IViewService
|
||||
#endif
|
||||
{
|
||||
public LoginPage ()
|
||||
public LoginPage ()
|
||||
{
|
||||
InitializeComponent ();
|
||||
|
||||
|
@ -44,25 +50,40 @@ namespace TINK.View.Login
|
|||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
public async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary> Displays detailed alert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="accept">Text of accept button.</param>
|
||||
/// <param name="cancel">Text of cancel button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public async Task<bool> DisplayAdvancedAlert(string title, string message, string details, string accept, string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", accept, cancel);
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
m_oNavigation.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
}
|
||||
=> m_oNavigation.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
#else
|
||||
/// <summary> Shows a page.</summary>
|
||||
/// <param name="route">Route of the page to show.</param>
|
||||
public async Task ShowPage(string route) => await Shell.Current.GoToAsync(route);
|
||||
#endif
|
||||
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public Task PushModalAsync(ViewTypes p_oTypeOfPage)
|
||||
public Task PushModalAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
|
@ -80,6 +101,7 @@ namespace TINK.View.Login
|
|||
await Navigation.PushAsync((Page)Activator.CreateInstance(p_oTypeOfPage.GetViewType()));
|
||||
}
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
/// <summary>
|
||||
/// Delegate to perform navigation.
|
||||
/// </summary>
|
||||
|
@ -93,6 +115,11 @@ namespace TINK.View.Login
|
|||
set { m_oNavigation = value; }
|
||||
}
|
||||
|
||||
#endif
|
||||
#if USCSHARP9
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
}
|
||||
}
|
||||
#else
|
||||
public Task<IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -1,21 +1,26 @@
|
|||
using Plugin.Connectivity;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
namespace TINK.View.Map
|
||||
{
|
||||
using TINK.Model.Services.CopriApi.ServerUris;
|
||||
using Serilog;
|
||||
using TINK.ViewModel.Map;
|
||||
using Xamarin.Forms.GoogleMaps;
|
||||
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
public partial class MapPage : ContentPage, IViewService, IDetailPage
|
||||
#else
|
||||
public partial class MapPage : ContentPage, IViewService
|
||||
#endif
|
||||
{
|
||||
/// <summary> View model to notify about whether page appears or hides. </summary>
|
||||
private MapPageViewModel m_oMapPageViewModel;
|
||||
private MapPageViewModel MapPageViewModel { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Constructs map page instance.
|
||||
|
@ -41,13 +46,23 @@ namespace TINK.View.Map
|
|||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
public async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary> Displays detailed alert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="accept">Text of accept button.</param>
|
||||
/// <param name="cancel">Text of cancel button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public async Task<bool> DisplayAdvancedAlert(string title, string message, string details, string accept, string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", accept, cancel);
|
||||
|
||||
/// <summary>
|
||||
/// Displays alert message.
|
||||
/// </summary>
|
||||
|
@ -61,14 +76,18 @@ namespace TINK.View.Map
|
|||
return await App.Current.MainPage.DisplayAlert(p_strTitle, p_strMessage, p_strAccept, p_strCancel);
|
||||
}
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
m_oNavigationMasterDetail.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
}
|
||||
=> NavigationMasterDetail.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
#else
|
||||
/// <summary> Shows a page.</summary>
|
||||
/// <param name="route">Route of the page to show.</param>
|
||||
public async Task ShowPage(string route) => await Shell.Current.GoToAsync(route);
|
||||
#endif
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to display.</param>
|
||||
|
@ -87,31 +106,34 @@ namespace TINK.View.Map
|
|||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
public async Task PushAsync(ViewTypes p_oTypeOfPage)
|
||||
{
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
var page = Activator.CreateInstance(p_oTypeOfPage.GetViewType()) as IDetailPage;
|
||||
#else
|
||||
var page = Activator.CreateInstance(p_oTypeOfPage.GetViewType());
|
||||
#endif
|
||||
if (page == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
page.NavigationMasterDetail = m_oNavigationMasterDetail;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
page.NavigationMasterDetail = NavigationMasterDetail;
|
||||
#endif
|
||||
|
||||
await Navigation.PushAsync((Page)page);
|
||||
}
|
||||
|
||||
#if USCSHARP9
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
#else
|
||||
public Task<IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
#endif
|
||||
|
||||
/// <summary> Delegate to perform navigation. </summary>
|
||||
private INavigationMasterDetail m_oNavigationMasterDetail;
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
/// <summary> Delegate to perform navigation.</summary>
|
||||
public INavigationMasterDetail NavigationMasterDetail
|
||||
{
|
||||
set
|
||||
{
|
||||
m_oNavigationMasterDetail = value;
|
||||
}
|
||||
}
|
||||
public INavigationMasterDetail NavigationMasterDetail { private get; set; }
|
||||
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Invoked when page is shown.
|
||||
/// Starts update process.
|
||||
|
@ -119,39 +141,99 @@ namespace TINK.View.Map
|
|||
protected async override void OnAppearing()
|
||||
{
|
||||
// Pass reference to member Navigation to show bikes at station x dialog.
|
||||
#if TRYNOTBACKSTYLE
|
||||
m_oMapPageViewModel = new MapPageViewModel();
|
||||
#else
|
||||
m_oMapPageViewModel = new MapPageViewModel(
|
||||
App.ModelRoot,
|
||||
(mapspan) => MyMap.MoveToRegion(mapspan),
|
||||
this,
|
||||
Navigation);
|
||||
#endif
|
||||
|
||||
BindingContext = m_oMapPageViewModel;
|
||||
|
||||
if (Device.RuntimePlatform == Device.iOS)
|
||||
try
|
||||
{
|
||||
TINKButton.BackgroundColor = Color.LightGray;
|
||||
TINKButton.BorderColor = Color.Black;
|
||||
TINKButton.Margin = new Thickness(10, 10, 10, 10);
|
||||
KonradButton.BackgroundColor = Color.LightGray;
|
||||
KonradButton.BorderColor = Color.Black;
|
||||
KonradButton.Margin = new Thickness(10, 10, 10, 10);
|
||||
Log.ForContext<MainPage>().Verbose("Constructing map page view model.");
|
||||
|
||||
#if TRYNOTBACKSTYLE
|
||||
m_oMapPageViewModel = new MapPageViewModel();
|
||||
#else
|
||||
MapPageViewModel = new MapPageViewModel(
|
||||
App.ModelRoot,
|
||||
App.PermissionsService,
|
||||
App.BluetoothService,
|
||||
App.GeolocationServicesContainer.Active,
|
||||
(mapspan) => MyMap.MoveToRegion(mapspan),
|
||||
this,
|
||||
Navigation);
|
||||
#endif
|
||||
} catch (Exception exception)
|
||||
{
|
||||
|
||||
Log.ForContext<MainPage>().Error("Constructing map page view model failed. {Exception}", exception);
|
||||
return;
|
||||
}
|
||||
|
||||
m_oMapPageViewModel.NavigationMasterDetail = m_oNavigationMasterDetail;
|
||||
try
|
||||
{
|
||||
BindingContext = MapPageViewModel;
|
||||
|
||||
base.OnAppearing();
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
MapPageViewModel.NavigationMasterDetail = NavigationMasterDetail;
|
||||
#endif
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<MainPage>().Error("Setting binding/ navigaton on map page failed. {Exception}", exception);
|
||||
return;
|
||||
}
|
||||
|
||||
// Pre move and scanle maps to avoid initial display of map in Rome.
|
||||
MapPageViewModel.MoveAndScale(
|
||||
(mapSpan) => MyMap.MoveToRegion(mapSpan),
|
||||
App.ModelRoot.Uris.ActiveUri,
|
||||
App.ModelRoot.GroupFilterMapPage);
|
||||
|
||||
await m_oMapPageViewModel.OnAppearing();
|
||||
try
|
||||
{
|
||||
if (Device.RuntimePlatform == Device.iOS)
|
||||
{
|
||||
TINKButton.BackgroundColor = Color.LightGray;
|
||||
TINKButton.BorderColor = Color.Black;
|
||||
TINKButton.Margin = new Thickness(10, 10, 10, 10);
|
||||
KonradButton.BackgroundColor = Color.LightGray;
|
||||
KonradButton.BorderColor = Color.Black;
|
||||
KonradButton.Margin = new Thickness(10, 10, 10, 10);
|
||||
}
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
// Continue because styling is not essential.
|
||||
Log.ForContext<MainPage>().Error("IOS specific styling of map page failed. {Exception}", exception);
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
base.OnAppearing();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
// Continue because styling is not essential.
|
||||
Log.ForContext<MainPage>().Error("Invoking OnAppearing of base failed. {Exception}", exception);
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Pre move and scanle maps to avoid initial display of map in Rome.
|
||||
Log.ForContext<MainPage>().Verbose("Moving and scaling map.");
|
||||
MapPageViewModel.MoveAndScale(
|
||||
(mapSpan) => MyMap.MoveToRegion(mapSpan),
|
||||
App.ModelRoot.Uris.ActiveUri,
|
||||
App.ModelRoot.GroupFilterMapPage);
|
||||
|
||||
}
|
||||
catch(Exception exception)
|
||||
{
|
||||
// Continue because a map not beeing moved/ scaled is no reason for aborting startup.
|
||||
Log.ForContext<MainPage>().Error("Moving and scaling map failed. {Exception}", exception);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Log.ForContext<MainPage>().Verbose("Invoking OnAppearing on map page view model.");
|
||||
await MapPageViewModel.OnAppearing();
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<MainPage>().Error("Invoking OnAppearing on map page view model failed. {Exception}", exception);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -160,10 +242,10 @@ namespace TINK.View.Map
|
|||
/// </summary>
|
||||
protected override async void OnDisappearing()
|
||||
{
|
||||
if (m_oMapPageViewModel != null)
|
||||
if (MapPageViewModel != null)
|
||||
{
|
||||
// View model might be null.
|
||||
await m_oMapPageViewModel?.OnDisappearing();
|
||||
await MapPageViewModel?.OnDisappearing();
|
||||
}
|
||||
|
||||
base.OnDisappearing();
|
||||
|
|
|
@ -4,7 +4,9 @@ using System.Linq;
|
|||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using TINK.Model.Bike.BluetoothLock;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using TINK.ViewModel;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
@ -58,21 +60,25 @@ namespace TINK.View.MyBikes
|
|||
|
||||
m_oViewModel = new MyBikesPageViewModel(
|
||||
model.ActiveUser,
|
||||
model.Permissions,
|
||||
CrossBluetoothLE.Current,
|
||||
App.PermissionsService,
|
||||
App.BluetoothService,
|
||||
Device.RuntimePlatform,
|
||||
() => model.GetIsConnected(),
|
||||
(isConnected) => model.GetConnector(isConnected),
|
||||
model.Geolocation,
|
||||
App.GeolocationServicesContainer.Active,
|
||||
model.LocksServices.Active,
|
||||
model.Polling,
|
||||
(d, obj) => synchronizationContext.Post(d, obj),
|
||||
this);
|
||||
model.SmartDevice,
|
||||
this)
|
||||
{
|
||||
IsReportLevelVerbose = model.IsReportLevelVerbose
|
||||
};
|
||||
}
|
||||
catch (Exception exception)
|
||||
{
|
||||
Log.ForContext<MyBikesPage>().Error("Displaying bikes at station page failed. {Exception}", exception);
|
||||
this.DisplayAlert("Fehler", $"Seite Räder an Station kann nicht angezeigt werden. ${exception.Message}", "OK");
|
||||
await DisplayAlert("Fehler", $"Seite Räder an Station kann nicht angezeigt werden. ${exception.Message}", "OK");
|
||||
return;
|
||||
|
||||
}
|
||||
|
@ -123,6 +129,16 @@ namespace TINK.View.MyBikes
|
|||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary> Displays detailed alert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="accept">Text of accept button.</param>
|
||||
/// <param name="cancel">Text of cancel button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public async Task<bool> DisplayAdvancedAlert(string title, string message, string details, string accept, string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", accept, cancel);
|
||||
|
||||
/// <summary>
|
||||
/// Displays alert message.
|
||||
/// </summary>
|
||||
|
@ -136,14 +152,14 @@ namespace TINK.View.MyBikes
|
|||
return await App.Current.MainPage.DisplayAlert(p_strTitle, p_strMessage, p_strAccept, p_strCancel);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
throw new NotSupportedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
#else
|
||||
/// <summary> Shows a page.</summary>
|
||||
/// <param name="route">Route of the page to show.</param>
|
||||
public async Task ShowPage(string route) => await Shell.Current.GoToAsync(route);
|
||||
#endif
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
|
@ -165,6 +181,10 @@ namespace TINK.View.MyBikes
|
|||
throw new NotSupportedException();
|
||||
}
|
||||
|
||||
#if USCSHARP9
|
||||
public async Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => await Navigation.ShowPopupAsync<FeedbackPopup.Result>(new FeedbackPopup());
|
||||
#else
|
||||
public async Task<IUserFeedback> DisplayUserFeedbackPopup() => await Navigation.ShowPopupAsync<FeedbackPopup.Result>(new FeedbackPopup());
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -3,7 +3,9 @@ using System.Collections.Generic;
|
|||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
||||
|
@ -19,7 +21,11 @@ namespace TINK.View.Root
|
|||
// - switch to login page form bikes at station page if not yet logged in
|
||||
/// </remarks>
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
public partial class RootPage : FlyoutPage, INavigationMasterDetail
|
||||
#else
|
||||
public partial class RootPage : FlyoutPage
|
||||
#endif
|
||||
{
|
||||
public RootPage()
|
||||
{
|
||||
|
@ -35,6 +41,7 @@ namespace TINK.View.Root
|
|||
return;
|
||||
}
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
var detailPage = navigationPage.RootPage as IDetailPage;
|
||||
if (detailPage == null)
|
||||
{
|
||||
|
@ -42,6 +49,7 @@ namespace TINK.View.Root
|
|||
}
|
||||
|
||||
detailPage.NavigationMasterDetail = this;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -70,12 +78,14 @@ namespace TINK.View.Root
|
|||
var page = (Page)Activator.CreateInstance(typeOfPage);
|
||||
page.Title = title;
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
if (page is IDetailPage detailPage)
|
||||
{
|
||||
// Detail page needs reference to perform navigation.
|
||||
// Examples see above in xdoc of class.
|
||||
detailPage.NavigationMasterDetail = this;
|
||||
}
|
||||
#endif
|
||||
|
||||
Detail = new NavigationPage(page);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,9 @@ using System.Text;
|
|||
using System.Threading.Tasks;
|
||||
using TINK.Model;
|
||||
using TINK.Services;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using TINK.View.Themes;
|
||||
using TINK.ViewModel.Root;
|
||||
using Xamarin.Forms;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using TINK.View.Info.BikeInfo;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using TINK.ViewModel.MasterDetail;
|
||||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
|
@ -13,8 +15,12 @@ namespace TINK.View
|
|||
public delegate void ShowPageDelegate(Type p_oType, string p_strTitle = null);
|
||||
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
public partial class MainPage : MasterDetailPage, INavigationMasterDetail
|
||||
{
|
||||
#else
|
||||
public partial class MainPage : MasterDetailPage
|
||||
#endif
|
||||
{
|
||||
public MainPage()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
@ -29,6 +35,7 @@ namespace TINK.View
|
|||
return;
|
||||
}
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
var detailPage = navigationPage.RootPage as IDetailPage;
|
||||
if (detailPage == null)
|
||||
{
|
||||
|
@ -36,6 +43,7 @@ namespace TINK.View
|
|||
}
|
||||
|
||||
detailPage.NavigationMasterDetail = this;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary> Creates and a page an shows it.</summary>
|
||||
|
@ -50,11 +58,13 @@ namespace TINK.View
|
|||
var page = (Page)Activator.CreateInstance(p_oTypeOfPage);
|
||||
page.Title = p_strTitle ?? Helper.GetCaption(p_oTypeOfPage);
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
var l_oPage = page as IDetailPage;
|
||||
if (l_oPage != null)
|
||||
{
|
||||
l_oPage.NavigationMasterDetail = this;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if !BACKSTYLE
|
||||
// When bike info page is shown do not allow to close this carousel before all pages were displayed.
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
|
||||
<ShellContent
|
||||
Title="{x:Static resources:AppResources.MarkingMapPage}"
|
||||
Route="MapPage"
|
||||
ContentTemplate="{DataTemplate mappage:MapPage}">
|
||||
<ShellContent.FlyoutIcon>
|
||||
<FontImageSource Glyph="{StaticResource IconMap}" Color="Black" FontFamily="FA-S" />
|
||||
|
@ -49,6 +50,7 @@
|
|||
<FlyoutItem FlyoutDisplayOptions="AsMultipleItems">
|
||||
<ShellContent
|
||||
Title="{x:Static resources:AppResources.MarkingLogin}"
|
||||
Route="LoginPage"
|
||||
IsVisible="{Binding IsLoginPageVisible}"
|
||||
ContentTemplate="{DataTemplate login:LoginPage}">
|
||||
<ShellContent.FlyoutIcon>
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
<conv:PermissionToVisibleConverter x:Key="PickLockServiceImplementation_Converter" VisibleFlag="PickLockServiceImplementation"/>
|
||||
<conv:PermissionToVisibleConverter x:Key="PickLocationServiceImplementation_Converter" VisibleFlag="PickLocationServiceImplementation"/>
|
||||
<conv:PermissionToVisibleConverter x:Key="PickLoggingLevel_Converter" VisibleFlag="PickLoggingLevel"/>
|
||||
<conv:PermissionToVisibleConverter x:Key="ReportLevel_Converter" VisibleFlag="ReportLevel"/>
|
||||
<conv:PermissionToVisibleConverter x:Key="ShowDiagnostics_Converter" VisibleFlag="ShowDiagnostics"/>
|
||||
<conv:PermissionToVisibleConverter x:Key="SwitchSiteCaching_Converter" VisibleFlag="SwitchNoSiteCaching"/>
|
||||
</ContentPage.Resources>
|
||||
|
@ -176,6 +177,18 @@
|
|||
IsEnabled="{Binding IsLogToExternalFolderVisible}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
<Frame
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource Frame_Converter}}">
|
||||
<!-- Logging -->
|
||||
<StackLayout>
|
||||
<Label
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ReportLevel_Converter}}"
|
||||
Text="Verbose error messages" />
|
||||
<Switch
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource ReportLevel_Converter}}"
|
||||
IsToggled="{Binding IsReportLevelVerbose}"/>
|
||||
</StackLayout>
|
||||
</Frame>
|
||||
<Frame
|
||||
IsVisible="{Binding DebugLevel, Converter={StaticResource Frame_Converter}}">
|
||||
<!-- Display of parameters -->
|
||||
|
|
|
@ -2,7 +2,9 @@
|
|||
using Xamarin.Forms;
|
||||
using Xamarin.Forms.Xaml;
|
||||
using System.Threading.Tasks;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using System;
|
||||
using TINK.Model.Device;
|
||||
using Xamarin.CommunityToolkit.Extensions;
|
||||
|
@ -10,7 +12,11 @@ using Xamarin.CommunityToolkit.Extensions;
|
|||
namespace TINK.View.Settings
|
||||
{
|
||||
[XamlCompilation(XamlCompilationOptions.Compile)]
|
||||
public partial class SettingsPage : ContentPage, IViewService, IDetailPage
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
public partial class SettingsPage : ContentPage, IViewService, IDetailPage
|
||||
#else
|
||||
public partial class SettingsPage : ContentPage, IViewService
|
||||
#endif
|
||||
{
|
||||
/// <summary> Refernce to view model. </summary>
|
||||
SettingsPageViewModel m_oViewModel = null;
|
||||
|
@ -24,6 +30,7 @@ namespace TINK.View.Settings
|
|||
|
||||
m_oViewModel = new SettingsPageViewModel(
|
||||
l_oModel,
|
||||
App.GeolocationServicesContainer,
|
||||
this);
|
||||
|
||||
BindingContext = m_oViewModel;
|
||||
|
@ -43,13 +50,23 @@ namespace TINK.View.Settings
|
|||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
public async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary> Displays detailed alert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="accept">Text of accept button.</param>
|
||||
/// <param name="cancel">Text of cancel button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public async Task<bool> DisplayAdvancedAlert(string title, string message, string details, string accept, string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", accept, cancel);
|
||||
|
||||
/// <summary> Displays alert message.</summary>
|
||||
/// <param name="p_strTitle">Title of message.</param>
|
||||
/// <param name="p_strMessage">Message to display.</param>
|
||||
|
@ -71,12 +88,18 @@ namespace TINK.View.Settings
|
|||
public new async Task<string> DisplayActionSheet(String p_strTitle, String p_strCancel, String destruction, params String[] p_oButtons)
|
||||
=> await base.DisplayActionSheet(p_strTitle, p_strCancel, destruction, p_oButtons);
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
/// <summary>
|
||||
/// Creates and a page an shows it.
|
||||
/// </summary>
|
||||
/// <param name="p_oTypeOfPage">Type of page to show.</param>
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
=> m_oNavigation.ShowPage(p_oType.GetViewType(), p_strTitle);
|
||||
#else
|
||||
/// <summary> Shows a page.</summary>
|
||||
/// <param name="route">Route of the page to show.</param>
|
||||
public async Task ShowPage(string route) => await Shell.Current.GoToAsync(route);
|
||||
#endif
|
||||
|
||||
/// <summary> Pushes a page onto the modal stack. </summary>
|
||||
/// <param name="p_oTypeOfPage">Page to display.</param>
|
||||
|
@ -87,6 +110,7 @@ namespace TINK.View.Settings
|
|||
public Task PopModalAsync()
|
||||
=> throw new NotSupportedException();
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
/// <summary>Delegate to perform navigation.</summary>
|
||||
private INavigationMasterDetail m_oNavigation;
|
||||
|
||||
|
@ -98,6 +122,7 @@ namespace TINK.View.Settings
|
|||
set { m_oNavigation = value; }
|
||||
}
|
||||
|
||||
#endif
|
||||
/// <summary>
|
||||
/// Invoked when pages is closed/ hidden.
|
||||
/// Stops update process.
|
||||
|
@ -118,7 +143,11 @@ namespace TINK.View.Settings
|
|||
public async Task PushAsync(ViewTypes p_oTypeOfPage)
|
||||
=> await Navigation.PushAsync((Page)Activator.CreateInstance(p_oTypeOfPage.GetViewType()));
|
||||
|
||||
#if USCSHARP9
|
||||
public async Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => await Navigation.ShowPopupAsync<FeedbackPopup.Result>(new FeedbackPopup());
|
||||
#else
|
||||
public async Task<IUserFeedback> DisplayUserFeedbackPopup() => await Navigation.ShowPopupAsync<FeedbackPopup.Result>(new FeedbackPopup());
|
||||
#endif
|
||||
|
||||
#if USERFEEDBACKDLG_TRYOUT
|
||||
public async void OnFeedbackClickedAsync(object sender, EventArgs ev)
|
||||
|
|
|
@ -28,13 +28,23 @@ namespace TINK.View.WhatsNew.Agb
|
|||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="cancel">Type of buttons.</param>
|
||||
public new async Task DisplayAdvancedAlert(
|
||||
public async Task DisplayAdvancedAlert(
|
||||
string title,
|
||||
string message,
|
||||
string details,
|
||||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary> Displays detailed alert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="accept">Text of accept button.</param>
|
||||
/// <param name="cancel">Text of cancel button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public async Task<bool> DisplayAdvancedAlert(string title, string message, string details, string accept, string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", accept, cancel);
|
||||
|
||||
/// <summary> Invoked when page is shown. </summary>
|
||||
protected async override void OnAppearing()
|
||||
{
|
||||
|
@ -61,11 +71,19 @@ namespace TINK.View.WhatsNew.Agb
|
|||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
#else
|
||||
/// <summary> Shows a page.</summary>
|
||||
/// <param name="route">Route of the page to show.</param>
|
||||
public async Task ShowPage(string route) => await Shell.Current.GoToAsync(route);
|
||||
#endif
|
||||
|
||||
#if USCSHARP9
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
#else
|
||||
public Task<IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -40,6 +40,16 @@ namespace TINK.View.WhatsNew
|
|||
string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", cancel);
|
||||
|
||||
/// <summary> Displays detailed alert message.</summary>
|
||||
/// <param name="title">Title of message.</param>
|
||||
/// <param name="message">Message to display.</param>
|
||||
/// <param name="details">Detailed error description.</param>
|
||||
/// <param name="accept">Text of accept button.</param>
|
||||
/// <param name="cancel">Text of cancel button.</param>
|
||||
/// <returns>True if user pressed accept.</returns>
|
||||
public async Task<bool> DisplayAdvancedAlert(string title, string message, string details, string accept, string cancel)
|
||||
=> await App.Current.MainPage.DisplayAlert(title, $"{message}\r\nDetails:\r\n{details}", accept, cancel);
|
||||
|
||||
public Task PopModalAsync()
|
||||
{
|
||||
throw new NotImplementedException(); ;
|
||||
|
@ -57,12 +67,20 @@ namespace TINK.View.WhatsNew
|
|||
await Navigation.PushModalAsync((Page)Activator.CreateInstance(p_oTypeOfPage.GetViewType()));
|
||||
}
|
||||
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
public void ShowPage(ViewTypes p_oType, string p_strTitle = null)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
=> throw new NotImplementedException();
|
||||
#else
|
||||
/// <summary> Shows a page.</summary>
|
||||
/// <param name="route">Route of the page to show.</param>
|
||||
public async Task ShowPage(string route) => await Shell.Current.GoToAsync(route);
|
||||
#endif
|
||||
|
||||
#if USCSHARP9
|
||||
public Task<IViewService.IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
#else
|
||||
public Task<IUserFeedback> DisplayUserFeedbackPopup() => throw new NotSupportedException();
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Invoked when pages is closed/ hidden.
|
||||
|
|
|
@ -1,69 +0,0 @@
|
|||
using System.ComponentModel;
|
||||
using Xamarin.Forms;
|
||||
using TINK.Services.CopriApi.ServerUris;
|
||||
using TINK.Model.User.Account;
|
||||
namespace TINK.ViewModel.Contact
|
||||
{
|
||||
public class HelpContactViewModel : INotifyPropertyChanged
|
||||
{
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
/// <summary> Holds value wether site caching is on or off.</summary>
|
||||
bool IsSiteCachingOn { get; }
|
||||
|
||||
/// <summary> Constructs view model.</summary>
|
||||
/// <param name="isSiteCachingOn">Set of user permissions</param>
|
||||
public HelpContactViewModel(
|
||||
string hostName,
|
||||
bool isSiteCachingOn)
|
||||
{
|
||||
HostName = hostName;
|
||||
IsSiteCachingOn = isSiteCachingOn;
|
||||
}
|
||||
|
||||
/// <summary> Holds the name of the host.</summary>
|
||||
private string HostName { get; }
|
||||
|
||||
/// <summary> Called when page is shown. </summary>
|
||||
public async void OnAppearing()
|
||||
{
|
||||
RentBikeText = new HtmlWebViewSource
|
||||
{
|
||||
Html = HostName.GetIsCopri()
|
||||
? ViewModelResourceHelper.GetSource("HtmlResouces.V02.InfoRentBike.html")
|
||||
: await ViewModelHelper.GetSource($"https://{HostName}/{CopriHelper.SHAREE_SILTEFOLDERNAME}/tariff_info.html", IsSiteCachingOn)
|
||||
};
|
||||
|
||||
TypesOfBikesText = new HtmlWebViewSource
|
||||
{
|
||||
Html = HostName.GetIsCopri()
|
||||
? ViewModelResourceHelper.GetSource("HtmlResouces.V02.InfoTypesOfBikes.html")
|
||||
: await ViewModelHelper.GetSource($"https://{HostName}/{CopriHelper.SHAREE_SILTEFOLDERNAME}/bike_info.html", IsSiteCachingOn)
|
||||
};
|
||||
}
|
||||
|
||||
private HtmlWebViewSource rentBikeText;
|
||||
|
||||
private HtmlWebViewSource typesOfBikesText;
|
||||
|
||||
public HtmlWebViewSource RentBikeText
|
||||
{
|
||||
get => rentBikeText;
|
||||
set
|
||||
{
|
||||
rentBikeText = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(RentBikeText)));
|
||||
}
|
||||
}
|
||||
|
||||
public HtmlWebViewSource TypesOfBikesText
|
||||
{
|
||||
get => typesOfBikesText;
|
||||
set
|
||||
{
|
||||
typesOfBikesText = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TypesOfBikesText)));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,7 +15,9 @@ using TINK.View.Root;
|
|||
using TINK.View.Settings;
|
||||
using Xamarin.Forms;
|
||||
using TINK.ViewModel.MasterDetail;
|
||||
#if USEMASTERDETAIL || USEFLYOUT
|
||||
using TINK.View.MasterDetail;
|
||||
#endif
|
||||
using TINK.Services;
|
||||
using TINK.View.Themes;
|
||||
|
||||
|
|
|
@ -87,7 +87,7 @@ namespace TINK.ViewModel.MasterDetail
|
|||
}
|
||||
else if (type == typeof(FeesAndBikesPage))
|
||||
{
|
||||
return "\uf153";
|
||||
return "\uf7d9";
|
||||
}
|
||||
else if (type == typeof(ContactPage))
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue