From a3e7cb93aab961aea024c4ad7a269afdfb8eab73 Mon Sep 17 00:00:00 2001 From: OxygenCobalt Date: Sat, 21 Aug 2021 19:49:25 -0600 Subject: [PATCH] home: merge all library views into home Merge LibraryFragment, SongsFragment, and others into a new fragment called HomeFragment. This is the beginning of the Auxio UI overhaul. This has caused some regressions here and there, but these will be rectified over time. --- .../java/org/oxycblt/auxio/MainFragment.kt | 96 +----- .../LibraryAdapter.kt => home/HomeAdapter.kt} | 24 +- .../org/oxycblt/auxio/home/HomeFragment.kt | 113 +++++++ .../auxio/home/pager/AlbumListFragment.kt | 59 ++++ .../auxio/home/pager/ArtistListFragment.kt | 59 ++++ .../auxio/home/pager/GenreListFragment.kt | 59 ++++ .../auxio/home/pager/SongListFragment.kt | 59 ++++ .../oxycblt/auxio/library/LibraryFragment.kt | 142 --------- .../oxycblt/auxio/library/LibraryViewModel.kt | 121 -------- .../oxycblt/auxio/recycler/FastScrollView.kt | 293 ------------------ .../oxycblt/auxio/search/SearchFragment.kt | 4 + .../auxio/settings/SettingsFragment.kt | 17 +- .../org/oxycblt/auxio/songs/SongsAdapter.kt | 49 --- .../org/oxycblt/auxio/songs/SongsFragment.kt | 85 ----- app/src/main/res/drawable/ui_circle.xml | 5 - .../main/res/layout-land/fragment_main.xml | 58 ---- app/src/main/res/layout/fragment_about.xml | 3 +- app/src/main/res/layout/fragment_home.xml | 50 +++ .../main/res/layout/fragment_home_list.xml | 13 + app/src/main/res/layout/fragment_library.xml | 41 --- app/src/main/res/layout/fragment_main.xml | 32 +- app/src/main/res/layout/fragment_search.xml | 2 +- app/src/main/res/layout/fragment_settings.xml | 4 +- app/src/main/res/layout/fragment_songs.xml | 41 --- app/src/main/res/layout/view_fast_scroll.xml | 50 --- .../menu/{menu_library.xml => menu_home.xml} | 14 +- app/src/main/res/menu/menu_nav.xml | 19 -- app/src/main/res/menu/menu_songs.xml | 9 - app/src/main/res/navigation/nav_explore.xml | 71 ++--- app/src/main/res/navigation/nav_main.xml | 17 +- app/src/main/res/values/dimens.xml | 8 +- app/src/main/res/values/styles_core.xml | 2 +- app/src/main/res/values/styles_ui.xml | 6 +- 33 files changed, 528 insertions(+), 1097 deletions(-) rename app/src/main/java/org/oxycblt/auxio/{library/LibraryAdapter.kt => home/HomeAdapter.kt} (78%) create mode 100644 app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt create mode 100644 app/src/main/java/org/oxycblt/auxio/home/pager/AlbumListFragment.kt create mode 100644 app/src/main/java/org/oxycblt/auxio/home/pager/ArtistListFragment.kt create mode 100644 app/src/main/java/org/oxycblt/auxio/home/pager/GenreListFragment.kt create mode 100644 app/src/main/java/org/oxycblt/auxio/home/pager/SongListFragment.kt delete mode 100644 app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt delete mode 100644 app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt delete mode 100644 app/src/main/java/org/oxycblt/auxio/recycler/FastScrollView.kt delete mode 100644 app/src/main/java/org/oxycblt/auxio/songs/SongsAdapter.kt delete mode 100644 app/src/main/java/org/oxycblt/auxio/songs/SongsFragment.kt delete mode 100644 app/src/main/res/drawable/ui_circle.xml delete mode 100644 app/src/main/res/layout-land/fragment_main.xml create mode 100644 app/src/main/res/layout/fragment_home.xml create mode 100644 app/src/main/res/layout/fragment_home_list.xml delete mode 100644 app/src/main/res/layout/fragment_library.xml delete mode 100644 app/src/main/res/layout/fragment_songs.xml delete mode 100644 app/src/main/res/layout/view_fast_scroll.xml rename app/src/main/res/menu/{menu_library.xml => menu_home.xml} (65%) delete mode 100644 app/src/main/res/menu/menu_nav.xml delete mode 100644 app/src/main/res/menu/menu_songs.xml diff --git a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt index 1de60aba4..e58029062 100644 --- a/app/src/main/java/org/oxycblt/auxio/MainFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/MainFragment.kt @@ -18,32 +18,21 @@ package org.oxycblt.auxio -import android.content.res.ColorStateList import android.os.Bundle import android.view.LayoutInflater -import android.view.MenuItem import android.view.View import android.view.ViewGroup -import androidx.core.graphics.ColorUtils import androidx.fragment.app.Fragment import androidx.fragment.app.activityViewModels -import androidx.navigation.NavController -import androidx.navigation.NavOptions -import androidx.navigation.fragment.NavHostFragment -import androidx.navigation.fragment.findNavController -import com.google.android.material.bottomnavigation.BottomNavigationView -import org.oxycblt.auxio.accent.Accent import org.oxycblt.auxio.databinding.FragmentMainBinding -import org.oxycblt.auxio.detail.DetailViewModel import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.playback.PlaybackViewModel /** - * The primary "Home" [Fragment] for Auxio. + * A wrapper around the home */ class MainFragment : Fragment() { private val playbackModel: PlaybackViewModel by activityViewModels() - private val detailModel: DetailViewModel by activityViewModels() override fun onCreateView( inflater: LayoutInflater, @@ -52,51 +41,10 @@ class MainFragment : Fragment() { ): View { val binding = FragmentMainBinding.inflate(inflater) - val colorActive = Accent.get().color.resolveColor(requireContext()) - val colorInactive = ColorUtils.setAlphaComponent(colorActive, 150) - - // Set up the tints for the navigation icons + text - val navTints = ColorStateList( - arrayOf( - intArrayOf(-android.R.attr.state_checked), - intArrayOf(android.R.attr.state_checked) - ), - intArrayOf(colorInactive, colorActive) - ) - - val navController = ( - childFragmentManager.findFragmentById(R.id.explore_nav_host) - as NavHostFragment? - )?.findNavController() - // --- UI SETUP --- binding.lifecycleOwner = viewLifecycleOwner - // Speed up the slide-in effect on the controls view, solely to improve the UX - // and maybe hide the problem where the main view will snap-shrink before the compact - // view can slide. - (binding.controlsContainer as ViewGroup).layoutTransition.setDuration(150) - - binding.navBar.apply { - itemIconTintList = navTints - itemTextColor = navTints - - if (requireContext().isTablet() && !requireContext().isLandscape()) { - labelVisibilityMode = BottomNavigationView.LABEL_VISIBILITY_LABELED - } - - navController?.let { controller -> - binding.navBar.setOnItemSelectedListener { item -> - navigateWithItem(controller, item) - } - } - - // BottomNavigationView is a special little snowflake and doesn't like it when - // we set the background in XML - setBackgroundColor(R.attr.colorSurface.resolveAttr(requireContext())) - } - // --- VIEWMODEL SETUP --- // Change CompactPlaybackFragment's visibility here so that an animation occurs. @@ -106,49 +54,11 @@ class MainFragment : Fragment() { handleCompactPlaybackVisibility(binding, song) } - detailModel.navToItem.observe(viewLifecycleOwner) { item -> - if (item != null && navController != null) { - val curDest = navController.currentDestination?.id - - // SongsFragment and SettingsFragment have no navigation pathways, so correct - // them to the library tab instead. - if (curDest == R.id.songs_fragment || curDest == R.id.settings_fragment) { - binding.navBar.selectedItemId = R.id.library_fragment - } - } - } - - playbackModel.setupPlayback(requireContext()) - logD("Fragment Created.") return binding.root } - /** - * Custom navigator code that has proper animations, unlike BottomNavigationView.setupWithNavController(). - */ - private fun navigateWithItem(navController: NavController, item: MenuItem): Boolean { - if (navController.currentDestination!!.id != item.itemId) { - val options = NavOptions.Builder() - .setLaunchSingleTop(true) - .setEnterAnim(R.animator.nav_default_enter_anim) - .setExitAnim(R.animator.nav_default_exit_anim) - .setPopEnterAnim(R.animator.nav_default_pop_enter_anim) - .setPopExitAnim(R.animator.nav_default_pop_exit_anim) - .build() - - return try { - navController.navigate(item.itemId, null, options) - true - } catch (e: IllegalArgumentException) { - false - } - } - - return false - } - /** * Handle the visibility of CompactPlaybackFragment. Done here so that there's a nice animation. */ @@ -156,13 +66,13 @@ class MainFragment : Fragment() { if (song == null) { logD("Hiding CompactPlaybackFragment since no song is being played.") - binding.compactPlayback.visibility = if (requireContext().isLandscape()) { + binding.mainPlayback.visibility = if (requireContext().isLandscape()) { View.INVISIBLE } else { View.GONE } } else { - binding.compactPlayback.visibility = View.VISIBLE + binding.mainPlayback.visibility = View.VISIBLE } } } diff --git a/app/src/main/java/org/oxycblt/auxio/library/LibraryAdapter.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeAdapter.kt similarity index 78% rename from app/src/main/java/org/oxycblt/auxio/library/LibraryAdapter.kt rename to app/src/main/java/org/oxycblt/auxio/home/HomeAdapter.kt index 669c92eb2..a5418f5d8 100644 --- a/app/src/main/java/org/oxycblt/auxio/library/LibraryAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeAdapter.kt @@ -1,6 +1,6 @@ /* * Copyright (c) 2021 Auxio Project - * LibraryAdapter.kt is part of Auxio. + * HomeAdapter.kt is part of Auxio. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -16,7 +16,7 @@ * along with this program. If not, see . */ -package org.oxycblt.auxio.library +package org.oxycblt.auxio.home import android.annotation.SuppressLint import android.view.View @@ -24,22 +24,25 @@ import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import org.oxycblt.auxio.music.Album import org.oxycblt.auxio.music.Artist +import org.oxycblt.auxio.music.BaseModel import org.oxycblt.auxio.music.Genre import org.oxycblt.auxio.music.Parent +import org.oxycblt.auxio.music.Song import org.oxycblt.auxio.recycler.viewholders.AlbumViewHolder import org.oxycblt.auxio.recycler.viewholders.ArtistViewHolder import org.oxycblt.auxio.recycler.viewholders.GenreViewHolder +import org.oxycblt.auxio.recycler.viewholders.SongViewHolder /** * An adapter for displaying library items. Supports [Parent]s only. * @author OxygenCobalt */ -class LibraryAdapter( - private val doOnClick: (data: Parent) -> Unit, - private val doOnLongClick: (view: View, data: Parent) -> Unit +class HomeAdapter( + private val doOnClick: (data: BaseModel) -> Unit, + private val doOnLongClick: (view: View, data: BaseModel) -> Unit ) : RecyclerView.Adapter() { - private var data = listOf() + private var data = listOf() override fun getItemCount(): Int = data.size @@ -48,6 +51,8 @@ class LibraryAdapter( is Genre -> GenreViewHolder.ITEM_TYPE is Artist -> ArtistViewHolder.ITEM_TYPE is Album -> AlbumViewHolder.ITEM_TYPE + is Song -> SongViewHolder.ITEM_TYPE + else -> error("Unsupported item ${data[position]::class.simpleName}") } } @@ -65,6 +70,10 @@ class LibraryAdapter( parent.context, doOnClick, doOnLongClick ) + SongViewHolder.ITEM_TYPE -> SongViewHolder.from( + parent.context, doOnClick, doOnLongClick + ) + else -> error("Invalid viewholder item type.") } } @@ -74,6 +83,7 @@ class LibraryAdapter( is Genre -> (holder as GenreViewHolder).bind(item) is Artist -> (holder as ArtistViewHolder).bind(item) is Album -> (holder as AlbumViewHolder).bind(item) + is Song -> (holder as SongViewHolder).bind(item) } } @@ -81,7 +91,7 @@ class LibraryAdapter( * Update the data with [newData]. [notifyDataSetChanged] will be called. */ @SuppressLint("NotifyDataSetChanged") - fun updateData(newData: List) { + fun updateData(newData: List) { data = newData notifyDataSetChanged() diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt new file mode 100644 index 000000000..f75b0a6fa --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021 Auxio Project + * MainFragment.kt is part of Auxio. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.oxycblt.auxio.home + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.navigation.fragment.findNavController +import androidx.viewpager2.adapter.FragmentStateAdapter +import com.google.android.material.tabs.TabLayoutMediator +import org.oxycblt.auxio.MainFragmentDirections +import org.oxycblt.auxio.R +import org.oxycblt.auxio.databinding.FragmentHomeBinding +import org.oxycblt.auxio.home.pager.AlbumListFragment +import org.oxycblt.auxio.home.pager.ArtistListFragment +import org.oxycblt.auxio.home.pager.GenreListFragment +import org.oxycblt.auxio.home.pager.SongListFragment +import org.oxycblt.auxio.logD +import org.oxycblt.auxio.playback.PlaybackViewModel + +/** + * The main "Launching Point" fragment of Auxio, allowing navigation to the detail + * views for each respective fragment. + * TODO: Re-add sorting (but new and improved) + * @author OxygenCobalt + */ +class HomeFragment : Fragment() { + private val playbackModel: PlaybackViewModel by activityViewModels() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + val binding = FragmentHomeBinding.inflate(inflater) + + // --- UI SETUP --- + + binding.lifecycleOwner = viewLifecycleOwner + + binding.homeToolbar.setOnMenuItemClickListener { item -> + when (item.itemId) { + R.id.action_settings -> { + parentFragment?.parentFragment?.findNavController()?.navigate( + MainFragmentDirections.actionShowSettings() + ) + } + + R.id.action_search -> { + findNavController().navigate(HomeFragmentDirections.actionShowSearch()) + } + } + + true + } + + binding.homePager.adapter = HomePagerAdapter() + + TabLayoutMediator(binding.homeTabs, binding.homePager) { tab, pos -> + val labelRes = when (pos) { + 0 -> R.string.lbl_songs + 1 -> R.string.lbl_albums + 2 -> R.string.lbl_artists + 3 -> R.string.lbl_genres + else -> error("Unreachable") + } + + tab.setText(labelRes) + }.attach() + + // --- VIEWMODEL SETUP --- + + playbackModel.setupPlayback(requireContext()) + + logD("Fragment Created.") + + return binding.root + } + + private inner class HomePagerAdapter : + FragmentStateAdapter(childFragmentManager, viewLifecycleOwner.lifecycle) { + override fun createFragment(position: Int): Fragment { + return when (position) { + 0 -> SongListFragment() + 1 -> AlbumListFragment() + 2 -> ArtistListFragment() + 3 -> GenreListFragment() + else -> error("Unreachable") + } + } + + override fun getItemCount(): Int = 4 + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/home/pager/AlbumListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/pager/AlbumListFragment.kt new file mode 100644 index 000000000..09afe9d22 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/home/pager/AlbumListFragment.kt @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Auxio Project + * GenreListFragment.kt is part of Auxio. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.oxycblt.auxio.home.pager + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import org.oxycblt.auxio.databinding.FragmentHomeListBinding +import org.oxycblt.auxio.home.HomeAdapter +import org.oxycblt.auxio.home.HomeFragmentDirections +import org.oxycblt.auxio.music.MusicStore +import org.oxycblt.auxio.playback.PlaybackViewModel +import org.oxycblt.auxio.ui.newMenu + +class AlbumListFragment : Fragment() { + private val playbackModel: PlaybackViewModel by viewModels() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + val binding = FragmentHomeListBinding.inflate(inflater) + + val adapter = HomeAdapter( + doOnClick = { item -> + HomeFragmentDirections.actionShowAlbum(item.id) + }, + ::newMenu + ) + + adapter.updateData(MusicStore.getInstance().albums) + + // --- UI SETUP --- + + binding.homeRecycler.adapter = adapter + + return binding.root + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/home/pager/ArtistListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/pager/ArtistListFragment.kt new file mode 100644 index 000000000..2c1a656bd --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/home/pager/ArtistListFragment.kt @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Auxio Project + * GenreListFragment.kt is part of Auxio. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.oxycblt.auxio.home.pager + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import org.oxycblt.auxio.databinding.FragmentHomeListBinding +import org.oxycblt.auxio.home.HomeAdapter +import org.oxycblt.auxio.home.HomeFragmentDirections +import org.oxycblt.auxio.music.MusicStore +import org.oxycblt.auxio.playback.PlaybackViewModel +import org.oxycblt.auxio.ui.newMenu + +class ArtistListFragment : Fragment() { + private val playbackModel: PlaybackViewModel by viewModels() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + val binding = FragmentHomeListBinding.inflate(inflater) + + val adapter = HomeAdapter( + doOnClick = { item -> + HomeFragmentDirections.actionShowArtist(item.id) + }, + ::newMenu + ) + + adapter.updateData(MusicStore.getInstance().artists) + + // --- UI SETUP --- + + binding.homeRecycler.adapter = adapter + + return binding.root + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/home/pager/GenreListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/pager/GenreListFragment.kt new file mode 100644 index 000000000..9331f0e99 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/home/pager/GenreListFragment.kt @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Auxio Project + * GenreListFragment.kt is part of Auxio. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.oxycblt.auxio.home.pager + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import org.oxycblt.auxio.databinding.FragmentHomeListBinding +import org.oxycblt.auxio.home.HomeAdapter +import org.oxycblt.auxio.home.HomeFragmentDirections +import org.oxycblt.auxio.music.MusicStore +import org.oxycblt.auxio.playback.PlaybackViewModel +import org.oxycblt.auxio.ui.newMenu + +class GenreListFragment : Fragment() { + private val playbackModel: PlaybackViewModel by viewModels() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + val binding = FragmentHomeListBinding.inflate(inflater) + + val adapter = HomeAdapter( + doOnClick = { item -> + HomeFragmentDirections.actionShowGenre(item.id) + }, + ::newMenu + ) + + adapter.updateData(MusicStore.getInstance().genres) + + // --- UI SETUP --- + + binding.homeRecycler.adapter = adapter + + return binding.root + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/home/pager/SongListFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/pager/SongListFragment.kt new file mode 100644 index 000000000..69f53bf74 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/home/pager/SongListFragment.kt @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021 Auxio Project + * GenreListFragment.kt is part of Auxio. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.oxycblt.auxio.home.pager + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.viewModels +import org.oxycblt.auxio.databinding.FragmentHomeListBinding +import org.oxycblt.auxio.home.HomeAdapter +import org.oxycblt.auxio.music.MusicStore +import org.oxycblt.auxio.music.Song +import org.oxycblt.auxio.playback.PlaybackViewModel +import org.oxycblt.auxio.ui.newMenu + +class SongListFragment : Fragment() { + private val playbackModel: PlaybackViewModel by viewModels() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + val binding = FragmentHomeListBinding.inflate(inflater) + + val adapter = HomeAdapter( + doOnClick = { item -> + playbackModel.playSong(item as Song) + }, + ::newMenu + ) + + adapter.updateData(MusicStore.getInstance().songs) + + // --- UI SETUP --- + + binding.homeRecycler.adapter = adapter + + return binding.root + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt b/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt deleted file mode 100644 index 0c2f4774d..000000000 --- a/app/src/main/java/org/oxycblt/auxio/library/LibraryFragment.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2021 Auxio Project - * LibraryFragment.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.library - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.Fragment -import androidx.fragment.app.activityViewModels -import androidx.navigation.fragment.findNavController -import androidx.recyclerview.widget.GridLayoutManager -import org.oxycblt.auxio.R -import org.oxycblt.auxio.databinding.FragmentLibraryBinding -import org.oxycblt.auxio.detail.DetailViewModel -import org.oxycblt.auxio.logD -import org.oxycblt.auxio.music.Album -import org.oxycblt.auxio.music.Artist -import org.oxycblt.auxio.music.Genre -import org.oxycblt.auxio.music.Parent -import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.recycler.sliceArticle -import org.oxycblt.auxio.spans -import org.oxycblt.auxio.ui.newMenu - -/** - * A [Fragment] that shows a custom list of [Genre], [Artist], or [Album] data. Also allows for - * search functionality. - * @author OxygenCobalt - */ -class LibraryFragment : Fragment() { - private val libraryModel: LibraryViewModel by activityViewModels() - private val detailModel: DetailViewModel by activityViewModels() - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - val binding = FragmentLibraryBinding.inflate(inflater) - val libraryAdapter = LibraryAdapter(::navToDetail, ::newMenu) - - // --- UI SETUP --- - - binding.lifecycleOwner = viewLifecycleOwner - - binding.libraryToolbar.apply { - menu.findItem(libraryModel.sortMode.toMenuId()).isChecked = true - - setOnMenuItemClickListener { item -> - if (item.itemId != R.id.submenu_sorting) { - libraryModel.updateSortMode(item.itemId) - item.isChecked = true - true - } else { - false - } - } - } - - binding.libraryRecycler.apply { - adapter = libraryAdapter - setHasFixedSize(true) - - if (spans != 1) { - layoutManager = GridLayoutManager(requireContext(), spans) - } - } - - binding.libraryFastScroll.setup(binding.libraryRecycler) { pos -> - val item = libraryModel.libraryData.value!![pos] - val char = item.displayName.sliceArticle().first().uppercaseChar() - - if (char.isDigit()) '#' else char - } - - // --- VIEWMODEL SETUP --- - - libraryModel.libraryData.observe(viewLifecycleOwner) { data -> - libraryAdapter.updateData(data) - } - - detailModel.navToItem.observe(viewLifecycleOwner) { item -> - if (item != null) { - libraryModel.setNavigating(false) - - if (item is Parent) { - navToDetail(item) - } else if (item is Song) { - navToDetail(item.album) - } - } - } - - logD("Fragment created.") - - return binding.root - } - - override fun onResume() { - super.onResume() - - libraryModel.setNavigating(false) - } - - /** - * Navigate to the detail UI for a [parent]. - */ - private fun navToDetail(parent: Parent) { - requireView().rootView.clearFocus() - - if (!libraryModel.isNavigating) { - libraryModel.setNavigating(true) - - logD("Navigating to the detail fragment for ${parent.name}") - - findNavController().navigate( - when (parent) { - is Genre -> LibraryFragmentDirections.actionShowGenre(parent.id) - is Artist -> LibraryFragmentDirections.actionShowArtist(parent.id) - is Album -> LibraryFragmentDirections.actionShowAlbum(parent.id) - } - ) - } - } -} diff --git a/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt b/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt deleted file mode 100644 index 0eeef5608..000000000 --- a/app/src/main/java/org/oxycblt/auxio/library/LibraryViewModel.kt +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2021 Auxio Project - * LibraryViewModel.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.library - -import androidx.annotation.IdRes -import androidx.lifecycle.LiveData -import androidx.lifecycle.MutableLiveData -import androidx.lifecycle.ViewModel -import org.oxycblt.auxio.R -import org.oxycblt.auxio.music.MusicStore -import org.oxycblt.auxio.music.Parent -import org.oxycblt.auxio.recycler.DisplayMode -import org.oxycblt.auxio.recycler.SortMode -import org.oxycblt.auxio.settings.SettingsManager - -/** - * A [ViewModel] that manages what [LibraryFragment] is currently showing, and also the search - * functionality. - * @author OxygenCobalt - */ -class LibraryViewModel : ViewModel(), SettingsManager.Callback { - private val mLibraryData = MutableLiveData(listOf()) - val libraryData: LiveData> get() = mLibraryData - - private var mSortMode = SortMode.ALPHA_DOWN - val sortMode: SortMode get() = mSortMode - - private var mDisplayMode = DisplayMode.SHOW_ARTISTS - - private var mIsNavigating = false - val isNavigating: Boolean get() = mIsNavigating - - private val settingsManager = SettingsManager.getInstance() - private val musicStore = MusicStore.getInstance() - - init { - settingsManager.addCallback(this) - - // Set up the display/sort modes - mDisplayMode = settingsManager.libraryDisplayMode - mSortMode = settingsManager.librarySortMode - - // Handle "NONE" SortMode that was removed in 1.4.1 - if (mSortMode == SortMode.NONE) { - mSortMode = SortMode.ALPHA_DOWN - } - - updateLibraryData() - } - - /** - * Update the current [SortMode] using an menu [itemId]. - */ - fun updateSortMode(@IdRes itemId: Int) { - val mode = when (itemId) { - R.id.option_sort_alpha_down -> SortMode.ALPHA_DOWN - R.id.option_sort_alpha_up -> SortMode.ALPHA_UP - - else -> SortMode.NONE - } - - if (mode != mSortMode) { - mSortMode = mode - settingsManager.librarySortMode = mode - - updateLibraryData() - } - } - - /** - * Update the current navigation status - */ - fun setNavigating(isNavigating: Boolean) { - mIsNavigating = isNavigating - } - - /** - * Shortcut function for updating the library data with the current [SortMode]/[DisplayMode] - */ - private fun updateLibraryData() { - mLibraryData.value = when (mDisplayMode) { - DisplayMode.SHOW_GENRES -> mSortMode.getSortedGenreList(musicStore.genres) - - DisplayMode.SHOW_ARTISTS -> mSortMode.getSortedArtistList(musicStore.artists) - - DisplayMode.SHOW_ALBUMS -> mSortMode.getSortedAlbumList(musicStore.albums) - - else -> error("DisplayMode $mDisplayMode is unsupported.") - } - } - - // --- OVERRIDES --- - - override fun onCleared() { - super.onCleared() - - settingsManager.removeCallback(this) - } - - override fun onLibDisplayModeUpdate(displayMode: DisplayMode) { - mDisplayMode = displayMode - - updateLibraryData() - } -} diff --git a/app/src/main/java/org/oxycblt/auxio/recycler/FastScrollView.kt b/app/src/main/java/org/oxycblt/auxio/recycler/FastScrollView.kt deleted file mode 100644 index e80750fca..000000000 --- a/app/src/main/java/org/oxycblt/auxio/recycler/FastScrollView.kt +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Copyright (c) 2021 Auxio Project - * FastScrollView.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.recycler - -import android.content.Context -import android.os.Build -import android.util.AttributeSet -import android.util.TypedValue -import android.view.HapticFeedbackConstants -import android.view.MotionEvent -import android.view.View -import androidx.constraintlayout.widget.ConstraintLayout -import androidx.core.view.isVisible -import androidx.core.view.postDelayed -import androidx.dynamicanimation.animation.DynamicAnimation -import androidx.dynamicanimation.animation.SpringAnimation -import androidx.dynamicanimation.animation.SpringForce -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView -import org.oxycblt.auxio.accent.Accent -import org.oxycblt.auxio.canScroll -import org.oxycblt.auxio.databinding.ViewFastScrollBinding -import org.oxycblt.auxio.inflater -import org.oxycblt.auxio.logD -import org.oxycblt.auxio.resolveAttr -import org.oxycblt.auxio.resolveColor -import kotlin.math.ceil -import kotlin.math.min -import kotlin.math.roundToInt - -/** - * A view that allows for quick scrolling through a [RecyclerView] with many items. Unlike other - * fast-scrollers, this one displays indicators and a thumb instead of simply a scroll bar. - * This code is fundamentally an adaptation of Reddit's IndicatorFastScroll, albeit specialized - * towards Auxio. The original library is here: https://github.com/reddit/IndicatorFastScroll/ - * TODO: Replace this with something similar to AndroidFastScroll [but optimized for Auxio], - * since this thumb view is a blocker to a better sort system. - * @author OxygenCobalt - */ -class FastScrollView @JvmOverloads constructor( - context: Context, - attrs: AttributeSet? = null, - defStyleAttr: Int = -1 -) : ConstraintLayout(context, attrs, defStyleAttr) { - - // --- UI --- - - private val binding = ViewFastScrollBinding.inflate(context.inflater, this, true) - private val thumbAnim: SpringAnimation - - // --- RECYCLER --- - - private var mRecycler: RecyclerView? = null - private var mGetItem: ((Int) -> Char)? = null - private val mObserver = object : RecyclerView.AdapterDataObserver() { - override fun onChanged() = postIndicatorUpdate() - - override fun onItemRangeChanged( - positionStart: Int, - itemCount: Int, - payload: Any? - ) = postIndicatorUpdate() - - override fun onItemRangeInserted( - positionStart: Int, - itemCount: Int - ) = onChanged() - - override fun onItemRangeMoved( - fromPosition: Int, - toPosition: Int, - itemCount: Int - ) = onChanged() - - override fun onItemRangeRemoved( - positionStart: Int, - itemCount: Int - ) = onChanged() - } - - // --- INDICATORS --- - - private data class Indicator(val char: Char, val pos: Int) - - private var indicators = listOf() - private val activeColor = Accent.get().color.resolveColor(context) - private val inactiveColor = android.R.attr.textColorSecondary.resolveAttr(context) - - // --- STATE --- - - private var hasPostedItemUpdate = false - private var wasValidTouch = false - private var lastPos = -1 - - init { - isFocusableInTouchMode = true - isClickable = true - - thumbAnim = SpringAnimation(binding.scrollThumb, DynamicAnimation.TRANSLATION_Y).apply { - spring = SpringForce().also { - it.dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY - } - } - - // Prevent the disappear animation from being displayed on startup by making the thumb - // invisible, it will be made visible once the animation ends - binding.scrollThumb.visibility = View.INVISIBLE - - postDelayed(200) { - binding.scrollThumb.visibility = View.VISIBLE - } - } - - /** - * Set up this view with a [RecyclerView]. [getItem] is called when the first character - * of a piece of data is needed. - */ - fun setup(recycler: RecyclerView, getItem: (Int) -> Char) { - check(mRecycler == null) { "Only set up this view once." } - - mRecycler = recycler - mGetItem = getItem - - recycler.adapter?.registerAdapterDataObserver(mObserver) - - postIndicatorUpdate() - } - - // --- INDICATOR UPDATES --- - - private fun postIndicatorUpdate() { - if (!hasPostedItemUpdate) { - hasPostedItemUpdate = true - - post { - val recycler = requireNotNull(mRecycler) - - if (recycler.isAttachedToWindow && recycler.adapter != null) { - updateIndicators() - binding.scrollIndicatorText.requestLayout() - } - - // Hide this view if there is nothing to scroll - isVisible = recycler.canScroll() - - hasPostedItemUpdate = false - } - } - } - - private fun updateIndicators() { - val recycler = requireNotNull(mRecycler) - val getItem = requireNotNull(mGetItem) - - indicators = 0.until(recycler.adapter!!.itemCount).mapNotNull { pos -> - Indicator(getItem(pos), pos) - }.distinctBy { it.char } - - val textHeight = TypedValue.applyDimension( - TypedValue.COMPLEX_UNIT_SP, 14F, resources.displayMetrics - ) - - // If the scroller size is too small to contain all the entries, truncate entries - // so that the fast scroller entries fit. Include the thumb in here so it isn't cut - // off. - val maxEntries = (height - (binding.scrollThumb.height * 2)) / textHeight - - if (indicators.size > maxEntries) { - val truncateInterval = ceil(indicators.size / maxEntries).toInt() - - check(truncateInterval > 1) { - "Needed to truncate, but truncateInterval was 1 or lower anyway" - } - - logD("More entries than screen space, truncating by $truncateInterval.") - - indicators = indicators.filterIndexed { index, _ -> - index % truncateInterval == 0 - } - } - - // Then set it as the unified TextView text, for efficiency purposes. - binding.scrollIndicatorText.text = indicators.joinToString("\n") { indicator -> - indicator.char.toString() - } - } - - // --- TOUCH --- - - @Suppress("ClickableViewAccessibility") - override fun onTouchEvent(event: MotionEvent): Boolean { - super.onTouchEvent(event) - performClick() - - val success = handleTouch(event.action, event.x.roundToInt(), event.y.roundToInt()) - - // Depending on the results, update the visibility of the thumb and the pressed state of - // this view. - binding.scrollThumb.isActivated = success - binding.scrollIndicatorText.isPressed = success - - return success - } - - private fun handleTouch(action: Int, touchX: Int, touchY: Int): Boolean { - when (action) { - MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> { - binding.scrollIndicatorText.setTextColor(inactiveColor) - wasValidTouch = false - lastPos = -1 - - return false - } - - // Since this view is unified between the thumb and the indicators, we have - // to check if the initial pointer position was in the indicators to prevent the - // scroll from being triggered outside its bounds. - MotionEvent.ACTION_DOWN -> { - wasValidTouch = binding.scrollIndicatorText.contains(touchX, touchY) - } - } - - // Try to figure out which indicator the pointer has landed on - if (binding.scrollIndicatorText.containsY(touchY) && wasValidTouch) { - // Get the touch position in regards to the TextView and the rough text height - val indicatorTouchY = touchY - binding.scrollIndicatorText.top - val textHeight = binding.scrollIndicatorText.height / indicators.size - - // Use that to calculate the indicator index, if the calculation is - // invalid just ignore it. - val index = min(indicatorTouchY / textHeight, indicators.lastIndex) - - // Also calculate the rough center position of the indicator for the scroll thumb - val centerY = binding.scrollIndicatorText.y + (textHeight / 2) + (index * textHeight) - - selectIndicator(indicators[index], centerY) - - return true - } - - return false - } - - private fun selectIndicator(indicator: Indicator, centerY: Float) { - if (indicator.pos != lastPos) { - lastPos = indicator.pos - binding.scrollIndicatorText.setTextColor(activeColor) - - // Stop any scroll momentum and snap-scroll to the position - mRecycler?.apply { - stopScroll() - (layoutManager as LinearLayoutManager).scrollToPositionWithOffset(indicator.pos, 0) - } - - // Update the thumb position/text - binding.scrollThumbText.text = indicator.char.toString() - thumbAnim.animateToFinalPosition(centerY - (binding.scrollThumb.measuredHeight / 2)) - - performHapticFeedback( - if (Build.VERSION.SDK_INT >= 27) { - // Dragging across a scroller is closer to moving a text handle - HapticFeedbackConstants.TEXT_HANDLE_MOVE - } else { - HapticFeedbackConstants.KEYBOARD_TAP - } - ) - } - } - - private fun View.contains(x: Int, y: Int): Boolean { - return x in (left until right) && containsY(y) - } - - private fun View.containsY(y: Int): Boolean { - return y in (top until bottom) - } -} diff --git a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt index cc80aade9..42a66db42 100644 --- a/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/search/SearchFragment.kt @@ -72,6 +72,10 @@ class SearchFragment : Fragment() { binding.searchToolbar.apply { menu.findItem(searchModel.filterMode.toId()).isChecked = true + setNavigationOnClickListener { + findNavController().navigateUp() + } + setOnMenuItemClickListener { item -> if (item.itemId != R.id.submenu_filtering) { searchModel.updateFilterModeWithId(item.itemId, requireContext()) diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsFragment.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsFragment.kt index 24b393445..10be0109d 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsFragment.kt @@ -24,7 +24,6 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.navigation.fragment.findNavController -import org.oxycblt.auxio.MainFragmentDirections import org.oxycblt.auxio.databinding.FragmentSettingsBinding /** @@ -39,12 +38,18 @@ class SettingsFragment : Fragment() { ): View { val binding = FragmentSettingsBinding.inflate(inflater) - binding.settingsToolbar.setOnMenuItemClickListener { - parentFragment?.parentFragment?.findNavController()?.navigate( - MainFragmentDirections.actionShowAbout() - ) + binding.settingsToolbar.apply { + setOnMenuItemClickListener { + findNavController().navigate( + SettingsFragmentDirections.actionShowAbout() + ) - true + true + } + + setNavigationOnClickListener { + findNavController().navigateUp() + } } return binding.root diff --git a/app/src/main/java/org/oxycblt/auxio/songs/SongsAdapter.kt b/app/src/main/java/org/oxycblt/auxio/songs/SongsAdapter.kt deleted file mode 100644 index 79df6bb79..000000000 --- a/app/src/main/java/org/oxycblt/auxio/songs/SongsAdapter.kt +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2021 Auxio Project - * SongsAdapter.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.songs - -import android.view.View -import android.view.ViewGroup -import androidx.recyclerview.widget.RecyclerView -import org.oxycblt.auxio.music.Song -import org.oxycblt.auxio.recycler.viewholders.SongViewHolder - -/** - * The adapter for [SongsFragment], shows basic songs without durations. - * @param data List of [Song]s to be shown - * @param doOnClick What to do on a click action - * @param doOnLongClick What to do on a long click action - * @author OxygenCobalt - */ -class SongsAdapter( - private val data: List, - private val doOnClick: (data: Song) -> Unit, - private val doOnLongClick: (view: View, data: Song) -> Unit -) : RecyclerView.Adapter() { - - override fun getItemCount(): Int = data.size - - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): SongViewHolder { - return SongViewHolder.from(parent.context, doOnClick, doOnLongClick) - } - - override fun onBindViewHolder(holder: SongViewHolder, position: Int) { - holder.bind(data[position]) - } -} diff --git a/app/src/main/java/org/oxycblt/auxio/songs/SongsFragment.kt b/app/src/main/java/org/oxycblt/auxio/songs/SongsFragment.kt deleted file mode 100644 index a9c53f4fc..000000000 --- a/app/src/main/java/org/oxycblt/auxio/songs/SongsFragment.kt +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2021 Auxio Project - * SongsFragment.kt is part of Auxio. - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.oxycblt.auxio.songs - -import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import androidx.fragment.app.Fragment -import androidx.fragment.app.activityViewModels -import androidx.recyclerview.widget.GridLayoutManager -import org.oxycblt.auxio.R -import org.oxycblt.auxio.databinding.FragmentSongsBinding -import org.oxycblt.auxio.logD -import org.oxycblt.auxio.music.MusicStore -import org.oxycblt.auxio.playback.PlaybackViewModel -import org.oxycblt.auxio.recycler.sliceArticle -import org.oxycblt.auxio.spans -import org.oxycblt.auxio.ui.newMenu - -/** - * A [Fragment] that shows a list of all songs on the device. - * Contains options to search/shuffle them. - * @author OxygenCobalt - */ -class SongsFragment : Fragment() { - private val playbackModel: PlaybackViewModel by activityViewModels() - private val musicStore = MusicStore.getInstance() - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - val binding = FragmentSongsBinding.inflate(inflater) - val songAdapter = SongsAdapter(musicStore.songs, playbackModel::playSong, ::newMenu) - - // --- UI SETUP --- - - binding.songToolbar.apply { - setOnMenuItemClickListener { - if (it.itemId == R.id.action_shuffle) { - playbackModel.shuffleAll() - true - } else false - } - } - - binding.songRecycler.apply { - adapter = songAdapter - setHasFixedSize(true) - - if (spans != 1) { - layoutManager = GridLayoutManager(requireContext(), spans) - } - } - - binding.songFastScroll.setup(binding.songRecycler) { pos -> - // Get the first character [respecting articles] - val char = musicStore.songs[pos].name.sliceArticle().first().uppercaseChar() - - if (char.isDigit()) '#' else char - } - - logD("Fragment created.") - - return binding.root - } -} diff --git a/app/src/main/res/drawable/ui_circle.xml b/app/src/main/res/drawable/ui_circle.xml deleted file mode 100644 index a6f3dfaa6..000000000 --- a/app/src/main/res/drawable/ui_circle.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/layout-land/fragment_main.xml b/app/src/main/res/layout-land/fragment_main.xml deleted file mode 100644 index 355ddc8a4..000000000 --- a/app/src/main/res/layout-land/fragment_main.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_about.xml b/app/src/main/res/layout/fragment_about.xml index 737a4ef15..6ac2acd18 100644 --- a/app/src/main/res/layout/fragment_about.xml +++ b/app/src/main/res/layout/fragment_about.xml @@ -36,8 +36,7 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_home_list.xml b/app/src/main/res/layout/fragment_home_list.xml new file mode 100644 index 000000000..13c5f46f4 --- /dev/null +++ b/app/src/main/res/layout/fragment_home_list.xml @@ -0,0 +1,13 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_library.xml b/app/src/main/res/layout/fragment_library.xml deleted file mode 100644 index 3f8c0286c..000000000 --- a/app/src/main/res/layout/fragment_library.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_main.xml b/app/src/main/res/layout/fragment_main.xml index 9028f7458..ccee4c219 100644 --- a/app/src/main/res/layout/fragment_main.xml +++ b/app/src/main/res/layout/fragment_main.xml @@ -19,35 +19,15 @@ android:layout_height="0dp" android:layout_weight="1" app:navGraph="@navigation/nav_explore" - tools:layout="@layout/fragment_library" /> + tools:layout="@layout/fragment_home" /> - - - - - - - + android:background="?attr/colorSurface" + tools:layout="@layout/fragment_compact_playback" /> \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_search.xml b/app/src/main/res/layout/fragment_search.xml index 52b71925c..583068ad3 100644 --- a/app/src/main/res/layout/fragment_search.xml +++ b/app/src/main/res/layout/fragment_search.xml @@ -16,7 +16,7 @@ diff --git a/app/src/main/res/layout/fragment_songs.xml b/app/src/main/res/layout/fragment_songs.xml deleted file mode 100644 index 4605fe19f..000000000 --- a/app/src/main/res/layout/fragment_songs.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/view_fast_scroll.xml b/app/src/main/res/layout/view_fast_scroll.xml deleted file mode 100644 index 39bf0eb44..000000000 --- a/app/src/main/res/layout/view_fast_scroll.xml +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/menu/menu_library.xml b/app/src/main/res/menu/menu_home.xml similarity index 65% rename from app/src/main/res/menu/menu_library.xml rename to app/src/main/res/menu/menu_home.xml index 0c951bba0..745b3360d 100644 --- a/app/src/main/res/menu/menu_library.xml +++ b/app/src/main/res/menu/menu_home.xml @@ -2,11 +2,17 @@ + + + app:showAsAction="ifRoom"> + + \ No newline at end of file diff --git a/app/src/main/res/menu/menu_nav.xml b/app/src/main/res/menu/menu_nav.xml deleted file mode 100644 index bb7ec7cb9..000000000 --- a/app/src/main/res/menu/menu_nav.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/menu/menu_songs.xml b/app/src/main/res/menu/menu_songs.xml deleted file mode 100644 index fa32396f5..000000000 --- a/app/src/main/res/menu/menu_songs.xml +++ /dev/null @@ -1,9 +0,0 @@ - - - - \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_explore.xml b/app/src/main/res/navigation/nav_explore.xml index e39b151d7..aa1ca9425 100644 --- a/app/src/main/res/navigation/nav_explore.xml +++ b/app/src/main/res/navigation/nav_explore.xml @@ -2,35 +2,8 @@ + app:startDestination="@id/home_fragment"> - - - - - - + android:id="@+id/home_fragment" + android:name="org.oxycblt.auxio.home.HomeFragment" + android:label="fragment_home" + tools:layout="@layout/fragment_home"> + + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/nav_main.xml b/app/src/main/res/navigation/nav_main.xml index 347d05f7a..49824152e 100644 --- a/app/src/main/res/navigation/nav_main.xml +++ b/app/src/main/res/navigation/nav_main.xml @@ -32,8 +32,8 @@ app:popEnterAnim="@anim/anim_stationary" app:popExitAnim="@anim/anim_nav_slide_down" /> + + + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index e26407a09..ea3854e66 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -6,7 +6,6 @@ --> - 4dp 8dp 16dp 24dp @@ -22,9 +21,6 @@ 48dp 64dp - 20dp - 24dp - 48dp 56dp 136dp @@ -33,8 +29,8 @@ 1dp 2dp - 48dp - 48dp + 20dp + 24dp 16sp diff --git a/app/src/main/res/values/styles_core.xml b/app/src/main/res/values/styles_core.xml index e738d3d4b..31b9064b0 100644 --- a/app/src/main/res/values/styles_core.xml +++ b/app/src/main/res/values/styles_core.xml @@ -14,7 +14,7 @@ @color/surface @color/design_default_color_primary - #FFFFFF + #00000000 ?attr/colorAccent ?attr/colorAccent diff --git a/app/src/main/res/values/styles_ui.xml b/app/src/main/res/values/styles_ui.xml index 8d76959bc..2b6cb2adf 100644 --- a/app/src/main/res/values/styles_ui.xml +++ b/app/src/main/res/values/styles_ui.xml @@ -7,7 +7,6 @@ match_parent ?android:attr/actionBarSize ?attr/colorSurface - @dimen/elevation_normal @style/ThemeOverlay.ToolbarPopup @style/TextAppearance.Toolbar.Header @@ -61,6 +60,10 @@ bounds + + +