using System; using System.Collections.ObjectModel; using System.Collections.Generic; using System.Threading.Tasks; using System.Linq; using Aurora.Design.Components.NavigationMenu; using Aurora.Design.Views.MainView; using Xamarin.Forms; using Xamarin.Forms.Xaml; using Aurora.Models.Media; using Aurora.Design.Components.MediaPlayer; using Aurora.Services.Player; using Autofac; namespace Aurora.Design.Views.Main { public enum PlayAction { Play, Pause, Resume, Stop } /// /// Delegate for updating player metadata /// /// public delegate Task SetPlayerDelegate(BaseMedia media, PlayAction action); public delegate bool GetIsPlayingDelegate(); public delegate void ShowModalDelegate(Type view, BaseDialogViewModel viewModel); public delegate void HideModalDelegate(); public delegate void FinishDialogDelegate(); public delegate void SetViewDelegate(Type viewType, Type viewModelType); [XamlCompilation(XamlCompilationOptions.Compile)] public partial class MainView : ContentPage//, IDisposable { private Dictionary _viewModels; private BaseViewModel _lastViewModel; private Player _playerComponent; private IPlayer _playerService; private ContentPresenter _viewContent; public MainView(IPlayer player) { InitializeComponent(); BindingContext = new MainViewModel(); _viewModels = new Dictionary(); _playerComponent = Player; _viewContent = (ContentPresenter)Content.FindByName("ViewContent"); _playerService = player; MasterPage.ListView.ItemSelected += OnNavItemSelected; Appearing += OnAppearing; } public void Dispose() { Appearing -= OnAppearing; } /// /// Event handler for side bar items being selected /// /// /// private void OnNavItemSelected(object sender, SelectedItemChangedEventArgs e) { var item = e.SelectedItem as NavigationItem; if (item == null) return; var view = (View)Activator.CreateInstance(item.TargetType); string viewModelName = item.TargetViewModelType.Name; //Check if we have an instantiated viewModel BaseViewModel vm = new BaseViewModel(); if (_viewModels.ContainsKey(viewModelName)) { _viewModels.TryGetValue(viewModelName, out vm); } else { if (item.TargetViewModelType.IsAssignableFrom(typeof(BaseViewModel))) { throw new InvalidOperationException("TargetViewModel field must be of type BaseViewModel"); } //Instantiate new view model vm = (BaseViewModel)App.Container.Resolve(item.TargetViewModelType); //Activator.CreateInstance(item.TargetViewModelType); _viewModels.Add(viewModelName, vm); } //Assign player controls to viewmodel if(vm is BasePlayerViewModel) { AssignPlayerControls(vm as BasePlayerViewModel); } ChangeModalVisiblity(false); vm.SetView = this.SetView; //Activate viewmodel vm.OnActive(); //Deactivate last viewModel _lastViewModel.OnInactive(); //Unasign deactivating vm if(_lastViewModel is BasePlayerViewModel) { UnassignPlayerControls(_lastViewModel as BasePlayerViewModel); } //Assign viewModel _lastViewModel = vm; view.BindingContext = vm; _viewContent.Content = view; } /// /// Event handler for page appearing. /// /// The object that fired the event. /// The event arguments private void OnAppearing(object sender, EventArgs args) { //Set initial view from first item in list ObservableCollection screenList = (ObservableCollection)MasterPage.ListView.ItemsSource; //Assign viewModel NavigationItem firstNavItem = screenList.FirstOrDefault().FirstOrDefault(); var view = (View)Activator.CreateInstance(firstNavItem.TargetType); BaseViewModel vm = new BaseViewModel(); if (_viewModels.ContainsKey(nameof(firstNavItem.TargetViewModelType))) { _viewModels.TryGetValue(nameof(firstNavItem.TargetViewModelType), out vm); } else { //Instantiate new view model vm = (BaseViewModel)App.Container.Resolve(firstNavItem.TargetViewModelType); //(BaseViewModel)Activator.CreateInstance(firstNavItem.TargetViewModelType); _viewModels.Add(nameof(firstNavItem.TargetViewModelType), vm); } view.BindingContext = vm; _lastViewModel = vm; if(vm is BasePlayerViewModel) { AssignPlayerControls(vm as BasePlayerViewModel); } vm.SetView = this.SetView; ChangeModalVisiblity(false); vm.OnActive(); _viewContent.Content = view; } /// /// Unassign setplayer delegate to prevent vms from changing player info when inactive /// /// private void UnassignPlayerControls(BasePlayerViewModel vm) { vm.ChangePlayerState = null; vm.IsPlaying = null; vm.ShowModal = null; } /// /// Assign main views music player controls to a view model /// /// BaseViewModel to assign controls to private void AssignPlayerControls(BasePlayerViewModel vm) { _playerComponent.PlayButtonCommand = new Command(vm.OnPlayButtonCommandExecute, vm.CanPlayButtonCommandExecute); _playerComponent.NextButtonCommand = new Command(vm.OnNextButtonExecute, vm.CanNextButtonCommandExecute); _playerComponent.PreviousButtonCommand = new Command(vm.OnPreviousButtonExecute, vm.CanPreviousButtonCommandExecute); vm.ChangePlayerState = ChangePlayerState; vm.IsPlaying = () => { return _playerService.PlaybackState == PlaybackState.Playing; }; vm.ShowModal = this.ShowModal; vm.HideModal = this.HideModal; } /// /// Delegate handler for a view model controling music playback /// /// /// /// private async Task ChangePlayerState(BaseMedia media, PlayAction action) { if (media != null && media.Metadata is AudioMetadata) { AudioMetadata meta = (AudioMetadata)media.Metadata; _playerComponent.ArtistName = meta.Artist; _playerComponent.SongTitle = meta.Title; } switch (action) { case PlayAction.Pause: { _playerService.Pause(); _playerComponent.IsPlaying = false; break; } case PlayAction.Play: { if (media == null) { break; } if (!_playerService.IsMediaLoaded(media)) { await _playerService.LoadMedia(media).ConfigureAwait(true); } _playerService.Play(); _playerComponent.IsPlaying = true; break; } case PlayAction.Resume: { _playerService.Play(); _playerComponent.IsPlaying = true; break; } case PlayAction.Stop: { _playerService.Stop(); _playerComponent.IsPlaying = false; break; } } } private void ShowModal(Type view, BaseDialogViewModel viewModel) { ContentPresenter modalContainer = (ContentPresenter)Modal.FindByName("ViewContent"); var vw = (View)Activator.CreateInstance(view); vw.BindingContext = viewModel; //Set modal container content modalContainer.Content = vw; //Set visibility ChangeModalVisiblity(true); } private void HideModal() { ChangeModalVisiblity(false); } private void ChangeModalVisiblity(bool isVisible) { Modal.IsVisible = isVisible; Content.IsVisible = !isVisible; } private void SetView(Type viewType, Type viewModelType) { BaseViewModel vm = new BaseViewModel(); if(this._viewModels.ContainsKey(viewModelType.Name)) { this._viewModels.TryGetValue(viewModelType.Name, out vm); } else { if (viewModelType.IsAssignableFrom(typeof(BaseViewModel))) { throw new InvalidOperationException("TargetViewModel field must be of type BaseViewModel"); } //Instantiate new view model vm = (BaseViewModel)App.Container.Resolve(viewModelType); //Activator.CreateInstance(item.TargetViewModelType); _viewModels.Add(viewModelType.Name, vm); } //Assign player controls to viewmodel if(vm is BasePlayerViewModel) { AssignPlayerControls(vm as BasePlayerViewModel); } ChangeModalVisiblity(false); //Activate viewmodel vm.OnActive(); //Deactivate last viewModel _lastViewModel.OnInactive(); //Unasign deactivating vm if(_lastViewModel is BasePlayerViewModel) { UnassignPlayerControls(_lastViewModel as BasePlayerViewModel); } var view = (View)Activator.CreateInstance(viewType); vm.SetView = this.SetView; //Assign viewModel _lastViewModel = vm; view.BindingContext = vm; _viewContent.Content = view; } } }