Merge branch 'main' into mlykotom/tz-perf-improvement

Change-Id: Id49a580012629163ec4a3663d95ab71b98910220

# Conflicts:
#	app/dependencies/prodReleaseRuntimeClasspath.txt
#	app/src/testDemo/kotlin/com/google/samples/apps/nowinandroid/ui/NiaAppScreenSizesScreenshotTests.kt
#	gradle/libs.versions.toml
pull/1187/head
Tomáš Mlynarič 4 months ago
commit f31fdb3ec2

@ -1,7 +1,7 @@
androidx.activity:activity-compose:1.8.0 androidx.activity:activity-compose:1.8.0
androidx.activity:activity-ktx:1.8.0 androidx.activity:activity-ktx:1.8.0
androidx.activity:activity:1.8.0 androidx.activity:activity:1.8.0
androidx.annotation:annotation-experimental:1.3.1 androidx.annotation:annotation-experimental:1.4.0
androidx.annotation:annotation-jvm:1.7.0 androidx.annotation:annotation-jvm:1.7.0
androidx.annotation:annotation:1.7.0 androidx.annotation:annotation:1.7.0
androidx.appcompat:appcompat-resources:1.6.1 androidx.appcompat:appcompat-resources:1.6.1
@ -9,48 +9,50 @@ androidx.arch.core:core-common:2.2.0
androidx.arch.core:core-runtime:2.2.0 androidx.arch.core:core-runtime:2.2.0
androidx.autofill:autofill:1.0.0 androidx.autofill:autofill:1.0.0
androidx.browser:browser:1.6.0 androidx.browser:browser:1.6.0
androidx.collection:collection-jvm:1.3.0 androidx.collection:collection-jvm:1.4.0
androidx.collection:collection:1.3.0 androidx.collection:collection-ktx:1.4.0
androidx.compose.animation:animation-android:1.5.4 androidx.collection:collection:1.4.0
androidx.compose.animation:animation-core-android:1.5.4 androidx.compose.animation:animation-android:1.6.1
androidx.compose.animation:animation-core:1.5.4 androidx.compose.animation:animation-core-android:1.6.1
androidx.compose.animation:animation:1.5.4 androidx.compose.animation:animation-core:1.6.1
androidx.compose.foundation:foundation-android:1.5.4 androidx.compose.animation:animation:1.6.1
androidx.compose.foundation:foundation-layout-android:1.5.4 androidx.compose.foundation:foundation-android:1.6.1
androidx.compose.foundation:foundation-layout:1.5.4 androidx.compose.foundation:foundation-layout-android:1.6.1
androidx.compose.foundation:foundation:1.5.4 androidx.compose.foundation:foundation-layout:1.6.1
androidx.compose.material3:material3:1.1.2 androidx.compose.foundation:foundation:1.6.1
androidx.compose.material:material-icons-core-android:1.5.4 androidx.compose.material3:material3-android:1.2.0
androidx.compose.material:material-icons-core:1.5.4 androidx.compose.material3:material3:1.2.0
androidx.compose.material:material-icons-extended-android:1.5.4 androidx.compose.material:material-icons-core-android:1.6.1
androidx.compose.material:material-icons-extended:1.5.4 androidx.compose.material:material-icons-core:1.6.1
androidx.compose.material:material-ripple-android:1.5.4 androidx.compose.material:material-icons-extended-android:1.6.1
androidx.compose.material:material-ripple:1.5.4 androidx.compose.material:material-icons-extended:1.6.1
androidx.compose.runtime:runtime-android:1.5.4 androidx.compose.material:material-ripple-android:1.6.1
androidx.compose.runtime:runtime-saveable-android:1.5.4 androidx.compose.material:material-ripple:1.6.1
androidx.compose.runtime:runtime-saveable:1.5.4 androidx.compose.runtime:runtime-android:1.6.1
androidx.compose.runtime:runtime:1.5.4 androidx.compose.runtime:runtime-saveable-android:1.6.1
androidx.compose.ui:ui-android:1.5.4 androidx.compose.runtime:runtime-saveable:1.6.1
androidx.compose.ui:ui-geometry-android:1.5.4 androidx.compose.runtime:runtime:1.6.1
androidx.compose.ui:ui-geometry:1.5.4 androidx.compose.ui:ui-android:1.6.1
androidx.compose.ui:ui-graphics-android:1.5.4 androidx.compose.ui:ui-geometry-android:1.6.1
androidx.compose.ui:ui-graphics:1.5.4 androidx.compose.ui:ui-geometry:1.6.1
androidx.compose.ui:ui-text-android:1.5.4 androidx.compose.ui:ui-graphics-android:1.6.1
androidx.compose.ui:ui-text:1.5.4 androidx.compose.ui:ui-graphics:1.6.1
androidx.compose.ui:ui-tooling-preview-android:1.5.4 androidx.compose.ui:ui-text-android:1.6.1
androidx.compose.ui:ui-tooling-preview:1.5.4 androidx.compose.ui:ui-text:1.6.1
androidx.compose.ui:ui-unit-android:1.5.4 androidx.compose.ui:ui-tooling-preview-android:1.6.1
androidx.compose.ui:ui-unit:1.5.4 androidx.compose.ui:ui-tooling-preview:1.6.1
androidx.compose.ui:ui-util-android:1.5.4 androidx.compose.ui:ui-unit-android:1.6.1
androidx.compose.ui:ui-util:1.5.4 androidx.compose.ui:ui-unit:1.6.1
androidx.compose.ui:ui:1.5.4 androidx.compose.ui:ui-util-android:1.6.1
androidx.compose:compose-bom:2023.10.01 androidx.compose.ui:ui-util:1.6.1
androidx.compose.ui:ui:1.6.1
androidx.compose:compose-bom:2024.02.00
androidx.concurrent:concurrent-futures:1.1.0 androidx.concurrent:concurrent-futures:1.1.0
androidx.core:core-ktx:1.12.0 androidx.core:core-ktx:1.12.0
androidx.core:core:1.12.0 androidx.core:core:1.12.0
androidx.customview:customview-poolingcontainer:1.0.0 androidx.customview:customview-poolingcontainer:1.0.0
androidx.customview:customview:1.0.0 androidx.customview:customview:1.0.0
androidx.emoji2:emoji2:1.4.0 androidx.emoji2:emoji2:1.3.0
androidx.exifinterface:exifinterface:1.3.6 androidx.exifinterface:exifinterface:1.3.6
androidx.fragment:fragment:1.5.1 androidx.fragment:fragment:1.5.1
androidx.interpolator:interpolator:1.0.0 androidx.interpolator:interpolator:1.0.0

@ -1,7 +1,7 @@
androidx.activity:activity-compose:1.8.0 androidx.activity:activity-compose:1.8.0
androidx.activity:activity-ktx:1.8.0 androidx.activity:activity-ktx:1.8.0
androidx.activity:activity:1.8.0 androidx.activity:activity:1.8.0
androidx.annotation:annotation-experimental:1.3.1 androidx.annotation:annotation-experimental:1.4.0
androidx.annotation:annotation-jvm:1.7.0 androidx.annotation:annotation-jvm:1.7.0
androidx.annotation:annotation:1.7.0 androidx.annotation:annotation:1.7.0
androidx.appcompat:appcompat-resources:1.6.1 androidx.appcompat:appcompat-resources:1.6.1
@ -10,45 +10,47 @@ androidx.arch.core:core-common:2.2.0
androidx.arch.core:core-runtime:2.2.0 androidx.arch.core:core-runtime:2.2.0
androidx.autofill:autofill:1.0.0 androidx.autofill:autofill:1.0.0
androidx.browser:browser:1.6.0 androidx.browser:browser:1.6.0
androidx.collection:collection-jvm:1.3.0 androidx.collection:collection-jvm:1.4.0
androidx.collection:collection-ktx:1.3.0 androidx.collection:collection-ktx:1.4.0
androidx.collection:collection:1.3.0 androidx.collection:collection:1.4.0
androidx.compose.animation:animation-android:1.5.4 androidx.compose.animation:animation-android:1.6.1
androidx.compose.animation:animation-core-android:1.5.4 androidx.compose.animation:animation-core-android:1.6.1
androidx.compose.animation:animation-core:1.5.4 androidx.compose.animation:animation-core:1.6.1
androidx.compose.animation:animation:1.5.4 androidx.compose.animation:animation:1.6.1
androidx.compose.foundation:foundation-android:1.5.4 androidx.compose.foundation:foundation-android:1.6.1
androidx.compose.foundation:foundation-layout-android:1.5.4 androidx.compose.foundation:foundation-layout-android:1.6.1
androidx.compose.foundation:foundation-layout:1.5.4 androidx.compose.foundation:foundation-layout:1.6.1
androidx.compose.foundation:foundation:1.5.4 androidx.compose.foundation:foundation:1.6.1
androidx.compose.material3:material3-window-size-class:1.1.2 androidx.compose.material3:material3-android:1.2.0
androidx.compose.material3:material3:1.1.2 androidx.compose.material3:material3-window-size-class-android:1.2.0
androidx.compose.material:material-icons-core-android:1.5.4 androidx.compose.material3:material3-window-size-class:1.2.0
androidx.compose.material:material-icons-core:1.5.4 androidx.compose.material3:material3:1.2.0
androidx.compose.material:material-icons-extended-android:1.5.4 androidx.compose.material:material-icons-core-android:1.6.1
androidx.compose.material:material-icons-extended:1.5.4 androidx.compose.material:material-icons-core:1.6.1
androidx.compose.material:material-ripple-android:1.5.4 androidx.compose.material:material-icons-extended-android:1.6.1
androidx.compose.material:material-ripple:1.5.4 androidx.compose.material:material-icons-extended:1.6.1
androidx.compose.runtime:runtime-android:1.5.4 androidx.compose.material:material-ripple-android:1.6.1
androidx.compose.runtime:runtime-saveable-android:1.5.4 androidx.compose.material:material-ripple:1.6.1
androidx.compose.runtime:runtime-saveable:1.5.4 androidx.compose.runtime:runtime-android:1.6.1
androidx.compose.runtime:runtime-saveable-android:1.6.1
androidx.compose.runtime:runtime-saveable:1.6.1
androidx.compose.runtime:runtime-tracing:1.0.0-beta01 androidx.compose.runtime:runtime-tracing:1.0.0-beta01
androidx.compose.runtime:runtime:1.5.4 androidx.compose.runtime:runtime:1.6.1
androidx.compose.ui:ui-android:1.5.4 androidx.compose.ui:ui-android:1.6.1
androidx.compose.ui:ui-geometry-android:1.5.4 androidx.compose.ui:ui-geometry-android:1.6.1
androidx.compose.ui:ui-geometry:1.5.4 androidx.compose.ui:ui-geometry:1.6.1
androidx.compose.ui:ui-graphics-android:1.5.4 androidx.compose.ui:ui-graphics-android:1.6.1
androidx.compose.ui:ui-graphics:1.5.4 androidx.compose.ui:ui-graphics:1.6.1
androidx.compose.ui:ui-text-android:1.5.4 androidx.compose.ui:ui-text-android:1.6.1
androidx.compose.ui:ui-text:1.5.4 androidx.compose.ui:ui-text:1.6.1
androidx.compose.ui:ui-tooling-preview-android:1.5.4 androidx.compose.ui:ui-tooling-preview-android:1.6.1
androidx.compose.ui:ui-tooling-preview:1.5.4 androidx.compose.ui:ui-tooling-preview:1.6.1
androidx.compose.ui:ui-unit-android:1.5.4 androidx.compose.ui:ui-unit-android:1.6.1
androidx.compose.ui:ui-unit:1.5.4 androidx.compose.ui:ui-unit:1.6.1
androidx.compose.ui:ui-util-android:1.5.4 androidx.compose.ui:ui-util-android:1.6.1
androidx.compose.ui:ui-util:1.5.4 androidx.compose.ui:ui-util:1.6.1
androidx.compose.ui:ui:1.5.4 androidx.compose.ui:ui:1.6.1
androidx.compose:compose-bom:2023.10.01 androidx.compose:compose-bom:2024.02.00
androidx.concurrent:concurrent-futures:1.1.0 androidx.concurrent:concurrent-futures:1.1.0
androidx.core:core-ktx:1.12.0 androidx.core:core-ktx:1.12.0
androidx.core:core-splashscreen:1.0.1 androidx.core:core-splashscreen:1.0.1
@ -62,8 +64,8 @@ androidx.datastore:datastore-preferences:1.0.0
androidx.datastore:datastore:1.0.0 androidx.datastore:datastore:1.0.0
androidx.documentfile:documentfile:1.0.0 androidx.documentfile:documentfile:1.0.0
androidx.drawerlayout:drawerlayout:1.0.0 androidx.drawerlayout:drawerlayout:1.0.0
androidx.emoji2:emoji2-views-helper:1.4.0 androidx.emoji2:emoji2-views-helper:1.3.0
androidx.emoji2:emoji2:1.4.0 androidx.emoji2:emoji2:1.3.0
androidx.exifinterface:exifinterface:1.3.6 androidx.exifinterface:exifinterface:1.3.6
androidx.fragment:fragment:1.5.1 androidx.fragment:fragment:1.5.1
androidx.hilt:hilt-common:1.1.0 androidx.hilt:hilt-common:1.1.0

@ -38,6 +38,7 @@ import com.google.samples.apps.nowinandroid.core.data.repository.UserDataReposit
import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourceRepository import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourceRepository
import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor import com.google.samples.apps.nowinandroid.core.data.util.NetworkMonitor
import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor import com.google.samples.apps.nowinandroid.core.data.util.TimeZoneMonitor
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
import com.google.samples.apps.nowinandroid.core.testing.util.DefaultRoborazziOptions import com.google.samples.apps.nowinandroid.core.testing.util.DefaultRoborazziOptions
import com.google.samples.apps.nowinandroid.uitesthiltmanifest.HiltComponentActivity import com.google.samples.apps.nowinandroid.uitesthiltmanifest.HiltComponentActivity
import dagger.hilt.android.testing.BindValue import dagger.hilt.android.testing.BindValue
@ -144,6 +145,7 @@ class NiaAppScreenSizesScreenshotTests {
) { ) {
TestHarness(size = DpSize(width, height)) { TestHarness(size = DpSize(width, height)) {
BoxWithConstraints { BoxWithConstraints {
NiaTheme {
val fakeAppState = rememberNiaAppState( val fakeAppState = rememberNiaAppState(
windowSizeClass = WindowSizeClass.calculateFromSize( windowSizeClass = WindowSizeClass.calculateFromSize(
DpSize(maxWidth, maxHeight), DpSize(maxWidth, maxHeight),
@ -157,6 +159,7 @@ class NiaAppScreenSizesScreenshotTests {
} }
} }
} }
}
composeTestRule.onRoot() composeTestRule.onRoot()
.captureRoboImage( .captureRoboImage(

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 105 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 233 KiB

After

Width:  |  Height:  |  Size: 266 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 58 KiB

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 153 KiB

After

Width:  |  Height:  |  Size: 178 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 103 KiB

@ -38,7 +38,7 @@ class ResultKtTest {
when (val errorResult = awaitItem()) { when (val errorResult = awaitItem()) {
is Result.Error -> assertEquals( is Result.Error -> assertEquals(
"Test Done", "Test Done",
errorResult.exception?.message, errorResult.exception.message,
) )
Result.Loading, Result.Loading,
is Result.Success, is Result.Success,

@ -285,16 +285,6 @@ fun NiaOutlinedButtonPreview() {
} }
} }
@ThemePreviews
@Composable
fun NiaButtonPreview2() {
NiaTheme {
NiaBackground(modifier = Modifier.size(150.dp, 50.dp)) {
NiaButton(onClick = {}, text = { Text("Test button") })
}
}
}
@ThemePreviews @ThemePreviews
@Composable @Composable
fun NiaButtonLeadingIconPreview() { fun NiaButtonLeadingIconPreview() {

@ -73,6 +73,8 @@ fun NiaFilterChip(
}, },
shape = CircleShape, shape = CircleShape,
border = FilterChipDefaults.filterChipBorder( border = FilterChipDefaults.filterChipBorder(
enabled = enabled,
selected = selected,
borderColor = MaterialTheme.colorScheme.onBackground, borderColor = MaterialTheme.colorScheme.onBackground,
selectedBorderColor = MaterialTheme.colorScheme.onBackground, selectedBorderColor = MaterialTheme.colorScheme.onBackground,
disabledBorderColor = MaterialTheme.colorScheme.onBackground.copy( disabledBorderColor = MaterialTheme.colorScheme.onBackground.copy(

@ -96,8 +96,8 @@ fun NiaLoadingWheel(
animationSpec = infiniteRepeatable( animationSpec = infiniteRepeatable(
animation = keyframes { animation = keyframes {
durationMillis = ROTATION_TIME / 2 durationMillis = ROTATION_TIME / 2
progressLineColor at ROTATION_TIME / NUM_OF_LINES / 2 with LinearEasing progressLineColor at ROTATION_TIME / NUM_OF_LINES / 2 using LinearEasing
baseLineColor at ROTATION_TIME / NUM_OF_LINES with LinearEasing baseLineColor at ROTATION_TIME / NUM_OF_LINES using LinearEasing
}, },
repeatMode = RepeatMode.Restart, repeatMode = RepeatMode.Restart,
initialStartOffset = StartOffset(ROTATION_TIME / NUM_OF_LINES / 2 * index), initialStartOffset = StartOffset(ROTATION_TIME / NUM_OF_LINES / 2 * index),

@ -167,7 +167,7 @@ fun NiaNavigationRail(
@ThemePreviews @ThemePreviews
@Composable @Composable
fun NiaNavigationPreview() { fun NiaNavigationBarPreview() {
val items = listOf("For you", "Saved", "Interests") val items = listOf("For you", "Saved", "Interests")
val icons = listOf( val icons = listOf(
NiaIcons.UpcomingBorder, NiaIcons.UpcomingBorder,
@ -205,6 +205,46 @@ fun NiaNavigationPreview() {
} }
} }
@ThemePreviews
@Composable
fun NiaNavigationRailPreview() {
val items = listOf("For you", "Saved", "Interests")
val icons = listOf(
NiaIcons.UpcomingBorder,
NiaIcons.BookmarksBorder,
NiaIcons.Grid3x3,
)
val selectedIcons = listOf(
NiaIcons.Upcoming,
NiaIcons.Bookmarks,
NiaIcons.Grid3x3,
)
NiaTheme {
NiaNavigationRail {
items.forEachIndexed { index, item ->
NiaNavigationRailItem(
icon = {
Icon(
imageVector = icons[index],
contentDescription = item,
)
},
selectedIcon = {
Icon(
imageVector = selectedIcons[index],
contentDescription = item,
)
},
label = { Text(item) },
selected = index == 0,
onClick = { },
)
}
}
}
}
/** /**
* Now in Android navigation default values. * Now in Android navigation default values.
*/ */

@ -91,7 +91,7 @@ fun NiaTabRow(
containerColor = Color.Transparent, containerColor = Color.Transparent,
contentColor = MaterialTheme.colorScheme.onSurface, contentColor = MaterialTheme.colorScheme.onSurface,
indicator = { tabPositions -> indicator = { tabPositions ->
TabRowDefaults.Indicator( TabRowDefaults.SecondaryIndicator(
modifier = Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex]), modifier = Modifier.tabIndicatorOffset(tabPositions[selectedTabIndex]),
height = 2.dp, height = 2.dp,
color = MaterialTheme.colorScheme.onSurface, color = MaterialTheme.colorScheme.onSurface,

@ -34,6 +34,7 @@ import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.stringResource
import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.tooling.preview.Preview
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
@ -77,6 +78,7 @@ fun NiaTopAppBar(
@Preview("Top App Bar") @Preview("Top App Bar")
@Composable @Composable
private fun NiaTopAppBarPreview() { private fun NiaTopAppBarPreview() {
NiaTheme {
NiaTopAppBar( NiaTopAppBar(
titleRes = android.R.string.untitled, titleRes = android.R.string.untitled,
navigationIcon = NiaIcons.Search, navigationIcon = NiaIcons.Search,
@ -85,3 +87,4 @@ private fun NiaTopAppBarPreview() {
actionIconContentDescription = "Action icon", actionIconContentDescription = "Action icon",
) )
} }
}

@ -17,6 +17,8 @@
package com.google.samples.apps.nowinandroid.core.designsystem.icon package com.google.samples.apps.nowinandroid.core.designsystem.icon
import androidx.compose.material.icons.Icons import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.rounded.ArrowBack
import androidx.compose.material.icons.automirrored.rounded.ShortText
import androidx.compose.material.icons.filled.MoreVert import androidx.compose.material.icons.filled.MoreVert
import androidx.compose.material.icons.outlined.Bookmarks import androidx.compose.material.icons.outlined.Bookmarks
import androidx.compose.material.icons.outlined.Upcoming import androidx.compose.material.icons.outlined.Upcoming
@ -41,7 +43,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
*/ */
object NiaIcons { object NiaIcons {
val Add = Icons.Rounded.Add val Add = Icons.Rounded.Add
val ArrowBack = Icons.Rounded.ArrowBack val ArrowBack = Icons.AutoMirrored.Rounded.ArrowBack
val Bookmark = Icons.Rounded.Bookmark val Bookmark = Icons.Rounded.Bookmark
val BookmarkBorder = Icons.Rounded.BookmarkBorder val BookmarkBorder = Icons.Rounded.BookmarkBorder
val Bookmarks = Icons.Rounded.Bookmarks val Bookmarks = Icons.Rounded.Bookmarks
@ -53,7 +55,7 @@ object NiaIcons {
val Person = Icons.Rounded.Person val Person = Icons.Rounded.Person
val Search = Icons.Rounded.Search val Search = Icons.Rounded.Search
val Settings = Icons.Rounded.Settings val Settings = Icons.Rounded.Settings
val ShortText = Icons.Rounded.ShortText val ShortText = Icons.AutoMirrored.Rounded.ShortText
val Upcoming = Icons.Rounded.Upcoming val Upcoming = Icons.Rounded.Upcoming
val UpcomingBorder = Icons.Outlined.Upcoming val UpcomingBorder = Icons.Outlined.Upcoming
val ViewDay = Icons.Rounded.ViewDay val ViewDay = Icons.Rounded.ViewDay

@ -19,6 +19,9 @@ package com.google.samples.apps.nowinandroid.core.designsystem.theme
import androidx.compose.material3.Typography import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.LineHeightStyle
import androidx.compose.ui.text.style.LineHeightStyle.Alignment
import androidx.compose.ui.text.style.LineHeightStyle.Trim
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
/** /**
@ -60,12 +63,20 @@ internal val NiaTypography = Typography(
fontSize = 24.sp, fontSize = 24.sp,
lineHeight = 32.sp, lineHeight = 32.sp,
letterSpacing = 0.sp, letterSpacing = 0.sp,
lineHeightStyle = LineHeightStyle(
alignment = Alignment.Bottom,
trim = Trim.None,
),
), ),
titleLarge = TextStyle( titleLarge = TextStyle(
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
fontSize = 22.sp, fontSize = 22.sp,
lineHeight = 28.sp, lineHeight = 28.sp,
letterSpacing = 0.sp, letterSpacing = 0.sp,
lineHeightStyle = LineHeightStyle(
alignment = Alignment.Bottom,
trim = Trim.LastLineBottom,
),
), ),
titleMedium = TextStyle( titleMedium = TextStyle(
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
@ -79,11 +90,16 @@ internal val NiaTypography = Typography(
lineHeight = 20.sp, lineHeight = 20.sp,
letterSpacing = 0.1.sp, letterSpacing = 0.1.sp,
), ),
// Default text style
bodyLarge = TextStyle( bodyLarge = TextStyle(
fontWeight = FontWeight.Normal, fontWeight = FontWeight.Normal,
fontSize = 16.sp, fontSize = 16.sp,
lineHeight = 24.sp, lineHeight = 24.sp,
letterSpacing = 0.5.sp, letterSpacing = 0.5.sp,
lineHeightStyle = LineHeightStyle(
alignment = Alignment.Center,
trim = Trim.None,
),
), ),
bodyMedium = TextStyle( bodyMedium = TextStyle(
fontWeight = FontWeight.Normal, fontWeight = FontWeight.Normal,
@ -97,22 +113,37 @@ internal val NiaTypography = Typography(
lineHeight = 16.sp, lineHeight = 16.sp,
letterSpacing = 0.4.sp, letterSpacing = 0.4.sp,
), ),
// Used for Button
labelLarge = TextStyle( labelLarge = TextStyle(
fontWeight = FontWeight.Medium, fontWeight = FontWeight.Medium,
fontSize = 14.sp, fontSize = 14.sp,
lineHeight = 20.sp, lineHeight = 20.sp,
letterSpacing = 0.1.sp, letterSpacing = 0.1.sp,
lineHeightStyle = LineHeightStyle(
alignment = Alignment.Center,
trim = Trim.LastLineBottom,
),
), ),
// Used for Navigation items
labelMedium = TextStyle( labelMedium = TextStyle(
fontWeight = FontWeight.Medium, fontWeight = FontWeight.Medium,
fontSize = 12.sp, fontSize = 12.sp,
lineHeight = 16.sp, lineHeight = 16.sp,
letterSpacing = 0.5.sp, letterSpacing = 0.5.sp,
lineHeightStyle = LineHeightStyle(
alignment = Alignment.Center,
trim = Trim.LastLineBottom,
), ),
),
// Used for Tag
labelSmall = TextStyle( labelSmall = TextStyle(
fontWeight = FontWeight.Medium, fontWeight = FontWeight.Medium,
fontSize = 10.sp, fontSize = 10.sp,
lineHeight = 16.sp, lineHeight = 14.sp,
letterSpacing = 0.sp, letterSpacing = 0.sp,
lineHeightStyle = LineHeightStyle(
alignment = Alignment.Center,
trim = Trim.LastLineBottom,
),
), ),
) )

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 8.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

@ -21,42 +21,36 @@ import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
import com.google.samples.apps.nowinandroid.core.model.data.SearchResult import com.google.samples.apps.nowinandroid.core.model.data.SearchResult
import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.model.data.Topic
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.update
import org.jetbrains.annotations.TestOnly
class TestSearchContentsRepository : SearchContentsRepository { class TestSearchContentsRepository : SearchContentsRepository {
private val cachedTopics: MutableList<Topic> = mutableListOf() private val cachedTopics = MutableStateFlow(emptyList<Topic>())
private val cachedNewsResources: MutableList<NewsResource> = mutableListOf() private val cachedNewsResources = MutableStateFlow(emptyList<NewsResource>())
override suspend fun populateFtsData() = Unit override suspend fun populateFtsData() = Unit
override fun searchContents(searchQuery: String): Flow<SearchResult> = flowOf( override fun searchContents(searchQuery: String): Flow<SearchResult> =
combine(cachedTopics, cachedNewsResources) { topics, news ->
SearchResult( SearchResult(
topics = cachedTopics.filter { topics = topics.filter {
searchQuery in it.name || searchQuery in it.shortDescription || searchQuery in it.longDescription searchQuery in it.name || searchQuery in it.shortDescription || searchQuery in it.longDescription
}, },
newsResources = cachedNewsResources.filter { newsResources = news.filter {
searchQuery in it.content || searchQuery in it.title searchQuery in it.content || searchQuery in it.title
}, },
),
) )
override fun getSearchContentsCount(): Flow<Int> = flow {
emit(cachedTopics.size + cachedNewsResources.size)
} }
/** override fun getSearchContentsCount(): Flow<Int> = combine(cachedTopics, cachedNewsResources) { topics, news -> topics.size + news.size }
* Test only method to add the topics to the stored list in memory
*/
fun addTopics(topics: List<Topic>) {
cachedTopics.addAll(topics)
}
/** @TestOnly
* Test only method to add the news resources to the stored list in memory fun addTopics(topics: List<Topic>) = cachedTopics.update { it + topics }
*/
fun addNewsResources(newsResources: List<NewsResource>) { @TestOnly
cachedNewsResources.addAll(newsResources) fun addNewsResources(newsResources: List<NewsResource>) =
} cachedNewsResources.update { it + newsResources }
} }

@ -119,7 +119,7 @@ fun NewsResourceCardExpanded(
Spacer(modifier = Modifier.weight(1f)) Spacer(modifier = Modifier.weight(1f))
BookmarkButton(isBookmarked, onToggleBookmark) BookmarkButton(isBookmarked, onToggleBookmark)
} }
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(14.dp))
Row(verticalAlignment = Alignment.CenterVertically) { Row(verticalAlignment = Alignment.CenterVertically) {
if (!hasBeenViewed) { if (!hasBeenViewed) {
NotificationDot( NotificationDot(
@ -130,7 +130,7 @@ fun NewsResourceCardExpanded(
} }
NewsResourceMetaData(userNewsResource.publishDate, userNewsResource.type) NewsResourceMetaData(userNewsResource.publishDate, userNewsResource.type)
} }
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(14.dp))
NewsResourceShortDescription(userNewsResource.content) NewsResourceShortDescription(userNewsResource.content)
Spacer(modifier = Modifier.height(12.dp)) Spacer(modifier = Modifier.height(12.dp))
NewsResourceTopics( NewsResourceTopics(

@ -28,7 +28,6 @@ import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
@ -508,7 +507,6 @@ fun ForYouScreenPopulatedFeed(
@PreviewParameter(UserNewsResourcePreviewParameterProvider::class) @PreviewParameter(UserNewsResourcePreviewParameterProvider::class)
userNewsResources: List<UserNewsResource>, userNewsResources: List<UserNewsResource>,
) { ) {
BoxWithConstraints {
NiaTheme { NiaTheme {
ForYouScreen( ForYouScreen(
isSyncing = false, isSyncing = false,
@ -526,7 +524,6 @@ fun ForYouScreenPopulatedFeed(
) )
} }
} }
}
@DevicePreviews @DevicePreviews
@Composable @Composable
@ -534,7 +531,6 @@ fun ForYouScreenOfflinePopulatedFeed(
@PreviewParameter(UserNewsResourcePreviewParameterProvider::class) @PreviewParameter(UserNewsResourcePreviewParameterProvider::class)
userNewsResources: List<UserNewsResource>, userNewsResources: List<UserNewsResource>,
) { ) {
BoxWithConstraints {
NiaTheme { NiaTheme {
ForYouScreen( ForYouScreen(
isSyncing = false, isSyncing = false,
@ -552,7 +548,6 @@ fun ForYouScreenOfflinePopulatedFeed(
) )
} }
} }
}
@DevicePreviews @DevicePreviews
@Composable @Composable
@ -560,7 +555,6 @@ fun ForYouScreenTopicSelection(
@PreviewParameter(UserNewsResourcePreviewParameterProvider::class) @PreviewParameter(UserNewsResourcePreviewParameterProvider::class)
userNewsResources: List<UserNewsResource>, userNewsResources: List<UserNewsResource>,
) { ) {
BoxWithConstraints {
NiaTheme { NiaTheme {
ForYouScreen( ForYouScreen(
isSyncing = false, isSyncing = false,
@ -581,12 +575,10 @@ fun ForYouScreenTopicSelection(
) )
} }
} }
}
@DevicePreviews @DevicePreviews
@Composable @Composable
fun ForYouScreenLoading() { fun ForYouScreenLoading() {
BoxWithConstraints {
NiaTheme { NiaTheme {
ForYouScreen( ForYouScreen(
isSyncing = false, isSyncing = false,
@ -602,7 +594,6 @@ fun ForYouScreenLoading() {
) )
} }
} }
}
@DevicePreviews @DevicePreviews
@Composable @Composable
@ -610,7 +601,6 @@ fun ForYouScreenPopulatedAndLoading(
@PreviewParameter(UserNewsResourcePreviewParameterProvider::class) @PreviewParameter(UserNewsResourcePreviewParameterProvider::class)
userNewsResources: List<UserNewsResource>, userNewsResources: List<UserNewsResource>,
) { ) {
BoxWithConstraints {
NiaTheme { NiaTheme {
ForYouScreen( ForYouScreen(
isSyncing = true, isSyncing = true,
@ -628,4 +618,3 @@ fun ForYouScreenPopulatedAndLoading(
) )
} }
} }
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 192 KiB

After

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 KiB

After

Width:  |  Height:  |  Size: 220 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 188 KiB

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 216 KiB

After

Width:  |  Height:  |  Size: 216 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 88 KiB

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 98 KiB

@ -26,6 +26,7 @@ import com.google.samples.apps.nowinandroid.core.testing.data.topicsTestData
import com.google.samples.apps.nowinandroid.core.testing.repository.TestRecentSearchRepository import com.google.samples.apps.nowinandroid.core.testing.repository.TestRecentSearchRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.TestSearchContentsRepository import com.google.samples.apps.nowinandroid.core.testing.repository.TestSearchContentsRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.emptyUserData
import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import com.google.samples.apps.nowinandroid.feature.search.RecentSearchQueriesUiState.Success import com.google.samples.apps.nowinandroid.feature.search.RecentSearchQueriesUiState.Success
import com.google.samples.apps.nowinandroid.feature.search.SearchResultUiState.EmptyQuery import com.google.samples.apps.nowinandroid.feature.search.SearchResultUiState.EmptyQuery
@ -71,6 +72,7 @@ class SearchViewModelTest {
recentSearchRepository = recentSearchRepository, recentSearchRepository = recentSearchRepository,
analyticsHelper = NoOpAnalyticsHelper(), analyticsHelper = NoOpAnalyticsHelper(),
) )
userDataRepository.setUserData(emptyUserData)
} }
@Test @Test
@ -100,8 +102,7 @@ class SearchViewModelTest {
searchContentsRepository.addTopics(topicsTestData) searchContentsRepository.addTopics(topicsTestData)
val result = viewModel.searchResultUiState.value val result = viewModel.searchResultUiState.value
// TODO: Figure out to get the latest emitted ui State? The result is emitted as EmptyQuery assertIs<SearchResultUiState.Success>(result)
// assertIs<Success>(result)
collectJob.cancel() collectJob.cancel()
} }

@ -37,7 +37,7 @@ import androidx.compose.foundation.selection.selectable
import androidx.compose.foundation.selection.selectableGroup import androidx.compose.foundation.selection.selectableGroup
import androidx.compose.foundation.verticalScroll import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Divider import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.RadioButton import androidx.compose.material3.RadioButton
import androidx.compose.material3.Text import androidx.compose.material3.Text
@ -115,7 +115,7 @@ fun SettingsDialog(
) )
}, },
text = { text = {
Divider() HorizontalDivider()
Column(Modifier.verticalScroll(rememberScrollState())) { Column(Modifier.verticalScroll(rememberScrollState())) {
when (settingsUiState) { when (settingsUiState) {
Loading -> { Loading -> {
@ -135,7 +135,7 @@ fun SettingsDialog(
) )
} }
} }
Divider(Modifier.padding(top = 8.dp)) HorizontalDivider(Modifier.padding(top = 8.dp))
LinksPanel() LinksPanel()
} }
TrackScreenViewEvent(screenName = "Settings") TrackScreenViewEvent(screenName = "Settings")

@ -7,7 +7,7 @@ androidTools = "31.2.0"
androidxActivity = "1.8.0" androidxActivity = "1.8.0"
androidxAppCompat = "1.6.1" androidxAppCompat = "1.6.1"
androidxBrowser = "1.6.0" androidxBrowser = "1.6.0"
androidxComposeBom = "2023.10.01" androidxComposeBom = "2024.02.00"
androidxComposeCompiler = "1.5.8" androidxComposeCompiler = "1.5.8"
androidxComposeRuntimeTracing = "1.0.0-beta01" androidxComposeRuntimeTracing = "1.0.0-beta01"
androidxCore = "1.12.0" androidxCore = "1.12.0"
@ -51,7 +51,7 @@ protobufPlugin = "0.9.4"
retrofit = "2.9.0" retrofit = "2.9.0"
retrofitKotlinxSerializationJson = "1.0.0" retrofitKotlinxSerializationJson = "1.0.0"
robolectric = "4.11.1" robolectric = "4.11.1"
roborazzi = "1.6.0" roborazzi = "1.7.0"
room = "2.6.1" room = "2.6.1"
secrets = "2.0.1" secrets = "2.0.1"
truth = "1.1.5" truth = "1.1.5"

Loading…
Cancel
Save