Skip to content

Commit 93084f4

Browse files
committed
Merge branch 'trunk' of github.com:wordpress-mobile/WordPress-Android into analysis/wordpress-main-deprecated-warnings-part-2
� Conflicts: � WordPress/src/main/java/org/wordpress/android/ui/mediapicker/loader/DeviceMediaLoader.kt
2 parents 7eb5607 + 09a3984 commit 93084f4

154 files changed

Lines changed: 912 additions & 789 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

RELEASE-NOTES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
21.0
44
-----
55
* [*] Updates splash screen for Android 12+ [https://github.com/wordpress-mobile/WordPress-Android/pull/17273]
6+
* [*] Fix text color of success messages in the QR code login flow [https://github.com/wordpress-mobile/WordPress-Android/pull/17286]
67

78
20.9
89
-----

WordPress/src/androidTest/java/org/wordpress/android/TestUtils.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
import android.content.SharedPreferences;
55
import android.content.SharedPreferences.Editor;
66
import android.database.sqlite.SQLiteDatabase;
7-
import android.preference.PreferenceManager;
87
import android.text.TextUtils;
98

9+
import androidx.preference.PreferenceManager;
10+
1011
import org.greenrobot.eventbus.EventBus;
1112
import org.wordpress.android.util.DateTimeUtils;
1213

WordPress/src/androidTest/java/org/wordpress/android/e2e/ContactUsTests.java

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -38,29 +38,6 @@ public void e2eSendButtonEnabledWhenTextIsEntered() {
3838
}
3939
}
4040

41-
@Ignore("As long as CI does not use gradle.properties from MobileSecrets")
42-
@Test
43-
public void e2eMessageCanBeSent() {
44-
String userMessageText = "Please ignore, this is an automated test.";
45-
String automatedReplyText = "Mobile support will respond as soon as possible, "
46-
+ "generally within 48-96 hours. "
47-
+ "Please reply with your site address (URL) "
48-
+ "and any additional details we should know.";
49-
50-
try {
51-
new LoginFlow()
52-
.chooseContinueWithWpCom()
53-
.tapHelp()
54-
.openContactUs()
55-
.setMessageText(userMessageText)
56-
.tapSendButton()
57-
.assertUserMessageDelivered(userMessageText)
58-
.assertSystemMessageReceived(automatedReplyText);
59-
} finally {
60-
new ContactSupportScreen().goBackAndDeleteUnsentMessageIfNeeded();
61-
}
62-
}
63-
6441
@Test
6542
public void e2eHelpCanBeOpenedWhileEnteringEmail() {
6643
new LoginFlow()

WordPress/src/androidTest/java/org/wordpress/android/e2e/pages/ContactSupportScreen.java

Lines changed: 0 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88

99
import static androidx.test.espresso.Espresso.onView;
1010
import static androidx.test.espresso.assertion.ViewAssertions.matches;
11-
import static androidx.test.espresso.matcher.ViewMatchers.hasDescendant;
1211
import static androidx.test.espresso.matcher.ViewMatchers.isCompletelyDisplayed;
1312
import static androidx.test.espresso.matcher.ViewMatchers.isEnabled;
1413
import static androidx.test.espresso.matcher.ViewMatchers.withId;
@@ -18,7 +17,6 @@
1817
import static org.hamcrest.Matchers.not;
1918
import static org.wordpress.android.support.WPSupportUtils.populateTextField;
2019
import static org.wordpress.android.support.WPSupportUtils.sleep;
21-
import static org.wordpress.android.support.WPSupportUtils.waitForElementToBeDisplayed;
2220
import static org.wordpress.android.support.WPSupportUtils.waitForElementToBeDisplayedWithoutFailure;
2321

2422
public class ContactSupportScreen {
@@ -42,11 +40,6 @@ public class ContactSupportScreen {
4240
));
4341

4442
// Actions:
45-
public ContactSupportScreen tapSendButton() {
46-
sendButton.perform(ViewActions.click());
47-
return this;
48-
}
49-
5043
public ContactSupportScreen setMessageText(String text) {
5144
populateTextField(textInput, text);
5245
// This sleep serves only one purpose: allowing human to notice
@@ -88,32 +81,4 @@ public ContactSupportScreen assertSendButtonEnabled() {
8881
sendButton.check(matches(isEnabled()));
8982
return this;
9083
}
91-
92-
public ContactSupportScreen assertUserMessageDelivered(String messageText) {
93-
ViewInteraction userMessageContainer = onView(allOf(
94-
withId(R.id.request_user_message_container),
95-
hasDescendant(allOf(
96-
withId(R.id.request_user_message_text),
97-
withText(messageText)
98-
)),
99-
hasDescendant(allOf(
100-
withId(R.id.request_user_message_status),
101-
withText("Delivered")
102-
))
103-
));
104-
105-
waitForElementToBeDisplayed(userMessageContainer);
106-
userMessageContainer.check(matches(isCompletelyDisplayed()));
107-
return this;
108-
}
109-
110-
public ContactSupportScreen assertSystemMessageReceived(String messageText) {
111-
ViewInteraction systemResponseBubble = onView(allOf(
112-
withId(R.id.request_system_message_text),
113-
withText(messageText)));
114-
115-
waitForElementToBeDisplayed(systemResponseBubble);
116-
systemResponseBubble.check(matches(isCompletelyDisplayed()));
117-
return this;
118-
}
11984
}

WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedFragment.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import android.content.res.Configuration.UI_MODE_NIGHT_YES
55
import android.os.Bundle
66
import android.view.LayoutInflater
77
import android.view.ViewGroup
8-
import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
98
import androidx.compose.foundation.layout.Box
109
import androidx.compose.foundation.layout.padding
1110
import androidx.compose.foundation.layout.size
@@ -32,6 +31,7 @@ import org.wordpress.android.ui.accounts.login.components.PrimaryButton
3231
import org.wordpress.android.ui.accounts.login.components.SecondaryButton
3332
import org.wordpress.android.ui.accounts.login.components.TopLinearGradient
3433
import org.wordpress.android.ui.compose.theme.AppTheme
34+
import org.wordpress.android.util.extensions.setTransparentSystemBars
3535

3636
val LocalPosition = compositionLocalOf { 0f }
3737

@@ -64,12 +64,12 @@ class LoginPrologueRevampedFragment : Fragment() {
6464

6565
override fun onResume() {
6666
super.onResume()
67-
requireActivity().window.addFlags(FLAG_LAYOUT_NO_LIMITS)
67+
requireActivity().window.setTransparentSystemBars(true)
6868
}
6969

7070
override fun onPause() {
7171
super.onPause()
72-
requireActivity().window.clearFlags(FLAG_LAYOUT_NO_LIMITS)
72+
requireActivity().window.setTransparentSystemBars(false)
7373
}
7474

7575
companion object {

WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/LoginPrologueRevampedViewModel.kt

Lines changed: 46 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -11,71 +11,88 @@ import androidx.lifecycle.ViewModel
1111
import dagger.hilt.android.lifecycle.HiltViewModel
1212
import dagger.hilt.android.qualifiers.ApplicationContext
1313
import javax.inject.Inject
14-
import kotlin.math.exp
15-
import kotlin.math.ln
14+
import kotlin.math.PI
1615

17-
// This factor is used to convert the raw values emitted from device sensor to an appropriate scale for the consuming
18-
// composables.
19-
private const val ACCELERATION_FACTOR = -0.1f
16+
/**
17+
* This factor is used to convert the raw values emitted from device sensor to an appropriate scale for the consuming
18+
* composables. The range for pitch values is -π/2 to π/2, representing an upright pose and an upside-down pose,
19+
* respectively. E.g. Setting this factor to 0.2 / (π/2) will scale this output range to -0.2 to 0.2. The resulting
20+
* product is interpreted in units proportional to the repeating child composable's height per second, i.e. at a
21+
* velocity of 0.1, it will take 10 seconds for the looping animation to repeat. When applied, the product can also be
22+
* thought of as a frequency value in Hz.
23+
*/
24+
private const val VELOCITY_FACTOR = (0.2 / (PI / 2)).toFloat()
2025

21-
// The maximum velocity (in either direction)
22-
private const val MAXIMUM_VELOCITY = 0.125f
23-
24-
// The velocity decay factor (i.e. 1/4th velocity after 1 second)
25-
private val VELOCITY_DECAY = -ln(4f)
26-
27-
// An additional acceleration applied to make the text scroll when the device is flat on a table
28-
private const val DRIFT = -0.05f
26+
/**
27+
* This is the default pitch provided for devices lacking support for the sensors used. This is consumed by the model
28+
* as a value in radians, but is specified here as -30 degrees for convenience. This represents a device pose that is
29+
* slightly upright from flat, approximating a typical usage pattern, and will ensure that the text is animated at
30+
* an appropriate velocity when sensors are unavailable.
31+
*/
32+
private const val DEFAULT_PITCH = (-30 * PI / 180).toFloat()
2933

3034
@HiltViewModel
3135
class LoginPrologueRevampedViewModel @Inject constructor(
3236
@ApplicationContext appContext: Context,
3337
) : ViewModel() {
34-
private var acceleration = -0.3f // Default value when sensor is off
35-
private var velocity = 0f
38+
private val accelerometerData = FloatArray(3)
39+
private val magnetometerData = FloatArray(3)
40+
private val rotationMatrix = FloatArray(9)
41+
private val orientationAngles = floatArrayOf(0f, DEFAULT_PITCH, 0f)
3642
private var position = 0f
3743

3844
/**
3945
* This function updates the physics model for the interactive animation by applying the elapsed time (in seconds)
4046
* to update the velocity and position.
4147
*
42-
* * Velocity is constrained so that it does not fall below -MAXIMUM_VELOCITY and does not exceed MAXIMUM_VELOCITY.
48+
* * Velocity is calculated as proportional to the pitch angle
4349
* * Position is constrained so that it always falls between 0 and 1, and represents the relative vertical offset
4450
* in terms of the height of the repeated child composable.
4551
*
4652
* @param elapsed the elapsed time (in seconds) since the last frame
4753
*/
4854
fun updateForFrame(elapsed: Float) {
49-
// Update the velocity, (decayed and clamped to the maximum)
50-
velocity = (velocity * exp(elapsed * VELOCITY_DECAY) + elapsed * acceleration)
51-
.coerceIn(-MAXIMUM_VELOCITY, MAXIMUM_VELOCITY)
52-
// Update the position, modulo 1 (ensuring a value greater or equal to 0, and less than 1)
53-
position = ((position + elapsed * velocity) % 1 + 1) % 1
55+
orientationAngles.let { (_, pitch) ->
56+
val velocity = pitch * VELOCITY_FACTOR
5457

55-
_positionData.postValue(position)
58+
// Update the position, modulo 1 (ensuring a value greater or equal to 0, and less than 1)
59+
position = ((position + elapsed * velocity) % 1 + 1) % 1
60+
61+
_positionData.postValue(position)
62+
}
5663
}
5764

58-
/** This LiveData responds to accelerometer data from the y-axis of the device and emits updated position data. */
65+
/**
66+
* This LiveData responds to orientation data to calculate the pitch of the device. This is then used to update the
67+
* velocity and position for each frame.
68+
*/
5969
private val _positionData = object : MutableLiveData<Float>(), SensorEventListener {
6070
private val sensorManager
6171
get() = appContext.getSystemService(Context.SENSOR_SERVICE) as SensorManager
6272

6373
override fun onActive() {
6474
super.onActive()
65-
val sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)
66-
sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_GAME)
75+
sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER)?.also {
76+
sensorManager.registerListener( this, it, SensorManager.SENSOR_DELAY_GAME)
77+
}
78+
sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD)?.also {
79+
sensorManager.registerListener( this, it, SensorManager.SENSOR_DELAY_GAME)
80+
}
6781
}
6882

6983
override fun onInactive() {
7084
super.onInactive()
7185
sensorManager.unregisterListener(this)
7286
}
7387

74-
override fun onSensorChanged(event: SensorEvent?) {
75-
event?.values?.let { (_, yAxisAcceleration, _) ->
76-
acceleration = yAxisAcceleration * ACCELERATION_FACTOR + DRIFT
77-
postValue(position)
88+
override fun onSensorChanged(event: SensorEvent) {
89+
when (event.sensor.type) {
90+
Sensor.TYPE_ACCELEROMETER -> event.values.copyInto(accelerometerData)
91+
Sensor.TYPE_MAGNETIC_FIELD -> event.values.copyInto(magnetometerData)
7892
}
93+
// Update the orientation angles when sensor data is updated
94+
SensorManager.getRotationMatrix(rotationMatrix, null, accelerometerData, magnetometerData)
95+
SensorManager.getOrientation(rotationMatrix, orientationAngles)
7996
}
8097

8198
override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) = Unit

WordPress/src/jetpack/java/org/wordpress/android/ui/accounts/login/components/ColumnWithFrostedGlassBackground.kt

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import androidx.compose.ui.graphics.Outline.Rectangle
1919
import androidx.compose.ui.graphics.Shape
2020
import androidx.compose.ui.graphics.SolidColor
2121
import androidx.compose.ui.layout.SubcomposeLayout
22-
import androidx.compose.ui.platform.LocalDensity
2322
import androidx.compose.ui.res.colorResource
2423
import androidx.compose.ui.unit.Density
2524
import androidx.compose.ui.unit.LayoutDirection
@@ -28,6 +27,8 @@ import org.wordpress.android.R
2827
import org.wordpress.android.ui.accounts.login.components.SlotsEnum.Buttons
2928
import org.wordpress.android.ui.accounts.login.components.SlotsEnum.ClippedBackground
3029

30+
private val blurRadius = 30.dp
31+
3132
/**
3233
* These slots are utilized below in a subcompose layout in order to measure the size of the buttons composable. The
3334
* measured height is then used to create a clip shape for the blurred background layer. This allows the background
@@ -37,23 +38,14 @@ private enum class SlotsEnum { Buttons, ClippedBackground }
3738

3839
@Composable
3940
private fun ColumnWithTopGlassBorder(
40-
modifier: Modifier = Modifier,
4141
content: @Composable ColumnScope.() -> Unit
4242
) {
4343
Column(
44-
modifier = modifier
45-
.background(
46-
brush = SolidColor(colorResource(R.color.bg_jetpack_login_splash_bottom_panel)),
47-
alpha = 0.6f
48-
)
44+
modifier = Modifier.background(SolidColor(colorResource(R.color.bg_jetpack_login_splash_bottom_panel)))
4945
) {
5046
Divider(
5147
thickness = 1.dp,
52-
color = colorResource(R.color.border_shadow_jetpack_login_splash_bottom_panel),
53-
)
54-
Divider(
55-
thickness = 1.dp,
56-
color = colorResource(R.color.border_highlight_jetpack_login_splash_bottom_panel),
48+
color = colorResource(R.color.border_top_jetpack_login_splash_bottom_panel),
5749
)
5850
content()
5951
}
@@ -64,8 +56,6 @@ fun ColumnWithFrostedGlassBackground(
6456
background: @Composable (modifier: Modifier, textModifier: Modifier) -> Unit,
6557
content: @Composable () -> Unit,
6658
) {
67-
val topBorderHeight = with(LocalDensity.current) { 1.dp.toPx() }
68-
6959
SubcomposeLayout { constraints ->
7060
val buttonsPlaceables = subcompose(Buttons) {
7161
ColumnWithTopGlassBorder {
@@ -81,7 +71,7 @@ fun ColumnWithFrostedGlassBackground(
8171
bottom = size.height,
8272
left = 0f,
8373
right = size.width,
84-
top = size.height - buttonsHeight + topBorderHeight,
74+
top = size.height - buttonsHeight,
8575
)
8676
)
8777
}
@@ -92,11 +82,11 @@ fun ColumnWithFrostedGlassBackground(
9282
modifier = Modifier.clip(buttonsClipShape),
9383
textModifier = Modifier.composed {
9484
if (VERSION.SDK_INT >= VERSION_CODES.S) {
95-
blur(15.dp, BlurredEdgeTreatment.Unbounded)
85+
blur(blurRadius, BlurredEdgeTreatment.Unbounded)
9686
} else {
9787
// On versions older than Android 12 the blur modifier is not supported,
9888
// so we make the text transparent to have the buttons stand out.
99-
alpha(0.25f)
89+
alpha(0.05f)
10090
}
10191
}
10292
)

0 commit comments

Comments
 (0)