mirror of
https://github.com/antebudimir/tempus.git
synced 2025-12-31 17:43:32 +00:00
feat: added the ability to filter and group downloaded songs
This commit is contained in:
parent
06e2729aca
commit
e87eda2757
8 changed files with 449 additions and 78 deletions
|
|
@ -52,4 +52,10 @@ class Download(@PrimaryKey override val id: String) : Child(id) {
|
||||||
originalWidth = child.originalWidth
|
originalWidth = child.originalWidth
|
||||||
originalHeight = child.originalHeight
|
originalHeight = child.originalHeight
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Keep
|
||||||
|
data class DownloadStack(
|
||||||
|
var id: String,
|
||||||
|
var view: String?
|
||||||
|
)
|
||||||
|
|
@ -11,25 +11,35 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
import com.cappielloantonio.tempo.R;
|
import com.cappielloantonio.tempo.R;
|
||||||
import com.cappielloantonio.tempo.databinding.ItemHorizontalDownloadBinding;
|
import com.cappielloantonio.tempo.databinding.ItemHorizontalDownloadBinding;
|
||||||
|
import com.cappielloantonio.tempo.glide.CustomGlideRequest;
|
||||||
import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.Child;
|
import com.cappielloantonio.tempo.subsonic.models.Child;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||||
|
import com.cappielloantonio.tempo.util.Util;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHorizontalAdapter.ViewHolder> {
|
public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHorizontalAdapter.ViewHolder> {
|
||||||
private final ClickCallback click;
|
private final ClickCallback click;
|
||||||
|
|
||||||
|
private String view;
|
||||||
|
private String filterKey;
|
||||||
|
private String filterValue;
|
||||||
|
|
||||||
private List<Child> songs;
|
private List<Child> songs;
|
||||||
|
private List<Child> grouped;
|
||||||
|
|
||||||
public DownloadHorizontalAdapter(ClickCallback click) {
|
public DownloadHorizontalAdapter(ClickCallback click) {
|
||||||
this.click = click;
|
this.click = click;
|
||||||
|
this.view = Constants.DOWNLOAD_TYPE_TRACK;
|
||||||
this.songs = Collections.emptyList();
|
this.songs = Collections.emptyList();
|
||||||
|
this.grouped = Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NonNull
|
@NonNull
|
||||||
|
|
@ -41,31 +51,43 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHori
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||||
Child song = songs.get(position);
|
switch (view) {
|
||||||
|
case Constants.DOWNLOAD_TYPE_TRACK:
|
||||||
holder.item.downloadedSongTitleTextView.setText(MusicUtil.getReadableString(song.getTitle()));
|
initTrackLayout(holder, position);
|
||||||
holder.item.downloadedSongArtistTextView.setText(holder.itemView.getContext().getString(R.string.song_subtitle_formatter, MusicUtil.getReadableString(song.getArtist()), MusicUtil.getReadableDurationString(song.getDuration(), false)));
|
break;
|
||||||
holder.item.downloadedSongAlbumTextView.setText(MusicUtil.getReadableString(song.getAlbum()));
|
case Constants.DOWNLOAD_TYPE_ALBUM:
|
||||||
|
initAlbumLayout(holder, position);
|
||||||
if (position > 0 && songs.get(position - 1) != null && !Objects.equals(songs.get(position - 1).getAlbum(), songs.get(position).getAlbum())) {
|
break;
|
||||||
holder.item.divider.setPadding(0, (int) holder.itemView.getContext().getResources().getDimension(R.dimen.downloaded_item_padding), 0, 0);
|
case Constants.DOWNLOAD_TYPE_ARTIST:
|
||||||
} else {
|
initArtistLayout(holder, position);
|
||||||
if (position > 0) holder.item.divider.setVisibility(View.GONE);
|
break;
|
||||||
|
case Constants.DOWNLOAD_TYPE_GENRE:
|
||||||
|
initGenreLayout(holder, position);
|
||||||
|
break;
|
||||||
|
case Constants.DOWNLOAD_TYPE_YEAR:
|
||||||
|
initYearLayout(holder, position);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return songs.size();
|
return grouped.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setItems(List<Child> songs) {
|
public void setItems(String view, String filterKey, String filterValue, List<Child> songs) {
|
||||||
|
this.view = filterValue != null ? view : filterKey;
|
||||||
|
this.filterKey = filterKey;
|
||||||
|
this.filterValue = filterValue;
|
||||||
|
|
||||||
this.songs = songs;
|
this.songs = songs;
|
||||||
|
this.grouped = groupSong(songs);
|
||||||
|
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Child getItem(int id) {
|
public Child getItem(int id) {
|
||||||
return songs.get(id);
|
return grouped.get(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -78,6 +100,145 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHori
|
||||||
return position;
|
return position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<Child> groupSong(List<Child> songs) {
|
||||||
|
switch (view) {
|
||||||
|
case Constants.DOWNLOAD_TYPE_TRACK:
|
||||||
|
return filterSong(filterKey, filterValue, songs.stream().filter(song -> Objects.nonNull(song.getId())).filter(Util.distinctByKey(Child::getId)).collect(Collectors.toList()));
|
||||||
|
case Constants.DOWNLOAD_TYPE_ALBUM:
|
||||||
|
return filterSong(filterKey, filterValue, songs.stream().filter(song -> Objects.nonNull(song.getAlbumId())).filter(Util.distinctByKey(Child::getAlbumId)).collect(Collectors.toList()));
|
||||||
|
case Constants.DOWNLOAD_TYPE_ARTIST:
|
||||||
|
return filterSong(filterKey, filterValue, songs.stream().filter(song -> Objects.nonNull(song.getArtistId())).filter(Util.distinctByKey(Child::getArtistId)).collect(Collectors.toList()));
|
||||||
|
case Constants.DOWNLOAD_TYPE_GENRE:
|
||||||
|
return filterSong(filterKey, filterValue, songs.stream().filter(song -> Objects.nonNull(song.getGenre())).filter(Util.distinctByKey(Child::getGenre)).collect(Collectors.toList()));
|
||||||
|
case Constants.DOWNLOAD_TYPE_YEAR:
|
||||||
|
return filterSong(filterKey, filterValue, songs.stream().filter(song -> Objects.nonNull(song.getYear())).filter(Util.distinctByKey(Child::getYear)).collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Child> filterSong(String filterKey, String filterValue, List<Child> songs) {
|
||||||
|
if (filterValue != null) {
|
||||||
|
switch (filterKey) {
|
||||||
|
case Constants.DOWNLOAD_TYPE_TRACK:
|
||||||
|
return songs.stream().filter(child -> child.getId().equals(filterValue)).collect(Collectors.toList());
|
||||||
|
case Constants.DOWNLOAD_TYPE_ALBUM:
|
||||||
|
return songs.stream().filter(child -> child.getAlbumId().equals(filterValue)).collect(Collectors.toList());
|
||||||
|
case Constants.DOWNLOAD_TYPE_GENRE:
|
||||||
|
return songs.stream().filter(child -> child.getGenre().equals(filterValue)).collect(Collectors.toList());
|
||||||
|
case Constants.DOWNLOAD_TYPE_YEAR:
|
||||||
|
return songs.stream().filter(child -> Objects.equals(child.getYear(), Integer.valueOf(filterValue))).collect(Collectors.toList());
|
||||||
|
case Constants.DOWNLOAD_TYPE_ARTIST:
|
||||||
|
return songs.stream().filter(child -> child.getArtistId().equals(filterValue)).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return songs;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String countSong(String filterKey, String filterValue, List<Child> songs) {
|
||||||
|
if (filterValue != null) {
|
||||||
|
switch (filterKey) {
|
||||||
|
case Constants.DOWNLOAD_TYPE_TRACK:
|
||||||
|
return String.valueOf(songs.stream().filter(child -> child.getId().equals(filterValue)).count());
|
||||||
|
case Constants.DOWNLOAD_TYPE_ALBUM:
|
||||||
|
return String.valueOf(songs.stream().filter(child -> child.getAlbumId().equals(filterValue)).count());
|
||||||
|
case Constants.DOWNLOAD_TYPE_GENRE:
|
||||||
|
return String.valueOf(songs.stream().filter(child -> child.getGenre().equals(filterValue)).count());
|
||||||
|
case Constants.DOWNLOAD_TYPE_YEAR:
|
||||||
|
return String.valueOf(songs.stream().filter(child -> Objects.equals(child.getYear(), Integer.valueOf(filterValue))).count());
|
||||||
|
case Constants.DOWNLOAD_TYPE_ARTIST:
|
||||||
|
return String.valueOf(songs.stream().filter(child -> child.getArtistId().equals(filterValue)).count());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initTrackLayout(ViewHolder holder, int position) {
|
||||||
|
Child song = grouped.get(position);
|
||||||
|
|
||||||
|
holder.item.downloadedItemTitleTextView.setText(MusicUtil.getReadableString(song.getTitle()));
|
||||||
|
holder.item.downloadedItemSubtitleTextView.setText(holder.itemView.getContext().getString(R.string.song_subtitle_formatter, MusicUtil.getReadableString(song.getArtist()), MusicUtil.getReadableDurationString(song.getDuration(), false)));
|
||||||
|
holder.item.downloadedItemPreTextView.setText(MusicUtil.getReadableString(song.getAlbum()));
|
||||||
|
|
||||||
|
CustomGlideRequest.Builder
|
||||||
|
.from(holder.itemView.getContext(), song.getCoverArtId())
|
||||||
|
.build()
|
||||||
|
.into(holder.item.itemCoverImageView);
|
||||||
|
|
||||||
|
holder.item.itemCoverImageView.setVisibility(View.VISIBLE);
|
||||||
|
holder.item.downloadedItemMoreButton.setVisibility(View.VISIBLE);
|
||||||
|
holder.item.divider.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
if (position > 0 && grouped.get(position - 1) != null && !Objects.equals(grouped.get(position - 1).getAlbum(), grouped.get(position).getAlbum())) {
|
||||||
|
holder.item.divider.setPadding(0, (int) holder.itemView.getContext().getResources().getDimension(R.dimen.downloaded_item_padding), 0, 0);
|
||||||
|
} else {
|
||||||
|
if (position > 0) holder.item.divider.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initAlbumLayout(ViewHolder holder, int position) {
|
||||||
|
Child song = grouped.get(position);
|
||||||
|
|
||||||
|
holder.item.downloadedItemTitleTextView.setText(MusicUtil.getReadableString(song.getAlbum()));
|
||||||
|
holder.item.downloadedItemSubtitleTextView.setText(holder.itemView.getContext().getString(R.string.download_item_single_subtitle_formatter, countSong(Constants.DOWNLOAD_TYPE_ALBUM, song.getAlbumId(), songs)));
|
||||||
|
holder.item.downloadedItemPreTextView.setText(MusicUtil.getReadableString(song.getArtist()));
|
||||||
|
|
||||||
|
CustomGlideRequest.Builder
|
||||||
|
.from(holder.itemView.getContext(), song.getCoverArtId())
|
||||||
|
.build()
|
||||||
|
.into(holder.item.itemCoverImageView);
|
||||||
|
|
||||||
|
holder.item.itemCoverImageView.setVisibility(View.VISIBLE);
|
||||||
|
holder.item.downloadedItemMoreButton.setVisibility(View.GONE);
|
||||||
|
holder.item.divider.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
|
if (position > 0 && grouped.get(position - 1) != null && !Objects.equals(grouped.get(position - 1).getArtist(), grouped.get(position).getArtist())) {
|
||||||
|
holder.item.divider.setPadding(0, (int) holder.itemView.getContext().getResources().getDimension(R.dimen.downloaded_item_padding), 0, 0);
|
||||||
|
} else {
|
||||||
|
if (position > 0) holder.item.divider.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initArtistLayout(ViewHolder holder, int position) {
|
||||||
|
Child song = grouped.get(position);
|
||||||
|
|
||||||
|
holder.item.downloadedItemTitleTextView.setText(MusicUtil.getReadableString(song.getArtist()));
|
||||||
|
holder.item.downloadedItemSubtitleTextView.setText(holder.itemView.getContext().getString(R.string.download_item_single_subtitle_formatter, countSong(Constants.DOWNLOAD_TYPE_ARTIST, song.getArtistId(), songs)));
|
||||||
|
|
||||||
|
CustomGlideRequest.Builder
|
||||||
|
.from(holder.itemView.getContext(), song.getCoverArtId())
|
||||||
|
.build()
|
||||||
|
.into(holder.item.itemCoverImageView);
|
||||||
|
|
||||||
|
holder.item.itemCoverImageView.setVisibility(View.VISIBLE);
|
||||||
|
holder.item.downloadedItemMoreButton.setVisibility(View.GONE);
|
||||||
|
holder.item.divider.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initGenreLayout(ViewHolder holder, int position) {
|
||||||
|
Child song = grouped.get(position);
|
||||||
|
|
||||||
|
holder.item.downloadedItemTitleTextView.setText(MusicUtil.getReadableString(song.getGenre()));
|
||||||
|
holder.item.downloadedItemSubtitleTextView.setText(holder.itemView.getContext().getString(R.string.download_item_single_subtitle_formatter, countSong(Constants.DOWNLOAD_TYPE_GENRE, song.getGenre(), songs)));
|
||||||
|
|
||||||
|
holder.item.itemCoverImageView.setVisibility(View.GONE);
|
||||||
|
holder.item.downloadedItemMoreButton.setVisibility(View.GONE);
|
||||||
|
holder.item.divider.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initYearLayout(ViewHolder holder, int position) {
|
||||||
|
Child song = grouped.get(position);
|
||||||
|
|
||||||
|
holder.item.downloadedItemTitleTextView.setText(String.valueOf(song.getYear()));
|
||||||
|
holder.item.downloadedItemSubtitleTextView.setText(holder.itemView.getContext().getString(R.string.download_item_single_subtitle_formatter, countSong(Constants.DOWNLOAD_TYPE_YEAR, song.getYear().toString(), songs)));
|
||||||
|
|
||||||
|
holder.item.itemCoverImageView.setVisibility(View.GONE);
|
||||||
|
holder.item.downloadedItemMoreButton.setVisibility(View.GONE);
|
||||||
|
holder.item.divider.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
public class ViewHolder extends RecyclerView.ViewHolder {
|
public class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
ItemHorizontalDownloadBinding item;
|
ItemHorizontalDownloadBinding item;
|
||||||
|
|
||||||
|
|
@ -86,30 +247,62 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHori
|
||||||
|
|
||||||
this.item = item;
|
this.item = item;
|
||||||
|
|
||||||
item.downloadedSongTitleTextView.setSelected(true);
|
item.downloadedItemTitleTextView.setSelected(true);
|
||||||
item.downloadedSongArtistTextView.setSelected(true);
|
item.downloadedItemSubtitleTextView.setSelected(true);
|
||||||
|
|
||||||
itemView.setOnClickListener(v -> onClick());
|
itemView.setOnClickListener(v -> onClick());
|
||||||
itemView.setOnLongClickListener(v -> onLongClick());
|
itemView.setOnLongClickListener(v -> onLongClick());
|
||||||
|
|
||||||
item.downloadedSongMoreButton.setOnClickListener(v -> onLongClick());
|
item.downloadedItemMoreButton.setOnClickListener(v -> onLongClick());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onClick() {
|
public void onClick() {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putParcelableArrayList(Constants.TRACKS_OBJECT, new ArrayList<>(songs));
|
|
||||||
bundle.putInt(Constants.ITEM_POSITION, getBindingAdapterPosition());
|
|
||||||
|
|
||||||
click.onMediaClick(bundle);
|
switch (view) {
|
||||||
|
case Constants.DOWNLOAD_TYPE_TRACK:
|
||||||
|
bundle.putParcelableArrayList(Constants.TRACKS_OBJECT, new ArrayList<>(songs));
|
||||||
|
bundle.putInt(Constants.ITEM_POSITION, getBindingAdapterPosition());
|
||||||
|
click.onMediaClick(bundle);
|
||||||
|
break;
|
||||||
|
case Constants.DOWNLOAD_TYPE_ALBUM:
|
||||||
|
bundle.putString(Constants.DOWNLOAD_TYPE_ALBUM, grouped.get(getBindingAdapterPosition()).getAlbumId());
|
||||||
|
click.onAlbumClick(bundle);
|
||||||
|
break;
|
||||||
|
case Constants.DOWNLOAD_TYPE_ARTIST:
|
||||||
|
bundle.putString(Constants.DOWNLOAD_TYPE_ARTIST, grouped.get(getBindingAdapterPosition()).getArtistId());
|
||||||
|
click.onArtistClick(bundle);
|
||||||
|
break;
|
||||||
|
case Constants.DOWNLOAD_TYPE_GENRE:
|
||||||
|
bundle.putString(Constants.DOWNLOAD_TYPE_GENRE, grouped.get(getBindingAdapterPosition()).getGenre());
|
||||||
|
click.onGenreClick(bundle);
|
||||||
|
break;
|
||||||
|
case Constants.DOWNLOAD_TYPE_YEAR:
|
||||||
|
bundle.putString(Constants.DOWNLOAD_TYPE_YEAR, grouped.get(getBindingAdapterPosition()).getYear().toString());
|
||||||
|
click.onYearClick(bundle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean onLongClick() {
|
private boolean onLongClick() {
|
||||||
Bundle bundle = new Bundle();
|
Bundle bundle = new Bundle();
|
||||||
bundle.putParcelable(Constants.TRACK_OBJECT, songs.get(getBindingAdapterPosition()));
|
|
||||||
|
|
||||||
click.onMediaLongClick(bundle);
|
switch (view) {
|
||||||
|
case Constants.DOWNLOAD_TYPE_TRACK:
|
||||||
|
bundle.putParcelable(Constants.TRACK_OBJECT, grouped.get(getBindingAdapterPosition()));
|
||||||
|
click.onMediaLongClick(bundle);
|
||||||
|
return true;
|
||||||
|
case Constants.DOWNLOAD_TYPE_ALBUM:
|
||||||
|
bundle.putString(Constants.DOWNLOAD_TYPE_ALBUM, grouped.get(getBindingAdapterPosition()).getAlbumId());
|
||||||
|
click.onAlbumLongClick(bundle);
|
||||||
|
return true;
|
||||||
|
case Constants.DOWNLOAD_TYPE_ARTIST:
|
||||||
|
bundle.putString(Constants.DOWNLOAD_TYPE_ARTIST, grouped.get(getBindingAdapterPosition()).getArtistId());
|
||||||
|
click.onArtistLongClick(bundle);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import android.os.Bundle;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.PopupMenu;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
@ -19,8 +20,10 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import com.cappielloantonio.tempo.R;
|
import com.cappielloantonio.tempo.R;
|
||||||
import com.cappielloantonio.tempo.databinding.FragmentDownloadBinding;
|
import com.cappielloantonio.tempo.databinding.FragmentDownloadBinding;
|
||||||
import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
||||||
|
import com.cappielloantonio.tempo.model.DownloadStack;
|
||||||
import com.cappielloantonio.tempo.service.MediaManager;
|
import com.cappielloantonio.tempo.service.MediaManager;
|
||||||
import com.cappielloantonio.tempo.service.MediaService;
|
import com.cappielloantonio.tempo.service.MediaService;
|
||||||
|
import com.cappielloantonio.tempo.subsonic.models.Child;
|
||||||
import com.cappielloantonio.tempo.ui.activity.MainActivity;
|
import com.cappielloantonio.tempo.ui.activity.MainActivity;
|
||||||
import com.cappielloantonio.tempo.ui.adapter.DownloadHorizontalAdapter;
|
import com.cappielloantonio.tempo.ui.adapter.DownloadHorizontalAdapter;
|
||||||
import com.cappielloantonio.tempo.util.Constants;
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
|
|
@ -28,6 +31,7 @@ import com.cappielloantonio.tempo.viewmodel.DownloadViewModel;
|
||||||
import com.google.android.material.appbar.MaterialToolbar;
|
import com.google.android.material.appbar.MaterialToolbar;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
@UnstableApi
|
@UnstableApi
|
||||||
|
|
@ -59,7 +63,7 @@ public class DownloadFragment extends Fragment implements ClickCallback {
|
||||||
super.onViewCreated(view, savedInstanceState);
|
super.onViewCreated(view, savedInstanceState);
|
||||||
|
|
||||||
initAppBar();
|
initAppBar();
|
||||||
initDownloadedSongView();
|
initDownloadedView();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -90,11 +94,12 @@ public class DownloadFragment extends Fragment implements ClickCallback {
|
||||||
Objects.requireNonNull(materialToolbar.getOverflowIcon()).setTint(requireContext().getResources().getColor(R.color.titleTextColor, null));
|
Objects.requireNonNull(materialToolbar.getOverflowIcon()).setTint(requireContext().getResources().getColor(R.color.titleTextColor, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initDownloadedSongView() {
|
private void initDownloadedView() {
|
||||||
bind.downloadedTracksRecyclerView.setHasFixedSize(true);
|
bind.downloadedRecyclerView.setHasFixedSize(true);
|
||||||
|
|
||||||
downloadHorizontalAdapter = new DownloadHorizontalAdapter(this);
|
downloadHorizontalAdapter = new DownloadHorizontalAdapter(this);
|
||||||
bind.downloadedTracksRecyclerView.setAdapter(downloadHorizontalAdapter);
|
bind.downloadedRecyclerView.setAdapter(downloadHorizontalAdapter);
|
||||||
|
|
||||||
downloadViewModel.getDownloadedTracks(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), songs -> {
|
downloadViewModel.getDownloadedTracks(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), songs -> {
|
||||||
if (songs != null) {
|
if (songs != null) {
|
||||||
if (songs.isEmpty()) {
|
if (songs.isEmpty()) {
|
||||||
|
|
@ -102,26 +107,87 @@ public class DownloadFragment extends Fragment implements ClickCallback {
|
||||||
bind.emptyDownloadLayout.setVisibility(View.VISIBLE);
|
bind.emptyDownloadLayout.setVisibility(View.VISIBLE);
|
||||||
bind.fragmentDownloadNestedScrollView.setVisibility(View.GONE);
|
bind.fragmentDownloadNestedScrollView.setVisibility(View.GONE);
|
||||||
|
|
||||||
bind.downloadDownloadedTracksPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
bind.downloadDownloadedPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||||
bind.downloadDownloadedTracksSector.setVisibility(View.GONE);
|
bind.downloadDownloadedSector.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
bind.downloadedGroupByImageView.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (bind != null) {
|
if (bind != null) {
|
||||||
bind.emptyDownloadLayout.setVisibility(View.GONE);
|
bind.emptyDownloadLayout.setVisibility(View.GONE);
|
||||||
bind.fragmentDownloadNestedScrollView.setVisibility(View.VISIBLE);
|
bind.fragmentDownloadNestedScrollView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
bind.downloadDownloadedTracksPlaceholder.placeholder.setVisibility(View.GONE);
|
bind.downloadDownloadedPlaceholder.placeholder.setVisibility(View.GONE);
|
||||||
bind.downloadDownloadedTracksSector.setVisibility(View.VISIBLE);
|
bind.downloadDownloadedSector.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
bind.downloadedTracksRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
bind.downloadedGroupByImageView.setVisibility(View.VISIBLE);
|
||||||
|
|
||||||
downloadHorizontalAdapter.setItems(songs);
|
finishDownloadView(songs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (bind != null) bind.loadingProgressBar.setVisibility(View.GONE);
|
if (bind != null) bind.loadingProgressBar.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
bind.downloadedGroupByImageView.setOnClickListener(view -> showPopupMenu(view, R.menu.download_popup_menu));
|
||||||
|
bind.downloadedGoBackImageView.setOnClickListener(view -> downloadViewModel.popViewStack());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void finishDownloadView(List<Child> songs) {
|
||||||
|
downloadViewModel.getViewStack().observe(getViewLifecycleOwner(), stack -> {
|
||||||
|
bind.downloadedRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext()));
|
||||||
|
|
||||||
|
DownloadStack lastLevel = stack.get(stack.size() - 1);
|
||||||
|
|
||||||
|
switch (lastLevel.getId()) {
|
||||||
|
case Constants.DOWNLOAD_TYPE_TRACK:
|
||||||
|
downloadHorizontalAdapter.setItems(Constants.DOWNLOAD_TYPE_TRACK, lastLevel.getId(), lastLevel.getView(), songs);
|
||||||
|
break;
|
||||||
|
case Constants.DOWNLOAD_TYPE_ALBUM:
|
||||||
|
downloadHorizontalAdapter.setItems(Constants.DOWNLOAD_TYPE_TRACK, lastLevel.getId(), lastLevel.getView(), songs);
|
||||||
|
break;
|
||||||
|
case Constants.DOWNLOAD_TYPE_ARTIST:
|
||||||
|
downloadHorizontalAdapter.setItems(Constants.DOWNLOAD_TYPE_ALBUM, lastLevel.getId(), lastLevel.getView(), songs);
|
||||||
|
break;
|
||||||
|
case Constants.DOWNLOAD_TYPE_GENRE:
|
||||||
|
downloadHorizontalAdapter.setItems(Constants.DOWNLOAD_TYPE_TRACK, lastLevel.getId(), lastLevel.getView(), songs);
|
||||||
|
break;
|
||||||
|
case Constants.DOWNLOAD_TYPE_YEAR:
|
||||||
|
downloadHorizontalAdapter.setItems(Constants.DOWNLOAD_TYPE_TRACK, lastLevel.getId(), lastLevel.getView(), songs);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bind.downloadedGoBackImageView.setVisibility(stack.size() > 1 ? View.VISIBLE : View.GONE);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showPopupMenu(View view, int menuResource) {
|
||||||
|
PopupMenu popup = new PopupMenu(requireContext(), view);
|
||||||
|
popup.getMenuInflater().inflate(menuResource, popup.getMenu());
|
||||||
|
|
||||||
|
popup.setOnMenuItemClickListener(menuItem -> {
|
||||||
|
if (menuItem.getItemId() == R.id.menu_download_group_by_track) {
|
||||||
|
downloadViewModel.initViewStack(new DownloadStack(Constants.DOWNLOAD_TYPE_TRACK, null));
|
||||||
|
return true;
|
||||||
|
} else if (menuItem.getItemId() == R.id.menu_download_group_by_album) {
|
||||||
|
downloadViewModel.initViewStack(new DownloadStack(Constants.DOWNLOAD_TYPE_ALBUM, null));
|
||||||
|
return true;
|
||||||
|
} else if (menuItem.getItemId() == R.id.menu_download_group_by_artist) {
|
||||||
|
downloadViewModel.initViewStack(new DownloadStack(Constants.DOWNLOAD_TYPE_ARTIST, null));
|
||||||
|
return true;
|
||||||
|
} else if (menuItem.getItemId() == R.id.menu_download_group_by_genre) {
|
||||||
|
downloadViewModel.initViewStack(new DownloadStack(Constants.DOWNLOAD_TYPE_GENRE, null));
|
||||||
|
return true;
|
||||||
|
} else if (menuItem.getItemId() == R.id.menu_download_group_by_year) {
|
||||||
|
downloadViewModel.initViewStack(new DownloadStack(Constants.DOWNLOAD_TYPE_YEAR, null));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
popup.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializeMediaBrowser() {
|
private void initializeMediaBrowser() {
|
||||||
|
|
@ -132,6 +198,26 @@ public class DownloadFragment extends Fragment implements ClickCallback {
|
||||||
MediaBrowser.releaseFuture(mediaBrowserListenableFuture);
|
MediaBrowser.releaseFuture(mediaBrowserListenableFuture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onYearClick(Bundle bundle) {
|
||||||
|
downloadViewModel.pushViewStack(new DownloadStack(Constants.DOWNLOAD_TYPE_YEAR, bundle.getString(Constants.DOWNLOAD_TYPE_YEAR)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onGenreClick(Bundle bundle) {
|
||||||
|
downloadViewModel.pushViewStack(new DownloadStack(Constants.DOWNLOAD_TYPE_GENRE, bundle.getString(Constants.DOWNLOAD_TYPE_GENRE)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onArtistClick(Bundle bundle) {
|
||||||
|
downloadViewModel.pushViewStack(new DownloadStack(Constants.DOWNLOAD_TYPE_ARTIST, bundle.getString(Constants.DOWNLOAD_TYPE_ARTIST)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAlbumClick(Bundle bundle) {
|
||||||
|
downloadViewModel.pushViewStack(new DownloadStack(Constants.DOWNLOAD_TYPE_ALBUM, bundle.getString(Constants.DOWNLOAD_TYPE_ALBUM)));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMediaClick(Bundle bundle) {
|
public void onMediaClick(Bundle bundle) {
|
||||||
MediaManager.startQueue(mediaBrowserListenableFuture, bundle.getParcelableArrayList(Constants.TRACKS_OBJECT), bundle.getInt(Constants.ITEM_POSITION));
|
MediaManager.startQueue(mediaBrowserListenableFuture, bundle.getParcelableArrayList(Constants.TRACKS_OBJECT), bundle.getInt(Constants.ITEM_POSITION));
|
||||||
|
|
|
||||||
17
app/src/main/java/com/cappielloantonio/tempo/util/Util.java
Normal file
17
app/src/main/java/com/cappielloantonio/tempo/util/Util.java
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.cappielloantonio.tempo.util;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
public class Util {
|
||||||
|
public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
|
||||||
|
try {
|
||||||
|
Map<Object, Boolean> uniqueMap = new ConcurrentHashMap<>();
|
||||||
|
return t -> uniqueMap.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null;
|
||||||
|
} catch (NullPointerException exception) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -8,27 +8,55 @@ import androidx.lifecycle.LifecycleOwner;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MutableLiveData;
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import com.cappielloantonio.tempo.model.DownloadStack;
|
||||||
import com.cappielloantonio.tempo.repository.DownloadRepository;
|
import com.cappielloantonio.tempo.repository.DownloadRepository;
|
||||||
import com.cappielloantonio.tempo.subsonic.models.Child;
|
import com.cappielloantonio.tempo.subsonic.models.Child;
|
||||||
|
import com.cappielloantonio.tempo.util.Constants;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
public class DownloadViewModel extends AndroidViewModel {
|
public class DownloadViewModel extends AndroidViewModel {
|
||||||
private static final String TAG = "HomeViewModel";
|
private static final String TAG = "DownloadViewModel";
|
||||||
|
|
||||||
private final DownloadRepository downloadRepository;
|
private final DownloadRepository downloadRepository;
|
||||||
|
|
||||||
private final MutableLiveData<List<Child>> downloadedTrackSample = new MutableLiveData<>(null);
|
private final MutableLiveData<List<Child>> downloadedTrackSample = new MutableLiveData<>(null);
|
||||||
|
private final MutableLiveData<ArrayList<DownloadStack>> viewStack = new MutableLiveData<>(null);
|
||||||
|
|
||||||
public DownloadViewModel(@NonNull Application application) {
|
public DownloadViewModel(@NonNull Application application) {
|
||||||
super(application);
|
super(application);
|
||||||
|
|
||||||
downloadRepository = new DownloadRepository();
|
downloadRepository = new DownloadRepository();
|
||||||
|
|
||||||
|
initViewStack(new DownloadStack(Constants.DOWNLOAD_TYPE_TRACK, null));
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<Child>> getDownloadedTracks(LifecycleOwner owner) {
|
public LiveData<List<Child>> getDownloadedTracks(LifecycleOwner owner) {
|
||||||
downloadRepository.getLiveDownload().observe(owner, downloads -> downloadedTrackSample.postValue(downloads.stream().map(download -> (Child) download).collect(Collectors.toList())));
|
downloadRepository.getLiveDownload().observe(owner, downloads -> downloadedTrackSample.postValue(downloads.stream().map(download -> (Child) download).collect(Collectors.toList())));
|
||||||
return downloadedTrackSample;
|
return downloadedTrackSample;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiveData<ArrayList<DownloadStack>> getViewStack() {
|
||||||
|
return viewStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initViewStack(DownloadStack level) {
|
||||||
|
ArrayList<DownloadStack> stack = new ArrayList<>();
|
||||||
|
stack.add(level);
|
||||||
|
viewStack.setValue(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void pushViewStack(DownloadStack level) {
|
||||||
|
ArrayList<DownloadStack> stack = viewStack.getValue();
|
||||||
|
stack.add(level);
|
||||||
|
viewStack.setValue(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void popViewStack() {
|
||||||
|
ArrayList<DownloadStack> stack = viewStack.getValue();
|
||||||
|
stack.remove(stack.size() - 1);
|
||||||
|
viewStack.setValue(stack);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,45 +62,67 @@
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||||
|
|
||||||
<LinearLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
android:id="@+id/download_linear_layout_container"
|
android:id="@+id/download_downloaded_sector"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical"
|
android:paddingHorizontal="16dp"
|
||||||
|
android:paddingTop="16dp"
|
||||||
android:paddingBottom="@dimen/global_padding_bottom">
|
android:paddingBottom="@dimen/global_padding_bottom">
|
||||||
|
|
||||||
<!-- Downloaded tracks -->
|
<TextView
|
||||||
<LinearLayout
|
android:id="@+id/downloaded_text_view_refreshable"
|
||||||
android:id="@+id/download_downloaded_tracks_sector"
|
style="@style/TitleLarge"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/download_title_section"
|
||||||
|
android:layout_marginBottom="16dp"
|
||||||
|
app:layout_constraintEnd_toStartOf="@+id/downloaded_go_back_image_view"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/downloaded_go_back_image_view"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_marginHorizontal="12dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@drawable/ic_arrow_back"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/downloaded_text_view_refreshable"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/downloaded_group_by_image_view"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/downloaded_text_view_refreshable" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/downloaded_group_by_image_view"
|
||||||
|
android:layout_width="24dp"
|
||||||
|
android:layout_height="24dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@drawable/ic_filter_list"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/downloaded_text_view_refreshable"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/downloaded_text_view_refreshable" />
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/downloaded_recycler_view"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="vertical">
|
android:clipToPadding="false"
|
||||||
|
android:nestedScrollingEnabled="false"
|
||||||
<TextView
|
android:paddingBottom="8dp"
|
||||||
android:id="@+id/downloaded_tracks_text_view_refreshable"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
style="@style/TitleLarge"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
android:layout_width="match_parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
android:layout_height="wrap_content"
|
app:layout_constraintTop_toBottomOf="@id/downloaded_text_view_refreshable" />
|
||||||
android:layout_marginBottom="8dp"
|
|
||||||
android:paddingStart="16dp"
|
|
||||||
android:paddingTop="16dp"
|
|
||||||
android:paddingEnd="16dp"
|
|
||||||
android:text="@string/download_title_section" />
|
|
||||||
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/downloaded_tracks_recycler_view"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:clipToPadding="false"
|
|
||||||
android:nestedScrollingEnabled="false"
|
|
||||||
android:paddingBottom="8dp" />
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
<include
|
<include
|
||||||
android:id="@+id/download_downloaded_tracks_placeholder"
|
android:id="@+id/download_downloaded_placeholder"
|
||||||
layout="@layout/item_placeholder_horizontal"
|
layout="@layout/item_placeholder_horizontal"
|
||||||
android:visibility="gone" />
|
android:visibility="gone"
|
||||||
</LinearLayout>
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/downloaded_text_view_refreshable" />
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
</androidx.core.widget.NestedScrollView>
|
</androidx.core.widget.NestedScrollView>
|
||||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,7 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:clipChildren="false"
|
android:clipChildren="false"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal">
|
||||||
android:paddingStart="16dp">
|
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/divider"
|
android:id="@+id/divider"
|
||||||
|
|
@ -17,7 +16,7 @@
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/downloaded_song_album_text_view"
|
android:id="@+id/downloaded_item_pre_text_view"
|
||||||
style="@style/LabelExtraSmall"
|
style="@style/LabelExtraSmall"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -28,8 +27,20 @@
|
||||||
android:layout_gravity="center_vertical" />
|
android:layout_gravity="center_vertical" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/item_cover_image_view"
|
||||||
|
android:layout_width="52dp"
|
||||||
|
android:layout_height="52dp"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_marginTop="8dp"
|
||||||
|
android:layout_marginEnd="12dp"
|
||||||
|
app:layout_constraintEnd_toStartOf="@id/downloaded_item_title_text_view"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/divider" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/downloaded_song_title_text_view"
|
android:id="@+id/downloaded_item_title_text_view"
|
||||||
style="@style/LabelMedium"
|
style="@style/LabelMedium"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -37,12 +48,14 @@
|
||||||
android:paddingEnd="12dp"
|
android:paddingEnd="12dp"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:text="@string/label_placeholder"
|
android:text="@string/label_placeholder"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/downloaded_song_more_button"
|
app:layout_constraintVertical_chainStyle="packed"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintEnd_toStartOf="@+id/downloaded_item_more_button"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/divider" />
|
app:layout_constraintStart_toEndOf="@+id/item_cover_image_view"
|
||||||
|
app:layout_constraintTop_toTopOf="@+id/item_cover_image_view"
|
||||||
|
app:layout_constraintBottom_toTopOf="@id/downloaded_item_subtitle_text_view"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/downloaded_song_artist_text_view"
|
android:id="@+id/downloaded_item_subtitle_text_view"
|
||||||
style="@style/LabelSmall"
|
style="@style/LabelSmall"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
|
@ -51,16 +64,15 @@
|
||||||
android:paddingBottom="6dp"
|
android:paddingBottom="6dp"
|
||||||
android:singleLine="true"
|
android:singleLine="true"
|
||||||
android:text="@string/label_placeholder"
|
android:text="@string/label_placeholder"
|
||||||
app:layout_constraintEnd_toStartOf="@+id/downloaded_song_more_button"
|
app:layout_constraintTop_toBottomOf="@id/downloaded_item_title_text_view"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintEnd_toStartOf="@+id/downloaded_item_more_button"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/downloaded_song_title_text_view" />
|
app:layout_constraintStart_toStartOf="@+id/downloaded_item_title_text_view"
|
||||||
|
app:layout_constraintBottom_toBottomOf="@+id/item_cover_image_view" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/downloaded_song_more_button"
|
android:id="@+id/downloaded_item_more_button"
|
||||||
android:layout_width="18dp"
|
android:layout_width="18dp"
|
||||||
android:layout_height="18dp"
|
android:layout_height="18dp"
|
||||||
android:layout_marginHorizontal="12dp"
|
|
||||||
android:layout_marginTop="10dp"
|
|
||||||
android:background="@drawable/ic_more_vert"
|
android:background="@drawable/ic_more_vert"
|
||||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,8 @@
|
||||||
<string name="delete_download_storage_dialog_title">Delete saved items</string>
|
<string name="delete_download_storage_dialog_title">Delete saved items</string>
|
||||||
<string name="download_info_empty_subtitle">Once you download a song, you\'ll find it here</string>
|
<string name="download_info_empty_subtitle">Once you download a song, you\'ll find it here</string>
|
||||||
<string name="download_info_empty_title">No downloads yet!</string>
|
<string name="download_info_empty_title">No downloads yet!</string>
|
||||||
|
<string name="download_item_multiple_subtitle_formatter">%1$s • %2$s items</string>
|
||||||
|
<string name="download_item_single_subtitle_formatter">%1$s items</string>
|
||||||
<string name="download_title_section">Downloads</string>
|
<string name="download_title_section">Downloads</string>
|
||||||
<string name="download_storage_internal_dialog_negative_button">Internal</string>
|
<string name="download_storage_internal_dialog_negative_button">Internal</string>
|
||||||
<string name="download_storage_external_dialog_positive_button">External</string>
|
<string name="download_storage_external_dialog_positive_button">External</string>
|
||||||
|
|
@ -280,4 +282,9 @@
|
||||||
<string name="description_empty_title">No description available</string>
|
<string name="description_empty_title">No description available</string>
|
||||||
<string name="menu_filter_download">Downloaded</string>
|
<string name="menu_filter_download">Downloaded</string>
|
||||||
<string name="menu_filter_all">All</string>
|
<string name="menu_filter_all">All</string>
|
||||||
|
<string name="menu_group_by_track">Track</string>
|
||||||
|
<string name="menu_group_by_album">Album</string>
|
||||||
|
<string name="menu_group_by_artist">Artist</string>
|
||||||
|
<string name="menu_group_by_genre">Genre</string>
|
||||||
|
<string name="menu_group_by_year">Year</string>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
Add table
Add a link
Reference in a new issue