image: make coverview respond to settings

Make CoverView respond to all cover settings and the round mode
setting.
This commit is contained in:
Alexander Capehart 2023-07-04 14:55:36 -06:00
parent e490ff64c1
commit ada446767d
No known key found for this signature in database
GPG key ID: 37DBE3621FE9AD47
5 changed files with 69 additions and 31 deletions

View file

@ -6,9 +6,10 @@
- Menus have been refreshed with a cleaner look - Menus have been refreshed with a cleaner look
#### What's Fixed #### What's Fixed
- Fixed issue where one could not navigate to settings after navigating - Fixed issue where one could not navigate to settings after navigating elsewhere
elsewhere
- Fixed the queue list being non-scrollable in certain cases - Fixed the queue list being non-scrollable in certain cases
- Fixed notification album covers not updating after changing the cover
aspect ratio setting
#### Dev/Meta #### Dev/Meta
- Unified navigation graph - Unified navigation graph

View file

@ -76,14 +76,14 @@ import org.oxycblt.auxio.util.getInteger
class CoverView class CoverView
@JvmOverloads @JvmOverloads
constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) : constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr: Int = 0) :
FrameLayout(context, attrs, defStyleAttr) { FrameLayout(context, attrs, defStyleAttr), ImageSettings.Listener, UISettings.Listener {
@Inject lateinit var imageLoader: ImageLoader @Inject lateinit var imageLoader: ImageLoader
@Inject lateinit var uiSettings: UISettings @Inject lateinit var uiSettings: UISettings
@Inject lateinit var imageSettings: ImageSettings @Inject lateinit var imageSettings: ImageSettings
private val image: ImageView private val image: ImageView
data class PlaybackIndicator( private data class PlaybackIndicator(
val view: ImageView, val view: ImageView,
val playingDrawable: AnimationDrawable, val playingDrawable: AnimationDrawable,
val pausedDrawable: Drawable val pausedDrawable: Drawable
@ -91,27 +91,30 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
private val playbackIndicator: PlaybackIndicator? private val playbackIndicator: PlaybackIndicator?
private val selectionBadge: ImageView? private val selectionBadge: ImageView?
private val sizing: Int
@DimenRes private val iconSizeRes: Int? @DimenRes private val iconSizeRes: Int?
@DimenRes private val cornerRadiusRes: Int? @DimenRes private var cornerRadiusRes: Int?
private var fadeAnimator: ValueAnimator? = null private var fadeAnimator: ValueAnimator? = null
private val indicatorMatrix = Matrix() private val indicatorMatrix = Matrix()
private val indicatorMatrixSrc = RectF() private val indicatorMatrixSrc = RectF()
private val indicatorMatrixDst = RectF() private val indicatorMatrixDst = RectF()
private data class Cover(
val songs: Collection<Song>,
val desc: String,
@DrawableRes val errorRes: Int
)
private var currentCover: Cover? = null
init { init {
// Obtain some StyledImageView attributes to use later when theming the custom view. // Obtain some StyledImageView attributes to use later when theming the custom view.
@SuppressLint("CustomViewStyleable") @SuppressLint("CustomViewStyleable")
val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.CoverView) val styledAttrs = context.obtainStyledAttributes(attrs, R.styleable.CoverView)
val sizing = styledAttrs.getIntOrThrow(R.styleable.CoverView_sizing) sizing = styledAttrs.getIntOrThrow(R.styleable.CoverView_sizing)
iconSizeRes = SIZING_ICON_SIZE[sizing] iconSizeRes = SIZING_ICON_SIZE[sizing]
cornerRadiusRes = cornerRadiusRes = getCornerRadiusRes()
if (uiSettings.roundMode) {
SIZING_CORNER_RADII[sizing]
} else {
null
}
val playbackIndicatorEnabled = val playbackIndicatorEnabled =
styledAttrs.getBoolean(R.styleable.CoverView_enablePlaybackIndicator, true) styledAttrs.getBoolean(R.styleable.CoverView_enablePlaybackIndicator, true)
@ -149,6 +152,9 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
} else { } else {
null null
} }
imageSettings.registerListener(this)
uiSettings.registerListener(this)
} }
override fun onFinishInflate() { override fun onFinishInflate() {
@ -161,19 +167,7 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
playbackIndicator?.run { addView(view) } playbackIndicator?.run { addView(view) }
// Add backgrounds to each child for visual consistency applyBackgroundsToChildren()
for (child in children) {
child.apply {
// If there are rounded corners, we want to make sure view content will be cropped
// with it.
clipToOutline = this != image
background =
MaterialShapeDrawable().apply {
fillColor = context.getColorCompat(R.color.sel_cover_bg)
setCornerSize(cornerRadiusRes?.let(context::getDimen) ?: 0f)
}
}
}
// The selection badge has it's own background we don't want overridden, add it after // The selection badge has it's own background we don't want overridden, add it after
// all other elements. // all other elements.
@ -191,6 +185,24 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
} }
} }
override fun onDetachedFromWindow() {
super.onDetachedFromWindow()
imageSettings.unregisterListener(this)
}
override fun onImageSettingsChanged() {
val cover = currentCover ?: return
bind(cover.songs, cover.desc, cover.errorRes)
}
override fun onRoundModeChanged() {
// TODO: Make this a recreate as soon as you can make the bottom sheet stop freaking out
cornerRadiusRes = getCornerRadiusRes()
applyBackgroundsToChildren()
val cover = currentCover ?: return
bind(cover.songs, cover.desc, cover.errorRes)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec) super.onMeasure(widthMeasureSpec, heightMeasureSpec)
@ -261,6 +273,29 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
} }
} }
private fun getCornerRadiusRes() =
if (uiSettings.roundMode) {
SIZING_CORNER_RADII[sizing]
} else {
null
}
private fun applyBackgroundsToChildren() {
// Add backgrounds to each child for visual consistency
for (child in children) {
child.apply {
// If there are rounded corners, we want to make sure view content will be cropped
// with it.
clipToOutline = this != image
background =
MaterialShapeDrawable().apply {
fillColor = context.getColorCompat(R.color.sel_cover_bg)
setCornerSize(cornerRadiusRes?.let(context::getDimen) ?: 0f)
}
}
}
}
private fun invalidateRootAlpha() { private fun invalidateRootAlpha() {
alpha = if (isEnabled || isSelected) 1f else 0.5f alpha = if (isEnabled || isSelected) 1f else 0.5f
} }
@ -401,6 +436,7 @@ constructor(context: Context, attrs: AttributeSet? = null, @AttrRes defStyleAttr
CoilUtils.dispose(image) CoilUtils.dispose(image)
imageLoader.enqueue(request.build()) imageLoader.enqueue(request.build())
contentDescription = desc contentDescription = desc
currentCover = Cover(songs, desc, errorRes)
} }
/** /**

View file

@ -39,7 +39,7 @@ interface ImageSettings : Settings<ImageSettings.Listener> {
interface Listener { interface Listener {
/** Called when [coverMode] changes. */ /** Called when [coverMode] changes. */
fun onCoverModeChanged() {} fun onImageSettingsChanged() {}
} }
} }
@ -77,9 +77,10 @@ class ImageSettingsImpl @Inject constructor(@ApplicationContext context: Context
} }
override fun onSettingChanged(key: String, listener: ImageSettings.Listener) { override fun onSettingChanged(key: String, listener: ImageSettings.Listener) {
if (key == getString(R.string.set_key_cover_mode)) { if (key == getString(R.string.set_key_cover_mode) ||
logD("Dispatching cover mode setting change") key == getString(R.string.set_key_square_covers)) {
listener.onCoverModeChanged() logD("Dispatching image setting change")
listener.onImageSettingsChanged()
} }
} }

View file

@ -173,7 +173,7 @@ constructor(
// --- SETTINGS OVERRIDES --- // --- SETTINGS OVERRIDES ---
override fun onCoverModeChanged() { override fun onImageSettingsChanged() {
// Need to reload the metadata cover. // Need to reload the metadata cover.
updateMediaMetadata(playbackManager.queue.currentSong, playbackManager.parent) updateMediaMetadata(playbackManager.queue.currentSong, playbackManager.parent)
} }

View file

@ -144,7 +144,7 @@ constructor(
// Respond to settings changes that will affect the widget // Respond to settings changes that will affect the widget
override fun onRoundModeChanged() = update() override fun onRoundModeChanged() = update()
override fun onCoverModeChanged() = update() override fun onImageSettingsChanged() = update()
/** /**
* A condensed form of the playback state that is safe to use in AppWidgets. * A condensed form of the playback state that is safe to use in AppWidgets.