diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt index ab9e17810..1dadf3ad8 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeFragment.kt @@ -95,7 +95,7 @@ class HomeFragment : ViewBindingFragment(), Toolbar.OnMenuI binding.homeToolbar.alpha = 1f - (abs(offset.toFloat()) / (range.toFloat() / 2)) - binding.homePager.updatePadding( + binding.homeContent.updatePadding( bottom = binding.homeAppbar.totalScrollRange + offset) }) } @@ -246,8 +246,7 @@ class HomeFragment : ViewBindingFragment(), Toolbar.OnMenuI } private fun updateSortMenu(displayMode: DisplayMode, isVisible: (Int) -> Boolean) { - val sortItem = - requireNotNull(sortItem) { "Cannot update sort menu when view does not exist" } + val sortItem = requireNotNull(sortItem) { "Cannot update sort menu while detached" } val toHighlight = homeModel.getSortForDisplay(displayMode) diff --git a/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt b/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt index e46933aab..a936af0ff 100644 --- a/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt +++ b/app/src/main/java/org/oxycblt/auxio/home/HomeViewModel.kt @@ -30,7 +30,6 @@ import org.oxycblt.auxio.settings.SettingsManager import org.oxycblt.auxio.ui.DisplayMode import org.oxycblt.auxio.ui.Sort import org.oxycblt.auxio.util.logD -import org.oxycblt.auxio.util.unlikelyToBeNull /** * The ViewModel for managing [HomeFragment]'s data, sorting modes, and tab state. @@ -107,19 +106,19 @@ class HomeViewModel : ViewModel(), SettingsManager.Callback, MusicStore.Callback when (_currentTab.value) { DisplayMode.SHOW_SONGS -> { settingsManager.libSongSort = sort - _songs.value = sort.songs(unlikelyToBeNull(_songs.value)) + _songs.value = sort.songs(_songs.value) } DisplayMode.SHOW_ALBUMS -> { settingsManager.libAlbumSort = sort - _albums.value = sort.albums(unlikelyToBeNull(_albums.value)) + _albums.value = sort.albums(_albums.value) } DisplayMode.SHOW_ARTISTS -> { settingsManager.libArtistSort = sort - _artists.value = sort.artists(unlikelyToBeNull(_artists.value)) + _artists.value = sort.artists(_artists.value) } DisplayMode.SHOW_GENRES -> { settingsManager.libGenreSort = sort - _genres.value = sort.genres(unlikelyToBeNull(_genres.value)) + _genres.value = sort.genres(_genres.value) } } } diff --git a/app/src/main/java/org/oxycblt/auxio/image/BaseFetcher.kt b/app/src/main/java/org/oxycblt/auxio/image/BaseFetcher.kt index d7e465fc2..50cfc0e67 100644 --- a/app/src/main/java/org/oxycblt/auxio/image/BaseFetcher.kt +++ b/app/src/main/java/org/oxycblt/auxio/image/BaseFetcher.kt @@ -75,6 +75,7 @@ abstract class BaseFetcher : Fetcher { } } catch (e: Exception) { logW("Unable to extract album art due to an error") + logW(e.stackTraceToString()) null } } @@ -114,6 +115,9 @@ abstract class BaseFetcher : Fetcher { } private fun fetchAospMetadataCovers(context: Context, album: Album): InputStream? { + // FIXME: Do not use use here, as Lollipop devices apparently do not have + // MediaMetadataRetriever implemented as AutoClosable. + MediaMetadataRetriever().use { ext -> // This call is time-consuming but it also doesn't seem to hold up the main thread, // so it's probably fine not to wrap it. diff --git a/app/src/main/java/org/oxycblt/auxio/music/Indexer.kt b/app/src/main/java/org/oxycblt/auxio/music/Indexer.kt index 2bdfc2213..7152c70e6 100644 --- a/app/src/main/java/org/oxycblt/auxio/music/Indexer.kt +++ b/app/src/main/java/org/oxycblt/auxio/music/Indexer.kt @@ -28,7 +28,6 @@ import kotlinx.coroutines.withContext import org.oxycblt.auxio.music.backend.Api21MediaStoreBackend import org.oxycblt.auxio.music.backend.Api29MediaStoreBackend import org.oxycblt.auxio.music.backend.Api30MediaStoreBackend -import org.oxycblt.auxio.music.backend.ExoPlayerBackend import org.oxycblt.auxio.ui.Sort import org.oxycblt.auxio.util.logD import org.oxycblt.auxio.util.logE @@ -188,7 +187,7 @@ class Indexer { else -> Api21MediaStoreBackend() } - val songs = buildSongs(context, ExoPlayerBackend(mediaStoreBackend), generation) + val songs = buildSongs(context, mediaStoreBackend, generation) if (songs.isEmpty()) { return null } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarFragment.kt index 9f38e75bc..296c6fbb2 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackBarFragment.kt @@ -75,11 +75,9 @@ class PlaybackBarFragment : ViewBindingFragment() { binding.playbackProgressBar.trackColor = requireContext().getColorStateListSafe(R.color.sel_track).defaultColor - binding.playbackSkipPrev?.setOnClickListener { playbackModel.prev() } - binding.playbackPlayPause.setOnClickListener { playbackModel.invertPlaying() } - binding.playbackSkipNext?.setOnClickListener { playbackModel.next() } + binding.playbackSkipNext.setOnClickListener { playbackModel.next() } // -- VIEWMODEL SETUP --- diff --git a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt index b87223f93..0fc0b0d9a 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/PlaybackPanelFragment.kt @@ -32,6 +32,7 @@ import org.oxycblt.auxio.playback.state.RepeatMode import org.oxycblt.auxio.ui.MainNavigationAction import org.oxycblt.auxio.ui.NavigationViewModel import org.oxycblt.auxio.ui.ViewBindingFragment +import org.oxycblt.auxio.util.getDrawableSafe import org.oxycblt.auxio.util.getSystemBarInsetsCompat import org.oxycblt.auxio.util.launch import org.oxycblt.auxio.util.logD @@ -162,7 +163,7 @@ class PlaybackPanelFragment : private fun updateRepeat(repeatMode: RepeatMode) { requireBinding().playbackRepeat.apply { isActivated = repeatMode != RepeatMode.NONE - setImageResource(repeatMode.icon) + icon = requireContext().getDrawableSafe(repeatMode.icon) } } diff --git a/app/src/main/java/org/oxycblt/auxio/playback/system/NotificationComponent.kt b/app/src/main/java/org/oxycblt/auxio/playback/system/NotificationComponent.kt index cb6a03176..ce5416265 100644 --- a/app/src/main/java/org/oxycblt/auxio/playback/system/NotificationComponent.kt +++ b/app/src/main/java/org/oxycblt/auxio/playback/system/NotificationComponent.kt @@ -170,7 +170,7 @@ class NotificationComponent( isShuffled: Boolean ): NotificationCompat.Action { val drawableRes = - if (isShuffled) R.drawable.ic_shuffle_state else R.drawable.ic_remote_shuffle_off + if (isShuffled) R.drawable.ic_shuffle else R.drawable.ic_remote_shuffle_off return buildAction(context, PlaybackService.ACTION_INVERT_SHUFFLE, drawableRes) } diff --git a/app/src/main/java/org/oxycblt/auxio/settings/SettingsCompat.kt b/app/src/main/java/org/oxycblt/auxio/settings/SettingsCompat.kt index 93ae2f008..af14da91b 100644 --- a/app/src/main/java/org/oxycblt/auxio/settings/SettingsCompat.kt +++ b/app/src/main/java/org/oxycblt/auxio/settings/SettingsCompat.kt @@ -74,6 +74,7 @@ fun handleAccentCompat(prefs: SharedPreferences): Accent { } } + // TODO: Default accent on android 12 should be dynamic colors return Accent.from(prefs.getInt(SettingsManager.KEY_ACCENT, 5)) } diff --git a/app/src/main/java/org/oxycblt/auxio/ui/IndicatorMaterialButton.kt b/app/src/main/java/org/oxycblt/auxio/ui/IndicatorMaterialButton.kt new file mode 100644 index 000000000..7183286b3 --- /dev/null +++ b/app/src/main/java/org/oxycblt/auxio/ui/IndicatorMaterialButton.kt @@ -0,0 +1,54 @@ +/* + * 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 . + */ + +package org.oxycblt.auxio.ui + +import android.content.Context +import android.graphics.Canvas +import android.util.AttributeSet +import androidx.annotation.AttrRes +import com.google.android.material.button.MaterialButton +import org.oxycblt.auxio.R +import org.oxycblt.auxio.util.getDrawableSafe + +class IndicatorMaterialButton +@JvmOverloads +constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) : + MaterialButton(context, attrs, defStyleAttr) { + private val indicatorDrawable = context.getDrawableSafe(R.drawable.ui_indicator) + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec) + + // Put the indicator right below the icon. + val x = (measuredWidth - indicatorDrawable.intrinsicWidth) / 2 + val y = ((measuredHeight - iconSize) / 2) + iconSize + + indicatorDrawable.bounds.set( + x, y, x + indicatorDrawable.intrinsicWidth, y + indicatorDrawable.intrinsicHeight) + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + + // I would use onDrawForeground but apparently that isn't called by Lollipop devices. + // This is not referenced in the documentation at all. + if (isActivated) { + indicatorDrawable.draw(canvas) + } + } +} diff --git a/app/src/main/java/org/oxycblt/auxio/ui/StyledImageButton.kt b/app/src/main/java/org/oxycblt/auxio/ui/StyledImageButton.kt deleted file mode 100644 index f04401770..000000000 --- a/app/src/main/java/org/oxycblt/auxio/ui/StyledImageButton.kt +++ /dev/null @@ -1,124 +0,0 @@ -/* - * 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 . - */ - -package org.oxycblt.auxio.ui - -import android.content.Context -import android.graphics.Canvas -import android.graphics.Matrix -import android.graphics.RectF -import android.util.AttributeSet -import androidx.annotation.AttrRes -import androidx.appcompat.widget.AppCompatImageButton -import org.oxycblt.auxio.R -import org.oxycblt.auxio.util.getDimenSizeSafe -import org.oxycblt.auxio.util.getDrawableSafe - -/** - * An [AppCompatImageButton] that applies many of the stylistic choices that Auxio uses regarding - * buttons. - * - * More specifically, this class add two features: - * - Specification of the icon size. This is to accommodate the playback buttons, which tend to be - * larger as by default the playback icons look terrible with the gobs of whitespace everywhere. - * - Addition of an indicator, which is a dot that can denote when a button is active. This is also - * useful for the playback buttons, as at times highlighting them is not enough to differentiate - * them. - * @author OxygenCobalt - * - * TODO: Remove this for Material Buttons (I hope) - */ -class StyledImageButton -@JvmOverloads -constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) : - AppCompatImageButton(context, attrs, defStyleAttr) { - private val iconSize: Int - private var hasIndicator = false - set(value) { - field = value - invalidate() - } - - private val centerMatrix = Matrix() - private val matrixSrc = RectF() - private val matrixDst = RectF() - private val indicatorDrawable = context.getDrawableSafe(R.drawable.ui_indicator) - - init { - val size = context.getDimenSizeSafe(R.dimen.size_btn_small) - minimumWidth = size - minimumHeight = size - scaleType = ScaleType.MATRIX - setBackgroundResource(R.drawable.ui_large_unbounded_ripple) - - val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.StyledImageButton) - iconSize = - styledAttrs - .getDimension( - R.styleable.StyledImageButton_iconSize, - context.getDimenSizeSafe(R.dimen.size_icon_normal).toFloat()) - .toInt() - hasIndicator = styledAttrs.getBoolean(R.styleable.StyledImageButton_hasIndicator, false) - styledAttrs.recycle() - } - - override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { - super.onMeasure(widthMeasureSpec, heightMeasureSpec) - - // FIXME: Scale this drawable based on available space after padding - - imageMatrix = - centerMatrix.apply { - reset() - drawable?.let { drawable -> - // Android is too good to allow us to set a fixed image size, so we instead need - // to define a matrix to scale an image directly. - - // First scale the icon up to the desired size. - matrixSrc.set( - 0f, - 0f, - drawable.intrinsicWidth.toFloat(), - drawable.intrinsicHeight.toFloat()) - matrixDst.set(0f, 0f, iconSize.toFloat(), iconSize.toFloat()) - centerMatrix.setRectToRect(matrixSrc, matrixDst, Matrix.ScaleToFit.CENTER) - - // Then actually center it into the icon, which the previous call does not - // actually do. - centerMatrix.postTranslate( - (measuredWidth - iconSize) / 2f, (measuredHeight - iconSize) / 2f) - } - } - - // Put the indicator right below the icon. - val x = (measuredWidth - indicatorDrawable.intrinsicWidth) / 2 - val y = ((measuredHeight - iconSize) / 2) + iconSize - - indicatorDrawable.bounds.set( - x, y, x + indicatorDrawable.intrinsicWidth, y + indicatorDrawable.intrinsicHeight) - } - - override fun onDraw(canvas: Canvas) { - super.onDraw(canvas) - - // I would use onDrawForeground but apparently that isn't called by Lollipop devices. - // This is not referenced in the documentation at all. - if (hasIndicator && isActivated) { - indicatorDrawable.draw(canvas) - } - } -} diff --git a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentAdapter.kt b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentAdapter.kt index 4eb9cd822..a02b819b0 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentAdapter.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentAdapter.kt @@ -92,7 +92,7 @@ class AccentViewHolder private constructor(private val binding: ItemAccentBindin fun setSelected(isSelected: Boolean) { binding.accent.apply { isEnabled = !isSelected - imageTintList = + iconTint = if (isSelected) { context.getAttrColorSafe(R.attr.colorSurface).stateList } else { diff --git a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentGridLayoutManager.kt b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentGridLayoutManager.kt index 2cb7b8cab..36513c9e1 100644 --- a/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentGridLayoutManager.kt +++ b/app/src/main/java/org/oxycblt/auxio/ui/accent/AccentGridLayoutManager.kt @@ -37,7 +37,7 @@ class AccentGridLayoutManager( ) : GridLayoutManager(context, attrs, defStyleAttr, defStyleRes) { // We use 72dp here since that's the rough size of the accent item. // This will need to be modified if this is used beyond the accent dialog. - private var columnWidth = context.pxOfDp(72f) + private var columnWidth = context.pxOfDp(64f) private var lastWidth = -1 private var lastHeight = -1 diff --git a/app/src/main/res/drawable/ic_shuffle_state.xml b/app/src/main/res/drawable/ic_shuffle.xml similarity index 92% rename from app/src/main/res/drawable/ic_shuffle_state.xml rename to app/src/main/res/drawable/ic_shuffle.xml index 95393c79f..0c2210449 100644 --- a/app/src/main/res/drawable/ic_shuffle_state.xml +++ b/app/src/main/res/drawable/ic_shuffle.xml @@ -2,7 +2,7 @@ - - - - - - @@ -123,27 +123,27 @@ app:layout_constraintTop_toBottomOf="@+id/playback_seek_bar" tools:src="@drawable/ic_pause" /> - - - - @@ -112,27 +112,27 @@ app:layout_constraintStart_toStartOf="@+id/playback_seek_bar" tools:src="@drawable/ic_pause" /> - - + tools:src="@drawable/ic_album" /> - - - - + app:layout_constraintTop_toTopOf="parent" /> - \ No newline at end of file + diff --git a/app/src/main/res/layout-w600dp-land/fragment_playback_panel.xml b/app/src/main/res/layout-w600dp-land/fragment_playback_panel.xml index 99b17d40f..bfdaa31a8 100644 --- a/app/src/main/res/layout-w600dp-land/fragment_playback_panel.xml +++ b/app/src/main/res/layout-w600dp-land/fragment_playback_panel.xml @@ -8,7 +8,7 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/app/src/main/res/layout/fragment_detail.xml b/app/src/main/res/layout/fragment_detail.xml index 0d43bd3de..c4a29ba54 100644 --- a/app/src/main/res/layout/fragment_detail.xml +++ b/app/src/main/res/layout/fragment_detail.xml @@ -15,9 +15,11 @@ app:liftOnScroll="true" app:liftOnScrollTargetViewId="@id/detail_recycler"> + + + style="@style/Widget.Auxio.Toolbar.Icon.Actions" /> diff --git a/app/src/main/res/layout/fragment_home.xml b/app/src/main/res/layout/fragment_home.xml index 104b13dd8..7e3d572b5 100644 --- a/app/src/main/res/layout/fragment_home.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -12,7 +12,9 @@ @@ -30,6 +32,7 @@ @@ -98,7 +101,7 @@ android:layout_height="wrap_content" android:layout_margin="@dimen/spacing_medium" android:contentDescription="@string/desc_shuffle_all" - android:src="@drawable/ic_shuffle_state" /> + android:src="@drawable/ic_shuffle" /> diff --git a/app/src/main/res/layout/fragment_playback_bar.xml b/app/src/main/res/layout/fragment_playback_bar.xml index 218048803..dcf3e67d9 100644 --- a/app/src/main/res/layout/fragment_playback_bar.xml +++ b/app/src/main/res/layout/fragment_playback_bar.xml @@ -43,14 +43,25 @@ app:layout_constraintTop_toBottomOf="@+id/playback_song" tools:text="Artist Name / Album Name" /> - + +