mirror of
https://dev.azure.com/TeilRad/sharee.bike%20App/_git/Code
synced 2025-04-21 12:36:28 +02:00
Version 3.0.381
This commit is contained in:
parent
f963c0a219
commit
3a363acf3a
1525 changed files with 60589 additions and 125098 deletions
75
SharedBusinessLogic/Model/Settings/GroupFilterSettings.cs
Normal file
75
SharedBusinessLogic/Model/Settings/GroupFilterSettings.cs
Normal file
|
@ -0,0 +1,75 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using ShareeBike.Model;
|
||||
using ShareeBike.Model.Connector.Filter;
|
||||
|
||||
namespace ShareeBike.ViewModel.Settings
|
||||
{
|
||||
public class GroupFilterSettings : IGroupFilterSettings
|
||||
{
|
||||
|
||||
public GroupFilterSettings(IDictionary<string, FilterState> filterDictionary = null)
|
||||
{
|
||||
FilterDictionary = filterDictionary ?? new Dictionary<string, FilterState>();
|
||||
|
||||
Filter = filterDictionary != null
|
||||
? (IGroupFilter)new IntersectGroupFilter(FilterDictionary.Where(x => x.Value == FilterState.On).Select(x => x.Key))
|
||||
: new NullGroupFilter();
|
||||
}
|
||||
|
||||
private IDictionary<string, FilterState> FilterDictionary { get; set; }
|
||||
|
||||
private IGroupFilter Filter { get; }
|
||||
|
||||
/// <summary> Performs filtering on response -group. </summary>
|
||||
public IEnumerable<string> DoFilter(IEnumerable<string> filter = null) => Filter.DoFilter(filter);
|
||||
|
||||
public FilterState this[string key] { get => FilterDictionary[key]; set => FilterDictionary[key] = value; }
|
||||
|
||||
public ICollection<string> Keys => FilterDictionary.Keys;
|
||||
|
||||
public ICollection<FilterState> Values => FilterDictionary.Values;
|
||||
|
||||
public int Count => FilterDictionary.Count;
|
||||
|
||||
public bool IsReadOnly => true;
|
||||
|
||||
public void Add(string key, FilterState value)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void Add(KeyValuePair<string, FilterState> item)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Contains(KeyValuePair<string, FilterState> item) => FilterDictionary.Contains(item);
|
||||
|
||||
public bool ContainsKey(string key) => FilterDictionary.ContainsKey(key);
|
||||
|
||||
public void CopyTo(KeyValuePair<string, FilterState>[] array, int arrayIndex) => FilterDictionary.CopyTo(array, arrayIndex);
|
||||
|
||||
public IEnumerator<KeyValuePair<string, FilterState>> GetEnumerator() => FilterDictionary.GetEnumerator();
|
||||
|
||||
public bool Remove(string key)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public bool Remove(KeyValuePair<string, FilterState> item)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
}
|
||||
|
||||
public bool TryGetValue(string key, out FilterState value) => FilterDictionary.TryGetValue(key, out value);
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator() => FilterDictionary.GetEnumerator();
|
||||
}
|
||||
}
|
11
SharedBusinessLogic/Model/Settings/IGroupFilterSettings.cs
Normal file
11
SharedBusinessLogic/Model/Settings/IGroupFilterSettings.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
using System.Collections.Generic;
|
||||
using ShareeBike.Model;
|
||||
|
||||
namespace ShareeBike.ViewModel.Settings
|
||||
{
|
||||
public interface IGroupFilterSettings : IDictionary<string, FilterState>
|
||||
{
|
||||
/// <summary> Performs filtering on response-group. </summary>
|
||||
IEnumerable<string> DoFilter(IEnumerable<string> filter = null);
|
||||
}
|
||||
}
|
9
SharedBusinessLogic/Model/Settings/IStartupSettings.cs
Normal file
9
SharedBusinessLogic/Model/Settings/IStartupSettings.cs
Normal file
|
@ -0,0 +1,9 @@
|
|||
namespace ShareeBike.Model.Settings
|
||||
{
|
||||
/// <summary> Settings determining the startup behavior of the app. </summary>
|
||||
public interface IStartupSettings
|
||||
{
|
||||
/// <summary> Holds the page to show when apps starts. </summary>
|
||||
ViewTypes StartupPage { get; set; }
|
||||
}
|
||||
}
|
578
SharedBusinessLogic/Model/Settings/JsonSettingsDictionary.cs
Normal file
578
SharedBusinessLogic/Model/Settings/JsonSettingsDictionary.cs
Normal file
|
@ -0,0 +1,578 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
using Serilog.Events;
|
||||
using ShareeBike.Model.Services.CopriApi.ServerUris;
|
||||
using ShareeBike.Services.BluetoothLock;
|
||||
using ShareeBike.Services.Geolocation;
|
||||
using ShareeBike.Settings;
|
||||
using ShareeBike.ViewModel.Map;
|
||||
using ShareeBike.ViewModel.Settings;
|
||||
|
||||
namespace ShareeBike.Model.Settings
|
||||
{
|
||||
public static class JsonSettingsDictionary
|
||||
{
|
||||
/// <summary>Title of the settings file.</summary>
|
||||
public const string SETTINGSFILETITLE = "Setting.Json";
|
||||
|
||||
/// <summary> Key of the app version entry. </summary>
|
||||
public const string APPVERSIONKEY = "AppVersion";
|
||||
|
||||
/// <summary> Key of the app version entry. </summary>
|
||||
public const string SHOWWHATSNEWKEY = "ShowWhatsNew";
|
||||
|
||||
/// <summary> Key of the app version entry. </summary>
|
||||
public const string EXPIRESAFTER = "ExpiresAfter";
|
||||
|
||||
/// <summary> Key of the connect timeout. </summary>
|
||||
public const string CONNECTTIMEOUT = "ConnectTimeout";
|
||||
|
||||
/// <summary> Key of the logging level entry. </summary>
|
||||
public const string MINLOGGINGLEVELKEY = "MinimumLoggingLevel";
|
||||
|
||||
/// <summary> Key of the logging level entry. </summary>
|
||||
public const string ISREPORTLEVELVERBOSEKEY = "IsReportLevelVerbose";
|
||||
|
||||
/// <summary> Key of the center to ... entry. </summary>
|
||||
public const string CENTERMAPTOCURRENTLOCATION = "CenterMapToCurrentLocation";
|
||||
|
||||
/// <summary> Key of the center to ... entry. </summary>
|
||||
public const string STARTUPSETTINGS = "StartupSettings";
|
||||
|
||||
public const string LOGTOEXTERNALFOLDER = "LogToExternalFolder";
|
||||
|
||||
public const string THEMEKEY = "Theme";
|
||||
|
||||
public const string ISSITECACHINGON = "IsSiteCachingOn";
|
||||
|
||||
/// <summary> Gets a nullable value.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get value from.</param>
|
||||
public static T? GetNullableEntry<T>(
|
||||
string keyName,
|
||||
IDictionary<string, string> settingsJSON) where T : struct
|
||||
{
|
||||
if (!settingsJSON.TryGetValue(keyName, out string boolText)
|
||||
|| string.IsNullOrEmpty(boolText))
|
||||
{
|
||||
// File holds no entry.
|
||||
return null;
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<T>(boolText);
|
||||
}
|
||||
|
||||
/// <summary> Gets a value to type class.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get value from.</param>
|
||||
public static T GetEntry<T>(
|
||||
string keyName,
|
||||
IDictionary<string, string> settingsJSON,
|
||||
Func<string, string> legacyValueConverter = null) where T : class
|
||||
{
|
||||
if (string.IsNullOrEmpty(keyName)
|
||||
|| settingsJSON == null
|
||||
|| !settingsJSON.TryGetValue(keyName, out string valueJSON)
|
||||
|| string.IsNullOrEmpty(valueJSON))
|
||||
{
|
||||
// File holds no entry.
|
||||
return null;
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<T>(legacyValueConverter != null
|
||||
? legacyValueConverter(valueJSON)
|
||||
: valueJSON);
|
||||
}
|
||||
|
||||
/// <summary> Sets a nullable.</summary>
|
||||
/// <param name="entry">Entry to add to dictionary.</param>
|
||||
/// <param name="keyName">Key to use for value. </param>
|
||||
/// <param name="targetDictionary">Dictionary to set value to.</param>
|
||||
public static Dictionary<string, string> SetEntry<T>(T entry, string keyName, IDictionary<string, string> targetDictionary)
|
||||
{
|
||||
// Set value.
|
||||
if (targetDictionary == null)
|
||||
throw new Exception($"Writing entry value {keyName} to dictionary failed. Dictionary must not be null.");
|
||||
|
||||
return targetDictionary.Union(new Dictionary<string, string>
|
||||
{
|
||||
{ keyName, JsonConvert.SerializeObject(entry) }
|
||||
}).ToDictionary(key => key.Key, value => value.Value);
|
||||
}
|
||||
|
||||
/// <summary> Sets the timeout to apply when connecting to bluetooth lock.</summary>
|
||||
/// <param name="targetDictionary">Dictionary to write information to.</param>
|
||||
/// <param name="connectTimeout">Connect timeout value.</param>
|
||||
public static Dictionary<string, string> SetConnectTimeout(
|
||||
this IDictionary<string, string> targetDictionary,
|
||||
TimeSpan connectTimeout)
|
||||
{
|
||||
if (targetDictionary == null)
|
||||
throw new Exception("Writing connect timeout info failed. Dictionary must not be null.");
|
||||
|
||||
return targetDictionary.Union(new Dictionary<string, string>
|
||||
{
|
||||
{ CONNECTTIMEOUT, JsonConvert.SerializeObject(connectTimeout, new JavaScriptDateTimeConverter()) }
|
||||
}).ToDictionary(key => key.Key, value => value.Value);
|
||||
}
|
||||
/// <summary> Sets the uri of the active copri host. </summary>
|
||||
/// <param name="settingsJSON">Dictionary holding parameters from JSON.</param>
|
||||
public static Dictionary<string, string> SetCopriHostUri(this IDictionary<string, string> targetDictionary, string p_strNextActiveUriText)
|
||||
{
|
||||
if (targetDictionary == null)
|
||||
throw new Exception("Writing copri host uri to dictionary failed. Dictionary must not be null.");
|
||||
|
||||
return targetDictionary.Union(new Dictionary<string, string>
|
||||
{
|
||||
{ typeof(CopriServerUriList).ToString(), JsonConvert.SerializeObject(p_strNextActiveUriText) },
|
||||
}).ToDictionary(key => key.Key, value => value.Value);
|
||||
}
|
||||
|
||||
/// <summary> Gets the timeout to apply when connecting to bluetooth lock.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get information from.</param>
|
||||
/// <returns>Connect timeout value.</returns>
|
||||
public static TimeSpan? GetConnectTimeout(Dictionary<string, string> settingsJSON)
|
||||
{
|
||||
if (!settingsJSON.TryGetValue(CONNECTTIMEOUT, out string connectTimeout)
|
||||
|| string.IsNullOrEmpty(connectTimeout))
|
||||
{
|
||||
// File holds no entry.
|
||||
return null;
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<TimeSpan>(connectTimeout, new JavaScriptDateTimeConverter());
|
||||
}
|
||||
/// <summary> Gets the logging level.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get logging level from.</param>
|
||||
/// <returns>Logging level</returns>
|
||||
public static Uri GetCopriHostUri(this IDictionary<string, string> settingsJSON)
|
||||
{
|
||||
// Get uri of copri server.
|
||||
if (!settingsJSON.TryGetValue(typeof(CopriServerUriList).ToString(), out string uriText)
|
||||
|| string.IsNullOrEmpty(uriText))
|
||||
{
|
||||
// File holds no entry.
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
return JsonConvert.DeserializeObject<Uri>(uriText);
|
||||
}
|
||||
|
||||
/// <summary> Sets the version of the app. </summary>
|
||||
/// <param name="settingsJSON">Dictionary holding parameters from JSON.</param>
|
||||
public static Dictionary<string, string> SetAppVersion(
|
||||
this IDictionary<string, string> targetDictionary,
|
||||
Version appVersion)
|
||||
{
|
||||
if (targetDictionary == null)
|
||||
throw new Exception("Writing app version to dictionary failed. Dictionary must not be null.");
|
||||
|
||||
return targetDictionary.Union(new Dictionary<string, string>
|
||||
{
|
||||
{APPVERSIONKEY , JsonConvert.SerializeObject(appVersion, new VersionConverter()) },
|
||||
}).ToDictionary(key => key.Key, value => value.Value);
|
||||
}
|
||||
|
||||
/// <summary> Gets the app versions.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get logging level from.</param>
|
||||
/// <returns>Logging level</returns>
|
||||
public static Version GetAppVersion(this IDictionary<string, string> settingsJSON)
|
||||
{
|
||||
// Get the version of the app which wrote the settings file.
|
||||
if (!settingsJSON.TryGetValue(APPVERSIONKEY, out string appVersion)
|
||||
|| string.IsNullOrEmpty(appVersion))
|
||||
{
|
||||
// File holds no entry.
|
||||
return null;
|
||||
}
|
||||
|
||||
return appVersion.TrimStart().StartsWith("\"")
|
||||
? JsonConvert.DeserializeObject<Version>(appVersion, new VersionConverter())
|
||||
: Version.Parse(appVersion); // Format used up to version 3.0.0.115
|
||||
}
|
||||
|
||||
|
||||
/// <summary> Sets whether polling is on or off and the period if polling is on. </summary>
|
||||
/// <param name="settingsJSON">Dictionary to write entries to.</param>
|
||||
public static Dictionary<string, string> SetPollingParameters(
|
||||
this IDictionary<string, string> targetDictionary,
|
||||
PollingParameters pollingParameter)
|
||||
{
|
||||
if (targetDictionary == null)
|
||||
throw new Exception("Writing polling parameters to dictionary failed. Dictionary must not be null.");
|
||||
|
||||
return targetDictionary.Union(new Dictionary<string, string>
|
||||
{
|
||||
{ $"{typeof(PollingParameters).Name}_{typeof(TimeSpan).Name}", JsonConvert.SerializeObject(pollingParameter.Periode) },
|
||||
{ $"{typeof(PollingParameters).Name}_{typeof(bool).Name}", JsonConvert.SerializeObject(pollingParameter.IsActivated) },
|
||||
}).ToDictionary(key => key.Key, value => value.Value);
|
||||
}
|
||||
|
||||
/// <summary> Get whether polling is on or off and the period if polling is on. </summary>
|
||||
/// <param name="settingsJSON">Dictionary holding parameters from JSON.</param>
|
||||
/// <returns>Polling parameters.</returns>
|
||||
public static PollingParameters GetPollingParameters(this IDictionary<string, string> settingsJSON)
|
||||
{
|
||||
// Check if dictionary contains entry for period.
|
||||
if (settingsJSON.TryGetValue($"{typeof(PollingParameters).Name}_{typeof(TimeSpan).Name}", out string period)
|
||||
&& settingsJSON.TryGetValue($"{typeof(PollingParameters).Name}_{typeof(bool).Name}", out string active)
|
||||
&& !string.IsNullOrEmpty(period)
|
||||
&& !string.IsNullOrEmpty(active))
|
||||
{
|
||||
return new PollingParameters(
|
||||
JsonConvert.DeserializeObject<TimeSpan>(period),
|
||||
JsonConvert.DeserializeObject<bool>(active));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary> Saves object to file. </summary>
|
||||
/// <param name="settingsList">Settings to save.</param>
|
||||
public static void Serialize(string settingsFileFolder, IDictionary<string, string> settingsList)
|
||||
{
|
||||
// Save settings to file.
|
||||
var l_oText = JsonConvert.SerializeObject(settingsList, Formatting.Indented);
|
||||
var l_oFolder = settingsFileFolder;
|
||||
System.IO.File.WriteAllText($"{l_oFolder}{System.IO.Path.DirectorySeparatorChar}{SETTINGSFILETITLE}", l_oText);
|
||||
}
|
||||
|
||||
/// <summary> Gets ShareeBike app settings form xml- file. </summary>
|
||||
/// <param name="settingsDirectory">Directory to read settings from.</param>
|
||||
/// <returns>Dictionary of settings.</returns>
|
||||
public static Dictionary<string, string> Deserialize(string settingsDirectory)
|
||||
{
|
||||
var fileName = $"{settingsDirectory}{System.IO.Path.DirectorySeparatorChar}{SETTINGSFILETITLE}";
|
||||
|
||||
if (!System.IO.File.Exists(fileName))
|
||||
{
|
||||
// File is empty. Nothing to read.
|
||||
return new Dictionary<string, string>(); ;
|
||||
}
|
||||
|
||||
var jsonFile = System.IO.File.ReadAllText(fileName);
|
||||
|
||||
if (string.IsNullOrEmpty(jsonFile))
|
||||
{
|
||||
// File is empty. Nothing to read.
|
||||
return new Dictionary<string, string>();
|
||||
}
|
||||
|
||||
// Load setting file.
|
||||
return JsonConvert.DeserializeObject<Dictionary<string, string>>(jsonFile);
|
||||
}
|
||||
|
||||
/// <summary> Gets the logging level.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get logging level from.</param>
|
||||
/// <returns>Logging level.</returns>
|
||||
public static LogEventLevel? GetMinimumLoggingLevel(
|
||||
Dictionary<string, string> settingsJSON)
|
||||
{
|
||||
// Get logging level.
|
||||
if (!settingsJSON.TryGetValue(MINLOGGINGLEVELKEY, out string level)
|
||||
|| string.IsNullOrEmpty(level))
|
||||
{
|
||||
// File holds no entry.
|
||||
return null;
|
||||
}
|
||||
|
||||
return (LogEventLevel)int.Parse(JsonConvert.DeserializeObject<string>(level));
|
||||
}
|
||||
|
||||
/// <summary> Gets a value indicating whether report level is verbose or not.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get value from.</param>
|
||||
public static bool? GetIsReportLevelVerbose(Dictionary<string, string> settingsJSON) => GetNullableEntry<bool>(ISREPORTLEVELVERBOSEKEY, settingsJSON);
|
||||
|
||||
/// <summary> Sets a value indicating whether report level is verbose or not.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get value from.</param>
|
||||
public static Dictionary<string, string> SetIsReportLevelVerbose(this IDictionary<string, string> targetDictionary, bool isReportLevelVerbose)
|
||||
=> SetEntry(isReportLevelVerbose, ISREPORTLEVELVERBOSEKEY, targetDictionary);
|
||||
|
||||
|
||||
/// <summary> Sets the logging level.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get logging level from.</param>
|
||||
public static Dictionary<string, string> SetMinimumLoggingLevel(this IDictionary<string, string> targetDictionary, LogEventLevel level)
|
||||
{
|
||||
// Set logging level.
|
||||
if (targetDictionary == null)
|
||||
throw new Exception("Writing logging level to dictionary failed. Dictionary must not be null.");
|
||||
|
||||
return targetDictionary.Union(new Dictionary<string, string>
|
||||
{
|
||||
{ MINLOGGINGLEVELKEY, JsonConvert.SerializeObject((int)level) }
|
||||
}).ToDictionary(key => key.Key, value => value.Value);
|
||||
}
|
||||
|
||||
/// <summary> Gets the version of app when whats new was shown.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get logging level from.</param>
|
||||
/// <returns>Version of the app.</returns>
|
||||
public static Version GetWhatsNew(Dictionary<string, string> settingsJSON)
|
||||
{
|
||||
// Get logging level.
|
||||
if (!settingsJSON.TryGetValue(SHOWWHATSNEWKEY, out string whatsNewVersion)
|
||||
|| string.IsNullOrEmpty(whatsNewVersion))
|
||||
{
|
||||
// File holds no entry.
|
||||
return null;
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<Version>(whatsNewVersion, new VersionConverter());
|
||||
}
|
||||
|
||||
/// <summary> Sets the version of app when whats new was shown.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get information from.</param>
|
||||
public static Dictionary<string, string> SetWhatsNew(this IDictionary<string, string> targetDictionary, Version appVersion)
|
||||
{
|
||||
// Set logging level.
|
||||
if (targetDictionary == null)
|
||||
throw new Exception("Writing WhatsNew info failed. Dictionary must not be null.");
|
||||
|
||||
return targetDictionary.Union(new Dictionary<string, string>
|
||||
{
|
||||
{ SHOWWHATSNEWKEY, JsonConvert.SerializeObject(appVersion, new VersionConverter()) }
|
||||
}).ToDictionary(key => key.Key, value => value.Value);
|
||||
}
|
||||
|
||||
/// <summary> Gets the expires after value.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get expires after value from.</param>
|
||||
/// <returns>Expires after value.</returns>
|
||||
public static TimeSpan? GetExpiresAfter(Dictionary<string, string> settingsJSON)
|
||||
{
|
||||
if (!settingsJSON.TryGetValue(EXPIRESAFTER, out string expiresAfter)
|
||||
|| string.IsNullOrEmpty(expiresAfter))
|
||||
{
|
||||
// File holds no entry.
|
||||
return null;
|
||||
}
|
||||
|
||||
return JsonConvert.DeserializeObject<TimeSpan>(expiresAfter, new JavaScriptDateTimeConverter());
|
||||
}
|
||||
|
||||
/// <summary> Sets the expiration time.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to write information to.</param>
|
||||
public static Dictionary<string, string> SetExpiresAfter(this IDictionary<string, string> targetDictionary, TimeSpan expiresAfter)
|
||||
{
|
||||
if (targetDictionary == null)
|
||||
throw new Exception("Writing ExpiresAfter info failed. Dictionary must not be null.");
|
||||
|
||||
return targetDictionary.Union(new Dictionary<string, string>
|
||||
{
|
||||
{ EXPIRESAFTER, JsonConvert.SerializeObject(expiresAfter, new JavaScriptDateTimeConverter()) }
|
||||
}).ToDictionary(key => key.Key, value => value.Value);
|
||||
}
|
||||
|
||||
/// <summary> Sets the active lock service name. </summary>
|
||||
/// <param name="targetDictionary">Dictionary holding parameters from JSON.</param>
|
||||
public static Dictionary<string, string> SetActiveLockService(this IDictionary<string, string> targetDictionary, string activeLockService)
|
||||
{
|
||||
if (targetDictionary == null)
|
||||
throw new Exception("Writing active lock service name to dictionary failed. Dictionary must not be null.");
|
||||
|
||||
return targetDictionary.Union(new Dictionary<string, string>
|
||||
{
|
||||
{ typeof(ILocksService).Name, activeLockService },
|
||||
}).ToDictionary(key => key.Key, value => value.Value);
|
||||
}
|
||||
|
||||
/// <summary> Gets the active lock service name.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get logging level from.</param>
|
||||
/// <returns>Active lock service name.</returns>
|
||||
public static string GetActiveLockService(this IDictionary<string, string> settingsJSON)
|
||||
{
|
||||
// Get uri of copri server.
|
||||
if (!settingsJSON.TryGetValue(typeof(ILocksService).Name, out string activeLockService)
|
||||
|| string.IsNullOrEmpty(activeLockService))
|
||||
{
|
||||
// File holds no entry.
|
||||
return null;
|
||||
}
|
||||
|
||||
if (activeLockService == "ShareeBike.Services.BluetoothLock.BLE.LockItByScanService")
|
||||
{
|
||||
// Name of this service was switched.
|
||||
return typeof(ShareeBike.Services.BluetoothLock.BLE.LockItByScanServicePolling).FullName;
|
||||
}
|
||||
|
||||
return activeLockService;
|
||||
}
|
||||
|
||||
/// <summary> Sets the active Geolocation service name. </summary>
|
||||
/// <param name="targetDictionary">Dictionary holding parameters from JSON.</param>
|
||||
public static Dictionary<string, string> SetActiveGeolocationService(
|
||||
this IDictionary<string, string> targetDictionary,
|
||||
string activeGeolocationService)
|
||||
{
|
||||
if (targetDictionary == null)
|
||||
throw new Exception("Writing active geolocation service name to dictionary failed. Dictionary must not be null.");
|
||||
|
||||
return targetDictionary.Union(new Dictionary<string, string>
|
||||
{
|
||||
{ typeof(IGeolocationService).Name, activeGeolocationService },
|
||||
}).ToDictionary(key => key.Key, value => value.Value);
|
||||
}
|
||||
|
||||
/// <summary> Gets the active Geolocation service name.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get name of geolocation service from.</param>
|
||||
/// <returns>Active lock service name.</returns>
|
||||
public static string GetActiveGeolocationService(this IDictionary<string, string> settingsJSON)
|
||||
{
|
||||
// Get uri of copri server.
|
||||
if (!settingsJSON.TryGetValue(typeof(IGeolocationService).Name, out string activeGeolocationService)
|
||||
|| string.IsNullOrEmpty(activeGeolocationService))
|
||||
{
|
||||
// File holds no entry.
|
||||
return null;
|
||||
}
|
||||
|
||||
return activeGeolocationService;
|
||||
}
|
||||
|
||||
/// <summary> Gets a value indicating whether to center the map to location or not.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get value from.</param>
|
||||
public static bool? GetCenterMapToCurrentLocation(Dictionary<string, string> settingsJSON) => GetNullableEntry<bool>(CENTERMAPTOCURRENTLOCATION, settingsJSON);
|
||||
|
||||
/// <summary> Sets a value indicating whether to center the map to location or not.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get value from.</param>
|
||||
public static Dictionary<string, string> SetCenterMapToCurrentLocation(this IDictionary<string, string> targetDictionary, bool centerMapToCurrentLocation)
|
||||
=> SetEntry(centerMapToCurrentLocation, CENTERMAPTOCURRENTLOCATION, targetDictionary);
|
||||
|
||||
/// <summary> Gets whether to store logging data on SD card or not.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get value from.</param>
|
||||
public static bool? GetLogToExternalFolder(Dictionary<string, string> settingsJSON) => GetNullableEntry<bool>(LOGTOEXTERNALFOLDER, settingsJSON);
|
||||
|
||||
/// <summary> Gets full class name of active theme.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get value from.</param>
|
||||
public static string GetActiveTheme(Dictionary<string, string> settingsJSON)
|
||||
=> GetEntry<string>(THEMEKEY, settingsJSON, (value) =>
|
||||
{
|
||||
if (value == JsonConvert.SerializeObject(typeof(Themes.LastenradBayern).FullName))
|
||||
{
|
||||
return JsonConvert.SerializeObject(ShareeBike.Services.ThemeNS.ThemeSet.LastenradBayern.ToString());
|
||||
}
|
||||
else if (value == JsonConvert.SerializeObject(typeof(Themes.ShareeBike).FullName))
|
||||
{
|
||||
return JsonConvert.SerializeObject(ShareeBike.Services.ThemeNS.ThemeSet.ShareeBike.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
return value;
|
||||
}
|
||||
});
|
||||
|
||||
/// <summary> Gets a value indicating whether site caching is on or off.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get value from.</param>
|
||||
public static bool? GetIsSiteCachingOn(Dictionary<string, string> settingsJSON) => GetNullableEntry<bool>(ISSITECACHINGON, settingsJSON);
|
||||
|
||||
/// <summary> Sets whether to store logging data on SD card or not.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to write value to.</param>
|
||||
public static Dictionary<string, string> SetLogToExternalFolder(this IDictionary<string, string> targetDictionary, bool useSdCard) => SetEntry(useSdCard, LOGTOEXTERNALFOLDER, targetDictionary);
|
||||
|
||||
/// <summary> Sets active theme.</summary>
|
||||
/// <param name="targetDictionary">Dictionary to set value to.</param>
|
||||
public static Dictionary<string, string> SetActiveTheme(
|
||||
this IDictionary<string, string> targetDictionary,
|
||||
string theme)
|
||||
=> SetEntry(theme, THEMEKEY, targetDictionary);
|
||||
|
||||
/// <summary> Sets whether site caching is on or off.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to get value from.</param>
|
||||
public static Dictionary<string, string> SetIsSiteCachingOn(this IDictionary<string, string> targetDictionary, bool useSdCard) => SetEntry(useSdCard, ISSITECACHINGON, targetDictionary);
|
||||
|
||||
/// <summary> Gets the map page filter. </summary>
|
||||
/// <param name="settings">Settings object to load from.</param>
|
||||
public static IGroupFilterMapPage GetGroupFilterMapPage(this IDictionary<string, string> settings)
|
||||
{
|
||||
var keyName = "FilterCollection_MapPageFilter";
|
||||
if (settings == null || !settings.ContainsKey(keyName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
return new GroupFilterMapPage(JsonConvert.DeserializeObject<IDictionary<string, FilterState>>(settings[keyName]));
|
||||
}
|
||||
|
||||
public static IDictionary<string, string> SetGroupFilterMapPage(
|
||||
this IDictionary<string, string> settings,
|
||||
IDictionary<string, FilterState> filterCollection)
|
||||
{
|
||||
if (settings == null
|
||||
|| filterCollection == null
|
||||
|| filterCollection.Count < 1)
|
||||
{
|
||||
return settings;
|
||||
}
|
||||
|
||||
settings["FilterCollection_MapPageFilter"] = JsonConvert.SerializeObject(filterCollection);
|
||||
return settings;
|
||||
}
|
||||
|
||||
/// <summary> Gets the settings filter. </summary>
|
||||
/// <param name="settings">Settings object to load from.</param>
|
||||
public static IGroupFilterSettings GetGoupFilterSettings(this IDictionary<string, string> settings)
|
||||
{
|
||||
var keyName = "FilterCollection";
|
||||
if (settings == null || !settings.ContainsKey(keyName))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var legacyFilterCollection = new GroupFilterSettings(JsonConvert.DeserializeObject<IDictionary<string, FilterState>>(settings[keyName]));
|
||||
|
||||
// Process legacy entries.
|
||||
var updatedFilterCollection = legacyFilterCollection.Where(x => x.Key.ToUpper() != "TINK.SMS" && x.Key.ToUpper() != "TINK.COPRI").ToDictionary(x => x.Key, x => x.Value);
|
||||
if (legacyFilterCollection.Count() <= updatedFilterCollection.Count())
|
||||
{
|
||||
// No legacy entries "INK.SMS" or "ShareeBike.COPRI" found.
|
||||
return legacyFilterCollection;
|
||||
}
|
||||
|
||||
var list = updatedFilterCollection.ToList();
|
||||
|
||||
updatedFilterCollection.Add(
|
||||
"TINK",
|
||||
legacyFilterCollection.Any(x => x.Key.ToUpper() == "TINK.COPRI") ? legacyFilterCollection.FirstOrDefault(x => x.Key.ToUpper() == "TINK.COPRI").Value : FilterState.Off);
|
||||
|
||||
return new GroupFilterSettings(updatedFilterCollection);
|
||||
}
|
||||
|
||||
public static IDictionary<string, string> SetGroupFilterSettings(
|
||||
this IDictionary<string, string> settings,
|
||||
IDictionary<string, FilterState> filterCollection)
|
||||
{
|
||||
if (settings == null
|
||||
|| filterCollection == null
|
||||
|| filterCollection.Count < 1)
|
||||
{
|
||||
return settings;
|
||||
}
|
||||
|
||||
settings["FilterCollection"] = JsonConvert.SerializeObject(filterCollection);
|
||||
return settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the startup settings from dictionary.
|
||||
/// </summary>
|
||||
/// <param name="settings">Settings object to load from.</param>
|
||||
public static StartupSettings GetStartupSettings(this IDictionary<string, string> settingsJSON)
|
||||
=> GetEntry<StartupSettings>(STARTUPSETTINGS, settingsJSON) ?? new StartupSettings();
|
||||
|
||||
/// <summary> Sets the startup settings.</summary>
|
||||
/// <param name="settingsJSON">Dictionary to write value to.</param>
|
||||
public static IDictionary<string, string> SetStartupSettings(
|
||||
this IDictionary<string, string> settingsJSON,
|
||||
IStartupSettings startupSettings)
|
||||
{
|
||||
if (settingsJSON == null
|
||||
|| startupSettings == null)
|
||||
{
|
||||
return settingsJSON;
|
||||
}
|
||||
|
||||
settingsJSON[STARTUPSETTINGS] = JsonConvert.SerializeObject(startupSettings);
|
||||
return settingsJSON;
|
||||
}
|
||||
}
|
||||
}
|
100
SharedBusinessLogic/Model/Settings/PollingParameters.cs
Normal file
100
SharedBusinessLogic/Model/Settings/PollingParameters.cs
Normal file
|
@ -0,0 +1,100 @@
|
|||
using System;
|
||||
|
||||
namespace ShareeBike.Settings
|
||||
{
|
||||
/// <summary> Holds polling parameters.</summary>
|
||||
public sealed class PollingParameters : IEquatable<PollingParameters>
|
||||
{
|
||||
/// <summary> Holds default polling parameters. </summary>
|
||||
public static PollingParameters Default { get; } = new PollingParameters(
|
||||
new TimeSpan(0, 0, 0, 60 /*secs*/, 0), // Default polling interval. Was 10 secs up to 3.0.357.
|
||||
true);
|
||||
|
||||
/// <summary> Holds polling parameters which represent polling off (empty polling object). </summary>
|
||||
public static PollingParameters NoPolling { get; } = new PollingParameters(
|
||||
TimeSpan.MaxValue,// Very long intervall which should never be used because polling IsActivated property is set to false.
|
||||
false);
|
||||
|
||||
/// <summary> Constructs a polling parameter object. </summary>
|
||||
/// <param name="period">Polling period.</param>
|
||||
/// <param name="activated">True if polling is activated.</param>
|
||||
public PollingParameters(TimeSpan period, bool activated)
|
||||
{
|
||||
Periode = period; // Can not be null because is a struct.
|
||||
IsActivated = activated;
|
||||
}
|
||||
|
||||
/// <summary>Holds the polling period.</summary>
|
||||
public TimeSpan Periode { get; }
|
||||
|
||||
/// <summary> Holds value whether polling is activated or not.</summary>
|
||||
public bool IsActivated { get; }
|
||||
|
||||
/// <summary> Checks equallity.</summary>
|
||||
/// <param name="other">Object to compare with.</param>
|
||||
/// <returns>True if objects are equal.</returns>
|
||||
public bool Equals(PollingParameters other)
|
||||
{
|
||||
return this == other;
|
||||
}
|
||||
|
||||
/// <summary> Checks equallity.</summary>
|
||||
/// <param name="obj">Object to compare with.</param>
|
||||
/// <returns>True if objects are equal.</returns>
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var l_oParameters = obj as PollingParameters;
|
||||
if (l_oParameters == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return this == l_oParameters;
|
||||
}
|
||||
|
||||
/// <summary> Gets the has code of object.</summary>
|
||||
/// <returns></returns>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Periode.GetHashCode() ^ IsActivated.GetHashCode();
|
||||
}
|
||||
|
||||
/// <summary> Gets the string representation of the object.</summary>
|
||||
/// <returns></returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return $"Polling is on={IsActivated}, polling interval={Periode.TotalSeconds}[sec].";
|
||||
}
|
||||
|
||||
/// <summary>Defines equality of thwo polling parameter objects.</summary>
|
||||
/// <param name="p_oSource">First object to compare.</param>
|
||||
/// <param name="p_oTarget">Second object to compare.</param>
|
||||
/// <returns>True if objects are equal</returns>
|
||||
public static bool operator ==(PollingParameters p_oSource, PollingParameters p_oTarget)
|
||||
{
|
||||
if (p_oSource is null && p_oTarget is null)
|
||||
{
|
||||
// Both object are null
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p_oSource is null ^ p_oTarget is null)
|
||||
{
|
||||
// Only one object is null.
|
||||
return false;
|
||||
}
|
||||
|
||||
return p_oSource.Periode == p_oTarget.Periode
|
||||
&& p_oSource.IsActivated == p_oTarget.IsActivated;
|
||||
}
|
||||
|
||||
/// <summary>Defines equality of thwo polling parameter objects.</summary>
|
||||
/// <param name="p_oSource">First object to compare.</param>
|
||||
/// <param name="p_oTarget">Second object to compare.</param>
|
||||
/// <returns>True if objects are equal</returns>
|
||||
public static bool operator !=(PollingParameters p_oSource, PollingParameters p_oTarget)
|
||||
{
|
||||
return (p_oSource == p_oTarget) == false;
|
||||
}
|
||||
}
|
||||
}
|
128
SharedBusinessLogic/Model/Settings/Settings.cs
Normal file
128
SharedBusinessLogic/Model/Settings/Settings.cs
Normal file
|
@ -0,0 +1,128 @@
|
|||
using System;
|
||||
using Serilog.Events;
|
||||
using ShareeBike.Services.BluetoothLock;
|
||||
using ShareeBike.Services.CopriApi.ServerUris;
|
||||
using ShareeBike.Services.Geolocation;
|
||||
using ShareeBike.Settings;
|
||||
using ShareeBike.ViewModel.Map;
|
||||
using ShareeBike.ViewModel.Settings;
|
||||
|
||||
|
||||
namespace ShareeBike.Model.Settings
|
||||
{
|
||||
/// <summary> Holds settings which are persisted.</summary>
|
||||
public class Settings
|
||||
{
|
||||
public const LogEventLevel DEFAULTLOGGINLEVEL = LogEventLevel.Information;
|
||||
|
||||
public const bool DEFAULTREPOTLEVEL = false;
|
||||
|
||||
/// <summary> Gets the type of the default geolocation service. </summary>
|
||||
/// <remarks> Switched from GeolocationService (GeolocationAccuracyMediumService) to GeolocationAccuracyHighService in app version 3.0.290.</remarks>
|
||||
public static Type DefaultLocationService => typeof(GeolocationAccuracyHighService);
|
||||
|
||||
// Default value of the expires after entry. Controls the expiration time of the cache values.
|
||||
private TimeSpan DEFAULTEXPIRESAFTER = TimeSpan.FromSeconds(1);
|
||||
|
||||
/// <summary> Constructs settings object. </summary>
|
||||
/// <param name="groupFilterMapPage">filter which is applied on the map view. Either Cargo or Citybike stations are displayed.</param>
|
||||
/// <param name="groupFilterSettings"></param>
|
||||
/// <param name="startupSettings">Settings determining the startup behavior of the app.</param>
|
||||
/// <param name="activeUri"></param>
|
||||
/// <param name="pollingParameters"></param>
|
||||
/// <param name="minimumLogEventLevel">Minimum logging level to be applied.</param>
|
||||
/// <param name="isReportLevelVerbose">True if logging level is verbose.</param>
|
||||
/// <param name="expiresAfter">Holds the expires after value.</param>
|
||||
/// <param name="activeLockService">Gets the name of the lock service to use.</param>
|
||||
/// <param name="connectTimeout">Timeout to apply when connecting to bluetooth lock</param>
|
||||
/// <param name="activeTheme">Full class name of active app theme.</param>
|
||||
public Settings(
|
||||
IGroupFilterMapPage groupFilterMapPage = null,
|
||||
IGroupFilterSettings groupFilterSettings = null,
|
||||
IStartupSettings startupSettings = null,
|
||||
Uri activeUri = null,
|
||||
PollingParameters pollingParameters = null,
|
||||
LogEventLevel? minimumLogEventLevel = null,
|
||||
bool? isReportLevelVerbose = null,
|
||||
TimeSpan? expiresAfter = null,
|
||||
string activeLockService = null,
|
||||
TimeSpan? connectTimeout = null,
|
||||
string activeGeolocationService = null,
|
||||
bool? centerMapToCurrentLocation = null,
|
||||
Xamarin.Forms.GoogleMaps.MapSpan mapSpan = null,
|
||||
bool? logToExternalFolder = null,
|
||||
bool? isSiteCachingOn = null,
|
||||
string activeTheme = null)
|
||||
{
|
||||
GroupFilterMapPage = groupFilterMapPage ?? new GroupFilterMapPage(); // Default behavior: No filtering.
|
||||
GroupFilterSettings = groupFilterSettings ?? new GroupFilterSettings(); // Default behavior: No filtering.
|
||||
StartupSettings = startupSettings ?? new StartupSettings();
|
||||
ActiveUri = GetActiveUri(activeUri);
|
||||
PollingParameters = pollingParameters ?? PollingParameters.Default;
|
||||
MinimumLogEventLevel = minimumLogEventLevel ?? DEFAULTLOGGINLEVEL;
|
||||
IsReportLevelVerbose = isReportLevelVerbose ?? DEFAULTREPOTLEVEL;
|
||||
ExpiresAfter = expiresAfter ?? DEFAULTEXPIRESAFTER;
|
||||
ActiveLockService = activeLockService ?? LocksServicesContainerMutable.DefaultLocksservice;
|
||||
ConnectTimeout = connectTimeout ?? new TimeSpan(0, 0, TimeOutProvider.DEFAULT_BLUETOOTHCONNECT_TIMEOUTSECONDS); // Try one sec. to connect.
|
||||
ActiveGeolocationService = activeGeolocationService ?? DefaultLocationService.FullName;
|
||||
CenterMapToCurrentLocation = centerMapToCurrentLocation ?? GetCenterMapToCurrentLocation(activeUri);
|
||||
MapSpan = mapSpan;
|
||||
LogToExternalFolder = logToExternalFolder ?? false;
|
||||
IsSiteCachingOn = isSiteCachingOn ?? true;
|
||||
ActiveTheme = activeTheme ?? typeof(Themes.ShareeBike).Name;
|
||||
}
|
||||
|
||||
/// <summary> Holds the filter which is applied on the map view. Either Cargo or Citybike stations are displayed. </summary>
|
||||
public IGroupFilterMapPage GroupFilterMapPage { get; }
|
||||
|
||||
/// <summary> Holds the filters loaded from settings. </summary>
|
||||
public IGroupFilterSettings GroupFilterSettings { get; }
|
||||
|
||||
/// <summary> Holds the settings determining app startup behavior. </summary>
|
||||
public IStartupSettings StartupSettings { get; }
|
||||
|
||||
/// <summary> Holds the uri to connect to. </summary>
|
||||
public Uri ActiveUri { get; }
|
||||
|
||||
/// <summary> Holds the polling parameters. </summary>
|
||||
public PollingParameters PollingParameters { get; }
|
||||
|
||||
/// <summary> Gets the minimum logging level. </summary>
|
||||
public LogEventLevel MinimumLogEventLevel { get; }
|
||||
|
||||
/// <summary> Gets the expires after value.</summary>
|
||||
public TimeSpan ExpiresAfter { get; }
|
||||
|
||||
/// <summary> Gets the lock service to use.</summary>
|
||||
public string ActiveLockService { get; private set; }
|
||||
|
||||
/// <summary> Timeout to apply when connecting to bluetooth lock.</summary>
|
||||
public TimeSpan ConnectTimeout { get; }
|
||||
|
||||
/// <summary> Gets the geolocation service to use.</summary>
|
||||
public string ActiveGeolocationService { get; }
|
||||
|
||||
/// <summary> True if map is centered to current position, false if not to center map.</summary>
|
||||
public bool CenterMapToCurrentLocation { get; }
|
||||
|
||||
/// <summary> Holds the map area to display. </summary>
|
||||
public Xamarin.Forms.GoogleMaps.MapSpan MapSpan { get; }
|
||||
|
||||
public bool LogToExternalFolder { get; }
|
||||
|
||||
public bool IsSiteCachingOn { get; }
|
||||
|
||||
public string ActiveTheme { get; }
|
||||
|
||||
/// <summary> Gets a value indicating whether reporting level is verbose or not.</summary>
|
||||
public bool IsReportLevelVerbose { get; }
|
||||
|
||||
public static Uri GetActiveUri(Uri activeUri) => activeUri ?? Services.CopriApi.ServerUris.CopriServerUriList.DefaultActiveUri;
|
||||
|
||||
public static bool GetCenterMapToCurrentLocation(Uri activeUri)
|
||||
{
|
||||
// ShareeBike does not require access to current location. Deactivate center map to current location for this reason.
|
||||
return !GetActiveUri(activeUri).Host.GetIsCopri();
|
||||
}
|
||||
}
|
||||
}
|
11
SharedBusinessLogic/Model/Settings/StartupSettings.cs
Normal file
11
SharedBusinessLogic/Model/Settings/StartupSettings.cs
Normal file
|
@ -0,0 +1,11 @@
|
|||
namespace ShareeBike.Model.Settings
|
||||
{
|
||||
/// <summary> Settings determining the startup behavior of the app. </summary>
|
||||
public class StartupSettings : IStartupSettings
|
||||
{
|
||||
public static ViewTypes DefaultStartupPage => ViewTypes.MapPage;
|
||||
|
||||
/// <summary> Holds the page to show when apps starts. </summary>
|
||||
public ViewTypes StartupPage { get; set; } = DefaultStartupPage;
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue