ui: re-add more button

Re-enable the more button in preparation for multi-select.
This commit is contained in:
Alexander Capehart 2022-11-22 10:58:41 -07:00
parent 2242c413d8
commit a3772b65c0
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
23 changed files with 87 additions and 122 deletions

View file

@ -30,13 +30,12 @@
- Fixed issue where the scroll popup would not display correctly in landscape mode [#230] - Fixed issue where the scroll popup would not display correctly in landscape mode [#230]
- Fixed issue where the playback progress would continue in the notification when - Fixed issue where the playback progress would continue in the notification when
audio focus was lost audio focus was lost
- Fixed issue where the app would crash if a song menu in the genre UI was opened
- Fixed issue where the artist name would not be shown in the OS audio switcher menu - Fixed issue where the artist name would not be shown in the OS audio switcher menu
- Fixed issue where the search view would not update if the library changed - Fixed issue where the search view would not update if the library changed
- Fixed visual bug with transitions in the black theme - Fixed visual bug with transitions in the black theme
#### What's Changed #### What's Changed
- Ignore MediaStore tags is now on by default - Ignore MediaStore tags is now Auxio's default and unchangeable behavior. The option has been removed.
- Removed the "Play from genre" option in the library/detail playback mode settings+ - Removed the "Play from genre" option in the library/detail playback mode settings+
- "Use alternate notification action" is now "Custom notification action" - "Use alternate notification action" is now "Custom notification action"
- "Show covers" and "Ignore MediaStore covers" have been unified into "Album covers" - "Show covers" and "Ignore MediaStore covers" have been unified into "Album covers"

View file

@ -21,7 +21,7 @@
## About ## About
Auxio is a local music player with a fast, reliable UI/UX without the many useless features present in other music players. Built off of <a href="https://exoplayer.dev/">Exoplayer</a>, Auxio has a much better listening experience compared to other apps that use the native MediaPlayer API. In short, **It plays music.** Auxio is a local music player with a fast, reliable UI/UX without the many useless features present in other music players. Built off of <a href="https://exoplayer.dev/">Exoplayer</a>, Auxio has superior library support and listening quality compared to other apps that use outdated android functionality. In short, **It plays music.**
I primarily built Auxio for myself, but you can use it too, I guess. I primarily built Auxio for myself, but you can use it too, I guess.
@ -46,32 +46,25 @@ I primarily built Auxio for myself, but you can use it too, I guess.
- Snappy UI derived from the latest Material Design guidelines - Snappy UI derived from the latest Material Design guidelines
- Opinionated UX that prioritizes ease of use over edge cases - Opinionated UX that prioritizes ease of use over edge cases
- Customizable behavior - Customizable behavior
- Advanced media indexer that prioritizes correct metadata - Seamless artist system that unifies album artist and artist tags
- Precise/Original Dates, Sort Tags, and Release Type support (Experimental) - Advanced media indexer with support for multiple artists, release types,
precise/original dates, sort tags, and more
- SD Card-aware folder management - SD Card-aware folder management
- Reliable playback state persistence - Reliable playback state persistence
- Full ReplayGain support (On MP3, MP4, FLAC, OGG, and OPUS) - Full ReplayGain support (On MP3, MP4, FLAC, OGG, and OPUS)
- External equalizer support (ex. Wavelet) - External equalizer support (ex. Wavelet)
- Edge-to-edge - Edge-to-edge
- Embedded covers support - Embedded covers support
- Search Functionality - Search functionality
- Headset autoplay - Headset autoplay
- Stylish widgets that automatically adapt to their size - Stylish widgets that automatically adapt to their size
- Completely private and offline - Completely private and offline
- No rounded album covers (Unless you want them. Then you can.) - No rounded album covers (Unless you want them. Then you can.)
## To come in the future:
- Playlists
- Liked songs
- Artist Images
- More customization options
- Other things, probably
## Permissions ## Permissions
- Storage (`READ_EXTERNAL_STORAGE`): to read and play your media files - Storage (`READ_MEDIA_AUDIO`, `READ_EXTERNAL_STORAGE`) to read and play your media files
- Services (`FOREGROUND_SERVICE`, `WAKE_LOCK`): to keep the music playing even if the app itself is in background - Services (`FOREGROUND_SERVICE`, `WAKE_LOCK`) to keep the music playing even if the app itself is in background
## Building ## Building

View file

@ -54,7 +54,6 @@ android {
} }
} }
dependencies { dependencies {
// Kotlin // Kotlin
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"

View file

@ -44,6 +44,10 @@ import org.oxycblt.auxio.util.systemBarInsetsCompat
* *
* TODO: Add multi-select * TODO: Add multi-select
* *
* TODO: Use proper material attributes (Not the weird dimen attributes I currently have)
*
* TODO: Test out material animation system
*
* @author OxygenCobalt * @author OxygenCobalt
*/ */
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {

View file

@ -236,9 +236,10 @@ class MainFragment :
private fun handleExplorePicker(items: List<Artist>?) { private fun handleExplorePicker(items: List<Artist>?) {
if (items != null) { if (items != null) {
navModel.mainNavigateTo(MainNavigationAction.Directions( navModel.mainNavigateTo(
MainFragmentDirections.actionPickNavigationArtist(items.map { it.uid }.toTypedArray()) MainNavigationAction.Directions(
)) MainFragmentDirections.actionPickNavigationArtist(
items.map { it.uid }.toTypedArray())))
navModel.finishExploreNavigation() navModel.finishExploreNavigation()
} }
} }
@ -253,9 +254,9 @@ class MainFragment :
private fun handlePlaybackPicker(song: Song?) { private fun handlePlaybackPicker(song: Song?) {
if (song != null) { if (song != null) {
navModel.mainNavigateTo(MainNavigationAction.Directions( navModel.mainNavigateTo(
MainFragmentDirections.actionPickPlaybackArtist(song.uid) MainNavigationAction.Directions(
)) MainFragmentDirections.actionPickPlaybackArtist(song.uid)))
playbackModel.finishPlaybackArtistPicker() playbackModel.finishPlaybackArtistPicker()
} }
} }

View file

@ -192,12 +192,7 @@ private class AlbumSongViewHolder private constructor(private val binding: ItemA
binding.songName.text = item.resolveName(binding.context) binding.songName.text = item.resolveName(binding.context)
binding.songDuration.text = item.durationMs.formatDurationMs(false) binding.songDuration.text = item.durationMs.formatDurationMs(false)
binding.songMenu.setOnClickListener { listener.onOpenMenu(item, it) }
// binding.songMenu.setOnClickListener { listener.onOpenMenu(item, it) }
binding.root.setOnLongClickListener {
listener.onOpenMenu(item, it)
true
}
binding.root.setOnClickListener { listener.onItemClick(item) } binding.root.setOnClickListener { listener.onItemClick(item) }
} }

View file

@ -160,12 +160,7 @@ private class ArtistAlbumViewHolder private constructor(private val binding: Ite
binding.parentName.text = item.resolveName(binding.context) binding.parentName.text = item.resolveName(binding.context)
binding.parentInfo.text = binding.parentInfo.text =
item.date?.resolveDate(binding.context) ?: binding.context.getString(R.string.def_date) item.date?.resolveDate(binding.context) ?: binding.context.getString(R.string.def_date)
binding.parentMenu.setOnClickListener { listener.onOpenMenu(item, it) }
// binding.parentMenu.setOnClickListener { listener.onOpenMenu(item, it) }
binding.root.setOnLongClickListener {
listener.onOpenMenu(item, it)
true
}
binding.root.setOnClickListener { listener.onItemClick(item) } binding.root.setOnClickListener { listener.onItemClick(item) }
} }
@ -194,11 +189,7 @@ private class ArtistSongViewHolder private constructor(private val binding: Item
binding.songAlbumCover.bind(item) binding.songAlbumCover.bind(item)
binding.songName.text = item.resolveName(binding.context) binding.songName.text = item.resolveName(binding.context)
binding.songInfo.text = item.album.resolveName(binding.context) binding.songInfo.text = item.album.resolveName(binding.context)
// binding.songMenu.setOnClickListener { listener.onOpenMenu(item, it) } binding.songMenu.setOnClickListener { listener.onOpenMenu(item, it) }
binding.root.setOnLongClickListener {
listener.onOpenMenu(item, it)
true
}
binding.root.setOnClickListener { listener.onItemClick(item) } binding.root.setOnClickListener { listener.onItemClick(item) }
} }

View file

@ -80,7 +80,7 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
// lifecycleObject builds this in the creation step, so doing this is okay. // lifecycleObject builds this in the creation step, so doing this is okay.
private val storagePermissionLauncher: ActivityResultLauncher<String> by lifecycleObject { private val storagePermissionLauncher: ActivityResultLauncher<String> by lifecycleObject {
registerForActivityResult(ActivityResultContracts.RequestPermission()) { registerForActivityResult(ActivityResultContracts.RequestPermission()) {
musicModel.reindex() musicModel.reindex(true)
} }
} }
@ -321,7 +321,7 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
binding.homeIndexingAction.apply { binding.homeIndexingAction.apply {
visibility = View.VISIBLE visibility = View.VISIBLE
text = context.getString(R.string.lbl_retry) text = context.getString(R.string.lbl_retry)
setOnClickListener { musicModel.reindex() } setOnClickListener { musicModel.reindex(true) }
} }
} }
is Indexer.Response.NoMusic -> { is Indexer.Response.NoMusic -> {
@ -330,7 +330,7 @@ class HomeFragment : ViewBindingFragment<FragmentHomeBinding>(), Toolbar.OnMenuI
binding.homeIndexingAction.apply { binding.homeIndexingAction.apply {
visibility = View.VISIBLE visibility = View.VISIBLE
text = context.getString(R.string.lbl_retry) text = context.getString(R.string.lbl_retry)
setOnClickListener { musicModel.reindex() } setOnClickListener { musicModel.reindex(true) }
} }
} }
is Indexer.Response.NoPerms -> { is Indexer.Response.NoPerms -> {

View file

@ -32,7 +32,8 @@ import org.oxycblt.auxio.music.Song
* *
* Pretty much each service component needs to load bitmaps of some kind, but doing a blind image * Pretty much each service component needs to load bitmaps of some kind, but doing a blind image
* request with some target callbacks could result in overlapping requests causing incorrect * request with some target callbacks could result in overlapping requests causing incorrect
* updates. This class (to an extent) resolves this by adding several guards * updates. This class (to an extent) resolves this by adding a concurrency guard to the image
* callbacks.
* *
* @author OxygenCobalt * @author OxygenCobalt
*/ */

View file

@ -284,15 +284,11 @@ class Song constructor(raw: Raw, settings: Settings) : Music() {
get() = unlikelyToBeNull(_album) get() = unlikelyToBeNull(_album)
private val artistMusicBrainzIds = raw.artistMusicBrainzIds.parseMultiValue(settings) private val artistMusicBrainzIds = raw.artistMusicBrainzIds.parseMultiValue(settings)
private val artistNames = raw.artistNames.parseMultiValue(settings) private val artistNames = raw.artistNames.parseMultiValue(settings)
private val artistSortNames = raw.artistSortNames.parseMultiValue(settings) private val artistSortNames = raw.artistSortNames.parseMultiValue(settings)
private val albumArtistMusicBrainzIds = raw.albumArtistMusicBrainzIds.parseMultiValue(settings) private val albumArtistMusicBrainzIds = raw.albumArtistMusicBrainzIds.parseMultiValue(settings)
private val albumArtistNames = raw.albumArtistNames.parseMultiValue(settings) private val albumArtistNames = raw.albumArtistNames.parseMultiValue(settings)
private val albumArtistSortNames = raw.albumArtistSortNames.parseMultiValue(settings) private val albumArtistSortNames = raw.albumArtistSortNames.parseMultiValue(settings)
private val rawArtists = private val rawArtists =

View file

@ -36,19 +36,16 @@ class MusicViewModel : ViewModel(), Indexer.Callback {
private val _statistics = MutableStateFlow<Statistics?>(null) private val _statistics = MutableStateFlow<Statistics?>(null)
/** The current statistics of the music library. */ /** The current statistics of the music library. */
val statistics: StateFlow<Statistics?> get() = _statistics val statistics: StateFlow<Statistics?>
get() = _statistics
init { init {
indexer.registerCallback(this) indexer.registerCallback(this)
} }
/** Re-index the music library. */ /** Re-index the music library while using the cache. */
fun reindex() { fun reindex(ignoreCache: Boolean) {
indexer.requestReindex(true) indexer.requestReindex(ignoreCache)
}
fun rescan() {
indexer.requestReindex(false)
} }
override fun onIndexerStateChanged(state: Indexer.State?) { override fun onIndexerStateChanged(state: Indexer.State?) {
@ -57,13 +54,13 @@ class MusicViewModel : ViewModel(), Indexer.Callback {
if (state is Indexer.State.Complete && state.response is Indexer.Response.Ok) { if (state is Indexer.State.Complete && state.response is Indexer.Response.Ok) {
val library = state.response.library val library = state.response.library
_statistics.value = Statistics( _statistics.value =
library.songs.size, Statistics(
library.albums.size, library.songs.size,
library.artists.size, library.albums.size,
library.genres.size, library.artists.size,
library.songs.sumOf { it.durationMs } library.genres.size,
) library.songs.sumOf { it.durationMs })
} }
} }
@ -71,9 +68,7 @@ class MusicViewModel : ViewModel(), Indexer.Callback {
indexer.unregisterCallback(this) indexer.unregisterCallback(this)
} }
/** /** Non-manipulated statistics about the music library. */
* Non-manipulated statistics about the music library.
*/
data class Statistics( data class Statistics(
/** The amount of songs. */ /** The amount of songs. */
val songs: Int, val songs: Int,
@ -83,6 +78,7 @@ class MusicViewModel : ViewModel(), Indexer.Callback {
val artists: Int, val artists: Int,
/** The amount of genres. */ /** The amount of genres. */
val genres: Int, val genres: Int,
/** The total duration of the music library. */
val durationMs: Long val durationMs: Long
) )
} }

View file

@ -18,12 +18,7 @@
package org.oxycblt.auxio.music package org.oxycblt.auxio.music
import android.content.Context import android.content.Context
import android.os.Build import java.text.SimpleDateFormat
import androidx.annotation.RequiresApi
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.temporal.TemporalQueries
import java.util.Locale
import kotlin.math.max import kotlin.math.max
import kotlin.math.min import kotlin.math.min
import org.oxycblt.auxio.BuildConfig import org.oxycblt.auxio.BuildConfig
@ -31,7 +26,6 @@ import org.oxycblt.auxio.R
import org.oxycblt.auxio.util.inRangeOrNull import org.oxycblt.auxio.util.inRangeOrNull
import org.oxycblt.auxio.util.logE import org.oxycblt.auxio.util.logE
import org.oxycblt.auxio.util.nonZeroOrNull import org.oxycblt.auxio.util.nonZeroOrNull
import java.text.SimpleDateFormat
/** /**
* An ISO-8601/RFC 3339 Date. * An ISO-8601/RFC 3339 Date.
@ -92,9 +86,12 @@ class Date private constructor(private val tokens: List<Int>) : Comparable<Date>
private fun resolveFullDate(context: Context): String { private fun resolveFullDate(context: Context): String {
return if (month != null) { return if (month != null) {
// Parse out from an ISO-ish format
val format = (SimpleDateFormat.getDateInstance() as SimpleDateFormat) val format = (SimpleDateFormat.getDateInstance() as SimpleDateFormat)
format.applyPattern("yyyy-MM-dd") format.applyPattern("yyyy-MM")
val date = format.parse("$year-$month-${day ?: 1}") ?: return resolveYear(context) val date = format.parse("$year-$month") ?: return resolveYear(context)
// Reformat as a readable month and year
format.applyPattern("MMM yyyy") format.applyPattern("MMM yyyy")
format.format(date) format.format(date)
} else { } else {
@ -264,8 +261,7 @@ sealed class ReleaseType {
/** /**
* Roughly analogous to the MusicBrainz "live" and "remix" secondary types. Unlike the main * Roughly analogous to the MusicBrainz "live" and "remix" secondary types. Unlike the main
* types, these only modify an existing, primary type. They are not implemented for secondary * types, these only modify an existing, primary type.
* types, however they may be expanded to compilations in the future.
*/ */
enum class Refinement { enum class Refinement {
LIVE, LIVE,
@ -274,7 +270,7 @@ sealed class ReleaseType {
companion object { companion object {
// Note: The parsing code is extremely clever in order to reduce duplication. It's // Note: The parsing code is extremely clever in order to reduce duplication. It's
// better just to read the specification behind release types than follow this code. // better just to read the specification behind release types than to follow this code.
fun parse(types: List<String>): ReleaseType? { fun parse(types: List<String>): ReleaseType? {
val primary = types.getOrNull(0) ?: return null val primary = types.getOrNull(0) ?: return null

View file

@ -70,7 +70,6 @@ class SeparatorsDialog : ViewBindingDialogFragment<DialogSeparatorsBinding>() {
} }
companion object { companion object {
private const val SEPARATOR_COMMA = ',' private const val SEPARATOR_COMMA = ','
private const val SEPARATOR_SEMICOLON = ';' private const val SEPARATOR_SEMICOLON = ';'
private const val SEPARATOR_SLASH = '/' private const val SEPARATOR_SLASH = '/'

View file

@ -19,13 +19,11 @@ package org.oxycblt.auxio.music.picker
import android.os.Bundle import android.os.Bundle
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs import androidx.navigation.fragment.navArgs
import org.oxycblt.auxio.databinding.DialogMusicPickerBinding import org.oxycblt.auxio.databinding.DialogMusicPickerBinding
import org.oxycblt.auxio.music.Music import org.oxycblt.auxio.music.Music
import org.oxycblt.auxio.ui.NavigationViewModel import org.oxycblt.auxio.ui.NavigationViewModel
import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.ui.recycler.Item
import org.oxycblt.auxio.util.collectImmediately
/** /**
* The [ArtistPickerDialog] for ambiguous artist navigation operations. * The [ArtistPickerDialog] for ambiguous artist navigation operations.

View file

@ -24,7 +24,6 @@ import org.oxycblt.auxio.music.Artist
import org.oxycblt.auxio.playback.PlaybackViewModel import org.oxycblt.auxio.playback.PlaybackViewModel
import org.oxycblt.auxio.ui.recycler.Item import org.oxycblt.auxio.ui.recycler.Item
import org.oxycblt.auxio.util.androidActivityViewModels import org.oxycblt.auxio.util.androidActivityViewModels
import org.oxycblt.auxio.util.unlikelyToBeNull
/** /**
* The [ArtistPickerDialog] for ambiguous artist playback operations. * The [ArtistPickerDialog] for ambiguous artist playback operations.
@ -42,8 +41,6 @@ class ArtistPlaybackPickerDialog : ArtistPickerDialog() {
override fun onItemClick(item: Item) { override fun onItemClick(item: Item) {
super.onItemClick(item) super.onItemClick(item)
check(item is Artist) { "Unexpected datatype: ${item::class.simpleName}" } check(item is Artist) { "Unexpected datatype: ${item::class.simpleName}" }
pickerModel.currentSong.value?.let { song -> pickerModel.currentSong.value?.let { song -> playbackModel.playFromArtist(song, item) }
playbackModel.playFromArtist(song, item)
}
} }
} }

View file

@ -1,3 +1,20 @@
/*
* Copyright (c) 2022 Auxio Project
*
* 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 <https://www.gnu.org/licenses/>.
*/
package org.oxycblt.auxio.music.picker package org.oxycblt.auxio.music.picker
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@ -13,15 +30,17 @@ class MusicPickerViewModel : ViewModel(), MusicStore.Callback {
private val musicStore = MusicStore.getInstance() private val musicStore = MusicStore.getInstance()
private val _currentSong = MutableStateFlow<Song?>(null) private val _currentSong = MutableStateFlow<Song?>(null)
val currentSong: StateFlow<Song?> get() = _currentSong val currentSong: StateFlow<Song?>
get() = _currentSong
private val _currentArtists = MutableStateFlow<List<Artist>?>(null) private val _currentArtists = MutableStateFlow<List<Artist>?>(null)
val currentArtists: StateFlow<List<Artist>?> get() = _currentArtists val currentArtists: StateFlow<List<Artist>?>
get() = _currentArtists
fun setSongUid(uid: Music.UID) { fun setSongUid(uid: Music.UID) {
val library = unlikelyToBeNull(musicStore.library) val library = unlikelyToBeNull(musicStore.library)
_currentSong.value = library.find(uid) _currentSong.value = library.find(uid)
_currentArtists.value = _currentSong.value?.artists _currentArtists.value = _currentSong.value?.artists
} }
fun setArtistUids(uids: Array<Music.UID>) { fun setArtistUids(uids: Array<Music.UID>) {
@ -36,9 +55,9 @@ class MusicPickerViewModel : ViewModel(), MusicStore.Callback {
if (song != null) { if (song != null) {
_currentSong.value = library.sanitize(song) _currentSong.value = library.sanitize(song)
_currentArtists.value = _currentSong.value?.artists _currentArtists.value = _currentSong.value?.artists
} else if (artists != null){ } else if (artists != null) {
_currentArtists.value = artists.mapNotNull { library.sanitize(it) } _currentArtists.value = artists.mapNotNull { library.sanitize(it) }
} }
} }
} }
} }

View file

@ -124,7 +124,7 @@ class PlaybackViewModel(application: Application) :
} }
} }
/** Complete the picker opening process when playing from an artist. */ /** Complete the picker opening process when playing from an artist. */
fun finishPlaybackArtistPicker() { fun finishPlaybackArtistPicker() {
_artistPlaybackPickerSong.value = null _artistPlaybackPickerSong.value = null
} }

View file

@ -76,12 +76,14 @@ class AboutFragment : ViewBindingFragment<FragmentAboutBinding>() {
val binding = requireBinding() val binding = requireBinding()
binding.aboutSongCount.text = getString(R.string.fmt_lib_song_count, statistics?.songs ?: 0) binding.aboutSongCount.text = getString(R.string.fmt_lib_song_count, statistics?.songs ?: 0)
requireBinding().aboutAlbumCount.text = getString(R.string.fmt_lib_album_count, statistics?.albums ?: 0) requireBinding().aboutAlbumCount.text =
getString(R.string.fmt_lib_album_count, statistics?.albums ?: 0)
requireBinding().aboutArtistCount.text = requireBinding().aboutArtistCount.text =
getString(R.string.fmt_lib_artist_count, statistics?.artists ?: 0) getString(R.string.fmt_lib_artist_count, statistics?.artists ?: 0)
requireBinding().aboutGenreCount.text = getString(R.string.fmt_lib_genre_count, statistics?.genres ?: 0) requireBinding().aboutGenreCount.text =
getString(R.string.fmt_lib_genre_count, statistics?.genres ?: 0)
binding.aboutTotalDuration.text = binding.aboutTotalDuration.text =
getString( getString(

View file

@ -120,6 +120,8 @@ class PreferenceFragment : PreferenceFragmentCompat() {
when (preference.key) { when (preference.key) {
context.getString(R.string.set_key_save_state) -> { context.getString(R.string.set_key_save_state) -> {
playbackModel.savePlaybackState { saved -> playbackModel.savePlaybackState { saved ->
// Use the nullable context, as we could try to show a toast when this
// fragment is no longer attached.
if (saved) { if (saved) {
this.context?.showToast(R.string.lbl_state_saved) this.context?.showToast(R.string.lbl_state_saved)
} else { } else {
@ -144,12 +146,8 @@ class PreferenceFragment : PreferenceFragmentCompat() {
this.context?.showToast(R.string.err_did_not_restore) this.context?.showToast(R.string.err_did_not_restore)
} }
} }
context.getString(R.string.set_key_reindex) -> { context.getString(R.string.set_key_reindex) -> musicModel.reindex(true)
musicModel.reindex() context.getString(R.string.set_key_rescan) -> musicModel.reindex(false)
}
context.getString(R.string.set_key_rescan) -> {
musicModel.rescan()
}
else -> return super.onPreferenceTreeClick(preference) else -> return super.onPreferenceTreeClick(preference)
} }

View file

@ -42,11 +42,7 @@ class SongViewHolder private constructor(private val binding: ItemSongBinding) :
binding.songAlbumCover.bind(item) binding.songAlbumCover.bind(item)
binding.songName.text = item.resolveName(binding.context) binding.songName.text = item.resolveName(binding.context)
binding.songInfo.text = item.resolveArtistContents(binding.context) binding.songInfo.text = item.resolveArtistContents(binding.context)
// binding.songMenu.setOnClickListener { listener.onOpenMenu(item, it) } binding.songMenu.setOnClickListener { listener.onOpenMenu(item, it) }
binding.root.setOnLongClickListener {
listener.onOpenMenu(item, it)
true
}
binding.root.setOnClickListener { listener.onItemClick(item) } binding.root.setOnClickListener { listener.onItemClick(item) }
} }
@ -79,11 +75,7 @@ class AlbumViewHolder private constructor(private val binding: ItemParentBinding
binding.parentImage.bind(item) binding.parentImage.bind(item)
binding.parentName.text = item.resolveName(binding.context) binding.parentName.text = item.resolveName(binding.context)
binding.parentInfo.text = item.resolveArtistContents(binding.context) binding.parentInfo.text = item.resolveArtistContents(binding.context)
// binding.parentMenu.setOnClickListener { listener.onOpenMenu(item, it) } binding.parentMenu.setOnClickListener { listener.onOpenMenu(item, it) }
binding.root.setOnLongClickListener {
listener.onOpenMenu(item, it)
true
}
binding.root.setOnClickListener { listener.onItemClick(item) } binding.root.setOnClickListener { listener.onItemClick(item) }
} }
@ -129,11 +121,7 @@ class ArtistViewHolder private constructor(private val binding: ItemParentBindin
binding.context.getPlural(R.plurals.fmt_album_count, item.albums.size) binding.context.getPlural(R.plurals.fmt_album_count, item.albums.size)
} }
// binding.parentMenu.setOnClickListener { listener.onOpenMenu(item, it) } binding.parentMenu.setOnClickListener { listener.onOpenMenu(item, it) }
binding.root.setOnLongClickListener {
listener.onOpenMenu(item, it)
true
}
binding.root.setOnClickListener { listener.onItemClick(item) } binding.root.setOnClickListener { listener.onItemClick(item) }
} }
@ -172,11 +160,7 @@ class GenreViewHolder private constructor(private val binding: ItemParentBinding
R.string.fmt_two, R.string.fmt_two,
binding.context.getPlural(R.plurals.fmt_artist_count, item.artists.size), binding.context.getPlural(R.plurals.fmt_artist_count, item.artists.size),
binding.context.getPlural(R.plurals.fmt_song_count, item.songs.size)) binding.context.getPlural(R.plurals.fmt_song_count, item.songs.size))
// binding.parentMenu.setOnClickListener { listener.onOpenMenu(item, it) } binding.parentMenu.setOnClickListener { listener.onOpenMenu(item, it) }
binding.root.setOnLongClickListener {
listener.onOpenMenu(item, it)
true
}
binding.root.setOnClickListener { listener.onItemClick(item) } binding.root.setOnClickListener { listener.onItemClick(item) }
} }

View file

@ -80,7 +80,6 @@
style="@style/Widget.Auxio.Button.Icon.Small" style="@style/Widget.Auxio.Button.Icon.Small"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone"
app:icon="@drawable/ic_more_24" app:icon="@drawable/ic_more_24"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View file

@ -49,7 +49,6 @@
style="@style/Widget.Auxio.Button.Icon.Small" style="@style/Widget.Auxio.Button.Icon.Small"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone"
app:icon="@drawable/ic_more_24" app:icon="@drawable/ic_more_24"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"

View file

@ -49,7 +49,6 @@
style="@style/Widget.Auxio.Button.Icon.Small" style="@style/Widget.Auxio.Button.Icon.Small"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:visibility="gone"
app:icon="@drawable/ic_more_24" app:icon="@drawable/ic_more_24"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"