From ab58f87554ef16c3bd8e788da59316ce4b1490f2 Mon Sep 17 00:00:00 2001 From: David Chavez Date: Tue, 19 Sep 2023 16:18:11 +0200 Subject: [PATCH] chore(capabilities): Revamp System (#86) --- .../kotlin_audio_example/MainActivity.kt | 29 +- .../kotlinaudio/models/Capability.kt | 80 ++++-- .../kotlinaudio/models/NotificationConfig.kt | 42 --- .../kotlinaudio/models/NotificationOptions.kt | 42 +++ .../notification/NotificationManager.kt | 263 ++++++------------ 5 files changed, 213 insertions(+), 243 deletions(-) delete mode 100644 kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/models/NotificationConfig.kt create mode 100644 kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/models/NotificationOptions.kt diff --git a/kotlin-audio-example/src/main/java/com/example/kotlin_audio_example/MainActivity.kt b/kotlin-audio-example/src/main/java/com/example/kotlin_audio_example/MainActivity.kt index 7cf74eef..954a5b0b 100644 --- a/kotlin-audio-example/src/main/java/com/example/kotlin_audio_example/MainActivity.kt +++ b/kotlin-audio-example/src/main/java/com/example/kotlin_audio_example/MainActivity.kt @@ -30,11 +30,13 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import com.doublesymmetry.kotlinaudio.models.AudioPlayerState +import com.doublesymmetry.kotlinaudio.models.CapabilitiesConfig +import com.doublesymmetry.kotlinaudio.models.Capability import com.doublesymmetry.kotlinaudio.models.DefaultAudioItem import com.doublesymmetry.kotlinaudio.models.MediaSessionCallback import com.doublesymmetry.kotlinaudio.models.MediaType -import com.doublesymmetry.kotlinaudio.models.NotificationButton -import com.doublesymmetry.kotlinaudio.models.NotificationConfig +import com.doublesymmetry.kotlinaudio.models.NofiticationActionOptions +import com.doublesymmetry.kotlinaudio.models.NotificationOptions import com.doublesymmetry.kotlinaudio.models.RepeatMode import com.doublesymmetry.kotlinaudio.models.PlayerConfig import com.doublesymmetry.kotlinaudio.players.QueuedAudioPlayer @@ -42,6 +44,7 @@ import com.example.kotlin_audio_example.ui.component.ActionBottomSheet import com.example.kotlin_audio_example.ui.component.PlayerControls import com.example.kotlin_audio_example.ui.component.TrackDisplay import com.example.kotlin_audio_example.ui.theme.KotlinAudioTheme +import com.google.android.exoplayer2.ui.R import kotlinx.coroutines.delay import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach @@ -160,15 +163,21 @@ class MainActivity : ComponentActivity() { } private fun setupNotification() { - val notificationConfig = NotificationConfig( - listOf( - NotificationButton.PLAY_PAUSE(), - NotificationButton.NEXT(isCompact = true), - NotificationButton.PREVIOUS(isCompact = true), - NotificationButton.SEEK_TO - ), accentColor = null, smallIcon = null, pendingIntent = null + val capabilitiesConfig = CapabilitiesConfig( + capabilities = listOf( + Capability.PlayPause(), + Capability.Next(), + Capability.Previous(), + Capability.Forward(notificationOptions = NofiticationActionOptions(isCompact = false)), + Capability.Backward(notificationOptions = NofiticationActionOptions(isCompact = false, icon = R.drawable.exo_icon_circular_play)), + Capability.SeekTo + ), + notificationOptions = NotificationOptions( + accentColor = null, smallIcon = null, pendingIntent = null + ) ) - player.notificationManager.createNotification(notificationConfig) + + player.notificationManager.createNotification(capabilitiesConfig) } companion object { diff --git a/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/models/Capability.kt b/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/models/Capability.kt index 2f99caa1..64093b79 100644 --- a/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/models/Capability.kt +++ b/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/models/Capability.kt @@ -1,19 +1,67 @@ package com.doublesymmetry.kotlinaudio.models -enum class Capability { - PLAY, - PLAY_FROM_ID, - PLAY_FROM_SEARCH, - PAUSE, - STOP, - SEEK_TO, - SKIP, - SKIP_TO_NEXT, - SKIP_TO_PREVIOUS, - JUMP_FORWARD, - JUMP_BACKWARD, - SET_RATING, - LIKE, - DISLIKE, - BOOKMARK +/** + * Defines the capabilities supported by the media session and whether they're also supported by the notification. + * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showPlayPauseButton] + * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showStopButton] + * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showRewindButton] + * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showRewindButtonCompact] + * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showForwardButton] + * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showForwardButtonCompact] + * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showNextButton] + * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showNextButtonCompact] + * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showPreviousButton] + * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showPreviousButtonCompact] + */ +sealed class Capability(open val showInNotification: Boolean = true) { + data class PlayPause( + override val showInNotification: Boolean = true, + val notificationOptions: NofiticationPlayPauseActionOptions = NofiticationPlayPauseActionOptions.DEFAULT + ) : Capability() + + object PlayFromId : Capability(showInNotification = false) + + object PlayFromSearch : Capability(showInNotification = false) + + data class Stop( + override val showInNotification: Boolean = true, + val notificationOptions: NofiticationIconActionOptions? = null + ) : Capability() + + object SeekTo : Capability(showInNotification = false) + + object Skip : Capability(showInNotification = false) + + data class Next( + override val showInNotification: Boolean = true, + val notificationOptions: NofiticationActionOptions = NofiticationActionOptions.DEFAULT + ) : Capability() + + data class Previous( + override val showInNotification: Boolean = true, + val notificationOptions: NofiticationActionOptions = NofiticationActionOptions.DEFAULT + ) : Capability() + + data class Forward( + override val showInNotification: Boolean = true, + val notificationOptions: NofiticationActionOptions = NofiticationActionOptions.DEFAULT + ) : Capability() + + data class Backward( + override val showInNotification: Boolean = true, + val notificationOptions: NofiticationActionOptions = NofiticationActionOptions.DEFAULT + ) : Capability() + + data class SetRating(val type: Int) : Capability(showInNotification = false) +} + + +data class CapabilitiesConfig( + val capabilities: List, + val notificationOptions: NotificationOptions, +) + +/** Custom extension to filter out only those capabilities that are supported by the notification */ +fun List.filterForNotification(): List { + return this.filter { it.showInNotification } } diff --git a/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/models/NotificationConfig.kt b/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/models/NotificationConfig.kt deleted file mode 100644 index 28563ded..00000000 --- a/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/models/NotificationConfig.kt +++ /dev/null @@ -1,42 +0,0 @@ -package com.doublesymmetry.kotlinaudio.models - -import android.app.PendingIntent -import androidx.annotation.DrawableRes - -/** - * Used to configure the player notification. - * @param buttons Provide customized notification buttons. They will be shown by default. Note that buttons can still be shown and hidden at runtime by using the functions in [NotificationManager][com.doublesymmetry.kotlinaudio.notification.NotificationManager], but they will have the default icon if not set explicitly here. - * @param accentColor The accent color of the notification. - * @param smallIcon The small icon of the notification which is also shown in the system status bar. - * @param pendingIntent The [PendingIntent] that would be called when tapping on the notification itself. - */ -data class NotificationConfig( - val buttons: List, - val accentColor: Int? = null, - @DrawableRes val smallIcon: Int? = null, - val pendingIntent: PendingIntent? = null -) - -/** - * Provide customized notification buttons. They will be shown by default. Note that buttons can still be shown and hidden at runtime by using the functions in [NotificationManager][com.doublesymmetry.kotlinaudio.notification.NotificationManager], but they will have the default icon if not set explicitly here. - * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showPlayPauseButton] - * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showStopButton] - * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showRewindButton] - * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showRewindButtonCompact] - * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showForwardButton] - * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showForwardButtonCompact] - * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showNextButton] - * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showNextButtonCompact] - * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showPreviousButton] - * @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showPreviousButtonCompact] - */ -@Suppress("ClassName") -sealed class NotificationButton { - class PLAY_PAUSE(@DrawableRes val playIcon: Int? = null, @DrawableRes val pauseIcon: Int? = null): NotificationButton() - class STOP(@DrawableRes val icon: Int? = null): NotificationButton() - class FORWARD(@DrawableRes val icon: Int? = null, val isCompact: Boolean = false): NotificationButton() - class BACKWARD(@DrawableRes val icon: Int? = null, val isCompact: Boolean = false): NotificationButton() - class NEXT(@DrawableRes val icon: Int? = null, val isCompact: Boolean = false): NotificationButton() - class PREVIOUS(@DrawableRes val icon: Int? = null, val isCompact: Boolean = false): NotificationButton() - object SEEK_TO : NotificationButton() -} \ No newline at end of file diff --git a/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/models/NotificationOptions.kt b/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/models/NotificationOptions.kt new file mode 100644 index 00000000..0984968a --- /dev/null +++ b/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/models/NotificationOptions.kt @@ -0,0 +1,42 @@ +package com.doublesymmetry.kotlinaudio.models + +import android.app.PendingIntent +import androidx.annotation.DrawableRes + +/** + * Used to configure the player notification. + * @param accentColor The accent color of the notification. + * @param smallIcon The small icon of the notification which is also shown in the system status bar. + * @param pendingIntent The [PendingIntent] that would be called when tapping on the notification itself. + */ +data class NotificationOptions( + val accentColor: Int? = null, + @DrawableRes val smallIcon: Int? = null, + val pendingIntent: PendingIntent? = null +) + +/** Used to configure the properties of a standard notification button */ +data class NofiticationActionOptions( + @DrawableRes val icon: Int? = null, + val isCompact: Boolean = false +) { + companion object { + val DEFAULT = NofiticationActionOptions(isCompact = true) + } +} + +/** Used to configure the properties of a standard notification button */ +data class NofiticationIconActionOptions( + @DrawableRes val icon: Int? = null, +) + +/** Used to configure the properties of a standard notification button */ +data class NofiticationPlayPauseActionOptions( + @DrawableRes val playIcon: Int? = null, + @DrawableRes var pauseIcon: Int? = null, + val isCompact: Boolean = false +) { + companion object { + val DEFAULT = NofiticationPlayPauseActionOptions(isCompact = true) + } +} diff --git a/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/notification/NotificationManager.kt b/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/notification/NotificationManager.kt index 45759f4c..1f4563a3 100644 --- a/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/notification/NotificationManager.kt +++ b/kotlin-audio/src/main/java/com/doublesymmetry/kotlinaudio/notification/NotificationManager.kt @@ -24,10 +24,11 @@ import com.doublesymmetry.kotlinaudio.R import com.doublesymmetry.kotlinaudio.event.NotificationEventHolder import com.doublesymmetry.kotlinaudio.event.PlayerEventHolder import com.doublesymmetry.kotlinaudio.models.AudioItem +import com.doublesymmetry.kotlinaudio.models.CapabilitiesConfig +import com.doublesymmetry.kotlinaudio.models.Capability import com.doublesymmetry.kotlinaudio.models.MediaSessionCallback -import com.doublesymmetry.kotlinaudio.models.NotificationButton -import com.doublesymmetry.kotlinaudio.models.NotificationConfig import com.doublesymmetry.kotlinaudio.models.NotificationState +import com.doublesymmetry.kotlinaudio.models.filterForNotification import com.doublesymmetry.kotlinaudio.players.components.getAudioItemHolder import com.google.android.exoplayer2.Player import com.google.android.exoplayer2.ext.mediasession.MediaSessionConnector @@ -92,7 +93,7 @@ class NotificationManager internal constructor( private var internalNotificationManager: PlayerNotificationManager? = null private val scope = MainScope() - private val buttons = mutableSetOf() + private var currentCapabilitiesConfig: CapabilitiesConfig? = null private var invalidateThrottleCount = 0 private var iconPlaceholder = Bitmap.createBitmap(64, 64, Bitmap.Config.ARGB_8888) @@ -190,7 +191,7 @@ class NotificationManager internal constructor( } } - private fun getDuration(index: Int? = null): Long? { + private fun getDuration(index: Int? = null): Long { val mediaItem = if (index == null) player.currentMediaItem else player.getMediaItemAt(index) return mediaItem?.getAudioItemHolder()?.audioItem?.duration ?: -1 @@ -302,12 +303,12 @@ class NotificationManager internal constructor( mediaSessionConnector.setQueueNavigator( object : TimelineQueueNavigator(mediaSession) { override fun getSupportedQueueNavigatorActions(player: Player): Long { - return buttons.fold(0) { acc, button -> - acc or when (button) { - is NotificationButton.NEXT -> { + return (currentCapabilitiesConfig?.capabilities ?: emptyList()).fold(0) { acc, capability -> + acc or when (capability) { + is Capability.Next -> { PlaybackStateCompat.ACTION_SKIP_TO_NEXT } - is NotificationButton.PREVIOUS -> { + is Capability.Previous -> { PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS } else -> { @@ -365,9 +366,7 @@ class NotificationManager internal constructor( getGenre()?.let { putString(MediaMetadataCompat.METADATA_KEY_GENRE, it) } - getDuration()?.let { - putLong(MediaMetadataCompat.METADATA_KEY_DURATION, it) - } + putLong(MediaMetadataCompat.METADATA_KEY_DURATION, getDuration()) getArtworkUrl()?.let { putString(MediaMetadataCompat.METADATA_KEY_ART_URI, it) } @@ -442,20 +441,12 @@ class NotificationManager internal constructor( override fun getCustomActions(player: Player): List { if (!needsCustomActionsToAddMissingButtons) return emptyList() - return buttons.mapNotNull { + return (currentCapabilitiesConfig?.capabilities ?: emptyList()).mapNotNull { when (it) { - is NotificationButton.BACKWARD -> { - REWIND - } - is NotificationButton.FORWARD -> { - FORWARD - } - is NotificationButton.STOP -> { - STOP - } - else -> { - null - } + is Capability.Backward -> REWIND + is Capability.Forward -> FORWARD + is Capability.Stop -> STOP + else -> null } } } @@ -485,29 +476,32 @@ class NotificationManager internal constructor( * Create a media player notification that automatically updates. Call this * method again with a different configuration to update the notification. */ - fun createNotification(config: NotificationConfig) = scope.launch { - if (isNotificationButtonsChanged(config.buttons)) { + fun createNotification(config: CapabilitiesConfig) = scope.launch { + // filter only the capabilities that are to be shown in the notification + val notificationEnabledCapabilities = config.capabilities.filterForNotification() + + // if the notification capabilities have changed, hide the notification + if (didNotificationActionsChange(notificationEnabledCapabilities)) { hideNotification() } - buttons.apply { - clear() - addAll(config.buttons) - } + // save the new capabilities config + currentCapabilitiesConfig = config stopIcon = null forwardIcon = null rewindIcon = null - updateMediaSessionPlaybackActions() + updateMediaSessionPlaybackActions(config.capabilities) - pendingIntent = config.pendingIntent + pendingIntent = config.notificationOptions.pendingIntent showPlayPauseButton = false showForwardButton = false showRewindButton = false showNextButton = false showPreviousButton = false showStopButton = false + if (internalNotificationManager == null) { internalNotificationManager = PlayerNotificationManager.Builder(context, NOTIFICATION_ID, CHANNEL_ID) @@ -517,44 +511,19 @@ class NotificationManager internal constructor( setCustomActionReceiver(customActionReceiver) setNotificationListener(this@NotificationManager) - for (button in buttons) { - if (button == null) continue - when (button) { - is NotificationButton.PLAY_PAUSE -> { - button.playIcon?.let { setPlayActionIconResourceId(it) } - button.pauseIcon?.let { setPauseActionIconResourceId(it) } - } - - is NotificationButton.STOP -> button.icon?.let { - setStopActionIconResourceId( - it - ) - } - - is NotificationButton.FORWARD -> button.icon?.let { - setFastForwardActionIconResourceId( - it - ) - } - - is NotificationButton.BACKWARD -> button.icon?.let { - setRewindActionIconResourceId( - it - ) - } - - is NotificationButton.NEXT -> button.icon?.let { - setNextActionIconResourceId( - it - ) - } - - is NotificationButton.PREVIOUS -> button.icon?.let { - setPreviousActionIconResourceId( - it - ) + for (capability in notificationEnabledCapabilities) { + when (capability) { + is Capability.PlayPause -> { + capability.notificationOptions?.playIcon?.let { setPlayActionIconResourceId(it) } + capability.notificationOptions?.playIcon?.let { setPauseActionIconResourceId(it) } } + is Capability.Stop -> capability.notificationOptions?.icon?.let { setStopActionIconResourceId(it) } + is Capability.Next -> capability.notificationOptions?.icon?.let { setNextActionIconResourceId(it) } + is Capability.Previous -> capability.notificationOptions?.icon?.let { setPreviousActionIconResourceId(it) } + is Capability.Forward -> capability.notificationOptions?.icon?.let { setFastForwardActionIconResourceId(it) } + is Capability.Backward -> capability.notificationOptions?.icon?.let { setRewindActionIconResourceId(it) } + // Technically this should never happen if the filter above is correct else -> {} } } @@ -563,149 +532,93 @@ class NotificationManager internal constructor( setPlayer(player) } } - setupInternalNotificationManager(config) + setupInternalNotificationManager(config.notificationOptions.accentColor, config.notificationOptions.smallIcon, notificationEnabledCapabilities) } - private fun isNotificationButtonsChanged(newButtons: List): Boolean { - val currentNotificationButtonsMapByType = buttons.filterNotNull().associateBy { it::class } - return newButtons.any { newButton -> - when (newButton) { - is NotificationButton.PLAY_PAUSE -> { - (currentNotificationButtonsMapByType[NotificationButton.PLAY_PAUSE::class] as? NotificationButton.PLAY_PAUSE).let { currentButton -> - newButton.pauseIcon != currentButton?.pauseIcon || newButton.playIcon != currentButton?.playIcon - } - } - - is NotificationButton.STOP -> { - (currentNotificationButtonsMapByType[NotificationButton.STOP::class] as? NotificationButton.STOP).let { currentButton -> - newButton.icon != currentButton?.icon - } - } - - is NotificationButton.FORWARD -> { - (currentNotificationButtonsMapByType[NotificationButton.FORWARD::class] as? NotificationButton.FORWARD).let { currentButton -> - newButton.icon != currentButton?.icon - } - } - - is NotificationButton.BACKWARD -> { - (currentNotificationButtonsMapByType[NotificationButton.BACKWARD::class] as? NotificationButton.BACKWARD).let { currentButton -> - newButton.icon != currentButton?.icon - } - } - - is NotificationButton.NEXT -> { - (currentNotificationButtonsMapByType[NotificationButton.NEXT::class] as? NotificationButton.NEXT).let { currentButton -> - newButton.icon != currentButton?.icon - } - } - - is NotificationButton.PREVIOUS -> { - (currentNotificationButtonsMapByType[NotificationButton.PREVIOUS::class] as? NotificationButton.PREVIOUS).let { currentButton -> - newButton.icon != currentButton?.icon - } - } + private fun didNotificationActionsChange(newCapabilities: List): Boolean { + // get previous capabilities that were enabled for the notification + val previousCapabilities = currentCapabilitiesConfig?.capabilities?.filterForNotification() - else -> false - } - } + // compare the previous capabilities with the new capabilities and return whether they are different + return previousCapabilities?.size == newCapabilities.size && previousCapabilities.containsAll(newCapabilities) } - private fun updateMediaSessionPlaybackActions() { + private fun updateMediaSessionPlaybackActions(capabilities: List) { mediaSessionConnector.setEnabledPlaybackActions( - buttons.fold( - PlaybackStateCompat.ACTION_SET_REPEAT_MODE - or PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE - or PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED - ) { acc, button -> - acc or when (button) { - is NotificationButton.PLAY_PAUSE -> { - PlaybackStateCompat.ACTION_PLAY or PlaybackStateCompat.ACTION_PAUSE - } - is NotificationButton.BACKWARD -> { - rewindIcon = button.icon ?: rewindIcon - PlaybackStateCompat.ACTION_REWIND + // PlaybackStateCompat.ACTION_SET_REPEAT_MODE or PlaybackStateCompat.ACTION_SET_SHUFFLE_MODE + capabilities.fold(PlaybackStateCompat.ACTION_SET_PLAYBACK_SPEED) { acc, capability -> + acc or when (capability) { + is Capability.PlayPause -> PlaybackStateCompat.ACTION_PLAY or PlaybackStateCompat.ACTION_PAUSE + is Capability.PlayFromId -> PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID + is Capability.PlayFromSearch -> PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH + is Capability.Stop -> { + stopIcon = capability.notificationOptions?.icon ?: stopIcon + PlaybackStateCompat.ACTION_STOP } - is NotificationButton.FORWARD -> { - forwardIcon = button.icon ?: forwardIcon + is Capability.SeekTo -> PlaybackStateCompat.ACTION_SEEK_TO + is Capability.Skip -> PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM + is Capability.Forward -> { + forwardIcon = capability.notificationOptions?.icon ?: forwardIcon PlaybackStateCompat.ACTION_FAST_FORWARD } - is NotificationButton.SEEK_TO -> { - PlaybackStateCompat.ACTION_SEEK_TO - } - is NotificationButton.STOP -> { - stopIcon = button.icon ?: stopIcon - PlaybackStateCompat.ACTION_STOP - } - else -> { - 0 + is Capability.Backward -> { + rewindIcon = capability.notificationOptions?.icon ?: rewindIcon + PlaybackStateCompat.ACTION_REWIND } + else -> 0 } } ) if (needsCustomActionsToAddMissingButtons) { - val customActionProviders = buttons + val customActionProviders = capabilities .sortedBy { when (it) { - is NotificationButton.BACKWARD -> 1 - is NotificationButton.FORWARD -> 2 - is NotificationButton.STOP -> 3 + is Capability.Backward -> 1 + is Capability.Forward -> 2 + is Capability.Stop -> 3 else -> 4 } } .mapNotNull { when (it) { - is NotificationButton.BACKWARD -> { - createMediaSessionAction(rewindIcon ?: DEFAULT_REWIND_ICON, REWIND) - } - is NotificationButton.FORWARD -> { - createMediaSessionAction(forwardIcon ?: DEFAULT_FORWARD_ICON, FORWARD) - } - is NotificationButton.STOP -> { - createMediaSessionAction(stopIcon ?: DEFAULT_STOP_ICON, STOP) - } - else -> { - null - } + is Capability.Backward -> createMediaSessionAction(rewindIcon ?: DEFAULT_REWIND_ICON, REWIND) + is Capability.Forward -> createMediaSessionAction(forwardIcon ?: DEFAULT_FORWARD_ICON, FORWARD) + is Capability.Stop -> createMediaSessionAction(stopIcon ?: DEFAULT_STOP_ICON, STOP) + else -> null } } mediaSessionConnector.setCustomActionProviders(*customActionProviders.toTypedArray()) } } - private fun setupInternalNotificationManager(config: NotificationConfig) { + private fun setupInternalNotificationManager(accentColor: Int?, @DrawableRes smallIcon: Int?, capabilities: List) { internalNotificationManager?.run { - setColor(config.accentColor ?: Color.TRANSPARENT) - config.smallIcon?.let { setSmallIcon(it) } - for (button in buttons) { - if (button == null) continue - when (button) { - is NotificationButton.PLAY_PAUSE -> { - showPlayPauseButton = true + setColor(accentColor ?: Color.TRANSPARENT) + smallIcon?.let { setSmallIcon(it) } + for (capability in capabilities) { + when (capability) { + is Capability.PlayPause -> showPlayPauseButton = true + is Capability.Stop -> showStopButton = true + is Capability.Next -> { + showNextButton = true + showNextButtonCompact = capability.notificationOptions?.isCompact ?: false } - is NotificationButton.STOP -> { - showStopButton = true + is Capability.Previous -> { + showPreviousButton = true + showPreviousButtonCompact = + capability.notificationOptions?.isCompact ?: false } - is NotificationButton.FORWARD -> { + is Capability.Forward -> { showForwardButton = true - showForwardButtonCompact = button.isCompact + showForwardButtonCompact = + capability.notificationOptions?.isCompact ?: false } - is NotificationButton.BACKWARD -> { + is Capability.Backward -> { showRewindButton = true - showRewindButtonCompact = button.isCompact - } - - is NotificationButton.NEXT -> { - showNextButton = true - showNextButtonCompact = button.isCompact - } - - is NotificationButton.PREVIOUS -> { - showPreviousButton = true - showPreviousButtonCompact = button.isCompact + showRewindButtonCompact = capability.notificationOptions?.isCompact ?: false } else -> {}