Last added playlist half working. More to come tomorrow.
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest package="com.kabouzeid.gramophone"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
package="com.kabouzeid.gramophone">
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||||
|
|
@ -18,7 +18,6 @@
|
||||||
android:supportsRtl="true"
|
android:supportsRtl="true"
|
||||||
android:theme="@style/Theme.MaterialMusic.Light"
|
android:theme="@style/Theme.MaterialMusic.Light"
|
||||||
tools:ignore="UnusedAttribute">
|
tools:ignore="UnusedAttribute">
|
||||||
|
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.activities.MainActivity"
|
android:name=".ui.activities.MainActivity"
|
||||||
android:label="@string/app_name">
|
android:label="@string/app_name">
|
||||||
|
|
@ -30,12 +29,11 @@
|
||||||
<category android:name="android.intent.category.APP_MUSIC" />
|
<category android:name="android.intent.category.APP_MUSIC" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
<action android:name="android.media.action.MEDIA_PLAY_FROM_SEARCH" />
|
||||||
|
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
|
||||||
|
|
@ -140,7 +138,9 @@
|
||||||
<activity
|
<activity
|
||||||
android:name=".ui.activities.SettingsActivity"
|
android:name=".ui.activities.SettingsActivity"
|
||||||
android:label="@string/title_activity_settings" />
|
android:label="@string/title_activity_settings" />
|
||||||
|
<activity
|
||||||
|
android:name=".ui.activities.SmartPlaylistDetailActivity"
|
||||||
|
android:label="@string/title_activity_smart_playlist_detail"></activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
||||||
</manifest>
|
</manifest>
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,10 @@ public abstract class AbsMultiSelectAdapter<VH extends RecyclerView.ViewHolder,
|
||||||
this.context = context;
|
this.context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void setMultiSelectMenuRes(int menuRes) {
|
||||||
|
this.menuRes = menuRes;
|
||||||
|
}
|
||||||
|
|
||||||
protected void toggleChecked(final int position) {
|
protected void toggleChecked(final int position) {
|
||||||
if (cabHolder != null) {
|
if (cabHolder != null) {
|
||||||
openCabIfNecessary();
|
openCabIfNecessary();
|
||||||
|
|
@ -52,7 +56,7 @@ public abstract class AbsMultiSelectAdapter<VH extends RecyclerView.ViewHolder,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void uncheckAll() {
|
private void unCheckAll() {
|
||||||
checked.clear();
|
checked.clear();
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
@ -74,13 +78,13 @@ public abstract class AbsMultiSelectAdapter<VH extends RecyclerView.ViewHolder,
|
||||||
public boolean onCabItemClicked(MenuItem menuItem) {
|
public boolean onCabItemClicked(MenuItem menuItem) {
|
||||||
onMultipleItemAction(menuItem, new ArrayList<>(checked));
|
onMultipleItemAction(menuItem, new ArrayList<>(checked));
|
||||||
cab.finish();
|
cab.finish();
|
||||||
uncheckAll();
|
unCheckAll();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCabFinished(MaterialCab materialCab) {
|
public boolean onCabFinished(MaterialCab materialCab) {
|
||||||
uncheckAll();
|
unCheckAll();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import android.view.LayoutInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.PopupMenu;
|
import android.widget.PopupMenu;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
|
@ -21,7 +22,9 @@ import com.kabouzeid.gramophone.interfaces.CabHolder;
|
||||||
import com.kabouzeid.gramophone.loader.PlaylistLoader;
|
import com.kabouzeid.gramophone.loader.PlaylistLoader;
|
||||||
import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
|
import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
|
||||||
import com.kabouzeid.gramophone.model.DataBaseChangedEvent;
|
import com.kabouzeid.gramophone.model.DataBaseChangedEvent;
|
||||||
|
import com.kabouzeid.gramophone.model.LastAddedPlaylist;
|
||||||
import com.kabouzeid.gramophone.model.Playlist;
|
import com.kabouzeid.gramophone.model.Playlist;
|
||||||
|
import com.kabouzeid.gramophone.model.SmartPlaylist;
|
||||||
import com.kabouzeid.gramophone.model.Song;
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
||||||
import com.kabouzeid.gramophone.util.NavigationUtil;
|
import com.kabouzeid.gramophone.util.NavigationUtil;
|
||||||
|
|
@ -30,12 +33,19 @@ import com.squareup.otto.Subscribe;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import butterknife.InjectView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karim Abou Zeid (kabouzeid)
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
*/
|
*/
|
||||||
public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewHolder, Playlist> {
|
public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewHolder, Playlist> {
|
||||||
|
|
||||||
public static final String TAG = PlaylistAdapter.class.getSimpleName();
|
public static final String TAG = PlaylistAdapter.class.getSimpleName();
|
||||||
|
|
||||||
|
private int VIEW_TYPE_SMART = 0;
|
||||||
|
private int VIEW_TYPE_DEFAULT = 1;
|
||||||
|
|
||||||
protected final AppCompatActivity activity;
|
protected final AppCompatActivity activity;
|
||||||
protected List<Playlist> dataSet;
|
protected List<Playlist> dataSet;
|
||||||
|
|
||||||
|
|
@ -46,12 +56,15 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewH
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadDataSet() {
|
public void loadDataSet() {
|
||||||
dataSet = PlaylistLoader.getAllPlaylists(activity);
|
dataSet = new ArrayList<>();
|
||||||
|
dataSet.add(new LastAddedPlaylist(activity));
|
||||||
|
dataSet.addAll(PlaylistLoader.getAllPlaylists(activity));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
View view = LayoutInflater.from(activity).inflate(R.layout.item_list_playlist, parent, false);
|
int layoutRes = viewType == VIEW_TYPE_DEFAULT ? R.layout.item_list_playlist : R.layout.item_list_smart_playlist;
|
||||||
|
View view = LayoutInflater.from(activity).inflate(layoutRes, parent, false);
|
||||||
return new ViewHolder(view);
|
return new ViewHolder(view);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -60,6 +73,19 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewH
|
||||||
final Playlist playlist = dataSet.get(position);
|
final Playlist playlist = dataSet.get(position);
|
||||||
holder.playlistName.setText(playlist.name);
|
holder.playlistName.setText(playlist.name);
|
||||||
holder.view.setActivated(isChecked(playlist));
|
holder.view.setActivated(isChecked(playlist));
|
||||||
|
holder.icon.setImageResource(getIconRes(playlist));
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getIconRes(Playlist playlist) {
|
||||||
|
if (playlist instanceof SmartPlaylist) {
|
||||||
|
return ((SmartPlaylist) playlist).iconRes;
|
||||||
|
}
|
||||||
|
return R.drawable.ic_queue_music_white_24dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
return dataSet.get(position) instanceof SmartPlaylist ? VIEW_TYPE_SMART : VIEW_TYPE_DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -90,28 +116,35 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewH
|
||||||
private ArrayList<Song> getSongList(List<Playlist> playlists) {
|
private ArrayList<Song> getSongList(List<Playlist> playlists) {
|
||||||
final ArrayList<Song> songs = new ArrayList<>();
|
final ArrayList<Song> songs = new ArrayList<>();
|
||||||
for (Playlist playlist : playlists) {
|
for (Playlist playlist : playlists) {
|
||||||
songs.addAll(PlaylistSongLoader.getPlaylistSongList(activity, playlist.id));
|
if (playlist instanceof SmartPlaylist) {
|
||||||
|
songs.addAll(((SmartPlaylist) playlist).getSongs(activity));
|
||||||
|
} else {
|
||||||
|
songs.addAll(PlaylistSongLoader.getPlaylistSongList(activity, playlist.id));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return songs;
|
return songs;
|
||||||
}
|
}
|
||||||
|
|
||||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
||||||
public final TextView playlistName;
|
@InjectView(R.id.playlist_name)
|
||||||
private final View menu;
|
TextView playlistName;
|
||||||
private final View view;
|
@InjectView(R.id.menu)
|
||||||
|
View menu;
|
||||||
|
@InjectView(R.id.playlist_icon)
|
||||||
|
ImageView icon;
|
||||||
|
View view;
|
||||||
|
|
||||||
public ViewHolder(View itemView) {
|
public ViewHolder(View itemView) {
|
||||||
super(itemView);
|
super(itemView);
|
||||||
|
ButterKnife.inject(this, itemView);
|
||||||
view = itemView;
|
view = itemView;
|
||||||
playlistName = (TextView) itemView.findViewById(R.id.playlist_name);
|
|
||||||
menu = itemView.findViewById(R.id.menu);
|
|
||||||
view.setOnClickListener(this);
|
view.setOnClickListener(this);
|
||||||
view.setOnLongClickListener(this);
|
view.setOnLongClickListener(this);
|
||||||
menu.setOnClickListener(new View.OnClickListener() {
|
menu.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
PopupMenu popupMenu = new PopupMenu(activity, view);
|
PopupMenu popupMenu = new PopupMenu(activity, view);
|
||||||
popupMenu.inflate(R.menu.menu_item_playlist);
|
popupMenu.inflate(getItemViewType() == VIEW_TYPE_SMART ? R.menu.menu_item_smart_playlist : R.menu.menu_item_playlist);
|
||||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
|
|
@ -132,7 +165,8 @@ public class PlaylistAdapter extends AbsMultiSelectAdapter<PlaylistAdapter.ViewH
|
||||||
Pair[] sharedViews = null;
|
Pair[] sharedViews = null;
|
||||||
if (activity instanceof AbsFabActivity)
|
if (activity instanceof AbsFabActivity)
|
||||||
sharedViews = ((AbsFabActivity) activity).getSharedViewsWithFab(null);
|
sharedViews = ((AbsFabActivity) activity).getSharedViewsWithFab(null);
|
||||||
NavigationUtil.goToPlaylist(activity, dataSet.get(getAdapterPosition()).id, sharedViews);
|
Playlist playlist = dataSet.get(getAdapterPosition());
|
||||||
|
NavigationUtil.goToPlaylist(activity, playlist, sharedViews);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
package com.kabouzeid.gramophone.adapter.songadapter;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v4.util.Pair;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.adapter.AbsMultiSelectAdapter;
|
||||||
|
import com.kabouzeid.gramophone.dialogs.AddToPlaylistDialog;
|
||||||
|
import com.kabouzeid.gramophone.helper.MenuItemClickHelper;
|
||||||
|
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||||
|
import com.kabouzeid.gramophone.interfaces.CabHolder;
|
||||||
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
|
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
||||||
|
import com.kabouzeid.gramophone.util.MusicUtil;
|
||||||
|
import com.kabouzeid.gramophone.util.NavigationUtil;
|
||||||
|
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
||||||
|
import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
|
*/
|
||||||
|
public abstract class AbsPlaylistSongAdapter<S extends Song> extends AbsMultiSelectAdapter<PlaylistSongViewHolder, S> implements PlaylistSongViewHolder.onViewHolderClickListener, PlaylistSongViewHolder.onViewHolderLongClickListener, PlaylistSongViewHolder.onViewHolderMenuItemClickListener {
|
||||||
|
|
||||||
|
public static final String TAG = AlbumSongAdapter.class.getSimpleName();
|
||||||
|
protected final AppCompatActivity activity;
|
||||||
|
protected ArrayList<S> dataSet;
|
||||||
|
|
||||||
|
public AbsPlaylistSongAdapter(AppCompatActivity activity, ArrayList<S> objects, @Nullable CabHolder cabHolder) {
|
||||||
|
super(activity, cabHolder, R.menu.menu_playlists_songs_selection);
|
||||||
|
setMultiSelectMenuRes(getMultiSelectMenuRes());
|
||||||
|
this.activity = activity;
|
||||||
|
dataSet = objects;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateDataSet(ArrayList<S> objects) {
|
||||||
|
dataSet = objects;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getMultiSelectMenuRes() {
|
||||||
|
return R.menu.menu_playlists_songs_selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected int getSongMenuRes() {
|
||||||
|
return R.menu.menu_item_playlist_song;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PlaylistSongViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
View view = LayoutInflater.from(activity).inflate(R.layout.item_list_song, parent, false);
|
||||||
|
return new PlaylistSongViewHolder(this, view, getSongMenuRes());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(final PlaylistSongViewHolder holder, int position) {
|
||||||
|
final S song = dataSet.get(position);
|
||||||
|
|
||||||
|
holder.view.setActivated(isChecked(song));
|
||||||
|
holder.songTitle.setText(song.title);
|
||||||
|
holder.songInfo.setText(song.artistName);
|
||||||
|
ImageLoader.getInstance().displayImage(
|
||||||
|
MusicUtil.getAlbumArtUri(song.albumId).toString(),
|
||||||
|
holder.albumArt,
|
||||||
|
new DisplayImageOptions.Builder()
|
||||||
|
.cacheInMemory(true)
|
||||||
|
.showImageOnFail(R.drawable.default_album_art)
|
||||||
|
.resetViewBeforeLoading(true)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return dataSet.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected S getIdentifier(int position) {
|
||||||
|
return dataSet.get(position);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMultipleItemAction(MenuItem menuItem, ArrayList<S> selection) {
|
||||||
|
switch (menuItem.getItemId()) {
|
||||||
|
case R.id.action_delete_from_playlist:
|
||||||
|
onDeleteFromPlaylist(selection);
|
||||||
|
break;
|
||||||
|
case R.id.action_add_to_playlist:
|
||||||
|
onAddToPlaylist(selection);
|
||||||
|
break;
|
||||||
|
case R.id.action_add_to_current_playing:
|
||||||
|
onAddToCurrentPlaying(selection);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v, int adapterPosition) {
|
||||||
|
if (isInQuickSelectMode()) {
|
||||||
|
toggleChecked(adapterPosition);
|
||||||
|
} else {
|
||||||
|
//noinspection unchecked
|
||||||
|
MusicPlayerRemote.openQueue((ArrayList<Song>) (List) dataSet, adapterPosition, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onLongClick(View v, int adapterPosition) {
|
||||||
|
toggleChecked(adapterPosition);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem item, PlaylistSongViewHolder viewHolder, int adapterPosition) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.action_delete_from_playlist:
|
||||||
|
onDeleteFromPlaylist(dataSet.get(adapterPosition));
|
||||||
|
return true;
|
||||||
|
case R.id.action_go_to_album:
|
||||||
|
Pair[] albumPairs = new Pair[]{
|
||||||
|
Pair.create(viewHolder.albumArt, activity.getString(R.string.transition_album_cover))
|
||||||
|
};
|
||||||
|
if (activity instanceof AbsFabActivity)
|
||||||
|
albumPairs = ((AbsFabActivity) activity).getSharedViewsWithFab(albumPairs);
|
||||||
|
NavigationUtil.goToAlbum(activity, dataSet.get(adapterPosition).albumId, albumPairs);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return MenuItemClickHelper.handleSongMenuClick(activity, dataSet.get(adapterPosition), item);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onDeleteFromPlaylist(S song) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onDeleteFromPlaylist(ArrayList<S> songs) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onAddToPlaylist(ArrayList<S> songs) {
|
||||||
|
//noinspection unchecked
|
||||||
|
AddToPlaylistDialog.create((ArrayList<Song>) (List) songs).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onAddToCurrentPlaying(ArrayList<S> songs) {
|
||||||
|
//noinspection unchecked
|
||||||
|
MusicPlayerRemote.enqueue((ArrayList<Song>) (List) songs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,165 +1,32 @@
|
||||||
package com.kabouzeid.gramophone.adapter.songadapter;
|
package com.kabouzeid.gramophone.adapter.songadapter;
|
||||||
|
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
import android.support.v4.util.Pair;
|
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
import android.support.v7.widget.RecyclerView;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.ImageView;
|
|
||||||
import android.widget.PopupMenu;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import com.kabouzeid.gramophone.R;
|
|
||||||
import com.kabouzeid.gramophone.adapter.AbsMultiSelectAdapter;
|
|
||||||
import com.kabouzeid.gramophone.dialogs.AddToPlaylistDialog;
|
|
||||||
import com.kabouzeid.gramophone.dialogs.RemoveFromPlaylistDialog;
|
import com.kabouzeid.gramophone.dialogs.RemoveFromPlaylistDialog;
|
||||||
import com.kabouzeid.gramophone.helper.MenuItemClickHelper;
|
|
||||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
|
||||||
import com.kabouzeid.gramophone.interfaces.CabHolder;
|
import com.kabouzeid.gramophone.interfaces.CabHolder;
|
||||||
import com.kabouzeid.gramophone.model.PlaylistSong;
|
import com.kabouzeid.gramophone.model.PlaylistSong;
|
||||||
import com.kabouzeid.gramophone.model.Song;
|
|
||||||
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
|
||||||
import com.kabouzeid.gramophone.util.MusicUtil;
|
|
||||||
import com.kabouzeid.gramophone.util.NavigationUtil;
|
|
||||||
import com.nostra13.universalimageloader.core.DisplayImageOptions;
|
|
||||||
import com.nostra13.universalimageloader.core.ImageLoader;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karim Abou Zeid (kabouzeid)
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
*/
|
*/
|
||||||
public class PlaylistSongAdapter extends AbsMultiSelectAdapter<PlaylistSongAdapter.ViewHolder, PlaylistSong> {
|
public class PlaylistSongAdapter extends AbsPlaylistSongAdapter<PlaylistSong> {
|
||||||
|
|
||||||
public static final String TAG = AlbumSongAdapter.class.getSimpleName();
|
|
||||||
protected final AppCompatActivity activity;
|
|
||||||
protected ArrayList<PlaylistSong> dataSet;
|
|
||||||
|
|
||||||
public PlaylistSongAdapter(AppCompatActivity activity, ArrayList<PlaylistSong> objects, @Nullable CabHolder cabHolder) {
|
public PlaylistSongAdapter(AppCompatActivity activity, ArrayList<PlaylistSong> objects, @Nullable CabHolder cabHolder) {
|
||||||
super(activity, cabHolder, R.menu.menu_playlists_songs_selection);
|
super(activity, objects, cabHolder);
|
||||||
this.activity = activity;
|
|
||||||
dataSet = objects;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void updateDataSet(ArrayList<PlaylistSong> objects) {
|
|
||||||
dataSet = objects;
|
|
||||||
notifyDataSetChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
protected void onDeleteFromPlaylist(ArrayList<PlaylistSong> songs) {
|
||||||
View view = LayoutInflater.from(activity).inflate(R.layout.item_list_song, parent, false);
|
super.onDeleteFromPlaylist(songs);
|
||||||
return new ViewHolder(view);
|
RemoveFromPlaylistDialog.create(songs).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(final ViewHolder holder, int position) {
|
protected void onDeleteFromPlaylist(PlaylistSong song) {
|
||||||
final PlaylistSong song = dataSet.get(position);
|
super.onDeleteFromPlaylist(song);
|
||||||
|
RemoveFromPlaylistDialog.create(song).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
|
||||||
holder.view.setActivated(isChecked(song));
|
|
||||||
holder.songTitle.setText(song.title);
|
|
||||||
holder.songInfo.setText(song.artistName);
|
|
||||||
ImageLoader.getInstance().displayImage(
|
|
||||||
MusicUtil.getAlbumArtUri(song.albumId).toString(),
|
|
||||||
holder.albumArt,
|
|
||||||
new DisplayImageOptions.Builder()
|
|
||||||
.cacheInMemory(true)
|
|
||||||
.showImageOnFail(R.drawable.default_album_art)
|
|
||||||
.resetViewBeforeLoading(true)
|
|
||||||
.build()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getItemCount() {
|
|
||||||
return dataSet.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected PlaylistSong getIdentifier(int position) {
|
|
||||||
return dataSet.get(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onMultipleItemAction(MenuItem menuItem, ArrayList<PlaylistSong> selection) {
|
|
||||||
switch (menuItem.getItemId()) {
|
|
||||||
case R.id.action_delete_from_playlist:
|
|
||||||
RemoveFromPlaylistDialog.create(selection).show(activity.getSupportFragmentManager(), "DELETE_FROM_PLAYLIST");
|
|
||||||
break;
|
|
||||||
case R.id.action_add_to_playlist:
|
|
||||||
//noinspection unchecked
|
|
||||||
AddToPlaylistDialog.create((ArrayList<Song>) (List) selection).show(activity.getSupportFragmentManager(), "ADD_PLAYLIST");
|
|
||||||
break;
|
|
||||||
case R.id.action_add_to_current_playing:
|
|
||||||
//noinspection unchecked
|
|
||||||
MusicPlayerRemote.enqueue((ArrayList<Song>) (List) selection);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
|
||||||
final TextView songTitle;
|
|
||||||
final TextView songInfo;
|
|
||||||
final ImageView overflowButton;
|
|
||||||
final ImageView albumArt;
|
|
||||||
final View view;
|
|
||||||
|
|
||||||
public ViewHolder(View itemView) {
|
|
||||||
super(itemView);
|
|
||||||
view = itemView;
|
|
||||||
songTitle = (TextView) itemView.findViewById(R.id.song_title);
|
|
||||||
songInfo = (TextView) itemView.findViewById(R.id.song_info);
|
|
||||||
albumArt = (ImageView) itemView.findViewById(R.id.album_art);
|
|
||||||
view.setOnClickListener(this);
|
|
||||||
view.setOnLongClickListener(this);
|
|
||||||
overflowButton = (ImageView) itemView.findViewById(R.id.menu);
|
|
||||||
overflowButton.setOnClickListener(new View.OnClickListener() {
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
PopupMenu popupMenu = new PopupMenu(activity, v);
|
|
||||||
popupMenu.inflate(R.menu.menu_item_playlist_song);
|
|
||||||
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
|
||||||
@Override
|
|
||||||
public boolean onMenuItemClick(MenuItem item) {
|
|
||||||
switch (item.getItemId()) {
|
|
||||||
case R.id.action_delete_from_playlist:
|
|
||||||
RemoveFromPlaylistDialog.create(dataSet.get(getAdapterPosition())).show(activity.getSupportFragmentManager(), "DELETE_FROM_PLAYLIST");
|
|
||||||
return true;
|
|
||||||
case R.id.action_go_to_album:
|
|
||||||
Pair[] albumPairs = new Pair[]{
|
|
||||||
Pair.create(albumArt, activity.getResources().getString(R.string.transition_album_cover))
|
|
||||||
};
|
|
||||||
if (activity instanceof AbsFabActivity)
|
|
||||||
albumPairs = ((AbsFabActivity) activity).getSharedViewsWithFab(albumPairs);
|
|
||||||
NavigationUtil.goToAlbum(activity, dataSet.get(getAdapterPosition()).albumId, albumPairs);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return MenuItemClickHelper.handleSongMenuClick(activity, dataSet.get(getAdapterPosition()), item);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
popupMenu.show();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClick(View v) {
|
|
||||||
if (isInQuickSelectMode()) {
|
|
||||||
toggleChecked(getAdapterPosition());
|
|
||||||
} else {
|
|
||||||
//noinspection unchecked
|
|
||||||
MusicPlayerRemote.openQueue((ArrayList<Song>) (List) dataSet, getAdapterPosition(), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean onLongClick(View view) {
|
|
||||||
toggleChecked(getAdapterPosition());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.kabouzeid.gramophone.adapter.songadapter;
|
||||||
|
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.PopupMenu;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.kabouzeid.gramophone.R;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
|
*/
|
||||||
|
public class PlaylistSongViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener {
|
||||||
|
final TextView songTitle;
|
||||||
|
final TextView songInfo;
|
||||||
|
final ImageView overflowButton;
|
||||||
|
final ImageView albumArt;
|
||||||
|
final View view;
|
||||||
|
|
||||||
|
final AbsPlaylistSongAdapter adapter;
|
||||||
|
|
||||||
|
public PlaylistSongViewHolder(final AbsPlaylistSongAdapter adapter, View itemView, final int songMenu) {
|
||||||
|
super(itemView);
|
||||||
|
this.adapter = adapter;
|
||||||
|
view = itemView;
|
||||||
|
songTitle = (TextView) itemView.findViewById(R.id.song_title);
|
||||||
|
songInfo = (TextView) itemView.findViewById(R.id.song_info);
|
||||||
|
albumArt = (ImageView) itemView.findViewById(R.id.album_art);
|
||||||
|
view.setOnClickListener(this);
|
||||||
|
view.setOnLongClickListener(this);
|
||||||
|
overflowButton = (ImageView) itemView.findViewById(R.id.menu);
|
||||||
|
overflowButton.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
PopupMenu popupMenu = new PopupMenu(adapter.activity, v);
|
||||||
|
popupMenu.inflate(songMenu);
|
||||||
|
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onMenuItemClick(MenuItem item) {
|
||||||
|
return adapter.onMenuItemClick(item, PlaylistSongViewHolder.this, getAdapterPosition());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
popupMenu.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
adapter.onClick(v, getAdapterPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onLongClick(View v) {
|
||||||
|
return adapter.onLongClick(v, getAdapterPosition());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected interface onViewHolderMenuItemClickListener {
|
||||||
|
boolean onMenuItemClick(MenuItem item, PlaylistSongViewHolder viewHolder, int adapterPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected interface onViewHolderClickListener {
|
||||||
|
void onClick(View v, int adapterPosition);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected interface onViewHolderLongClickListener {
|
||||||
|
boolean onLongClick(View v, int adapterPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.kabouzeid.gramophone.adapter.songadapter.smartplaylist;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.interfaces.CabHolder;
|
||||||
|
import com.kabouzeid.gramophone.model.LastAddedPlaylist;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
|
*/
|
||||||
|
public class LastAddedSongAdapter extends SmartPlaylistSongAdapter {
|
||||||
|
|
||||||
|
public LastAddedSongAdapter(AppCompatActivity activity, @Nullable CabHolder cabHolder) {
|
||||||
|
super(activity, new LastAddedPlaylist(activity), cabHolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getMultiSelectMenuRes() {
|
||||||
|
return R.menu.menu_last_added_playlist_songs_selection;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected int getSongMenuRes() {
|
||||||
|
return R.menu.menu_item_last_added_playlist_song;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package com.kabouzeid.gramophone.adapter.songadapter.smartplaylist;
|
||||||
|
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
|
||||||
|
import com.kabouzeid.gramophone.adapter.songadapter.AbsPlaylistSongAdapter;
|
||||||
|
import com.kabouzeid.gramophone.interfaces.CabHolder;
|
||||||
|
import com.kabouzeid.gramophone.model.SmartPlaylist;
|
||||||
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
|
*/
|
||||||
|
public abstract class SmartPlaylistSongAdapter extends AbsPlaylistSongAdapter<Song> {
|
||||||
|
private SmartPlaylist playlist;
|
||||||
|
|
||||||
|
public SmartPlaylistSongAdapter(AppCompatActivity activity, SmartPlaylist playlist, @Nullable CabHolder cabHolder) {
|
||||||
|
super(activity, playlist.getSongs(activity), cabHolder);
|
||||||
|
this.playlist = playlist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateDataSet() {
|
||||||
|
updateDataSet(playlist.getSongs(activity));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
package com.kabouzeid.gramophone.helper;
|
package com.kabouzeid.gramophone.helper;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.support.v4.util.Pair;
|
import android.support.v4.util.Pair;
|
||||||
import android.support.v7.app.AppCompatActivity;
|
import android.support.v7.app.AppCompatActivity;
|
||||||
|
|
@ -12,9 +13,11 @@ import com.kabouzeid.gramophone.dialogs.DeleteSongsDialog;
|
||||||
import com.kabouzeid.gramophone.dialogs.RenamePlaylistDialog;
|
import com.kabouzeid.gramophone.dialogs.RenamePlaylistDialog;
|
||||||
import com.kabouzeid.gramophone.dialogs.SongDetailDialog;
|
import com.kabouzeid.gramophone.dialogs.SongDetailDialog;
|
||||||
import com.kabouzeid.gramophone.interfaces.PaletteColorHolder;
|
import com.kabouzeid.gramophone.interfaces.PaletteColorHolder;
|
||||||
|
import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
|
||||||
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
import com.kabouzeid.gramophone.loader.SongFilePathLoader;
|
||||||
import com.kabouzeid.gramophone.misc.AppKeys;
|
import com.kabouzeid.gramophone.misc.AppKeys;
|
||||||
import com.kabouzeid.gramophone.model.Playlist;
|
import com.kabouzeid.gramophone.model.Playlist;
|
||||||
|
import com.kabouzeid.gramophone.model.SmartPlaylist;
|
||||||
import com.kabouzeid.gramophone.model.Song;
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
||||||
import com.kabouzeid.gramophone.ui.activities.tageditor.SongTagEditorActivity;
|
import com.kabouzeid.gramophone.ui.activities.tageditor.SongTagEditorActivity;
|
||||||
|
|
@ -22,6 +25,7 @@ import com.kabouzeid.gramophone.util.MusicUtil;
|
||||||
import com.kabouzeid.gramophone.util.NavigationUtil;
|
import com.kabouzeid.gramophone.util.NavigationUtil;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karim Abou Zeid (kabouzeid), Aidan Follestad (afollestad)
|
* @author Karim Abou Zeid (kabouzeid), Aidan Follestad (afollestad)
|
||||||
|
|
@ -78,6 +82,12 @@ public class MenuItemClickHelper {
|
||||||
|
|
||||||
public static boolean handlePlaylistMenuClick(AppCompatActivity activity, Playlist playlist, MenuItem item) {
|
public static boolean handlePlaylistMenuClick(AppCompatActivity activity, Playlist playlist, MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
switch (item.getItemId()) {
|
||||||
|
case R.id.action_play:
|
||||||
|
MusicPlayerRemote.openQueue(new ArrayList<>(getPlaylistSongs(activity, playlist)), 0, true);
|
||||||
|
return true;
|
||||||
|
case R.id.action_add_to_current_playing:
|
||||||
|
MusicPlayerRemote.enqueue(new ArrayList<>(getPlaylistSongs(activity, playlist)));
|
||||||
|
return true;
|
||||||
case R.id.action_rename_playlist:
|
case R.id.action_rename_playlist:
|
||||||
RenamePlaylistDialog.create(playlist.id).show(activity.getSupportFragmentManager(), "RENAME_PLAYLIST");
|
RenamePlaylistDialog.create(playlist.id).show(activity.getSupportFragmentManager(), "RENAME_PLAYLIST");
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -87,4 +97,10 @@ public class MenuItemClickHelper {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ArrayList<? extends Song> getPlaylistSongs(Activity activity, Playlist playlist) {
|
||||||
|
return playlist instanceof SmartPlaylist ?
|
||||||
|
((SmartPlaylist) playlist).getSongs(activity) :
|
||||||
|
PlaylistSongLoader.getPlaylistSongList(activity, playlist.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ import com.kabouzeid.gramophone.model.Song;
|
||||||
import com.kabouzeid.gramophone.service.MusicService;
|
import com.kabouzeid.gramophone.service.MusicService;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -207,7 +206,7 @@ public class MusicPlayerRemote {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean enqueue(List<Song> songs) {
|
public static boolean enqueue(ArrayList<Song> songs) {
|
||||||
if (musicService != null) {
|
if (musicService != null) {
|
||||||
musicService.addSongs(songs);
|
musicService.addSongs(songs);
|
||||||
final String toast = songs.size() == 1 ? musicService.getResources().getString(R.string.added_title_to_playing_queue) : musicService.getResources().getString(R.string.added_x_titles_to_playing_queue, songs.size());
|
final String toast = songs.size() == 1 ? musicService.getResources().getString(R.string.added_title_to_playing_queue) : musicService.getResources().getString(R.string.added_x_titles_to_playing_queue, songs.size());
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.kabouzeid.gramophone.loader;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.database.Cursor;
|
||||||
|
import android.provider.BaseColumns;
|
||||||
|
import android.provider.MediaStore;
|
||||||
|
import android.provider.MediaStore.Audio.AudioColumns;
|
||||||
|
|
||||||
|
import com.kabouzeid.gramophone.model.Song;
|
||||||
|
import com.kabouzeid.gramophone.util.PreferenceUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class LastAddedLoader {
|
||||||
|
|
||||||
|
public static ArrayList<Song> getLastAddedSongs(Context context) {
|
||||||
|
return SongLoader.getSongs(makeLastAddedCursor(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Cursor makeLastAddedCursor(final Context context) {
|
||||||
|
long fourWeeksAgo = (System.currentTimeMillis() / 1000) - (4 * 3600 * 24 * 7);
|
||||||
|
// possible saved timestamp caused by user "clearing" the last added playlist
|
||||||
|
long cutoff = PreferenceUtils.getInstance(context).getLastAddedCutOff() / 1000;
|
||||||
|
if (cutoff < fourWeeksAgo) {
|
||||||
|
cutoff = fourWeeksAgo;
|
||||||
|
}
|
||||||
|
|
||||||
|
//noinspection StringBufferReplaceableByString
|
||||||
|
final StringBuilder selection = new StringBuilder();
|
||||||
|
selection.append(AudioColumns.IS_MUSIC + "=1");
|
||||||
|
selection.append(" AND " + AudioColumns.TITLE + " != ''");
|
||||||
|
selection.append(" AND " + MediaStore.Audio.Media.DATE_ADDED + ">");
|
||||||
|
selection.append(cutoff);
|
||||||
|
|
||||||
|
return context.getContentResolver().query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
||||||
|
new String[]{
|
||||||
|
/* 0 */
|
||||||
|
BaseColumns._ID,
|
||||||
|
/* 1 */
|
||||||
|
MediaStore.Audio.AudioColumns.TITLE,
|
||||||
|
/* 2 */
|
||||||
|
MediaStore.Audio.AudioColumns.ARTIST,
|
||||||
|
/* 3 */
|
||||||
|
MediaStore.Audio.AudioColumns.ALBUM,
|
||||||
|
/* 4 */
|
||||||
|
MediaStore.Audio.AudioColumns.DURATION,
|
||||||
|
/* 5 */
|
||||||
|
MediaStore.Audio.AudioColumns.TRACK,
|
||||||
|
/* 6 */
|
||||||
|
MediaStore.Audio.AudioColumns.ARTIST_ID,
|
||||||
|
/* 7 */
|
||||||
|
MediaStore.Audio.AudioColumns.ALBUM_ID
|
||||||
|
}, selection.toString(), null, MediaStore.Audio.Media.DATE_ADDED + " DESC");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.kabouzeid.gramophone.model;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.loader.LastAddedLoader;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
|
*/
|
||||||
|
public class LastAddedPlaylist extends SmartPlaylist {
|
||||||
|
|
||||||
|
public LastAddedPlaylist(Context context) {
|
||||||
|
super(context.getString(R.string.last_added), R.drawable.ic_queue_white_24dp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ArrayList<Song> getSongs(Context context) {
|
||||||
|
return LastAddedLoader.getLastAddedSongs(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
package com.kabouzeid.gramophone.model;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.support.annotation.DrawableRes;
|
||||||
|
|
||||||
|
import com.kabouzeid.gramophone.R;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
|
*/
|
||||||
|
public abstract class SmartPlaylist extends Playlist {
|
||||||
|
private static final long serialVersionUID = 3013701295356403681L;
|
||||||
|
|
||||||
|
@DrawableRes
|
||||||
|
public final int iconRes;
|
||||||
|
|
||||||
|
public SmartPlaylist(final String name, final int iconRes) {
|
||||||
|
super(-1, name);
|
||||||
|
this.iconRes = iconRes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SmartPlaylist() {
|
||||||
|
super();
|
||||||
|
this.iconRes = R.drawable.ic_queue_music_white_24dp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract ArrayList<Song> getSongs(Context context);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
final int prime = 31;
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = prime * result + iconRes;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(final Object obj) {
|
||||||
|
if (super.equals(obj)) {
|
||||||
|
if (getClass() != obj.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final SmartPlaylist other = (SmartPlaylist) obj;
|
||||||
|
return iconRes == other.iconRes;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -59,7 +59,6 @@ import com.nostra13.universalimageloader.core.ImageLoader;
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
|
|
@ -419,8 +418,9 @@ public class MainActivity extends AbsFabActivity
|
||||||
final int id = (int) parseIdFromIntent(intent, "playlistId", "playlist");
|
final int id = (int) parseIdFromIntent(intent, "playlistId", "playlist");
|
||||||
if (id >= 0) {
|
if (id >= 0) {
|
||||||
int position = intent.getIntExtra("position", 0);
|
int position = intent.getIntExtra("position", 0);
|
||||||
//noinspection unchecked
|
ArrayList<Song> songs = new ArrayList<>();
|
||||||
MusicPlayerRemote.openQueue((ArrayList<Song>) (List<? extends Song>) PlaylistSongLoader.getPlaylistSongList(this, id), position, true);
|
songs.addAll(PlaylistSongLoader.getPlaylistSongList(this, id));
|
||||||
|
MusicPlayerRemote.openQueue(songs, position, true);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
} else if (MediaStore.Audio.Albums.CONTENT_TYPE.equals(mimeType)) {
|
} else if (MediaStore.Audio.Albums.CONTENT_TYPE.equals(mimeType)) {
|
||||||
|
|
|
||||||
|
|
@ -13,9 +13,7 @@ import com.kabouzeid.gramophone.App;
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.adapter.songadapter.PlaylistSongAdapter;
|
import com.kabouzeid.gramophone.adapter.songadapter.PlaylistSongAdapter;
|
||||||
import com.kabouzeid.gramophone.interfaces.CabHolder;
|
import com.kabouzeid.gramophone.interfaces.CabHolder;
|
||||||
import com.kabouzeid.gramophone.loader.PlaylistLoader;
|
|
||||||
import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
|
import com.kabouzeid.gramophone.loader.PlaylistSongLoader;
|
||||||
import com.kabouzeid.gramophone.misc.AppKeys;
|
|
||||||
import com.kabouzeid.gramophone.misc.DragSortRecycler;
|
import com.kabouzeid.gramophone.misc.DragSortRecycler;
|
||||||
import com.kabouzeid.gramophone.model.DataBaseChangedEvent;
|
import com.kabouzeid.gramophone.model.DataBaseChangedEvent;
|
||||||
import com.kabouzeid.gramophone.model.Playlist;
|
import com.kabouzeid.gramophone.model.Playlist;
|
||||||
|
|
@ -32,6 +30,8 @@ public class PlaylistDetailActivity extends AbsFabActivity implements CabHolder
|
||||||
|
|
||||||
public static final String TAG = PlaylistDetailActivity.class.getSimpleName();
|
public static final String TAG = PlaylistDetailActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
public static String EXTRA_PLAYLIST = "extra_playlist";
|
||||||
|
|
||||||
private Playlist playlist;
|
private Playlist playlist;
|
||||||
private MaterialCab cab;
|
private MaterialCab cab;
|
||||||
private PlaylistSongAdapter adapter;
|
private PlaylistSongAdapter adapter;
|
||||||
|
|
@ -86,8 +86,10 @@ public class PlaylistDetailActivity extends AbsFabActivity implements CabHolder
|
||||||
|
|
||||||
private void getIntentExtras() {
|
private void getIntentExtras() {
|
||||||
Bundle intentExtras = getIntent().getExtras();
|
Bundle intentExtras = getIntent().getExtras();
|
||||||
final int playlistId = intentExtras.getInt(AppKeys.E_PLAYLIST);
|
try {
|
||||||
playlist = PlaylistLoader.getPlaylist(this, playlistId);
|
playlist = (Playlist) intentExtras.getSerializable(EXTRA_PLAYLIST);
|
||||||
|
} catch (ClassCastException ignored) {
|
||||||
|
}
|
||||||
if (playlist == null) {
|
if (playlist == null) {
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
|
@ -120,6 +122,9 @@ public class PlaylistDetailActivity extends AbsFabActivity implements CabHolder
|
||||||
case R.id.action_playing_queue:
|
case R.id.action_playing_queue:
|
||||||
NavigationUtil.openPlayingQueueDialog(this);
|
NavigationUtil.openPlayingQueueDialog(this);
|
||||||
return true;
|
return true;
|
||||||
|
case R.id.action_clear_playlist:
|
||||||
|
//TODO
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,162 @@
|
||||||
|
package com.kabouzeid.gramophone.ui.activities;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.support.v7.widget.GridLayoutManager;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.support.v7.widget.Toolbar;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.afollestad.materialcab.MaterialCab;
|
||||||
|
import com.kabouzeid.gramophone.App;
|
||||||
|
import com.kabouzeid.gramophone.R;
|
||||||
|
import com.kabouzeid.gramophone.adapter.songadapter.smartplaylist.LastAddedSongAdapter;
|
||||||
|
import com.kabouzeid.gramophone.adapter.songadapter.smartplaylist.SmartPlaylistSongAdapter;
|
||||||
|
import com.kabouzeid.gramophone.interfaces.CabHolder;
|
||||||
|
import com.kabouzeid.gramophone.model.DataBaseChangedEvent;
|
||||||
|
import com.kabouzeid.gramophone.model.SmartPlaylist;
|
||||||
|
import com.kabouzeid.gramophone.ui.activities.base.AbsFabActivity;
|
||||||
|
import com.kabouzeid.gramophone.util.NavigationUtil;
|
||||||
|
import com.kabouzeid.gramophone.util.PreferenceUtils;
|
||||||
|
import com.squareup.otto.Subscribe;
|
||||||
|
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import butterknife.InjectView;
|
||||||
|
|
||||||
|
public class SmartPlaylistDetailActivity extends AbsFabActivity implements CabHolder {
|
||||||
|
|
||||||
|
public static final String TAG = SmartPlaylistDetailActivity.class.getSimpleName();
|
||||||
|
|
||||||
|
@InjectView(R.id.recycler_view)
|
||||||
|
RecyclerView recyclerView;
|
||||||
|
@InjectView(R.id.toolbar)
|
||||||
|
Toolbar toolbar;
|
||||||
|
@InjectView(android.R.id.empty)
|
||||||
|
TextView empty;
|
||||||
|
|
||||||
|
private SmartPlaylist playlist;
|
||||||
|
private MaterialCab cab;
|
||||||
|
private SmartPlaylistSongAdapter adapter;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_playlist_detail);
|
||||||
|
ButterKnife.inject(this);
|
||||||
|
|
||||||
|
getIntentExtras();
|
||||||
|
|
||||||
|
setUpRecyclerView();
|
||||||
|
|
||||||
|
checkIsEmpty();
|
||||||
|
|
||||||
|
setUpToolBar();
|
||||||
|
|
||||||
|
if (PreferenceUtils.getInstance(this).coloredNavigationBarPlaylist())
|
||||||
|
setNavigationBarThemeColor();
|
||||||
|
setStatusBarThemeColor();
|
||||||
|
|
||||||
|
App.bus.register(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpRecyclerView() {
|
||||||
|
adapter = new LastAddedSongAdapter(this, this);
|
||||||
|
|
||||||
|
recyclerView.setLayoutManager(new GridLayoutManager(this, 1));
|
||||||
|
recyclerView.setAdapter(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpToolBar() {
|
||||||
|
toolbar.setBackgroundColor(getThemeColorPrimary());
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
//noinspection ConstantConditions
|
||||||
|
getSupportActionBar().setTitle(playlist.name);
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getIntentExtras() {
|
||||||
|
Bundle intentExtras = getIntent().getExtras();
|
||||||
|
try {
|
||||||
|
playlist = (SmartPlaylist) intentExtras.getSerializable(PlaylistDetailActivity.EXTRA_PLAYLIST);
|
||||||
|
} catch (ClassCastException ignored) {
|
||||||
|
}
|
||||||
|
if (playlist == null) {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTag() {
|
||||||
|
return TAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
getMenuInflater().inflate(R.menu.menu_playlist_detail, menu);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
int id = item.getItemId();
|
||||||
|
switch (id) {
|
||||||
|
case R.id.action_equalizer:
|
||||||
|
NavigationUtil.openEqualizer(this);
|
||||||
|
return true;
|
||||||
|
case android.R.id.home:
|
||||||
|
super.onBackPressed();
|
||||||
|
return true;
|
||||||
|
case R.id.action_current_playing:
|
||||||
|
NavigationUtil.openCurrentPlayingIfPossible(this, getSharedViewsWithFab(null));
|
||||||
|
return true;
|
||||||
|
case R.id.action_playing_queue:
|
||||||
|
NavigationUtil.openPlayingQueueDialog(this);
|
||||||
|
return true;
|
||||||
|
case R.id.action_clear_playlist:
|
||||||
|
//TODO
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public MaterialCab openCab(final int menu, final MaterialCab.Callback callback) {
|
||||||
|
if (cab != null && cab.isActive()) cab.finish();
|
||||||
|
cab = new MaterialCab(this, R.id.cab_stub)
|
||||||
|
.setMenu(menu)
|
||||||
|
.setBackgroundColor(PreferenceUtils.getInstance(this).getThemeColorPrimary())
|
||||||
|
.start(callback);
|
||||||
|
return cab;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
App.bus.unregister(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Subscribe
|
||||||
|
public void onDataBaseEvent(DataBaseChangedEvent event) {
|
||||||
|
switch (event.getAction()) {
|
||||||
|
case DataBaseChangedEvent.PLAYLISTS_CHANGED:
|
||||||
|
case DataBaseChangedEvent.DATABASE_CHANGED:
|
||||||
|
adapter.updateDataSet();
|
||||||
|
checkIsEmpty();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBackPressed() {
|
||||||
|
if (cab != null && cab.isActive()) cab.finish();
|
||||||
|
else super.onBackPressed();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkIsEmpty() {
|
||||||
|
empty.setVisibility(
|
||||||
|
adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package com.kabouzeid.gramophone.ui.fragments.mainactivityfragments;
|
package com.kabouzeid.gramophone.ui.fragments.mainactivityfragments;
|
||||||
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.annotation.LayoutRes;
|
||||||
import android.support.annotation.StringRes;
|
import android.support.annotation.StringRes;
|
||||||
import android.support.design.widget.AppBarLayout;
|
import android.support.design.widget.AppBarLayout;
|
||||||
import android.support.design.widget.AppBarLayout.OnOffsetChangedListener;
|
import android.support.design.widget.AppBarLayout.OnOffsetChangedListener;
|
||||||
|
|
@ -15,38 +16,49 @@ import android.widget.TextView;
|
||||||
import com.kabouzeid.gramophone.R;
|
import com.kabouzeid.gramophone.R;
|
||||||
import com.kabouzeid.gramophone.views.FastScroller;
|
import com.kabouzeid.gramophone.views.FastScroller;
|
||||||
|
|
||||||
|
import butterknife.ButterKnife;
|
||||||
|
import butterknife.InjectView;
|
||||||
|
import butterknife.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karim Abou Zeid (kabouzeid)
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
*/
|
*/
|
||||||
public abstract class AbsMainActivityRecyclerViewFragment extends AbsMainActivityFragment implements OnOffsetChangedListener {
|
public abstract class AbsMainActivityRecyclerViewFragment extends AbsMainActivityFragment implements OnOffsetChangedListener {
|
||||||
|
|
||||||
public static final String TAG = AbsMainActivityRecyclerViewFragment.class.getSimpleName();
|
public static final String TAG = AbsMainActivityRecyclerViewFragment.class.getSimpleName();
|
||||||
private RecyclerView recyclerView;
|
|
||||||
|
@InjectView(R.id.recycler_view)
|
||||||
|
RecyclerView recyclerView;
|
||||||
|
@Optional
|
||||||
|
@InjectView(android.R.id.empty)
|
||||||
|
TextView empty;
|
||||||
|
@Optional
|
||||||
|
@InjectView(R.id.fast_scroller)
|
||||||
|
FastScroller fastScroller;
|
||||||
|
|
||||||
private RecyclerView.Adapter mAdapter;
|
private RecyclerView.Adapter mAdapter;
|
||||||
private FastScroller fastScroller;
|
|
||||||
private TextView empty;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
return inflater.inflate(R.layout.fragment_main_activity_recycler_view, container, false);
|
View view = inflater.inflate(getLayoutRes(), container, false);
|
||||||
|
ButterKnife.inject(this, view);
|
||||||
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onViewCreated(View view, Bundle savedInstanceState) {
|
public void onViewCreated(View view, Bundle savedInstanceState) {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view);
|
if (fastScroller != null) {
|
||||||
fastScroller = (FastScroller) view.findViewById(R.id.fast_scroller);
|
fastScroller.setRecyclerView(recyclerView);
|
||||||
empty = (TextView) view.findViewById(android.R.id.empty);
|
fastScroller.setPressedHandleColor(getMainActivity().getThemeColorPrimary());
|
||||||
|
fastScroller.setOnHandleTouchListener(new View.OnTouchListener() {
|
||||||
fastScroller.setRecyclerView(recyclerView);
|
@Override
|
||||||
fastScroller.setPressedHandleColor(getMainActivity().getThemeColorPrimary());
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
fastScroller.setOnHandleTouchListener(new View.OnTouchListener() {
|
return false;
|
||||||
@Override
|
}
|
||||||
public boolean onTouch(View v, MotionEvent event) {
|
});
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
getMainActivity().addOnAppBarOffsetChangedListener(this);
|
getMainActivity().addOnAppBarOffsetChangedListener(this);
|
||||||
|
|
||||||
|
|
@ -75,9 +87,11 @@ public abstract class AbsMainActivityRecyclerViewFragment extends AbsMainActivit
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
|
public void onOffsetChanged(AppBarLayout appBarLayout, int i) {
|
||||||
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) fastScroller.getLayoutParams();
|
if (fastScroller != null) {
|
||||||
params.setMargins(params.leftMargin, params.topMargin, params.rightMargin, getMainActivity().getTotalAppBarScrollingRange() + i);
|
FrameLayout.LayoutParams params = (FrameLayout.LayoutParams) fastScroller.getLayoutParams();
|
||||||
fastScroller.setLayoutParams(params);
|
params.setMargins(params.leftMargin, params.topMargin, params.rightMargin, getMainActivity().getTotalAppBarScrollingRange() + i);
|
||||||
|
fastScroller.setLayoutParams(params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -93,10 +107,12 @@ public abstract class AbsMainActivityRecyclerViewFragment extends AbsMainActivit
|
||||||
}
|
}
|
||||||
|
|
||||||
private void showEmptyMessageIfEmpty() {
|
private void showEmptyMessageIfEmpty() {
|
||||||
RecyclerView.Adapter adapter = getAdapter();
|
if (empty != null) {
|
||||||
if (adapter != null) {
|
RecyclerView.Adapter adapter = getAdapter();
|
||||||
empty.setText(getEmptyMessage());
|
if (adapter != null) {
|
||||||
empty.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
|
empty.setText(getEmptyMessage());
|
||||||
|
empty.setVisibility(adapter.getItemCount() == 0 ? View.VISIBLE : View.GONE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -105,7 +121,22 @@ public abstract class AbsMainActivityRecyclerViewFragment extends AbsMainActivit
|
||||||
return R.string.empty;
|
return R.string.empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@LayoutRes
|
||||||
|
protected int getLayoutRes() {
|
||||||
|
return R.layout.fragment_main_activity_recycler_view;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected RecyclerView getRecyclerView() {
|
||||||
|
return recyclerView;
|
||||||
|
}
|
||||||
|
|
||||||
protected abstract RecyclerView.LayoutManager createLayoutManager();
|
protected abstract RecyclerView.LayoutManager createLayoutManager();
|
||||||
|
|
||||||
protected abstract RecyclerView.Adapter createAdapter();
|
protected abstract RecyclerView.Adapter createAdapter();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyView() {
|
||||||
|
super.onDestroyView();
|
||||||
|
ButterKnife.reset(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,10 +15,13 @@ import com.kabouzeid.gramophone.dialogs.PlayingQueueDialog;
|
||||||
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
|
||||||
import com.kabouzeid.gramophone.interfaces.KabViewsDisableAble;
|
import com.kabouzeid.gramophone.interfaces.KabViewsDisableAble;
|
||||||
import com.kabouzeid.gramophone.misc.AppKeys;
|
import com.kabouzeid.gramophone.misc.AppKeys;
|
||||||
|
import com.kabouzeid.gramophone.model.Playlist;
|
||||||
|
import com.kabouzeid.gramophone.model.SmartPlaylist;
|
||||||
import com.kabouzeid.gramophone.ui.activities.AlbumDetailActivity;
|
import com.kabouzeid.gramophone.ui.activities.AlbumDetailActivity;
|
||||||
import com.kabouzeid.gramophone.ui.activities.ArtistDetailActivity;
|
import com.kabouzeid.gramophone.ui.activities.ArtistDetailActivity;
|
||||||
import com.kabouzeid.gramophone.ui.activities.MusicControllerActivity;
|
import com.kabouzeid.gramophone.ui.activities.MusicControllerActivity;
|
||||||
import com.kabouzeid.gramophone.ui.activities.PlaylistDetailActivity;
|
import com.kabouzeid.gramophone.ui.activities.PlaylistDetailActivity;
|
||||||
|
import com.kabouzeid.gramophone.ui.activities.SmartPlaylistDetailActivity;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Karim Abou Zeid (kabouzeid)
|
* @author Karim Abou Zeid (kabouzeid)
|
||||||
|
|
@ -63,12 +66,19 @@ public class NavigationUtil {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void goToPlaylist(final Activity activity, final int playlistId, final Pair[] sharedViews) {
|
public static void goToPlaylist(final Activity activity, final Playlist playlist, final Pair[] sharedViews) {
|
||||||
if ((activity instanceof KabViewsDisableAble && ((KabViewsDisableAble) activity).areViewsEnabled()) || !(activity instanceof KabViewsDisableAble)) {
|
if ((activity instanceof KabViewsDisableAble && ((KabViewsDisableAble) activity).areViewsEnabled()) || !(activity instanceof KabViewsDisableAble)) {
|
||||||
if (activity instanceof KabViewsDisableAble)
|
if (activity instanceof KabViewsDisableAble)
|
||||||
((KabViewsDisableAble) activity).disableViews();
|
((KabViewsDisableAble) activity).disableViews();
|
||||||
final Intent intent = new Intent(activity, PlaylistDetailActivity.class);
|
|
||||||
intent.putExtra(AppKeys.E_PLAYLIST, playlistId);
|
final Intent intent;
|
||||||
|
if (playlist instanceof SmartPlaylist) {
|
||||||
|
intent = new Intent(activity, SmartPlaylistDetailActivity.class);
|
||||||
|
} else {
|
||||||
|
intent = new Intent(activity, PlaylistDetailActivity.class);
|
||||||
|
}
|
||||||
|
intent.putExtra(PlaylistDetailActivity.EXTRA_PLAYLIST, playlist);
|
||||||
|
|
||||||
if (sharedViews != null) {
|
if (sharedViews != null) {
|
||||||
@SuppressWarnings("unchecked") ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
|
@SuppressWarnings("unchecked") ActivityOptionsCompat optionsCompat = ActivityOptionsCompat.makeSceneTransitionAnimation(activity,
|
||||||
sharedViews
|
sharedViews
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,6 @@ import java.util.List;
|
||||||
*/
|
*/
|
||||||
public class PlaylistsUtil {
|
public class PlaylistsUtil {
|
||||||
|
|
||||||
// public static final String MUSIC_ONLY_SELECTION = MediaStore.Audio.AudioColumns.IS_MUSIC + "=1"
|
|
||||||
// + " AND " + MediaStore.Audio.AudioColumns.TITLE + " != ''"; //$NON-NLS-2$
|
|
||||||
|
|
||||||
public static int createPlaylist(final Context context, final String name) {
|
public static int createPlaylist(final Context context, final String name) {
|
||||||
if (name != null && name.length() > 0) {
|
if (name != null && name.length() > 0) {
|
||||||
final ContentResolver resolver = context.getContentResolver();
|
final ContentResolver resolver = context.getContentResolver();
|
||||||
|
|
@ -61,13 +58,13 @@ public class PlaylistsUtil {
|
||||||
// context.getContentResolver().delete(uri, null, null);
|
// context.getContentResolver().delete(uri, null, null);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public static void deletePlaylists(final Context context, final long playlistId) {
|
// public static void deletePlaylists(final Context context, final long playlistId) {
|
||||||
final Uri uri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
|
// final Uri uri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
|
||||||
String where = MediaStore.Audio.Playlists._ID + "=?";
|
// String where = MediaStore.Audio.Playlists._ID + "=?";
|
||||||
String[] whereVal = {String.valueOf(playlistId)};
|
// String[] whereVal = {String.valueOf(playlistId)};
|
||||||
context.getContentResolver().delete(uri, where, whereVal);
|
// context.getContentResolver().delete(uri, where, whereVal);
|
||||||
App.bus.post(new DataBaseChangedEvent(DataBaseChangedEvent.PLAYLISTS_CHANGED));
|
// App.bus.post(new DataBaseChangedEvent(DataBaseChangedEvent.PLAYLISTS_CHANGED));
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static void deletePlaylists(final Context context, final ArrayList<Playlist> playlists) {
|
public static void deletePlaylists(final Context context, final ArrayList<Playlist> playlists) {
|
||||||
final Uri uri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
|
final Uri uri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
|
||||||
|
|
@ -136,19 +133,20 @@ public class PlaylistsUtil {
|
||||||
return contentValues;
|
return contentValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void removeFromPlaylist(final Context context, final PlaylistSong song) {
|
// public static void removeFromPlaylist(final Context context, final PlaylistSong song) {
|
||||||
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri(
|
// Uri uri = MediaStore.Audio.Playlists.Members.getContentUri(
|
||||||
"external", song.playlistId);
|
// "external", song.playlistId);
|
||||||
String selection = MediaStore.Audio.Playlists.Members._ID + " =?";
|
// String selection = MediaStore.Audio.Playlists.Members._ID + " =?";
|
||||||
String[] selectionArgs = new String[]{String.valueOf(song.idInPlayList)};
|
// String[] selectionArgs = new String[]{String.valueOf(song.idInPlayList)};
|
||||||
|
//
|
||||||
context.getContentResolver().delete(uri, selection, selectionArgs);
|
// context.getContentResolver().delete(uri, selection, selectionArgs);
|
||||||
App.bus.post(new DataBaseChangedEvent(DataBaseChangedEvent.PLAYLISTS_CHANGED));
|
// App.bus.post(new DataBaseChangedEvent(DataBaseChangedEvent.PLAYLISTS_CHANGED));
|
||||||
}
|
// }
|
||||||
|
|
||||||
public static void removeFromPlaylist(final Context context, final List<PlaylistSong> songs) {
|
public static void removeFromPlaylist(final Context context, final List<PlaylistSong> songs) {
|
||||||
|
final int playlistId = songs.get(0).playlistId;
|
||||||
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri(
|
Uri uri = MediaStore.Audio.Playlists.Members.getContentUri(
|
||||||
"external", songs.get(0).playlistId);
|
"external", playlistId);
|
||||||
String selectionArgs[] = new String[songs.size()];
|
String selectionArgs[] = new String[songs.size()];
|
||||||
for (int i = 0; i < selectionArgs.length; i++) {
|
for (int i = 0; i < selectionArgs.length; i++) {
|
||||||
selectionArgs[i] = String.valueOf(songs.get(i).idInPlayList);
|
selectionArgs[i] = String.valueOf(songs.get(i).idInPlayList);
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ public final class PreferenceUtils {
|
||||||
public static final String FADE_PLAY_PAUSE = "fade_play_pause";
|
public static final String FADE_PLAY_PAUSE = "fade_play_pause";
|
||||||
public static final String COLORED_NOTIFICATION = "colored_notification";
|
public static final String COLORED_NOTIFICATION = "colored_notification";
|
||||||
public static final String GAPLESS_PLAYBACK = "gapless_playback";
|
public static final String GAPLESS_PLAYBACK = "gapless_playback";
|
||||||
|
public static final String LAST_ADDED_CUTOFF_TIMESTAMP = "last_added_cutoff_timestamp";
|
||||||
|
|
||||||
private static PreferenceUtils sInstance;
|
private static PreferenceUtils sInstance;
|
||||||
|
|
||||||
|
|
@ -283,4 +284,15 @@ public final class PreferenceUtils {
|
||||||
public final int getAlbumGridColumnsLand() {
|
public final int getAlbumGridColumnsLand() {
|
||||||
return mPreferences.getInt(ALBUM_GRID_COLUMNS_LAND, 3);
|
return mPreferences.getInt(ALBUM_GRID_COLUMNS_LAND, 3);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public long getLastAddedCutOff() {
|
||||||
|
return mPreferences.getLong(LAST_ADDED_CUTOFF_TIMESTAMP, 0L);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("CommitPrefEdits")
|
||||||
|
public void setLastAddedCutoffTimestamp(final long timestamp) {
|
||||||
|
final SharedPreferences.Editor editor = mPreferences.edit();
|
||||||
|
editor.putLong(LAST_ADDED_CUTOFF_TIMESTAMP, timestamp);
|
||||||
|
editor.commit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
BIN
app/src/main/res/drawable-hdpi/ic_access_time_white_24dp.png
Normal file
|
After Width: | Height: | Size: 655 B |
BIN
app/src/main/res/drawable-hdpi/ic_trending_up_white_24dp.png
Normal file
|
After Width: | Height: | Size: 283 B |
BIN
app/src/main/res/drawable-mdpi/ic_access_time_white_24dp.png
Normal file
|
After Width: | Height: | Size: 424 B |
BIN
app/src/main/res/drawable-mdpi/ic_trending_up_white_24dp.png
Normal file
|
After Width: | Height: | Size: 213 B |
BIN
app/src/main/res/drawable-xhdpi/ic_access_time_white_24dp.png
Normal file
|
After Width: | Height: | Size: 879 B |
BIN
app/src/main/res/drawable-xhdpi/ic_trending_up_white_24dp.png
Normal file
|
After Width: | Height: | Size: 324 B |
BIN
app/src/main/res/drawable-xxhdpi/ic_access_time_white_24dp.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
BIN
app/src/main/res/drawable-xxhdpi/ic_trending_up_white_24dp.png
Normal file
|
After Width: | Height: | Size: 491 B |
BIN
app/src/main/res/drawable-xxxhdpi/ic_access_time_white_24dp.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
app/src/main/res/drawable-xxxhdpi/ic_trending_up_white_24dp.png
Normal file
|
After Width: | Height: | Size: 586 B |
|
|
@ -4,7 +4,6 @@
|
||||||
android:layout_height="match_parent">
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
<android.support.v7.widget.RecyclerView
|
<android.support.v7.widget.RecyclerView
|
||||||
android:paddingTop="@dimen/list_padding_vertical"
|
|
||||||
android:paddingBottom="@dimen/bottom_offset_fab_activity"
|
android:paddingBottom="@dimen/bottom_offset_fab_activity"
|
||||||
android:id="@+id/recycler_view"
|
android:id="@+id/recycler_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
||||||
36
app/src/main/res/layout/fragment_playlist_view.xml
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/smart_playlist_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical" />
|
||||||
|
|
||||||
|
<android.support.v7.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:paddingBottom="@dimen/bottom_offset_fab_activity"
|
||||||
|
android:scrollbars="none" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@android:id/empty"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:fontFamily="sans-serif-light"
|
||||||
|
android:text="@string/empty"
|
||||||
|
android:textColor="?android:textColorSecondary"
|
||||||
|
android:textSize="@dimen/empty_text_size" />
|
||||||
|
|
||||||
|
<com.kabouzeid.gramophone.views.FastScroller
|
||||||
|
android:id="@+id/fast_scroller"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="end" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
@ -1,18 +1,21 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="72dp"
|
android:layout_height="72dp"
|
||||||
android:background="?rect_selector">
|
android:background="?card_color"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:foreground="?rect_selector"
|
||||||
|
tools:ignore="UnusedAttribute">
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:descendantFocusability="blocksDescendants"
|
android:descendantFocusability="blocksDescendants"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingLeft="16dp"
|
android:paddingLeft="16dp"
|
||||||
android:paddingStart="16dp"
|
android:paddingStart="16dp"
|
||||||
tools:ignore="RtlSymmetry">
|
tools:ignore="RtlSymmetry">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/track_number"
|
android:id="@+id/track_number"
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,12 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="72dp"
|
android:layout_height="72dp"
|
||||||
android:foreground="?rect_selector">
|
android:background="?card_color"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:foreground="?rect_selector"
|
||||||
|
tools:ignore="UnusedAttribute">
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,20 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="72dp"
|
android:layout_height="72dp"
|
||||||
android:foreground="?rect_selector">
|
android:background="?card_color"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:foreground="?rect_selector"
|
||||||
|
tools:ignore="UnusedAttribute">
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:descendantFocusability="blocksDescendants"
|
android:descendantFocusability="blocksDescendants"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:paddingLeft="16dp"
|
android:paddingLeft="16dp"
|
||||||
android:paddingStart="16dp">
|
android:paddingStart="16dp">
|
||||||
|
|
||||||
<com.kabouzeid.gramophone.views.WidthFitSquareImageView
|
<com.kabouzeid.gramophone.views.WidthFitSquareImageView
|
||||||
android:id="@+id/album_art"
|
android:id="@+id/album_art"
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,10 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="64dp"
|
android:layout_height="64dp"
|
||||||
android:background="?rect_selector">
|
android:background="?card_color"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:foreground="?rect_selector"
|
||||||
|
tools:ignore="UnusedAttribute">
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
@ -13,7 +16,6 @@
|
||||||
android:paddingStart="16dp">
|
android:paddingStart="16dp">
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:tint="?themed_drawable_color"
|
|
||||||
android:id="@+id/playlist_icon"
|
android:id="@+id/playlist_icon"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
|
|
@ -21,6 +23,7 @@
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:padding="8dp"
|
android:padding="8dp"
|
||||||
android:src="@drawable/ic_queue_music_white_24dp"
|
android:src="@drawable/ic_queue_music_white_24dp"
|
||||||
|
android:tint="?themed_drawable_color"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
|
|
@ -40,8 +43,8 @@
|
||||||
android:id="@+id/menu"
|
android:id="@+id/menu"
|
||||||
style="@style/OverFlowButton"
|
style="@style/OverFlowButton"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_marginRight="2dp"
|
|
||||||
android:layout_marginEnd="2dp"
|
android:layout_marginEnd="2dp"
|
||||||
|
android:layout_marginRight="2dp"
|
||||||
tools:ignore="ContentDescription" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
|
||||||
|
|
@ -3,9 +3,11 @@
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="64dp"
|
android:layout_height="64dp"
|
||||||
|
android:background="?card_color"
|
||||||
android:descendantFocusability="blocksDescendants"
|
android:descendantFocusability="blocksDescendants"
|
||||||
|
android:elevation="2dp"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
tools:ignore="ContentDescription">
|
tools:ignore="UnusedAttribute">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/song_title"
|
android:id="@+id/song_title"
|
||||||
|
|
@ -22,8 +24,9 @@
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/playing_indicator"
|
android:id="@+id/playing_indicator"
|
||||||
style="@style/PlayingIndicator"
|
style="@style/PlayingIndicator"
|
||||||
|
android:layout_marginEnd="-8dp"
|
||||||
android:layout_marginRight="-8dp"
|
android:layout_marginRight="-8dp"
|
||||||
android:layout_marginEnd="-8dp" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/menu"
|
android:id="@+id/menu"
|
||||||
|
|
|
||||||
|
|
@ -1,58 +0,0 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="64dp"
|
|
||||||
android:descendantFocusability="blocksDescendants"
|
|
||||||
android:orientation="horizontal"
|
|
||||||
android:paddingLeft="16dp"
|
|
||||||
android:paddingStart="16dp">
|
|
||||||
|
|
||||||
<com.kabouzeid.gramophone.views.WidthFitSquareImageView
|
|
||||||
android:id="@+id/image"
|
|
||||||
android:layout_width="40dp"
|
|
||||||
android:layout_height="40dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:gravity="center"
|
|
||||||
android:scaleType="centerCrop" />
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_weight="1"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:fontFamily="sans-serif"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
|
||||||
android:textColor="?title_text_color" />
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/sub_title"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="16dp"
|
|
||||||
android:layout_marginRight="16dp"
|
|
||||||
android:fontFamily="sans-serif"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:textAppearance="@style/TextAppearance.AppCompat.Body1"
|
|
||||||
android:textColor="?caption_text_color" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/menu"
|
|
||||||
style="@style/OverFlowButton"
|
|
||||||
android:layout_gravity="center_vertical"
|
|
||||||
android:layout_marginRight="2dp"
|
|
||||||
android:layout_marginEnd="2dp"
|
|
||||||
tools:ignore="ContentDescription" />
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
50
app/src/main/res/layout/item_list_smart_playlist.xml
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="64dp"
|
||||||
|
android:foreground="?rect_selector"
|
||||||
|
tools:ignore="UnusedAttribute">
|
||||||
|
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:paddingLeft="16dp"
|
||||||
|
android:paddingStart="16dp">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/playlist_icon"
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="8dp"
|
||||||
|
android:src="@drawable/ic_queue_music_white_24dp"
|
||||||
|
android:tint="?themed_drawable_color"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/playlist_name"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginLeft="16dp"
|
||||||
|
android:layout_marginRight="16dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:fontFamily="sans-serif"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAppearance="@style/TextAppearance.AppCompat.Subhead"
|
||||||
|
android:textColor="?title_text_color" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/menu"
|
||||||
|
style="@style/OverFlowButton"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
android:layout_marginEnd="2dp"
|
||||||
|
android:layout_marginRight="2dp"
|
||||||
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
@ -1,9 +1,12 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="72dp"
|
android:layout_height="72dp"
|
||||||
android:foreground="?rect_selector">
|
android:background="?card_color"
|
||||||
|
android:elevation="2dp"
|
||||||
|
android:foreground="?rect_selector"
|
||||||
|
tools:ignore="UnusedAttribute">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
|
|
||||||
44
app/src/main/res/menu/menu_item_last_added_playlist_song.xml
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_play_next"
|
||||||
|
android:title="@string/action_play_next"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_add_to_current_playing"
|
||||||
|
android:title="@string/action_add_to_playing_queue"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_add_to_playlist"
|
||||||
|
android:title="@string/action_add_to_playlist"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_go_to_album"
|
||||||
|
android:title="@string/action_go_to_album"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_go_to_artist"
|
||||||
|
android:title="@string/action_go_to_artist"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_share"
|
||||||
|
android:title="@string/action_share"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_tag_editor"
|
||||||
|
android:title="@string/action_tag_editor"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_details"
|
||||||
|
android:title="@string/action_details"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_set_as_ringtone"
|
||||||
|
android:title="@string/action_set_as_ringtone"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_delete_from_disk"
|
||||||
|
android:title="@string/action_delete_from_disk"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
</menu>
|
||||||
|
|
@ -1,9 +1,16 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_play"
|
||||||
|
android:title="@string/action_play" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_add_to_current_playing"
|
||||||
|
android:title="@string/action_add_to_playing_queue" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_rename_playlist"
|
android:id="@+id/action_rename_playlist"
|
||||||
android:title="@string/rename_playlist_title"/>
|
android:title="@string/rename_playlist_title" />
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_delete_playlist"
|
android:id="@+id/action_delete_playlist"
|
||||||
android:title="@string/delete_playlist_title"/>
|
android:title="@string/delete_playlist_title" />
|
||||||
</menu>
|
</menu>
|
||||||
10
app/src/main/res/menu/menu_item_smart_playlist.xml
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_play"
|
||||||
|
android:title="@string/action_play" />
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_add_to_current_playing"
|
||||||
|
android:title="@string/action_add_to_playing_queue" />
|
||||||
|
</menu>
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_add_to_playlist"
|
||||||
|
android:icon="@drawable/ic_playlist_add_white_24dp"
|
||||||
|
android:title="@string/action_add_to_playlist"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_add_to_current_playing"
|
||||||
|
android:icon="@drawable/ic_queue_white_24dp"
|
||||||
|
android:title="@string/action_add_to_playing_queue"
|
||||||
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
|
|
@ -9,6 +9,11 @@
|
||||||
android:title="@string/action_currently_playing"
|
android:title="@string/action_currently_playing"
|
||||||
app:showAsAction="ifRoom" />
|
app:showAsAction="ifRoom" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_clear_playlist"
|
||||||
|
android:title="@string/action_clear_playlist"
|
||||||
|
app:showAsAction="never" />
|
||||||
|
|
||||||
<item
|
<item
|
||||||
android:id="@+id/action_playing_queue"
|
android:id="@+id/action_playing_queue"
|
||||||
android:title="@string/action_playing_queue"
|
android:title="@string/action_playing_queue"
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,11 @@
|
||||||
<string name="app_name">Phonograph</string>
|
<string name="app_name">Phonograph</string>
|
||||||
<string name="credits_4">\u0020<a href="http://cookicons.co/">Cookicons</a></string>
|
<string name="credits_4">\u0020<a href="http://cookicons.co/">Cookicons</a></string>
|
||||||
<string name="credits_2">\u0020<b>Karim Abou Zeid</b>.\n\n<a href="https://plus.google.com/+KarimAbouZeid23697">Google+</a>   <a href="https://twitter.com/karim23697">Twitter</a>\n\n</string>
|
<string name="credits_2">\u0020<b>Karim Abou Zeid</b>.\n\n<a href="https://plus.google.com/+KarimAbouZeid23697">Google+</a>   <a href="https://twitter.com/karim23697">Twitter</a>\n\n</string>
|
||||||
|
|
||||||
|
<string name="title_activity_smart_playlist_detail">SmartPlaylistDetailActivity</string>
|
||||||
|
<string name="title_activity_tag_editor">TagEditorActivity</string>
|
||||||
|
<string name="title_activity_album_tag_editor">AlbumTagEditorActivity</string>
|
||||||
|
<string name="title_activity_settings">SettingsActivity</string>
|
||||||
|
<string name="title_activity_playlist_detail">PlaylistActivity</string>
|
||||||
|
<string name="title_activity_search">SearchActivity</string>
|
||||||
</resources>
|
</resources>
|
||||||
|
|
@ -10,9 +10,11 @@
|
||||||
<string name="action_settings">"Settings"</string>
|
<string name="action_settings">"Settings"</string>
|
||||||
<string name="action_about">About</string>
|
<string name="action_about">About</string>
|
||||||
<string name="action_currently_playing">Currently playing</string>
|
<string name="action_currently_playing">Currently playing</string>
|
||||||
|
<string name="action_clear_playlist">Clear playlist</string>
|
||||||
<string name="action_playing_queue">Playing queue</string>
|
<string name="action_playing_queue">Playing queue</string>
|
||||||
<string name="action_search">Search</string>
|
<string name="action_search">Search</string>
|
||||||
<string name="action_play_next">Play next</string>
|
<string name="action_play_next">Play next</string>
|
||||||
|
<string name="action_play">Play</string>
|
||||||
<string name="action_add_to_playing_queue">Add to playing queue</string>
|
<string name="action_add_to_playing_queue">Add to playing queue</string>
|
||||||
<string name="action_remove_from_playing_queue">Remove from playing queue</string>
|
<string name="action_remove_from_playing_queue">Remove from playing queue</string>
|
||||||
<string name="action_add_to_playlist">Add to playlist…</string>
|
<string name="action_add_to_playlist">Add to playlist…</string>
|
||||||
|
|
@ -28,7 +30,6 @@
|
||||||
<string name="biography_unavailable">We were not able to find a matching biography for this artist.</string>
|
<string name="biography_unavailable">We were not able to find a matching biography for this artist.</string>
|
||||||
<string name="biography">Biography</string>
|
<string name="biography">Biography</string>
|
||||||
<string name="audio_focus_denied">No audio focus.</string>
|
<string name="audio_focus_denied">No audio focus.</string>
|
||||||
<string name="title_activity_tag_editor">Tag editor</string>
|
|
||||||
<string name="tag_editor">Tag editor</string>
|
<string name="tag_editor">Tag editor</string>
|
||||||
<string name="album">Album</string>
|
<string name="album">Album</string>
|
||||||
<string name="artist">Artist</string>
|
<string name="artist">Artist</string>
|
||||||
|
|
@ -40,7 +41,6 @@
|
||||||
<string name="album_or_artist_empty">The album title or the album artist text field is empty.</string>
|
<string name="album_or_artist_empty">The album title or the album artist text field is empty.</string>
|
||||||
<string name="writing_file_number">Writing file</string>
|
<string name="writing_file_number">Writing file</string>
|
||||||
<string name="saving_changes">Saving changes…</string>
|
<string name="saving_changes">Saving changes…</string>
|
||||||
<string name="title_activity_album_tag_editor">Album Tag Editor</string>
|
|
||||||
<string name="label_details">Details</string>
|
<string name="label_details">Details</string>
|
||||||
<string name="label_file_name">File name</string>
|
<string name="label_file_name">File name</string>
|
||||||
<string name="label_file_path">File path</string>
|
<string name="label_file_path">File path</string>
|
||||||
|
|
@ -55,13 +55,11 @@
|
||||||
<string name="save_as_playlist">Save as playlist</string>
|
<string name="save_as_playlist">Save as playlist</string>
|
||||||
<string name="credits_3">Icon by</string>
|
<string name="credits_3">Icon by</string>
|
||||||
<string name="credits_1">"Phonograph is a completely free material designed music player by"</string>
|
<string name="credits_1">"Phonograph is a completely free material designed music player by"</string>
|
||||||
<string name="title_activity_search">Search</string>
|
|
||||||
<string name="no_results">No results</string>
|
<string name="no_results">No results</string>
|
||||||
<string name="action_re_download_artist_image">Update artist image</string>
|
<string name="action_re_download_artist_image">Update artist image</string>
|
||||||
<string name="updating">Updating…</string>
|
<string name="updating">Updating…</string>
|
||||||
<string name="added_title_to_playing_queue">"Added 1 title to the playing queue."</string>
|
<string name="added_title_to_playing_queue">"Added 1 title to the playing queue."</string>
|
||||||
<string name="added_x_titles_to_playing_queue">Added %1$d titles to the playing queue.</string>
|
<string name="added_x_titles_to_playing_queue">Added %1$d titles to the playing queue.</string>
|
||||||
<string name="title_activity_playlist_detail">Playlist Activity</string>
|
|
||||||
<string name="action_remove_from_playlist">Remove from playlist</string>
|
<string name="action_remove_from_playlist">Remove from playlist</string>
|
||||||
<string name="new_playlist_action">New playlist…</string>
|
<string name="new_playlist_action">New playlist…</string>
|
||||||
<string name="action_grid_columns">Grid columns</string>
|
<string name="action_grid_columns">Grid columns</string>
|
||||||
|
|
@ -99,7 +97,6 @@
|
||||||
<string name="pref_summary_colored_navigation_bar">In which views the navigation bar should be colored.</string>
|
<string name="pref_summary_colored_navigation_bar">In which views the navigation bar should be colored.</string>
|
||||||
<string name="pref_title_navigation_bar">Colored navigation bar</string>
|
<string name="pref_title_navigation_bar">Colored navigation bar</string>
|
||||||
<string name="pref_title_set_default_start_page">Start page</string>
|
<string name="pref_title_set_default_start_page">Start page</string>
|
||||||
<string name="title_activity_settings">Settings</string>
|
|
||||||
<string name="pref_title_colored_navigation_bar_artists">Artist view</string>
|
<string name="pref_title_colored_navigation_bar_artists">Artist view</string>
|
||||||
<string name="pref_title_colored_navigation_bar_albums">Album view</string>
|
<string name="pref_title_colored_navigation_bar_albums">Album view</string>
|
||||||
<string name="pref_title_colored_navigation_bar_current_playing">Playing view</string>
|
<string name="pref_title_colored_navigation_bar_current_playing">Playing view</string>
|
||||||
|
|
@ -146,15 +143,18 @@
|
||||||
<string name="pref_summary_fade_play_pause">"Fades the song in/out on play/pause."</string>
|
<string name="pref_summary_fade_play_pause">"Fades the song in/out on play/pause."</string>
|
||||||
<string name="pref_summary_gapless_playback">"Eliminates the gap between two songs. Disabling this might fix playback issues."</string>
|
<string name="pref_summary_gapless_playback">"Eliminates the gap between two songs. Disabling this might fix playback issues."</string>
|
||||||
<string name="pref_summary_force_square_album_art">Album art in the now playing view is forced to be squared.</string>
|
<string name="pref_summary_force_square_album_art">Album art in the now playing view is forced to be squared.</string>
|
||||||
<string name="pref_summary_opaque_toolbar_now_playing">The toolbar is opaque and do not cover the album art.</string>
|
<string name="pref_summary_opaque_toolbar_now_playing">The toolbar is opaque and does not cover the album art.</string>
|
||||||
<string name="pref_summary_opaque_statusbar_now_playing">The statusbar is opaque and do not cover the album art.</string>
|
<string name="pref_summary_opaque_statusbar_now_playing">The statusbar is opaque and does not cover the album art.</string>
|
||||||
<string name="pref_summary_larger_title_box_now_playing">The box below the album art where the song title and artist goes is larger in its height.</string>
|
<string name="pref_summary_larger_title_box_now_playing">The box below the album art where the song title and artist goes is larger in its height.</string>
|
||||||
<string name="pref_summary_alternative_progress_slider_now_playing">Uses a progressbar which do not cover the album art instead of the normal progress slider.</string>
|
<string name="pref_summary_alternative_progress_slider_now_playing">Uses a progressbar which does not cover the album art instead of the default progress slider.</string>
|
||||||
<string name="pref_summary_playback_controller_card_now_playing">Displays a card below the playback controller buttons (play/pause etc.).</string>
|
<string name="pref_summary_playback_controller_card_now_playing">Displays a card below the playback controller buttons (play/pause etc.).</string>
|
||||||
<string name="failed_download_albumart">"Unable to download the art for this album."</string>
|
<string name="failed_download_albumart">"Unable to download the art for this album."</string>
|
||||||
<string name="search_hint">Search your library…</string>
|
<string name="search_hint">Search your library…</string>
|
||||||
<string name="rescanning_media">Rescanning media…</string>
|
<string name="rescanning_media">Rescanning media…</string>
|
||||||
<string name="other">Other</string>
|
<string name="favorites">Favorites</string>
|
||||||
|
<string name="last_added">Last added</string>
|
||||||
|
<string name="recently_played">Recently played</string>
|
||||||
|
<string name="my_top_tracks">My top tracks</string>
|
||||||
<string-array name="update_album_cover_options">
|
<string-array name="update_album_cover_options">
|
||||||
<item>Download from Last.fm</item>
|
<item>Download from Last.fm</item>
|
||||||
<item>Pick from Local Storage</item>
|
<item>Pick from Local Storage</item>
|
||||||
|
|
|
||||||