Skip to content

Commit

Permalink
Add Pixel Watch skip buttons setting
Browse files Browse the repository at this point in the history
  • Loading branch information
geekygecko committed Jan 23, 2025
1 parent 8d3e82f commit bca5a2b
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ class MediaActionsFragment : BaseFragment() {
MediaActionsPage(
state = state,
onShowCustomActionsChanged = viewModel::setShowCustomActionsChanged,
onNextPreviousTrackSkipButtonsChanged = viewModel::setNextPreviousTrackSkipButtonsChanged,
onActionsOrderChanged = viewModel::onActionsOrderChanged,
onActionMoved = viewModel::onActionMoved,
onBackClick = ::onBackClick,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ fun MediaActionsPage(
state: State,
onBackClick: () -> Unit,
onShowCustomActionsChanged: (Boolean) -> Unit,
onNextPreviousTrackSkipButtonsChanged: (Boolean) -> Unit,
onActionsOrderChanged: (List<MenuAction>) -> Unit,
modifier: Modifier = Modifier,
onActionMoved: (fromIndex: Int, toIndex: Int, action: MenuAction) -> Unit = { _, _, _ -> },
Expand All @@ -52,6 +53,8 @@ fun MediaActionsPage(
PageHeader(
customActionsVisibility = state.customActionsVisibility,
onShowCustomActionsChanged = onShowCustomActionsChanged,
nextPreviousTrackSkipButtons = state.nextPreviousTrackSkipButtons,
onNextPreviousTrackSkipButtonsChanged = onNextPreviousTrackSkipButtonsChanged,
)
},
menuActions = state.actions,
Expand All @@ -69,13 +72,19 @@ fun MediaActionsPage(
private fun PageHeader(
customActionsVisibility: Boolean,
onShowCustomActionsChanged: (Boolean) -> Unit,
nextPreviousTrackSkipButtons: Boolean,
onNextPreviousTrackSkipButtonsChanged: (Boolean) -> Unit,
modifier: Modifier = Modifier,
) {
Column(modifier = modifier) {
ShowCustomActionsSettings(
customActionsVisibility = customActionsVisibility,
onShowCustomActionsChanged = onShowCustomActionsChanged,
)
PixelWatchSKipButtonsSetting(
nextPreviousTrackSkipButtons = nextPreviousTrackSkipButtons,
onNextPreviousTrackSkipButtonsChanged = onNextPreviousTrackSkipButtonsChanged,
)
Spacer(Modifier.height(16.dp))
SettingRow(
primaryText = stringResource(LR.string.settings_media_actions_prioritize_title),
Expand Down Expand Up @@ -111,6 +120,28 @@ private fun ShowCustomActionsSettings(
)
}

@Composable
private fun PixelWatchSKipButtonsSetting(
nextPreviousTrackSkipButtons: Boolean,
onNextPreviousTrackSkipButtonsChanged: (Boolean) -> Unit,
modifier: Modifier = Modifier,
) {
SettingRow(
primaryText = stringResource(LR.string.settings_pixel_watch_title),
secondaryText = stringResource(LR.string.settings_pixel_watch_subtitle),
toggle = SettingRowToggle.Switch(checked = nextPreviousTrackSkipButtons),
indent = false,
modifier = modifier
.padding(top = 8.dp)
.toggleable(
value = nextPreviousTrackSkipButtons,
role = Role.Switch,
) {
onNextPreviousTrackSkipButtonsChanged(it)
},
)
}

@Preview
@Composable
fun MediaActionsPagePreview(@PreviewParameter(ThemePreviewParameterProvider::class) themeType: Theme.ThemeType) {
Expand All @@ -129,6 +160,7 @@ fun MediaActionsPagePreview(@PreviewParameter(ThemePreviewParameterProvider::cla
),
onBackClick = {},
onShowCustomActionsChanged = {},
onNextPreviousTrackSkipButtonsChanged = {},
onActionsOrderChanged = {},
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ class MediaActionsViewModel @Inject constructor(

data class State(
val customActionsVisibility: Boolean = false,
val nextPreviousTrackSkipButtons: Boolean = false,
val actions: List<MenuAction> = emptyList(),
)

Expand All @@ -36,9 +37,11 @@ class MediaActionsViewModel @Inject constructor(
combine(
settings.mediaControlItems.flow,
settings.customMediaActionsVisibility.flow,
) { items, visibility ->
settings.nextPreviousTrackSkipButtons.flow,
) { items, visibility, skipButtons ->
State(
customActionsVisibility = visibility,
nextPreviousTrackSkipButtons = skipButtons,
actions = items.map { MenuAction(key = it.key, name = it.controlName, icon = it.iconRes) },
)
}
Expand All @@ -55,6 +58,14 @@ class MediaActionsViewModel @Inject constructor(
)
}

fun setNextPreviousTrackSkipButtonsChanged(enabled: Boolean) {
settings.nextPreviousTrackSkipButtons.set(enabled, updateModifiedAt = true)
analyticsTracker.track(
AnalyticsEvent.SETTINGS_GENERAL_MEDIA_NOTIFICATION_NEXT_PREVIOUS_TRACK_SKIP_BUTTONS_TOGGLED,
mapOf("enabled" to enabled),
)
}

fun onActionsOrderChanged(menuActions: List<MenuAction>) {
val mediaNotificationControls = menuActions.mapNotNull { MediaNotificationControls.itemForId(it.key) }
settings.mediaControlItems.set(mediaNotificationControls, updateModifiedAt = true)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,7 @@ enum class AnalyticsEvent(val key: String) {
SETTINGS_GENERAL_AUTO_SLEEP_TIMER_RESTART_TOGGLED("settings_general_auto_sleep_timer_restart_toggled"),
SETTINGS_GENERAL_MEDIA_NOTIFICATION_CONTROLS_SHOWN("settings_general_media_notification_controls_shown"),
SETTINGS_GENERAL_MEDIA_NOTIFICATION_CONTROLS_SHOW_CUSTOM_TOGGLED("settings_general_media_notification_controls_show_custom_toggled"),
SETTINGS_GENERAL_MEDIA_NOTIFICATION_NEXT_PREVIOUS_TRACK_SKIP_BUTTONS_TOGGLED("settings_general_media_notification_next_previous_track_skip_buttons_toggled"),
SETTINGS_GENERAL_MEDIA_NOTIFICATION_CONTROLS_ORDER_CHANGED("settings_general_media_notification_controls_order_changed"),
SETTINGS_GENERAL_AUTOPLAY_TOGGLED("settings_general_autoplay_toggled"),
SETTINGS_GENERAL_USE_REAL_TIME_FOR_PLAYBACK_REMAINING_TIME("settings_use_real_time_for_playback_remaining_time"),
Expand Down
2 changes: 2 additions & 0 deletions modules/services/localization/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,8 @@
<string name="settings_media_actions_customise">Customize media actions</string>
<string name="settings_media_actions_show_title">Show custom media actions</string>
<string name="settings_media_actions_show_subtitle">Show custom media actions in Android 13+ media notifications and Android Auto.</string>
<string name="settings_pixel_watch_title">Pixel Watch skip buttons</string>
<string name="settings_pixel_watch_subtitle">Replace the custom skip buttons with standard next/previous track buttons that function as skip buttons, allowing compatibility with more devices.</string>
<string name="settings_media_notification_controls">Media notification controls</string>
<string name="settings_media_notification_controls_title_archive" translatable="false">@string/archive</string>
<string name="settings_media_notification_controls_title_mark_as_played" translatable="false">@string/mark_as_played</string>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,7 @@ interface Settings {
fun setHasDoneInitialOnboarding()

val customMediaActionsVisibility: UserSetting<Boolean>
val nextPreviousTrackSkipButtons: UserSetting<Boolean>

fun isNotificationsDisabledMessageShown(): Boolean
fun setNotificationsDisabledMessageShown(value: Boolean)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1357,6 +1357,12 @@ class SettingsImpl @Inject constructor(
sharedPrefs = sharedPreferences,
)

override val nextPreviousTrackSkipButtons = UserSetting.BoolPref(
sharedPrefKey = "NextPreviousTrackSkipButtonsKey",
defaultValue = false,
sharedPrefs = sharedPreferences,
)

override fun isNotificationsDisabledMessageShown() =
getBoolean(NOTIFICATIONS_DISABLED_MESSAGE_SHOWN, false)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -287,12 +287,12 @@ class MediaSessionManager(
PlaybackStateCompat.ACTION_REWIND or
prepareActions

return if (shouldHideCustomSkipButtons()) {
return if (useCustomSkipButtons()) {
actions
} else {
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS or
PlaybackStateCompat.ACTION_SKIP_TO_NEXT or
actions
} else {
actions
}
}
}
Expand Down Expand Up @@ -428,7 +428,7 @@ class MediaSessionManager(
}

private fun addCustomActions(stateBuilder: PlaybackStateCompat.Builder, currentEpisode: BaseEpisode, playbackState: PlaybackState) {
if (!shouldHideCustomSkipButtons()) {
if (useCustomSkipButtons()) {
addCustomAction(stateBuilder, APP_ACTION_SKIP_BACK, "Skip back", IR.drawable.media_skipback)
addCustomAction(stateBuilder, APP_ACTION_SKIP_FWD, "Skip forward", IR.drawable.media_skipforward)
}
Expand Down Expand Up @@ -960,8 +960,9 @@ class MediaSessionManager(
playbackManager.playNow(episode = latestEpisode, sourceView = sourceView)
}

private fun shouldHideCustomSkipButtons(): Boolean {
return MANUFACTURERS_TO_HIDE_CUSTOM_SKIP_BUTTONS.contains(Build.MANUFACTURER.lowercase())
private fun useCustomSkipButtons(): Boolean {
return !MANUFACTURERS_TO_HIDE_CUSTOM_SKIP_BUTTONS.contains(Build.MANUFACTURER.lowercase()) &&
!settings.nextPreviousTrackSkipButtons.value
}
}

Expand Down

0 comments on commit bca5a2b

Please sign in to comment.