using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; using TINK.Services; using TINK.Services.CopriApi.ServerUris; using TINK.View; 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.View.Themes; using Xamarin.Forms; namespace TINK.ViewModel { /// /// View model managing master detail menu. /// class MasterPageViewModel : INotifyPropertyChanged { /// /// Dictionary to manage collection of menu items. /// private Dictionary m_oEntryDictionary; /// Updates menu entries depending on state. private void UpdateMenuEntries() { var l_oSelectedMenuItem = SelectedMenuItem ?? new MainPageMenuItem(0, typeof(MapPage)); 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 } /// Adds a menu item to master detail menu. /// Type decribing entry to be added. 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 MainPageMenuItem(m_oEntryDictionary[p_oType], p_oType)); } /// Removes a page from menu. /// 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 MasterPageViewModel() { MenuItems = new ObservableCollection(); m_oEntryDictionary = new Dictionary(); 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 themes)) return; MasterDetailMenuTitlte = GetMasterDetailMenuTitle(themes.Active); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MasterDetailMenuTitlte))); }; MasterDetailMenuTitlte = GetMasterDetailMenuTitle(App.ModelRoot.Themes.Active); UpdateMenuEntries(); } /// /// Gets the flyout title from theme name /// /// Name of theme. /// Flyout title. private string GetMasterDetailMenuTitle(object theme) { if (!(theme is ITheme active)) return "sharee.bike"; return $"sharee.bike{(!string.IsNullOrEmpty(active.OperatorInfo) ? ($"\r\n{active.OperatorInfo}") : string.Empty)}"; } private string masterDetailMenuTitlte; /// /// Holds the title of the fylout page. /// public string MasterDetailMenuTitlte { get { return masterDetailMenuTitlte; } set { if (masterDetailMenuTitlte == value) return; masterDetailMenuTitlte = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(MasterDetailMenuTitlte))); } } /// /// Provides collection of menu items for master page. /// public ObservableCollection MenuItems { get; private set; } /// /// View service used to manage menu state. /// public ShowPageDelegate ShowPageViewService { get; set; } /// /// Gets or sets the selected item. /// public MainPageMenuItem SelectedMenuItem { get; set; } /// /// Command object which is invoked from view when an item is selected. /// public Command MenuItemSelected { get { return new Command(OnUpdateRequired); } } /// Manges updates required due to selection of a menu or login events. public void OnUpdateRequired() { if (ShowPageViewService == null) return; UpdateMenuEntries(); if (SelectedMenuItem == null) { // Nothing to do if no menu entry is selected. return; } ShowPageViewService(SelectedMenuItem.TargetType); } #region INotifyPropertyChanged Implementation public event PropertyChangedEventHandler PropertyChanged; void OnPropertyChanged([CallerMemberName] string propertyName = "") { if (PropertyChanged == null) return; PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #endregion } }