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-ktx: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:1.7.0
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.autofill:autofill:1.0.0
androidx.browser:browser:1.6.0
androidx.collection:collection-jvm:1.3.0
androidx.collection:collection:1.3.0
androidx.compose.animation:animation-android:1.5.4
androidx.compose.animation:animation-core-android:1.5.4
androidx.compose.animation:animation-core:1.5.4
androidx.compose.animation:animation:1.5.4
androidx.compose.foundation:foundation-android:1.5.4
androidx.compose.foundation:foundation-layout-android:1.5.4
androidx.compose.foundation:foundation-layout:1.5.4
androidx.compose.foundation:foundation:1.5.4
androidx.compose.material3:material3:1.1.2
androidx.compose.material:material-icons-core-android:1.5.4
androidx.compose.material:material-icons-core:1.5.4
androidx.compose.material:material-icons-extended-android:1.5.4
androidx.compose.material:material-icons-extended:1.5.4
androidx.compose.material:material-ripple-android:1.5.4
androidx.compose.material:material-ripple:1.5.4
androidx.compose.runtime:runtime-android:1.5.4
androidx.compose.runtime:runtime-saveable-android:1.5.4
androidx.compose.runtime:runtime-saveable:1.5.4
androidx.compose.runtime:runtime:1.5.4
androidx.compose.ui:ui-android:1.5.4
androidx.compose.ui:ui-geometry-android:1.5.4
androidx.compose.ui:ui-geometry:1.5.4
androidx.compose.ui:ui-graphics-android:1.5.4
androidx.compose.ui:ui-graphics:1.5.4
androidx.compose.ui:ui-text-android:1.5.4
androidx.compose.ui:ui-text:1.5.4
androidx.compose.ui:ui-tooling-preview-android:1.5.4
androidx.compose.ui:ui-tooling-preview:1.5.4
androidx.compose.ui:ui-unit-android:1.5.4
androidx.compose.ui:ui-unit:1.5.4
androidx.compose.ui:ui-util-android:1.5.4
androidx.compose.ui:ui-util:1.5.4
androidx.compose.ui:ui:1.5.4
androidx.compose:compose-bom:2023.10.01
androidx.collection:collection-jvm:1.4.0
androidx.collection:collection-ktx:1.4.0
androidx.collection:collection:1.4.0
androidx.compose.animation:animation-android:1.6.1
androidx.compose.animation:animation-core-android:1.6.1
androidx.compose.animation:animation-core:1.6.1
androidx.compose.animation:animation:1.6.1
androidx.compose.foundation:foundation-android:1.6.1
androidx.compose.foundation:foundation-layout-android:1.6.1
androidx.compose.foundation:foundation-layout:1.6.1
androidx.compose.foundation:foundation:1.6.1
androidx.compose.material3:material3-android:1.2.0
androidx.compose.material3:material3:1.2.0
androidx.compose.material:material-icons-core-android:1.6.1
androidx.compose.material:material-icons-core:1.6.1
androidx.compose.material:material-icons-extended-android:1.6.1
androidx.compose.material:material-icons-extended:1.6.1
androidx.compose.material:material-ripple-android:1.6.1
androidx.compose.material:material-ripple:1.6.1
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:1.6.1
androidx.compose.ui:ui-android:1.6.1
androidx.compose.ui:ui-geometry-android:1.6.1
androidx.compose.ui:ui-geometry:1.6.1
androidx.compose.ui:ui-graphics-android:1.6.1
androidx.compose.ui:ui-graphics:1.6.1
androidx.compose.ui:ui-text-android:1.6.1
androidx.compose.ui:ui-text:1.6.1
androidx.compose.ui:ui-tooling-preview-android:1.6.1
androidx.compose.ui:ui-tooling-preview:1.6.1
androidx.compose.ui:ui-unit-android:1.6.1
androidx.compose.ui:ui-unit:1.6.1
androidx.compose.ui:ui-util-android:1.6.1
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.core:core-ktx:1.12.0
androidx.core:core:1.12.0
androidx.customview:customview-poolingcontainer: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.fragment:fragment:1.5.1
androidx.interpolator:interpolator:1.0.0

@ -1,7 +1,7 @@
androidx.activity:activity-compose:1.8.0
androidx.activity:activity-ktx: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:1.7.0
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.autofill:autofill:1.0.0
androidx.browser:browser:1.6.0
androidx.collection:collection-jvm:1.3.0
androidx.collection:collection-ktx:1.3.0
androidx.collection:collection:1.3.0
androidx.compose.animation:animation-android:1.5.4
androidx.compose.animation:animation-core-android:1.5.4
androidx.compose.animation:animation-core:1.5.4
androidx.compose.animation:animation:1.5.4
androidx.compose.foundation:foundation-android:1.5.4
androidx.compose.foundation:foundation-layout-android:1.5.4
androidx.compose.foundation:foundation-layout:1.5.4
androidx.compose.foundation:foundation:1.5.4
androidx.compose.material3:material3-window-size-class:1.1.2
androidx.compose.material3:material3:1.1.2
androidx.compose.material:material-icons-core-android:1.5.4
androidx.compose.material:material-icons-core:1.5.4
androidx.compose.material:material-icons-extended-android:1.5.4
androidx.compose.material:material-icons-extended:1.5.4
androidx.compose.material:material-ripple-android:1.5.4
androidx.compose.material:material-ripple:1.5.4
androidx.compose.runtime:runtime-android:1.5.4
androidx.compose.runtime:runtime-saveable-android:1.5.4
androidx.compose.runtime:runtime-saveable:1.5.4
androidx.collection:collection-jvm:1.4.0
androidx.collection:collection-ktx:1.4.0
androidx.collection:collection:1.4.0
androidx.compose.animation:animation-android:1.6.1
androidx.compose.animation:animation-core-android:1.6.1
androidx.compose.animation:animation-core:1.6.1
androidx.compose.animation:animation:1.6.1
androidx.compose.foundation:foundation-android:1.6.1
androidx.compose.foundation:foundation-layout-android:1.6.1
androidx.compose.foundation:foundation-layout:1.6.1
androidx.compose.foundation:foundation:1.6.1
androidx.compose.material3:material3-android:1.2.0
androidx.compose.material3:material3-window-size-class-android:1.2.0
androidx.compose.material3:material3-window-size-class:1.2.0
androidx.compose.material3:material3:1.2.0
androidx.compose.material:material-icons-core-android:1.6.1
androidx.compose.material:material-icons-core:1.6.1
androidx.compose.material:material-icons-extended-android:1.6.1
androidx.compose.material:material-icons-extended:1.6.1
androidx.compose.material:material-ripple-android:1.6.1
androidx.compose.material:material-ripple:1.6.1
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:1.5.4
androidx.compose.ui:ui-android:1.5.4
androidx.compose.ui:ui-geometry-android:1.5.4
androidx.compose.ui:ui-geometry:1.5.4
androidx.compose.ui:ui-graphics-android:1.5.4
androidx.compose.ui:ui-graphics:1.5.4
androidx.compose.ui:ui-text-android:1.5.4
androidx.compose.ui:ui-text:1.5.4
androidx.compose.ui:ui-tooling-preview-android:1.5.4
androidx.compose.ui:ui-tooling-preview:1.5.4
androidx.compose.ui:ui-unit-android:1.5.4
androidx.compose.ui:ui-unit:1.5.4
androidx.compose.ui:ui-util-android:1.5.4
androidx.compose.ui:ui-util:1.5.4
androidx.compose.ui:ui:1.5.4
androidx.compose:compose-bom:2023.10.01
androidx.compose.runtime:runtime:1.6.1
androidx.compose.ui:ui-android:1.6.1
androidx.compose.ui:ui-geometry-android:1.6.1
androidx.compose.ui:ui-geometry:1.6.1
androidx.compose.ui:ui-graphics-android:1.6.1
androidx.compose.ui:ui-graphics:1.6.1
androidx.compose.ui:ui-text-android:1.6.1
androidx.compose.ui:ui-text:1.6.1
androidx.compose.ui:ui-tooling-preview-android:1.6.1
androidx.compose.ui:ui-tooling-preview:1.6.1
androidx.compose.ui:ui-unit-android:1.6.1
androidx.compose.ui:ui-unit:1.6.1
androidx.compose.ui:ui-util-android:1.6.1
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.core:core-ktx:1.12.0
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.documentfile:documentfile:1.0.0
androidx.drawerlayout:drawerlayout:1.0.0
androidx.emoji2:emoji2-views-helper:1.4.0
androidx.emoji2:emoji2:1.4.0
androidx.emoji2:emoji2-views-helper:1.3.0
androidx.emoji2:emoji2:1.3.0
androidx.exifinterface:exifinterface:1.3.6
androidx.fragment:fragment:1.5.1
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.util.NetworkMonitor
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.uitesthiltmanifest.HiltComponentActivity
import dagger.hilt.android.testing.BindValue
@ -144,15 +145,17 @@ class NiaAppScreenSizesScreenshotTests {
) {
TestHarness(size = DpSize(width, height)) {
BoxWithConstraints {
val fakeAppState = rememberNiaAppState(
windowSizeClass = WindowSizeClass.calculateFromSize(
DpSize(maxWidth, maxHeight),
),
networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor,
)
NiaApp(fakeAppState)
NiaTheme {
val fakeAppState = rememberNiaAppState(
windowSizeClass = WindowSizeClass.calculateFromSize(
DpSize(maxWidth, maxHeight),
),
networkMonitor = networkMonitor,
userNewsResourceRepository = userNewsResourceRepository,
timeZoneMonitor = timeZoneMonitor,
)
NiaApp(fakeAppState)
}
}
}
}

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()) {
is Result.Error -> assertEquals(
"Test Done",
errorResult.exception?.message,
errorResult.exception.message,
)
Result.Loading,
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
@Composable
fun NiaButtonLeadingIconPreview() {

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

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

@ -167,7 +167,7 @@ fun NiaNavigationRail(
@ThemePreviews
@Composable
fun NiaNavigationPreview() {
fun NiaNavigationBarPreview() {
val items = listOf("For you", "Saved", "Interests")
val icons = listOf(
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.
*/

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

@ -34,6 +34,7 @@ import androidx.compose.ui.platform.testTag
import androidx.compose.ui.res.stringResource
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.theme.NiaTheme
@OptIn(ExperimentalMaterial3Api::class)
@Composable
@ -77,11 +78,13 @@ fun NiaTopAppBar(
@Preview("Top App Bar")
@Composable
private fun NiaTopAppBarPreview() {
NiaTopAppBar(
titleRes = android.R.string.untitled,
navigationIcon = NiaIcons.Search,
navigationIconContentDescription = "Navigation icon",
actionIcon = NiaIcons.MoreVert,
actionIconContentDescription = "Action icon",
)
NiaTheme {
NiaTopAppBar(
titleRes = android.R.string.untitled,
navigationIcon = NiaIcons.Search,
navigationIconContentDescription = "Navigation icon",
actionIcon = NiaIcons.MoreVert,
actionIconContentDescription = "Action icon",
)
}
}

@ -17,6 +17,8 @@
package com.google.samples.apps.nowinandroid.core.designsystem.icon
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.outlined.Bookmarks
import androidx.compose.material.icons.outlined.Upcoming
@ -41,7 +43,7 @@ import androidx.compose.ui.graphics.vector.ImageVector
*/
object NiaIcons {
val Add = Icons.Rounded.Add
val ArrowBack = Icons.Rounded.ArrowBack
val ArrowBack = Icons.AutoMirrored.Rounded.ArrowBack
val Bookmark = Icons.Rounded.Bookmark
val BookmarkBorder = Icons.Rounded.BookmarkBorder
val Bookmarks = Icons.Rounded.Bookmarks
@ -53,7 +55,7 @@ object NiaIcons {
val Person = Icons.Rounded.Person
val Search = Icons.Rounded.Search
val Settings = Icons.Rounded.Settings
val ShortText = Icons.Rounded.ShortText
val ShortText = Icons.AutoMirrored.Rounded.ShortText
val Upcoming = Icons.Rounded.Upcoming
val UpcomingBorder = Icons.Outlined.Upcoming
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.ui.text.TextStyle
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
/**
@ -60,12 +63,20 @@ internal val NiaTypography = Typography(
fontSize = 24.sp,
lineHeight = 32.sp,
letterSpacing = 0.sp,
lineHeightStyle = LineHeightStyle(
alignment = Alignment.Bottom,
trim = Trim.None,
),
),
titleLarge = TextStyle(
fontWeight = FontWeight.Bold,
fontSize = 22.sp,
lineHeight = 28.sp,
letterSpacing = 0.sp,
lineHeightStyle = LineHeightStyle(
alignment = Alignment.Bottom,
trim = Trim.LastLineBottom,
),
),
titleMedium = TextStyle(
fontWeight = FontWeight.Bold,
@ -79,11 +90,16 @@ internal val NiaTypography = Typography(
lineHeight = 20.sp,
letterSpacing = 0.1.sp,
),
// Default text style
bodyLarge = TextStyle(
fontWeight = FontWeight.Normal,
fontSize = 16.sp,
lineHeight = 24.sp,
letterSpacing = 0.5.sp,
lineHeightStyle = LineHeightStyle(
alignment = Alignment.Center,
trim = Trim.None,
),
),
bodyMedium = TextStyle(
fontWeight = FontWeight.Normal,
@ -97,22 +113,37 @@ internal val NiaTypography = Typography(
lineHeight = 16.sp,
letterSpacing = 0.4.sp,
),
// Used for Button
labelLarge = TextStyle(
fontWeight = FontWeight.Medium,
fontSize = 14.sp,
lineHeight = 20.sp,
letterSpacing = 0.1.sp,
lineHeightStyle = LineHeightStyle(
alignment = Alignment.Center,
trim = Trim.LastLineBottom,
),
),
// Used for Navigation items
labelMedium = TextStyle(
fontWeight = FontWeight.Medium,
fontSize = 12.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp,
lineHeightStyle = LineHeightStyle(
alignment = Alignment.Center,
trim = Trim.LastLineBottom,
),
),
// Used for Tag
labelSmall = TextStyle(
fontWeight = FontWeight.Medium,
fontSize = 10.sp,
lineHeight = 16.sp,
lineHeight = 14.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.Topic
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.update
import org.jetbrains.annotations.TestOnly
class TestSearchContentsRepository : SearchContentsRepository {
private val cachedTopics: MutableList<Topic> = mutableListOf()
private val cachedNewsResources: MutableList<NewsResource> = mutableListOf()
private val cachedTopics = MutableStateFlow(emptyList<Topic>())
private val cachedNewsResources = MutableStateFlow(emptyList<NewsResource>())
override suspend fun populateFtsData() = Unit
override fun searchContents(searchQuery: String): Flow<SearchResult> = flowOf(
SearchResult(
topics = cachedTopics.filter {
searchQuery in it.name || searchQuery in it.shortDescription || searchQuery in it.longDescription
},
newsResources = cachedNewsResources.filter {
searchQuery in it.content || searchQuery in it.title
},
),
)
override fun getSearchContentsCount(): Flow<Int> = flow {
emit(cachedTopics.size + cachedNewsResources.size)
}
/**
* Test only method to add the topics to the stored list in memory
*/
fun addTopics(topics: List<Topic>) {
cachedTopics.addAll(topics)
}
/**
* Test only method to add the news resources to the stored list in memory
*/
fun addNewsResources(newsResources: List<NewsResource>) {
cachedNewsResources.addAll(newsResources)
}
override fun searchContents(searchQuery: String): Flow<SearchResult> =
combine(cachedTopics, cachedNewsResources) { topics, news ->
SearchResult(
topics = topics.filter {
searchQuery in it.name || searchQuery in it.shortDescription || searchQuery in it.longDescription
},
newsResources = news.filter {
searchQuery in it.content || searchQuery in it.title
},
)
}
override fun getSearchContentsCount(): Flow<Int> = combine(cachedTopics, cachedNewsResources) { topics, news -> topics.size + news.size }
@TestOnly
fun addTopics(topics: List<Topic>) = cachedTopics.update { it + topics }
@TestOnly
fun addNewsResources(newsResources: List<NewsResource>) =
cachedNewsResources.update { it + newsResources }
}

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

@ -28,7 +28,6 @@ import androidx.compose.animation.slideOutVertically
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
@ -508,23 +507,21 @@ fun ForYouScreenPopulatedFeed(
@PreviewParameter(UserNewsResourcePreviewParameterProvider::class)
userNewsResources: List<UserNewsResource>,
) {
BoxWithConstraints {
NiaTheme {
ForYouScreen(
isSyncing = false,
onboardingUiState = OnboardingUiState.NotShown,
feedState = NewsFeedUiState.Success(
feed = userNewsResources,
),
deepLinkedUserNewsResource = null,
onTopicCheckedChanged = { _, _ -> },
saveFollowedTopics = {},
onNewsResourcesCheckedChanged = { _, _ -> },
onNewsResourceViewed = {},
onTopicClick = {},
onDeepLinkOpened = {},
)
}
NiaTheme {
ForYouScreen(
isSyncing = false,
onboardingUiState = OnboardingUiState.NotShown,
feedState = NewsFeedUiState.Success(
feed = userNewsResources,
),
deepLinkedUserNewsResource = null,
onTopicCheckedChanged = { _, _ -> },
saveFollowedTopics = {},
onNewsResourcesCheckedChanged = { _, _ -> },
onNewsResourceViewed = {},
onTopicClick = {},
onDeepLinkOpened = {},
)
}
}
@ -534,23 +531,21 @@ fun ForYouScreenOfflinePopulatedFeed(
@PreviewParameter(UserNewsResourcePreviewParameterProvider::class)
userNewsResources: List<UserNewsResource>,
) {
BoxWithConstraints {
NiaTheme {
ForYouScreen(
isSyncing = false,
onboardingUiState = OnboardingUiState.NotShown,
feedState = NewsFeedUiState.Success(
feed = userNewsResources,
),
deepLinkedUserNewsResource = null,
onTopicCheckedChanged = { _, _ -> },
saveFollowedTopics = {},
onNewsResourcesCheckedChanged = { _, _ -> },
onNewsResourceViewed = {},
onTopicClick = {},
onDeepLinkOpened = {},
)
}
NiaTheme {
ForYouScreen(
isSyncing = false,
onboardingUiState = OnboardingUiState.NotShown,
feedState = NewsFeedUiState.Success(
feed = userNewsResources,
),
deepLinkedUserNewsResource = null,
onTopicCheckedChanged = { _, _ -> },
saveFollowedTopics = {},
onNewsResourcesCheckedChanged = { _, _ -> },
onNewsResourceViewed = {},
onTopicClick = {},
onDeepLinkOpened = {},
)
}
}
@ -560,47 +555,43 @@ fun ForYouScreenTopicSelection(
@PreviewParameter(UserNewsResourcePreviewParameterProvider::class)
userNewsResources: List<UserNewsResource>,
) {
BoxWithConstraints {
NiaTheme {
ForYouScreen(
isSyncing = false,
onboardingUiState = OnboardingUiState.Shown(
topics = userNewsResources.flatMap { news -> news.followableTopics }
.distinctBy { it.topic.id },
),
feedState = NewsFeedUiState.Success(
feed = userNewsResources,
),
deepLinkedUserNewsResource = null,
onTopicCheckedChanged = { _, _ -> },
saveFollowedTopics = {},
onNewsResourcesCheckedChanged = { _, _ -> },
onNewsResourceViewed = {},
onTopicClick = {},
onDeepLinkOpened = {},
)
}
NiaTheme {
ForYouScreen(
isSyncing = false,
onboardingUiState = OnboardingUiState.Shown(
topics = userNewsResources.flatMap { news -> news.followableTopics }
.distinctBy { it.topic.id },
),
feedState = NewsFeedUiState.Success(
feed = userNewsResources,
),
deepLinkedUserNewsResource = null,
onTopicCheckedChanged = { _, _ -> },
saveFollowedTopics = {},
onNewsResourcesCheckedChanged = { _, _ -> },
onNewsResourceViewed = {},
onTopicClick = {},
onDeepLinkOpened = {},
)
}
}
@DevicePreviews
@Composable
fun ForYouScreenLoading() {
BoxWithConstraints {
NiaTheme {
ForYouScreen(
isSyncing = false,
onboardingUiState = OnboardingUiState.Loading,
feedState = NewsFeedUiState.Loading,
deepLinkedUserNewsResource = null,
onTopicCheckedChanged = { _, _ -> },
saveFollowedTopics = {},
onNewsResourcesCheckedChanged = { _, _ -> },
onNewsResourceViewed = {},
onTopicClick = {},
onDeepLinkOpened = {},
)
}
NiaTheme {
ForYouScreen(
isSyncing = false,
onboardingUiState = OnboardingUiState.Loading,
feedState = NewsFeedUiState.Loading,
deepLinkedUserNewsResource = null,
onTopicCheckedChanged = { _, _ -> },
saveFollowedTopics = {},
onNewsResourcesCheckedChanged = { _, _ -> },
onNewsResourceViewed = {},
onTopicClick = {},
onDeepLinkOpened = {},
)
}
}
@ -610,22 +601,20 @@ fun ForYouScreenPopulatedAndLoading(
@PreviewParameter(UserNewsResourcePreviewParameterProvider::class)
userNewsResources: List<UserNewsResource>,
) {
BoxWithConstraints {
NiaTheme {
ForYouScreen(
isSyncing = true,
onboardingUiState = OnboardingUiState.Loading,
feedState = NewsFeedUiState.Success(
feed = userNewsResources,
),
deepLinkedUserNewsResource = null,
onTopicCheckedChanged = { _, _ -> },
saveFollowedTopics = {},
onNewsResourcesCheckedChanged = { _, _ -> },
onNewsResourceViewed = {},
onTopicClick = {},
onDeepLinkOpened = {},
)
}
NiaTheme {
ForYouScreen(
isSyncing = true,
onboardingUiState = OnboardingUiState.Loading,
feedState = NewsFeedUiState.Success(
feed = userNewsResources,
),
deepLinkedUserNewsResource = null,
onTopicCheckedChanged = { _, _ -> },
saveFollowedTopics = {},
onNewsResourcesCheckedChanged = { _, _ -> },
onNewsResourceViewed = {},
onTopicClick = {},
onDeepLinkOpened = {},
)
}
}

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

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

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

Loading…
Cancel
Save