Adding a way to save youtube playlists.

This commit is contained in:
Anonymous Raccoon
2018-05-12 18:39:05 +02:00
parent 91977b2f1b
commit 0c28e46368
13 changed files with 715 additions and 448 deletions
+10
View File
@@ -272,6 +272,7 @@
<Compile Include="Resources\Portable Class\YtFile.cs" />
<Compile Include="Resources\Resource.Designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resources\values\ButtonHolder.cs" />
<Compile Include="Resources\values\ChannelHolder.cs" />
<Compile Include="Resources\values\DownloadFile.cs" />
<Compile Include="Resources\values\EmptyCategoryHolder.cs" />
@@ -556,6 +557,15 @@
<ItemGroup>
<AndroidResource Include="Resources\layout\EmptyYoutubeSearch.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\BorderlessButton.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\layout\SaveAPlaylist.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\Edit.png" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
+1 -1
View File
@@ -25,7 +25,7 @@ namespace MusicApp.Resources.Portable_Class
public static List<HomeSection> adapterItems = new List<HomeSection>();
public View view;
private string[] actions = new string[] { "Play", "Play Next", "Play Last", "Add To Playlist", "Edit Metadata" };
private readonly string[] actions = new string[] { "Play", "Play Next", "Play Last", "Add To Playlist", "Edit Metadata" };
public override void OnActivityCreated(Bundle savedInstanceState)
{
+153 -15
View File
@@ -2,6 +2,7 @@
using Android.Database;
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;
@@ -161,18 +162,53 @@ namespace MusicApp.Resources.Portable_Class
{
Google.Apis.YouTube.v3.Data.Playlist playlist = response.Items[i];
YtPlaylists.Add(playlist);
Song song = new Song(playlist.Snippet.Title, playlist.Snippet.ChannelTitle, playlist.Snippet.Thumbnails.Default__.Url, playlist.Id, -1, -1, playlist.Id, true);
Song song = new Song(playlist.Snippet.Title, playlist.Snippet.ChannelTitle, playlist.Snippet.Thumbnails.Default__.Url, playlist.Id, -1, -1, playlist.Id, true, true);
ytPlaylists.Add(song);
}
adapter.SetYtPlaylists(ytPlaylists, false);
//Saved playlists
ChannelSectionsResource.ListRequest forkedRequest = youtube.ChannelSections.List("snippet,contentDetails");
forkedRequest.Mine = true;
ChannelSectionListResponse forkedResponse = await forkedRequest.ExecuteAsync();
if (instance == null)
return;
bool forkedFound = false;
foreach (ChannelSection section in forkedResponse.Items)
{
if(section.Snippet.Title == "Saved Playlists")
{
for (int i = 0; i < section.ContentDetails.Playlists.Count; i++)
{
PlaylistsResource.ListRequest plRequest = youtube.Playlists.List("snippet, contentDetails");
plRequest.Id = section.ContentDetails.Playlists[i];
if(ytPlaylists.Count == 1)
PlaylistListResponse plResponse = await plRequest.ExecuteAsync();
if (instance == null)
return;
Google.Apis.YouTube.v3.Data.Playlist playlist = plResponse.Items[0];
playlist.Kind = "youtube#saved";
YtPlaylists.Add(playlist);
Song song = new Song(playlist.Snippet.Title, playlist.Snippet.ChannelTitle, playlist.Snippet.Thumbnails.Default__.Url, playlist.Id, -1, -1, playlist.Id, true, false);
ytPlaylists.Add(song);
forkedFound = true;
}
}
}
if (ytPlaylists.Count == 1)
{
ytPlaylists.Add(new Song("EMPTY", "You don't have any youtube playlist on your account. \nWarning: Only playlist from your google account are displayed", null, null, -1, -1, null));
}
adapter.SetYtPlaylists(ytPlaylists);
if (forkedFound)
adapter.SetYtPlaylists(ytPlaylists, true);
else
adapter.SetYtPlaylists(ytPlaylists, true);
}
public static Fragment NewInstance()
@@ -194,6 +230,63 @@ namespace MusicApp.Resources.Portable_Class
private void ListView_ItemClick(object sender, int Position)
{
if(Position == playList.Count + ytPlaylists.Count)
{
View view = LayoutInflater.Inflate(Resource.Layout.SaveAPlaylist, null);
AlertDialog dialog = new AlertDialog.Builder(Activity, MainActivity.dialogTheme)
.SetTitle("Add a Playlist")
.SetView(view)
.SetNegativeButton("Cancel", (s, eventArgs) => { })
.SetPositiveButton("Go", async (s, eventArgs) =>
{
string url = view.FindViewById<EditText>(Resource.Id.playlistURL).Text;
string playlistID = url.Substring(url.IndexOf('=') + 1);
ChannelSectionsResource.ListRequest forkedRequest = YoutubeEngine.youtubeService.ChannelSections.List("snippet,contentDetails");
forkedRequest.Mine = true;
ChannelSectionListResponse forkedResponse = await forkedRequest.ExecuteAsync();
foreach (ChannelSection section in forkedResponse.Items)
{
if (section.Snippet.Title == "Saved Playlists")
{
//AddToSection
if (section.ContentDetails.Playlists.Contains(playlistID))
{
Snackbar.Make(Activity.FindViewById<View>(Resource.Id.snackBar), "You've already added this playlist.", 1).Show();
return;
}
else
{
section.ContentDetails.Playlists.Add(playlistID);
ChannelSectionsResource.UpdateRequest request = YoutubeEngine.youtubeService.ChannelSections.Update(section, "snippet,contentDetails");
ChannelSection response = await request.ExecuteAsync();
Refresh();
return;
}
}
}
//CreateSection and add to it
ChannelSection newSection = new ChannelSection();
ChannelSectionContentDetails details = new ChannelSectionContentDetails();
ChannelSectionSnippet snippet = new ChannelSectionSnippet();
details.Playlists = new List<string>() { playlistID };
snippet.Title = "Saved Playlists";
snippet.Type = "multiplePlaylists";
snippet.Style = "horizontalRow";
newSection.ContentDetails = details;
newSection.Snippet = snippet;
ChannelSectionsResource.InsertRequest insert = YoutubeEngine.youtubeService.ChannelSections.Insert(newSection, "snippet,contentDetails");
ChannelSection insertResponse = await insert.ExecuteAsync();
Refresh();
})
.Show();
return;
}
bool local = Position <= playList.Count;
Song playlist = local ?
new Song(playList[Position], null, null, null, -1, playlistId[Position], null) :
@@ -249,7 +342,7 @@ namespace MusicApp.Resources.Portable_Class
break;
}
});
else
else if(playlist.isParsed)
builder.SetItems(new string[] { "Play in order", "Random play", "Rename", "Delete", "Download" }, (senderAlert, args) =>
{
switch (args.Which)
@@ -273,6 +366,27 @@ namespace MusicApp.Resources.Portable_Class
break;
}
});
else
builder.SetItems(new string[] { "Play in order", "Random play", "Remove", "Download" }, (senderAlert, args) =>
{
switch (args.Which)
{
case 0:
PlayInOrder(playlist.GetPath());
break;
case 1:
YoutubeEngine.RandomPlay(playlist.GetPath());
break;
case 2:
Unfork(Position, playlist.GetPath());
break;
case 3:
YoutubeEngine.DownloadPlaylist(playlist.GetPath());
break;
default:
break;
}
});
builder.Show();
}
@@ -285,11 +399,11 @@ namespace MusicApp.Resources.Portable_Class
if (musicCursor != null && musicCursor.MoveToFirst())
{
int titleID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Title);
int artistID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Artist);
int albumID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Album);
int thisID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Id);
int pathID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Data);
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 pathID = musicCursor.GetColumnIndex(Media.InterfaceConsts.Data);
do
{
string Artist = musicCursor.GetString(artistID);
@@ -449,16 +563,16 @@ namespace MusicApp.Resources.Portable_Class
{
Google.Apis.YouTube.v3.Data.Playlist playlist = new Google.Apis.YouTube.v3.Data.Playlist
{
Snippet = YtPlaylists[position].Snippet
Snippet = YtPlaylists[position - playList.Count].Snippet
};
playlist.Snippet.Title = name;
playlist.Id = playlistID;
YtPlaylists[position].Snippet.Title = name;
YtPlaylists[position - playList.Count].Snippet.Title = name;
YoutubeEngine.youtubeService.Playlists.Update(playlist, "snippet").Execute();
ytPlaylists[position].SetName(name);
adapter.UpdateElement(position, ytPlaylists[position]);
ytPlaylists[position - playList.Count].SetName(name);
adapter.UpdateElement(position, ytPlaylists[position - playList.Count]);
}
void RemoveYoutubePlaylist(int position, string playlistID)
@@ -466,8 +580,32 @@ namespace MusicApp.Resources.Portable_Class
PlaylistsResource.DeleteRequest deleteRequest = YoutubeEngine.youtubeService.Playlists.Delete(playlistID);
deleteRequest.Execute();
ytPlaylists.RemoveAt(position);
YtPlaylists.RemoveAt(position);
adapter.Remove(position);
YtPlaylists.RemoveAt(position - playList.Count);
if (ytPlaylists.Count == 1)
{
ytPlaylists.Add(new Song("EMPTY", "You don't have any youtube playlist on your account. \nWarning: Only playlist from your google account are displayed", null, null, -1, -1, null));
}
}
async void Unfork(int position, string playlistID)
{
ChannelSectionsResource.ListRequest forkedRequest = YoutubeEngine.youtubeService.ChannelSections.List("snippet,contentDetails");
forkedRequest.Mine = true;
ChannelSectionListResponse forkedResponse = await forkedRequest.ExecuteAsync();
foreach (ChannelSection section in forkedResponse.Items)
{
if (section.Snippet.Title == "Saved Playlists")
{
section.ContentDetails.Playlists.Remove(playlistID);
ChannelSectionsResource.UpdateRequest request = YoutubeEngine.youtubeService.ChannelSections.Update(section, "snippet,contentDetails");
ChannelSection response = await request.ExecuteAsync();
}
}
YtPlaylists.RemoveAt(position - playList.Count);
adapter.Remove(position);
if (ytPlaylists.Count == 1)
@@ -1,5 +1,6 @@
using Android.App;
using Android.Graphics;
using Android.Graphics.Drawables;
using Android.Support.V7.Widget;
using Android.Views;
using Android.Widget;
@@ -15,6 +16,7 @@ namespace MusicApp.Resources.Portable_Class
private List<string> playlistsName;
private List<int> playlistCount;
private List<Song> ytPlaylists;
private bool? forkSaved = false;
public int listPadding;
public event EventHandler<int> ItemClick;
public event EventHandler<int> ItemLongCLick;
@@ -45,32 +47,30 @@ namespace MusicApp.Resources.Portable_Class
{
playlistsName.RemoveAt(position);
playlistCount.RemoveAt(position);
//NotifyItemRangeInserted(position, 1);
if (playlistsName.Count == 1)
{
playlistsName.Add("EMPTY - You don't have any playlist on your device.");
playlistCount.Add(-1);
//NotifyItemRangeInserted(2, 1);
}
}
else
{
ytPlaylists.RemoveAt(position - playlistsName.Count);
//NotifyItemRangeInserted(position - playlistsName.Count, 1);
if (ytPlaylists.Count == 1)
{
ytPlaylists.Add(new Song("EMPTY", "You don't have any youtube playlist on your account. \nWarning: Only playlist from your google account are displayed", null, null, -1, -1, null));
//NotifyItemRangeInserted(playlistsName.Count + 2, 1);
}
}
NotifyDataSetChanged();
}
public void SetYtPlaylists(List<Song> ytPlaylists)
public void SetYtPlaylists(List<Song> ytPlaylists, bool forkSaved)
{
if(this.ytPlaylists.Count > 0)
this.forkSaved = forkSaved;
if (this.ytPlaylists.Count > 0)
NotifyItemRangeRemoved(playlistsName.Count + 1, this.ytPlaylists.Count);
this.ytPlaylists = ytPlaylists;
@@ -78,7 +78,7 @@ namespace MusicApp.Resources.Portable_Class
NotifyItemRangeInserted(playlistsName.Count + 1, ytPlaylists.Count);
}
public override int ItemCount => playlistsName.Count + ytPlaylists.Count;
public override int ItemCount => playlistsName.Count + ytPlaylists.Count + (forkSaved == true ? 1 : 0);
public override void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)
{
@@ -97,6 +97,20 @@ namespace MusicApp.Resources.Portable_Class
EmptyCategoryHolder holder = (EmptyCategoryHolder)viewHolder;
holder.text.Text = playlistsName[1].Substring(8);
}
else if (position == playlistsName.Count + ytPlaylists.Count)
{
ButtonHolder holder = (ButtonHolder)viewHolder;
if (MainActivity.Theme == 1)
{
((GradientDrawable)holder.ItemView.Background).SetStroke(5, Android.Content.Res.ColorStateList.ValueOf(Color.Argb(255, 62, 80, 180)));
holder.Button.SetTextColor(Color.Argb(255, 62, 80, 180));
}
else
{
((GradientDrawable)holder.ItemView.Background).SetStroke(5, Android.Content.Res.ColorStateList.ValueOf(Color.Argb(255, 21, 183, 237)));
holder.Button.SetTextColor(Color.Argb(255, 21, 183, 237));
}
}
else if (playlistsName.Count >= position)
{
TwoLineHolder holder = (TwoLineHolder) viewHolder;
@@ -137,7 +151,7 @@ namespace MusicApp.Resources.Portable_Class
holder.more.LayoutParameters = layoutParams;
}
}
else if(position > playlistsName.Count)
else if (position > playlistsName.Count && ytPlaylists.Count >= position - playlistsName.Count)
{
RecyclerHolder holder = (RecyclerHolder)viewHolder;
Song song = ytPlaylists[position - playlistsName.Count];
@@ -148,6 +162,15 @@ namespace MusicApp.Resources.Portable_Class
var songAlbumArtUri = Android.Net.Uri.Parse(song.GetAlbum());
Picasso.With(Application.Context).Load(songAlbumArtUri).Placeholder(Resource.Drawable.MusicIcon).Resize(400, 400).CenterCrop().Into(holder.AlbumArt);
if (song.isParsed)
{
holder.edit.Visibility = ViewStates.Visible;
if (MainActivity.Theme == 1)
holder.edit.SetColorFilter(Color.White);
}
else
holder.edit.Visibility = ViewStates.Gone;
holder.more.Tag = position;
if (!holder.more.HasOnClickListeners)
{
@@ -201,6 +224,11 @@ namespace MusicApp.Resources.Portable_Class
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.SongList, parent, false);
return new RecyclerHolder(itemView, OnClick, OnLongClick);
}
else if (viewType == 3)
{
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.BorderlessButton, parent, false);
return new ButtonHolder(itemView, OnClick);
}
else
{
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.EmptyListCategory, parent, false);
@@ -214,10 +242,12 @@ namespace MusicApp.Resources.Portable_Class
return 0;
else if (playlistsName.Count >= position && (playlistsName.Count > 2 || !playlistsName[1].StartsWith("EMPTY - ")))
return 1;
else if(position > playlistsName.Count && (ytPlaylists.Count > 2 || ytPlaylists[1].GetName() != "EMPTY"))
else if(position > playlistsName.Count && position < playlistsName.Count + ytPlaylists.Count && (ytPlaylists.Count > 2 || ytPlaylists[1].GetName() != "EMPTY"))
return 2;
else
else if (position == playlistsName.Count + ytPlaylists.Count)
return 3;
else
return 4;
}
void OnClick(int position)
@@ -13,6 +13,7 @@ namespace MusicApp.Resources.Portable_Class
public TextView Title;
public TextView Artist;
public ImageView AlbumArt;
public ImageView edit;
public ImageView youtubeIcon;
public ImageView more;
@@ -23,6 +24,7 @@ namespace MusicApp.Resources.Portable_Class
Title = itemView.FindViewById<TextView>(Resource.Id.title);
Artist = itemView.FindViewById<TextView>(Resource.Id.artist);
AlbumArt = itemView.FindViewById<ImageView>(Resource.Id.albumArt);
edit = itemView.FindViewById<ImageView>(Resource.Id.edit);
youtubeIcon = itemView.FindViewById<ImageView>(Resource.Id.youtubeIcon);
more = itemView.FindViewById<ImageView>(Resource.Id.moreButton);
@@ -25,6 +25,8 @@ namespace MusicApp.Resources.Portable_Class
public async override void OnActivityCreated(Bundle savedInstanceState)
{
base.OnActivityCreated(savedInstanceState);
if(MainActivity.Theme == 0)
ListView.SetBackgroundColor(Android.Graphics.Color.White);
await MainActivity.instance.WaitForYoutube();
+425 -407
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 242 B

@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8" ?>
<Button
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_marginLeft="20dp"
android:layout_marginRight="20dp"
android:background="@drawable/FlatButtonBorder"
android:id="@+id/button"
android:text="Add a playlist" />
@@ -1,16 +1,17 @@
<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<EditText
android:id="@+id/playlistName"
android:inputType="text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="4dp"
android:hint="Playlist Name" />
android:id="@+id/playlistName"
android:inputType="text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="4dp"
android:hint="Playlist Name" />
</LinearLayout>
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8" ?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="wrap_content">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="4dp"
android:text="You can add any youtube playlist by entering the playlist url in this field. You can find a playlist url by clicking the share button on the youtube app then click Copy Link. \nWarning: it will add a section &quot;Saved Playlists&quot; on your youtube channel."/>
<EditText
android:id="@+id/playlistURL"
android:inputType="text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:layout_marginLeft="8dp"
android:layout_marginRight="8dp"
android:layout_marginBottom="4dp"
android:hint="Playlist URL" />
</LinearLayout>
+10 -2
View File
@@ -53,12 +53,20 @@
android:layout_alignParentRight="true" >
<ImageView
android:id="@+id/youtubeIcon"
android:layout_width="50dp"
android:layout_height="50dp"
android:layout_width="30dp"
android:layout_height="30dp"
android:padding="5dp"
android:background="@null"
android:src="@drawable/youtubeIcon"
android:visibility="gone" />
<ImageView
android:id="@+id/edit"
android:layout_width="30dp"
android:layout_height="30dp"
android:padding="5dp"
android:background="@null"
android:src="@drawable/Edit"
android:visibility="gone" />
<ImageView
android:id="@+id/moreButton"
android:layout_width="30dp"
+22
View File
@@ -0,0 +1,22 @@
using Android.Support.V7.Widget;
using Android.Views;
using Android.Widget;
using System;
namespace MusicApp.Resources.values
{
public class ButtonHolder : RecyclerView.ViewHolder
{
public Button Button;
public ButtonHolder(View itemView, Action<int> listener) : base(itemView)
{
Button = itemView.FindViewById<Button>(Resource.Id.button);
if (listener != null)
{
itemView.Click += (sender, e) => listener(AdapterPosition);
}
}
}
}