Skip to content

Commit

Permalink
Improve Capabilities to be more Kotlin like
Browse files Browse the repository at this point in the history
  • Loading branch information
dcvz committed Jul 27, 2023
1 parent 7ba0696 commit f344d2d
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 115 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -138,14 +138,14 @@ class FirstFragment : Fragment() {
private fun setupNotification() {
val capabilitiesConfig = CapabilitiesConfig(
capabilities = listOf(
Capability.PLAY_PAUSE(),
Capability.NEXT(notificationConfig = NofiticationActionConfig(isCompact = true)),
Capability.PREVIOUS(notificationConfig = NofiticationActionConfig(isCompact = true)),
Capability.FORWARD(notificationConfig = NofiticationActionConfig(isCompact = true)),
Capability.BACKWARD(notificationConfig = NofiticationActionConfig(isCompact = true, icon = com.google.android.exoplayer2.ui.R.drawable.exo_icon_circular_play)),
Capability.SEEK_TO
Capability.PlayPause(),
Capability.Next(notificationOptions = NofiticationActionOptions(isCompact = true)),
Capability.Previous(notificationOptions = NofiticationActionOptions(isCompact = true)),
Capability.Forward(notificationOptions = NofiticationActionOptions(isCompact = true)),
Capability.Backward(notificationOptions = NofiticationActionOptions(isCompact = true, icon = com.google.android.exoplayer2.ui.R.drawable.exo_icon_circular_play)),
Capability.SeekTo
),
notificationConfig = NotificationConfig(
notificationOptions = NotificationOptions(
accentColor = null, smallIcon = null, pendingIntent = null
)
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package com.doublesymmetry.kotlinaudio.models

import android.support.v4.media.RatingCompat

/**
* Defines the capabilities supported by the media session and whether they're also supported by the notification.
* @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showPlayPauseButton]
Expand All @@ -15,69 +13,62 @@ import android.support.v4.media.RatingCompat
* @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showPreviousButton]
* @see [com.doublesymmetry.kotlinaudio.notification.NotificationManager.showPreviousButtonCompact]
*/
sealed class Capability {
/**
* Play and pause capability with optional configuration for the notification.
* @param showInNotification Whether to show the button in the notification. Defaults to true.
* @param notificationConfig The configuration for the notification button.
*/
data class PLAY_PAUSE(val showInNotification: Boolean = true, val notificationConfig: NofiticationPlayPauseActionConfig? = null): Capability()
sealed class Capability(open val showInNotification: Boolean = true) {
data class PlayPause(
override val showInNotification: Boolean = true,
val notificationOptions: NofiticationPlayPauseActionOptions? = null
) : 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)

/** Play from a media id capability. Used in the media session. */
object PLAY_FROM_ID: Capability()
/** Play from search capability. Used in the media session. */
object PLAY_FROM_SEARCH: Capability()
/**
* Stop capability with optional configuration for the notification.
* @param showInNotification Whether to show the button in the notification. Defaults to true.
* @param notificationConfig The configuration for the notification button.
*/
data class STOP(val showInNotification: Boolean = true, val notificationConfig: NofiticationIconActionConfig? = null): Capability()
/** Seek to capability. Used in the media session. */
object SEEK_TO: Capability()
/** Skip to queue item capability. Used in the media session. */
object SKIP: Capability()
/**
* Skip to next item capability with optional configuration for the notification.
* @param showInNotification Whether to show the button in the notification. Defaults to true.
* @param notificationConfig The configuration for the notification button.
*/
data class NEXT(val showInNotification: Boolean = true, val notificationConfig: NofiticationActionConfig? = null): Capability()
/**
* Skip to previous item capability with optional configuration for the notification.
* @param showInNotification Whether to show the button in the notification. Defaults to true.
* @param notificationConfig The configuration for the notification button.
*/
data class PREVIOUS(val showInNotification: Boolean = true, val notificationConfig: NofiticationActionConfig? = null): Capability()
/**
* Skip forward by interval capability with optional configuration for the notification.
* @param showInNotification Whether to show the button in the notification. Defaults to true.
* @param notificationConfig The configuration for the notification button.
*/
data class FORWARD(val showInNotification: Boolean = true, val notificationConfig: NofiticationActionConfig? = null): Capability()
/**
* Skip backward by interval capability with optional configuration for the notification.
* @param showInNotification Whether to show the button in the notification. Defaults to true.
* @param notificationConfig The configuration for the notification button.
*/
data class BACKWARD(val showInNotification: Boolean = true, val notificationConfig: NofiticationActionConfig? = null): Capability()
/** Set rating capability. Used in the media session. */
data class SET_RATING(val type: Int): Capability()
data class Next(
override val showInNotification: Boolean = true,
val notificationOptions: NofiticationActionOptions? = null
) : Capability()

data class Previous(
override val showInNotification: Boolean = true,
val notificationOptions: NofiticationActionOptions? = null
) : Capability()

data class Forward(
override val showInNotification: Boolean = true,
val notificationOptions: NofiticationActionOptions? = null
) : Capability()

data class Backward(
override val showInNotification: Boolean = true,
val notificationOptions: NofiticationActionOptions? = null
) : Capability()

data class SetRating(val type: Int) : Capability()
}


data class CapabilitiesConfig(
val capabilities: List<Capability>,
val notificationConfig: NotificationConfig,
val notificationOptions: NotificationOptions,
)

/** Custom extension to filter out only those capabilities that are supported by the notification */
fun List<Capability>.filterForNotification(): List<Capability> {
return this.filter {
(it is Capability.PLAY_PAUSE && it.showInNotification)
|| (it is Capability.STOP && it.showInNotification)
|| (it is Capability.NEXT && it.showInNotification)
|| (it is Capability.PREVIOUS && it.showInNotification)
|| (it is Capability.FORWARD && it.showInNotification)
|| (it is Capability.BACKWARD && it.showInNotification)
(it is Capability.PlayPause && it.showInNotification)
|| (it is Capability.Stop && it.showInNotification)
|| (it is Capability.Next && it.showInNotification)
|| (it is Capability.Previous && it.showInNotification)
|| (it is Capability.Forward && it.showInNotification)
|| (it is Capability.Backward && it.showInNotification)
} ?: emptyList()
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,25 @@ import androidx.annotation.DrawableRes
* @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(
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 NofiticationActionConfig(
data class NofiticationActionOptions(
@DrawableRes val icon: Int? = null,
val isCompact: Boolean = false
)

/** Used to configure the properties of a standard notification button */
data class NofiticationIconActionConfig(
data class NofiticationIconActionOptions(
@DrawableRes val icon: Int? = null,
)

/** Used to configure the properties of a standard notification button */
data class NofiticationPlayPauseActionConfig(
data class NofiticationPlayPauseActionOptions(
@DrawableRes val playIcon: Int? = null,
@DrawableRes var pauseIcon: Int? = null,
val isCompact: Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,10 +317,10 @@ class NotificationManager internal constructor(
override fun getSupportedQueueNavigatorActions(player: Player): Long {
return (currentCapabilitiesConfig?.capabilities ?: emptyList()).fold(0) { acc, capability ->
acc or when (capability) {
is Capability.NEXT -> {
is Capability.Next -> {
PlaybackStateCompat.ACTION_SKIP_TO_NEXT
}
is Capability.PREVIOUS -> {
is Capability.Previous -> {
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
}
else -> 0
Expand Down Expand Up @@ -445,13 +445,13 @@ class NotificationManager internal constructor(
if (!needsCustomActionsToAddMissingButtons) return emptyList()
return (currentCapabilitiesConfig?.capabilities ?: emptyList()).mapNotNull {
when (it) {
is Capability.BACKWARD -> {
is Capability.Backward -> {
REWIND
}
is Capability.FORWARD -> {
is Capability.Forward -> {
FORWARD
}
is Capability.STOP -> {
is Capability.Stop -> {
STOP
}
else -> null
Expand Down Expand Up @@ -502,7 +502,7 @@ class NotificationManager internal constructor(

updateMediaSessionPlaybackActions(config.capabilities)

pendingIntent = config.notificationConfig.pendingIntent
pendingIntent = config.notificationOptions.pendingIntent
showPlayPauseButton = false
showForwardButton = false
showRewindButton = false
Expand All @@ -521,15 +521,15 @@ class NotificationManager internal constructor(

for (capability in notificationEnabledCapabilities) {
when (capability) {
is Capability.PLAY_PAUSE -> {
capability.notificationConfig?.playIcon?.let { setPlayActionIconResourceId(it) }
capability.notificationConfig?.playIcon?.let { setPauseActionIconResourceId(it) }
is Capability.PlayPause -> {
capability.notificationOptions?.playIcon?.let { setPlayActionIconResourceId(it) }
capability.notificationOptions?.playIcon?.let { setPauseActionIconResourceId(it) }
}
is Capability.STOP -> capability.notificationConfig?.icon?.let { setStopActionIconResourceId(it) }
is Capability.NEXT -> capability.notificationConfig?.icon?.let { setNextActionIconResourceId(it) }
is Capability.PREVIOUS -> capability.notificationConfig?.icon?.let { setPreviousActionIconResourceId(it) }
is Capability.FORWARD -> capability.notificationConfig?.icon?.let { setFastForwardActionIconResourceId(it) }
is Capability.BACKWARD -> capability.notificationConfig?.icon?.let { setRewindActionIconResourceId(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 -> {}
}
Expand All @@ -539,7 +539,7 @@ class NotificationManager internal constructor(
setPlayer(player)
}
}
setupInternalNotificationManager(config.notificationConfig.accentColor, config.notificationConfig.smallIcon, notificationEnabledCapabilities)
setupInternalNotificationManager(config.notificationOptions.accentColor, config.notificationOptions.smallIcon, notificationEnabledCapabilities)
}

private fun didNotificationActionsChange(newCapabilities: List<Capability>): Boolean {
Expand All @@ -555,31 +555,31 @@ class NotificationManager internal constructor(
// 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.PLAY_PAUSE -> {
is Capability.PlayPause -> {
PlaybackStateCompat.ACTION_PLAY or PlaybackStateCompat.ACTION_PAUSE
}
is Capability.PLAY_FROM_ID -> {
is Capability.PlayFromId -> {
PlaybackStateCompat.ACTION_PLAY_FROM_MEDIA_ID
}
is Capability.PLAY_FROM_SEARCH -> {
is Capability.PlayFromSearch -> {
PlaybackStateCompat.ACTION_PLAY_FROM_SEARCH
}
is Capability.STOP -> {
stopIcon = capability.notificationConfig?.icon ?: stopIcon
is Capability.Stop -> {
stopIcon = capability.notificationOptions?.icon ?: stopIcon
PlaybackStateCompat.ACTION_STOP
}
is Capability.SEEK_TO -> {
is Capability.SeekTo -> {
PlaybackStateCompat.ACTION_SEEK_TO
}
is Capability.SKIP -> {
is Capability.Skip -> {
PlaybackStateCompat.ACTION_SKIP_TO_QUEUE_ITEM
}
is Capability.FORWARD -> {
forwardIcon = capability.notificationConfig?.icon ?: forwardIcon
is Capability.Forward -> {
forwardIcon = capability.notificationOptions?.icon ?: forwardIcon
PlaybackStateCompat.ACTION_FAST_FORWARD
}
is Capability.BACKWARD -> {
rewindIcon = capability.notificationConfig?.icon ?: rewindIcon
is Capability.Backward -> {
rewindIcon = capability.notificationOptions?.icon ?: rewindIcon
PlaybackStateCompat.ACTION_REWIND
}
else -> {
Expand All @@ -592,23 +592,17 @@ class NotificationManager internal constructor(
val customActionProviders = capabilities
.sortedBy {
when (it) {
is Capability.BACKWARD -> 1
is Capability.FORWARD -> 2
is Capability.STOP -> 3
is Capability.Backward -> 1
is Capability.Forward -> 2
is Capability.Stop -> 3
else -> 4
}
}
.mapNotNull {
when (it) {
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)
}
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
}
Expand All @@ -624,23 +618,23 @@ class NotificationManager internal constructor(
smallIcon?.let { setSmallIcon(it) }
for (capability in capabilities) {
when (capability) {
is Capability.PLAY_PAUSE -> showPlayPauseButton = true
is Capability.STOP -> showStopButton = true
is Capability.NEXT -> {
is Capability.PlayPause -> showPlayPauseButton = true
is Capability.Stop -> showStopButton = true
is Capability.Next -> {
showNextButton = true
showNextButtonCompact = capability.notificationConfig?.isCompact ?: false
showNextButtonCompact = capability.notificationOptions?.isCompact ?: false
}
is Capability.PREVIOUS -> {
is Capability.Previous -> {
showPreviousButton = true
showPreviousButtonCompact = capability.notificationConfig?.isCompact ?: false
showPreviousButtonCompact = capability.notificationOptions?.isCompact ?: false
}
is Capability.FORWARD -> {
is Capability.Forward -> {
showForwardButton = true
showForwardButtonCompact = capability.notificationConfig?.isCompact ?: false
showForwardButtonCompact = capability.notificationOptions?.isCompact ?: false
}
is Capability.BACKWARD -> {
is Capability.Backward -> {
showRewindButton = true
showRewindButtonCompact = capability.notificationConfig?.isCompact ?: false
showRewindButtonCompact = capability.notificationOptions?.isCompact ?: false
}
else -> {}
}
Expand Down

0 comments on commit f344d2d

Please sign in to comment.