diff --git a/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/ClearRippleTheme.kt b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/ClearRippleTheme.kt new file mode 100644 index 000000000..bc7d10bf8 --- /dev/null +++ b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/ClearRippleTheme.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.samples.apps.nowinandroid.core.ui + +import androidx.compose.material.ripple.RippleAlpha +import androidx.compose.material.ripple.RippleTheme +import androidx.compose.runtime.Composable +import androidx.compose.ui.graphics.Color + +object ClearRippleTheme : RippleTheme { + + @Composable + override fun defaultColor(): Color = Color.Transparent + + @Composable + override fun rippleAlpha() = RippleAlpha( + draggedAlpha = 0.0f, + focusedAlpha = 0.0f, + hoveredAlpha = 0.0f, + pressedAlpha = 0.0f, + ) +} diff --git a/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NiaScreens.kt b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NiaScreens.kt deleted file mode 100644 index a3553ad65..000000000 --- a/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NiaScreens.kt +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.google.samples.apps.nowinandroid.core.ui - -import androidx.annotation.StringRes -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.material.icons.Icons -import androidx.compose.material.icons.filled.MoreVert -import androidx.compose.material.icons.filled.Search -import androidx.compose.material.ripple.RippleAlpha -import androidx.compose.material.ripple.RippleTheme -import androidx.compose.material3.Icon -import androidx.compose.material3.IconButton -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight - -@Composable -fun NiaToolbar( - modifier: Modifier = Modifier, - @StringRes titleRes: Int, - onSearchClick: () -> Unit = {}, - onMenuClick: () -> Unit = {}, -) { - Row( - horizontalArrangement = Arrangement.SpaceBetween, - verticalAlignment = Alignment.CenterVertically, - modifier = modifier.fillMaxWidth() - ) { - IconButton(onClick = { onSearchClick() }) { - Icon( - imageVector = Icons.Filled.Search, - contentDescription = null - ) - } - Text( - text = stringResource(id = titleRes), - style = MaterialTheme.typography.titleLarge, - fontWeight = FontWeight.Bold - ) - IconButton(onClick = { onMenuClick() }) { - Icon( - imageVector = Icons.Filled.MoreVert, - contentDescription = null - ) - } - } -} - -object ClearRippleTheme : RippleTheme { - - @Composable - override fun defaultColor(): Color = Color.Transparent - - @Composable - override fun rippleAlpha() = RippleAlpha( - draggedAlpha = 0.0f, - focusedAlpha = 0.0f, - hoveredAlpha = 0.0f, - pressedAlpha = 0.0f, - ) -} diff --git a/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/component/TopAppBar.kt b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/component/TopAppBar.kt new file mode 100644 index 000000000..5a0caa2d2 --- /dev/null +++ b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/component/TopAppBar.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.samples.apps.nowinandroid.core.ui.component + +import androidx.annotation.StringRes +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.material.icons.filled.Search +import androidx.compose.material3.CenterAlignedTopAppBar +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.tooling.preview.Preview +import com.google.samples.apps.nowinandroid.core.ui.R + +@Composable +fun NiaTopAppBar( + @StringRes titleRes: Int, + navigationIcon: ImageVector, + navigationIconContentDescription: String?, + actionIcon: ImageVector, + actionIconContentDescription: String?, + modifier: Modifier = Modifier, + onNavigationClick: () -> Unit = {}, + onActionClick: () -> Unit = {} +) { + CenterAlignedTopAppBar( + title = { Text(text = stringResource(id = titleRes)) }, + navigationIcon = { + IconButton(onClick = onNavigationClick) { + Icon( + imageVector = navigationIcon, + contentDescription = navigationIconContentDescription, + tint = MaterialTheme.colorScheme.onSurface + ) + } + }, + actions = { + IconButton(onClick = onActionClick) { + Icon( + imageVector = actionIcon, + contentDescription = actionIconContentDescription, + tint = MaterialTheme.colorScheme.onSurface + ) + } + }, + modifier = modifier + ) +} + +@Preview("Top App Bar") +@Composable +fun NiaTopAppBarPreview() { + NiaTopAppBar( + titleRes = R.string.top_app_bar_preview_title, + navigationIcon = Icons.Default.Search, + navigationIconContentDescription = "Navigation icon", + actionIcon = Icons.Default.MoreVert, + actionIconContentDescription = "Action icon" + ) +} diff --git a/core-ui/src/main/res/values/strings.xml b/core-ui/src/main/res/values/strings.xml index 46f144829..78412bb0a 100644 --- a/core-ui/src/main/res/values/strings.xml +++ b/core-ui/src/main/res/values/strings.xml @@ -19,4 +19,6 @@ Back Open Resource Link + + Title diff --git a/feature-following/src/main/java/com/google/samples/apps/nowinandroid/feature/following/FollowingScreen.kt b/feature-following/src/main/java/com/google/samples/apps/nowinandroid/feature/following/FollowingScreen.kt index 4ea98253b..a7df67fb3 100644 --- a/feature-following/src/main/java/com/google/samples/apps/nowinandroid/feature/following/FollowingScreen.kt +++ b/feature-following/src/main/java/com/google/samples/apps/nowinandroid/feature/following/FollowingScreen.kt @@ -18,6 +18,9 @@ package com.google.samples.apps.nowinandroid.feature.following import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.padding +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.material.icons.filled.Search import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState @@ -28,9 +31,9 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import com.google.samples.apps.nowinandroid.core.ui.LoadingWheel -import com.google.samples.apps.nowinandroid.core.ui.NiaToolbar import com.google.samples.apps.nowinandroid.core.ui.component.NiaTab import com.google.samples.apps.nowinandroid.core.ui.component.NiaTabRow +import com.google.samples.apps.nowinandroid.core.ui.component.NiaTopAppBar @Composable fun InterestsRoute( @@ -69,7 +72,17 @@ fun FollowingScreen( modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally ) { - NiaToolbar(titleRes = R.string.interests) + NiaTopAppBar( + titleRes = R.string.interests, + navigationIcon = Icons.Filled.Search, + navigationIconContentDescription = stringResource( + id = R.string.top_app_bar_navigation_button_content_desc + ), + actionIcon = Icons.Filled.MoreVert, + actionIconContentDescription = stringResource( + id = R.string.top_app_bar_navigation_button_content_desc + ) + ) when (uiState) { FollowingUiState.Loading -> LoadingWheel( diff --git a/feature-following/src/main/res/values/strings.xml b/feature-following/src/main/res/values/strings.xml index 7b0d5ef1a..4ba1d1ecd 100644 --- a/feature-following/src/main/res/values/strings.xml +++ b/feature-following/src/main/res/values/strings.xml @@ -21,4 +21,6 @@ "No available data" Follow interest button Unfollow interest button + Menu + Search diff --git a/feature-foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt b/feature-foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt index a98ddfebc..a9db3ab1f 100644 --- a/feature-foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt +++ b/feature-foryou/src/androidTest/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreenTest.kt @@ -23,9 +23,13 @@ import androidx.compose.ui.test.assertIsEnabled import androidx.compose.ui.test.assertIsNotEnabled import androidx.compose.ui.test.assertIsOff import androidx.compose.ui.test.assertIsOn +import androidx.compose.ui.test.hasScrollToNodeAction +import androidx.compose.ui.test.hasText import androidx.compose.ui.test.junit4.createAndroidComposeRule +import androidx.compose.ui.test.onFirst import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithText +import androidx.compose.ui.test.performScrollToNode import com.google.samples.apps.nowinandroid.core.model.data.Author import com.google.samples.apps.nowinandroid.core.model.data.FollowableAuthor import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic @@ -37,6 +41,12 @@ class ForYouScreenTest { @get:Rule val composeTestRule = createAndroidComposeRule() + private val doneButtonMatcher by lazy { + hasText( + composeTestRule.activity.resources.getString(R.string.done) + ) + } + @Test fun circularProgressIndicator_whenScreenIsLoading_exists() { composeTestRule.setContent { @@ -142,8 +152,14 @@ class ForYouScreenTest { .assertIsDisplayed() .assertHasClickAction() + // Scroll until the Done button is visible + composeTestRule + .onAllNodes(hasScrollToNodeAction()) + .onFirst() + .performScrollToNode(doneButtonMatcher) + composeTestRule - .onNodeWithText(composeTestRule.activity.resources.getString(R.string.done)) + .onNode(doneButtonMatcher) .assertIsDisplayed() .assertIsNotEnabled() .assertHasClickAction() @@ -241,8 +257,14 @@ class ForYouScreenTest { .assertIsOff() .assertHasClickAction() + // Scroll until the Done button is visible composeTestRule - .onNodeWithText(composeTestRule.activity.resources.getString(R.string.done)) + .onAllNodes(hasScrollToNodeAction()) + .onFirst() + .performScrollToNode(doneButtonMatcher) + + composeTestRule + .onNode(doneButtonMatcher) .assertIsDisplayed() .assertIsEnabled() .assertHasClickAction() @@ -346,8 +368,14 @@ class ForYouScreenTest { .assertIsOff() .assertHasClickAction() + // Scroll until the Done button is visible + composeTestRule + .onAllNodes(hasScrollToNodeAction()) + .onFirst() + .performScrollToNode(doneButtonMatcher) + composeTestRule - .onNodeWithText(composeTestRule.activity.resources.getString(R.string.done)) + .onNode(doneButtonMatcher) .assertIsDisplayed() .assertIsEnabled() .assertHasClickAction() diff --git a/feature-foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreen.kt b/feature-foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreen.kt index 95affbbf6..6a44c2b79 100644 --- a/feature-foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreen.kt +++ b/feature-foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouScreen.kt @@ -33,6 +33,9 @@ import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CornerSize import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Search +import androidx.compose.material.icons.outlined.AccountCircle import androidx.compose.material3.Button import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon @@ -64,6 +67,7 @@ import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.ui.LoadingWheel import com.google.samples.apps.nowinandroid.core.ui.NewsResourceCardExpanded import com.google.samples.apps.nowinandroid.core.ui.component.NiaToggleButton +import com.google.samples.apps.nowinandroid.core.ui.component.NiaTopAppBar import com.google.samples.apps.nowinandroid.core.ui.icon.NiaIcons import com.google.samples.apps.nowinandroid.core.ui.theme.NiaTypography import com.google.samples.apps.nowinandroid.feature.foryou.ForYouFeedUiState.PopulatedFeed @@ -99,6 +103,19 @@ fun ForYouScreen( LazyColumn( modifier = modifier.fillMaxSize() ) { + item { + NiaTopAppBar( + titleRes = R.string.top_app_bar_title, + navigationIcon = Icons.Filled.Search, + navigationIconContentDescription = stringResource( + id = R.string.top_app_bar_navigation_button_content_desc + ), + actionIcon = Icons.Outlined.AccountCircle, + actionIconContentDescription = stringResource( + id = R.string.top_app_bar_navigation_button_content_desc + ) + ) + } when (uiState) { is ForYouFeedUiState.Loading -> { item { diff --git a/feature-foryou/src/main/res/values/strings.xml b/feature-foryou/src/main/res/values/strings.xml index be136b32d..48c40620d 100644 --- a/feature-foryou/src/main/res/values/strings.xml +++ b/feature-foryou/src/main/res/values/strings.xml @@ -22,6 +22,9 @@ Navigate up What are you interested in? Updates from topics you follow will appear here. Follow some things to get started. + Now in Android + My account + Search You are following