commit db3ded8c6a1463731906aa0bf741dbd2a5d5ea4a
parent 19bce43f2de1cc0b5846efcf25d638289743ca87
Author: John Oberhauser <j.git-global@obez.io>
Date: Wed, 19 Nov 2025 23:07:48 +0000
Bug 2000709: Adding a nimbus flag for hiding the terms of use prompt drag handle r=android-reviewers,twhite
Differential Revision: https://phabricator.services.mozilla.com/D272955
Diffstat:
5 files changed, 62 insertions(+), 4 deletions(-)
diff --git a/mobile/android/fenix/app/nimbus.fml.yaml b/mobile/android/fenix/app/nimbus.fml.yaml
@@ -654,6 +654,10 @@ features:
description: The maximum number of times to show the prompt.
type: Int
default: 2
+ enable-drag-to-dismiss:
+ description: Whether to show a drag handle on the prompt and allows users to use it to dismiss the prompt.
+ type: Boolean
+ default: true
tab-strip:
description: Enables tab strip.
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/termsofuse/ui/TermsOfUseBottomSheet.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/termsofuse/ui/TermsOfUseBottomSheet.kt
@@ -12,6 +12,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.BottomSheetDefaults
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ModalBottomSheet
import androidx.compose.material3.ModalBottomSheetProperties
@@ -43,6 +44,7 @@ private val sheetMaxWidth = 450.dp
/**
* The terms of service prompt.
*
+ * @param showDragHandle If the user should see and be able to use a drag handle to dismiss the prompt.
* @param onDismiss The callback to invoke when the prompt is dismissed.
* @param onDismissRequest The callback to invoke when the user clicks outside of the bottom sheet,
* after sheet animates to Hidden. See [ModalBottomSheet].
@@ -55,6 +57,7 @@ private val sheetMaxWidth = 450.dp
@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TermsOfUseBottomSheet(
+ showDragHandle: Boolean = true,
onDismiss: () -> Unit,
onDismissRequest: () -> Unit,
onAcceptClicked: () -> Unit,
@@ -72,6 +75,7 @@ fun TermsOfUseBottomSheet(
}
BottomSheet(
+ showDragHandle = showDragHandle,
sheetState = sheetState,
onDismiss = onDismiss,
onDismissRequest = onDismissRequest,
@@ -86,6 +90,7 @@ fun TermsOfUseBottomSheet(
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun BottomSheet(
+ showDragHandle: Boolean,
sheetState: SheetState,
onDismiss: () -> Unit = {},
onDismissRequest: () -> Unit = {},
@@ -96,6 +101,12 @@ private fun BottomSheet(
onLearnMoreClicked: () -> Unit = {},
) {
ModalBottomSheet(
+ sheetGesturesEnabled = showDragHandle,
+ dragHandle = if (showDragHandle) {
+ { BottomSheetDefaults.DragHandle() }
+ } else {
+ null
+ },
onDismissRequest = { onDismissRequest() },
sheetMaxWidth = sheetMaxWidth,
sheetState = sheetState,
@@ -105,6 +116,7 @@ private fun BottomSheet(
),
) {
BottomSheetContent(
+ showDragHandle = showDragHandle,
sheetState = sheetState,
onDismiss = onDismiss,
onAcceptClicked = onAcceptClicked,
@@ -119,6 +131,7 @@ private fun BottomSheet(
@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun BottomSheetContent(
+ showDragHandle: Boolean,
sheetState: SheetState,
onDismiss: () -> Unit,
onAcceptClicked: () -> Unit = {},
@@ -135,6 +148,10 @@ private fun BottomSheetContent(
.verticalScroll(scrollState)
.padding(horizontal = 32.dp),
) {
+ if (!showDragHandle) {
+ Spacer(Modifier.size(16.dp))
+ }
+
Image(
painter = painterResource(id = R.drawable.ic_firefox),
contentDescription = null,
@@ -254,7 +271,24 @@ private fun TermsOfUseBottomSheetMobilePortraitPreview() {
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
FirefoxTheme {
- BottomSheet(sheetState = sheetState)
+ BottomSheet(
+ showDragHandle = true,
+ sheetState = sheetState,
+ )
+ }
+}
+
+@OptIn(ExperimentalMaterial3Api::class)
+@PreviewLightDark
+@Composable
+private fun TermsOfUseBottomSheetMobilePortraitNoHandlePreview() {
+ val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
+
+ FirefoxTheme {
+ BottomSheet(
+ showDragHandle = false,
+ sheetState = sheetState,
+ )
}
}
@@ -272,7 +306,10 @@ private fun TermsOfUseBottomSheetMobileLandscapePreview() {
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
FirefoxTheme {
- BottomSheet(sheetState = sheetState)
+ BottomSheet(
+ showDragHandle = true,
+ sheetState = sheetState,
+ )
}
}
@@ -290,7 +327,10 @@ private fun TermsOfUseBottomSheetTabletPortraitPreview() {
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
FirefoxTheme {
- BottomSheet(sheetState = sheetState)
+ BottomSheet(
+ showDragHandle = true,
+ sheetState = sheetState,
+ )
}
}
@@ -304,6 +344,9 @@ private fun TermsOfUseBottomSheetTabletLandscapePreview() {
val sheetState = rememberModalBottomSheetState(skipPartiallyExpanded = true)
FirefoxTheme {
- BottomSheet(sheetState = sheetState)
+ BottomSheet(
+ showDragHandle = true,
+ sheetState = sheetState,
+ )
}
}
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/termsofuse/ui/TermsOfUseBottomSheetFragment.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/termsofuse/ui/TermsOfUseBottomSheetFragment.kt
@@ -62,6 +62,7 @@ class TermsOfUseBottomSheetFragment : BottomSheetDialogFragment() {
setContent {
FirefoxTheme {
TermsOfUseBottomSheet(
+ showDragHandle = settings().shouldShowTermsOfUsePromptDragHandle,
onDismiss = { dismiss() },
onDismissRequest = {
termsOfUsePromptStore.dispatch(
diff --git a/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt b/mobile/android/fenix/app/src/main/java/org/mozilla/fenix/utils/Settings.kt
@@ -617,6 +617,15 @@ class Settings(
)
/**
+ * Returns true if the nimbus flag for showing the terms of use drag handle is true.
+ */
+ var shouldShowTermsOfUsePromptDragHandle by lazyFeatureFlagPreference(
+ key = appContext.getPreferenceKey(R.string.pref_key_terms_prompt_drag_handle_enabled),
+ default = { FxNimbus.features.termsOfUsePrompt.value().enableDragToDismiss },
+ featureFlag = true,
+ )
+
+ /**
* The maximum number of times the Terms of Use prompt should be displayed.
*
* Use a function to ensure the most up-to-date Nimbus value is retrieved.
diff --git a/mobile/android/fenix/app/src/main/res/values/preference_keys.xml b/mobile/android/fenix/app/src/main/res/values/preference_keys.xml
@@ -86,6 +86,7 @@
<string name="pref_key_terms_accepted_date" translatable="false">pref_key_terms_accepted_date</string>
<string name="pref_key_terms_accepted_version" translatable="false">pref_key_terms_accepted_version</string>
<string name="pref_key_terms_prompt_enabled" translatable="false">pref_key_terms_prompt_enabled</string>
+ <string name="pref_key_terms_prompt_drag_handle_enabled" translatable="false">pref_key_terms_prompt_drag_handle_enabled</string>
<string name="pref_key_terms_prompt_displayed_count" translatable="false">pref_key_terms_prompt_displayed_count</string>
<string name="pref_key_terms_last_prompt_time" translatable="false">pref_key_terms_last_prompt_time</string>
<string name="pref_key_terms_postponed" translatable="false">pref_key_terms_postponed</string>