Skip to content

Commit dc3a510

Browse files
Merge pull request #99 from google-developer-training/starter_e2e_new
Starter update E2E
2 parents 757d5e4 + e975d25 commit dc3a510

File tree

17 files changed

+68
-330
lines changed

17 files changed

+68
-330
lines changed

app/build.gradle.kts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,12 @@ plugins {
2121

2222
android {
2323
namespace = "com.example.reply"
24-
compileSdk = 33
24+
compileSdk = 34
2525

2626
defaultConfig {
2727
applicationId = "com.example.reply"
2828
minSdk = 24
29-
targetSdk = 33
29+
targetSdk = 34
3030
versionCode = 1
3131
versionName = "1.0"
3232

@@ -57,7 +57,7 @@ android {
5757
compose = true
5858
}
5959
composeOptions {
60-
kotlinCompilerExtensionVersion = "1.4.7"
60+
kotlinCompilerExtensionVersion = "1.5.10"
6161
}
6262
packaging {
6363
resources {
@@ -67,18 +67,18 @@ android {
6767
}
6868

6969
dependencies {
70-
implementation(platform("androidx.compose:compose-bom:2023.06.00"))
71-
implementation("androidx.activity:activity-compose:1.7.2")
70+
implementation(platform("androidx.compose:compose-bom:2024.02.01"))
71+
implementation("androidx.activity:activity-compose:1.8.2")
7272
implementation("androidx.compose.material:material-icons-extended")
7373
implementation("androidx.compose.material3:material3")
7474
implementation("androidx.compose.ui:ui")
7575
implementation("androidx.compose.ui:ui-graphics")
7676
implementation("androidx.compose.ui:ui-tooling-preview")
77-
implementation("androidx.core:core-ktx:1.10.1")
77+
implementation("androidx.core:core-ktx:1.12.0")
7878
implementation("androidx.lifecycle:lifecycle-runtime-ktx:${rootProject.extra["lifecycle_version"]}")
7979
implementation("androidx.lifecycle:lifecycle-viewmodel-compose:${rootProject.extra["lifecycle_version"]}")
8080

81-
androidTestImplementation(platform("androidx.compose:compose-bom:2023.06.00"))
81+
androidTestImplementation(platform("androidx.compose:compose-bom:2024.02.01"))
8282
androidTestImplementation("androidx.compose.ui:ui-test-junit4")
8383
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
8484
androidTestImplementation("androidx.test.ext:junit:1.1.5")

app/src/androidTest/java/com/example/reply/test/ComposeTestRuleExtensions.kt

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -21,21 +21,8 @@ import androidx.compose.ui.test.SemanticsNodeInteraction
2121
import androidx.compose.ui.test.junit4.AndroidComposeTestRule
2222
import androidx.compose.ui.test.onNodeWithContentDescription
2323
import androidx.compose.ui.test.onNodeWithTag
24-
import androidx.compose.ui.test.onNodeWithText
2524
import androidx.test.ext.junit.rules.ActivityScenarioRule
2625

27-
/**
28-
* Finds a semantics node with the given string resource id.
29-
*
30-
* The [onNodeWithText] finder provided by compose ui test API, doesn't support usage of
31-
* string resource id to find the semantics node. This extension function accesses string resource
32-
* using underlying activity property and passes it to [onNodeWithText] function as argument and
33-
* returns the [SemanticsNodeInteraction] object.
34-
*/
35-
fun <A : ComponentActivity> AndroidComposeTestRule<ActivityScenarioRule<A>, A>.onNodeWithStringId(
36-
@StringRes id: Int
37-
): SemanticsNodeInteraction = onNodeWithText(activity.getString(id))
38-
3926
/**
4027
* Finds a semantics node from the content description with the given string resource id.
4128
*

app/src/main/java/com/example/reply/MainActivity.kt

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,38 @@ package com.example.reply
1818
import android.os.Bundle
1919
import androidx.activity.ComponentActivity
2020
import androidx.activity.compose.setContent
21+
import androidx.activity.enableEdgeToEdge
22+
import androidx.compose.foundation.layout.WindowInsets
23+
import androidx.compose.foundation.layout.asPaddingValues
24+
import androidx.compose.foundation.layout.calculateEndPadding
25+
import androidx.compose.foundation.layout.calculateStartPadding
26+
import androidx.compose.foundation.layout.padding
27+
import androidx.compose.foundation.layout.safeDrawing
2128
import androidx.compose.material3.Surface
2229
import androidx.compose.runtime.Composable
30+
import androidx.compose.ui.Modifier
31+
import androidx.compose.ui.platform.LocalLayoutDirection
2332
import androidx.compose.ui.tooling.preview.Preview
2433
import com.example.reply.ui.ReplyApp
2534
import com.example.reply.ui.theme.ReplyTheme
2635

2736
class MainActivity : ComponentActivity() {
2837

2938
override fun onCreate(savedInstanceState: Bundle?) {
39+
enableEdgeToEdge()
3040
super.onCreate(savedInstanceState)
31-
3241
setContent {
3342
ReplyTheme {
34-
Surface {
43+
val layoutDirection = LocalLayoutDirection.current
44+
Surface(
45+
modifier = Modifier
46+
.padding(
47+
start = WindowInsets.safeDrawing.asPaddingValues()
48+
.calculateStartPadding(layoutDirection),
49+
end = WindowInsets.safeDrawing.asPaddingValues()
50+
.calculateEndPadding(layoutDirection)
51+
)
52+
) {
3553
ReplyApp()
3654
}
3755
}

app/src/main/java/com/example/reply/data/local/LocalAccountsDataProvider.kt

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,15 +25,6 @@ import com.example.reply.data.Account
2525
object LocalAccountsDataProvider {
2626
val defaultAccount = Account(-1, -1, -1, -1, R.drawable.avatar_1)
2727

28-
val userAccount =
29-
Account(
30-
id = 1,
31-
firstName = R.string.account_1_first_name,
32-
lastName = R.string.account_1_last_name,
33-
email = R.string.account_1_email,
34-
avatar = R.drawable.avatar_10
35-
)
36-
3728
private val allUserContactAccounts = listOf(
3829
Account(
3930
id = 4L,

app/src/main/java/com/example/reply/ui/ReplyDetailsScreen.kt

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,18 @@ import androidx.compose.foundation.layout.Arrangement
2121
import androidx.compose.foundation.layout.Box
2222
import androidx.compose.foundation.layout.Column
2323
import androidx.compose.foundation.layout.Row
24+
import androidx.compose.foundation.layout.WindowInsets
25+
import androidx.compose.foundation.layout.asPaddingValues
2426
import androidx.compose.foundation.layout.fillMaxSize
2527
import androidx.compose.foundation.layout.fillMaxWidth
28+
import androidx.compose.foundation.layout.navigationBarsPadding
2629
import androidx.compose.foundation.layout.padding
30+
import androidx.compose.foundation.layout.safeDrawing
2731
import androidx.compose.foundation.layout.size
2832
import androidx.compose.foundation.lazy.LazyColumn
2933
import androidx.compose.foundation.shape.CircleShape
3034
import androidx.compose.material.icons.Icons
31-
import androidx.compose.material.icons.filled.ArrowBack
35+
import androidx.compose.material.icons.automirrored.filled.ArrowBack
3236
import androidx.compose.material3.Button
3337
import androidx.compose.material3.ButtonDefaults
3438
import androidx.compose.material3.Card
@@ -55,23 +59,28 @@ fun ReplyDetailsScreen(
5559
) {
5660
Box(modifier = modifier) {
5761
LazyColumn(
62+
contentPadding = WindowInsets.safeDrawing.asPaddingValues(),
5863
modifier = Modifier
5964
.fillMaxSize()
6065
.background(color = MaterialTheme.colorScheme.inverseOnSurface)
61-
.padding(top = dimensionResource(R.dimen.detail_card_list_padding_top))
6266
) {
6367
item {
6468
ReplyDetailsScreenTopBar(
6569
onBackPressed,
6670
replyUiState,
6771
Modifier
6872
.fillMaxWidth()
69-
.padding(bottom = dimensionResource(R.dimen.detail_topbar_padding_bottom))
73+
.padding(
74+
bottom = dimensionResource(R.dimen.detail_topbar_padding_bottom),
75+
top = dimensionResource(R.dimen.topbar_padding_vertical)
76+
)
7077
)
7178
ReplyEmailDetailsCard(
7279
email = replyUiState.currentSelectedEmail,
7380
mailboxType = replyUiState.currentMailbox,
74-
modifier = Modifier.padding(horizontal = dimensionResource(R.dimen.detail_card_outer_padding_horizontal))
81+
modifier = Modifier
82+
.navigationBarsPadding()
83+
.padding(horizontal = dimensionResource(R.dimen.detail_card_outer_padding_horizontal))
7584
)
7685
}
7786
}
@@ -95,7 +104,7 @@ private fun ReplyDetailsScreenTopBar(
95104
.background(MaterialTheme.colorScheme.surface, shape = CircleShape),
96105
) {
97106
Icon(
98-
imageVector = Icons.Default.ArrowBack,
107+
imageVector = Icons.AutoMirrored.Filled.ArrowBack,
99108
contentDescription = stringResource(id = R.string.navigation_back)
100109
)
101110
}

app/src/main/java/com/example/reply/ui/ReplyHomeContent.kt

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,13 @@ import androidx.compose.foundation.layout.Arrangement
2222
import androidx.compose.foundation.layout.Box
2323
import androidx.compose.foundation.layout.Column
2424
import androidx.compose.foundation.layout.Row
25+
import androidx.compose.foundation.layout.WindowInsets
26+
import androidx.compose.foundation.layout.asPaddingValues
2527
import androidx.compose.foundation.layout.fillMaxWidth
2628
import androidx.compose.foundation.layout.padding
29+
import androidx.compose.foundation.layout.safeDrawing
2730
import androidx.compose.foundation.layout.size
31+
import androidx.compose.foundation.layout.statusBars
2832
import androidx.compose.foundation.lazy.LazyColumn
2933
import androidx.compose.foundation.lazy.items
3034
import androidx.compose.foundation.shape.CircleShape
@@ -58,6 +62,7 @@ fun ReplyListOnlyContent(
5862

5963
LazyColumn(
6064
modifier = modifier,
65+
contentPadding = WindowInsets.safeDrawing.asPaddingValues(),
6166
verticalArrangement = Arrangement.spacedBy(
6267
dimensionResource(R.dimen.email_list_item_vertical_spacing)
6368
)
@@ -88,14 +93,15 @@ fun ReplyListAndDetailContent(
8893
modifier: Modifier = Modifier
8994
) {
9095
val emails = replyUiState.currentMailboxEmails
91-
Row(modifier = modifier) {
96+
Row(
97+
modifier = modifier,
98+
horizontalArrangement = Arrangement.SpaceEvenly
99+
) {
92100
LazyColumn(
101+
contentPadding = WindowInsets.statusBars.asPaddingValues(),
93102
modifier = Modifier
94103
.weight(1f)
95-
.padding(
96-
end = dimensionResource(R.dimen.list_and_detail_list_padding_end),
97-
top = dimensionResource(R.dimen.list_and_detail_list_padding_top)
98-
),
104+
.padding(horizontal = dimensionResource(R.dimen.email_list_only_horizontal_padding)),
99105
verticalArrangement = Arrangement.spacedBy(
100106
dimensionResource(R.dimen.email_list_item_vertical_spacing)
101107
)
@@ -113,8 +119,10 @@ fun ReplyListAndDetailContent(
113119
val activity = LocalContext.current as Activity
114120
ReplyDetailsScreen(
115121
replyUiState = replyUiState,
116-
onBackPressed = {},
117-
modifier = Modifier.weight(1f)
122+
modifier = Modifier
123+
.padding(top = dimensionResource(R.dimen.email_list_item_vertical_spacing))
124+
.weight(1f),
125+
onBackPressed = {}
118126
)
119127
}
120128
}

app/src/main/java/com/example/reply/ui/ReplyHomeScreen.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ import androidx.compose.foundation.layout.fillMaxWidth
2525
import androidx.compose.foundation.layout.padding
2626
import androidx.compose.foundation.layout.size
2727
import androidx.compose.material.icons.Icons
28+
import androidx.compose.material.icons.automirrored.filled.Send
2829
import androidx.compose.material.icons.filled.Drafts
2930
import androidx.compose.material.icons.filled.Inbox
3031
import androidx.compose.material.icons.filled.Report
31-
import androidx.compose.material.icons.filled.Send
3232
import androidx.compose.material3.Icon
3333
import androidx.compose.material3.MaterialTheme
3434
import androidx.compose.material3.NavigationBar
@@ -67,7 +67,7 @@ fun ReplyHomeScreen(
6767
),
6868
NavigationItemContent(
6969
mailboxType = MailboxType.Sent,
70-
icon = Icons.Default.Send,
70+
icon = Icons.AutoMirrored.Filled.Send,
7171
text = stringResource(id = R.string.tab_sent)
7272
),
7373
NavigationItemContent(
@@ -228,8 +228,7 @@ private fun NavigationDrawerHeader(
228228
ReplyProfileImage(
229229
drawableResource = LocalAccountsDataProvider.defaultAccount.avatar,
230230
description = stringResource(id = R.string.profile),
231-
modifier = Modifier
232-
.size(dimensionResource(R.dimen.profile_image_size))
231+
modifier = Modifier.size(dimensionResource(R.dimen.profile_image_size))
233232
)
234233
}
235234
}

app/src/main/java/com/example/reply/ui/theme/Theme.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,12 @@ import android.app.Activity
2020
import android.os.Build
2121
import androidx.compose.foundation.isSystemInDarkTheme
2222
import androidx.compose.material3.MaterialTheme
23-
import androidx.compose.material3.lightColorScheme
2423
import androidx.compose.material3.darkColorScheme
2524
import androidx.compose.material3.dynamicDarkColorScheme
2625
import androidx.compose.material3.dynamicLightColorScheme
26+
import androidx.compose.material3.lightColorScheme
2727
import androidx.compose.runtime.Composable
2828
import androidx.compose.runtime.SideEffect
29-
import androidx.compose.ui.graphics.toArgb
3029
import androidx.compose.ui.platform.LocalContext
3130
import androidx.compose.ui.platform.LocalView
3231
import androidx.core.view.WindowCompat
@@ -114,12 +113,12 @@ fun ReplyTheme(
114113
darkTheme -> DarkColorScheme
115114
else -> LightColorScheme
116115
}
116+
117117
val view = LocalView.current
118118
if (!view.isInEditMode) {
119119
SideEffect {
120120
val window = (view.context as Activity).window
121-
window.statusBarColor = colorScheme.primary.toArgb()
122-
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme
121+
WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme
123122
}
124123
}
125124

-345 KB
Binary file not shown.
-41.5 KB
Binary file not shown.

0 commit comments

Comments
 (0)