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.PlayerService; using System.Threading; 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(); [XamlCompilation(XamlCompilationOptions.Compile)] public partial class MainView : ContentPage//, IDisposable { private Dictionary _viewModels; private BaseViewModel _lastViewModel; private Player _playerComponent; private PlayerService _playerService; private ContentPresenter _viewContent; public MainView() { InitializeComponent(); BindingContext = new MainViewModel(); _viewModels = new Dictionary(); _playerComponent = Player; _viewContent = (ContentPresenter)Content.FindByName("ViewContent"); _playerService = PlayerService.Instance; 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); //Check if we have an instantiated viewModel BaseViewModel vm = new BaseViewModel(); if (_viewModels.ContainsKey(item.Id)) { _viewModels.TryGetValue(item.Id, out vm); } else { if (item.TargetViewModelType.BaseType != typeof(BaseViewModel)) { throw new InvalidOperationException("TargetViewModel field must be of type BaseViewModel"); } //Instantiate new view model vm = (BaseViewModel)Activator.CreateInstance(item.TargetViewModelType); _viewModels.Add(item.Id, vm); } //Assign player controls to viewmodel AssignPlayerControls(vm); ChangeModalVisiblity(false); //Activate viewmodel vm.OnActive(); //Deactivate last viewModel _lastViewModel.OnInactive(); //Unasign deactivating vm UnassignPlayerControls(_lastViewModel); //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(firstNavItem.Id)) { _viewModels.TryGetValue(firstNavItem.Id, out vm); } else { //Instantiate new view model vm = (BaseViewModel)Activator.CreateInstance(firstNavItem.TargetViewModelType); _viewModels.Add(firstNavItem.Id, vm); } view.BindingContext = vm; _lastViewModel = vm; AssignPlayerControls(vm); ChangeModalVisiblity(false); vm.OnActive(); _viewContent.Content = view; } /// /// Unassign setplayer delegate to prevent vms from changing player info when inactive /// /// private void UnassignPlayerControls(BaseViewModel 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(BaseViewModel vm) { _playerComponent.PlayButtonCommand = new Command(vm.OnPlayButtonExecute, vm.CanPlayButtonExecute); _playerComponent.NextButtonCommand = new Command(vm.OnNextButtonExecute, vm.CanNextButtonExecute); _playerComponent.PreviousButtonCommand = new Command(vm.OnPreviousButtonExecute, vm.CanPreviousButtonExecute); 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; } } }