Version 3.0.255

This commit is contained in:
Oliver Hauff 2021-11-07 19:42:59 +01:00
parent db9c288584
commit 5a26bf273b
1495 changed files with 159465 additions and 5060 deletions

View file

@ -0,0 +1,196 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using TINK.Services.CopriApi.ServerUris;
using TINK.View;
using TINK.View.Account;
using TINK.View.Contact;
using TINK.View.Info;
using TINK.View.Login;
using TINK.View.Map;
using TINK.View.FindBike;
using TINK.View.MyBikes;
using TINK.View.Root;
using TINK.View.Settings;
using Xamarin.Forms;
using TINK.ViewModel.MasterDetail;
#if USEFLYOUT
using TINK.View.MasterDetail;
#endif
using TINK.Services;
using TINK.View.Themes;
namespace TINK.ViewModel.Root
{
/// <summary>
/// View model for flyout menu entries. Respositility
/// - populates entries depending on app state on showing menu
/// - updates menu denpending on app state change, i.e. user logs in/ out.
/// </summary>
public class RootPageFlyoutViewModel : INotifyPropertyChanged
{
/// <summary>
/// Dictionary to manage collection of menu items.
/// </summary>
private Dictionary<Type, int> m_oEntryDictionary;
public event PropertyChangedEventHandler PropertyChanged;
/// <summary> Updates menu entries depending on state. </summary>
private void UpdateMenuEntries()
{
for (int l_iIndex = MenuItems.Count - 1; l_iIndex >= 0; l_iIndex--)
{
MenuItems.Clear();
m_oEntryDictionary.Clear();
}
CheckAddItem(typeof(MapPage));
if (App.ModelRoot.ActiveUser.IsLoggedIn)
{
CheckAddItem(typeof(MyBikesPage));
CheckAddItem(typeof(FindBikePage));
CheckAddItem(typeof(AccountPage));
}
else
{
CheckAddItem(typeof(LoginPage));
}
if (App.ModelRoot.Uris.ActiveUri.Host.GetIsCopri()
|| App.ModelRoot.ActiveUser.IsLoggedIn)
{
CheckAddItem(typeof(SettingsPage));
}
CheckAddItem(typeof(FeesAndBikesPage)); // Fees and bikes
CheckAddItem(typeof(ContactPage)); // Feedback and contact
CheckAddItem(typeof(TabbedPageInfo)); // About sharee.bike
}
/// <summary>Adds a menu item to master detail menu.</summary>
/// <param name="p_oType">Type decribing entry to be added.</param>
private void CheckAddItem(Type p_oType)
{
if (m_oEntryDictionary.ContainsKey(p_oType))
{
// Nothing to do because has already been added.
return;
}
m_oEntryDictionary.Add(
p_oType,
m_oEntryDictionary.Count);
MenuItems.Add(new RootPageFlyoutMenuItem {
TargetType = p_oType,
GlyphCode = Helper.GetGlyphCode(p_oType),
Title = Helper.GetCaption(p_oType),
Id = m_oEntryDictionary[p_oType] }) ;
}
/// <summary> Removes a page from menu.</summary>
/// <param name="p_oType"></param>
private void RemoveItem(Type p_oType)
{
if (!m_oEntryDictionary.ContainsKey(p_oType))
{
// Nothing to do because item was never added/ already removed.
return;
}
MenuItems.Remove(MenuItems[m_oEntryDictionary[p_oType]]);
m_oEntryDictionary.Remove(p_oType);
}
public RootPageFlyoutViewModel()
{
MenuItems = new ObservableCollection<RootPageFlyoutMenuItem>();
m_oEntryDictionary = new Dictionary<Type, int>();
// Update menu entries on login/ logout actions.
App.ModelRoot.ActiveUser.StateChanged += (sender, eventargs) => OnUpdateRequired();
// Update flyout view model whenever theme is switched.
App.ModelRoot.Themes.PropertyChanged += (sender, eventargs) =>
{
if (!(sender is ServicesContainerMutable<object> themes))
return;
MasterDetailMenuTitlte = GetMasterDetailMenuTitle(themes.Active);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MasterDetailMenuTitlte)));
};
MasterDetailMenuTitlte = GetMasterDetailMenuTitle(App.ModelRoot.Themes.Active);
UpdateMenuEntries();
}
/// <summary>
/// Gets the flyout title from theme name
/// </summary>
/// <param name="theme">Name of theme.</param>
/// <returns>Flyout title.</returns>
private string GetMasterDetailMenuTitle(object theme)
{
if (!(theme is ITheme active))
return TINK.Themes.LastenradBayern.OPERATORINFO;
return $"{(!string.IsNullOrEmpty(active.OperatorInfo) ? ($"{active.OperatorInfo}") : "sharee.bike")}";
}
/// <summary>
/// Holds the title of the fylout page.
/// </summary>
public string MasterDetailMenuTitlte { get; private set; }
/// <summary>
/// Provides collection of menu items for master page.
/// </summary>
public ObservableCollection<RootPageFlyoutMenuItem> MenuItems
{
get; private set;
}
/// <summary>
/// Gets or sets the selected item.
/// </summary>
public MainPageMenuItem SelectedMenuItem
{
get;
set;
}
/// <summary>
/// Command object which is invoked from view when an item is selected.
/// </summary>
public Command MenuItemSelected
{
get
{
return new Command(OnUpdateRequired);
}
}
/// <summary> Manges updates required due to selection of a menu or login events.</summary>
public void OnUpdateRequired()
{
UpdateMenuEntries();
if (SelectedMenuItem == null)
{
// Nothing to do if no menu entry is selected.
return;
}
}
}
}

View file

@ -0,0 +1,115 @@
using System;
using TINK.MultilingualResources;
using TINK.View.Account;
using TINK.View.Contact;
using TINK.View.FindBike;
using TINK.View.Info;
using TINK.View.Login;
using TINK.View.Map;
using TINK.View.MyBikes;
using TINK.View.Settings;
using TINK.ViewModel.Info;
namespace TINK.ViewModel.MasterDetail
{
public static class Helper
{
/// <summary>
/// Gets a description for a map page used as menu item entry and caption.
/// </summary>
/// <param name="type">Type of page to get caption for.</param>
/// <returns></returns>
public static string GetCaption(Type type)
{
if (type == typeof(MapPage)) // Bikes sites
{
return AppResources.MarkingMapPage;
}
else if (type == typeof(FindBikePage)) // Find Bike
{
return AppResources.MarkingFindBike;
}
else if (type == typeof(MyBikesPage)) // My Bikes
{
return AppResources.MarkingMyBikes;
}
else if (type == typeof(AccountPage)) // Account
{
return AppResources.MarkingAccount;
}
else if (type == typeof(LoginPage)) // Login
{
return AppResources.MarkingLogin;
}
else if (type == typeof(SettingsPage)) // Settings
{
return AppResources.MarkingSettings;
}
else if (type == typeof(FeesAndBikesPage))
{
return AppResources.MarkingFeesAndBikes;
}
else if (type == typeof(ContactPage))
{
return AppResources.MarkingFeedbackAndContact;
}
else if (type == typeof(TabbedPageInfo))
{
return string.Format(AppResources.MarkingAbout, ContactPageViewModel.GetAppName(App.ModelRoot.Uris.ActiveUri));
}
else
{
return type.Name;
}
}
/// <summary>
/// Gets a description for a map page used as menu item entry and caption.
/// </summary>
/// <param name="type">Type of page to get caption for.</param>
/// <returns></returns>
public static string GetGlyphCode(Type type)
{
if (type == typeof(MapPage)) // Bikes sites
{
return "\uf5a0";
}
else if (type == typeof(FindBikePage)) // My Bikes
{
return "\uf002";
}
else if (type == typeof(MyBikesPage)) // My Bikes
{
return "\uf206";
}
else if (type == typeof(AccountPage)) // Account
{
return "\uf007";
}
else if (type == typeof(LoginPage)) // Login
{
return "\uf2f6";
}
else if (type == typeof(SettingsPage)) // Settings
{
return "\uf013";
}
else if (type == typeof(FeesAndBikesPage))
{
return "\uf7d9";
}
else if (type == typeof(ContactPage))
{
return "\uf095";
}
else if (type == typeof(TabbedPageInfo))
{
return "\uf05a";
}
else
{
return type.Name;
}
}
}
}

View file

@ -0,0 +1,72 @@
using TINK.MultilingualResources;
using TINK.ViewModel.Info;
using TINK.Services.CopriApi.ServerUris;
using System.ComponentModel;
using TINK.View.Themes;
using TINK.Services;
namespace TINK.ViewModel.RootShell
{
public class AppShellViewModel : INotifyPropertyChanged
{
public AppShellViewModel()
{
App.ModelRoot.ActiveUser.StateChanged += (sender, eventargs) =>
{
// Login state changed. Update related menu entries.
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsMyBikesPageVisible)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsFindBikePageVisible)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsAccountPageVisible)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsLoginPageVisible)));
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsSettingsPageVisible)));
};
// Update flyout view model whenever theme is switched.
App.ModelRoot.Themes.PropertyChanged += (sender, eventargs) =>
{
if (!(sender is ServicesContainerMutable<object> themes))
return;
MasterDetailMenuTitlte = GetMasterDetailMenuTitle(themes.Active);
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MasterDetailMenuTitlte)));
};
MasterDetailMenuTitlte = GetMasterDetailMenuTitle(App.ModelRoot.Themes.Active);
}
/// <summary>
/// Gets the flyout title from theme name
/// </summary>
/// <param name="theme">Name of theme.</param>
/// <returns>Flyout title.</returns>
private string GetMasterDetailMenuTitle(object theme)
{
if (!(theme is ITheme active))
return TINK.Themes.ShareeBike.OPERATORINFO;
return $"{(!string.IsNullOrEmpty(active.OperatorInfo) ? ($"{active.OperatorInfo}") : "sharee.bike")}";
}
/// <summary>
/// Holds the title of the fylout page.
/// </summary>
public string MasterDetailMenuTitlte { get; private set; }
public event PropertyChangedEventHandler PropertyChanged;
public bool IsMyBikesPageVisible => App.ModelRoot.ActiveUser.IsLoggedIn;
public bool IsFindBikePageVisible => App.ModelRoot.ActiveUser.IsLoggedIn;
public bool IsAccountPageVisible => App.ModelRoot.ActiveUser.IsLoggedIn;
public bool IsLoginPageVisible => !App.ModelRoot.ActiveUser.IsLoggedIn;
public bool IsSettingsPageVisible => App.ModelRoot.Uris.ActiveUri.Host.GetIsCopri()
|| App.ModelRoot.ActiveUser.IsLoggedIn;
public string TabbedPageIngoTitle => string.Format(AppResources.MarkingAbout, ContactPageViewModel.GetAppName(App.ModelRoot.Uris.ActiveUri));
}
}

View file

@ -0,0 +1,42 @@
using Serilog;
using System.IO;
using System.Reflection;
using System.Text;
namespace TINK.ViewModel
{
public static class ViewModelResourceHelper
{
/// <summary> Get ressource prefix depending on platform.</summary>
public static string RessourcePrefix
{
get
{
#if __IOS__
return "TINK.iOS.";
#endif
#if __ANDROID__
return "TINK.Droid.";
#endif
#if WINDOWS_UWP
return "TINK.WinPhone.";
#endif
}
}
/// <summary> Gets an an embedded html ressource.</summary>
/// <param name="resrouceName">Name of resource to get.</param>
/// <returns></returns>
public static string GetSource(string resrouceName)
{
var l_oRessourceName = RessourcePrefix + resrouceName;
Log.Verbose($"Using this resource prefix { RessourcePrefix}.");
// note that the prefix includes the trailing period '.' that is required
var assembly = typeof(ViewModelResourceHelper).GetTypeInfo().Assembly;
var stream = assembly.GetManifestResourceStream(l_oRessourceName);
return stream != null
? (new StreamReader(stream, Encoding.UTF8)).ReadToEnd()
: string.Format("<!DOCTYPE html><html lang=\"de\"><body>An error occurred loading html- ressource {0}.</body>", l_oRessourceName);
}
}
}