mirror of
https://github.com/zoriya/Opus.git
synced 2025-12-06 06:26:15 +00:00
Starting to rework code oraganizing structure. Making browse use content loader and load only what it need.
This commit is contained in:
77
Opus/Code/Adapter/BaseCursor.cs
Normal file
77
Opus/Code/Adapter/BaseCursor.cs
Normal file
@@ -0,0 +1,77 @@
|
||||
using Android.Database;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
|
||||
namespace Opus.Adapter
|
||||
{
|
||||
public abstract class BaseCursor<T> : RecyclerView.Adapter
|
||||
{
|
||||
public ICursor cursor;
|
||||
/// <summary>
|
||||
/// 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 override int ItemCount => BaseCount + ItemBefore;
|
||||
|
||||
public override void OnBindViewHolder(RecyclerView.ViewHolder holder, int position)
|
||||
{
|
||||
if (cursor.MoveToPosition(position - ItemBefore))
|
||||
OnBindViewHolder(holder, Convert(cursor));
|
||||
}
|
||||
public abstract void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, T item);
|
||||
|
||||
public void SwapCursor(ICursor newCursor)
|
||||
{
|
||||
if (newCursor == cursor)
|
||||
return;
|
||||
|
||||
if (newCursor != null)
|
||||
{
|
||||
MainActivity.instance.FindViewById(Resource.Id.loading).Visibility = ViewStates.Gone;
|
||||
cursor = newCursor;
|
||||
NotifyDataSetChanged();
|
||||
}
|
||||
else
|
||||
{
|
||||
NotifyItemRangeRemoved(0, ItemCount);
|
||||
cursor = null;
|
||||
MainActivity.instance.FindViewById(Resource.Id.loading).Visibility = ViewStates.Visible;
|
||||
}
|
||||
}
|
||||
|
||||
public T GetItem(int position)
|
||||
{
|
||||
cursor.MoveToPosition(position - ItemBefore);
|
||||
return Convert(cursor);
|
||||
}
|
||||
|
||||
public void OnClick(int position)
|
||||
{
|
||||
if (position >= ItemBefore)
|
||||
{
|
||||
cursor.MoveToPosition(position - ItemBefore);
|
||||
Clicked(Convert(cursor));
|
||||
}
|
||||
else
|
||||
HeaderClicked(position);
|
||||
}
|
||||
public abstract void Clicked(T item);
|
||||
public virtual void HeaderClicked(int position) { }
|
||||
|
||||
public void OnLongClick(int position)
|
||||
{
|
||||
if (position >= ItemBefore)
|
||||
{
|
||||
cursor.MoveToPosition(position - ItemBefore);
|
||||
LongClicked(Convert(cursor));
|
||||
}
|
||||
else
|
||||
HeaderLongClicked(position);
|
||||
}
|
||||
public abstract void LongClicked(T item);
|
||||
public virtual void HeaderLongClicked(int position) { }
|
||||
|
||||
public abstract T Convert(ICursor cursor);
|
||||
}
|
||||
}
|
||||
115
Opus/Code/Adapter/BrowseAdapter.cs
Normal file
115
Opus/Code/Adapter/BrowseAdapter.cs
Normal file
@@ -0,0 +1,115 @@
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Database;
|
||||
using Android.Graphics;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Fragments;
|
||||
using Square.Picasso;
|
||||
|
||||
namespace Opus.Adapter
|
||||
{
|
||||
public class BrowseAdapter : BaseCursor<Song>
|
||||
{
|
||||
public bool displayShuffle;
|
||||
public override int ItemBefore => (displayShuffle && BaseCount != 0) ? 1 : 0;
|
||||
|
||||
|
||||
public BrowseAdapter()
|
||||
{
|
||||
cursor = null;
|
||||
displayShuffle = true;
|
||||
}
|
||||
|
||||
public BrowseAdapter(ICursor cursor, bool displayShuffle)
|
||||
{
|
||||
this.cursor = cursor;
|
||||
this.displayShuffle = displayShuffle;
|
||||
}
|
||||
|
||||
public override void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)
|
||||
{
|
||||
if (position == 0 && displayShuffle)
|
||||
{
|
||||
if (MainActivity.Theme == 1)
|
||||
((CardView)viewHolder.ItemView).SetCardBackgroundColor(Color.ParseColor("#212121"));
|
||||
else
|
||||
((CardView)viewHolder.ItemView).SetCardBackgroundColor(Color.White);
|
||||
}
|
||||
else
|
||||
base.OnBindViewHolder(viewHolder, position);
|
||||
}
|
||||
|
||||
public override void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, Song song)
|
||||
{
|
||||
SongHolder holder = (SongHolder)viewHolder;
|
||||
|
||||
if (MainActivity.Theme == 1)
|
||||
{
|
||||
holder.more.SetColorFilter(Color.White);
|
||||
holder.Title.SetTextColor(Color.White);
|
||||
holder.Artist.SetTextColor(Color.White);
|
||||
holder.Artist.Alpha = 0.7f;
|
||||
}
|
||||
|
||||
holder.Title.Text = song.Title;
|
||||
holder.Artist.Text = song.Artist;
|
||||
|
||||
var songCover = Android.Net.Uri.Parse("content://media/external/audio/albumart");
|
||||
var songAlbumArtUri = ContentUris.WithAppendedId(songCover, song.AlbumArt);
|
||||
Picasso.With(Application.Context).Load(songAlbumArtUri).Placeholder(Resource.Color.background_material_dark).Resize(400, 400).CenterCrop().Into(holder.AlbumArt);
|
||||
|
||||
if (!holder.more.HasOnClickListeners)
|
||||
{
|
||||
holder.more.Click += (sender, e) =>
|
||||
{
|
||||
Browse.instance?.More(GetItem(holder.AdapterPosition));
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
|
||||
{
|
||||
if (viewType == 0)
|
||||
{
|
||||
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.ShuffleButton, parent, false);
|
||||
return new UslessHolder(itemView, OnClick);
|
||||
}
|
||||
else
|
||||
{
|
||||
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.SongList, parent, false);
|
||||
return new SongHolder(itemView, OnClick, OnLongClick);
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetItemViewType(int position)
|
||||
{
|
||||
if (position == 0 && displayShuffle)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
public override void HeaderClicked(int position)
|
||||
{
|
||||
MainActivity.instance.ShuffleAll();
|
||||
}
|
||||
|
||||
public override void Clicked(Song song)
|
||||
{
|
||||
song = Browse.CompleteItem(song);
|
||||
Browse.Play(song);
|
||||
}
|
||||
|
||||
public override void LongClicked(Song song)
|
||||
{
|
||||
Browse.instance?.More(song);
|
||||
}
|
||||
|
||||
public override Song Convert(ICursor cursor)
|
||||
{
|
||||
return Song.FromCursor(cursor);
|
||||
}
|
||||
}
|
||||
}
|
||||
138
Opus/Code/DataStructure/Song.cs
Normal file
138
Opus/Code/DataStructure/Song.cs
Normal file
@@ -0,0 +1,138 @@
|
||||
using Android.Database;
|
||||
using Android.Gms.Cast;
|
||||
using Android.Provider;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Newtonsoft.Json;
|
||||
using SQLite;
|
||||
using System;
|
||||
|
||||
namespace Opus.DataStructure
|
||||
{
|
||||
[Serializable]
|
||||
public class Song
|
||||
{
|
||||
[PrimaryKey, Unique]
|
||||
public int Index { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
public string Artist { get; set; }
|
||||
public string Album { get; set; }
|
||||
public long AlbumArt { get; set; }
|
||||
public string YoutubeID { get; set; }
|
||||
public long Id { get; set; }
|
||||
public string Path { get; set; }
|
||||
public bool? IsParsed { get; set; }
|
||||
public bool IsYt { get; set; }
|
||||
public DateTimeOffset? ExpireDate { get; set;}
|
||||
public bool IsLiveStream = false;
|
||||
public string TrackID;
|
||||
|
||||
public Song() { }
|
||||
|
||||
public Song(string title, string artist, string album, string youtubeID, long albumArt, long id, string path, bool isYT = false, bool isParsed = true)
|
||||
{
|
||||
Title = title;
|
||||
Artist = artist;
|
||||
Album = album;
|
||||
YoutubeID = youtubeID;
|
||||
AlbumArt = albumArt;
|
||||
Id = id;
|
||||
Path = path;
|
||||
IsYt = isYT;
|
||||
IsParsed = isParsed;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Title + " Artist: " + Artist + " Album: " + Album + " youtubeID: " + YoutubeID + " AlbumArt: " + AlbumArt + " Id: " + Id + " Path: " + Path + " isYT: " + IsYt + " isParsed: " + IsParsed;
|
||||
}
|
||||
|
||||
public static Song FromCursor(ICursor cursor)
|
||||
{
|
||||
int titleID = cursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Title);
|
||||
int artistID = cursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Artist);
|
||||
int albumID = cursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Album);
|
||||
int thisID = cursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Id);
|
||||
int pathID = cursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Data);
|
||||
|
||||
string Artist = cursor.GetString(artistID);
|
||||
string Title = cursor.GetString(titleID);
|
||||
string Album = cursor.GetString(albumID);
|
||||
long AlbumArt = cursor.GetLong(cursor.GetColumnIndex(MediaStore.Audio.Albums.InterfaceConsts.AlbumId));
|
||||
long id = cursor.GetLong(thisID);
|
||||
string path = cursor.GetString(pathID);
|
||||
|
||||
if (Title == null)
|
||||
Title = "Unknown Title";
|
||||
if (Artist == null)
|
||||
Artist = "Unknow Artist";
|
||||
if (Album == null)
|
||||
Album = "Unknow Album";
|
||||
|
||||
return new Song(Title, Artist, Album, null, AlbumArt, id, path);
|
||||
}
|
||||
|
||||
|
||||
public static explicit operator Song(string v)
|
||||
{
|
||||
if (v == null)
|
||||
return null;
|
||||
|
||||
string Name = v.Substring(0, v.IndexOf(" Artist: "));
|
||||
string Artist = v.Substring(v.IndexOf(" Artist: ") + 9, v.IndexOf(" Album: ") - Name.Length - 8);
|
||||
string Album = v.Substring(v.IndexOf(" Album: ") + 8, v.IndexOf(" youtubeID: ") - v.IndexOf(" Album: ") - 8);
|
||||
string youtubeID = v.Substring(v.IndexOf(" youtubeID: ") + 12, v.IndexOf(" AlbumArt: ") - v.IndexOf(" youtubeID: ") - 12);
|
||||
long AlbumArt = long.Parse(v.Substring(v.IndexOf(" AlbumArt: ") + 11, v.IndexOf(" Id: ") - v.IndexOf(" AlbumArt: ") - 11));
|
||||
long id = long.Parse(v.Substring(v.IndexOf(" Id: ") + 5, v.IndexOf(" Path: ") - v.IndexOf(" Id: ") - 5));
|
||||
string path = v.Substring(v.IndexOf(" Path: ") + 7, v.IndexOf(" isYT: ") - v.IndexOf(" Path: ") - 7);
|
||||
bool isYT = bool.Parse(v.Substring(v.IndexOf(" isYT: ") + 7, v.IndexOf(" isParsed: ") - v.IndexOf(" isYT: ") - 7));
|
||||
bool isParsed = bool.Parse(v.Substring(v.IndexOf(" isParsed: ") + 11));
|
||||
|
||||
Song song = new Song(Name, Artist, Album, youtubeID, AlbumArt, id, path, isYT, isParsed);
|
||||
return song;
|
||||
}
|
||||
|
||||
public static explicit operator Song(MediaQueueItem v)
|
||||
{
|
||||
if (v == null)
|
||||
return null;
|
||||
|
||||
return JsonConvert.DeserializeObject<Song>(v.Media.CustomData.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public class SongHolder : RecyclerView.ViewHolder
|
||||
{
|
||||
public ImageView reorder;
|
||||
public TextView Title;
|
||||
public TextView Artist;
|
||||
public TextView Live;
|
||||
public ImageView AlbumArt;
|
||||
public ImageView youtubeIcon;
|
||||
public ImageView more;
|
||||
public TextView status;
|
||||
public Button action;
|
||||
public View RightButtons;
|
||||
public View TextLayout;
|
||||
|
||||
public SongHolder(View itemView, Action<int> listener, Action<int> longListener) : base(itemView)
|
||||
{
|
||||
reorder = itemView.FindViewById<ImageView>(Resource.Id.reorder);
|
||||
Title = itemView.FindViewById<TextView>(Resource.Id.title);
|
||||
Artist = itemView.FindViewById<TextView>(Resource.Id.artist);
|
||||
Live = itemView.FindViewById<TextView>(Resource.Id.isLive);
|
||||
AlbumArt = itemView.FindViewById<ImageView>(Resource.Id.albumArt);
|
||||
youtubeIcon = itemView.FindViewById<ImageView>(Resource.Id.youtubeIcon);
|
||||
more = itemView.FindViewById<ImageView>(Resource.Id.moreButton);
|
||||
RightButtons = itemView.FindViewById(Resource.Id.rightButtons);
|
||||
TextLayout = itemView.FindViewById(Resource.Id.textLayout);
|
||||
status = itemView.FindViewById<TextView>(Resource.Id.status);
|
||||
action = itemView.FindViewById<Button>(Resource.Id.action);
|
||||
|
||||
itemView.Click += (sender, e) => listener(AdapterPosition);
|
||||
itemView.LongClick += (sender, e) => longListener(AdapterPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
using Android.Views;
|
||||
using System;
|
||||
|
||||
namespace Opus.Resources.Portable_Class
|
||||
namespace Opus.DataStructure
|
||||
{
|
||||
public class UslessHolder : RecyclerView.ViewHolder
|
||||
{
|
||||
@@ -4,15 +4,18 @@ using Android.Content.PM;
|
||||
using Android.Database;
|
||||
using Android.OS;
|
||||
using Android.Provider;
|
||||
using Android.Runtime;
|
||||
using Android.Support.Design.Widget;
|
||||
using Android.Support.V4.App;
|
||||
using Android.Support.V4.Content;
|
||||
using Android.Support.V7.App;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Google.Apis.YouTube.v3;
|
||||
using Opus.Resources.values;
|
||||
using Java.Lang;
|
||||
using Opus.Adapter;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.Portable_Class;
|
||||
using SQLite;
|
||||
using Square.Picasso;
|
||||
using System;
|
||||
@@ -25,21 +28,19 @@ using Color = Android.Graphics.Color;
|
||||
using CursorLoader = Android.Support.V4.Content.CursorLoader;
|
||||
using Uri = Android.Net.Uri;
|
||||
|
||||
namespace Opus.Resources.Portable_Class
|
||||
namespace Opus.Fragments
|
||||
{
|
||||
public class Browse : Fragment
|
||||
public class Browse : Fragment, LoaderManager.ILoaderCallbacks
|
||||
{
|
||||
public static Browse instance;
|
||||
public RecyclerView ListView;
|
||||
public BrowseAdapter adapter;
|
||||
public List<Song> musicList = new List<Song>();
|
||||
public List<Song> result;
|
||||
public bool focused = true;
|
||||
|
||||
private TextView EmptyView;
|
||||
|
||||
public Browse() { }
|
||||
protected Browse(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }
|
||||
//public Browse() { }
|
||||
//protected Browse(IntPtr javaReference, JniHandleOwnership transfer) : base(javaReference, transfer) { }
|
||||
|
||||
public override void OnActivityCreated(Bundle savedInstanceState)
|
||||
{
|
||||
@@ -59,13 +60,16 @@ namespace Opus.Resources.Portable_Class
|
||||
{
|
||||
View view = inflater.Inflate(Resource.Layout.CompleteRecycler, container, false);
|
||||
|
||||
if(MainActivity.Theme == 1)
|
||||
view.SetBackgroundColor(Color.ParseColor("#424242"));
|
||||
//if(MainActivity.Theme == 1)
|
||||
// view.SetBackgroundColor(Color.ParseColor("#424242"));
|
||||
|
||||
view.FindViewById(Resource.Id.loading).Visibility = ViewStates.Visible;
|
||||
EmptyView = view.FindViewById<TextView>(Resource.Id.empty);
|
||||
ListView = view.FindViewById<RecyclerView>(Resource.Id.recycler);
|
||||
ListView.SetLayoutManager(new LinearLayoutManager(Android.App.Application.Context));
|
||||
ListView.SetItemAnimator(new DefaultItemAnimator());
|
||||
adapter = new BrowseAdapter();
|
||||
ListView.SetAdapter(adapter);
|
||||
|
||||
#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed
|
||||
PopulateList();
|
||||
@@ -73,6 +77,42 @@ namespace Opus.Resources.Portable_Class
|
||||
return view;
|
||||
}
|
||||
|
||||
public async Task PopulateList()
|
||||
{
|
||||
if (await MainActivity.instance.GetReadPermission() == false)
|
||||
{
|
||||
MainActivity.instance.FindViewById(Resource.Id.loading).Visibility = ViewStates.Gone;
|
||||
EmptyView.Visibility = ViewStates.Visible;
|
||||
EmptyView.Text = GetString(Resource.String.no_permission);
|
||||
return;
|
||||
}
|
||||
|
||||
LoaderManager.GetInstance(this).InitLoader(0, null, this);
|
||||
|
||||
//if (adapter.ItemCount == 0)
|
||||
//{
|
||||
// EmptyView.Visibility = ViewStates.Visible;
|
||||
// EmptyView.Text = MainActivity.instance.Resources.GetString(Resource.String.no_song);
|
||||
//}
|
||||
}
|
||||
|
||||
public Android.Support.V4.Content.Loader OnCreateLoader(int id, Bundle args)
|
||||
{
|
||||
Uri musicUri = MediaStore.Audio.Media.ExternalContentUri;
|
||||
|
||||
return new CursorLoader(Android.App.Application.Context, musicUri, null, null, null, MediaStore.Audio.Media.InterfaceConsts.Title + " ASC");
|
||||
}
|
||||
|
||||
public void OnLoadFinished(Android.Support.V4.Content.Loader loader, Java.Lang.Object data)
|
||||
{
|
||||
adapter.SwapCursor((ICursor)data);
|
||||
}
|
||||
|
||||
public void OnLoaderReset(Android.Support.V4.Content.Loader loader)
|
||||
{
|
||||
adapter.SwapCursor(null);
|
||||
}
|
||||
|
||||
public static Fragment NewInstance()
|
||||
{
|
||||
if (instance == null)
|
||||
@@ -80,111 +120,40 @@ namespace Opus.Resources.Portable_Class
|
||||
return instance;
|
||||
}
|
||||
|
||||
public async Task PopulateList()
|
||||
{
|
||||
if (await MainActivity.instance.GetReadPermission() == false)
|
||||
return;
|
||||
|
||||
musicList = new List<Song>();
|
||||
Uri musicUri = MediaStore.Audio.Media.ExternalContentUri;
|
||||
|
||||
CursorLoader cursorLoader = new CursorLoader(Android.App.Application.Context, musicUri, null, null, null, null);
|
||||
ICursor musicCursor = (ICursor)cursorLoader.LoadInBackground();
|
||||
|
||||
if (musicCursor != null && musicCursor.MoveToFirst())
|
||||
{
|
||||
int titleID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Title);
|
||||
int artistID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Artist);
|
||||
int albumID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Album);
|
||||
int thisID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Id);
|
||||
int pathID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Data);
|
||||
do
|
||||
{
|
||||
string Artist = musicCursor.GetString(artistID);
|
||||
string Title = musicCursor.GetString(titleID);
|
||||
string Album = musicCursor.GetString(albumID);
|
||||
long AlbumArt = musicCursor.GetLong(musicCursor.GetColumnIndex(MediaStore.Audio.Albums.InterfaceConsts.AlbumId));
|
||||
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";
|
||||
|
||||
musicList.Add(new Song(Title, Artist, Album, null, AlbumArt, id, path));
|
||||
}
|
||||
while (musicCursor.MoveToNext());
|
||||
musicCursor.Close();
|
||||
List<Song> songList = musicList.OrderBy(x => x.Title).ToList();
|
||||
musicList = songList;
|
||||
}
|
||||
|
||||
adapter = new BrowseAdapter(result ?? musicList, result == null);
|
||||
ListView.SetAdapter(adapter);
|
||||
adapter.ItemClick += ListView_ItemClick;
|
||||
adapter.ItemLongCLick += ListView_ItemLongClick;
|
||||
|
||||
if (adapter.ItemCount == 0)
|
||||
{
|
||||
EmptyView.Visibility = ViewStates.Visible;
|
||||
EmptyView.Text = MainActivity.instance.Resources.GetString(Resource.String.no_song);
|
||||
}
|
||||
}
|
||||
|
||||
private async void OnRefresh(object sender, EventArgs e)
|
||||
private void OnRefresh(object sender, EventArgs e)
|
||||
{
|
||||
if (!focused)
|
||||
return;
|
||||
await Refresh();
|
||||
Refresh();
|
||||
MainActivity.instance.contentRefresh.Refreshing = false;
|
||||
}
|
||||
|
||||
public async Task Refresh()
|
||||
public void Refresh()
|
||||
{
|
||||
await PopulateList();
|
||||
adapter.NotifyDataSetChanged();
|
||||
}
|
||||
|
||||
//SHOULD CALL THIS METHOD EVERYTIME THE SEARCHBAR TEXT CHANGE
|
||||
public void Search(string search)
|
||||
{
|
||||
result = new List<Song>();
|
||||
foreach(Song item in musicList)
|
||||
{
|
||||
if(item.Title.ToLower().Contains(search.ToLower()) || item.Artist.ToLower().Contains(search.ToLower()))
|
||||
{
|
||||
result.Add(item);
|
||||
}
|
||||
}
|
||||
adapter = new BrowseAdapter(result, result.Count == musicList.Count);
|
||||
adapter.ItemClick += ListView_ItemClick;
|
||||
adapter.ItemLongCLick += ListView_ItemLongClick;
|
||||
Console.WriteLine("&ListView: " + ListView);
|
||||
ListView.SetAdapter(adapter);
|
||||
LoaderManager.GetInstance(this).RestartLoader(0, null, this);
|
||||
|
||||
//result = new List<Song>();
|
||||
//foreach(Song item in musicList)
|
||||
//{
|
||||
// if(item.Title.ToLower().Contains(search.ToLower()) || item.Artist.ToLower().Contains(search.ToLower()))
|
||||
// {
|
||||
// result.Add(item);
|
||||
// }
|
||||
//}
|
||||
//adapter = new BrowseAdapter(result, result.Count == musicList.Count);
|
||||
//adapter.ItemClick += ListView_ItemClick;
|
||||
//adapter.ItemLongCLick += ListView_ItemLongClick;
|
||||
//Console.WriteLine("&ListView: " + ListView);
|
||||
//ListView.SetAdapter(adapter);
|
||||
}
|
||||
|
||||
public void ListView_ItemClick(object sender, int position)
|
||||
{
|
||||
Song item = musicList[position];
|
||||
if (result != null)
|
||||
item = result[position];
|
||||
|
||||
item = CompleteItem(item);
|
||||
|
||||
Play(item);
|
||||
}
|
||||
|
||||
private void ListView_ItemLongClick(object sender, int position)
|
||||
{
|
||||
Song item = musicList[position];
|
||||
if (result != null)
|
||||
item = result[position];
|
||||
|
||||
More(item, position);
|
||||
}
|
||||
|
||||
public void More(Song item, int position)
|
||||
public void More(Song item)
|
||||
{
|
||||
item = CompleteItem(item);
|
||||
|
||||
@@ -192,6 +161,7 @@ namespace Opus.Resources.Portable_Class
|
||||
View bottomView = MainActivity.instance.LayoutInflater.Inflate(Resource.Layout.BottomSheet, null);
|
||||
bottomView.FindViewById<TextView>(Resource.Id.bsTitle).Text = item.Title;
|
||||
bottomView.FindViewById<TextView>(Resource.Id.bsArtist).Text = item.Artist;
|
||||
bottomSheet.SetContentView(bottomView);
|
||||
if (item.Album == null)
|
||||
{
|
||||
var songCover = Uri.Parse("content://media/external/audio/albumart");
|
||||
@@ -203,7 +173,6 @@ namespace Opus.Resources.Portable_Class
|
||||
{
|
||||
Picasso.With(MainActivity.instance).Load(item.Album).Placeholder(Resource.Drawable.noAlbum).Transform(new RemoveBlackBorder(true)).Into(bottomView.FindViewById<ImageView>(Resource.Id.bsArt));
|
||||
}
|
||||
bottomSheet.SetContentView(bottomView);
|
||||
|
||||
bottomSheet.FindViewById<ListView>(Resource.Id.bsItems).Adapter = new BottomSheetAdapter(MainActivity.instance, Resource.Layout.BottomSheetText, new List<BottomSheetAction>
|
||||
{
|
||||
@@ -46,6 +46,8 @@ using Request = Square.OkHttp.Request;
|
||||
using SearchView = Android.Support.V7.Widget.SearchView;
|
||||
using Toolbar = Android.Support.V7.Widget.Toolbar;
|
||||
using TransportType = Android.Net.TransportType;
|
||||
using Opus.Fragments;
|
||||
using Opus.DataStructure;
|
||||
|
||||
namespace Opus
|
||||
{
|
||||
@@ -322,15 +322,16 @@
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Code\Adapter\BaseCursor.cs" />
|
||||
<Compile Include="GlobalSuppressions.cs" />
|
||||
<Compile Include="MainActivity.cs" />
|
||||
<Compile Include="Code\MainActivity.cs" />
|
||||
<Compile Include="Resources\Portable Class\AccountPreference.cs" />
|
||||
<Compile Include="Resources\Portable Class\AccountTarget.cs" />
|
||||
<Compile Include="Resources\Portable Class\BrowseAdapter.cs" />
|
||||
<Compile Include="Code\Adapter\BrowseAdapter.cs" />
|
||||
<Compile Include="Resources\Portable Class\AddToPlaylistAdapter.cs" />
|
||||
<Compile Include="Resources\Portable Class\AudioStopper.cs" />
|
||||
<Compile Include="Resources\Portable Class\BottomSheetAdapter.cs" />
|
||||
<Compile Include="Resources\Portable Class\Browse.cs" />
|
||||
<Compile Include="Code\Fragments\Browse.cs" />
|
||||
<Compile Include="Resources\Portable Class\CastCallback.cs" />
|
||||
<Compile Include="Resources\Portable Class\CastProvider.cs" />
|
||||
<Compile Include="Resources\Portable Class\CastQueueManager.cs" />
|
||||
@@ -374,14 +375,13 @@
|
||||
<Compile Include="Resources\Portable Class\Queue.cs" />
|
||||
<Compile Include="Resources\Portable Class\QueueHolder.cs" />
|
||||
<Compile Include="Resources\Portable Class\QueueAdapter.cs" />
|
||||
<Compile Include="Resources\Portable Class\RecyclerHolder.cs" />
|
||||
<Compile Include="Resources\Portable Class\SeekbarPreference.cs" />
|
||||
<Compile Include="Resources\Portable Class\Sleeper.cs" />
|
||||
<Compile Include="Resources\Portable Class\SnackbarCallback.cs" />
|
||||
<Compile Include="Resources\Portable Class\SuggestionAdapter.cs" />
|
||||
<Compile Include="Resources\Portable Class\PlaylistItem.cs" />
|
||||
<Compile Include="Resources\Portable Class\TwoLineAdapter.cs" />
|
||||
<Compile Include="Resources\Portable Class\UslessHolder.cs" />
|
||||
<Compile Include="Code\DataStructure\UslessHolder.cs" />
|
||||
<Compile Include="Resources\Portable Class\ViewPagerAdapter.cs" />
|
||||
<Compile Include="Resources\Portable Class\YoutubeEngine.cs" />
|
||||
<Compile Include="Resources\Portable Class\YtAdapter.cs" />
|
||||
@@ -398,7 +398,7 @@
|
||||
<Compile Include="Resources\Portable Class\HomeItem.cs" />
|
||||
<Compile Include="Resources\Portable Class\HomeSection.cs" />
|
||||
<Compile Include="Resources\Portable Class\PaddingChange.cs" />
|
||||
<Compile Include="Resources\Portable Class\Song.cs" />
|
||||
<Compile Include="Code\DataStructure\Song.cs" />
|
||||
<Compile Include="Resources\Portable Class\Suggestion.cs" />
|
||||
<Compile Include="Resources\Portable Class\TwoLineHolder.cs" />
|
||||
</ItemGroup>
|
||||
@@ -897,6 +897,9 @@
|
||||
<SubType>Designer</SubType>
|
||||
</AndroidResource>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Code\API\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
|
||||
<Import Project="..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Animated.Vector.Drawable.targets" Condition="Exists('..\packages\Xamarin.Android.Support.Animated.Vector.Drawable.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.Animated.Vector.Drawable.targets')" />
|
||||
<Import Project="..\packages\Xamarin.Android.Support.v7.Preference.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.v7.Preference.targets" Condition="Exists('..\packages\Xamarin.Android.Support.v7.Preference.25.4.0.2\build\MonoAndroid70\Xamarin.Android.Support.v7.Preference.targets')" />
|
||||
|
||||
@@ -4,6 +4,7 @@ using Android.Graphics;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Opus.DataStructure;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Graphics;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Opus.Resources.values;
|
||||
using Square.Picasso;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Opus.Resources.Portable_Class
|
||||
{
|
||||
public class BrowseAdapter : RecyclerView.Adapter
|
||||
{
|
||||
public List<Song> songList;
|
||||
public bool displayShuffle;
|
||||
public event EventHandler<int> ItemClick;
|
||||
public event EventHandler<int> ItemLongCLick;
|
||||
|
||||
public BrowseAdapter(List<Song> songList, bool displayShuffle)
|
||||
{
|
||||
this.songList = songList;
|
||||
this.displayShuffle = displayShuffle;
|
||||
}
|
||||
|
||||
public override int ItemCount => songList.Count + ((displayShuffle && songList.Count != 0) ? 1 : 0);
|
||||
|
||||
public override void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)
|
||||
{
|
||||
if(position == 0 && displayShuffle)
|
||||
{
|
||||
if (MainActivity.Theme == 1)
|
||||
((CardView)viewHolder.ItemView).SetCardBackgroundColor(Color.ParseColor("#212121"));
|
||||
else
|
||||
((CardView)viewHolder.ItemView).SetCardBackgroundColor(Color.White);
|
||||
}
|
||||
else
|
||||
{
|
||||
RecyclerHolder holder = (RecyclerHolder)viewHolder;
|
||||
|
||||
if (MainActivity.Theme == 1)
|
||||
{
|
||||
holder.more.SetColorFilter(Color.White);
|
||||
holder.Title.SetTextColor(Color.White);
|
||||
holder.Artist.SetTextColor(Color.White);
|
||||
holder.Artist.Alpha = 0.7f;
|
||||
holder.ItemView.SetBackgroundColor(Color.ParseColor("#424242"));
|
||||
}
|
||||
else
|
||||
holder.ItemView.SetBackgroundColor(Color.White);
|
||||
|
||||
Song song = songList[position - (displayShuffle ? 1 : 0)];
|
||||
|
||||
holder.Title.Text = song.Title;
|
||||
holder.Artist.Text = song.Artist;
|
||||
|
||||
var songCover = Android.Net.Uri.Parse("content://media/external/audio/albumart");
|
||||
var songAlbumArtUri = ContentUris.WithAppendedId(songCover, song.AlbumArt);
|
||||
Picasso.With(Application.Context).Load(songAlbumArtUri).Placeholder(Resource.Color.background_material_dark).Resize(400, 400).CenterCrop().Into(holder.AlbumArt);
|
||||
|
||||
if (!holder.more.HasOnClickListeners)
|
||||
{
|
||||
holder.more.Click += (sender, e) =>
|
||||
{
|
||||
if (Browse.instance != null)
|
||||
{
|
||||
Browse.instance.More(songList[holder.AdapterPosition - (displayShuffle ? 1 : 0)], holder.AdapterPosition - (displayShuffle ? 1 : 0));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override RecyclerView.ViewHolder OnCreateViewHolder(ViewGroup parent, int viewType)
|
||||
{
|
||||
if (viewType == 0)
|
||||
{
|
||||
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.ShuffleButton, parent, false);
|
||||
return new UslessHolder(itemView, OnClick);
|
||||
}
|
||||
else
|
||||
{
|
||||
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.SongList, parent, false);
|
||||
return new RecyclerHolder(itemView, OnClick, OnLongClick);
|
||||
}
|
||||
}
|
||||
|
||||
public override int GetItemViewType(int position)
|
||||
{
|
||||
if (position == 0 && displayShuffle)
|
||||
return 0;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
void OnClick(int position)
|
||||
{
|
||||
if (position == 0 && displayShuffle)
|
||||
MainActivity.instance.ShuffleAll();
|
||||
else
|
||||
ItemClick?.Invoke(this, position - (displayShuffle ? 1 : 0));
|
||||
}
|
||||
|
||||
void OnLongClick(int position)
|
||||
{
|
||||
ItemLongCLick?.Invoke(this, position - (displayShuffle ? 1 : 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using Android.Gms.Cast.Framework.Media;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.values;
|
||||
|
||||
namespace Opus.Resources.Portable_Class
|
||||
|
||||
@@ -5,6 +5,7 @@ using Android.Support.V7.Widget;
|
||||
using Android.Text;
|
||||
using Android.Text.Style;
|
||||
using Android.Views;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.values;
|
||||
using Square.Picasso;
|
||||
|
||||
@@ -47,7 +48,7 @@ namespace Opus.Resources.Portable_Class
|
||||
header.Layout(0, 0, header.MeasuredWidth, header.MeasuredHeight);
|
||||
|
||||
header.FindViewById(Resource.Id.topDivider).Visibility = ViewStates.Gone;
|
||||
BindHolder(new RecyclerHolder(header, null, null));
|
||||
BindHolder(new SongHolder(header, null, null));
|
||||
Queue.instance.HeaderHeight = header.MeasuredHeight;
|
||||
|
||||
c.Save();
|
||||
@@ -68,7 +69,7 @@ namespace Opus.Resources.Portable_Class
|
||||
header.Layout(0, 0, header.MeasuredWidth, header.MeasuredHeight);
|
||||
|
||||
header.FindViewById(Resource.Id.bottomDivider).Visibility = ViewStates.Gone;
|
||||
BindHolder(new RecyclerHolder(header, null, null));
|
||||
BindHolder(new SongHolder(header, null, null));
|
||||
Queue.instance.HeaderHeight = -header.MeasuredHeight;
|
||||
|
||||
c.Save();
|
||||
@@ -84,7 +85,7 @@ namespace Opus.Resources.Portable_Class
|
||||
}
|
||||
}
|
||||
|
||||
void BindHolder(RecyclerHolder holder)
|
||||
void BindHolder(SongHolder holder)
|
||||
{
|
||||
Song current = MusicPlayer.queue[MusicPlayer.CurrentID()];
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ using Android.Support.V4.App;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Opus.Fragments;
|
||||
using Opus.Resources.values;
|
||||
using SQLite;
|
||||
using Square.Picasso;
|
||||
|
||||
@@ -12,6 +12,7 @@ using Android.Support.V7.App;
|
||||
using Android.Util;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.values;
|
||||
using Square.Picasso;
|
||||
using System.IO;
|
||||
|
||||
@@ -11,6 +11,8 @@ using Android.Support.V7.App;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Fragments;
|
||||
using Opus.Resources.values;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
using Android.Content;
|
||||
using Android.Database;
|
||||
using Android.Net;
|
||||
using Android.OS;
|
||||
using Android.Provider;
|
||||
using Android.Support.Design.Widget;
|
||||
using Android.Support.V4.App;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Opus.Resources.values;
|
||||
using Opus.Adapter;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Fragments;
|
||||
using Square.Picasso;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using CursorLoader = Android.Support.V4.Content.CursorLoader;
|
||||
|
||||
namespace Opus.Resources.Portable_Class
|
||||
{
|
||||
@@ -68,116 +67,116 @@ namespace Opus.Resources.Portable_Class
|
||||
|
||||
void PopulateList()
|
||||
{
|
||||
Uri musicUri = MediaStore.Audio.Media.GetContentUriForPath(path);
|
||||
//Uri musicUri = MediaStore.Audio.Media.GetContentUriForPath(path);
|
||||
|
||||
CursorLoader cursorLoader = new CursorLoader(Android.App.Application.Context, musicUri, null, null, null, null);
|
||||
ICursor musicCursor = (ICursor)cursorLoader.LoadInBackground();
|
||||
//CursorLoader cursorLoader = new CursorLoader(Android.App.Application.Context, musicUri, null, null, null, null);
|
||||
//ICursor musicCursor = (ICursor)cursorLoader.LoadInBackground();
|
||||
|
||||
tracks = new List<Song>();
|
||||
//tracks = new List<Song>();
|
||||
|
||||
if (musicCursor != null && musicCursor.MoveToFirst())
|
||||
{
|
||||
int titleID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Title);
|
||||
int artistID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Artist);
|
||||
int albumID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Album);
|
||||
int thisID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Id);
|
||||
int pathID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Data);
|
||||
do
|
||||
{
|
||||
string path = musicCursor.GetString(pathID);
|
||||
//if (musicCursor != null && musicCursor.MoveToFirst())
|
||||
//{
|
||||
// int titleID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Title);
|
||||
// int artistID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Artist);
|
||||
// int albumID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Album);
|
||||
// int thisID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Id);
|
||||
// int pathID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Data);
|
||||
// do
|
||||
// {
|
||||
// string path = musicCursor.GetString(pathID);
|
||||
|
||||
if (!path.Contains(this.path))
|
||||
continue;
|
||||
// if (!path.Contains(this.path))
|
||||
// continue;
|
||||
|
||||
string Artist = musicCursor.GetString(artistID);
|
||||
string Title = musicCursor.GetString(titleID);
|
||||
string Album = musicCursor.GetString(albumID);
|
||||
long AlbumArt = musicCursor.GetLong(musicCursor.GetColumnIndex(MediaStore.Audio.Albums.InterfaceConsts.AlbumId));
|
||||
long id = musicCursor.GetLong(thisID);
|
||||
// string Artist = musicCursor.GetString(artistID);
|
||||
// string Title = musicCursor.GetString(titleID);
|
||||
// string Album = musicCursor.GetString(albumID);
|
||||
// long AlbumArt = musicCursor.GetLong(musicCursor.GetColumnIndex(MediaStore.Audio.Albums.InterfaceConsts.AlbumId));
|
||||
// long id = musicCursor.GetLong(thisID);
|
||||
|
||||
if (Title == null)
|
||||
Title = "Unknown Title";
|
||||
if (Artist == null)
|
||||
Artist = "Unknow Artist";
|
||||
if (Album == null)
|
||||
Album = "Unknow Album";
|
||||
// if (Title == null)
|
||||
// Title = "Unknown Title";
|
||||
// if (Artist == null)
|
||||
// Artist = "Unknow Artist";
|
||||
// if (Album == null)
|
||||
// Album = "Unknow Album";
|
||||
|
||||
tracks.Add(new Song(Title, Artist, Album, null, AlbumArt, id, path));
|
||||
}
|
||||
while (musicCursor.MoveToNext());
|
||||
musicCursor.Close();
|
||||
}
|
||||
// tracks.Add(new Song(Title, Artist, Album, null, AlbumArt, id, path));
|
||||
// }
|
||||
// while (musicCursor.MoveToNext());
|
||||
// musicCursor.Close();
|
||||
//}
|
||||
|
||||
adapter = new BrowseAdapter(tracks, false);
|
||||
adapter.ItemClick += ListView_ItemClick;
|
||||
adapter.ItemLongCLick += ListView_ItemLongClick;
|
||||
ListView.SetAdapter(adapter);
|
||||
//adapter = new BrowseAdapter(tracks, false);
|
||||
//adapter.ItemClick += ListView_ItemClick;
|
||||
//adapter.ItemLongCLick += ListView_ItemLongClick;
|
||||
//ListView.SetAdapter(adapter);
|
||||
}
|
||||
|
||||
private void OnRefresh(object sender, System.EventArgs e)
|
||||
{
|
||||
tracks.Clear();
|
||||
//tracks.Clear();
|
||||
|
||||
Uri musicUri = MediaStore.Audio.Media.GetContentUriForPath(path);
|
||||
//Uri musicUri = MediaStore.Audio.Media.GetContentUriForPath(path);
|
||||
|
||||
CursorLoader cursorLoader = new CursorLoader(Android.App.Application.Context, musicUri, null, null, null, null);
|
||||
ICursor musicCursor = (ICursor)cursorLoader.LoadInBackground();
|
||||
//CursorLoader cursorLoader = new CursorLoader(Android.App.Application.Context, musicUri, null, null, null, null);
|
||||
//ICursor musicCursor = (ICursor)cursorLoader.LoadInBackground();
|
||||
|
||||
|
||||
if (musicCursor != null && musicCursor.MoveToFirst())
|
||||
{
|
||||
int titleID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Title);
|
||||
int artistID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Artist);
|
||||
int albumID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Album);
|
||||
int thisID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Id);
|
||||
int pathID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Data);
|
||||
do
|
||||
{
|
||||
string path = musicCursor.GetString(pathID);
|
||||
//if (musicCursor != null && musicCursor.MoveToFirst())
|
||||
//{
|
||||
// int titleID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Title);
|
||||
// int artistID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Artist);
|
||||
// int albumID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Album);
|
||||
// int thisID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Id);
|
||||
// int pathID = musicCursor.GetColumnIndex(MediaStore.Audio.Media.InterfaceConsts.Data);
|
||||
// do
|
||||
// {
|
||||
// string path = musicCursor.GetString(pathID);
|
||||
|
||||
if (!path.Contains(this.path))
|
||||
continue;
|
||||
// if (!path.Contains(this.path))
|
||||
// continue;
|
||||
|
||||
string Artist = musicCursor.GetString(artistID);
|
||||
string Title = musicCursor.GetString(titleID);
|
||||
string Album = musicCursor.GetString(albumID);
|
||||
long AlbumArt = musicCursor.GetLong(musicCursor.GetColumnIndex(MediaStore.Audio.Albums.InterfaceConsts.AlbumId));
|
||||
long id = musicCursor.GetLong(thisID);
|
||||
// string Artist = musicCursor.GetString(artistID);
|
||||
// string Title = musicCursor.GetString(titleID);
|
||||
// string Album = musicCursor.GetString(albumID);
|
||||
// long AlbumArt = musicCursor.GetLong(musicCursor.GetColumnIndex(MediaStore.Audio.Albums.InterfaceConsts.AlbumId));
|
||||
// long id = musicCursor.GetLong(thisID);
|
||||
|
||||
if (Title == null)
|
||||
Title = "Unknown Title";
|
||||
if (Artist == null)
|
||||
Artist = "Unknow Artist";
|
||||
if (Album == null)
|
||||
Album = "Unknow Album";
|
||||
// if (Title == null)
|
||||
// Title = "Unknown Title";
|
||||
// if (Artist == null)
|
||||
// Artist = "Unknow Artist";
|
||||
// if (Album == null)
|
||||
// Album = "Unknow Album";
|
||||
|
||||
tracks.Add(new Song(Title, Artist, Album, null, AlbumArt, id, path));
|
||||
}
|
||||
while (musicCursor.MoveToNext());
|
||||
musicCursor.Close();
|
||||
}
|
||||
// tracks.Add(new Song(Title, Artist, Album, null, AlbumArt, id, path));
|
||||
// }
|
||||
// while (musicCursor.MoveToNext());
|
||||
// musicCursor.Close();
|
||||
//}
|
||||
|
||||
adapter = new BrowseAdapter(tracks, false);
|
||||
adapter.ItemClick += ListView_ItemClick;
|
||||
adapter.ItemLongCLick += ListView_ItemLongClick;
|
||||
ListView.SetAdapter(adapter);
|
||||
MainActivity.instance.contentRefresh.Refreshing = false;
|
||||
//adapter = new BrowseAdapter(tracks, false);
|
||||
//adapter.ItemClick += ListView_ItemClick;
|
||||
//adapter.ItemLongCLick += ListView_ItemLongClick;
|
||||
//ListView.SetAdapter(adapter);
|
||||
//MainActivity.instance.contentRefresh.Refreshing = false;
|
||||
}
|
||||
|
||||
public void Search(string search)
|
||||
{
|
||||
result = new List<Song>();
|
||||
foreach (Song item in tracks)
|
||||
{
|
||||
if (item.Title.ToLower().Contains(search.ToLower()) || item.Artist.ToLower().Contains(search.ToLower()))
|
||||
{
|
||||
result.Add(item);
|
||||
}
|
||||
}
|
||||
adapter = new BrowseAdapter(result, false);
|
||||
adapter.ItemClick += ListView_ItemClick;
|
||||
adapter.ItemLongCLick += ListView_ItemLongClick;
|
||||
ListView.SetAdapter(adapter);
|
||||
//result = new List<Song>();
|
||||
//foreach (Song item in tracks)
|
||||
//{
|
||||
// if (item.Title.ToLower().Contains(search.ToLower()) || item.Artist.ToLower().Contains(search.ToLower()))
|
||||
// {
|
||||
// result.Add(item);
|
||||
// }
|
||||
//}
|
||||
//adapter = new BrowseAdapter(result, false);
|
||||
//adapter.ItemClick += ListView_ItemClick;
|
||||
//adapter.ItemLongCLick += ListView_ItemLongClick;
|
||||
//ListView.SetAdapter(adapter);
|
||||
}
|
||||
|
||||
private async void ListView_ItemClick(object sender, int position)
|
||||
|
||||
@@ -10,6 +10,7 @@ using Android.Support.V7.Widget.Helper;
|
||||
using Android.Views;
|
||||
using Google.Apis.YouTube.v3;
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.values;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -5,6 +5,7 @@ using Android.Support.Design.Widget;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Util;
|
||||
using Android.Views;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.values;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -6,6 +6,7 @@ using Android.Support.V7.Preferences;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.values;
|
||||
using Square.Picasso;
|
||||
using System.Collections.Generic;
|
||||
@@ -43,7 +44,7 @@ namespace Opus.Resources.Portable_Class
|
||||
|
||||
public override void OnBindViewHolder(RecyclerView.ViewHolder viewHolder, int position)
|
||||
{
|
||||
RecyclerHolder holder = (RecyclerHolder)viewHolder;
|
||||
SongHolder holder = (SongHolder)viewHolder;
|
||||
|
||||
if(UseChannel)
|
||||
{
|
||||
@@ -80,12 +81,12 @@ namespace Opus.Resources.Portable_Class
|
||||
if(UseChannel)
|
||||
{
|
||||
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.HomeChannel, parent, false);
|
||||
return new RecyclerHolder(itemView, OnClick, OnLongClick);
|
||||
return new SongHolder(itemView, OnClick, OnLongClick);
|
||||
}
|
||||
else
|
||||
{
|
||||
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.HomePlaylist, parent, false);
|
||||
return new RecyclerHolder(itemView, OnClick, OnLongClick);
|
||||
return new SongHolder(itemView, OnClick, OnLongClick);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Android.Support.V7.Widget;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.Portable_Class;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
@@ -7,6 +7,8 @@ using Android.Support.Design.Widget;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Fragments;
|
||||
using Opus.Resources.values;
|
||||
using Square.Picasso;
|
||||
using System.Collections.Generic;
|
||||
@@ -65,7 +67,7 @@ namespace Opus.Resources.Portable_Class
|
||||
}
|
||||
else
|
||||
{
|
||||
RecyclerHolder holder = (RecyclerHolder)viewHolder;
|
||||
SongHolder holder = (SongHolder)viewHolder;
|
||||
|
||||
Song song = songList.Count <= position ? null : songList[position];
|
||||
|
||||
@@ -102,7 +104,7 @@ namespace Opus.Resources.Portable_Class
|
||||
{
|
||||
if (payloads.Count > 0)
|
||||
{
|
||||
RecyclerHolder holder = (RecyclerHolder)viewHolder;
|
||||
SongHolder holder = (SongHolder)viewHolder;
|
||||
|
||||
if(payloads[0].ToString() == holder.Title.Text)
|
||||
return;
|
||||
@@ -130,7 +132,7 @@ namespace Opus.Resources.Portable_Class
|
||||
if (viewType == 0)
|
||||
{
|
||||
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.LineSong, parent, false);
|
||||
return new RecyclerHolder(itemView, OnClick, OnLongClick);
|
||||
return new SongHolder(itemView, OnClick, OnLongClick);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -193,7 +195,7 @@ namespace Opus.Resources.Portable_Class
|
||||
List<BottomSheetAction> actions = new List<BottomSheetAction>
|
||||
{
|
||||
new BottomSheetAction(Resource.Drawable.Play, MainActivity.instance.Resources.GetString(Resource.String.play), (sender, eventArg) => { OnClick(position); bottomSheet.Dismiss(); }),
|
||||
new BottomSheetAction(Resource.Drawable.Close, MainActivity.instance.Resources.GetString(Resource.String.remove_from_queue), (sender, eventArg) => { Queue.RemoveFromQueue(position); bottomSheet.Dismiss(); }),
|
||||
new BottomSheetAction(Resource.Drawable.Close, MainActivity.instance.Resources.GetString(Resource.String.remove_from_queue), (sender, eventArg) => { MusicPlayer.RemoveFromQueue(position); bottomSheet.Dismiss(); }),
|
||||
new BottomSheetAction(Resource.Drawable.PlaylistAdd, MainActivity.instance.Resources.GetString(Resource.String.add_to_playlist), (sender, eventArg) => { Browse.GetPlaylist(item); bottomSheet.Dismiss(); })
|
||||
};
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ using CursorLoader = Android.Support.V4.Content.CursorLoader;
|
||||
using MediaInfo = Android.Gms.Cast.MediaInfo;
|
||||
using MediaMetadata = Android.Gms.Cast.MediaMetadata;
|
||||
using Uri = Android.Net.Uri;
|
||||
using Opus.Fragments;
|
||||
using Opus.DataStructure;
|
||||
|
||||
namespace Opus.Resources.Portable_Class
|
||||
{
|
||||
|
||||
@@ -3,6 +3,7 @@ using Android.Support.Design.Widget;
|
||||
using Android.Support.V4.App;
|
||||
using Android.Support.V4.View;
|
||||
using Android.Views;
|
||||
using Opus.Fragments;
|
||||
|
||||
namespace Opus.Resources.Portable_Class
|
||||
{
|
||||
|
||||
@@ -16,6 +16,8 @@ using Android.Text.Style;
|
||||
using Android.Util;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Fragments;
|
||||
using Opus.Resources.Portable_Class;
|
||||
using Opus.Resources.values;
|
||||
using Square.Picasso;
|
||||
@@ -376,7 +378,9 @@ namespace Opus
|
||||
|
||||
private void Fav(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
Snackbar snackBar = Snackbar.Make(MainActivity.instance.FindViewById<CoordinatorLayout>(Resource.Id.snackBar), "Comming Soon", Snackbar.LengthLong);
|
||||
snackBar.View.FindViewById<TextView>(Resource.Id.snackbar_text).SetTextColor(Color.White);
|
||||
snackBar.Show();
|
||||
}
|
||||
|
||||
private async void More(object s, EventArgs e)
|
||||
|
||||
@@ -19,6 +19,8 @@ using System.Threading.Tasks;
|
||||
using static Android.Provider.MediaStore.Audio;
|
||||
using CursorLoader = Android.Support.V4.Content.CursorLoader;
|
||||
using Application = Android.App.Application;
|
||||
using Opus.Fragments;
|
||||
using Opus.DataStructure;
|
||||
|
||||
namespace Opus.Resources.Portable_Class
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@ using Android.Graphics.Drawables;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.values;
|
||||
using Square.Picasso;
|
||||
using System;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Opus.Resources.values;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.values;
|
||||
using SQLite;
|
||||
using System;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ using Android.Graphics;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.values;
|
||||
using Square.Picasso;
|
||||
using System;
|
||||
@@ -126,7 +127,7 @@ namespace Opus.Resources.Portable_Class
|
||||
if(position >= songList.Count)
|
||||
return;
|
||||
|
||||
RecyclerHolder holder = (RecyclerHolder)viewHolder;
|
||||
SongHolder holder = (SongHolder)viewHolder;
|
||||
|
||||
holder.Title.Text = songList[position].Title;
|
||||
holder.Artist.Text = songList[position].Artist;
|
||||
@@ -173,7 +174,7 @@ namespace Opus.Resources.Portable_Class
|
||||
if(viewType == 0)
|
||||
{
|
||||
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.SongList, parent, false);
|
||||
return new RecyclerHolder(itemView, OnClick, OnLongClick);
|
||||
return new SongHolder(itemView, OnClick, OnLongClick);
|
||||
}
|
||||
else if(viewType == 1)
|
||||
{
|
||||
|
||||
@@ -10,6 +10,8 @@ using Android.Views;
|
||||
using Android.Widget;
|
||||
using Google.Apis.YouTube.v3;
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Fragments;
|
||||
using Opus.Resources.values;
|
||||
using SQLite;
|
||||
using Square.Picasso;
|
||||
|
||||
@@ -12,6 +12,8 @@ using Android.Text.Style;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Opus;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Fragments;
|
||||
using Opus.Resources.Portable_Class;
|
||||
using Opus.Resources.values;
|
||||
using Square.Picasso;
|
||||
@@ -110,7 +112,7 @@ public class Queue : Fragment, RecyclerView.IOnItemTouchListener, PopupMenu.IOnM
|
||||
if(i > 0)
|
||||
{
|
||||
Song song = MusicPlayer.queue[i - 1];
|
||||
RecyclerHolder holder = (RecyclerHolder)ListView.GetChildViewHolder(((LinearLayoutManager)ListView.GetLayoutManager()).FindViewByPosition(i));
|
||||
SongHolder holder = (SongHolder)ListView.GetChildViewHolder(((LinearLayoutManager)ListView.GetLayoutManager()).FindViewByPosition(i));
|
||||
if (MusicPlayer.CurrentID() > -1 && MusicPlayer.queue[MusicPlayer.CurrentID()] == song)
|
||||
{
|
||||
holder.status.Visibility = ViewStates.Visible;
|
||||
|
||||
@@ -8,6 +8,7 @@ using Android.Text;
|
||||
using Android.Text.Style;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.values;
|
||||
using Square.Picasso;
|
||||
using System;
|
||||
@@ -143,7 +144,7 @@ namespace Opus.Resources.Portable_Class
|
||||
else
|
||||
{
|
||||
position--;
|
||||
RecyclerHolder holder = (RecyclerHolder)viewHolder;
|
||||
SongHolder holder = (SongHolder)viewHolder;
|
||||
|
||||
holder.reorder.SetColorFilter(Color.White);
|
||||
holder.Title.SetTextColor(Color.White);
|
||||
@@ -326,7 +327,7 @@ namespace Opus.Resources.Portable_Class
|
||||
}
|
||||
else
|
||||
{
|
||||
RecyclerHolder holder = (RecyclerHolder)viewHolder;
|
||||
SongHolder holder = (SongHolder)viewHolder;
|
||||
|
||||
if (payloads[0].ToString() == holder.Title.Text)
|
||||
return;
|
||||
@@ -366,7 +367,7 @@ namespace Opus.Resources.Portable_Class
|
||||
if (viewType == 0)
|
||||
{
|
||||
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.SongList, parent, false);
|
||||
return new RecyclerHolder(itemView, OnClick, OnLongClick);
|
||||
return new SongHolder(itemView, OnClick, OnLongClick);
|
||||
}
|
||||
else if(viewType == 1)
|
||||
{
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
using Android.Graphics;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using System;
|
||||
|
||||
namespace Opus.Resources.Portable_Class
|
||||
{
|
||||
public class RecyclerHolder : RecyclerView.ViewHolder
|
||||
{
|
||||
public ImageView reorder;
|
||||
public TextView Title;
|
||||
public TextView Artist;
|
||||
public TextView Live;
|
||||
public ImageView AlbumArt;
|
||||
public ImageView youtubeIcon;
|
||||
public ImageView more;
|
||||
public TextView status;
|
||||
public Button action;
|
||||
public View RightButtons;
|
||||
public View TextLayout;
|
||||
|
||||
public RecyclerHolder(View itemView, Action<int> listener, Action<int> longListener) : base(itemView)
|
||||
{
|
||||
reorder = itemView.FindViewById<ImageView>(Resource.Id.reorder);
|
||||
Title = itemView.FindViewById<TextView>(Resource.Id.title);
|
||||
Artist = itemView.FindViewById<TextView>(Resource.Id.artist);
|
||||
Live = itemView.FindViewById<TextView>(Resource.Id.isLive);
|
||||
AlbumArt = itemView.FindViewById<ImageView>(Resource.Id.albumArt);
|
||||
youtubeIcon = itemView.FindViewById<ImageView>(Resource.Id.youtubeIcon);
|
||||
more = itemView.FindViewById<ImageView>(Resource.Id.moreButton);
|
||||
RightButtons = itemView.FindViewById(Resource.Id.rightButtons);
|
||||
TextLayout = itemView.FindViewById(Resource.Id.textLayout);
|
||||
status = itemView.FindViewById<TextView>(Resource.Id.status);
|
||||
action = itemView.FindViewById<Button>(Resource.Id.action);
|
||||
|
||||
itemView.Click += (sender, e) => listener(AdapterPosition);
|
||||
itemView.LongClick += (sender, e) => longListener(AdapterPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using Android.Net;
|
||||
using Android.Provider;
|
||||
using Android.Support.Design.Widget;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.values;
|
||||
|
||||
namespace Opus.Resources.Portable_Class
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
using Android.Gms.Cast;
|
||||
using Newtonsoft.Json;
|
||||
using SQLite;
|
||||
using System;
|
||||
|
||||
namespace Opus.Resources.values
|
||||
{
|
||||
[Serializable]
|
||||
public class Song
|
||||
{
|
||||
[PrimaryKey, Unique]
|
||||
public int Index { get; set; }
|
||||
|
||||
public string Title { get; set; }
|
||||
public string Artist { get; set; }
|
||||
public string Album { get; set; }
|
||||
public long AlbumArt { get; set; }
|
||||
public string YoutubeID { get; set; }
|
||||
public long Id { get; set; }
|
||||
public string Path { get; set; }
|
||||
public bool? IsParsed { get; set; }
|
||||
public bool IsYt { get; set; }
|
||||
public DateTimeOffset? ExpireDate { get; set;}
|
||||
public bool IsLiveStream = false;
|
||||
public string TrackID;
|
||||
|
||||
public Song() { }
|
||||
|
||||
public Song(string title, string artist, string album, string youtubeID, long albumArt, long id, string path, bool isYT = false, bool isParsed = true)
|
||||
{
|
||||
Title = title;
|
||||
Artist = artist;
|
||||
Album = album;
|
||||
YoutubeID = youtubeID;
|
||||
AlbumArt = albumArt;
|
||||
Id = id;
|
||||
Path = path;
|
||||
IsYt = isYT;
|
||||
IsParsed = isParsed;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Title + " Artist: " + Artist + " Album: " + Album + " youtubeID: " + YoutubeID + " AlbumArt: " + AlbumArt + " Id: " + Id + " Path: " + Path + " isYT: " + IsYt + " isParsed: " + IsParsed;
|
||||
}
|
||||
|
||||
public static explicit operator Song(string v)
|
||||
{
|
||||
if (v == null)
|
||||
return null;
|
||||
|
||||
string Name = v.Substring(0, v.IndexOf(" Artist: "));
|
||||
string Artist = v.Substring(v.IndexOf(" Artist: ") + 9, v.IndexOf(" Album: ") - Name.Length - 8);
|
||||
string Album = v.Substring(v.IndexOf(" Album: ") + 8, v.IndexOf(" youtubeID: ") - v.IndexOf(" Album: ") - 8);
|
||||
string youtubeID = v.Substring(v.IndexOf(" youtubeID: ") + 12, v.IndexOf(" AlbumArt: ") - v.IndexOf(" youtubeID: ") - 12);
|
||||
long AlbumArt = long.Parse(v.Substring(v.IndexOf(" AlbumArt: ") + 11, v.IndexOf(" Id: ") - v.IndexOf(" AlbumArt: ") - 11));
|
||||
long id = long.Parse(v.Substring(v.IndexOf(" Id: ") + 5, v.IndexOf(" Path: ") - v.IndexOf(" Id: ") - 5));
|
||||
string path = v.Substring(v.IndexOf(" Path: ") + 7, v.IndexOf(" isYT: ") - v.IndexOf(" Path: ") - 7);
|
||||
bool isYT = bool.Parse(v.Substring(v.IndexOf(" isYT: ") + 7, v.IndexOf(" isParsed: ") - v.IndexOf(" isYT: ") - 7));
|
||||
bool isParsed = bool.Parse(v.Substring(v.IndexOf(" isParsed: ") + 11));
|
||||
|
||||
Song song = new Song(Name, Artist, Album, youtubeID, AlbumArt, id, path, isYT, isParsed);
|
||||
return song;
|
||||
}
|
||||
|
||||
public static explicit operator Song(MediaQueueItem v)
|
||||
{
|
||||
if (v == null)
|
||||
return null;
|
||||
|
||||
return JsonConvert.DeserializeObject<Song>(v.Media.CustomData.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ using Android.Views;
|
||||
using Android.Widget;
|
||||
using Google.Apis.YouTube.v3;
|
||||
using Google.Apis.YouTube.v3.Data;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Fragments;
|
||||
using Opus.Resources.values;
|
||||
using Square.Picasso;
|
||||
using System;
|
||||
|
||||
@@ -5,6 +5,7 @@ using Android.Support.V7.Preferences;
|
||||
using Android.Support.V7.Widget;
|
||||
using Android.Views;
|
||||
using Android.Widget;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.values;
|
||||
using Square.Picasso;
|
||||
using System;
|
||||
@@ -34,7 +35,7 @@ namespace Opus.Resources.Portable_Class
|
||||
|
||||
if(items[position].Kind == YtKind.Video)
|
||||
{
|
||||
RecyclerHolder holder = (RecyclerHolder)viewHolder;
|
||||
SongHolder holder = (SongHolder)viewHolder;
|
||||
|
||||
holder.Title.Text = song.Title;
|
||||
holder.Artist.Text = song.Artist;
|
||||
@@ -165,7 +166,7 @@ namespace Opus.Resources.Portable_Class
|
||||
if(viewType == 0)
|
||||
{
|
||||
View itemView = LayoutInflater.From(parent.Context).Inflate(Resource.Layout.SongList, parent, false);
|
||||
return new RecyclerHolder(itemView, OnClick, OnLongClick);
|
||||
return new SongHolder(itemView, OnClick, OnLongClick);
|
||||
}
|
||||
else if(viewType == 1)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Opus.Resources.values;
|
||||
using Opus.DataStructure;
|
||||
using Opus.Resources.values;
|
||||
|
||||
namespace Opus.Resources.Portable_Class
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user