Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge staging to main for Assurance 3.0.2 release #130

Merged
merged 16 commits into from
Aug 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

package com.adobe.marketing.mobile.assurance.internal.ui.pin.error

import android.app.Application
import androidx.compose.ui.test.assertCountEquals
import androidx.compose.ui.test.assertIsDisplayed
import androidx.compose.ui.test.assertTextEquals
Expand All @@ -20,9 +21,12 @@ import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onChildren
import androidx.compose.ui.test.onNodeWithTag
import androidx.compose.ui.test.performClick
import androidx.test.platform.app.InstrumentationRegistry
import com.adobe.marketing.mobile.MobileCore
import com.adobe.marketing.mobile.assurance.internal.AssuranceConstants
import com.adobe.marketing.mobile.assurance.internal.ui.AssuranceUiTestTags
import com.adobe.marketing.mobile.assurance.internal.ui.pin.PinScreenAction
import org.junit.Before
import org.junit.Rule
import org.junit.Test

Expand All @@ -33,6 +37,11 @@ class PinErrorViewTest {

private val actions = mutableListOf<PinScreenAction>()

@Before
fun setUp() {
MobileCore.setApplication(InstrumentationRegistry.getInstrumentation().context.applicationContext as Application)
}

@Test
fun testPinErrorViewWithRetryableError() {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

package com.adobe.marketing.mobile.assurance.internal.ui.quickconnect

import android.app.Application
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.test.assertAny
import androidx.compose.ui.test.assertHasClickAction
Expand All @@ -22,16 +23,24 @@ import androidx.compose.ui.test.hasText
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onChildren
import androidx.compose.ui.test.onNodeWithTag
import androidx.test.platform.app.InstrumentationRegistry
import com.adobe.marketing.mobile.MobileCore
import com.adobe.marketing.mobile.assurance.internal.AssuranceConstants
import com.adobe.marketing.mobile.assurance.internal.ui.AssuranceUiTestTags
import com.adobe.marketing.mobile.assurance.internal.ui.common.ConnectionState
import org.junit.Before
import org.junit.Rule
import org.junit.Test

class QuickConnectViewTests {
@get: Rule
val composeTestRule = createComposeRule()

@Before
fun setUp() {
MobileCore.setApplication(InstrumentationRegistry.getInstrumentation().context.applicationContext as Application)
}

@Test
fun testQuickConnectViewWhenIdle() {
val quickConnectState = mutableStateOf<ConnectionState>(ConnectionState.Disconnected(null))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public class Assurance {

public static final Class<? extends Extension> EXTENSION = AssuranceExtension.class;
public static final String LOG_TAG = "Assurance";
public static final String EXTENSION_VERSION = "3.0.1";
public static final String EXTENSION_VERSION = "3.0.2";
public static final String EXTENSION_NAME = "com.adobe.assurance";
public static final String EXTENSION_FRIENDLY_NAME = "Assurance";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

package com.adobe.marketing.mobile.assurance.internal

import com.adobe.marketing.mobile.assurance.R
import com.adobe.marketing.mobile.services.ServiceProvider
import java.util.concurrent.TimeUnit

internal object AssuranceConstants {
Expand Down Expand Up @@ -230,76 +232,93 @@ internal object AssuranceConstants {
}

internal enum class AssuranceConnectionError(
val error: String,
val description: String,
private val errorResId: Int,
private val descriptionResId: Int,
@JvmField val isRetryable: Boolean
) {
GENERIC_ERROR(
"Connection Error",
"The connection may be failing due to a network issue or an incorrect Pin. " +
"Please verify internet connectivity or the Pin and try again.",
R.string.error_title_incorrect_pin_or_network,
R.string.error_desc_incorrect_pin_or_network,
true
),
NO_ORG_ID(
"Invalid Configuration",
"The Experience Cloud organization identifier is unavailable from the SDK. Ensure" +
" SDK configuration is setup correctly. See documentation for more detail.",
R.string.error_title_invalid_org_id,
R.string.error_desc_invalid_org_id,
false
),
ORG_ID_MISMATCH(
"Unauthorized Access",
"The Experience Cloud organization identifier does not match with that of the" +
" Assurance session. Ensure the right Experience Cloud organization is being" +
" used. See documentation for more detail.",
R.string.error_title_unauthorized_access,
R.string.error_desc_unauthorized_access,
false
),
CONNECTION_LIMIT(
"Connection Limit Reached",
"You have reached the maximum number of connected devices allowed for a session. " +
"Please disconnect another device and try again.",
R.string.error_title_connection_limit,
R.string.error_desc_connection_limit,
false
),
EVENT_LIMIT(
"Event Limit Reached",
"You have reached the maximum number of events that can be sent per minute.",
R.string.error_title_event_limit,
R.string.error_desc_event_limit,
false
),
CLIENT_ERROR(
"Client Disconnected",
"This client has been disconnected due to an unexpected error. Error Code 4400.",
R.string.error_title_unexpected_error,
R.string.error_desc_unexpected_error,
false
),
SESSION_DELETED(
"Session Deleted",
"The session client connected to has been deleted. Error Code 4903.",
R.string.error_title_session_deleted,
R.string.error_desc_session_deleted,
false
),
CREATE_DEVICE_REQUEST_MALFORMED(
"Malformed Request",
"The network request for device creation was malformed.",
R.string.error_title_invalid_registration_request,
R.string.error_desc_invalid_registration_request,
false
),
STATUS_CHECK_REQUEST_MALFORMED(
"Malformed Request",
"The network request for status check was malformed.",
R.string.error_title_invalid_registration_request,
R.string.error_desc_invalid_registration_request,
false
),
RETRY_LIMIT_REACHED(
"Retry Limit Reached",
"The maximum allowed retries for fetching the session details were reached.",
R.string.error_title_retry_limit_reached,
R.string.error_desc_retry_limit_reached,
true
),
CREATE_DEVICE_REQUEST_FAILED(
"Request Failed",
"Failed to register device.",
R.string.error_title_registration_error,
R.string.error_desc_registration_error,
true
),
DEVICE_STATUS_REQUEST_FAILED(
"Request Failed",
"Failed to get device status",
R.string.error_title_registration_error,
R.string.error_desc_registration_error,
true
),
UNEXPECTED_ERROR("Unexpected Error", "An unexpected error occurred", true)
UNEXPECTED_ERROR(
R.string.error_title_invalid_registration_response,
R.string.error_desc_invalid_registration_response,
true
);

val error: String
get() {
val context = ServiceProvider.getInstance().appContextService.applicationContext
// This code path should never be crossed if the app context is null because the SDK
// operations require a valid context. Default to empty string if context is null
// because we don't want to crash the app.
return context?.getString(errorResId) ?: ""
}

val description: String
get() {
val context = ServiceProvider.getInstance().appContextService.applicationContext
// This code path should never be crossed if the app context is null because the SDK
// operations require a valid context. Default to empty string if context is null
// because we don't want to crash the app.
return context?.getString(descriptionResId) ?: ""
}
}

internal enum class UILogColorVisibility(val value: Int) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,14 @@ import android.content.pm.ActivityInfo
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.safeDrawingPadding
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.SideEffect
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.toArgb
import androidx.navigation.compose.rememberNavController
import com.adobe.marketing.mobile.assurance.internal.AssuranceComponentRegistry
Expand All @@ -26,7 +31,7 @@ import com.adobe.marketing.mobile.assurance.internal.ui.theme.AssuranceTheme.bac
/**
* Activity that hosts all of the Assurance UI.
*/
internal class AssuranceActivity : ComponentActivity() {
class AssuranceActivity : ComponentActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
Expand All @@ -36,29 +41,46 @@ internal class AssuranceActivity : ComponentActivity() {
setContent {
MaterialTheme(
content = {
// Locks the Assurance screen to always be in portrait mode.
val orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
DisposableEffect(orientation) {
val originalOrientation = requestedOrientation
requestedOrientation = orientation
onDispose {
// restore original orientation when view disappears
requestedOrientation = originalOrientation
}
}
Surface(
modifier = Modifier
.fillMaxSize(),
color = backgroundColor
) {
Box(
modifier = Modifier
.safeDrawingPadding()
.fillMaxSize()
) {

// Locks the Assurance screen to always be in portrait mode.
val orientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
DisposableEffect(orientation) {
val originalOrientation = requestedOrientation
requestedOrientation = orientation
onDispose {
// restore original orientation when view disappears
requestedOrientation = originalOrientation
}
}

// Set the status bar and navigation bar colors to be the same as the
// background color of Assurance screens. This isto simulate an edge to edge
// experience while the Assurance UI is active.
SideEffect {
with(this@AssuranceActivity) {
window.statusBarColor = backgroundColor.toArgb()
window.navigationBarColor = backgroundColor.toArgb()
// Set the status bar and navigation bar colors to be the same as the
// background color of Assurance screens. This is to simulate an edge to edge
// experience while the Assurance UI is active.
// TODO:
// When Assurance SDK's target SDK is updated to 35 (where the
// window.statusBarColor, window.navigationBarColor APIs are deprecated),
// update activity-compose dependency and use enableEdgeToEdge API.
SideEffect {
with(this@AssuranceActivity) {
window.statusBarColor = backgroundColor.toArgb()
window.navigationBarColor = backgroundColor.toArgb()
}
}

// The AssuranceNavHost composable which is the entry point for the Assurance UI.
AssuranceNavHost(rememberNavController(), connectionPhase)
}
}

// The AssuranceNavHost composable which is the entry point for the Assurance UI.
AssuranceNavHost(rememberNavController(), connectionPhase)
}
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ internal fun AssuranceErrorScreen(assuranceConnectionError: AssuranceConstants.A
modifier = Modifier.align(Alignment.BottomCenter)
) {
Text(
text = stringResource(id = R.string.pin_connect_button_dismiss),
text = stringResource(id = R.string.error_screen_button_dismiss),
fontFamily = FontFamily.SansSerif,
style = TextStyle(color = Color.White, fontSize = 24.sp)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ internal fun ActionButtonRow(
}
) {
Text(
text = stringResource(id = R.string.pin_connect_button_cancel),
text = stringResource(id = R.string.pin_screen_button_cancel),
fontFamily = FontFamily.SansSerif,
style = TextStyle(color = Color.White, fontSize = 24.sp)
)
Expand All @@ -71,7 +71,7 @@ internal fun ActionButtonRow(
onClick = { onAction(PinScreenAction.Connect(pin)) }
) {
Text(
text = stringResource(id = R.string.pin_connect_button_connect),
text = stringResource(id = R.string.pin_screen_button_connect),
fontFamily = FontFamily.SansSerif,
style = TextStyle(color = Color.White, fontSize = 24.sp)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,13 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.ui.Alignment
Expand All @@ -44,9 +48,12 @@ internal fun DialPadView(
pinScreenState: State<PinScreenState>,
onAction: (action: PinScreenAction) -> Unit
) {

val scrollState = rememberScrollState()
Box(
modifier = Modifier
.fillMaxSize()
.verticalScroll(scrollState)
.background(backgroundColor)
.padding(horizontal = AssuranceTheme.dimensions.padding.xxLarge)
.testTag(AssuranceUiTestTags.PinScreen.DIAL_PAD_VIEW)
Expand All @@ -56,12 +63,13 @@ internal fun DialPadView(
verticalArrangement = Arrangement.spacedBy(AssuranceTheme.dimensions.spacing.medium)
) {
AssuranceHeader()
AssuranceSubHeader(text = stringResource(id = R.string.pin_connect_enter_pin_text))
AssuranceSubHeader(text = stringResource(id = R.string.pin_screen_header))
InputFeedbackRow(input = pinScreenState.value.pin)
NumberRow(listOf("1", "2", "3"), onClick = { action -> onAction(action) })
NumberRow(listOf("4", "5", "6"), onClick = { action -> onAction(action) })
NumberRow(listOf("7", "8", "9"), onClick = { action -> onAction(action) })
SymbolRow(onClick = { action -> onAction(action) })
Spacer(modifier = Modifier.height(AssuranceTheme.dimensions.spacing.xLarge))
}

ActionButtonRow(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ internal fun ActionButtonRow(
}
) {
Text(
text = stringResource(id = R.string.pin_connect_button_cancel),
text = stringResource(id = R.string.pin_screen_button_cancel),
fontFamily = FontFamily.SansSerif,
style = TextStyle(color = Color.White, fontSize = 24.sp)
)
Expand All @@ -66,7 +66,7 @@ internal fun ActionButtonRow(
onClick = { onAction(PinScreenAction.Retry) }
) {
Text(
text = stringResource(id = R.string.pin_connect_button_retry),
text = stringResource(id = R.string.pin_screen_button_retry),
fontFamily = FontFamily.SansSerif,
style = TextStyle(color = Color.White, fontSize = 24.sp)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ internal fun PinAuthErrorMessageContent(text: String) {
fontFamily = FontFamily.SansSerif,
fontSize = 18.sp,
fontWeight = FontWeight.Normal,
textAlign = TextAlign.Justify
textAlign = TextAlign.Start
),
modifier = Modifier
.fillMaxWidth()
Expand Down
Loading
Loading