Library annotations (#638)

Populate album name / artist name / song counts across different view as "subtitle" that enriches the main info displayed in the title.
This includes the notification, different list-based views, the main menu, the now-playing view, search result...

For example, the included images show the added annotations highlighted with white underline
![screenshot_20190108-035119](https://user-images.githubusercontent.com/13333482/50807749-ce600000-12fb-11e9-86c6-9efb41389194.jpg)
![screenshot_20190108-035137](https://user-images.githubusercontent.com/13333482/50807750-ce600000-12fb-11e9-90e2-650aae0b159a.jpg)
![screenshot_20190108-035228](https://user-images.githubusercontent.com/13333482/50807751-ce600000-12fb-11e9-8f74-b04dbae0c6d2.jpg)
![screenshot_20190108-035244](https://user-images.githubusercontent.com/13333482/50807752-cef89680-12fb-11e9-892c-80fd55805c11.jpg)
![screenshot_20190108-035414](https://user-images.githubusercontent.com/13333482/50807753-cef89680-12fb-11e9-80a1-ee784c855876.jpg)
This commit is contained in:
soncaokim 2019-01-22 04:48:25 +01:00 committed by Eugene
commit b0a4ffdcb5
14 changed files with 100 additions and 47 deletions

View file

@ -72,7 +72,7 @@ public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder
case ALBUM: case ALBUM:
final Album album = (Album) dataSet.get(position); final Album album = (Album) dataSet.get(position);
holder.title.setText(album.getTitle()); holder.title.setText(album.getTitle());
holder.text.setText(album.getArtistName()); holder.text.setText(MusicUtil.getAlbumInfoString(activity, album));
SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong()) SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
.checkIgnoreMediaStore(activity).build() .checkIgnoreMediaStore(activity).build()
.into(holder.image); .into(holder.image);
@ -87,7 +87,7 @@ public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder
case SONG: case SONG:
final Song song = (Song) dataSet.get(position); final Song song = (Song) dataSet.get(position);
holder.title.setText(song.title); holder.title.setText(song.title);
holder.text.setText(song.albumName); holder.text.setText(MusicUtil.getSongInfoString(song));
break; break;
default: default:
holder.title.setText(dataSet.get(position).toString()); holder.title.setText(dataSet.get(position).toString());

View file

@ -27,6 +27,7 @@ import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.NavigationUtil; import com.kabouzeid.gramophone.util.NavigationUtil;
import com.kabouzeid.gramophone.util.PreferenceUtil; import com.kabouzeid.gramophone.util.PreferenceUtil;
import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView; import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView;
import java.util.ArrayList; import java.util.ArrayList;
@ -84,7 +85,10 @@ public class AlbumAdapter extends AbsMultiSelectAdapter<AlbumAdapter.ViewHolder,
} }
protected String getAlbumText(Album album) { protected String getAlbumText(Album album) {
return album.getArtistName(); return MusicUtil.buildInfoString(
album.getArtistName(),
MusicUtil.getSongCountString(activity, album.songs.size())
);
} }
@Override @Override

View file

@ -158,7 +158,7 @@ public class SongAdapter extends AbsMultiSelectAdapter<SongAdapter.ViewHolder, S
} }
protected String getSongText(Song song) { protected String getSongText(Song song) {
return song.artistName; return MusicUtil.getSongInfoString(song);
} }
@Override @Override

View file

@ -16,12 +16,12 @@ import android.graphics.RectF;
import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable; import android.graphics.drawable.Drawable;
import android.os.Build; import android.os.Build;
import android.text.TextUtils;
import android.widget.RemoteViews; import android.widget.RemoteViews;
import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.service.MusicService; import com.kabouzeid.gramophone.service.MusicService;
import com.kabouzeid.gramophone.util.MusicUtil;
public abstract class BaseAppWidget extends AppWidgetProvider { public abstract class BaseAppWidget extends AppWidgetProvider {
public static final String NAME = "app_widget"; public static final String NAME = "app_widget";
@ -137,12 +137,6 @@ public abstract class BaseAppWidget extends AppWidgetProvider {
} }
protected String getSongArtistAndAlbum(final Song song) { protected String getSongArtistAndAlbum(final Song song) {
final StringBuilder builder = new StringBuilder(); return MusicUtil.getSongInfoString(song);
builder.append(song.artistName);
if (!TextUtils.isEmpty(song.artistName) && !TextUtils.isEmpty(song.albumName)) {
builder.append("");
}
builder.append(song.albumName);
return builder.toString();
} }
} }

View file

@ -5,6 +5,7 @@ import android.os.Parcel;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.util.MusicUtil;
import java.util.ArrayList; import java.util.ArrayList;
@ -13,8 +14,6 @@ import java.util.ArrayList;
*/ */
public abstract class AbsCustomPlaylist extends Playlist { public abstract class AbsCustomPlaylist extends Playlist {
public static final String INFO_STRING_SEPARATOR = "";
public AbsCustomPlaylist(int id, String name) { public AbsCustomPlaylist(int id, String name) {
super(id, name); super(id, name);
} }
@ -32,14 +31,12 @@ public abstract class AbsCustomPlaylist extends Playlist {
@NonNull @NonNull
@Override @Override
public String getInfoString(@NonNull Context context) { public String getInfoString(@NonNull Context context) {
String baseInfo = super.getInfoString(context);
int songCount = getSongs(context).size(); int songCount = getSongs(context).size();
String songCountText = (songCount == 0) ? String songCountString = MusicUtil.getSongCountString(context, songCount);
context.getString(R.string.no_songs) :
String.valueOf(songCount) + " " + context.getString(R.string.songs);
if (baseInfo.isEmpty()) {return songCountText;} return MusicUtil.buildInfoString(
return songCountText + INFO_STRING_SEPARATOR + baseInfo; songCountString,
super.getInfoString(context)
);
} }
} }

View file

@ -8,6 +8,7 @@ import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.loader.TopAndRecentlyPlayedTracksLoader; import com.kabouzeid.gramophone.loader.TopAndRecentlyPlayedTracksLoader;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.provider.HistoryStore; import com.kabouzeid.gramophone.provider.HistoryStore;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.PreferenceUtil; import com.kabouzeid.gramophone.util.PreferenceUtil;
import java.util.ArrayList; import java.util.ArrayList;
@ -24,11 +25,12 @@ public class HistoryPlaylist extends AbsSmartPlaylist {
@NonNull @NonNull
@Override @Override
public String getInfoString(@NonNull Context context) { public String getInfoString(@NonNull Context context) {
String baseInfo = super.getInfoString(context);
String cutoff = PreferenceUtil.getInstance(context).getRecentlyPlayedCutoffText(context); String cutoff = PreferenceUtil.getInstance(context).getRecentlyPlayedCutoffText(context);
if (baseInfo.isEmpty()) {return cutoff;} return MusicUtil.buildInfoString(
return cutoff + INFO_STRING_SEPARATOR + baseInfo; cutoff,
super.getInfoString(context)
);
} }
@NonNull @NonNull

View file

@ -7,6 +7,7 @@ import android.support.annotation.NonNull;
import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.loader.LastAddedLoader; import com.kabouzeid.gramophone.loader.LastAddedLoader;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.PreferenceUtil; import com.kabouzeid.gramophone.util.PreferenceUtil;
import java.util.ArrayList; import java.util.ArrayList;
@ -23,11 +24,12 @@ public class LastAddedPlaylist extends AbsSmartPlaylist {
@NonNull @NonNull
@Override @Override
public String getInfoString(@NonNull Context context) { public String getInfoString(@NonNull Context context) {
String baseInfo = super.getInfoString(context);
String cutoff = PreferenceUtil.getInstance(context).getLastAddedCutoffText(context); String cutoff = PreferenceUtil.getInstance(context).getLastAddedCutoffText(context);
if (baseInfo.isEmpty()) {return cutoff;} return MusicUtil.buildInfoString(
return cutoff + INFO_STRING_SEPARATOR + baseInfo; cutoff,
super.getInfoString(context)
);
} }
@NonNull @NonNull

View file

@ -7,6 +7,7 @@ import android.support.annotation.NonNull;
import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.loader.TopAndRecentlyPlayedTracksLoader; import com.kabouzeid.gramophone.loader.TopAndRecentlyPlayedTracksLoader;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.PreferenceUtil; import com.kabouzeid.gramophone.util.PreferenceUtil;
import java.util.ArrayList; import java.util.ArrayList;
@ -23,11 +24,12 @@ public class NotRecentlyPlayedPlaylist extends AbsSmartPlaylist {
@NonNull @NonNull
@Override @Override
public String getInfoString(@NonNull Context context) { public String getInfoString(@NonNull Context context) {
String baseInfo = super.getInfoString(context);
String cutoff = PreferenceUtil.getInstance(context).getRecentlyPlayedCutoffText(context); String cutoff = PreferenceUtil.getInstance(context).getRecentlyPlayedCutoffText(context);
if (baseInfo.isEmpty()) {return cutoff;} return MusicUtil.buildInfoString(
return cutoff + INFO_STRING_SEPARATOR + baseInfo; cutoff,
super.getInfoString(context)
);
} }
@NonNull @NonNull

View file

@ -11,7 +11,6 @@ import android.os.Build;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import android.support.v4.media.app.NotificationCompat.MediaStyle; import android.support.v4.media.app.NotificationCompat.MediaStyle;
import android.support.v7.graphics.Palette; import android.support.v7.graphics.Palette;
import android.text.TextUtils;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.bumptech.glide.request.animation.GlideAnimation; import com.bumptech.glide.request.animation.GlideAnimation;
@ -22,6 +21,7 @@ import com.kabouzeid.gramophone.glide.palette.BitmapPaletteWrapper;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.service.MusicService; import com.kabouzeid.gramophone.service.MusicService;
import com.kabouzeid.gramophone.ui.activities.MainActivity; import com.kabouzeid.gramophone.ui.activities.MainActivity;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.PreferenceUtil; import com.kabouzeid.gramophone.util.PreferenceUtil;
import static com.kabouzeid.gramophone.service.MusicService.ACTION_REWIND; import static com.kabouzeid.gramophone.service.MusicService.ACTION_REWIND;
@ -36,11 +36,8 @@ public class PlayingNotificationImpl24 extends PlayingNotification {
final Song song = service.getCurrentSong(); final Song song = service.getCurrentSong();
final String albumName = song.albumName;
final String artistName = song.artistName;
final boolean isPlaying = service.isPlaying(); final boolean isPlaying = service.isPlaying();
final String text = TextUtils.isEmpty(albumName) final String text = MusicUtil.getSongInfoString(song);
? artistName : artistName + " - " + albumName;
final int playButtonResId = isPlaying final int playButtonResId = isPlaying
? R.drawable.ic_pause_white_24dp : R.drawable.ic_play_arrow_white_24dp; ? R.drawable.ic_pause_white_24dp : R.drawable.ic_play_arrow_white_24dp;

View file

@ -23,6 +23,7 @@ import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import com.bumptech.glide.Glide; import com.bumptech.glide.Glide;
import com.kabouzeid.appthemehelper.ThemeStore; import com.kabouzeid.appthemehelper.ThemeStore;
import com.kabouzeid.appthemehelper.util.ATHUtil; import com.kabouzeid.appthemehelper.util.ATHUtil;
import com.kabouzeid.appthemehelper.util.NavigationViewUtil; import com.kabouzeid.appthemehelper.util.NavigationViewUtil;
@ -42,7 +43,9 @@ import com.kabouzeid.gramophone.ui.activities.base.AbsSlidingMusicPanelActivity;
import com.kabouzeid.gramophone.ui.activities.intro.AppIntroActivity; import com.kabouzeid.gramophone.ui.activities.intro.AppIntroActivity;
import com.kabouzeid.gramophone.ui.fragments.mainactivity.folders.FoldersFragment; import com.kabouzeid.gramophone.ui.fragments.mainactivity.folders.FoldersFragment;
import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.LibraryFragment; import com.kabouzeid.gramophone.ui.fragments.mainactivity.library.LibraryFragment;
import com.kabouzeid.gramophone.util.MusicUtil;
import com.kabouzeid.gramophone.util.PreferenceUtil; import com.kabouzeid.gramophone.util.PreferenceUtil;
import com.sothree.slidinguppanel.SlidingUpPanelLayout; import com.sothree.slidinguppanel.SlidingUpPanelLayout;
import java.util.ArrayList; import java.util.ArrayList;
@ -217,7 +220,7 @@ public class MainActivity extends AbsSlidingMusicPanelActivity {
}); });
} }
((TextView) navigationDrawerHeader.findViewById(R.id.title)).setText(song.title); ((TextView) navigationDrawerHeader.findViewById(R.id.title)).setText(song.title);
((TextView) navigationDrawerHeader.findViewById(R.id.text)).setText(song.artistName); ((TextView) navigationDrawerHeader.findViewById(R.id.text)).setText(MusicUtil.getSongInfoString(song));
SongGlideRequest.Builder.from(Glide.with(this), song) SongGlideRequest.Builder.from(Glide.with(this), song)
.checkIgnoreMediaStore(this).build() .checkIgnoreMediaStore(this).build()
.into(((ImageView) navigationDrawerHeader.findViewById(R.id.image))); .into(((ImageView) navigationDrawerHeader.findViewById(R.id.image)));

View file

@ -132,7 +132,12 @@ public abstract class AbsPlayerFragment extends AbsMusicServiceFragment implemen
} }
protected String getUpNextAndQueueTime() { protected String getUpNextAndQueueTime() {
return getResources().getString(R.string.up_next) + "" + MusicUtil.getReadableDurationString(MusicPlayerRemote.getQueueDurationMillis(MusicPlayerRemote.getPosition())); final long duration = MusicPlayerRemote.getQueueDurationMillis(MusicPlayerRemote.getPosition());
return MusicUtil.buildInfoString(
getResources().getString(R.string.up_next),
MusicUtil.getReadableDurationString(duration)
);
} }
public abstract void onShow(); public abstract void onShow();

View file

@ -568,7 +568,7 @@ public class CardPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
public void updateCurrentSong(Song song) { public void updateCurrentSong(Song song) {
currentSong = song; currentSong = song;
currentSongViewHolder.title.setText(song.title); currentSongViewHolder.title.setText(song.title);
currentSongViewHolder.text.setText(song.artistName); currentSongViewHolder.text.setText(MusicUtil.getSongInfoString(song));
} }
@Override @Override
@ -603,7 +603,7 @@ public class CardPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
@Override @Override
public void updateCurrentSong(Song song) { public void updateCurrentSong(Song song) {
fragment.toolbar.setTitle(song.title); fragment.toolbar.setTitle(song.title);
fragment.toolbar.setSubtitle(song.artistName); fragment.toolbar.setSubtitle(MusicUtil.getSongInfoString(song));
} }
@Override @Override

View file

@ -548,7 +548,7 @@ public class FlatPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
public void updateCurrentSong(Song song) { public void updateCurrentSong(Song song) {
currentSong = song; currentSong = song;
currentSongViewHolder.title.setText(song.title); currentSongViewHolder.title.setText(song.title);
currentSongViewHolder.text.setText(song.artistName); currentSongViewHolder.text.setText(MusicUtil.getSongInfoString(song));
} }
@Override @Override
@ -576,7 +576,7 @@ public class FlatPlayerFragment extends AbsPlayerFragment implements PlayerAlbum
@Override @Override
public void updateCurrentSong(Song song) { public void updateCurrentSong(Song song) {
fragment.toolbar.setTitle(song.title); fragment.toolbar.setTitle(song.title);
fragment.toolbar.setSubtitle(song.artistName); fragment.toolbar.setSubtitle(MusicUtil.getSongInfoString(song));
} }
@Override @Override

View file

@ -22,11 +22,13 @@ import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.loader.PlaylistLoader; import com.kabouzeid.gramophone.loader.PlaylistLoader;
import com.kabouzeid.gramophone.loader.SongLoader; import com.kabouzeid.gramophone.loader.SongLoader;
import com.kabouzeid.gramophone.model.Album;
import com.kabouzeid.gramophone.model.Artist; import com.kabouzeid.gramophone.model.Artist;
import com.kabouzeid.gramophone.model.Genre; import com.kabouzeid.gramophone.model.Genre;
import com.kabouzeid.gramophone.model.Playlist; import com.kabouzeid.gramophone.model.Playlist;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
import com.kabouzeid.gramophone.model.lyrics.AbsSynchronizedLyrics; import com.kabouzeid.gramophone.model.lyrics.AbsSynchronizedLyrics;
import com.kabouzeid.gramophone.util.MusicUtil;
import org.jaudiotagger.audio.AudioFileIO; import org.jaudiotagger.audio.AudioFileIO;
import org.jaudiotagger.tag.FieldKey; import org.jaudiotagger.tag.FieldKey;
@ -107,22 +109,45 @@ public class MusicUtil {
public static String getArtistInfoString(@NonNull final Context context, @NonNull final Artist artist) { public static String getArtistInfoString(@NonNull final Context context, @NonNull final Artist artist) {
int albumCount = artist.getAlbumCount(); int albumCount = artist.getAlbumCount();
int songCount = artist.getSongCount(); int songCount = artist.getSongCount();
String albumString = albumCount == 1 ? context.getResources().getString(R.string.album) : context.getResources().getString(R.string.albums);
String songString = songCount == 1 ? context.getResources().getString(R.string.song) : context.getResources().getString(R.string.songs); return MusicUtil.buildInfoString(
return albumCount + " " + albumString + "" + songCount + " " + songString; MusicUtil.getAlbumCountString(context, albumCount),
MusicUtil.getSongCountString(context, songCount)
);
}
@NonNull
public static String getAlbumInfoString(@NonNull final Context context, @NonNull final Album album) {
int songCount = album.getSongCount();
return MusicUtil.buildInfoString(
album.getArtistName(),
MusicUtil.getSongCountString(context, songCount)
);
}
@NonNull
public static String getSongInfoString(@NonNull final Song song) {
return MusicUtil.buildInfoString(
song.artistName,
song.albumName
);
} }
@NonNull @NonNull
public static String getGenreInfoString(@NonNull final Context context, @NonNull final Genre genre) { public static String getGenreInfoString(@NonNull final Context context, @NonNull final Genre genre) {
int songCount = genre.songCount; int songCount = genre.songCount;
String songString = songCount == 1 ? context.getResources().getString(R.string.song) : context.getResources().getString(R.string.songs); return MusicUtil.getSongCountString(context, songCount);
return songCount + " " + songString;
} }
@NonNull @NonNull
public static String getPlaylistInfoString(@NonNull final Context context, @NonNull List<Song> songs) { public static String getPlaylistInfoString(@NonNull final Context context, @NonNull List<Song> songs) {
final long duration = getTotalDuration(context, songs); final long duration = getTotalDuration(context, songs);
return MusicUtil.getSongCountString(context, songs.size()) + "" + MusicUtil.getReadableDurationString(duration);
return MusicUtil.buildInfoString(
MusicUtil.getSongCountString(context, songs.size()),
MusicUtil.getReadableDurationString(duration)
);
} }
@NonNull @NonNull
@ -162,6 +187,28 @@ public class MusicUtil {
} }
} }
/**
* Build a concatenated string from the provided arguments
* The intended purpose is to show extra annotations
* to a music library item.
* Ex: for a given album --> buildInfoString(album.artist, album.songCount)
*/
public static String buildInfoString(@NonNull final String string1, @NonNull final String string2)
{
// Skip empty strings
if (string1.isEmpty()) {return string2;}
if (string2.isEmpty()) {return string1;}
final String separator = "";
final StringBuilder builder = new StringBuilder();
builder.append(string1);
builder.append(separator);
builder.append(string2);
return builder.toString();
}
//iTunes uses for example 1002 for track 2 CD1 or 3011 for track 11 CD3. //iTunes uses for example 1002 for track 2 CD1 or 3011 for track 11 CD3.
//this method converts those values to normal tracknumbers //this method converts those values to normal tracknumbers
public static int getFixedTrackNumber(int trackNumberToFix) { public static int getFixedTrackNumber(int trackNumberToFix) {