diff --git a/app/src/main/java/com/cappielloantonio/tempo/model/Download.kt b/app/src/main/java/com/cappielloantonio/tempo/model/Download.kt index 76e3e915..1cad76cc 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/model/Download.kt +++ b/app/src/main/java/com/cappielloantonio/tempo/model/Download.kt @@ -52,4 +52,10 @@ class Download(@PrimaryKey override val id: String) : Child(id) { originalWidth = child.originalWidth originalHeight = child.originalHeight } -} \ No newline at end of file +} + +@Keep +data class DownloadStack( + var id: String, + var view: String? +) \ No newline at end of file diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/DownloadHorizontalAdapter.java b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/DownloadHorizontalAdapter.java index 90cbf207..fecfe3ac 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/DownloadHorizontalAdapter.java +++ b/app/src/main/java/com/cappielloantonio/tempo/ui/adapter/DownloadHorizontalAdapter.java @@ -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 { private final ClickCallback click; + private String view; + private String filterKey; + private String filterValue; + private List songs; + private List 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 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 songs) { + public void setItems(String view, String filterKey, String filterValue, List 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 groupSong(List 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 filterSong(String filterKey, String filterValue, List 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 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 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; } } } diff --git a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/DownloadFragment.java b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/DownloadFragment.java index 36c46420..6abd6d05 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/DownloadFragment.java +++ b/app/src/main/java/com/cappielloantonio/tempo/ui/fragment/DownloadFragment.java @@ -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 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)); diff --git a/app/src/main/java/com/cappielloantonio/tempo/util/Util.java b/app/src/main/java/com/cappielloantonio/tempo/util/Util.java new file mode 100644 index 00000000..32a1bd05 --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/tempo/util/Util.java @@ -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 Predicate distinctByKey(Function keyExtractor) { + try { + Map uniqueMap = new ConcurrentHashMap<>(); + return t -> uniqueMap.putIfAbsent(keyExtractor.apply(t), Boolean.TRUE) == null; + } catch (NullPointerException exception) { + return null; + } + } +} diff --git a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/DownloadViewModel.java b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/DownloadViewModel.java index 234528d7..4484f3fc 100644 --- a/app/src/main/java/com/cappielloantonio/tempo/viewmodel/DownloadViewModel.java +++ b/app/src/main/java/com/cappielloantonio/tempo/viewmodel/DownloadViewModel.java @@ -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> downloadedTrackSample = new MutableLiveData<>(null); + private final MutableLiveData> viewStack = new MutableLiveData<>(null); public DownloadViewModel(@NonNull Application application) { super(application); downloadRepository = new DownloadRepository(); + + initViewStack(new DownloadStack(Constants.DOWNLOAD_TYPE_TRACK, null)); } public LiveData> getDownloadedTracks(LifecycleOwner owner) { downloadRepository.getLiveDownload().observe(owner, downloads -> downloadedTrackSample.postValue(downloads.stream().map(download -> (Child) download).collect(Collectors.toList()))); return downloadedTrackSample; } + + public LiveData> getViewStack() { + return viewStack; + } + + public void initViewStack(DownloadStack level) { + ArrayList stack = new ArrayList<>(); + stack.add(level); + viewStack.setValue(stack); + } + + public void pushViewStack(DownloadStack level) { + ArrayList stack = viewStack.getValue(); + stack.add(level); + viewStack.setValue(stack); + } + + public void popViewStack() { + ArrayList stack = viewStack.getValue(); + stack.remove(stack.size() - 1); + viewStack.setValue(stack); + } } diff --git a/app/src/main/res/layout/fragment_download.xml b/app/src/main/res/layout/fragment_download.xml index b0f87e5c..4326ac71 100644 --- a/app/src/main/res/layout/fragment_download.xml +++ b/app/src/main/res/layout/fragment_download.xml @@ -62,45 +62,67 @@ android:visibility="gone" app:layout_behavior="@string/appbar_scrolling_view_behavior"> - - - + + + + + + - - - - - + 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" /> - + android:visibility="gone" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/downloaded_text_view_refreshable" /> + + diff --git a/app/src/main/res/layout/item_horizontal_download.xml b/app/src/main/res/layout/item_horizontal_download.xml index deca1a0a..1e0d5d47 100644 --- a/app/src/main/res/layout/item_horizontal_download.xml +++ b/app/src/main/res/layout/item_horizontal_download.xml @@ -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"> + + + 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"/> + 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" /> Delete saved items Once you download a song, you\'ll find it here No downloads yet! + %1$s • %2$s items + %1$s items Downloads Internal External @@ -280,4 +282,9 @@ No description available Downloaded All + Track + Album + Artist + Genre + Year \ No newline at end of file