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
|
||||
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.databinding.ItemHorizontalDownloadBinding;
|
||||
import com.cappielloantonio.tempo.glide.CustomGlideRequest;
|
||||
import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
||||
import com.cappielloantonio.tempo.subsonic.models.Child;
|
||||
import com.cappielloantonio.tempo.util.Constants;
|
||||
import com.cappielloantonio.tempo.util.MusicUtil;
|
||||
import com.cappielloantonio.tempo.util.Util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@UnstableApi
|
||||
public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHorizontalAdapter.ViewHolder> {
|
||||
private final ClickCallback click;
|
||||
|
||||
private String view;
|
||||
private String filterKey;
|
||||
private String filterValue;
|
||||
|
||||
private List<Child> songs;
|
||||
private List<Child> grouped;
|
||||
|
||||
public DownloadHorizontalAdapter(ClickCallback click) {
|
||||
this.click = click;
|
||||
this.view = Constants.DOWNLOAD_TYPE_TRACK;
|
||||
this.songs = Collections.emptyList();
|
||||
this.grouped = Collections.emptyList();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
|
|
@ -41,31 +51,43 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHori
|
|||
|
||||
@Override
|
||||
public void onBindViewHolder(ViewHolder holder, int position) {
|
||||
Child song = songs.get(position);
|
||||
|
||||
holder.item.downloadedSongTitleTextView.setText(MusicUtil.getReadableString(song.getTitle()));
|
||||
holder.item.downloadedSongArtistTextView.setText(holder.itemView.getContext().getString(R.string.song_subtitle_formatter, MusicUtil.getReadableString(song.getArtist()), MusicUtil.getReadableDurationString(song.getDuration(), false)));
|
||||
holder.item.downloadedSongAlbumTextView.setText(MusicUtil.getReadableString(song.getAlbum()));
|
||||
|
||||
if (position > 0 && songs.get(position - 1) != null && !Objects.equals(songs.get(position - 1).getAlbum(), songs.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);
|
||||
switch (view) {
|
||||
case Constants.DOWNLOAD_TYPE_TRACK:
|
||||
initTrackLayout(holder, position);
|
||||
break;
|
||||
case Constants.DOWNLOAD_TYPE_ALBUM:
|
||||
initAlbumLayout(holder, position);
|
||||
break;
|
||||
case Constants.DOWNLOAD_TYPE_ARTIST:
|
||||
initArtistLayout(holder, position);
|
||||
break;
|
||||
case Constants.DOWNLOAD_TYPE_GENRE:
|
||||
initGenreLayout(holder, position);
|
||||
break;
|
||||
case Constants.DOWNLOAD_TYPE_YEAR:
|
||||
initYearLayout(holder, position);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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.grouped = groupSong(songs);
|
||||
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
|
||||
public Child getItem(int id) {
|
||||
return songs.get(id);
|
||||
return grouped.get(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -78,6 +100,145 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHori
|
|||
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 {
|
||||
ItemHorizontalDownloadBinding item;
|
||||
|
||||
|
|
@ -86,30 +247,62 @@ public class DownloadHorizontalAdapter extends RecyclerView.Adapter<DownloadHori
|
|||
|
||||
this.item = item;
|
||||
|
||||
item.downloadedSongTitleTextView.setSelected(true);
|
||||
item.downloadedSongArtistTextView.setSelected(true);
|
||||
item.downloadedItemTitleTextView.setSelected(true);
|
||||
item.downloadedItemSubtitleTextView.setSelected(true);
|
||||
|
||||
itemView.setOnClickListener(v -> onClick());
|
||||
itemView.setOnLongClickListener(v -> onLongClick());
|
||||
|
||||
item.downloadedSongMoreButton.setOnClickListener(v -> onLongClick());
|
||||
item.downloadedItemMoreButton.setOnClickListener(v -> onLongClick());
|
||||
}
|
||||
|
||||
public void onClick() {
|
||||
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() {
|
||||
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.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.PopupMenu;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
|
@ -19,8 +20,10 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
|||
import com.cappielloantonio.tempo.R;
|
||||
import com.cappielloantonio.tempo.databinding.FragmentDownloadBinding;
|
||||
import com.cappielloantonio.tempo.interfaces.ClickCallback;
|
||||
import com.cappielloantonio.tempo.model.DownloadStack;
|
||||
import com.cappielloantonio.tempo.service.MediaManager;
|
||||
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.adapter.DownloadHorizontalAdapter;
|
||||
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.common.util.concurrent.ListenableFuture;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@UnstableApi
|
||||
|
|
@ -59,7 +63,7 @@ public class DownloadFragment extends Fragment implements ClickCallback {
|
|||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
initAppBar();
|
||||
initDownloadedSongView();
|
||||
initDownloadedView();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -90,11 +94,12 @@ public class DownloadFragment extends Fragment implements ClickCallback {
|
|||
Objects.requireNonNull(materialToolbar.getOverflowIcon()).setTint(requireContext().getResources().getColor(R.color.titleTextColor, null));
|
||||
}
|
||||
|
||||
private void initDownloadedSongView() {
|
||||
bind.downloadedTracksRecyclerView.setHasFixedSize(true);
|
||||
private void initDownloadedView() {
|
||||
bind.downloadedRecyclerView.setHasFixedSize(true);
|
||||
|
||||
downloadHorizontalAdapter = new DownloadHorizontalAdapter(this);
|
||||
bind.downloadedTracksRecyclerView.setAdapter(downloadHorizontalAdapter);
|
||||
bind.downloadedRecyclerView.setAdapter(downloadHorizontalAdapter);
|
||||
|
||||
downloadViewModel.getDownloadedTracks(getViewLifecycleOwner()).observe(getViewLifecycleOwner(), songs -> {
|
||||
if (songs != null) {
|
||||
if (songs.isEmpty()) {
|
||||
|
|
@ -102,26 +107,87 @@ public class DownloadFragment extends Fragment implements ClickCallback {
|
|||
bind.emptyDownloadLayout.setVisibility(View.VISIBLE);
|
||||
bind.fragmentDownloadNestedScrollView.setVisibility(View.GONE);
|
||||
|
||||
bind.downloadDownloadedTracksPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
bind.downloadDownloadedTracksSector.setVisibility(View.GONE);
|
||||
bind.downloadDownloadedPlaceholder.placeholder.setVisibility(View.VISIBLE);
|
||||
bind.downloadDownloadedSector.setVisibility(View.GONE);
|
||||
|
||||
bind.downloadedGroupByImageView.setVisibility(View.GONE);
|
||||
}
|
||||
} else {
|
||||
if (bind != null) {
|
||||
bind.emptyDownloadLayout.setVisibility(View.GONE);
|
||||
bind.fragmentDownloadNestedScrollView.setVisibility(View.VISIBLE);
|
||||
|
||||
bind.downloadDownloadedTracksPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
bind.downloadDownloadedTracksSector.setVisibility(View.VISIBLE);
|
||||
bind.downloadDownloadedPlaceholder.placeholder.setVisibility(View.GONE);
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
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() {
|
||||
|
|
@ -132,6 +198,26 @@ public class DownloadFragment extends Fragment implements ClickCallback {
|
|||
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
|
||||
public void onMediaClick(Bundle bundle) {
|
||||
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.MutableLiveData;
|
||||
|
||||
import com.cappielloantonio.tempo.model.DownloadStack;
|
||||
import com.cappielloantonio.tempo.repository.DownloadRepository;
|
||||
import com.cappielloantonio.tempo.subsonic.models.Child;
|
||||
import com.cappielloantonio.tempo.util.Constants;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DownloadViewModel extends AndroidViewModel {
|
||||
private static final String TAG = "HomeViewModel";
|
||||
private static final String TAG = "DownloadViewModel";
|
||||
|
||||
private final DownloadRepository downloadRepository;
|
||||
|
||||
private final MutableLiveData<List<Child>> downloadedTrackSample = new MutableLiveData<>(null);
|
||||
private final MutableLiveData<ArrayList<DownloadStack>> viewStack = new MutableLiveData<>(null);
|
||||
|
||||
public DownloadViewModel(@NonNull Application application) {
|
||||
super(application);
|
||||
|
||||
downloadRepository = new DownloadRepository();
|
||||
|
||||
initViewStack(new DownloadStack(Constants.DOWNLOAD_TYPE_TRACK, null));
|
||||
}
|
||||
|
||||
public LiveData<List<Child>> getDownloadedTracks(LifecycleOwner owner) {
|
||||
downloadRepository.getLiveDownload().observe(owner, downloads -> downloadedTrackSample.postValue(downloads.stream().map(download -> (Child) download).collect(Collectors.toList())));
|
||||
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"
|
||||
app:layout_behavior="@string/appbar_scrolling_view_behavior">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/download_linear_layout_container"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/download_downloaded_sector"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingHorizontal="16dp"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingBottom="@dimen/global_padding_bottom">
|
||||
|
||||
<!-- Downloaded tracks -->
|
||||
<LinearLayout
|
||||
android:id="@+id/download_downloaded_tracks_sector"
|
||||
<TextView
|
||||
android:id="@+id/downloaded_text_view_refreshable"
|
||||
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_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/downloaded_tracks_text_view_refreshable"
|
||||
style="@style/TitleLarge"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
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>
|
||||
android:clipToPadding="false"
|
||||
android:nestedScrollingEnabled="false"
|
||||
android:paddingBottom="8dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/downloaded_text_view_refreshable" />
|
||||
|
||||
<include
|
||||
android:id="@+id/download_downloaded_tracks_placeholder"
|
||||
android:id="@+id/download_downloaded_placeholder"
|
||||
layout="@layout/item_placeholder_horizontal"
|
||||
android:visibility="gone" />
|
||||
</LinearLayout>
|
||||
android:visibility="gone"
|
||||
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.coordinatorlayout.widget.CoordinatorLayout>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipChildren="false"
|
||||
android:orientation="horizontal"
|
||||
android:paddingStart="16dp">
|
||||
android:orientation="horizontal">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/divider"
|
||||
|
|
@ -17,7 +16,7 @@
|
|||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/downloaded_song_album_text_view"
|
||||
android:id="@+id/downloaded_item_pre_text_view"
|
||||
style="@style/LabelExtraSmall"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
@ -28,8 +27,20 @@
|
|||
android:layout_gravity="center_vertical" />
|
||||
</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
|
||||
android:id="@+id/downloaded_song_title_text_view"
|
||||
android:id="@+id/downloaded_item_title_text_view"
|
||||
style="@style/LabelMedium"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
@ -37,12 +48,14 @@
|
|||
android:paddingEnd="12dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/label_placeholder"
|
||||
app:layout_constraintEnd_toStartOf="@+id/downloaded_song_more_button"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/divider" />
|
||||
app:layout_constraintVertical_chainStyle="packed"
|
||||
app:layout_constraintEnd_toStartOf="@+id/downloaded_item_more_button"
|
||||
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
|
||||
android:id="@+id/downloaded_song_artist_text_view"
|
||||
android:id="@+id/downloaded_item_subtitle_text_view"
|
||||
style="@style/LabelSmall"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
|
|
@ -51,16 +64,15 @@
|
|||
android:paddingBottom="6dp"
|
||||
android:singleLine="true"
|
||||
android:text="@string/label_placeholder"
|
||||
app:layout_constraintEnd_toStartOf="@+id/downloaded_song_more_button"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/downloaded_song_title_text_view" />
|
||||
app:layout_constraintTop_toBottomOf="@id/downloaded_item_title_text_view"
|
||||
app:layout_constraintEnd_toStartOf="@+id/downloaded_item_more_button"
|
||||
app:layout_constraintStart_toStartOf="@+id/downloaded_item_title_text_view"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/item_cover_image_view" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/downloaded_song_more_button"
|
||||
android:id="@+id/downloaded_item_more_button"
|
||||
android:layout_width="18dp"
|
||||
android:layout_height="18dp"
|
||||
android:layout_marginHorizontal="12dp"
|
||||
android:layout_marginTop="10dp"
|
||||
android:background="@drawable/ic_more_vert"
|
||||
android:foreground="?android:attr/selectableItemBackgroundBorderless"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
|
|
|||
|
|
@ -55,6 +55,8 @@
|
|||
<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_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_storage_internal_dialog_negative_button">Internal</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="menu_filter_download">Downloaded</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>
|
||||
Loading…
Add table
Add a link
Reference in a new issue