From 51b971269688e481b5925bbc09b1eb425d3b874e Mon Sep 17 00:00:00 2001
From: Tristan Roux
Date: Tue, 23 Apr 2019 00:02:09 +0200
Subject: [PATCH] Finishing playlisttracks rework for local and youtube
playlists.
---
Opus/Code/DataStructure/PlaylistItem.cs | 1 +
Opus/Code/DataStructure/SearchableList.cs | 56 ++++
Opus/Code/Others/ItemTouchCallback.cs | 2 +-
Opus/Code/UI/Adapter/BaseCursor.cs | 18 +-
Opus/Code/UI/Adapter/BrowseAdapter.cs | 7 +-
Opus/Code/UI/Adapter/PlaylistTrackAdapter.cs | 134 +++++----
Opus/Code/UI/Fragments/Home.cs | 4 +-
Opus/Code/UI/Fragments/Playlist.cs | 6 +-
Opus/Code/UI/Fragments/PlaylistTracks.cs | 258 +++++++++---------
Opus/Code/UI/Fragments/Queue.cs | 2 +-
Opus/Opus.csproj | 3 +-
Opus/Resources/Resource.Designer.cs | 130 ++++-----
...ecyclerFragment.xml => LonelyRecycler.xml} | 0
13 files changed, 359 insertions(+), 262 deletions(-)
create mode 100644 Opus/Code/DataStructure/SearchableList.cs
rename Opus/Resources/layout/{RecyclerFragment.xml => LonelyRecycler.xml} (100%)
diff --git a/Opus/Code/DataStructure/PlaylistItem.cs b/Opus/Code/DataStructure/PlaylistItem.cs
index 55ffe63..10ef731 100644
--- a/Opus/Code/DataStructure/PlaylistItem.cs
+++ b/Opus/Code/DataStructure/PlaylistItem.cs
@@ -33,6 +33,7 @@ namespace Opus.DataStructure
public PlaylistItem(string Name, string YoutubeID, Google.Apis.YouTube.v3.Data.Playlist Snippet = null, int Count = 0)
{
this.Name = Name;
+ LocalID = -1;
this.YoutubeID = YoutubeID;
this.Snippet = Snippet;
this.Count = Count;
diff --git a/Opus/Code/DataStructure/SearchableList.cs b/Opus/Code/DataStructure/SearchableList.cs
new file mode 100644
index 0000000..9d99931
--- /dev/null
+++ b/Opus/Code/DataStructure/SearchableList.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Opus.DataStructure
+{
+ [Serializable]
+ public class SearchableList : List
+ {
+ private List cachedList = null;
+ private List CachedList
+ {
+ get
+ {
+ return cachedList ?? this;
+ }
+ set
+ {
+ cachedList = value;
+ }
+ }
+
+ private Func filter = x => true;
+
+ public SearchableList() { }
+ public SearchableList(IEnumerable collection) : base(collection) { AddRange(collection); }
+
+ public void SetFilter(Func filter)
+ {
+ this.filter = filter;
+ cachedList = this.Where(filter).ToList();
+ }
+
+
+ public new T this[int index]
+ {
+ get
+ {
+ return CachedList[index];
+ }
+ }
+
+ public new int Count
+ {
+ get
+ {
+ return CachedList.Count;
+ }
+ }
+
+ public void Invalidate()
+ {
+ cachedList = this.Where(filter).ToList();
+ }
+ }
+}
\ No newline at end of file
diff --git a/Opus/Code/Others/ItemTouchCallback.cs b/Opus/Code/Others/ItemTouchCallback.cs
index f9e484f..9845df7 100644
--- a/Opus/Code/Others/ItemTouchCallback.cs
+++ b/Opus/Code/Others/ItemTouchCallback.cs
@@ -23,7 +23,7 @@ namespace Opus.Others
if (alwaysAllowSwap)
return true;
- if (PlaylistTracks.instance != null && (!PlaylistTracks.instance.item.HasWritePermission || ((PlaylistTrackAdapter)adapter)?.IsEmpty == true))
+ if (PlaylistTracks.instance != null && (!PlaylistTracks.instance.item.HasWritePermission || ((PlaylistTrackAdapter)adapter)?.BaseCount == 0))
return false;
return true;
}
diff --git a/Opus/Code/UI/Adapter/BaseCursor.cs b/Opus/Code/UI/Adapter/BaseCursor.cs
index 559bf0f..4da4a9d 100644
--- a/Opus/Code/UI/Adapter/BaseCursor.cs
+++ b/Opus/Code/UI/Adapter/BaseCursor.cs
@@ -11,7 +11,7 @@ namespace Opus.Adapter
/// This is the number of items (for example headers) there is before the list represented by the cursor.
///
public abstract int ItemBefore { get; }
- public int BaseCount { get { return cursor != null ? cursor.Count : 0; } }
+ public virtual int BaseCount { get { return cursor != null ? cursor.Count : 0; } }
public override int ItemCount => BaseCount + ItemBefore;
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
@@ -21,14 +21,16 @@ namespace Opus.Adapter
}
public abstract void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, T item);
- public void SwapCursor(ICursor newCursor)
+ public void SwapCursor(ICursor newCursor, bool loadingHandling = true)
{
if (newCursor == cursor)
return;
if (newCursor != null)
{
- MainActivity.instance.FindViewById(Resource.Id.loading).Visibility = ViewStates.Gone;
+ if(loadingHandling)
+ MainActivity.instance.FindViewById(Resource.Id.loading).Visibility = ViewStates.Gone;
+
cursor = newCursor;
NotifyDataSetChanged();
}
@@ -36,7 +38,9 @@ namespace Opus.Adapter
{
NotifyItemRangeRemoved(0, ItemCount);
cursor = null;
- MainActivity.instance.FindViewById(Resource.Id.loading).Visibility = ViewStates.Visible;
+
+ if(loadingHandling)
+ MainActivity.instance.FindViewById(Resource.Id.loading).Visibility = ViewStates.Visible;
}
}
@@ -46,7 +50,7 @@ namespace Opus.Adapter
return Convert(cursor);
}
- public void OnClick(int position)
+ public virtual void OnClick(int position)
{
if (position >= ItemBefore)
{
@@ -59,7 +63,7 @@ namespace Opus.Adapter
public abstract void Clicked(T item, int position);
public virtual void HeaderClicked(int position) { }
- public void OnLongClick(int position)
+ public virtual void OnLongClick(int position)
{
if (position >= ItemBefore)
{
@@ -69,7 +73,7 @@ namespace Opus.Adapter
else
HeaderLongClicked(position);
}
- public abstract void LongClicked(T item, int positon);
+ public abstract void LongClicked(T item, int position);
public virtual void HeaderLongClicked(int position) { }
public abstract T Convert(ICursor cursor);
diff --git a/Opus/Code/UI/Adapter/BrowseAdapter.cs b/Opus/Code/UI/Adapter/BrowseAdapter.cs
index 99e50d8..815efc5 100644
--- a/Opus/Code/UI/Adapter/BrowseAdapter.cs
+++ b/Opus/Code/UI/Adapter/BrowseAdapter.cs
@@ -4,7 +4,6 @@ using Android.Database;
using Android.Graphics;
using Android.Support.V7.Widget;
using Android.Views;
-using Opus.Api;
using Opus.DataStructure;
using Opus.Fragments;
using Square.Picasso;
@@ -17,9 +16,9 @@ namespace Opus.Adapter
public bool displayShuffle;
public override int ItemBefore => (displayShuffle && BaseCount != 0) ? 1 : 0;
- private Action clickAction;
- private Action longClickAction;
- private Action headerAction;
+ private readonly Action clickAction;
+ private readonly Action longClickAction;
+ private readonly Action headerAction;
public BrowseAdapter(Action clickAction, Action longClickAction, Action headerAction = null)
{
diff --git a/Opus/Code/UI/Adapter/PlaylistTrackAdapter.cs b/Opus/Code/UI/Adapter/PlaylistTrackAdapter.cs
index 17e6a2a..7c404cd 100644
--- a/Opus/Code/UI/Adapter/PlaylistTrackAdapter.cs
+++ b/Opus/Code/UI/Adapter/PlaylistTrackAdapter.cs
@@ -1,6 +1,7 @@
using Android.App;
using Android.Content;
using Android.Content.Res;
+using Android.Database;
using Android.Graphics;
using Android.Support.V7.Widget;
using Android.Views;
@@ -10,55 +11,62 @@ using Opus.DataStructure;
using Opus.Fragments;
using Opus.Others;
using Square.Picasso;
-using System;
-using System.Collections.Generic;
namespace Opus.Adapter
{
- public class PlaylistTrackAdapter : RecyclerView.Adapter, IItemTouchAdapter
+ public class PlaylistTrackAdapter : BaseCursor, IItemTouchAdapter
{
- public List songList;
- public event EventHandler ItemClick;
- public event EventHandler ItemLongClick;
- public int listPadding;
- public bool IsEmpty = false;
+ public SearchableList tracks;
public bool IsSliding { get; set; }
- public PlaylistTrackAdapter(List songList)
+
+ public PlaylistTrackAdapter() { }
+ public PlaylistTrackAdapter(SearchableList tracks)
{
- this.songList = songList;
+ this.tracks = tracks;
+ cursor = null;
}
- public override int ItemCount
+ public override int ItemBefore
{
get
{
- int count = songList.Count + (PlaylistTracks.instance.fullyLoadded ? 0 : 1) + (PlaylistTracks.instance.useHeader ? 0 : 1);
- if (count == 0 || (count == 1 && !PlaylistTracks.instance.useHeader))
- {
- IsEmpty = true;
+ int count = PlaylistTracks.instance.useHeader ? 0 : 1; //Display the smallheader if the playlist doesnt use the big header
+ if (BaseCount == 0 && PlaylistTracks.instance.fullyLoadded) //Display an empty view if the playlist is fully loaded and there is no tracks
count++;
- }
return count;
}
}
+ private int ItemAfter
+ {
+ get
+ {
+ return PlaylistTracks.instance.fullyLoadded ? 0 : 1; //Display a loading bar if the playlist is not fully loaded
+ }
+ }
+
+ public override int BaseCount => tracks == null ? base.BaseCount : tracks.Count;
+ public override int ItemCount => base.ItemCount + ItemAfter;
+
+
public override void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)
{
- if(IsEmpty && position + 1 == ItemCount)
+ if (position == ItemCount - 1 && !PlaylistTracks.instance.fullyLoadded)
+ {
+ int pad = MainActivity.instance.DpToPx(30);
+ ((RecyclerView.LayoutParams)viewHolder.ItemView.LayoutParameters).TopMargin = pad;
+ ((RecyclerView.LayoutParams)viewHolder.ItemView.LayoutParameters).BottomMargin = pad;
+ }
+ else if (BaseCount == 0 && position == 0)
{
((TextView)viewHolder.ItemView).Text = MainActivity.instance.GetString(Resource.String.playlist_empty);
- return;
}
-
- if (!PlaylistTracks.instance.useHeader)
- position--;
-
- if(position == -1 && !PlaylistTracks.instance.useHeader)
+ else if (position == 0 && !PlaylistTracks.instance.useHeader)
{
View header = viewHolder.ItemView;
- header.FindViewById(Resource.Id.headerNumber).Text = songList.Count + " " + (songList.Count < 2 ? MainActivity.instance.GetString(Resource.String.element) : MainActivity.instance.GetString(Resource.String.elements));
+ header.FindViewById(Resource.Id.headerNumber).Text = tracks.Count + " " + (tracks.Count < 2 ? MainActivity.instance.GetString(Resource.String.element) : MainActivity.instance.GetString(Resource.String.elements));
if (!header.FindViewById(Resource.Id.headerPlay).HasOnClickListeners)
{
header.FindViewById(Resource.Id.headerPlay).Click += (sender, e0) => { PlaylistManager.PlayInOrder(PlaylistTracks.instance.item); };
@@ -82,32 +90,34 @@ namespace Opus.Adapter
header.FindViewById(Resource.Id.headerShuffle).ImageTintList = ColorStateList.ValueOf(Color.Black);
header.FindViewById(Resource.Id.headerMore).ImageTintList = ColorStateList.ValueOf(Color.Black);
}
-
- return;
}
+ else if (tracks != null)
+ OnBindViewHolder(viewHolder, tracks[position - ItemBefore]);
+ else
+ base.OnBindViewHolder(viewHolder, position);
+ }
- if(position >= songList.Count)
- return;
-
+ public override void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, Song item)
+ {
SongHolder holder = (SongHolder)viewHolder;
- holder.Title.Text = songList[position].Title;
- holder.Artist.Text = songList[position].Artist;
+ holder.Title.Text = item.Title;
+ holder.Artist.Text = item.Artist;
- if (songList[position].AlbumArt == -1 || songList[position].IsYt)
+ if (item.AlbumArt == -1 || item.IsYt)
{
- var songAlbumArtUri = Android.Net.Uri.Parse(songList[position].Album);
- Picasso.With(Application.Context).Load(songAlbumArtUri).Placeholder(Resource.Color.background_material_dark).Transform(new RemoveBlackBorder(true)).Into(holder.AlbumArt);
+ var songAlbumArtUri = Android.Net.Uri.Parse(item.Album);
+ Picasso.With(Application.Context).Load(songAlbumArtUri).Placeholder(Resource.Color.placeholder).Transform(new RemoveBlackBorder(true)).Into(holder.AlbumArt);
}
else
{
var songCover = Android.Net.Uri.Parse("content://media/external/audio/albumart");
- var songAlbumArtUri = ContentUris.WithAppendedId(songCover, songList[position].AlbumArt);
+ var songAlbumArtUri = ContentUris.WithAppendedId(songCover, item.AlbumArt);
- Picasso.With(Application.Context).Load(songAlbumArtUri).Placeholder(Resource.Color.background_material_dark).Resize(400, 400).CenterCrop().Into(holder.AlbumArt);
+ Picasso.With(Application.Context).Load(songAlbumArtUri).Placeholder(Resource.Color.placeholder).Resize(400, 400).CenterCrop().Into(holder.AlbumArt);
}
- if (songList[position].IsLiveStream)
+ if (item.IsLiveStream)
holder.Live.Visibility = ViewStates.Visible;
else
holder.Live.Visibility = ViewStates.Gone;
@@ -116,7 +126,7 @@ namespace Opus.Adapter
{
holder.more.Click += (sender, e) =>
{
- PlaylistTracks.instance.More(holder.AdapterPosition);
+ PlaylistTracks.instance.More(tracks == null ? GetItem(holder.AdapterPosition) : tracks[holder.AdapterPosition], holder.AdapterPosition);
};
}
@@ -131,6 +141,37 @@ namespace Opus.Adapter
}
}
+ public override void OnClick(int position)
+ {
+ if (tracks != null && position >= ItemBefore)
+ Clicked(tracks[position - ItemBefore], position - ItemBefore);
+ else
+ base.OnClick(position);
+ }
+
+ public override void Clicked(Song item, int position)
+ {
+ PlaylistManager.PlayInOrder(PlaylistTracks.instance.item, position);
+ }
+
+ public override void OnLongClick(int position)
+ {
+ if (tracks != null && position >= ItemBefore)
+ LongClicked(tracks[position - ItemBefore], position - ItemBefore);
+ else
+ base.OnLongClick(position);
+ }
+
+ public override void LongClicked(Song item, int position)
+ {
+ PlaylistTracks.instance.More(item, position);
+ }
+
+ public override Song Convert(ICursor cursor)
+ {
+ return Song.FromCursor(cursor);
+ }
+
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
{
if(viewType == 0)
@@ -157,25 +198,16 @@ namespace Opus.Adapter
public override int GetItemViewType(int position)
{
- if (IsEmpty && position + 1 == ItemCount)
+ if (position == ItemCount - 1 && !PlaylistTracks.instance.fullyLoadded)
+ return 1;
+ else if (BaseCount == 0 && position == 0)
return 3;
if (position == 0 && !PlaylistTracks.instance.useHeader)
return 2;
- else if (position - (PlaylistTracks.instance.useHeader ? 0 : 1) >= songList.Count)
- return 1;
return 0;
}
- void OnClick(int position)
- {
- ItemClick?.Invoke(this, position);
- }
-
- void OnLongClick(int position)
- {
- ItemLongClick?.Invoke(this, position);
- }
public void ItemMoved(int fromPosition, int toPosition) { }
@@ -183,7 +215,7 @@ namespace Opus.Adapter
public void ItemDismissed(int position)
{
- PlaylistTracks.instance.RemoveFromPlaylist(songList[position], position);
+ PlaylistTracks.instance.RemoveFromPlaylist(tracks[position], position);
}
}
}
\ No newline at end of file
diff --git a/Opus/Code/UI/Fragments/Home.cs b/Opus/Code/UI/Fragments/Home.cs
index b290753..8db1493 100644
--- a/Opus/Code/UI/Fragments/Home.cs
+++ b/Opus/Code/UI/Fragments/Home.cs
@@ -48,7 +48,8 @@ namespace Opus.Fragments
#pragma warning disable CS4014
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
- view = inflater.Inflate(Resource.Layout.RecyclerFragment, container, false);
+ view = inflater.Inflate(Resource.Layout.CompleteRecycler, container, false);
+ view.FindViewById(Resource.Id.loading).Visibility = ViewStates.Visible;
ListView = view.FindViewById(Resource.Id.recycler);
ListView.SetLayoutManager(new LinearLayoutManager(Android.App.Application.Context));
@@ -122,6 +123,7 @@ namespace Opus.Fragments
}
}
+ view.FindViewById(Resource.Id.loading).Visibility = ViewStates.Gone;
adapter = new HomeAdapter(adapterItems);
ListView.SetAdapter(adapter);
adapter.ItemClick += ListView_ItemClick;
diff --git a/Opus/Code/UI/Fragments/Playlist.cs b/Opus/Code/UI/Fragments/Playlist.cs
index cae70cd..8d94a9c 100644
--- a/Opus/Code/UI/Fragments/Playlist.cs
+++ b/Opus/Code/UI/Fragments/Playlist.cs
@@ -25,6 +25,7 @@ namespace Opus.Fragments
public static Playlist instance;
public RecyclerView ListView;
private PlaylistAdapter adapter;
+ private View LoadingView;
private bool populating = false;
private List LocalPlaylists = new List();
@@ -46,7 +47,9 @@ namespace Opus.Fragments
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
- View view = inflater.Inflate(Resource.Layout.RecyclerFragment, container, false);
+ View view = inflater.Inflate(Resource.Layout.CompleteRecycler, container, false);
+ LoadingView = view.FindViewById(Resource.Id.loading);
+ LoadingView.Visibility = ViewStates.Visible;
ListView = view.FindViewById(Resource.Id.recycler);
ListView.SetLayoutManager(new LinearLayoutManager(Application.Context));
instance = this;
@@ -92,6 +95,7 @@ namespace Opus.Fragments
YoutubePlaylists.AddRange(SyncedPlaylists);
//Display this for now, we'll load non synced youtube playlist in the background.
+ LoadingView.Visibility = ViewStates.Gone;
YoutubePlaylists.Add(Loading);
adapter = new PlaylistAdapter(LocalPlaylists, YoutubePlaylists);
ListView.SetAdapter(adapter);
diff --git a/Opus/Code/UI/Fragments/PlaylistTracks.cs b/Opus/Code/UI/Fragments/PlaylistTracks.cs
index 845e020..3536f12 100644
--- a/Opus/Code/UI/Fragments/PlaylistTracks.cs
+++ b/Opus/Code/UI/Fragments/PlaylistTracks.cs
@@ -6,6 +6,7 @@ using Android.Support.Design.Widget;
using Android.Support.V4.App;
using Android.Views;
using Android.Widget;
+using Java.Lang;
using Opus.Adapter;
using Opus.Api;
using Opus.DataStructure;
@@ -22,24 +23,26 @@ using Toolbar = Android.Support.V7.Widget.Toolbar;
namespace Opus.Fragments
{
- public class PlaylistTracks : Fragment, PopupMenu.IOnMenuItemClickListener, AppBarLayout.IOnOffsetChangedListener
+ public class PlaylistTracks : Fragment, PopupMenu.IOnMenuItemClickListener, AppBarLayout.IOnOffsetChangedListener, LoaderManager.ILoaderCallbacks
{
public static PlaylistTracks instance;
public PlaylistItem item;
+
+ public TextView EmptyView;
public RecyclerView ListView;
public PlaylistTrackAdapter adapter;
private Android.Support.V7.Widget.Helper.ItemTouchHelper itemTouchHelper;
- public List result = null;
+
+ private string query;
private string nextPageToken = null;
public bool fullyLoadded = true;
public bool forked;
public bool lastVisible = false;
public bool useHeader = true;
public bool navigating = false;
-
- public List tracks = new List();
private bool loading = false;
+
public override void OnActivityCreated(Bundle savedInstanceState)
{
base.OnActivityCreated(savedInstanceState);
@@ -55,10 +58,10 @@ namespace Opus.Fragments
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
- View view = inflater.Inflate(Resource.Layout.RecyclerFragment, container, false);
+ View view = inflater.Inflate(Resource.Layout.LonelyRecycler, container, false);
ListView = view.FindViewById(Resource.Id.recycler);
ListView.SetLayoutManager(new Android.Support.V7.Widget.LinearLayoutManager(MainActivity.instance));
- ListView.SetAdapter(new PlaylistTrackAdapter(new List()));
+ ListView.SetAdapter(new PlaylistTrackAdapter(new SearchableList()));
ListView.ScrollChange += ListView_ScrollChange;
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
@@ -72,9 +75,7 @@ namespace Opus.Fragments
private void ListView_ScrollChange(object sender, View.ScrollChangeEventArgs e)
{
if (((Android.Support.V7.Widget.LinearLayoutManager)ListView?.GetLayoutManager())?.FindLastVisibleItemPosition() == adapter?.ItemCount - 1)
-#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
LoadMore();
-#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
}
void CreateHeader()
@@ -85,9 +86,9 @@ namespace Opus.Fragments
Activity.FindViewById(Resource.Id.headerTitle).Text = item.Name;
if (!Activity.FindViewById(Resource.Id.headerPlay).HasOnClickListeners)
- Activity.FindViewById(Resource.Id.headerPlay).Click += (sender, e0) => { PlaylistManager.PlayInOrder(item); };
+ Activity.FindViewById(Resource.Id.headerPlay).Click += HeaderPlay;
if (!Activity.FindViewById(Resource.Id.headerShuffle).HasOnClickListeners)
- Activity.FindViewById(Resource.Id.headerShuffle).Click += (sender, e0) => { PlaylistManager.Shuffle(item); };
+ Activity.FindViewById(Resource.Id.headerShuffle).Click += HeaderShuffle;
if (!Activity.FindViewById(Resource.Id.headerMore).HasOnClickListeners)
Activity.FindViewById(Resource.Id.headerMore).Click += PlaylistMore;
@@ -107,8 +108,20 @@ namespace Opus.Fragments
Activity.FindViewById(Resource.Id.collapsingToolbar).RequestLayout();
}
+ void HeaderPlay(object sender, System.EventArgs e)
+ {
+ PlaylistManager.PlayInOrder(item);
+ }
+
+ void HeaderShuffle(object sender, System.EventArgs e)
+ {
+ PlaylistManager.Shuffle(item);
+ }
+
public override void OnDestroyView()
{
+ Activity.FindViewById(Resource.Id.headerPlay).Click -= HeaderPlay;
+ Activity.FindViewById(Resource.Id.headerShuffle).Click -= HeaderShuffle;
Activity.FindViewById(Resource.Id.headerMore).Click -= PlaylistMore;
if (!MainActivity.instance.Paused)
@@ -158,7 +171,6 @@ namespace Opus.Fragments
break;
case Resource.Id.fork:
-#pragma warning disable CS4014
PlaylistManager.ForkPlaylist(item.YoutubeID);
break;
@@ -174,7 +186,10 @@ namespace Opus.Fragments
break;
case Resource.Id.sync:
- PlaylistManager.StopSyncingDialog(item, () => { /*SHOULD RECREATE CURSOR LOADER HERE*/ });
+ PlaylistManager.StopSyncingDialog(item, () =>
+ {
+ MainActivity.instance.SupportFragmentManager.PopBackStack();
+ });
break;
case Resource.Id.delete:
@@ -231,73 +246,40 @@ namespace Opus.Fragments
async Task PopulateList()
{
- if (item.LocalID == 0 && item.YoutubeID == "" && tracks.Count == 0)
+ if (item.LocalID == -1 && item.YoutubeID == ""/* && tracks.Count == 0*/)
return;
- if (item.LocalID != 0)
+ if (item.LocalID != -1)
{
- Uri musicUri = Playlists.Members.GetContentUri("external", item.LocalID);
-
- CursorLoader cursorLoader = new CursorLoader(Android.App.Application.Context, musicUri, null, null, null, null);
- ICursor musicCursor = (ICursor)cursorLoader.LoadInBackground();
-
- tracks = new List();
-
- if (musicCursor != null && musicCursor.MoveToFirst())
+ if (await MainActivity.instance.GetReadPermission() == false)
{
- int titleID = musicCursor.GetColumnIndex(Media.InterfaceConsts.Title);
- int artistID = musicCursor.GetColumnIndex(Media.InterfaceConsts.Artist);
- int albumID = musicCursor.GetColumnIndex(Media.InterfaceConsts.Album);
- 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(albumArtID);
- long id = musicCursor.GetLong(thisID);
- string path = musicCursor.GetString(pathID);
-
- if (Title == null)
- Title = "Unknown Title";
- if (Artist == null)
- Artist = "Unknow Artist";
- if (Album == null)
- Album = "Unknow Album";
-
- Song song = new Song(Title, Artist, Album, null, AlbumArt, id, path);
- if (item.SyncState == SyncState.True)
- song = LocalManager.CompleteItem(song);
-
- tracks.Add(song);
- }
- while (musicCursor.MoveToNext());
- musicCursor.Close();
+ MainActivity.instance.FindViewById(Resource.Id.loading).Visibility = ViewStates.Gone;
+ //adapter.ErrorMSG = GetString(Resource.String.no_permission);
+ return;
}
- adapter = new PlaylistTrackAdapter(tracks);
- adapter.ItemClick += ListView_ItemClick;
- adapter.ItemLongClick += ListView_ItemLongClick;
+ adapter = new PlaylistTrackAdapter();
ListView.SetAdapter(adapter);
Android.Support.V7.Widget.Helper.ItemTouchHelper.Callback callback = new ItemTouchCallback(adapter, false);
itemTouchHelper = new Android.Support.V7.Widget.Helper.ItemTouchHelper(callback);
itemTouchHelper.AttachToRecyclerView(ListView);
- Activity.FindViewById(Resource.Id.headerNumber).Text = tracks.Count.ToString() + " songs";
- var songCover = Uri.Parse("content://media/external/audio/albumart");
- var songAlbumArtUri = ContentUris.WithAppendedId(songCover, tracks[0].AlbumArt);
-
- if(item.ImageURL == null)
- Picasso.With(Android.App.Application.Context).Load(songAlbumArtUri).Placeholder(Resource.Drawable.noAlbum).Resize(1080, 1080).CenterCrop().Into(Activity.FindViewById(Resource.Id.headerArt));
+ LoaderManager.GetInstance(this).InitLoader(0, null, this);
}
else if (item.YoutubeID != null)
{
+ fullyLoadded = false;
+ SearchableList tracks = new SearchableList();
+ adapter = new PlaylistTrackAdapter(tracks);
+ ListView.SetAdapter(adapter);
+
+ Android.Support.V7.Widget.Helper.ItemTouchHelper.Callback callback = new ItemTouchCallback(adapter, false);
+ itemTouchHelper = new Android.Support.V7.Widget.Helper.ItemTouchHelper(callback);
+ itemTouchHelper.AttachToRecyclerView(ListView);
+
try
{
- tracks = new List();
var ytPlaylistRequest = YoutubeSearch.youtubeService.PlaylistItems.List("snippet, contentDetails");
ytPlaylistRequest.PlaylistId = item.YoutubeID;
ytPlaylistRequest.MaxResults = 50;
@@ -317,32 +299,59 @@ namespace Opus.Fragments
}
nextPageToken = ytPlaylist.NextPageToken;
- if(nextPageToken == null)
+ if (nextPageToken == null)
fullyLoadded = true;
- adapter = new PlaylistTrackAdapter(tracks);
- adapter.ItemClick += ListView_ItemClick;
- adapter.ItemLongClick += ListView_ItemLongClick;
- ListView.SetAdapter(adapter);
+ tracks.Invalidate();
+ adapter.NotifyDataSetChanged();
- Android.Support.V7.Widget.Helper.ItemTouchHelper.Callback callback = new ItemTouchCallback(adapter, false);
- itemTouchHelper = new Android.Support.V7.Widget.Helper.ItemTouchHelper(callback);
- itemTouchHelper.AttachToRecyclerView(ListView);
}
catch (System.Net.Http.HttpRequestException)
{
MainActivity.instance.Timout();
}
}
- else if(tracks.Count != 0)
+ //else if(tracks.Count != 0)
+ //{
+ // adapter = new PlaylistTrackAdapter(tracks);
+ // adapter.ItemClick += ListView_ItemClick;
+ // adapter.ItemLongClick += ListView_ItemLongClick;
+ // ListView.SetAdapter(adapter);
+ //}
+ }
+
+ public Android.Support.V4.Content.Loader OnCreateLoader(int id, Bundle args)
+ {
+ Uri musicUri = Playlists.Members.GetContentUri("external", item.LocalID);
+ string selection;
+ if (query != null)
+ selection = Media.InterfaceConsts.Title + " LIKE \"%" + query + "%\" OR " + Media.InterfaceConsts.Artist + " LIKE \"%" + query + "%\"";
+ else
+ selection = null;
+
+ return new CursorLoader(Android.App.Application.Context, musicUri, null, selection, null, null);
+ }
+
+ public void OnLoadFinished(Android.Support.V4.Content.Loader loader, Object data)
+ {
+ adapter.SwapCursor((ICursor)data, false);
+
+ if (item.LocalID != -1)
{
- adapter = new PlaylistTrackAdapter(tracks);
- adapter.ItemClick += ListView_ItemClick;
- adapter.ItemLongClick += ListView_ItemLongClick;
- ListView.SetAdapter(adapter);
+ Activity.FindViewById(Resource.Id.headerNumber).Text = item.Count.ToString() + " " + GetString(Resource.String.elements);
+ var songCover = Uri.Parse("content://media/external/audio/albumart");
+ var songAlbumArtUri = ContentUris.WithAppendedId(songCover, adapter.GetItem(0).AlbumArt);
+
+ if (item.ImageURL == null)
+ Picasso.With(Android.App.Application.Context).Load(songAlbumArtUri).Placeholder(Resource.Drawable.noAlbum).Resize(1080, 1080).CenterCrop().Into(Activity.FindViewById(Resource.Id.headerArt));
}
}
+ public void OnLoaderReset(Android.Support.V4.Content.Loader loader)
+ {
+ adapter.SwapCursor(null, false);
+ }
+
string SongToName(Song song)
{
return song.Title;
@@ -359,7 +368,7 @@ namespace Opus.Fragments
MainActivity.instance.contentRefresh.Refreshing = false;
}
- public async Task LoadMore()
+ public async void LoadMore()
{
if (nextPageToken == null || loading)
return;
@@ -377,6 +386,8 @@ namespace Opus.Fragments
if (instance == null)
return;
+ int countBefore = adapter.BaseCount;
+
foreach (var item in ytPlaylist.Items)
{
if (item.Snippet.Title != "[Deleted video]" && item.Snippet.Title != "Private video" && item.Snippet.Title != "Deleted video")
@@ -385,80 +396,67 @@ namespace Opus.Fragments
{
TrackID = item.Id
};
- tracks.Add(song);
+ adapter.tracks.Add(song);
}
}
+ adapter.tracks.Invalidate();
+ adapter.NotifyItemRangeInserted(countBefore, adapter.tracks.Count - countBefore);
+
nextPageToken = ytPlaylist.NextPageToken;
if (nextPageToken == null)
+ {
fullyLoadded = true;
- adapter.NotifyDataSetChanged();
+ adapter.NotifyItemRemoved(adapter.ItemCount);
+ }
}
catch (System.Net.Http.HttpRequestException)
{
MainActivity.instance.Timout();
}
loading = false;
+
+ //We are still at the end of the list, should load the rest (normaly because of the search).
+ if (!fullyLoadded && ((Android.Support.V7.Widget.LinearLayoutManager)ListView?.GetLayoutManager())?.FindLastVisibleItemPosition() == adapter?.ItemCount - 1)
+ LoadMore();
}
public void Search(string search)
{
- result = new List();
- for (int i = 0; i < tracks.Count; i++)
+ if (search == "")
+ query = null;
+ else
+ query = search.ToLower();
+
+ if(item.LocalID != -1)
+ LoaderManager.GetInstance(this).RestartLoader(0, null, this);
+ else
{
- Song item = tracks[i];
- if (item.Title.ToLower().Contains(search.ToLower()) || item.Artist.ToLower().Contains(search.ToLower()))
- {
- result.Add(item);
- }
+ if (query == null)
+ adapter.tracks.SetFilter(x => true);
+ else
+ adapter.tracks.SetFilter(x => x.Title.ToLower().Contains(query) || x.Artist.ToLower().Contains(query));
+
+ adapter.NotifyDataSetChanged();
}
- adapter = new PlaylistTrackAdapter(result);
- adapter.ItemClick += ListView_ItemClick;
- adapter.ItemLongClick += ListView_ItemLongClick;
-
- Android.Support.V7.Widget.Helper.ItemTouchHelper.Callback callback = new ItemTouchCallback(adapter, false);
- itemTouchHelper = new Android.Support.V7.Widget.Helper.ItemTouchHelper(callback);
- itemTouchHelper.AttachToRecyclerView(ListView);
-
- ListView.SetAdapter(adapter);
}
- private void ListView_ItemClick(object sender, int Position)
+ public void More(Song song, int position)
{
- if (!useHeader)
- Position--;
-
- PlaylistManager.PlayInOrder(item, Position);
- }
-
- private void ListView_ItemLongClick(object sender, int Position)
- {
- More(Position);
- }
-
- public void More(int position)
- {
- if (!useHeader)
- position--;
-
- Song item = tracks[position];
- if (result != null && result.Count > position)
- item = result[position];
-
BottomSheetDialog bottomSheet = new BottomSheetDialog(MainActivity.instance);
View bottomView = LayoutInflater.Inflate(Resource.Layout.BottomSheet, null);
- bottomView.FindViewById(Resource.Id.bsTitle).Text = item.Title;
- bottomView.FindViewById(Resource.Id.bsArtist).Text = item.Artist;
- if (item.Album == null)
+ bottomView.FindViewById(Resource.Id.bsTitle).Text = song.Title;
+ bottomView.FindViewById(Resource.Id.bsArtist).Text = song.Artist;
+ if (song.Album == null)
{
var songCover = Uri.Parse("content://media/external/audio/albumart");
- var nextAlbumArtUri = ContentUris.WithAppendedId(songCover, item.AlbumArt);
+ var nextAlbumArtUri = ContentUris.WithAppendedId(songCover, song.AlbumArt);
Picasso.With(MainActivity.instance).Load(nextAlbumArtUri).Placeholder(Resource.Drawable.noAlbum).Resize(400, 400).CenterCrop().Into(bottomView.FindViewById(Resource.Id.bsArt));
}
else
{
- Picasso.With(MainActivity.instance).Load(item.Album).Placeholder(Resource.Drawable.noAlbum).Transform(new RemoveBlackBorder(true)).Into(bottomView.FindViewById(Resource.Id.bsArt));
+ Picasso.With(MainActivity.instance).Load(song.Album).Placeholder(Resource.Drawable.noAlbum).Transform(new RemoveBlackBorder(true)).Into(bottomView.FindViewById(Resource.Id.bsArt));
}
bottomSheet.SetContentView(bottomView);
@@ -466,40 +464,40 @@ namespace Opus.Fragments
{
new BottomSheetAction(Resource.Drawable.Play, Resources.GetString(Resource.String.play), (sender, eventArg) =>
{
- PlaylistManager.PlayInOrder(this.item, position);
+ PlaylistManager.PlayInOrder(item, position);
bottomSheet.Dismiss();
}),
new BottomSheetAction(Resource.Drawable.PlaylistPlay, Resources.GetString(Resource.String.play_next), (sender, eventArg) =>
{
- SongManager.PlayNext(item);
+ SongManager.PlayNext(song);
bottomSheet.Dismiss();
}),
new BottomSheetAction(Resource.Drawable.Queue, Resources.GetString(Resource.String.play_last), (sender, eventArg) =>
{
- SongManager.PlayLast(item);
+ SongManager.PlayLast(song);
bottomSheet.Dismiss();
}),
new BottomSheetAction(Resource.Drawable.PlaylistAdd, Resources.GetString(Resource.String.add_to_playlist), (sender, eventArg) =>
{
- PlaylistManager.AddSongToPlaylistDialog(item);
+ PlaylistManager.AddSongToPlaylistDialog(song);
bottomSheet.Dismiss();
})
};
- if (this.item.HasWritePermission)
+ if (item.HasWritePermission)
{
actions.Add(new BottomSheetAction(Resource.Drawable.Close, Resources.GetString(Resource.String.remove_track_from_playlist), (sender, eventArg) =>
{
- RemoveFromPlaylist(item, position);
+ RemoveFromPlaylist(song, position);
bottomSheet.Dismiss();
}));
}
- if (!item.IsYt)
+ if (!song.IsYt)
{
actions.Add(new BottomSheetAction(Resource.Drawable.Edit, Resources.GetString(Resource.String.edit_metadata), (sender, eventArg) =>
{
- LocalManager.EditMetadata(item);
+ LocalManager.EditMetadata(song);
bottomSheet.Dismiss();
}));
}
@@ -509,12 +507,12 @@ namespace Opus.Fragments
{
new BottomSheetAction(Resource.Drawable.PlayCircle, Resources.GetString(Resource.String.create_mix_from_song), (sender, eventArg) =>
{
- YoutubeManager.CreateMixFromSong(item);
+ YoutubeManager.CreateMixFromSong(song);
bottomSheet.Dismiss();
}),
new BottomSheetAction(Resource.Drawable.Download, Resources.GetString(Resource.String.download), (sender, eventArg) =>
{
- YoutubeManager.Download(new[] { item }, null);
+ YoutubeManager.Download(new[] { song }, null);
bottomSheet.Dismiss();
})
});
diff --git a/Opus/Code/UI/Fragments/Queue.cs b/Opus/Code/UI/Fragments/Queue.cs
index 756b8e1..2911aaa 100644
--- a/Opus/Code/UI/Fragments/Queue.cs
+++ b/Opus/Code/UI/Fragments/Queue.cs
@@ -36,7 +36,7 @@ public class Queue : Fragment, RecyclerView.IOnItemTouchListener, PopupMenu.IOnM
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
- View view = inflater.Inflate(Resource.Layout.RecyclerFragment, container, false);
+ View view = inflater.Inflate(Resource.Layout.LonelyRecycler, container, false);
instance = this;
ListView = view.FindViewById(Resource.Id.recycler);
ListView.SetLayoutManager(new LinearLayoutManager(Application.Context));
diff --git a/Opus/Opus.csproj b/Opus/Opus.csproj
index f5b7b72..f9a1e0d 100644
--- a/Opus/Opus.csproj
+++ b/Opus/Opus.csproj
@@ -322,6 +322,7 @@
+
@@ -515,7 +516,7 @@
-
+
Designer
diff --git a/Opus/Resources/Resource.Designer.cs b/Opus/Resources/Resource.Designer.cs
index 3ba124c..4d81fc9 100644
--- a/Opus/Resources/Resource.Designer.cs
+++ b/Opus/Resources/Resource.Designer.cs
@@ -6756,199 +6756,199 @@ namespace Opus
public const int LogOutButton = 2130903117;
// aapt resource value: 0x7f03004e
- public const int Main = 2130903118;
+ public const int LonelyRecycler = 2130903118;
// aapt resource value: 0x7f03004f
- public const int mr_cast_dialog = 2130903119;
+ public const int Main = 2130903119;
// aapt resource value: 0x7f030050
- public const int mr_cast_group_item = 2130903120;
+ public const int mr_cast_dialog = 2130903120;
// aapt resource value: 0x7f030051
- public const int mr_cast_group_volume_item = 2130903121;
+ public const int mr_cast_group_item = 2130903121;
// aapt resource value: 0x7f030052
- public const int mr_cast_media_metadata = 2130903122;
+ public const int mr_cast_group_volume_item = 2130903122;
// aapt resource value: 0x7f030053
- public const int mr_cast_route_item = 2130903123;
+ public const int mr_cast_media_metadata = 2130903123;
// aapt resource value: 0x7f030054
- public const int mr_chooser_dialog = 2130903124;
+ public const int mr_cast_route_item = 2130903124;
// aapt resource value: 0x7f030055
- public const int mr_chooser_list_item = 2130903125;
+ public const int mr_chooser_dialog = 2130903125;
// aapt resource value: 0x7f030056
- public const int mr_controller_material_dialog_b = 2130903126;
+ public const int mr_chooser_list_item = 2130903126;
// aapt resource value: 0x7f030057
- public const int mr_controller_volume_item = 2130903127;
+ public const int mr_controller_material_dialog_b = 2130903127;
// aapt resource value: 0x7f030058
- public const int mr_dialog_header_item = 2130903128;
+ public const int mr_controller_volume_item = 2130903128;
// aapt resource value: 0x7f030059
- public const int mr_picker_dialog = 2130903129;
+ public const int mr_dialog_header_item = 2130903129;
// aapt resource value: 0x7f03005a
- public const int mr_picker_route_item = 2130903130;
+ public const int mr_picker_dialog = 2130903130;
// aapt resource value: 0x7f03005b
- public const int mr_playback_control = 2130903131;
+ public const int mr_picker_route_item = 2130903131;
// aapt resource value: 0x7f03005c
- public const int mr_volume_control = 2130903132;
+ public const int mr_playback_control = 2130903132;
// aapt resource value: 0x7f03005d
- public const int mtrl_layout_snackbar = 2130903133;
+ public const int mr_volume_control = 2130903133;
// aapt resource value: 0x7f03005e
- public const int mtrl_layout_snackbar_include = 2130903134;
+ public const int mtrl_layout_snackbar = 2130903134;
// aapt resource value: 0x7f03005f
- public const int MusicLayout = 2130903135;
+ public const int mtrl_layout_snackbar_include = 2130903135;
// aapt resource value: 0x7f030060
- public const int NoSong = 2130903136;
+ public const int MusicLayout = 2130903136;
// aapt resource value: 0x7f030061
- public const int notification_action = 2130903137;
+ public const int NoSong = 2130903137;
// aapt resource value: 0x7f030062
- public const int notification_action_tombstone = 2130903138;
+ public const int notification_action = 2130903138;
// aapt resource value: 0x7f030063
- public const int notification_media_action = 2130903139;
+ public const int notification_action_tombstone = 2130903139;
// aapt resource value: 0x7f030064
- public const int notification_media_cancel_action = 2130903140;
+ public const int notification_media_action = 2130903140;
// aapt resource value: 0x7f030065
- public const int notification_template_big_media = 2130903141;
+ public const int notification_media_cancel_action = 2130903141;
// aapt resource value: 0x7f030066
- public const int notification_template_big_media_custom = 2130903142;
+ public const int notification_template_big_media = 2130903142;
// aapt resource value: 0x7f030067
- public const int notification_template_big_media_narrow = 2130903143;
+ public const int notification_template_big_media_custom = 2130903143;
// aapt resource value: 0x7f030068
- public const int notification_template_big_media_narrow_custom = 2130903144;
+ public const int notification_template_big_media_narrow = 2130903144;
// aapt resource value: 0x7f030069
- public const int notification_template_custom_big = 2130903145;
+ public const int notification_template_big_media_narrow_custom = 2130903145;
// aapt resource value: 0x7f03006a
- public const int notification_template_icon_group = 2130903146;
+ public const int notification_template_custom_big = 2130903146;
// aapt resource value: 0x7f03006b
- public const int notification_template_lines_media = 2130903147;
+ public const int notification_template_icon_group = 2130903147;
// aapt resource value: 0x7f03006c
- public const int notification_template_media = 2130903148;
+ public const int notification_template_lines_media = 2130903148;
// aapt resource value: 0x7f03006d
- public const int notification_template_media_custom = 2130903149;
+ public const int notification_template_media = 2130903149;
// aapt resource value: 0x7f03006e
- public const int notification_template_part_chronometer = 2130903150;
+ public const int notification_template_media_custom = 2130903150;
// aapt resource value: 0x7f03006f
- public const int notification_template_part_time = 2130903151;
+ public const int notification_template_part_chronometer = 2130903151;
// aapt resource value: 0x7f030070
- public const int NoYtPlaylist = 2130903152;
+ public const int notification_template_part_time = 2130903152;
// aapt resource value: 0x7f030071
- public const int NumberPicker = 2130903153;
+ public const int NoYtPlaylist = 2130903153;
// aapt resource value: 0x7f030072
- public const int player = 2130903154;
+ public const int NumberPicker = 2130903154;
// aapt resource value: 0x7f030073
- public const int playerInfo = 2130903155;
+ public const int player = 2130903155;
// aapt resource value: 0x7f030074
- public const int PlaylistHeader = 2130903156;
+ public const int playerInfo = 2130903156;
// aapt resource value: 0x7f030075
- public const int PlaylistItem = 2130903157;
+ public const int PlaylistHeader = 2130903157;
// aapt resource value: 0x7f030076
- public const int PlaylistList = 2130903158;
+ public const int PlaylistItem = 2130903158;
// aapt resource value: 0x7f030077
- public const int PlaylistSmallHeader = 2130903159;
+ public const int PlaylistList = 2130903159;
// aapt resource value: 0x7f030078
- public const int preference = 2130903160;
+ public const int PlaylistSmallHeader = 2130903160;
// aapt resource value: 0x7f030079
- public const int preference_category = 2130903161;
+ public const int preference = 2130903161;
// aapt resource value: 0x7f03007a
- public const int preference_category_material = 2130903162;
+ public const int preference_category = 2130903162;
// aapt resource value: 0x7f03007b
- public const int preference_dialog_edittext = 2130903163;
+ public const int preference_category_material = 2130903163;
// aapt resource value: 0x7f03007c
- public const int preference_dropdown = 2130903164;
+ public const int preference_dialog_edittext = 2130903164;
// aapt resource value: 0x7f03007d
- public const int preference_dropdown_material = 2130903165;
+ public const int preference_dropdown = 2130903165;
// aapt resource value: 0x7f03007e
- public const int preference_information = 2130903166;
+ public const int preference_dropdown_material = 2130903166;
// aapt resource value: 0x7f03007f
- public const int preference_information_material = 2130903167;
+ public const int preference_information = 2130903167;
// aapt resource value: 0x7f030080
- public const int preference_list_fragment = 2130903168;
+ public const int preference_information_material = 2130903168;
// aapt resource value: 0x7f030081
- public const int preference_material = 2130903169;
+ public const int preference_list_fragment = 2130903169;
// aapt resource value: 0x7f030082
- public const int preference_recyclerview = 2130903170;
+ public const int preference_material = 2130903170;
// aapt resource value: 0x7f030083
- public const int preference_widget_checkbox = 2130903171;
+ public const int preference_recyclerview = 2130903171;
// aapt resource value: 0x7f030084
- public const int preference_widget_seekbar = 2130903172;
+ public const int preference_widget_checkbox = 2130903172;
// aapt resource value: 0x7f030085
- public const int preference_widget_seekbar_material = 2130903173;
+ public const int preference_widget_seekbar = 2130903173;
// aapt resource value: 0x7f030086
- public const int preference_widget_switch = 2130903174;
+ public const int preference_widget_seekbar_material = 2130903174;
// aapt resource value: 0x7f030087
- public const int preference_widget_switch_compat = 2130903175;
+ public const int preference_widget_switch = 2130903175;
// aapt resource value: 0x7f030088
- public const int PreferenceCategory = 2130903176;
+ public const int preference_widget_switch_compat = 2130903176;
// aapt resource value: 0x7f030089
- public const int PreferenceRoot = 2130903177;
+ public const int PreferenceCategory = 2130903177;
// aapt resource value: 0x7f03008a
- public const int Preferences = 2130903178;
+ public const int PreferenceRoot = 2130903178;
// aapt resource value: 0x7f03008b
- public const int QueueCurrent = 2130903179;
+ public const int Preferences = 2130903179;
// aapt resource value: 0x7f03008c
- public const int QueueFooter = 2130903180;
+ public const int QueueCurrent = 2130903180;
// aapt resource value: 0x7f03008d
- public const int QueueHeader = 2130903181;
+ public const int QueueFooter = 2130903181;
// aapt resource value: 0x7f03008e
- public const int RecyclerFragment = 2130903182;
+ public const int QueueHeader = 2130903182;
// aapt resource value: 0x7f03008f
public const int SaveAPlaylist = 2130903183;
diff --git a/Opus/Resources/layout/RecyclerFragment.xml b/Opus/Resources/layout/LonelyRecycler.xml
similarity index 100%
rename from Opus/Resources/layout/RecyclerFragment.xml
rename to Opus/Resources/layout/LonelyRecycler.xml