For #12855 - Upstream the CFRPopup from Fenix to AC to share it in multiple projects #12828
Conversation
enum class Orientation | ||
|
||
// WIP | ||
object ScreenOrientation { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fenix uses GeckoScreenOrientation
from geckoview
which seems like a just a bit too big of a dependency to add for just that listener.
So we have to add our own.
Thinking that it might be useful to have it in a separate module, available to other ones which don't need the CFR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I saw this earlier when investigating other CFRs for Focus and I was curious, why do we use the GeckoScreenOrientation listener for the CFRs? It seems like it's used for knowing when the app was rotated and we can get that directly from Android APIs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+100 for this upstream change though. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was using GeckoScreenOrientation
since it was already available and ready to use.
Having to find a replacement now reminded me that although there are Android APIs for this (which GeckoScreenOrientation
uses), there are many such APIs, some deprecated in other versions of Android and there is no simple listener that would just work.
For example the OrientationEventListener Google recommends will also fire if "Auto-rotate" is disabled, similar to a sensor listener though the display will not actually be rotated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
taskcluster and build changes lgtm. Someone else should review all the .kt files.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a good example of Compose code to have upstream for referencing that makes it easy to read too. It also has nice examples of propagation of properties needed by inner functions. 🙂
Let's remove the debug println and add a translatable doc - everything else looks great!
style = MaterialTheme.typography.body2, | ||
) | ||
}, | ||
action = { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Self-note: Comparing to what is in Focus, it looks like action
is the new API addition with the added properties
above too.
class CFRPopup(
private val container: View,
private val text: String,
private val anchor: View,
private val properties: CFRPopupProperties = CFRPopupProperties(),
private val onDismiss: () -> Unit = {},
)
data class CFRPopupProperties( | ||
val popupWidth: Dp = CFRPopup.DEFAULT_WIDTH.dp, | ||
val popupAlignment: PopupAlignment = PopupAlignment.BODY_TO_ANCHOR_CENTER, | ||
val popupBodyColors: List<Int> = listOf(Color.Blue.toArgb()), | ||
val dismissButtonColor: Int = Color.Black.toArgb(), | ||
val indicatorDirection: IndicatorDirection = IndicatorDirection.UP, | ||
val dismissOnBackPress: Boolean = true, | ||
val dismissOnClickOutside: Boolean = true, | ||
val overlapAnchor: Boolean = false, | ||
val popupVerticalOffset: Dp = CFRPopup.DEFAULT_VERTICAL_OFFSET.dp, | ||
val indicatorArrowStartOffset: Dp = CFRPopup.DEFAULT_INDICATOR_START_OFFSET.dp, | ||
) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cosmetic (update only if there are other valuable additions to make to the PR): keep the popup
, indicator
, and dismiss
properties together.
data class CFRPopupProperties( | |
val popupWidth: Dp = CFRPopup.DEFAULT_WIDTH.dp, | |
val popupAlignment: PopupAlignment = PopupAlignment.BODY_TO_ANCHOR_CENTER, | |
val popupBodyColors: List<Int> = listOf(Color.Blue.toArgb()), | |
val dismissButtonColor: Int = Color.Black.toArgb(), | |
val indicatorDirection: IndicatorDirection = IndicatorDirection.UP, | |
val dismissOnBackPress: Boolean = true, | |
val dismissOnClickOutside: Boolean = true, | |
val overlapAnchor: Boolean = false, | |
val popupVerticalOffset: Dp = CFRPopup.DEFAULT_VERTICAL_OFFSET.dp, | |
val indicatorArrowStartOffset: Dp = CFRPopup.DEFAULT_INDICATOR_START_OFFSET.dp, | |
) | |
data class CFRPopupProperties( | |
val popupWidth: Dp = CFRPopup.DEFAULT_WIDTH.dp, | |
val popupAlignment: PopupAlignment = PopupAlignment.BODY_TO_ANCHOR_CENTER, | |
val popupBodyColors: List<Int> = listOf(Color.Blue.toArgb()), | |
val popupVerticalOffset: Dp = CFRPopup.DEFAULT_VERTICAL_OFFSET.dp, | |
val dismissButtonColor: Int = Color.Black.toArgb(), | |
val dismissOnBackPress: Boolean = true, | |
val dismissOnClickOutside: Boolean = true, | |
val overlapAnchor: Boolean = false, | |
val indicatorDirection: IndicatorDirection = IndicatorDirection.UP, | |
val indicatorArrowStartOffset: Dp = CFRPopup.DEFAULT_INDICATOR_START_OFFSET.dp, | |
) |
println("Mugurel: anchor start?: ${anchor.x}") | ||
println("Mugurel: popup start?: ${popupBounds.startCoord}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oops.
), | ||
) | ||
|
||
MaterialTheme { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not well versed in Compose, so disregard accordingly: how does the MaterialTheme
interact with our FirefoxTheme
if we have it wrapped here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They both are singletons from where inner composables can request values.
The composables are hardcoded to request a certain value from a certain singleton theme.
For example a platform composable uses values from MaterialTheme - https://cs.android.com/androidx/platform/tools/dokka-devsite-plugin/+/master:testData/compose/source/androidx/compose/material/Card.kt;l=59,60;drc=6fed3de7a56143de954d55e508a7449deb9af582
Or here Fenix composables use values from the FirefoxTheme - https://github.com/mozilla-mobile/fenix/blob/262aa169911853f23afdd94ebf2b0def0b274cb2/app/src/main/java/org/mozilla/fenix/home/recentbookmarks/view/RecentBookmarks.kt#L135-L138
Wrapping composables in themes would allow theme values to be overriden
- like I did here for in place overrides or
- as shown here for general overrides which would then require wrapping all platform composables with that new theme which overrides all
MaterialTheme
colors.
but we don't do/need that here so all references to MaterialTheme can be removed.
Tested on Focus with Gabi's patch from mozilla-mobile/focus-android#7705 and saw everything working just as before.
components/compose/cfr/src/main/java/mozilla/components/compose/cfr/CFRPopupContent.kt
Show resolved
Hide resolved
- 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/. --> | ||
<resources> | ||
<string name="mozac_cfr_dismiss_button_content_description">Dismiss</string> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs translation description above this, right?
@@ -0,0 +1 @@ | |||
sdk=28 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't need this anymore with robolectric upgraded now.
private val displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager | ||
|
||
@VisibleForTesting | ||
internal var currentOrientation = -10 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where did -10 come from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wanted an invalid value to start with to ensure the below check display.rotation != currentOrientation
will always pass.
Should've been better documented.
Instead of using a magic number SCREEN_ORIENTATION_UNSET/UNSPECIFIED
would better suffice.
...ompose/cfr/src/main/java/mozilla/components/compose/cfr/helper/DisplayOrientationListener.kt
Outdated
Show resolved
Hide resolved
This pull request has conflicts when rebasing. Could you fix it @Mugurell? 🙏 |
This pull request has conflicts when rebasing. Could you fix it @Mugurell? 🙏 |
Not sure why the CI tasks are stuck. |
Seems like
in Locally this builds fine. |
This upstreams the CFR composable already used on Fenix allowing it to be reused on other projects also. The setup process requires quite a few parameters because as it is highly customizable supporting different indicator orientations or positionings in relation to the anchor and also supporting RTL.
Seems like this was failing because of the |
|
@Mergifyio backport releases/107.0 |
✅ Backports have been created
|
Found 2 small bugs that I fixed in the process, testing on Focus everything works as expected.
Proposed new API tested on Focus which would allow the needed customization - https://github.com/mozilla-mobile/android-components/pull/12828/files#diff-55b4a3672da3aa9ede82afef5dcc594077503876393b52b77cedbdf9d7315584
CFRPopupsInLTR.mp4
CFRPopupInRTL.mp4
Pull Request checklist
After merge
GitHub Automation
Fixes #12855