Start reworking add to playlits, now working prety well with local playlists.

This commit is contained in:
Anonymous Raccoon
2018-11-18 18:26:10 +01:00
parent 69092ebcae
commit b6ca3e572f
9 changed files with 756 additions and 548 deletions
+7
View File
@@ -259,6 +259,7 @@
<Compile Include="Resources\Portable Class\AccountPreference.cs" />
<Compile Include="Resources\Portable Class\AccountTarget.cs" />
<Compile Include="Resources\Portable Class\Adapter.cs" />
<Compile Include="Resources\Portable Class\AddToPlaylistAdapter.cs" />
<Compile Include="Resources\Portable Class\AudioStopper.cs" />
<Compile Include="Resources\Portable Class\Browse.cs" />
<Compile Include="Resources\Portable Class\ChannelAdapter.cs" />
@@ -734,6 +735,12 @@
<ItemGroup>
<AndroidResource Include="Resources\drawable\Filter.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\AddToPlaylistItem.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\PublicIcon.xml" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Import Project="..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Animated.Vector.Drawable.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Animated.Vector.Drawable.targets')" />
<Import Project="..\packages\Xamarin.Android.Support.v7.Preference.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.v7.Preference.targets" Condition="Exists('..\packages\Xamarin.Android.Support.v7.Preference.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.v7.Preference.targets')" />
@@ -0,0 +1,104 @@
using Android.App;
using Android.Graphics;
using Android.Support.V7.Widget;
using Android.Views;
using Android.Widget;
using System;
using System.Collections.Generic;
namespace MusicApp.Resources.Portable_Class
{
public class AddToPlaylistAdapter : RecyclerView.Adapter
{
private List<PlaylistItem> LocalPlaylists = new List<PlaylistItem>();
private List<PlaylistItem> YoutubePlaylists = new List<PlaylistItem>();
public event EventHandler<int> ItemClick;
public AddToPlaylistAdapter(List<PlaylistItem> LocalPlaylists, List<PlaylistItem> YoutubePlaylists)
{
this.LocalPlaylists = LocalPlaylists;
this.YoutubePlaylists = YoutubePlaylists;
}
public override int ItemCount => LocalPlaylists.Count + YoutubePlaylists.Count;
public override void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)
{
if (position >= LocalPlaylists.Count && YoutubePlaylists[position - LocalPlaylists.Count].Name == "Loading" && YoutubePlaylists[position - LocalPlaylists.Count].YoutubeID == null)
return;
AddToPlaylistHolder holder = (AddToPlaylistHolder)viewHolder;
holder.Title.Text = LocalPlaylists[position].Name;
if((LocalPlaylists.Count > position && LocalPlaylists[position].SongContained) || (position > LocalPlaylists.Count && YoutubePlaylists[position - LocalPlaylists.Count].SongContained))
holder.Added.Checked = true;
else
holder.Added.Checked = false;
if ((LocalPlaylists.Count > position && LocalPlaylists[position].SyncState == SyncState.True) || (position > LocalPlaylists.Count && YoutubePlaylists[position - LocalPlaylists.Count].SyncState == SyncState.True))
{
holder.Status.Visibility = ViewStates.Visible;
holder.Status.SetImageResource(Resource.Drawable.Sync);
}
else if(position >= LocalPlaylists.Count)
{
holder.Status.Visibility = ViewStates.Visible;
holder.Status.SetImageResource(Resource.Drawable.PublicIcon);
}
else
{
holder.Status.Visibility = ViewStates.Gone;
}
if (MainActivity.Theme == 1)
{
holder.Status.SetColorFilter(Color.White);
holder.Title.SetTextColor(Color.White);
}
}
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
if (viewType == 0)
{
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.AddToPlaylistItem, parent, false);
return new AddToPlaylistHolder(itemView, OnClick);
}
else
{
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.smallLoading, parent, false);
return new UslessHolder(itemView);
}
}
public override int GetItemViewType(int position)
{
if (position == LocalPlaylists.Count + YoutubePlaylists.Count - 1 && YoutubePlaylists[position - LocalPlaylists.Count].Name == "Loading")
return 1;
else
return 0;
}
void OnClick(int position)
{
ItemClick?.Invoke(this, position);
}
}
public class AddToPlaylistHolder : RecyclerView.ViewHolder
{
public TextView Title;
public CheckBox Added;
public ImageView Status;
public AddToPlaylistHolder(View itemView, Action<int> listener) : base(itemView)
{
Title = itemView.FindViewById<TextView>(Resource.Id.title);
Added = itemView.FindViewById<CheckBox>(Resource.Id.added);
Status = itemView.FindViewById<ImageView>(Resource.Id.status);
itemView.Click += (sender, e) => listener(AdapterPosition);
}
}
}
+70 -10
View File
@@ -5,8 +5,10 @@ using Android.Database;
using Android.Net;
using Android.OS;
using Android.Provider;
using Android.Support.Design.Widget;
using Android.Support.V4.App;
using Android.Support.V7.App;
using Android.Support.V7.Widget;
using Android.Views;
using Android.Widget;
using MusicApp.Resources.values;
@@ -81,7 +83,7 @@ namespace MusicApp.Resources.Portable_Class
{
musicList = new List<Song>();
Android.Net.Uri musicUri = MediaStore.Audio.Media.ExternalContentUri;
Uri musicUri = MediaStore.Audio.Media.ExternalContentUri;
CursorLoader cursorLoader = new CursorLoader(Android.App.Application.Context, musicUri, null, null, null, null);
ICursor musicCursor = (ICursor)cursorLoader.LoadInBackground();
@@ -327,12 +329,30 @@ namespace MusicApp.Resources.Portable_Class
context.StartService(intent);
}
public static bool SongIsContained(long audioID, long playlistID)
{
Uri uri = MediaStore.Audio.Playlists.Members.GetContentUri("external", playlistID);
CursorLoader loader = new CursorLoader(Android.App.Application.Context, uri, null, null, null, null);
ICursor cursor = (ICursor)loader.LoadInBackground();
if (cursor != null && cursor.MoveToFirst())
{
int idColumn = cursor.GetColumnIndex(MediaStore.Audio.Playlists.Members.AudioId);
do
{
long id = cursor.GetLong(idColumn);
if (id == audioID)
return true;
}
while (cursor.MoveToNext());
cursor.Close();
}
return false;
}
public static void GetPlaylist(Song item)
{
List<string> playList = new List<string>();
List<long> playListId = new List<long>();
playList.Add("Create a playlist");
playListId.Add(0);
List<PlaylistItem> LocalPlaylists = new List<PlaylistItem>();
Uri uri = MediaStore.Audio.Playlists.ExternalContentUri;
CursorLoader loader = new CursorLoader(Android.App.Application.Context, uri, null, null, null, null);
@@ -341,24 +361,64 @@ namespace MusicApp.Resources.Portable_Class
if (cursor != null && cursor.MoveToFirst())
{
int nameID = cursor.GetColumnIndex(MediaStore.Audio.Playlists.InterfaceConsts.Name);
int pathID = cursor.GetColumnIndex(MediaStore.Audio.Playlists.InterfaceConsts.Data);
int playlistID = cursor.GetColumnIndex(MediaStore.Audio.Playlists.InterfaceConsts.Id);
do
{
string name = cursor.GetString(nameID);
long id = cursor.GetLong(playlistID);
playList.Add(name);
playListId.Add(id);
PlaylistItem playlist = new PlaylistItem(name, id)
{
SongContained = SongIsContained(item.Id, id)
};
LocalPlaylists.Add(playlist);
}
while (cursor.MoveToNext());
cursor.Close();
}
List<PlaylistItem> YoutubePlaylists = new List<PlaylistItem>
{
new PlaylistItem("Loading", null)
};
View Layout = inflater.Inflate(Resource.Layout.RecyclerFragment, null);
AlertDialog.Builder builder = new AlertDialog.Builder(act, MainActivity.dialogTheme);
builder.SetTitle("Add to a playlist");
builder.SetItems(playList.ToArray(), (senderAlert, args) =>
builder.SetView(Layout);
RecyclerView ListView = Layout.FindViewById<RecyclerView>(Resource.Id.recycler);
ListView.SetPadding(0, MainActivity.instance.DpToPx(5), 0, 0);
ListView.SetLayoutManager(new LinearLayoutManager(MainActivity.instance));
AddToPlaylistAdapter adapter = new AddToPlaylistAdapter(LocalPlaylists, YoutubePlaylists);
ListView.SetAdapter(adapter);
adapter.ItemClick += async (sender, position) =>
{
AddToPlaylist(item, playList[args.Which], playListId[args.Which]);
});
AddToPlaylistHolder holder = (AddToPlaylistHolder)ListView.GetChildViewHolder(ListView.GetChildAt(position));
bool add = !holder.Added.Checked;
holder.Added.Checked = add;
bool Local = position < LocalPlaylists.Count;
PlaylistItem playlist = Local ? LocalPlaylists[position] : YoutubePlaylists[position - LocalPlaylists.Count];
if (add)
{
if (Local)
AddToPlaylist(item, playlist.Name, playlist.LocalID);
}
else
{
if (playlist.SyncState == SyncState.True && playlist.YoutubeID != null && playlist.LocalID != 0)
{
if (item.TrackID == null)
item = await PlaylistTracks.CompleteItem(item, playlist.YoutubeID);
}
SnackbarCallback callback = new SnackbarCallback(item, playlist.LocalID);
Snackbar snackBar = Snackbar.Make(MainActivity.instance.FindViewById(Resource.Id.snackBar), (item.Title.Length > 20 ? item.Title.Substring(0, 17) + "..." : item.Title) + " has been removed from the playlist.", Snackbar.LengthLong)
.SetAction("Undo", (v) => { callback.canceled = true; });
snackBar.AddCallback(callback);
snackBar.View.FindViewById<TextView>(Resource.Id.snackbar_text).SetTextColor(Android.Graphics.Color.White);
snackBar.Show();
}
};
builder.Show();
}
@@ -299,7 +299,7 @@ namespace MusicApp.Resources.Portable_Class
base.OnStop();
}
private async Task<Song> CompleteItem(Song song)
public static async Task<Song> CompleteItem(Song song, string YoutubeID)
{
if (song.youtubeID == null)
song = Browse.CompleteItem(song);
@@ -484,14 +484,15 @@ namespace MusicApp.Resources.Portable_Class
int titleID = musicCursor.GetColumnIndex(Media.InterfaceConsts.Title);
int artistID = musicCursor.GetColumnIndex(Media.InterfaceConsts.Artist);
int albumID = musicCursor.GetColumnIndex(Media.InterfaceConsts.Album);
int thisID = musicCursor.GetColumnIndex(Media.InterfaceConsts.Id);
int albumArtID = musicCursor.GetColumnIndex(Albums.InterfaceConsts.AlbumId);
int thisID = musicCursor.GetColumnIndex(Playlists.Members.AudioId);
int pathID = musicCursor.GetColumnIndex(Media.InterfaceConsts.Data);
do
{
string Artist = musicCursor.GetString(artistID);
string Title = musicCursor.GetString(titleID);
string Album = musicCursor.GetString(albumID);
long AlbumArt = musicCursor.GetLong(musicCursor.GetColumnIndex(Albums.InterfaceConsts.AlbumId));
long AlbumArt = musicCursor.GetLong(albumArtID);
long id = musicCursor.GetLong(thisID);
string path = musicCursor.GetString(pathID);
@@ -697,7 +698,7 @@ namespace MusicApp.Resources.Portable_Class
builder.SetTitle("Pick an action");
if (hasWriteAcess && YoutubeID != "")
{
builder.SetItems(action.ToArray(), async (senderAlert, args) =>
builder.SetItems(action.ToArray(), (senderAlert, args) =>
{
switch (args.Which)
{
@@ -720,20 +721,7 @@ namespace MusicApp.Resources.Portable_Class
break;
case 3:
if(Synced && LocalID != 0)
{
RemoveFromPlaylist(item);
if (item.TrackID == null)
item = await CompleteItem(item);
YoutubeEngine.RemoveFromPlaylist(item.TrackID);
}
else if (LocalID != 0)
RemoveFromPlaylist(item);
else if(YoutubeID != null)
{
YoutubeEngine.RemoveFromPlaylist(item.TrackID);
RemoveFromYtPlaylist(item, item.TrackID);
}
DeleteDialog(position);
break;
case 4:
@@ -910,9 +898,9 @@ namespace MusicApp.Resources.Portable_Class
if(Synced && YoutubeID != null && LocalID != 0)
{
if (song.TrackID == null)
song = await CompleteItem(song);
song = await CompleteItem(song, YoutubeID);
}
SnackbarCallback callback = new SnackbarCallback(position, song, LocalID);
SnackbarCallback callback = new SnackbarCallback(song, LocalID);
Snackbar snackBar = Snackbar.Make(MainActivity.instance.FindViewById(Resource.Id.snackBar), (song.Title.Length > 20 ? song.Title.Substring(0, 17) + "..." : song.Title) + " has been removed from the playlist.", Snackbar.LengthLong)
.SetAction("Undo", (v) =>
@@ -926,7 +914,7 @@ namespace MusicApp.Resources.Portable_Class
adapter.Insert(position, song);
tracks.Insert(position, song);
}
if (LocalID != 0)
else if (LocalID != 0)
{
adapter.Insert(position, song);
tracks.Insert(position, song);
@@ -8,14 +8,12 @@ namespace MusicApp.Resources.Portable_Class
{
public class SnackbarCallback : BaseTransientBottomBar.BaseCallback
{
private int position;
private Song song;
private long playlistId;
public bool canceled = false;
public SnackbarCallback(int position, Song song, long playlistId)
public SnackbarCallback(Song song, long playlistId)
{
this.position = position;
this.song = song;
this.playlistId = playlistId;
}
@@ -33,7 +31,7 @@ namespace MusicApp.Resources.Portable_Class
{
ContentResolver resolver = MainActivity.instance.ContentResolver;
Uri uri = MediaStore.Audio.Playlists.Members.GetContentUri("external", playlistId);
resolver.Delete(uri, MediaStore.Audio.Playlists.Members.Id + "=?", new string[] { song.Id.ToString() });
resolver.Delete(uri, MediaStore.Audio.Playlists.Members.AudioId + "=?", new string[] { song.Id.ToString() });
}
}
}
+522 -513
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8" ?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:pathData="M0 0h24v24H0z" />
<path
android:pathData="M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2zm-1 17.93c-3.95-.49-7-3.85-7-7.93 0-.62.08-1.21.21-1.79L9 15v1c0 1.1.9 2 2 2v1.93zm6.9-2.54c-.26-.81-1-1.39-1.9-1.39h-1v-3c0-.55-.45-1-1-1H8v-2h2c.55 0 1-.45 1-1V7h2c1.1 0 2-.9 2-2v-.41c2.93 1.19 5 4.06 5 7.41 0 2.08-.8 3.97-2.1 5.39z"
android:fillColor="#000000" />
</vector>
@@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8" ?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:padding="3dp" >
<CheckBox
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingLeft="5dp"
android:layout_centerVertical="true"
android:id="@+id/added" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/title"
android:textSize="14dip"
android:layout_centerVertical="true"
android:layout_toRightOf="@id/added"
android:layout_toLeftOf="@+id/status" />
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@null"
android:id="@+id/status"
android:paddingRight="5dp"
android:layout_centerVertical="true"
android:layout_alignParentRight="true" />
</RelativeLayout>
@@ -16,6 +16,7 @@ namespace MusicApp.Resources.Portable_Class
public string ImageURL { get; set; }
public bool HasWritePermission { get; set; }
public SyncState SyncState = SyncState.False;
public bool SongContained; //For AddToPlaylist dialog
public PlaylistItem() { }