mirror of
https://github.com/zoriya/Opus.git
synced 2025-12-06 06:26:15 +00:00
Finishing playlisttracks rework for local and youtube playlists.
This commit is contained in:
@@ -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;
|
||||
|
||||
56
Opus/Code/DataStructure/SearchableList.cs
Normal file
56
Opus/Code/DataStructure/SearchableList.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Opus.DataStructure
|
||||
{
|
||||
[Serializable]
|
||||
public class SearchableList<T> : List<T>
|
||||
{
|
||||
private List<T> cachedList = null;
|
||||
private List<T> CachedList
|
||||
{
|
||||
get
|
||||
{
|
||||
return cachedList ?? this;
|
||||
}
|
||||
set
|
||||
{
|
||||
cachedList = value;
|
||||
}
|
||||
}
|
||||
|
||||
private Func<T, bool> filter = x => true;
|
||||
|
||||
public SearchableList() { }
|
||||
public SearchableList(IEnumerable<T> collection) : base(collection) { AddRange(collection); }
|
||||
|
||||
public void SetFilter(Func<T, bool> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
/// </summary>
|
||||
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);
|
||||
|
||||
@@ -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<Song, int> clickAction;
|
||||
private Action<Song, int> longClickAction;
|
||||
private Action<int> headerAction;
|
||||
private readonly Action<Song, int> clickAction;
|
||||
private readonly Action<Song, int> longClickAction;
|
||||
private readonly Action<int> headerAction;
|
||||
|
||||
public BrowseAdapter(Action<Song, int> clickAction, Action<Song, int> longClickAction, Action<int> headerAction = null)
|
||||
{
|
||||
|
||||
@@ -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<Song>, IItemTouchAdapter
|
||||
{
|
||||
public List<Song> songList;
|
||||
public event EventHandler<int> ItemClick;
|
||||
public event EventHandler<int> ItemLongClick;
|
||||
public int listPadding;
|
||||
public bool IsEmpty = false;
|
||||
public SearchableList<Song> tracks;
|
||||
public bool IsSliding { get; set; }
|
||||
|
||||
public PlaylistTrackAdapter(List<Song> songList)
|
||||
|
||||
public PlaylistTrackAdapter() { }
|
||||
public PlaylistTrackAdapter(SearchableList<Song> 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<TextView>(Resource.Id.headerNumber).Text = songList.Count + " " + (songList.Count < 2 ? MainActivity.instance.GetString(Resource.String.element) : MainActivity.instance.GetString(Resource.String.elements));
|
||||
header.FindViewById<TextView>(Resource.Id.headerNumber).Text = tracks.Count + " " + (tracks.Count < 2 ? MainActivity.instance.GetString(Resource.String.element) : MainActivity.instance.GetString(Resource.String.elements));
|
||||
if (!header.FindViewById<ImageButton>(Resource.Id.headerPlay).HasOnClickListeners)
|
||||
{
|
||||
header.FindViewById<ImageButton>(Resource.Id.headerPlay).Click += (sender, e0) => { PlaylistManager.PlayInOrder(PlaylistTracks.instance.item); };
|
||||
@@ -82,32 +90,34 @@ namespace Opus.Adapter
|
||||
header.FindViewById<ImageButton>(Resource.Id.headerShuffle).ImageTintList = ColorStateList.ValueOf(Color.Black);
|
||||
header.FindViewById<ImageButton>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<RecyclerView>(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;
|
||||
|
||||
@@ -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<PlaylistItem> LocalPlaylists = new List<PlaylistItem>();
|
||||
@@ -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<RecyclerView>(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);
|
||||
|
||||
@@ -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<Song> 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<Song> tracks = new List<Song>();
|
||||
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<RecyclerView>(Resource.Id.recycler);
|
||||
ListView.SetLayoutManager(new Android.Support.V7.Widget.LinearLayoutManager(MainActivity.instance));
|
||||
ListView.SetAdapter(new PlaylistTrackAdapter(new List<Song>()));
|
||||
ListView.SetAdapter(new PlaylistTrackAdapter(new SearchableList<Song>()));
|
||||
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<TextView>(Resource.Id.headerTitle).Text = item.Name;
|
||||
|
||||
if (!Activity.FindViewById<ImageButton>(Resource.Id.headerPlay).HasOnClickListeners)
|
||||
Activity.FindViewById<ImageButton>(Resource.Id.headerPlay).Click += (sender, e0) => { PlaylistManager.PlayInOrder(item); };
|
||||
Activity.FindViewById<ImageButton>(Resource.Id.headerPlay).Click += HeaderPlay;
|
||||
if (!Activity.FindViewById<ImageButton>(Resource.Id.headerShuffle).HasOnClickListeners)
|
||||
Activity.FindViewById<ImageButton>(Resource.Id.headerShuffle).Click += (sender, e0) => { PlaylistManager.Shuffle(item); };
|
||||
Activity.FindViewById<ImageButton>(Resource.Id.headerShuffle).Click += HeaderShuffle;
|
||||
if (!Activity.FindViewById<ImageButton>(Resource.Id.headerMore).HasOnClickListeners)
|
||||
Activity.FindViewById<ImageButton>(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<ImageButton>(Resource.Id.headerPlay).Click -= HeaderPlay;
|
||||
Activity.FindViewById<ImageButton>(Resource.Id.headerShuffle).Click -= HeaderShuffle;
|
||||
Activity.FindViewById<ImageButton>(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<Song>();
|
||||
|
||||
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<TextView>(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<ImageView>(Resource.Id.headerArt));
|
||||
LoaderManager.GetInstance(this).InitLoader(0, null, this);
|
||||
}
|
||||
else if (item.YoutubeID != null)
|
||||
{
|
||||
fullyLoadded = false;
|
||||
SearchableList<Song> tracks = new SearchableList<Song>();
|
||||
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<Song>();
|
||||
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<TextView>(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<ImageView>(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<Song>();
|
||||
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<TextView>(Resource.Id.bsTitle).Text = item.Title;
|
||||
bottomView.FindViewById<TextView>(Resource.Id.bsArtist).Text = item.Artist;
|
||||
if (item.Album == null)
|
||||
bottomView.FindViewById<TextView>(Resource.Id.bsTitle).Text = song.Title;
|
||||
bottomView.FindViewById<TextView>(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<ImageView>(Resource.Id.bsArt));
|
||||
}
|
||||
else
|
||||
{
|
||||
Picasso.With(MainActivity.instance).Load(item.Album).Placeholder(Resource.Drawable.noAlbum).Transform(new RemoveBlackBorder(true)).Into(bottomView.FindViewById<ImageView>(Resource.Id.bsArt));
|
||||
Picasso.With(MainActivity.instance).Load(song.Album).Placeholder(Resource.Drawable.noAlbum).Transform(new RemoveBlackBorder(true)).Into(bottomView.FindViewById<ImageView>(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();
|
||||
})
|
||||
});
|
||||
|
||||
@@ -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<RecyclerView>(Resource.Id.recycler);
|
||||
ListView.SetLayoutManager(new LinearLayoutManager(Application.Context));
|
||||
|
||||
@@ -322,6 +322,7 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Code\DataStructure\SearchableList.cs" />
|
||||
<Compile Include="Code\UI\Adapter\BaseCursor.cs" />
|
||||
<Compile Include="Code\Api\LocalManager.cs" />
|
||||
<Compile Include="Code\Api\PlaylistManager.cs" />
|
||||
@@ -515,7 +516,7 @@
|
||||
<AndroidResource Include="Resources\drawable\needProcessing.png" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AndroidResource Include="Resources\layout\RecyclerFragment.xml">
|
||||
<AndroidResource Include="Resources\layout\LonelyRecycler.xml">
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
</ItemGroup>
|
||||
|
||||
130
Opus/Resources/Resource.Designer.cs
generated
130
Opus/Resources/Resource.Designer.cs
generated
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user