summaryrefslogtreecommitdiffstats
path: root/mobile/android/android-components/components/compose
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:35:29 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:35:29 +0000
commit59203c63bb777a3bacec32fb8830fba33540e809 (patch)
tree58298e711c0ff0575818c30485b44a2f21bf28a0 /mobile/android/android-components/components/compose
parentAdding upstream version 126.0.1. (diff)
downloadfirefox-59203c63bb777a3bacec32fb8830fba33540e809.tar.xz
firefox-59203c63bb777a3bacec32fb8830fba33540e809.zip
Adding upstream version 127.0.upstream/127.0
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mobile/android/android-components/components/compose')
-rw-r--r--mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupLayout.kt160
1 files changed, 160 insertions, 0 deletions
diff --git a/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupLayout.kt b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupLayout.kt
new file mode 100644
index 0000000000..4585c0303d
--- /dev/null
+++ b/mobile/android/android-components/components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupLayout.kt
@@ -0,0 +1,160 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package mozilla.components.compose.cfr
+
+import android.view.View
+import androidx.compose.foundation.background
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.IntrinsicSize
+import androidx.compose.foundation.layout.Spacer
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.size
+import androidx.compose.material.Button
+import androidx.compose.material.Text
+import androidx.compose.material.TextButton
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.LaunchedEffect
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.runtime.saveable.rememberSaveable
+import androidx.compose.runtime.setValue
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.tooling.preview.Preview
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
+
+typealias DismissAction = () -> Unit
+
+/**
+ * A layout for displaying a [CFRPopup] anchored by [anchorContent].
+ *
+ * @param showCFR Whether to display the CFR.
+ * @param properties [CFRPopupProperties] allowing to customize the popup appearance and behavior.
+ * @param onCFRShown Invoked when the CFR is displayed.
+ * @param onDismiss Invoked when the CFR is dismissed. Returns true if the dismissal was
+ * explicit (e.g. clicked via the "X" button).
+ * @param text [Text] block containing the CFR's message.
+ * @param action Optional Composable displayed below [text]. Provides a [DismissAction] if the CFR needs
+ * to be dismissed after the action is invoked.
+ * @param anchorContent The Composable to anchor the CFR to.
+ */
+@Composable
+fun CFRPopupLayout(
+ showCFR: Boolean,
+ properties: CFRPopupProperties,
+ onCFRShown: () -> Unit,
+ onDismiss: (Boolean) -> Unit,
+ text: @Composable () -> Unit,
+ action: @Composable (dismissCFR: DismissAction) -> Unit = {},
+ anchorContent: @Composable () -> Unit,
+) {
+ var hasDismissedCFR by rememberSaveable { mutableStateOf(false) }
+
+ Box(
+ modifier = Modifier.height(intrinsicSize = IntrinsicSize.Min),
+ ) {
+ if (showCFR && !hasDismissedCFR) {
+ LaunchedEffect(Unit) {
+ onCFRShown()
+ }
+
+ var popup: CFRPopup? = null
+
+ val invokeDismiss: DismissAction = {
+ if (!hasDismissedCFR) {
+ popup?.dismiss()
+ }
+ popup = null
+ }
+
+ AndroidView(
+ modifier = Modifier.fillMaxSize(),
+ factory = { context ->
+ View(context).also {
+ popup = CFRPopup(
+ anchor = it,
+ properties = properties,
+ onDismiss = { dismissFromButton ->
+ onDismiss(dismissFromButton)
+ hasDismissedCFR = true
+ },
+ text = text,
+ action = {
+ action(invokeDismiss)
+ },
+ )
+ }
+ },
+ onRelease = {
+ invokeDismiss()
+ },
+ update = {
+ popup?.dismiss()
+ popup?.show()
+ },
+ )
+ }
+
+ anchorContent()
+ }
+}
+
+/**
+ * This is to validate the sizing of the underlying AndroidView. The current implementation of CFRs
+ * via [CFRPopupFullscreenLayout] do not render in previews.
+ */
+@Preview
+@Composable
+private fun CFRPopupLayoutPreview() {
+ var cfrVisible by remember { mutableStateOf(true) }
+
+ Column(
+ modifier = Modifier
+ .fillMaxSize()
+ .background(color = Color.LightGray),
+ ) {
+ CFRPopupLayout(
+ showCFR = cfrVisible,
+ properties = CFRPopupProperties(),
+ onCFRShown = {},
+ onDismiss = { cfrVisible = false },
+ text = {
+ Text(text = "This is a CFR in Compose")
+ },
+ action = {
+ TextButton(onClick = { cfrVisible = false }) {
+ Text(text = "Dismiss")
+ }
+ },
+ ) {
+ Box(modifier = Modifier.size(300.dp)) {
+ Text(
+ text = "This is the thing the CFR is anchored to",
+ modifier = Modifier.align(alignment = Alignment.Center),
+ )
+ }
+ }
+
+ Spacer(modifier = Modifier.height(60.dp))
+
+ Box(modifier = Modifier.size(100.dp)) {
+ Text(
+ text = "This is just another element",
+ modifier = Modifier.align(alignment = Alignment.Center),
+ )
+ }
+
+ Spacer(modifier = Modifier.height(60.dp))
+
+ Button(onClick = { cfrVisible = true }) {
+ Text(text = "Show CFR")
+ }
+ }
+}