diff --git a/MusicApp/MainActivity.cs b/MusicApp/MainActivity.cs index 4beda1d..7fd1c53 100644 --- a/MusicApp/MainActivity.cs +++ b/MusicApp/MainActivity.cs @@ -606,22 +606,8 @@ namespace MusicApp if(PlaylistTracks.instance != null) { - HideSearch(); - if (PlaylistTracks.instance.isEmpty) - { - ViewGroup rootView = FindViewById(Android.Resource.Id.Content); - rootView.RemoveView(PlaylistTracks.instance.emptyView); - } - SupportActionBar.SetHomeButtonEnabled(false); - SupportActionBar.SetDisplayHomeAsUpEnabled(false); - SupportActionBar.SetDisplayShowTitleEnabled(true); - SupportActionBar.Title = "MusicApp"; - - contentRefresh.Refresh -= PlaylistTracks.instance.OnRefresh; - OnPaddingChanged -= PlaylistTracks.instance.OnPaddingChanged; - FindViewById(Resource.Id.appbar).RemoveOnOffsetChangedListener(PlaylistTracks.instance); - FindViewById(Resource.Id.playlistHeader).Visibility = ViewStates.Gone; - PlaylistTracks.instance = null; + PlaylistTracks.instance.navigating = true; + SupportFragmentManager.BeginTransaction().Remove(PlaylistTracks.instance).Commit(); } Android.Support.V4.App.Fragment fragment = null; diff --git a/MusicApp/Resources/Portable Class/ItemTouchCallback.cs b/MusicApp/Resources/Portable Class/ItemTouchCallback.cs index c9e04eb..fba961f 100644 --- a/MusicApp/Resources/Portable Class/ItemTouchCallback.cs +++ b/MusicApp/Resources/Portable Class/ItemTouchCallback.cs @@ -50,15 +50,19 @@ namespace MusicApp.Resources.Portable_Class public override void OnSwiped(RecyclerView.ViewHolder viewHolder, int direction) { adapter.ItemDismissed(viewHolder.AdapterPosition); + MainActivity.instance.contentRefresh.SetEnabled(true); } - public override void OnChildDraw(Canvas c, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, bool isCurrentlyActive) { if (actionState == ItemTouchHelper.ActionStateSwipe) { viewHolder.ItemView.TranslationX = dX; - MainActivity.instance.contentRefresh.SetEnabled(false); + + if(isCurrentlyActive) + MainActivity.instance.contentRefresh.SetEnabled(false); + else + MainActivity.instance.contentRefresh.SetEnabled(true); ColorDrawable background = new ColorDrawable(Color.Red); if (dX < 0) diff --git a/MusicApp/Resources/Portable Class/PlaylistTrackAdapter.cs b/MusicApp/Resources/Portable Class/PlaylistTrackAdapter.cs index 4b33134..a501262 100644 --- a/MusicApp/Resources/Portable Class/PlaylistTrackAdapter.cs +++ b/MusicApp/Resources/Portable Class/PlaylistTrackAdapter.cs @@ -1,5 +1,6 @@ using Android.App; using Android.Content; +using Android.Content.Res; using Android.Graphics; using Android.Support.V7.Widget; using Android.Views; @@ -8,6 +9,7 @@ using MusicApp.Resources.values; using Square.Picasso; using System; using System.Collections.Generic; +using System.Linq; namespace MusicApp.Resources.Portable_Class { @@ -37,10 +39,60 @@ namespace MusicApp.Resources.Portable_Class NotifyItemRemoved(position); } - public override int ItemCount => songList.Count + (PlaylistTracks.instance.fullyLoadded ? 0 : 1); + public override int ItemCount => songList.Count + (PlaylistTracks.instance.fullyLoadded ? 0 : 1) + (PlaylistTracks.instance.useHeader ? 0 : 1); public override void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) { + if (!PlaylistTracks.instance.useHeader) + position--; + + if(position == -1 && !PlaylistTracks.instance.useHeader) + { + View header = viewHolder.ItemView; + header.FindViewById(Resource.Id.headerNumber).Text = PlaylistTracks.instance.tracks.Count + " songs"; + header.FindViewById(Resource.Id.headerPlay).Click += (sender, e0) => { PlaylistTracks.instance.PlayInOrder(0, false); }; + header.FindViewById(Resource.Id.headerShuffle).Click += (sender, e0) => + { + if (PlaylistTracks.instance.tracks[0].IsYt) + { + Random r = new Random(); + Song[] songs = PlaylistTracks.instance.tracks.OrderBy(x => r.Next()).ToArray(); + YoutubeEngine.PlayFiles(songs); + } + else + { + List tracksPath = new List(); + foreach (Song song in PlaylistTracks.instance.tracks) + tracksPath.Add(song.Path); + + Intent intent = new Intent(MainActivity.instance, typeof(MusicPlayer)); + intent.PutStringArrayListExtra("files", tracksPath); + intent.SetAction("RandomPlay"); + MainActivity.instance.StartService(intent); + + Intent inte = new Intent(MainActivity.instance, typeof(Player)); + MainActivity.instance.StartActivity(inte); + } + }; + header.FindViewById(Resource.Id.headerMore).Click += (sender, e0) => + { + Android.Support.V7.Widget.PopupMenu menu = new Android.Support.V7.Widget.PopupMenu(MainActivity.instance, header.FindViewById(Resource.Id.headerMore)); + menu.Inflate(Resource.Menu.playlist_smallheader_more); + menu.SetOnMenuItemClickListener(PlaylistTracks.instance); + menu.Show(); + }; + + if (MainActivity.Theme != 1) + { + header.SetBackgroundColor(Color.Argb(255, 255, 255, 255)); + header.FindViewById(Resource.Id.headerPlay).ImageTintList = ColorStateList.ValueOf(Color.Black); + header.FindViewById(Resource.Id.headerShuffle).ImageTintList = ColorStateList.ValueOf(Color.Black); + header.FindViewById(Resource.Id.headerMore).ImageTintList = ColorStateList.ValueOf(Color.Black); + } + + return; + } + if(position >= songList.Count) return; @@ -90,16 +142,23 @@ namespace MusicApp.Resources.Portable_Class View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.SongList, parent, false); return new RecyclerHolder(itemView, OnClick, OnLongClick); } - else + else if(viewType == 1) { View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.smallLoading, parent, false); return new UslessHolder(itemView); } + else + { + View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.PlaylistSmallHeader, parent, false); + return new UslessHolder(itemView); + } } public override int GetItemViewType(int position) { - if (position >= songList.Count) + if (position == 0 && !PlaylistTracks.instance.useHeader) + return 2; + else if (position - (PlaylistTracks.instance.useHeader ? 0 : 1) >= songList.Count) return 1; return 0; } @@ -132,26 +191,11 @@ namespace MusicApp.Resources.Portable_Class //NotifyItemMoved(fromPosition, toPosition); } - public void ItemMoveEnded(int fromPosition, int toPosition) - { - //if (MusicPlayer.CurrentID() == fromPosition) - // MusicPlayer.currentID = toPosition; - - //MusicPlayer.instance.UpdateQueueSlots(); - } - - //List Swap(List list, int fromPosition, int toPosition) - //{ - // T item = list[fromPosition]; - // list[fromPosition] = list[toPosition]; - // list[toPosition] = item; - // return list; - //} + public void ItemMoveEnded(int fromPosition, int toPosition) { } public void ItemDismissed(int position) { - //Queue.RemoveFromQueue(songList[position]); - //NotifyItemRemoved(position); + PlaylistTracks.instance.DeleteDialog(position); } } } \ No newline at end of file diff --git a/MusicApp/Resources/Portable Class/PlaylistTracks.cs b/MusicApp/Resources/Portable Class/PlaylistTracks.cs index 5a8635e..7528790 100644 --- a/MusicApp/Resources/Portable Class/PlaylistTracks.cs +++ b/MusicApp/Resources/Portable Class/PlaylistTracks.cs @@ -1,7 +1,5 @@ using Android.Content; -using Android.Content.Res; using Android.Database; -using Android.Graphics; using Android.Net; using Android.OS; using Android.Provider; @@ -19,6 +17,8 @@ using System.Linq; using System.Threading.Tasks; using static Android.Provider.MediaStore.Audio; using RecyclerView = Android.Support.V7.Widget.RecyclerView; +using PopupMenu = Android.Support.V7.Widget.PopupMenu; + namespace MusicApp.Resources.Portable_Class { @@ -30,7 +30,7 @@ namespace MusicApp.Resources.Portable_Class public PlaylistTrackAdapter adapter; public View emptyView; private Android.Support.V7.Widget.Helper.ItemTouchHelper itemTouchHelper; - public List result; + public List result = null; public long playlistId; public string ytID; private string author; @@ -42,8 +42,9 @@ namespace MusicApp.Resources.Portable_Class public bool fullyLoadded = false; public bool isEmpty = false; public bool lastVisible = false; - private bool useHeader = true; + public bool useHeader = true; public static bool openned = false; + public bool navigating = false; public List tracks = new List(); private List ytTracksIDs = new List(); @@ -237,13 +238,13 @@ namespace MusicApp.Resources.Portable_Class if (YoutubeEngine.instances[i].focused) selectedTab = i; } - if (Player.instance == null) + if (Player.instance == null && !navigating) { MainActivity.instance?.SupportFragmentManager.BeginTransaction().Attach(YoutubeEngine.instances[selectedTab]).Commit(); MainActivity.instance?.SupportFragmentManager.BeginTransaction().Remove(instance).Commit(); } } - else if (Player.instance == null) + else if (Player.instance == null && !navigating) MainActivity.instance?.SupportFragmentManager.PopBackStack(); instance = null; @@ -260,10 +261,6 @@ namespace MusicApp.Resources.Portable_Class ListView.SetAdapter(new PlaylistTrackAdapter(new List())); ListView.ScrollChange += ListView_ScrollChange; - Android.Support.V7.Widget.Helper.ItemTouchHelper.Callback callback = new ItemTouchCallback(adapter); - itemTouchHelper = new Android.Support.V7.Widget.Helper.ItemTouchHelper(callback); - itemTouchHelper.AttachToRecyclerView(ListView); - PopulateList(); CreateHeader(); return view; @@ -271,7 +268,7 @@ namespace MusicApp.Resources.Portable_Class private void ListView_ScrollChange(object sender, View.ScrollChangeEventArgs e) { - if (((Android.Support.V7.Widget.LinearLayoutManager)ListView.GetLayoutManager()).FindLastVisibleItemPosition() == adapter.ItemCount - 1) + if (((Android.Support.V7.Widget.LinearLayoutManager)ListView?.GetLayoutManager())?.FindLastVisibleItemPosition() == adapter?.ItemCount - 1) LoadMore(); } @@ -321,51 +318,6 @@ namespace MusicApp.Resources.Portable_Class Picasso.With(Android.App.Application.Context).Load(thumnailURI).Placeholder(Resource.Drawable.noAlbum).Resize(1080, 1080).CenterCrop().Into(Activity.FindViewById(Resource.Id.headerArt)); } } - else - { - View header = LayoutInflater.Inflate(Resource.Layout.PlaylistSmallHeader, null, false); - //ListView.AddHeaderView(header); - header.FindViewById(Resource.Id.headerNumber).Text = tracks.Count + " songs"; - header.FindViewById(Resource.Id.headerPlay).Click += (sender, e0) => { PlayInOrder(0, false); }; - header.FindViewById(Resource.Id.headerShuffle).Click += (sender, e0) => - { - if (tracks[0].IsYt) - { - System.Random r = new System.Random(); - Song[] songs = tracks.OrderBy(x => r.Next()).ToArray(); - YoutubeEngine.PlayFiles(songs); - } - else - { - List tracksPath = new List(); - foreach (Song song in tracks) - tracksPath.Add(song.Path); - - Intent intent = new Intent(MainActivity.instance, typeof(MusicPlayer)); - intent.PutStringArrayListExtra("files", tracksPath); - intent.SetAction("RandomPlay"); - MainActivity.instance.StartService(intent); - - Intent inte = new Intent(MainActivity.instance, typeof(Player)); - MainActivity.instance.StartActivity(inte); - } - }; - header.FindViewById(Resource.Id.headerMore).Click += (sender, e0) => - { - PopupMenu menu = new PopupMenu(Activity, header.FindViewById(Resource.Id.headerMore)); - menu.Inflate(Resource.Menu.playlist_smallheader_more); - menu.SetOnMenuItemClickListener(this); - menu.Show(); - }; - - if (MainActivity.Theme != 1) - { - header.SetBackgroundColor(Color.Argb(255, 255, 255, 255)); - header.FindViewById(Resource.Id.headerPlay).ImageTintList = ColorStateList.ValueOf(Color.Black); - header.FindViewById(Resource.Id.headerShuffle).ImageTintList = ColorStateList.ValueOf(Color.Black); - header.FindViewById(Resource.Id.headerMore).ImageTintList = ColorStateList.ValueOf(Color.Black); - } - } } public static Fragment NewInstance(List songs, string playlistName) @@ -374,6 +326,7 @@ namespace MusicApp.Resources.Portable_Class instance.tracks = songs; instance.playlistName = playlistName; instance.useHeader = false; + instance.fullyLoadded = true; return instance; } @@ -382,6 +335,7 @@ namespace MusicApp.Resources.Portable_Class instance = new PlaylistTracks { Arguments = new Bundle() }; instance.playlistId = playlistId; instance.playlistName = playlistName; + instance.fullyLoadded = true; return instance; } @@ -395,6 +349,7 @@ namespace MusicApp.Resources.Portable_Class instance.author = author; instance.count = count; instance.thumnailURI = Uri.Parse(thumbnailURI); + instance.fullyLoadded = false; return instance; } @@ -441,16 +396,19 @@ namespace MusicApp.Resources.Portable_Class musicCursor.Close(); } - //adapter = new PlaylistTrackAdapter(tracks) - //{ - // listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot - //}; - adapter.AddToList(tracks); + adapter = new PlaylistTrackAdapter(tracks) + { + listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot + }; adapter.listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot; adapter.ItemClick += ListView_ItemClick; adapter.ItemLongClick += ListView_ItemLongClick; ListView.SetAdapter(adapter); + Android.Support.V7.Widget.Helper.ItemTouchHelper.Callback callback = new ItemTouchCallback(adapter); + itemTouchHelper = new Android.Support.V7.Widget.Helper.ItemTouchHelper(callback); + itemTouchHelper.AttachToRecyclerView(ListView); + if (adapter == null || adapter.ItemCount == 0) { isEmpty = true; @@ -483,16 +441,19 @@ namespace MusicApp.Resources.Portable_Class } nextPageToken = ytPlaylist.NextPageToken; - //adapter = new PlaylistTrackAdapter(tracks) - //{ - // listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot - //}; - adapter.AddToList(tracks); + adapter = new PlaylistTrackAdapter(tracks) + { + listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot + }; adapter.listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot; adapter.ItemClick += ListView_ItemClick; adapter.ItemLongClick += ListView_ItemLongClick; ListView.SetAdapter(adapter); + Android.Support.V7.Widget.Helper.ItemTouchHelper.Callback callback = new ItemTouchCallback(adapter); + itemTouchHelper = new Android.Support.V7.Widget.Helper.ItemTouchHelper(callback); + itemTouchHelper.AttachToRecyclerView(ListView); + if (adapter == null || adapter.ItemCount == 0) { isEmpty = true; @@ -501,11 +462,10 @@ namespace MusicApp.Resources.Portable_Class } else if(tracks.Count != 0) { - //adapter = new PlaylistTrackAdapter(tracks) - //{ - // listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot - //}; - adapter.AddToList(tracks); + adapter = new PlaylistTrackAdapter(tracks) + { + listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot + }; adapter.listPadding = MainActivity.paddingBot - MainActivity.defaultPaddingBot; adapter.ItemClick += ListView_ItemClick; adapter.ItemLongClick += ListView_ItemLongClick; @@ -575,25 +535,39 @@ namespace MusicApp.Resources.Portable_Class }; adapter.ItemClick += ListView_ItemClick; adapter.ItemLongClick += ListView_ItemLongClick; + + Android.Support.V7.Widget.Helper.ItemTouchHelper.Callback callback = new ItemTouchCallback(adapter); + itemTouchHelper = new Android.Support.V7.Widget.Helper.ItemTouchHelper(callback); + itemTouchHelper.AttachToRecyclerView(ListView); + ListView.SetAdapter(adapter); } private void ListView_ItemClick(object sender, int Position) { - PlayInOrder(useHeader ? Position : Position - 1, true); + if (useHeader) + Position--; + + PlayInOrder(Position, true); } private void ListView_ItemLongClick(object sender, int Position) { - Song item = tracks[useHeader ? Position : Position - 1]; - if (result != null && result.Count > (useHeader ? Position : Position - 1)) - item = result[useHeader ? Position : Position - 1]; + if (!useHeader) + Position--; - More(item, useHeader ? Position : Position - 1); + Song item = tracks[Position]; + if (result != null && result.Count > Position) + item = result[Position]; + + More(item, Position); } public void More(Song item, int position) { + if (!useHeader) + position--; + List action = actions.ToList(); if (!item.IsYt) @@ -616,8 +590,7 @@ namespace MusicApp.Resources.Portable_Class switch (args.Which) { case 0: - int Position = tracks.IndexOf(item); - PlayInOrder(Position, true); + PlayInOrder(position, true); break; case 1: @@ -635,12 +608,12 @@ namespace MusicApp.Resources.Portable_Class break; case 3: - if (!item.IsYt) + if (playlistId != 0) RemoveFromPlaylist(item); - else + else if(ytID != null) { string ytTrackID = ytTracksIDs[position]; - if (ytTracksIdsResult != null) + if (ytTracksIdsResult != null && ytTracksIdsResult.Count > position) ytTrackID = ytTracksIdsResult[position]; YoutubeEngine.RemoveFromPlaylist(ytTrackID); @@ -675,8 +648,7 @@ namespace MusicApp.Resources.Portable_Class switch (args.Which) { case 0: - int Position = tracks.IndexOf(item); - PlayInOrder(Position, true); + PlayInOrder(position, true); break; case 1: @@ -715,7 +687,7 @@ namespace MusicApp.Resources.Portable_Class builder.Show(); } - async void PlayInOrder(int fromPosition, bool useTransition) + public async void PlayInOrder(int fromPosition, bool useTransition) { List songs = tracks.GetRange(fromPosition, tracks.Count - fromPosition); if (result != null && result.Count - 1 >= fromPosition) @@ -753,10 +725,11 @@ namespace MusicApp.Resources.Portable_Class private void RemoveFromYtPlaylist(Song item, string ytTrackID) { - tracks.Remove(item); ytTracksIDs.Remove(ytTrackID); ytTracksIdsResult?.Remove(ytTrackID); adapter.Remove(item); + tracks.Remove(item); + result?.Remove(item); if (adapter == null || adapter.ItemCount == 0) { isEmpty = true; @@ -769,8 +742,9 @@ namespace MusicApp.Resources.Portable_Class ContentResolver resolver = Activity.ContentResolver; Uri uri = MediaStore.Audio.Playlists.Members.GetContentUri("external", playlistId); resolver.Delete(uri, MediaStore.Audio.Playlists.Members.Id + "=?", new string[] { item.Id.ToString() }); - tracks.Remove(item); adapter.Remove(item); + tracks.Remove(item); + result?.Remove(item); if (adapter == null || adapter.ItemCount == 0) { isEmpty = true; @@ -806,5 +780,31 @@ namespace MusicApp.Resources.Portable_Class MainActivity.instance.SupportActionBar.SetDisplayShowTitleEnabled(true); } } + + public void DeleteDialog(int position) + { + if (!useHeader) + position--; + + Song song = tracks[position]; + if (result != null && result.Count > position) + song = result[position]; + + AlertDialog dialog = new AlertDialog.Builder(MainActivity.instance, MainActivity.dialogTheme) + .SetTitle("Remove " + song.Title + " from playlist ?") + .SetPositiveButton("Yes", (sender, e) => + { + if (ytID != null) + { + YoutubeEngine.RemoveFromPlaylist((ytTracksIdsResult != null && ytTracksIdsResult.Count > position) ? ytTracksIdsResult[position] : ytTracksIDs[position]); + RemoveFromYtPlaylist(song, (ytTracksIdsResult != null && ytTracksIdsResult.Count > position) ? ytTracksIdsResult[position] : ytTracksIDs[position]); + } + else if (playlistId != 0) + RemoveFromPlaylist(song); + }) + .SetNegativeButton("No", (sender, e) => { adapter.NotifyItemChanged(position); }) + .Create(); + dialog.Show(); + } } } diff --git a/MusicApp/Resources/Portable Class/YoutubeEngine.cs b/MusicApp/Resources/Portable Class/YoutubeEngine.cs index da44596..83e5ad7 100644 --- a/MusicApp/Resources/Portable Class/YoutubeEngine.cs +++ b/MusicApp/Resources/Portable Class/YoutubeEngine.cs @@ -577,9 +577,9 @@ namespace MusicApp.Resources.Portable_Class return null; } - public static void RemoveFromPlaylist(string videoID) + public static async void RemoveFromPlaylist(string videoID) { - youtubeService.PlaylistItems.Delete(videoID).Execute(); + await youtubeService.PlaylistItems.Delete(videoID).ExecuteAsync(); } public static async void GetPlaylists(string videoID, Context context) diff --git a/MusicApp/Resources/layout/SongList.xml b/MusicApp/Resources/layout/SongList.xml index 87ae764..bee9f36 100644 --- a/MusicApp/Resources/layout/SongList.xml +++ b/MusicApp/Resources/layout/SongList.xml @@ -3,6 +3,7 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" + android:background="?android:colorBackground" android:padding="8dp" >