diff --git a/.idea/misc.xml b/.idea/misc.xml index 5ee1139f..b14a85af 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -40,7 +40,7 @@ - + @@ -83,7 +83,7 @@ - + @@ -92,7 +92,7 @@ - + @@ -104,7 +104,7 @@ - + @@ -120,8 +120,9 @@ + - + @@ -130,6 +131,7 @@ + diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistCatalogueAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistCatalogueAdapter.java deleted file mode 100644 index 1161ee06..00000000 --- a/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistCatalogueAdapter.java +++ /dev/null @@ -1,156 +0,0 @@ -package com.cappielloantonio.play.adapter; - -import android.content.Context; -import android.os.Bundle; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; -import android.view.inputmethod.InputMethodManager; -import android.widget.Filter; -import android.widget.Filterable; -import android.widget.ImageView; -import android.widget.TextView; - -import androidx.annotation.NonNull; -import androidx.navigation.Navigation; -import androidx.recyclerview.widget.RecyclerView; - -import com.cappielloantonio.play.R; -import com.cappielloantonio.play.glide.CustomGlideRequest; -import com.cappielloantonio.play.model.Playlist; -import com.cappielloantonio.play.ui.activity.MainActivity; -import com.cappielloantonio.play.ui.dialog.PlaylistEditorDialog; -import com.cappielloantonio.play.util.MusicUtil; - -import java.util.ArrayList; -import java.util.List; - -public class PlaylistCatalogueAdapter extends RecyclerView.Adapter implements Filterable { - private static final String TAG = "PlaylistCatalogueAdapter"; - - private final LayoutInflater mInflater; - private final MainActivity activity; - private final Context context; - private final boolean isOffline; - - - private final Filter filtering = new Filter() { - @Override - protected FilterResults performFiltering(CharSequence constraint) { - List filteredList = new ArrayList<>(); - - if (constraint == null || constraint.length() == 0) { - filteredList.addAll(playlistsFull); - } else { - String filterPattern = constraint.toString().toLowerCase().trim(); - - for (Playlist item : playlistsFull) { - if (item.getName().toLowerCase().contains(filterPattern)) { - filteredList.add(item); - } - } - } - - FilterResults results = new FilterResults(); - results.values = filteredList; - - return results; - } - - @Override - protected void publishResults(CharSequence constraint, FilterResults results) { - playlists.clear(); - playlists.addAll((List) results.values); - notifyDataSetChanged(); - } - }; - - private List playlists; - private List playlistsFull; - - public PlaylistCatalogueAdapter(MainActivity activity, Context context, boolean isOffline) { - this.activity = activity; - this.context = context; - this.mInflater = LayoutInflater.from(context); - this.playlists = new ArrayList<>(); - this.isOffline = isOffline; - } - - @NonNull - @Override - public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { - View view = mInflater.inflate(R.layout.item_library_catalogue_playlist, parent, false); - return new ViewHolder(view); - } - - @Override - public void onBindViewHolder(ViewHolder holder, int position) { - Playlist playlist = playlists.get(position); - - holder.textPlaylistName.setText(MusicUtil.getReadableString(playlist.getName())); - - CustomGlideRequest.Builder - .from(context, playlist.getPrimary(), CustomGlideRequest.PLAYLIST_PIC, null) - .build() - .into(holder.cover); - } - - @Override - public int getItemCount() { - return playlists.size(); - } - - public Playlist getItem(int position) { - return playlists.get(position); - } - - public void setItems(List playlists) { - this.playlists = playlists; - this.playlistsFull = new ArrayList<>(playlists); - notifyDataSetChanged(); - } - - @Override - public Filter getFilter() { - return filtering; - } - - public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { - TextView textPlaylistName; - ImageView cover; - - ViewHolder(View itemView) { - super(itemView); - - textPlaylistName = itemView.findViewById(R.id.playlist_name_text); - cover = itemView.findViewById(R.id.playlist_cover_image_view); - - itemView.setOnClickListener(this); - itemView.setOnLongClickListener(this); - } - - @Override - public void onClick(View view) { - Bundle bundle = new Bundle(); - bundle.putParcelable("playlist_object", playlists.get(getBindingAdapterPosition())); - bundle.putBoolean("is_offline", isOffline); - - Navigation.findNavController(view).navigate(R.id.action_playlistCatalogueFragment_to_playlistPageFragment, bundle); - - InputMethodManager imm = (InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE); - imm.hideSoftInputFromWindow(view.getWindowToken(), 0); - } - - @Override - public boolean onLongClick(View view) { - Bundle bundle = new Bundle(); - bundle.putParcelable("playlist_object", playlists.get(getBindingAdapterPosition())); - - PlaylistEditorDialog dialog = new PlaylistEditorDialog(); - dialog.setArguments(bundle); - dialog.show(activity.getSupportFragmentManager(), null); - - return true; - } - } -} diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistDialogHorizontalAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistDialogHorizontalAdapter.java new file mode 100644 index 00000000..27fc62ea --- /dev/null +++ b/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistDialogHorizontalAdapter.java @@ -0,0 +1,94 @@ +package com.cappielloantonio.play.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.cappielloantonio.play.R; +import com.cappielloantonio.play.model.Playlist; +import com.cappielloantonio.play.ui.dialog.PlaylistChooserDialog; +import com.cappielloantonio.play.util.MusicUtil; +import com.cappielloantonio.play.viewmodel.PlaylistChooserViewModel; + +import java.util.ArrayList; +import java.util.List; + +public class PlaylistDialogHorizontalAdapter extends RecyclerView.Adapter { + private static final String TAG = "PlaylistDialogHorizontalAdapter"; + + private final Context context; + private final LayoutInflater mInflater; + + private final PlaylistChooserViewModel playlistChooserViewModel; + private final PlaylistChooserDialog playlistChooserDialog; + + private List playlists; + + public PlaylistDialogHorizontalAdapter(Context context, PlaylistChooserViewModel playlistChooserViewModel, PlaylistChooserDialog playlistChooserDialog) { + this.context = context; + this.mInflater = LayoutInflater.from(context); + this.playlists = new ArrayList<>(); + + this.playlistChooserViewModel = playlistChooserViewModel; + this.playlistChooserDialog = playlistChooserDialog; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = mInflater.inflate(R.layout.item_horizontal_playlist_dialog, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(ViewHolder holder, int position) { + Playlist playlist = playlists.get(position); + + holder.playlistTitle.setText(MusicUtil.getReadableString(playlist.getName())); + holder.playlistTrackCount.setText(context.getString(R.string.playlist_counted_tracks, playlist.getSongCount())); + holder.playlistDuration.setText(MusicUtil.getReadableDurationString(playlist.getDuration(), false)); + } + + @Override + public int getItemCount() { + return playlists.size(); + } + + public void setItems(List playlists) { + this.playlists = playlists; + notifyDataSetChanged(); + } + + public Playlist getItem(int id) { + return playlists.get(id); + } + + public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + TextView playlistTitle; + TextView playlistTrackCount; + TextView playlistDuration; + + ViewHolder(View itemView) { + super(itemView); + + playlistTitle = itemView.findViewById(R.id.playlist_dialog_title_text_view); + playlistTrackCount = itemView.findViewById(R.id.playlist_dialog_count_text_view); + playlistDuration = itemView.findViewById(R.id.playlist_dialog_duration_text_view); + + itemView.setOnClickListener(this); + + playlistTitle.setSelected(true); + } + + @Override + public void onClick(View view) { + playlistChooserViewModel.addSongToPlaylist(playlists.get(getBindingAdapterPosition()).getId()); + playlistChooserDialog.dismiss(); + } + } +} diff --git a/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistHorizontalAdapter.java b/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistHorizontalAdapter.java index c0376188..22b9b860 100644 --- a/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistHorizontalAdapter.java +++ b/app/src/main/java/com/cappielloantonio/play/adapter/PlaylistHorizontalAdapter.java @@ -1,41 +1,75 @@ package com.cappielloantonio.play.adapter; import android.content.Context; +import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.view.inputmethod.InputMethodManager; +import android.widget.Filter; +import android.widget.Filterable; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.navigation.Navigation; import androidx.recyclerview.widget.RecyclerView; import com.cappielloantonio.play.R; import com.cappielloantonio.play.model.Playlist; -import com.cappielloantonio.play.ui.dialog.PlaylistChooserDialog; +import com.cappielloantonio.play.ui.activity.MainActivity; +import com.cappielloantonio.play.ui.dialog.PlaylistEditorDialog; import com.cappielloantonio.play.util.MusicUtil; -import com.cappielloantonio.play.viewmodel.PlaylistChooserViewModel; import java.util.ArrayList; import java.util.List; +import java.util.Objects; -public class PlaylistHorizontalAdapter extends RecyclerView.Adapter { - private static final String TAG = "PlaylistHorizontalAdapter"; +public class PlaylistHorizontalAdapter extends RecyclerView.Adapter implements Filterable { + private static final String TAG = "PlaylistDialogHorizontalAdapter"; + private List playlists; + private List playlistsFull; + + private final MainActivity activity; private final Context context; private final LayoutInflater mInflater; - private final PlaylistChooserViewModel playlistChooserViewModel; - private final PlaylistChooserDialog playlistChooserDialog; + private final Filter filtering = new Filter() { + @Override + protected FilterResults performFiltering(CharSequence constraint) { + List filteredList = new ArrayList<>(); - private List playlists; + if (constraint == null || constraint.length() == 0) { + filteredList.addAll(playlistsFull); + } else { + String filterPattern = constraint.toString().toLowerCase().trim(); - public PlaylistHorizontalAdapter(Context context, PlaylistChooserViewModel playlistChooserViewModel, PlaylistChooserDialog playlistChooserDialog) { + for (Playlist item : playlistsFull) { + if (item.getName().toLowerCase().contains(filterPattern)) { + filteredList.add(item); + } + } + } + + FilterResults results = new FilterResults(); + results.values = filteredList; + + return results; + } + + @Override + protected void publishResults(CharSequence constraint, FilterResults results) { + playlists.clear(); + playlists.addAll((List) results.values); + notifyDataSetChanged(); + } + }; + + public PlaylistHorizontalAdapter(MainActivity activity, Context context) { + this.activity = activity; this.context = context; this.mInflater = LayoutInflater.from(context); this.playlists = new ArrayList<>(); - - this.playlistChooserViewModel = playlistChooserViewModel; - this.playlistChooserDialog = playlistChooserDialog; } @NonNull @@ -59,16 +93,22 @@ public class PlaylistHorizontalAdapter extends RecyclerView.Adapter playlists) { - this.playlists = playlists; - notifyDataSetChanged(); - } - public Playlist getItem(int id) { return playlists.get(id); } - public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + public void setItems(List playlists) { + this.playlists = playlists; + this.playlistsFull = new ArrayList<>(playlists); + notifyDataSetChanged(); + } + + @Override + public Filter getFilter() { + return filtering; + } + + public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, View.OnLongClickListener { TextView playlistTitle; TextView playlistTrackCount; TextView playlistDuration; @@ -81,14 +121,41 @@ public class PlaylistHorizontalAdapter extends RecyclerView.Adapter { if (playlists != null) { if (playlists.size() > 0) { if (bind != null) bind.noPlaylistsCreatedTextView.setVisibility(View.GONE); if (bind != null) bind.playlistDialogRecyclerView.setVisibility(View.VISIBLE); - playlistHorizontalAdapter.setItems(playlists); + playlistDialogHorizontalAdapter.setItems(playlists); } else { if (bind != null) bind.noPlaylistsCreatedTextView.setVisibility(View.VISIBLE); if (bind != null) bind.playlistDialogRecyclerView.setVisibility(View.GONE); diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/LibraryFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/LibraryFragment.java index ec7bff37..fc9698a3 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/LibraryFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/LibraryFragment.java @@ -13,7 +13,6 @@ import androidx.annotation.Nullable; import androidx.core.view.ViewCompat; import androidx.fragment.app.Fragment; import androidx.lifecycle.ViewModelProvider; -import androidx.media3.session.MediaBrowser; import androidx.recyclerview.widget.GridLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.PagerSnapHelper; @@ -26,6 +25,9 @@ import com.cappielloantonio.play.adapter.AlbumHorizontalAdapter; import com.cappielloantonio.play.adapter.ArtistAdapter; import com.cappielloantonio.play.adapter.GenreAdapter; import com.cappielloantonio.play.adapter.PlaylistAdapter; +import com.cappielloantonio.play.adapter.PlaylistDialogHorizontalAdapter; +import com.cappielloantonio.play.adapter.PlaylistHorizontalAdapter; +import com.cappielloantonio.play.adapter.SongHorizontalAdapter; import com.cappielloantonio.play.databinding.FragmentLibraryBinding; import com.cappielloantonio.play.helper.recyclerview.CustomLinearSnapHelper; import com.cappielloantonio.play.helper.recyclerview.DotsIndicatorDecoration; @@ -35,7 +37,6 @@ import com.cappielloantonio.play.ui.activity.MainActivity; import com.cappielloantonio.play.util.UIUtil; import com.cappielloantonio.play.viewmodel.LibraryViewModel; import com.google.android.gms.cast.framework.CastButtonFactory; -import com.google.common.util.concurrent.ListenableFuture; import java.util.Objects; @@ -52,6 +53,8 @@ public class LibraryFragment extends Fragment { private GenreAdapter genreAdapter; private PlaylistAdapter playlistAdapter; + private PlaylistHorizontalAdapter playlistHorizontalAdapter; + @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -254,11 +257,10 @@ public class LibraryFragment extends Fragment { } private void initPlaylistSlideView() { - bind.playlistViewPager.setOrientation(ViewPager2.ORIENTATION_HORIZONTAL); + bind.playlistRecyclerView.setHasFixedSize(true); - playlistAdapter = new PlaylistAdapter(activity, requireContext(), false); - bind.playlistViewPager.setAdapter(playlistAdapter); - bind.playlistViewPager.setOffscreenPageLimit(3); + playlistHorizontalAdapter = new PlaylistHorizontalAdapter(activity, requireContext()); + bind.playlistRecyclerView.setAdapter(playlistHorizontalAdapter); libraryViewModel.getPlaylistSample().observe(requireActivity(), playlists -> { if (playlists == null) { if (bind != null) bind.libraryPlaylistPlaceholder.placeholder.setVisibility(View.VISIBLE); @@ -266,26 +268,22 @@ public class LibraryFragment extends Fragment { } else { if (bind != null) bind.libraryPlaylistPlaceholder.placeholder.setVisibility(View.GONE); if (bind != null) bind.libraryPlaylistSector.setVisibility(!playlists.isEmpty() ? View.VISIBLE : View.GONE); + if (bind != null) bind.playlistRecyclerView.setLayoutManager(new GridLayoutManager(requireContext(), UIUtil.getSpanCount(playlists.size(), 5), GridLayoutManager.HORIZONTAL, false)); - playlistAdapter.setItems(playlists); + playlistHorizontalAdapter.setItems(playlists); } }); - setDiscoverSongSlideViewOffset(20, 16); - } + SnapHelper starredTrackSnapHelper = new PagerSnapHelper(); + starredTrackSnapHelper.attachToRecyclerView(bind.playlistRecyclerView); - private void setDiscoverSongSlideViewOffset(float pageOffset, float pageMargin) { - bind.playlistViewPager.setPageTransformer((page, position) -> { - float myOffset = position * -(2 * pageOffset + pageMargin); - if (bind.playlistViewPager.getOrientation() == ViewPager2.ORIENTATION_HORIZONTAL) { - if (ViewCompat.getLayoutDirection(bind.playlistViewPager) == ViewCompat.LAYOUT_DIRECTION_RTL) { - page.setTranslationX(-myOffset); - } else { - page.setTranslationX(myOffset); - } - } else { - page.setTranslationY(myOffset); - } - }); + bind.playlistRecyclerView.addItemDecoration( + new DotsIndicatorDecoration( + getResources().getDimensionPixelSize(R.dimen.radius), + getResources().getDimensionPixelSize(R.dimen.radius) * 4, + getResources().getDimensionPixelSize(R.dimen.dots_height), + requireContext().getResources().getColor(R.color.titleTextColor, null), + requireContext().getResources().getColor(R.color.titleTextColor, null)) + ); } } diff --git a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistCatalogueFragment.java b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistCatalogueFragment.java index 2b381c73..444b89a0 100644 --- a/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistCatalogueFragment.java +++ b/app/src/main/java/com/cappielloantonio/play/ui/fragment/PlaylistCatalogueFragment.java @@ -21,7 +21,7 @@ import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import com.cappielloantonio.play.R; -import com.cappielloantonio.play.adapter.PlaylistCatalogueAdapter; +import com.cappielloantonio.play.adapter.PlaylistHorizontalAdapter; import com.cappielloantonio.play.databinding.FragmentPlaylistCatalogueBinding; import com.cappielloantonio.play.model.Playlist; import com.cappielloantonio.play.ui.activity.MainActivity; @@ -37,7 +37,7 @@ public class PlaylistCatalogueFragment extends Fragment { private MainActivity activity; private PlaylistCatalogueViewModel playlistCatalogueViewModel; - private PlaylistCatalogueAdapter playlistCatalogueAdapter; + private PlaylistHorizontalAdapter playlistHorizontalAdapter; @Override public void onCreate(@Nullable Bundle savedInstanceState) { @@ -108,10 +108,10 @@ public class PlaylistCatalogueFragment extends Fragment { bind.playlistCatalogueRecyclerView.setLayoutManager(new LinearLayoutManager(requireContext())); bind.playlistCatalogueRecyclerView.setHasFixedSize(true); - playlistCatalogueAdapter = new PlaylistCatalogueAdapter(activity, requireContext(), playlistCatalogueViewModel.getType().equals(Playlist.DOWNLOADED)); - bind.playlistCatalogueRecyclerView.setAdapter(playlistCatalogueAdapter); + playlistHorizontalAdapter = new PlaylistHorizontalAdapter(activity, requireContext()); + bind.playlistCatalogueRecyclerView.setAdapter(playlistHorizontalAdapter); - if(getActivity() != null) { + if (getActivity() != null) { playlistCatalogueViewModel.getPlaylistList(requireActivity()).observe(requireActivity(), playlists -> playlistCatalogueViewModel.getPinnedPlaylistList(requireActivity()).observe(requireActivity(), pinnedPlaylists -> { @@ -135,7 +135,7 @@ public class PlaylistCatalogueFragment extends Fragment { sortedList.addAll(unsortedList); } - playlistCatalogueAdapter.setItems(sortedList); + playlistHorizontalAdapter.setItems(sortedList); playlistCatalogueViewModel.unpinPlaylist(pinnedPlaylistsNotFound); })); } @@ -163,7 +163,7 @@ public class PlaylistCatalogueFragment extends Fragment { @Override public boolean onQueryTextChange(String newText) { - playlistCatalogueAdapter.getFilter().filter(newText); + playlistHorizontalAdapter.getFilter().filter(newText); return false; } }); diff --git a/app/src/main/res/layout/fragment_library.xml b/app/src/main/res/layout/fragment_library.xml index 4ac95f9a..e30b9f33 100644 --- a/app/src/main/res/layout/fragment_library.xml +++ b/app/src/main/res/layout/fragment_library.xml @@ -284,7 +284,6 @@ android:paddingEnd="8dp" android:text="@string/library_title_playlist" /> - - - @@ -309,7 +309,7 @@ diff --git a/app/src/main/res/layout/fragment_playlist_catalogue.xml b/app/src/main/res/layout/fragment_playlist_catalogue.xml index 940e6d1f..328ef6db 100644 --- a/app/src/main/res/layout/fragment_playlist_catalogue.xml +++ b/app/src/main/res/layout/fragment_playlist_catalogue.xml @@ -49,8 +49,8 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:clipToPadding="false" - android:paddingStart="16dp" - android:paddingEnd="16dp" + android:paddingStart="2dp" + android:paddingEnd="2dp" android:paddingBottom="@dimen/global_padding_bottom" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> diff --git a/app/src/main/res/layout/item_horizontal_playlist.xml b/app/src/main/res/layout/item_horizontal_playlist.xml index 69f853a7..a8b9dead 100644 --- a/app/src/main/res/layout/item_horizontal_playlist.xml +++ b/app/src/main/res/layout/item_horizontal_playlist.xml @@ -1,71 +1,82 @@ - + android:layout_marginStart="16dp" + android:layout_marginEnd="14dp" + android:layout_marginBottom="4dp" + android:checkable="true" + android:clickable="true" + android:focusable="true"> - - - + android:background="?attr/selectableItemBackground" + android:clipChildren="false" + android:padding="4dp"> - - - - - - \ No newline at end of file + android:scrollHorizontally="true" + android:singleLine="true" + android:text="@string/label_placeholder" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/item_horizontal_playlist_dialog.xml b/app/src/main/res/layout/item_horizontal_playlist_dialog.xml new file mode 100644 index 00000000..69f853a7 --- /dev/null +++ b/app/src/main/res/layout/item_horizontal_playlist_dialog.xml @@ -0,0 +1,71 @@ + + + + + + + + + + + + + \ No newline at end of file