Split feature modules into api and impl modules

Source code is still left in api module. impl module is empty at this point.
pull/1902/head
Clara Fok 3 months ago
parent 8092c60c0f
commit 7cc2b1ae42

@ -67,12 +67,12 @@ android {
} }
dependencies { dependencies {
implementation(projects.feature.interests) implementation(projects.feature.interests.api)
implementation(projects.feature.foryou) implementation(projects.feature.foryou.api)
implementation(projects.feature.bookmarks) implementation(projects.feature.bookmarks.api)
implementation(projects.feature.topic) implementation(projects.feature.topic.api)
implementation(projects.feature.search) implementation(projects.feature.search.api)
implementation(projects.feature.settings) implementation(projects.feature.settings.api)
implementation(projects.core.common) implementation(projects.core.common)
implementation(projects.core.ui) implementation(projects.core.ui)

@ -47,10 +47,10 @@ import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import javax.inject.Inject import javax.inject.Inject
import com.google.samples.apps.nowinandroid.feature.bookmarks.R as BookmarksR import com.google.samples.apps.nowinandroid.feature.bookmarks.api.R as BookmarksR
import com.google.samples.apps.nowinandroid.feature.foryou.R as FeatureForyouR import com.google.samples.apps.nowinandroid.feature.foryou.api.R as FeatureForyouR
import com.google.samples.apps.nowinandroid.feature.search.R as FeatureSearchR import com.google.samples.apps.nowinandroid.feature.search.api.R as FeatureSearchR
import com.google.samples.apps.nowinandroid.feature.settings.R as SettingsR import com.google.samples.apps.nowinandroid.feature.settings.api.R as SettingsR
/** /**
* Tests all the navigation flows that are handled by the navigation library. * Tests all the navigation flows that are handled by the navigation library.
@ -83,8 +83,8 @@ class NavigationTest {
lateinit var newsRepository: NewsRepository lateinit var newsRepository: NewsRepository
// The strings used for matching in these tests // The strings used for matching in these tests
private val navigateUp by composeTestRule.stringResource(FeatureForyouR.string.feature_foryou_navigate_up) private val navigateUp by composeTestRule.stringResource(FeatureForyouR.string.feature_foryou_api_navigate_up)
private val forYou by composeTestRule.stringResource(FeatureForyouR.string.feature_foryou_title) private val forYou by composeTestRule.stringResource(FeatureForyouR.string.feature_foryou_api_title)
private val interests by composeTestRule.stringResource(FeatureSearchR.string.feature_search_interests) private val interests by composeTestRule.stringResource(FeatureSearchR.string.feature_search_interests)
private val sampleTopic = "Headlines" private val sampleTopic = "Headlines"
private val appName by composeTestRule.stringResource(R.string.app_name) private val appName by composeTestRule.stringResource(R.string.app_name)

@ -19,13 +19,13 @@ package com.google.samples.apps.nowinandroid.navigation
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.navigation.compose.NavHost import androidx.navigation.compose.NavHost
import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.bookmarksScreen import com.google.samples.apps.nowinandroid.feature.bookmarks.api.navigation.bookmarksScreen
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.ForYouBaseRoute import com.google.samples.apps.nowinandroid.feature.foryou.api.navigation.ForYouBaseRoute
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.forYouSection import com.google.samples.apps.nowinandroid.feature.foryou.api.navigation.forYouSection
import com.google.samples.apps.nowinandroid.feature.interests.navigation.navigateToInterests import com.google.samples.apps.nowinandroid.feature.interests.api.navigation.navigateToInterests
import com.google.samples.apps.nowinandroid.feature.search.navigation.searchScreen import com.google.samples.apps.nowinandroid.feature.search.api.navigation.searchScreen
import com.google.samples.apps.nowinandroid.feature.topic.navigation.navigateToTopic import com.google.samples.apps.nowinandroid.feature.topic.api.navigation.navigateToTopic
import com.google.samples.apps.nowinandroid.feature.topic.navigation.topicScreen import com.google.samples.apps.nowinandroid.feature.topic.api.navigation.topicScreen
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination.INTERESTS import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination.INTERESTS
import com.google.samples.apps.nowinandroid.ui.NiaAppState import com.google.samples.apps.nowinandroid.ui.NiaAppState
import com.google.samples.apps.nowinandroid.ui.interests2pane.interestsListDetailScreen import com.google.samples.apps.nowinandroid.ui.interests2pane.interestsListDetailScreen

@ -20,14 +20,14 @@ import androidx.annotation.StringRes
import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.graphics.vector.ImageVector
import com.google.samples.apps.nowinandroid.R import com.google.samples.apps.nowinandroid.R
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.feature.bookmarks.navigation.BookmarksRoute import com.google.samples.apps.nowinandroid.feature.bookmarks.api.navigation.BookmarksRoute
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.ForYouBaseRoute import com.google.samples.apps.nowinandroid.feature.foryou.api.navigation.ForYouBaseRoute
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.ForYouRoute import com.google.samples.apps.nowinandroid.feature.foryou.api.navigation.ForYouRoute
import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsRoute import com.google.samples.apps.nowinandroid.feature.interests.api.navigation.InterestsRoute
import kotlin.reflect.KClass import kotlin.reflect.KClass
import com.google.samples.apps.nowinandroid.feature.bookmarks.R as bookmarksR import com.google.samples.apps.nowinandroid.feature.bookmarks.api.R as bookmarksR
import com.google.samples.apps.nowinandroid.feature.foryou.R as forYouR import com.google.samples.apps.nowinandroid.feature.foryou.api.R as forYouR
import com.google.samples.apps.nowinandroid.feature.search.R as searchR import com.google.samples.apps.nowinandroid.feature.search.api.R as searchR
/** /**
* Type for the top level destinations in the application. Contains metadata about the destination * Type for the top level destinations in the application. Contains metadata about the destination
@ -54,7 +54,7 @@ enum class TopLevelDestination(
FOR_YOU( FOR_YOU(
selectedIcon = NiaIcons.Upcoming, selectedIcon = NiaIcons.Upcoming,
unselectedIcon = NiaIcons.UpcomingBorder, unselectedIcon = NiaIcons.UpcomingBorder,
iconTextId = forYouR.string.feature_foryou_title, iconTextId = forYouR.string.feature_foryou_api_title,
titleTextId = R.string.app_name, titleTextId = R.string.app_name,
route = ForYouRoute::class, route = ForYouRoute::class,
baseRoute = ForYouBaseRoute::class, baseRoute = ForYouBaseRoute::class,
@ -62,15 +62,15 @@ enum class TopLevelDestination(
BOOKMARKS( BOOKMARKS(
selectedIcon = NiaIcons.Bookmarks, selectedIcon = NiaIcons.Bookmarks,
unselectedIcon = NiaIcons.BookmarksBorder, unselectedIcon = NiaIcons.BookmarksBorder,
iconTextId = bookmarksR.string.feature_bookmarks_title, iconTextId = bookmarksR.string.feature_bookmarks_api_title,
titleTextId = bookmarksR.string.feature_bookmarks_title, titleTextId = bookmarksR.string.feature_bookmarks_api_title,
route = BookmarksRoute::class, route = BookmarksRoute::class,
), ),
INTERESTS( INTERESTS(
selectedIcon = NiaIcons.Grid3x3, selectedIcon = NiaIcons.Grid3x3,
unselectedIcon = NiaIcons.Grid3x3, unselectedIcon = NiaIcons.Grid3x3,
iconTextId = searchR.string.feature_search_interests, iconTextId = searchR.string.feature_search_api_interests,
titleTextId = searchR.string.feature_search_interests, titleTextId = searchR.string.feature_search_api_interests,
route = InterestsRoute::class, route = InterestsRoute::class,
), ),
} }

@ -71,11 +71,11 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaTopAp
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.GradientColors import com.google.samples.apps.nowinandroid.core.designsystem.theme.GradientColors
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalGradientColors import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalGradientColors
import com.google.samples.apps.nowinandroid.feature.settings.SettingsDialog import com.google.samples.apps.nowinandroid.feature.settings.api.SettingsDialog
import com.google.samples.apps.nowinandroid.navigation.NiaNavHost import com.google.samples.apps.nowinandroid.navigation.NiaNavHost
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
import kotlin.reflect.KClass import kotlin.reflect.KClass
import com.google.samples.apps.nowinandroid.feature.settings.R as settingsR import com.google.samples.apps.nowinandroid.feature.settings.api.R as settingsR
@Composable @Composable
fun NiaApp( fun NiaApp(

@ -34,10 +34,10 @@ import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourc
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.ui.TrackDisposableJank import com.google.samples.apps.nowinandroid.core.ui.TrackDisposableJank
import com.google.samples.apps.nowinandroid.feature.bookmarks.navigation.navigateToBookmarks import com.google.samples.apps.nowinandroid.feature.bookmarks.api.navigation.navigateToBookmarks
import com.google.samples.apps.nowinandroid.feature.foryou.navigation.navigateToForYou import com.google.samples.apps.nowinandroid.feature.foryou.api.navigation.navigateToForYou
import com.google.samples.apps.nowinandroid.feature.interests.navigation.navigateToInterests import com.google.samples.apps.nowinandroid.feature.interests.api.navigation.navigateToInterests
import com.google.samples.apps.nowinandroid.feature.search.navigation.navigateToSearch import com.google.samples.apps.nowinandroid.feature.search.api.navigation.navigateToSearch
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination.BOOKMARKS import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination.BOOKMARKS
import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination.FOR_YOU import com.google.samples.apps.nowinandroid.navigation.TopLevelDestination.FOR_YOU

@ -19,7 +19,7 @@ package com.google.samples.apps.nowinandroid.ui.interests2pane
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.navigation.toRoute import androidx.navigation.toRoute
import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsRoute import com.google.samples.apps.nowinandroid.feature.interests.api.navigation.InterestsRoute
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow
import javax.inject.Inject import javax.inject.Inject

@ -52,12 +52,12 @@ import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import androidx.navigation.NavGraphBuilder import androidx.navigation.NavGraphBuilder
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import com.google.samples.apps.nowinandroid.feature.interests.InterestsRoute import com.google.samples.apps.nowinandroid.feature.interests.api.InterestsRoute
import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsRoute import com.google.samples.apps.nowinandroid.feature.interests.api.navigation.InterestsRoute
import com.google.samples.apps.nowinandroid.feature.topic.TopicDetailPlaceholder import com.google.samples.apps.nowinandroid.feature.topic.api.TopicDetailPlaceholder
import com.google.samples.apps.nowinandroid.feature.topic.TopicScreen import com.google.samples.apps.nowinandroid.feature.topic.api.TopicScreen
import com.google.samples.apps.nowinandroid.feature.topic.TopicViewModel import com.google.samples.apps.nowinandroid.feature.topic.api.TopicViewModel
import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicRoute import com.google.samples.apps.nowinandroid.feature.topic.api.navigation.TopicRoute
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlin.math.max import kotlin.math.max

@ -45,7 +45,7 @@ import org.robolectric.annotation.Config
import javax.inject.Inject import javax.inject.Inject
import kotlin.properties.ReadOnlyProperty import kotlin.properties.ReadOnlyProperty
import kotlin.test.assertTrue import kotlin.test.assertTrue
import com.google.samples.apps.nowinandroid.feature.topic.R as FeatureTopicR import com.google.samples.apps.nowinandroid.feature.topic.api.R as FeatureTopicR
private const val EXPANDED_WIDTH = "w1200dp-h840dp" private const val EXPANDED_WIDTH = "w1200dp-h840dp"
private const val COMPACT_WIDTH = "w412dp-h915dp" private const val COMPACT_WIDTH = "w412dp-h915dp"

@ -1,3 +0,0 @@
# :feature:bookmarks module
## Dependency graph
![Dependency graph](../../docs/images/graphs/dep_graph_feature_bookmarks.svg)

@ -21,7 +21,7 @@ plugins {
} }
android { android {
namespace = "com.google.samples.apps.nowinandroid.feature.bookmarks" namespace = "com.google.samples.apps.nowinandroid.feature.bookmarks.api"
} }
dependencies { dependencies {

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.bookmarks package com.google.samples.apps.nowinandroid.feature.bookmarks.api
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.CompositionLocalProvider
@ -35,7 +35,6 @@ import androidx.lifecycle.Lifecycle
import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.lifecycle.testing.TestLifecycleOwner import androidx.lifecycle.testing.TestLifecycleOwner
import com.google.samples.apps.nowinandroid.core.testing.data.userNewsResourcesTestData import com.google.samples.apps.nowinandroid.core.testing.data.userNewsResourcesTestData
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState
import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.bookmarks package com.google.samples.apps.nowinandroid.feature.bookmarks.api
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
@ -112,8 +112,8 @@ internal fun BookmarksScreen(
undoBookmarkRemoval: () -> Unit = {}, undoBookmarkRemoval: () -> Unit = {},
clearUndoState: () -> Unit = {}, clearUndoState: () -> Unit = {},
) { ) {
val bookmarkRemovedMessage = stringResource(id = R.string.feature_bookmarks_removed) val bookmarkRemovedMessage = stringResource(id = R.string.feature_bookmarks_api_removed)
val undoText = stringResource(id = R.string.feature_bookmarks_undo) val undoText = stringResource(id = R.string.feature_bookmarks_api_undo)
LaunchedEffect(shouldDisplayUndoBookmark) { LaunchedEffect(shouldDisplayUndoBookmark) {
if (shouldDisplayUndoBookmark) { if (shouldDisplayUndoBookmark) {
@ -155,7 +155,7 @@ private fun LoadingState(modifier: Modifier = Modifier) {
.fillMaxWidth() .fillMaxWidth()
.wrapContentSize() .wrapContentSize()
.testTag("forYou:loading"), .testTag("forYou:loading"),
contentDesc = stringResource(id = R.string.feature_bookmarks_loading), contentDesc = stringResource(id = R.string.feature_bookmarks_api_loading),
) )
} }
@ -228,7 +228,7 @@ private fun EmptyState(modifier: Modifier = Modifier) {
val iconTint = LocalTintTheme.current.iconTint val iconTint = LocalTintTheme.current.iconTint
Image( Image(
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
painter = painterResource(id = R.drawable.feature_bookmarks_img_empty_bookmarks), painter = painterResource(id = R.drawable.feature_bookmarks_api_mg_empty_bookmarks),
colorFilter = if (iconTint != Color.Unspecified) ColorFilter.tint(iconTint) else null, colorFilter = if (iconTint != Color.Unspecified) ColorFilter.tint(iconTint) else null,
contentDescription = null, contentDescription = null,
) )
@ -236,7 +236,7 @@ private fun EmptyState(modifier: Modifier = Modifier) {
Spacer(modifier = Modifier.height(48.dp)) Spacer(modifier = Modifier.height(48.dp))
Text( Text(
text = stringResource(id = R.string.feature_bookmarks_empty_error), text = stringResource(id = R.string.feature_bookmarks_api_empty_error),
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
@ -246,7 +246,7 @@ private fun EmptyState(modifier: Modifier = Modifier) {
Spacer(modifier = Modifier.height(8.dp)) Spacer(modifier = Modifier.height(8.dp))
Text( Text(
text = stringResource(id = R.string.feature_bookmarks_empty_description), text = stringResource(id = R.string.feature_bookmarks_api_empty_description),
modifier = Modifier.fillMaxWidth(), modifier = Modifier.fillMaxWidth(),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.bookmarks package com.google.samples.apps.nowinandroid.feature.bookmarks.api
import androidx.compose.runtime.getValue import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.mutableStateOf

@ -14,13 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.bookmarks.navigation package com.google.samples.apps.nowinandroid.feature.bookmarks.api.navigation
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions import androidx.navigation.NavOptions
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import com.google.samples.apps.nowinandroid.feature.bookmarks.BookmarksRoute import com.google.samples.apps.nowinandroid.feature.bookmarks.api.BookmarksRoute
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable object BookmarksRoute @Serializable object BookmarksRoute

@ -15,10 +15,10 @@
limitations under the License. limitations under the License.
--> -->
<resources> <resources>
<string name="feature_bookmarks_title">Saved</string> <string name="feature_bookmarks_api_title">Saved</string>
<string name="feature_bookmarks_loading">Loading saved…</string> <string name="feature_bookmarks_api_loading">Loading saved…</string>
<string name="feature_bookmarks_empty_error">No saved updates</string> <string name="feature_bookmarks_api_empty_error">No saved updates</string>
<string name="feature_bookmarks_empty_description">Updates you save will be stored here\nto read later</string> <string name="feature_bookmarks_api_empty_description">Updates you save will be stored here\nto read later</string>
<string name="feature_bookmarks_removed">Bookmark removed</string> <string name="feature_bookmarks_api_removed">Bookmark removed</string>
<string name="feature_bookmarks_undo">UNDO</string> <string name="feature_bookmarks_api_undo">UNDO</string>
</resources> </resources>

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.bookmarks package com.google.samples.apps.nowinandroid.feature.bookmarks.api
import com.google.samples.apps.nowinandroid.core.data.repository.CompositeUserNewsResourceRepository import com.google.samples.apps.nowinandroid.core.data.repository.CompositeUserNewsResourceRepository
import com.google.samples.apps.nowinandroid.core.testing.data.newsResourcesTestData import com.google.samples.apps.nowinandroid.core.testing.data.newsResourcesTestData
@ -23,6 +23,7 @@ import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserData
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.core.ui.NewsFeedUiState.Loading import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Loading
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Success import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Success
import com.google.samples.apps.nowinandroid.feature.bookmarks.api.BookmarksViewModel
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.UnconfinedTestDispatcher

@ -0,0 +1,26 @@
/*
* 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.
*/
plugins {
alias(libs.plugins.nowinandroid.android.feature)
alias(libs.plugins.nowinandroid.android.library.compose)
}
android {
namespace = "com.google.samples.apps.nowinandroid.feature.bookmarks.impl"
}
dependencies { }

@ -22,7 +22,7 @@ plugins {
} }
android { android {
namespace = "com.google.samples.apps.nowinandroid.feature.foryou" namespace = "com.google.samples.apps.nowinandroid.feature.foryou.api"
testOptions.unitTests.isIncludeAndroidResources = true testOptions.unitTests.isIncludeAndroidResources = true
} }

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.foryou package com.google.samples.apps.nowinandroid.feature.foryou.api
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box
@ -45,7 +45,7 @@ class ForYouScreenTest {
private val doneButtonMatcher by lazy { private val doneButtonMatcher by lazy {
hasText( hasText(
composeTestRule.activity.resources.getString(R.string.feature_foryou_done), composeTestRule.activity.resources.getString(R.string.feature_foryou_api_done),
) )
} }
@ -70,7 +70,7 @@ class ForYouScreenTest {
composeTestRule composeTestRule
.onNodeWithContentDescription( .onNodeWithContentDescription(
composeTestRule.activity.resources.getString(R.string.feature_foryou_loading), composeTestRule.activity.resources.getString(R.string.feature_foryou_api_loading),
) )
.assertExists() .assertExists()
} }
@ -96,7 +96,7 @@ class ForYouScreenTest {
composeTestRule composeTestRule
.onNodeWithContentDescription( .onNodeWithContentDescription(
composeTestRule.activity.resources.getString(R.string.feature_foryou_loading), composeTestRule.activity.resources.getString(R.string.feature_foryou_api_loading),
) )
.assertExists() .assertExists()
} }
@ -215,7 +215,7 @@ class ForYouScreenTest {
composeTestRule composeTestRule
.onNodeWithContentDescription( .onNodeWithContentDescription(
composeTestRule.activity.resources.getString(R.string.feature_foryou_loading), composeTestRule.activity.resources.getString(R.string.feature_foryou_api_loading),
) )
.assertExists() .assertExists()
} }
@ -241,7 +241,7 @@ class ForYouScreenTest {
composeTestRule composeTestRule
.onNodeWithContentDescription( .onNodeWithContentDescription(
composeTestRule.activity.resources.getString(R.string.feature_foryou_loading), composeTestRule.activity.resources.getString(R.string.feature_foryou_api_loading),
) )
.assertExists() .assertExists()
} }

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.foryou package com.google.samples.apps.nowinandroid.feature.foryou.api
import android.net.Uri import android.net.Uri
import android.os.Build.VERSION import android.os.Build.VERSION
@ -215,7 +215,7 @@ internal fun ForYouScreen(
targetOffsetY = { fullHeight -> -fullHeight }, targetOffsetY = { fullHeight -> -fullHeight },
) + fadeOut(), ) + fadeOut(),
) { ) {
val loadingContentDescription = stringResource(id = R.string.feature_foryou_loading) val loadingContentDescription = stringResource(id = R.string.feature_foryou_api_loading)
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -270,7 +270,7 @@ private fun LazyStaggeredGridScope.onboarding(
item(span = StaggeredGridItemSpan.FullLine, contentType = "onboarding") { item(span = StaggeredGridItemSpan.FullLine, contentType = "onboarding") {
Column(modifier = interestsItemModifier) { Column(modifier = interestsItemModifier) {
Text( Text(
text = stringResource(R.string.feature_foryou_onboarding_guidance_title), text = stringResource(R.string.feature_foryou_api_onboarding_guidance_title),
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
@ -278,7 +278,7 @@ private fun LazyStaggeredGridScope.onboarding(
style = MaterialTheme.typography.titleMedium, style = MaterialTheme.typography.titleMedium,
) )
Text( Text(
text = stringResource(R.string.feature_foryou_onboarding_guidance_subtitle), text = stringResource(R.string.feature_foryou_api_onboarding_guidance_subtitle),
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(top = 8.dp, start = 24.dp, end = 24.dp), .padding(top = 8.dp, start = 24.dp, end = 24.dp),
@ -304,7 +304,7 @@ private fun LazyStaggeredGridScope.onboarding(
.fillMaxWidth(), .fillMaxWidth(),
) { ) {
Text( Text(
text = stringResource(R.string.feature_foryou_done), text = stringResource(R.string.feature_foryou_api_done),
) )
} }
} }
@ -433,7 +433,7 @@ fun TopicIcon(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
) { ) {
DynamicAsyncImage( DynamicAsyncImage(
placeholder = painterResource(R.drawable.feature_foryou_ic_icon_placeholder), placeholder = painterResource(R.drawable.feature_foryou_api_ic_icon_placeholder),
imageUrl = imageUrl, imageUrl = imageUrl,
// decorative // decorative
contentDescription = null, contentDescription = null,

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.foryou package com.google.samples.apps.nowinandroid.feature.foryou.api
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.foryou package com.google.samples.apps.nowinandroid.feature.foryou.api
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.foryou.navigation package com.google.samples.apps.nowinandroid.feature.foryou.api.navigation
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder import androidx.navigation.NavGraphBuilder
@ -23,7 +23,7 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.navigation import androidx.navigation.compose.navigation
import androidx.navigation.navDeepLink import androidx.navigation.navDeepLink
import com.google.samples.apps.nowinandroid.core.notifications.DEEP_LINK_URI_PATTERN import com.google.samples.apps.nowinandroid.core.notifications.DEEP_LINK_URI_PATTERN
import com.google.samples.apps.nowinandroid.feature.foryou.ForYouScreen import com.google.samples.apps.nowinandroid.feature.foryou.api.ForYouScreen
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable data object ForYouRoute // route to ForYou screen @Serializable data object ForYouRoute // route to ForYou screen

@ -15,11 +15,11 @@
limitations under the License. limitations under the License.
--> -->
<resources> <resources>
<string name="feature_foryou_title">For you</string> <string name="feature_foryou_api_title">For you</string>
<string name="feature_foryou_done">Done</string> <string name="feature_foryou_api_done">Done</string>
<string name="feature_foryou_loading">Loading for you…</string> <string name="feature_foryou_api_loading">Loading for you…</string>
<string name="feature_foryou_navigate_up">Navigate up</string> <string name="feature_foryou_api_navigate_up">Navigate up</string>
<string name="feature_foryou_onboarding_guidance_title">What are you interested in?</string> <string name="feature_foryou_api_onboarding_guidance_title">What are you interested in?</string>
<string name="feature_foryou_onboarding_guidance_subtitle">Updates from topics you follow will appear here. Follow some things to get started.</string> <string name="feature_foryou_api_onboarding_guidance_subtitle">Updates from topics you follow will appear here. Follow some things to get started.</string>
</resources> </resources>

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.foryou package com.google.samples.apps.nowinandroid.feature.foryou.api
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -31,9 +31,9 @@ import com.google.samples.apps.nowinandroid.core.testing.util.captureMultiDevice
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Success import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Success
import com.google.samples.apps.nowinandroid.core.ui.UserNewsResourcePreviewParameterProvider import com.google.samples.apps.nowinandroid.core.ui.UserNewsResourcePreviewParameterProvider
import com.google.samples.apps.nowinandroid.feature.foryou.OnboardingUiState.Loading import com.google.samples.apps.nowinandroid.feature.foryou.api.OnboardingUiState.Loading
import com.google.samples.apps.nowinandroid.feature.foryou.OnboardingUiState.NotShown import com.google.samples.apps.nowinandroid.feature.foryou.api.OnboardingUiState.NotShown
import com.google.samples.apps.nowinandroid.feature.foryou.OnboardingUiState.Shown import com.google.samples.apps.nowinandroid.feature.foryou.api.OnboardingUiState.Shown
import dagger.hilt.android.testing.HiltTestApplication import dagger.hilt.android.testing.HiltTestApplication
import org.hamcrest.Matchers import org.hamcrest.Matchers
import org.junit.Before import org.junit.Before

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.foryou package com.google.samples.apps.nowinandroid.feature.foryou.api
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import com.google.samples.apps.nowinandroid.core.analytics.AnalyticsEvent import com.google.samples.apps.nowinandroid.core.analytics.AnalyticsEvent

@ -0,0 +1,26 @@
/*
* 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.
*/
plugins {
alias(libs.plugins.nowinandroid.android.feature)
alias(libs.plugins.nowinandroid.android.library.compose)
}
android {
namespace = "com.google.samples.apps.nowinandroid.feature.foryou.impl"
}
dependencies { }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 208 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 231 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

@ -20,7 +20,7 @@ plugins {
alias(libs.plugins.nowinandroid.android.library.jacoco) alias(libs.plugins.nowinandroid.android.library.jacoco)
} }
android { android {
namespace = "com.google.samples.apps.nowinandroid.feature.interests" namespace = "com.google.samples.apps.nowinandroid.feature.interests.api"
} }
dependencies { dependencies {

@ -25,13 +25,13 @@ import androidx.compose.ui.test.onAllNodesWithContentDescription
import androidx.compose.ui.test.onNodeWithContentDescription import androidx.compose.ui.test.onNodeWithContentDescription
import androidx.compose.ui.test.onNodeWithText import androidx.compose.ui.test.onNodeWithText
import com.google.samples.apps.nowinandroid.core.testing.data.followableTopicTestData import com.google.samples.apps.nowinandroid.core.testing.data.followableTopicTestData
import com.google.samples.apps.nowinandroid.feature.interests.InterestsScreen import com.google.samples.apps.nowinandroid.feature.interests.api.InterestsScreen
import com.google.samples.apps.nowinandroid.feature.interests.InterestsUiState import com.google.samples.apps.nowinandroid.feature.interests.api.InterestsUiState
import org.junit.Before import org.junit.Before
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test
import com.google.samples.apps.nowinandroid.core.ui.R as CoreUiR import com.google.samples.apps.nowinandroid.core.ui.R as CoreUiR
import com.google.samples.apps.nowinandroid.feature.interests.R as InterestsR import com.google.samples.apps.nowinandroid.feature.interests.api.R as InterestsR
/** /**
* UI test for checking the correct behaviour of the Interests screen; * UI test for checking the correct behaviour of the Interests screen;
@ -51,8 +51,8 @@ class InterestsScreenTest {
@Before @Before
fun setup() { fun setup() {
composeTestRule.activity.apply { composeTestRule.activity.apply {
interestsLoading = getString(InterestsR.string.feature_interests_loading) interestsLoading = getString(InterestsR.string.feature_interests_api_loading)
interestsEmptyHeader = getString(InterestsR.string.feature_interests_empty_header) interestsEmptyHeader = getString(InterestsR.string.feature_interests_api_empty_header)
interestsTopicCardFollowButton = interestsTopicCardFollowButton =
getString(CoreUiR.string.core_ui_interests_card_follow_button_content_desc) getString(CoreUiR.string.core_ui_interests_card_follow_button_content_desc)
interestsTopicCardUnfollowButton = interestsTopicCardUnfollowButton =

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.interests package com.google.samples.apps.nowinandroid.feature.interests.api
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.material3.Text import androidx.compose.material3.Text
@ -70,7 +70,7 @@ internal fun InterestsScreen(
when (uiState) { when (uiState) {
InterestsUiState.Loading -> InterestsUiState.Loading ->
NiaLoadingWheel( NiaLoadingWheel(
contentDesc = stringResource(id = R.string.feature_interests_loading), contentDesc = stringResource(id = R.string.feature_interests_api_loading),
) )
is InterestsUiState.Interests -> is InterestsUiState.Interests ->
@ -90,7 +90,7 @@ internal fun InterestsScreen(
@Composable @Composable
private fun InterestsEmptyScreen() { private fun InterestsEmptyScreen() {
Text(text = stringResource(id = R.string.feature_interests_empty_header)) Text(text = stringResource(id = R.string.feature_interests_api_empty_header))
} }
@DevicePreviews @DevicePreviews

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.interests package com.google.samples.apps.nowinandroid.feature.interests.api
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
@ -24,7 +24,7 @@ import com.google.samples.apps.nowinandroid.core.data.repository.UserDataReposit
import com.google.samples.apps.nowinandroid.core.domain.GetFollowableTopicsUseCase import com.google.samples.apps.nowinandroid.core.domain.GetFollowableTopicsUseCase
import com.google.samples.apps.nowinandroid.core.domain.TopicSortField import com.google.samples.apps.nowinandroid.core.domain.TopicSortField
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.feature.interests.navigation.InterestsRoute import com.google.samples.apps.nowinandroid.feature.interests.api.navigation.InterestsRoute
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.interests package com.google.samples.apps.nowinandroid.feature.interests.api
import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Box

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.interests.navigation package com.google.samples.apps.nowinandroid.feature.interests.api.navigation
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavOptions import androidx.navigation.NavOptions

@ -15,7 +15,7 @@
limitations under the License. limitations under the License.
--> -->
<resources> <resources>
<string name="feature_interests_title">Interests</string> <string name="feature_interests_api_title">Interests</string>
<string name="feature_interests_loading">Loading data</string> <string name="feature_interests_api_loading">Loading data</string>
<string name="feature_interests_empty_header">"No available data"</string> <string name="feature_interests_api_empty_header">"No available data"</string>
</resources> </resources>

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.interests package com.google.samples.apps.nowinandroid.interests.api
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.navigation.testing.invoke import androidx.navigation.testing.invoke

@ -0,0 +1,24 @@
/*
* 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.
*/
plugins {
alias(libs.plugins.nowinandroid.android.feature)
alias(libs.plugins.nowinandroid.android.library.compose)
alias(libs.plugins.nowinandroid.android.library.jacoco)
}
android {
namespace = "com.google.samples.apps.nowinandroid.feature.interests.impl"
}

@ -21,7 +21,7 @@ plugins {
} }
android { android {
namespace = "com.google.samples.apps.nowinandroid.feature.search" namespace = "com.google.samples.apps.nowinandroid.feature.search.api"
} }
dependencies { dependencies {

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.search package com.google.samples.apps.nowinandroid.feature.search.api
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.compose.ui.test.assertCountEquals import androidx.compose.ui.test.assertCountEquals

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.search package com.google.samples.apps.nowinandroid.feature.search.api
import com.google.samples.apps.nowinandroid.core.data.model.RecentSearchQuery import com.google.samples.apps.nowinandroid.core.data.model.RecentSearchQuery

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.search package com.google.samples.apps.nowinandroid.feature.search.api
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.search package com.google.samples.apps.nowinandroid.feature.search.api
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.Orientation
@ -93,7 +93,7 @@ import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Success
import com.google.samples.apps.nowinandroid.core.ui.R.string import com.google.samples.apps.nowinandroid.core.ui.R.string
import com.google.samples.apps.nowinandroid.core.ui.TrackScreenViewEvent import com.google.samples.apps.nowinandroid.core.ui.TrackScreenViewEvent
import com.google.samples.apps.nowinandroid.core.ui.newsFeed import com.google.samples.apps.nowinandroid.core.ui.newsFeed
import com.google.samples.apps.nowinandroid.feature.search.R as searchR import com.google.samples.apps.nowinandroid.feature.search.api.R as searchR
@Composable @Composable
internal fun SearchRoute( internal fun SearchRoute(
@ -211,7 +211,7 @@ fun EmptySearchResultBody(
horizontalAlignment = Alignment.CenterHorizontally, horizontalAlignment = Alignment.CenterHorizontally,
modifier = Modifier.padding(horizontal = 48.dp), modifier = Modifier.padding(horizontal = 48.dp),
) { ) {
val message = stringResource(id = searchR.string.feature_search_result_not_found, searchQuery) val message = stringResource(id = searchR.string.feature_search_api_result_not_found, searchQuery)
val start = message.indexOf(searchQuery) val start = message.indexOf(searchQuery)
Text( Text(
text = AnnotatedString( text = AnnotatedString(
@ -229,7 +229,7 @@ fun EmptySearchResultBody(
modifier = Modifier.padding(vertical = 24.dp), modifier = Modifier.padding(vertical = 24.dp),
) )
val tryAnotherSearchString = buildAnnotatedString { val tryAnotherSearchString = buildAnnotatedString {
append(stringResource(id = searchR.string.feature_search_try_another_search)) append(stringResource(id = searchR.string.feature_search_api_try_another_search))
append(" ") append(" ")
withLink( withLink(
LinkAnnotation.Clickable( LinkAnnotation.Clickable(
@ -245,12 +245,12 @@ fun EmptySearchResultBody(
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
), ),
) { ) {
append(stringResource(id = searchR.string.feature_search_interests)) append(stringResource(id = searchR.string.feature_search_api_interests))
} }
} }
append(" ") append(" ")
append(stringResource(id = searchR.string.feature_search_to_browse_topics)) append(stringResource(id = searchR.string.feature_search_api_to_browse_topics))
} }
Text( Text(
text = tryAnotherSearchString, text = tryAnotherSearchString,
@ -273,7 +273,7 @@ private fun SearchNotReadyBody() {
modifier = Modifier.padding(horizontal = 48.dp), modifier = Modifier.padding(horizontal = 48.dp),
) { ) {
Text( Text(
text = stringResource(id = searchR.string.feature_search_not_ready), text = stringResource(id = searchR.string.feature_search_api_not_ready),
style = MaterialTheme.typography.bodyLarge, style = MaterialTheme.typography.bodyLarge,
textAlign = TextAlign.Center, textAlign = TextAlign.Center,
modifier = Modifier.padding(vertical = 24.dp), modifier = Modifier.padding(vertical = 24.dp),
@ -314,7 +314,7 @@ private fun SearchResultBody(
Text( Text(
text = buildAnnotatedString { text = buildAnnotatedString {
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) { withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
append(stringResource(id = searchR.string.feature_search_topics)) append(stringResource(id = searchR.string.feature_search_api_topics))
} }
}, },
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
@ -350,7 +350,7 @@ private fun SearchResultBody(
Text( Text(
text = buildAnnotatedString { text = buildAnnotatedString {
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) { withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
append(stringResource(id = searchR.string.feature_search_updates)) append(stringResource(id = searchR.string.feature_search_api_updates))
} }
}, },
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
@ -402,7 +402,7 @@ private fun RecentSearchesBody(
Text( Text(
text = buildAnnotatedString { text = buildAnnotatedString {
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) { withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
append(stringResource(id = searchR.string.feature_search_recent_searches)) append(stringResource(id = searchR.string.feature_search_api_recent_searches))
} }
}, },
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
@ -417,7 +417,7 @@ private fun RecentSearchesBody(
Icon( Icon(
imageVector = NiaIcons.Close, imageVector = NiaIcons.Close,
contentDescription = stringResource( contentDescription = stringResource(
id = searchR.string.feature_search_clear_recent_searches_content_desc, id = searchR.string.feature_search_api_clear_recent_searches_content_desc,
), ),
tint = MaterialTheme.colorScheme.onSurface, tint = MaterialTheme.colorScheme.onSurface,
) )
@ -491,7 +491,7 @@ private fun SearchTextField(
Icon( Icon(
imageVector = NiaIcons.Search, imageVector = NiaIcons.Search,
contentDescription = stringResource( contentDescription = stringResource(
id = searchR.string.feature_search_title, id = searchR.string.feature_search_api_title,
), ),
tint = MaterialTheme.colorScheme.onSurface, tint = MaterialTheme.colorScheme.onSurface,
) )
@ -506,7 +506,7 @@ private fun SearchTextField(
Icon( Icon(
imageVector = NiaIcons.Close, imageVector = NiaIcons.Close,
contentDescription = stringResource( contentDescription = stringResource(
id = searchR.string.feature_search_clear_search_text_content_desc, id = searchR.string.feature_search_api_clear_search_text_content_desc,
), ),
tint = MaterialTheme.colorScheme.onSurface, tint = MaterialTheme.colorScheme.onSurface,
) )

@ -1,5 +1,5 @@
/* /*
* Copyright 2023 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -16,12 +16,13 @@
@file:Suppress("ktlint:standard:max-line-length") @file:Suppress("ktlint:standard:max-line-length")
package com.google.samples.apps.nowinandroid.feature.search package com.google.samples.apps.nowinandroid.feature.search.api
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.core.ui.PreviewParameterData.newsResources import com.google.samples.apps.nowinandroid.core.ui.PreviewParameterData.newsResources
import com.google.samples.apps.nowinandroid.core.ui.PreviewParameterData.topics import com.google.samples.apps.nowinandroid.core.ui.PreviewParameterData.topics
import com.google.samples.apps.nowinandroid.feature.search.api.SearchResultUiState.Success
/** /**
* This [PreviewParameterProvider](https://developer.android.com/reference/kotlin/androidx/compose/ui/tooling/preview/PreviewParameterProvider) * This [PreviewParameterProvider](https://developer.android.com/reference/kotlin/androidx/compose/ui/tooling/preview/PreviewParameterProvider)
@ -29,7 +30,7 @@ import com.google.samples.apps.nowinandroid.core.ui.PreviewParameterData.topics
*/ */
class SearchUiStatePreviewParameterProvider : PreviewParameterProvider<SearchResultUiState> { class SearchUiStatePreviewParameterProvider : PreviewParameterProvider<SearchResultUiState> {
override val values: Sequence<SearchResultUiState> = sequenceOf( override val values: Sequence<SearchResultUiState> = sequenceOf(
SearchResultUiState.Success( Success(
topics = topics.mapIndexed { i, topic -> topics = topics.mapIndexed { i, topic ->
FollowableTopic(topic = topic, isFollowed = i % 2 == 0) FollowableTopic(topic = topic, isFollowed = i % 2 == 0)
}, },

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.search package com.google.samples.apps.nowinandroid.feature.search.api
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel

@ -14,13 +14,13 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.search.navigation package com.google.samples.apps.nowinandroid.feature.search.api.navigation
import androidx.navigation.NavController import androidx.navigation.NavController
import androidx.navigation.NavGraphBuilder import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptions import androidx.navigation.NavOptions
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import com.google.samples.apps.nowinandroid.feature.search.SearchRoute import com.google.samples.apps.nowinandroid.feature.search.api.SearchRoute
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable data object SearchRoute @Serializable data object SearchRoute
@ -36,7 +36,7 @@ fun NavGraphBuilder.searchScreen(
// TODO: Handle back stack for each top-level destination. At the moment each top-level // TODO: Handle back stack for each top-level destination. At the moment each top-level
// destination may have own search screen's back stack. // destination may have own search screen's back stack.
composable<SearchRoute> { composable<SearchRoute> {
SearchRoute( com.google.samples.apps.nowinandroid.feature.search.api.SearchRoute(
onBackClick = onBackClick, onBackClick = onBackClick,
onInterestsClick = onInterestsClick, onInterestsClick = onInterestsClick,
onTopicClick = onTopicClick, onTopicClick = onTopicClick,

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2023 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
http://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.
-->
<resources>
<string name="feature_search_api_title">Search</string>
<string name="feature_search_api_clear_search_text_content_desc">Clear search text</string>
<string name="feature_search_api_result_not_found">Sorry, there is no content found for your search \"%1$s\"</string>
<string name="feature_search_api_not_ready">Sorry, we are still processing the search index. Please come back later</string>
<string name="feature_search_api_try_another_search">Try another search or explorer </string>
<string name="feature_search_api_interests">Interests</string>
<string name="feature_search_api_to_browse_topics"> to browse topics</string>
<string name="feature_search_api_topics">Topics</string>
<string name="feature_search_api_updates">Updates</string>
<string name="feature_search_api_recent_searches">Recent searches</string>
<string name="feature_search_api_clear_recent_searches_content_desc">Clear searches</string>
</resources>

@ -1,5 +1,5 @@
/* /*
* Copyright 2023 The Android Open Source Project * Copyright 2022 The Android Open Source Project
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.search package com.google.samples.apps.nowinandroid.feature.search.api
import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.SavedStateHandle
import com.google.samples.apps.nowinandroid.core.analytics.NoOpAnalyticsHelper import com.google.samples.apps.nowinandroid.core.analytics.NoOpAnalyticsHelper
@ -27,10 +27,10 @@ import com.google.samples.apps.nowinandroid.core.testing.repository.TestSearchCo
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.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.api.RecentSearchQueriesUiState.Success
import com.google.samples.apps.nowinandroid.feature.search.SearchResultUiState.EmptyQuery import com.google.samples.apps.nowinandroid.feature.search.api.SearchResultUiState.EmptyQuery
import com.google.samples.apps.nowinandroid.feature.search.SearchResultUiState.Loading import com.google.samples.apps.nowinandroid.feature.search.api.SearchResultUiState.Loading
import com.google.samples.apps.nowinandroid.feature.search.SearchResultUiState.SearchNotReady import com.google.samples.apps.nowinandroid.feature.search.api.SearchResultUiState.SearchNotReady
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.first
import kotlinx.coroutines.launch import kotlinx.coroutines.launch

@ -0,0 +1,25 @@
/*
* Copyright 2023 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.
*/
plugins {
alias(libs.plugins.nowinandroid.android.feature)
alias(libs.plugins.nowinandroid.android.library.compose)
alias(libs.plugins.nowinandroid.android.library.jacoco)
}
android {
namespace = "com.google.samples.apps.nowinandroid.feature.search.impl"
}

@ -1,29 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2023 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
http://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.
-->
<resources>
<string name="feature_search_title">Search</string>
<string name="feature_search_clear_search_text_content_desc">Clear search text</string>
<string name="feature_search_result_not_found">Sorry, there is no content found for your search \"%1$s\"</string>
<string name="feature_search_not_ready">Sorry, we are still processing the search index. Please come back later</string>
<string name="feature_search_try_another_search">Try another search or explorer </string>
<string name="feature_search_interests">Interests</string>
<string name="feature_search_to_browse_topics"> to browse topics</string>
<string name="feature_search_topics">Topics</string>
<string name="feature_search_updates">Updates</string>
<string name="feature_search_recent_searches">Recent searches</string>
<string name="feature_search_clear_recent_searches_content_desc">Clear searches</string>
</resources>

@ -21,7 +21,7 @@ plugins {
} }
android { android {
namespace = "com.google.samples.apps.nowinandroid.feature.settings" namespace = "com.google.samples.apps.nowinandroid.feature.settings.api"
} }
dependencies { dependencies {

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.settings package com.google.samples.apps.nowinandroid.feature.settings.api
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.compose.ui.test.assertIsSelected import androidx.compose.ui.test.assertIsSelected
@ -23,8 +23,8 @@ import androidx.compose.ui.test.onNodeWithText
import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig.DARK import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig.DARK
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.ANDROID import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.ANDROID
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.DEFAULT import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.DEFAULT
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Loading import com.google.samples.apps.nowinandroid.feature.settings.api.SettingsUiState.Loading
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Success import com.google.samples.apps.nowinandroid.feature.settings.api.SettingsUiState.Success
import org.junit.Rule import org.junit.Rule
import org.junit.Test import org.junit.Test

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
android:theme="@style/Theme.AppCompat" />
<activity
android:name="com.google.android.gms.oss.licenses.OssLicensesActivity"
android:theme="@style/Theme.AppCompat" />
</application>
</manifest>

@ -16,7 +16,7 @@
@file:Suppress("ktlint:standard:max-line-length") @file:Suppress("ktlint:standard:max-line-length")
package com.google.samples.apps.nowinandroid.feature.settings package com.google.samples.apps.nowinandroid.feature.settings.api
import android.content.Intent import android.content.Intent
import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.AnimatedVisibility
@ -66,9 +66,9 @@ import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.ANDROID import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.ANDROID
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.DEFAULT import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.DEFAULT
import com.google.samples.apps.nowinandroid.core.ui.TrackScreenViewEvent import com.google.samples.apps.nowinandroid.core.ui.TrackScreenViewEvent
import com.google.samples.apps.nowinandroid.feature.settings.R.string import com.google.samples.apps.nowinandroid.feature.settings.api.R.string
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Loading import com.google.samples.apps.nowinandroid.feature.settings.api.SettingsUiState.Loading
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Success import com.google.samples.apps.nowinandroid.feature.settings.api.SettingsUiState.Success
@Composable @Composable
fun SettingsDialog( fun SettingsDialog(

@ -14,15 +14,15 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.settings package com.google.samples.apps.nowinandroid.feature.settings.api
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Loading import com.google.samples.apps.nowinandroid.feature.settings.api.SettingsUiState.Loading
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Success import com.google.samples.apps.nowinandroid.feature.settings.api.SettingsUiState.Success
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed import kotlinx.coroutines.flow.SharingStarted.Companion.WhileSubscribed
import kotlinx.coroutines.flow.StateFlow import kotlinx.coroutines.flow.StateFlow

@ -14,14 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.settings package com.google.samples.apps.nowinandroid.feature.settings.api
import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig.DARK import com.google.samples.apps.nowinandroid.core.model.data.DarkThemeConfig.DARK
import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.ANDROID import com.google.samples.apps.nowinandroid.core.model.data.ThemeBrand.ANDROID
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.util.MainDispatcherRule import com.google.samples.apps.nowinandroid.core.testing.util.MainDispatcherRule
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Loading import com.google.samples.apps.nowinandroid.feature.settings.api.SettingsUiState.Loading
import com.google.samples.apps.nowinandroid.feature.settings.SettingsUiState.Success import com.google.samples.apps.nowinandroid.feature.settings.api.SettingsUiState.Success
import kotlinx.coroutines.flow.collect import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.test.UnconfinedTestDispatcher import kotlinx.coroutines.test.UnconfinedTestDispatcher

@ -1,27 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
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
http://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.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<activity
android:name="com.google.android.gms.oss.licenses.OssLicensesMenuActivity"
android:theme="@style/Theme.AppCompat" />
<activity
android:name="com.google.android.gms.oss.licenses.OssLicensesActivity"
android:theme="@style/Theme.AppCompat" />
</application>
</manifest>

@ -0,0 +1 @@
/build

@ -21,7 +21,7 @@ plugins {
} }
android { android {
namespace = "com.google.samples.apps.nowinandroid.feature.topic" namespace = "com.google.samples.apps.nowinandroid.feature.topic.api"
} }
dependencies { dependencies {

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.topic package com.google.samples.apps.nowinandroid.feature.topic.api
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.compose.ui.test.hasScrollToNodeAction import androidx.compose.ui.test.hasScrollToNodeAction
@ -45,7 +45,7 @@ class TopicScreenTest {
@Before @Before
fun setup() { fun setup() {
composeTestRule.activity.apply { composeTestRule.activity.apply {
topicLoading = getString(R.string.feature_topic_loading) topicLoading = getString(R.string.feature_topic_api_loading)
} }
} }

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.topic package com.google.samples.apps.nowinandroid.feature.topic.api
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -50,12 +50,12 @@ fun TopicDetailPlaceholder(modifier: Modifier = Modifier) {
), ),
) { ) {
Icon( Icon(
painter = painterResource(id = R.drawable.feature_topic_ic_topic_placeholder), painter = painterResource(id = R.drawable.feature_topic_api_ic_topic_placeholder),
contentDescription = null, contentDescription = null,
tint = MaterialTheme.colorScheme.primary, tint = MaterialTheme.colorScheme.primary,
) )
Text( Text(
text = stringResource(id = R.string.feature_topic_select_an_interest), text = stringResource(id = R.string.feature_topic_api_select_an_interest),
style = MaterialTheme.typography.titleLarge, style = MaterialTheme.typography.titleLarge,
) )
} }

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.topic package com.google.samples.apps.nowinandroid.feature.topic.api
import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting
import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.Orientation
@ -68,7 +68,7 @@ import com.google.samples.apps.nowinandroid.core.ui.TrackScreenViewEvent
import com.google.samples.apps.nowinandroid.core.ui.TrackScrollJank import com.google.samples.apps.nowinandroid.core.ui.TrackScrollJank
import com.google.samples.apps.nowinandroid.core.ui.UserNewsResourcePreviewParameterProvider import com.google.samples.apps.nowinandroid.core.ui.UserNewsResourcePreviewParameterProvider
import com.google.samples.apps.nowinandroid.core.ui.userNewsResourceCardItems import com.google.samples.apps.nowinandroid.core.ui.userNewsResourceCardItems
import com.google.samples.apps.nowinandroid.feature.topic.R.string import com.google.samples.apps.nowinandroid.feature.topic.api.R.string
@Composable @Composable
fun TopicScreen( fun TopicScreen(
@ -124,7 +124,7 @@ internal fun TopicScreen(
TopicUiState.Loading -> item { TopicUiState.Loading -> item {
NiaLoadingWheel( NiaLoadingWheel(
modifier = modifier, modifier = modifier,
contentDesc = stringResource(id = string.feature_topic_loading), contentDesc = stringResource(id = string.feature_topic_api_loading),
) )
} }

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.topic package com.google.samples.apps.nowinandroid.feature.topic.api
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.topic.navigation package com.google.samples.apps.nowinandroid.feature.topic.api.navigation
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavController import androidx.navigation.NavController
@ -22,8 +22,8 @@ import androidx.navigation.NavGraphBuilder
import androidx.navigation.NavOptionsBuilder import androidx.navigation.NavOptionsBuilder
import androidx.navigation.compose.composable import androidx.navigation.compose.composable
import androidx.navigation.toRoute import androidx.navigation.toRoute
import com.google.samples.apps.nowinandroid.feature.topic.TopicScreen import com.google.samples.apps.nowinandroid.feature.topic.api.TopicScreen
import com.google.samples.apps.nowinandroid.feature.topic.TopicViewModel import com.google.samples.apps.nowinandroid.feature.topic.api.TopicViewModel
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable data class TopicRoute(val id: String) @Serializable data class TopicRoute(val id: String)

@ -1,19 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- <!--
Copyright 2024 The Android Open Source Project ~ Copyright 2024 The Android Open Source Project
~
Licensed under the Apache License, Version 2.0 (the "License"); ~ Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. ~ you may not use this file except in compliance with the License.
You may obtain a copy of the License at ~ You may obtain a copy of the License at
~
http://www.apache.org/licenses/LICENSE-2.0 ~ https://www.apache.org/licenses/LICENSE-2.0
~
Unless required by applicable law or agreed to in writing, software ~ Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, ~ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and ~ See the License for the specific language governing permissions and
limitations under the License. ~ limitations under the License.
--> -->
<vector xmlns:android="http://schemas.android.com/apk/res/android" <vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="64dp" android:width="64dp"
android:height="64dp" android:height="64dp"

@ -15,6 +15,6 @@
limitations under the License. limitations under the License.
--> -->
<resources> <resources>
<string name="feature_topic_loading">Loading topic</string> <string name="feature_topic_api_loading">Loading topic</string>
<string name="feature_topic_select_an_interest">Select an Interest</string> <string name="feature_topic_api_select_an_interest">Select an Interest</string>
</resources> </resources>

@ -14,7 +14,7 @@
* limitations under the License. * limitations under the License.
*/ */
package com.google.samples.apps.nowinandroid.feature.topic package com.google.samples.apps.nowinandroid.feature.topic.api
import com.google.samples.apps.nowinandroid.core.data.repository.CompositeUserNewsResourceRepository import com.google.samples.apps.nowinandroid.core.data.repository.CompositeUserNewsResourceRepository
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic

@ -0,0 +1,25 @@
/*
* 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.
*/
plugins {
alias(libs.plugins.nowinandroid.android.feature)
alias(libs.plugins.nowinandroid.android.library.compose)
alias(libs.plugins.nowinandroid.android.library.jacoco)
}
android {
namespace = "com.google.samples.apps.nowinandroid.feature.topic.impl"
}

@ -65,12 +65,17 @@ include(":core:screenshot-testing")
include(":core:testing") include(":core:testing")
include(":core:ui") include(":core:ui")
include(":feature:foryou") include(":feature:foryou:api")
include(":feature:interests") include(":feature:foryou:impl")
include(":feature:bookmarks") include(":feature:interests:api")
include(":feature:topic") include(":feature:interests:impl")
include(":feature:search") include(":feature:bookmarks:api")
include(":feature:settings") include(":feature:bookmarks:impl")
include(":feature:topic:api")
include(":feature:topic:impl")
include(":feature:search:api")
include(":feature:search:impl")
include(":feature:settings:api")
include(":lint") include(":lint")
include(":sync:work") include(":sync:work")
include(":sync:sync-test") include(":sync:sync-test")

Loading…
Cancel
Save