diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index a24d14540..0a9e39c9d 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -34,14 +34,7 @@
-
-
-
-
-
-
-
-
+
@@ -307,19 +300,11 @@
+
-
-
-
-
-
-
-
-
-
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 70e6b25c3..16406e511 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -129,7 +129,7 @@ dependencies {
resolutionStrategy {
force(libs.junit4)
// Temporary workaround for https://issuetracker.google.com/174733673
- force("org.objenesis:objenesis:3.2")
+ force("org.objenesis:objenesis:2.6")
}
}
}
diff --git a/core-data-test/src/main/java/com/google/samples/apps/nowinandroid/core/data/test/TestDataModule.kt b/core-data-test/src/main/java/com/google/samples/apps/nowinandroid/core/data/test/TestDataModule.kt
index 3966ead2e..fa31a37a5 100644
--- a/core-data-test/src/main/java/com/google/samples/apps/nowinandroid/core/data/test/TestDataModule.kt
+++ b/core-data-test/src/main/java/com/google/samples/apps/nowinandroid/core/data/test/TestDataModule.kt
@@ -20,9 +20,11 @@ import com.google.samples.apps.nowinandroid.core.data.di.DataModule
import com.google.samples.apps.nowinandroid.core.data.repository.AuthorsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.NewsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
+import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
import com.google.samples.apps.nowinandroid.core.data.repository.fake.FakeAuthorsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.fake.FakeNewsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.fake.FakeTopicsRepository
+import com.google.samples.apps.nowinandroid.core.data.repository.fake.FakeUserDataRepository
import dagger.Binds
import dagger.Module
import dagger.hilt.components.SingletonComponent
@@ -48,4 +50,9 @@ interface TestDataModule {
fun bindsNewsResourceRepository(
fakeNewsRepository: FakeNewsRepository
): NewsRepository
+
+ @Binds
+ fun bindsUserDataRepository(
+ userDataRepository: FakeUserDataRepository
+ ): UserDataRepository
}
diff --git a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/di/DataModule.kt b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/di/DataModule.kt
index f44ff986e..3e30e7e59 100644
--- a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/di/DataModule.kt
+++ b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/di/DataModule.kt
@@ -21,7 +21,9 @@ import com.google.samples.apps.nowinandroid.core.data.repository.NewsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.OfflineFirstAuthorsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.OfflineFirstNewsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.OfflineFirstTopicsRepository
+import com.google.samples.apps.nowinandroid.core.data.repository.OfflineFirstUserDataRepository
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
+import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
@@ -45,4 +47,9 @@ interface DataModule {
fun bindsNewsResourceRepository(
newsRepository: OfflineFirstNewsRepository
): NewsRepository
+
+ @Binds
+ fun bindsUserDataRepository(
+ userDataRepository: OfflineFirstUserDataRepository
+ ): UserDataRepository
}
diff --git a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/AuthorsRepository.kt b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/AuthorsRepository.kt
index 6921b94b3..8a27d5704 100644
--- a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/AuthorsRepository.kt
+++ b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/AuthorsRepository.kt
@@ -30,19 +30,4 @@ interface AuthorsRepository : Syncable {
* Gets data for a specific author
*/
fun getAuthorStream(id: String): Flow
-
- /**
- * Sets the user's currently followed authors
- */
- suspend fun setFollowedAuthorIds(followedAuthorIds: Set)
-
- /**
- * Toggles the user's newly followed/unfollowed author
- */
- suspend fun toggleFollowedAuthorId(followedAuthorId: String, followed: Boolean)
-
- /**
- * Returns the users currently followed authors
- */
- fun getFollowedAuthorIdsStream(): Flow>
}
diff --git a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstAuthorsRepository.kt b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstAuthorsRepository.kt
index 5344810f3..0773bdc59 100644
--- a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstAuthorsRepository.kt
+++ b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstAuthorsRepository.kt
@@ -23,7 +23,6 @@ import com.google.samples.apps.nowinandroid.core.database.dao.AuthorDao
import com.google.samples.apps.nowinandroid.core.database.model.AuthorEntity
import com.google.samples.apps.nowinandroid.core.database.model.asExternalModel
import com.google.samples.apps.nowinandroid.core.datastore.ChangeListVersions
-import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferencesDataSource
import com.google.samples.apps.nowinandroid.core.model.data.Author
import com.google.samples.apps.nowinandroid.core.network.NiaNetworkDataSource
import com.google.samples.apps.nowinandroid.core.network.model.NetworkAuthor
@@ -38,7 +37,6 @@ import kotlinx.coroutines.flow.map
class OfflineFirstAuthorsRepository @Inject constructor(
private val authorDao: AuthorDao,
private val network: NiaNetworkDataSource,
- private val niaPreferences: NiaPreferencesDataSource,
) : AuthorsRepository {
override fun getAuthorStream(id: String): Flow =
@@ -50,14 +48,6 @@ class OfflineFirstAuthorsRepository @Inject constructor(
authorDao.getAuthorEntitiesStream()
.map { it.map(AuthorEntity::asExternalModel) }
- override suspend fun setFollowedAuthorIds(followedAuthorIds: Set) =
- niaPreferences.setFollowedAuthorIds(followedAuthorIds)
-
- override suspend fun toggleFollowedAuthorId(followedAuthorId: String, followed: Boolean) =
- niaPreferences.toggleFollowedAuthorId(followedAuthorId, followed)
-
- override fun getFollowedAuthorIdsStream(): Flow> = niaPreferences.followedAuthorIds
-
override suspend fun syncWith(synchronizer: Synchronizer): Boolean =
synchronizer.changeListSync(
versionReader = ChangeListVersions::authorVersion,
diff --git a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstTopicsRepository.kt b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstTopicsRepository.kt
index 4e2c64c9d..04d800021 100644
--- a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstTopicsRepository.kt
+++ b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstTopicsRepository.kt
@@ -23,7 +23,6 @@ import com.google.samples.apps.nowinandroid.core.database.dao.TopicDao
import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity
import com.google.samples.apps.nowinandroid.core.database.model.asExternalModel
import com.google.samples.apps.nowinandroid.core.datastore.ChangeListVersions
-import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferencesDataSource
import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.network.NiaNetworkDataSource
import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic
@@ -38,7 +37,6 @@ import kotlinx.coroutines.flow.map
class OfflineFirstTopicsRepository @Inject constructor(
private val topicDao: TopicDao,
private val network: NiaNetworkDataSource,
- private val niaPreferences: NiaPreferencesDataSource,
) : TopicsRepository {
override fun getTopicsStream(): Flow> =
@@ -48,14 +46,6 @@ class OfflineFirstTopicsRepository @Inject constructor(
override fun getTopic(id: String): Flow =
topicDao.getTopicEntity(id).map { it.asExternalModel() }
- override suspend fun setFollowedTopicIds(followedTopicIds: Set) =
- niaPreferences.setFollowedTopicIds(followedTopicIds)
-
- override suspend fun toggleFollowedTopicId(followedTopicId: String, followed: Boolean) =
- niaPreferences.toggleFollowedTopicId(followedTopicId, followed)
-
- override fun getFollowedTopicIdsStream() = niaPreferences.followedTopicIds
-
override suspend fun syncWith(synchronizer: Synchronizer): Boolean =
synchronizer.changeListSync(
versionReader = ChangeListVersions::topicVersion,
diff --git a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstUserDataRepository.kt b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstUserDataRepository.kt
new file mode 100644
index 000000000..08bfa18b4
--- /dev/null
+++ b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstUserDataRepository.kt
@@ -0,0 +1,42 @@
+/*
+ * 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.data.repository
+
+import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferencesDataSource
+import com.google.samples.apps.nowinandroid.core.model.data.UserData
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+
+class OfflineFirstUserDataRepository @Inject constructor(
+ private val niaPreferencesDataSource: NiaPreferencesDataSource
+) : UserDataRepository {
+
+ override val userDataStream: Flow =
+ niaPreferencesDataSource.userDataStream
+
+ override suspend fun setFollowedTopicIds(followedTopicIds: Set) =
+ niaPreferencesDataSource.setFollowedTopicIds(followedTopicIds)
+
+ override suspend fun toggleFollowedTopicId(followedTopicId: String, followed: Boolean) =
+ niaPreferencesDataSource.toggleFollowedTopicId(followedTopicId, followed)
+
+ override suspend fun setFollowedAuthorIds(followedAuthorIds: Set) =
+ niaPreferencesDataSource.setFollowedAuthorIds(followedAuthorIds)
+
+ override suspend fun toggleFollowedAuthorId(followedAuthorId: String, followed: Boolean) =
+ niaPreferencesDataSource.toggleFollowedAuthorId(followedAuthorId, followed)
+}
diff --git a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/TopicsRepository.kt b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/TopicsRepository.kt
index a4d2185b1..2e48fb334 100644
--- a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/TopicsRepository.kt
+++ b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/TopicsRepository.kt
@@ -30,19 +30,4 @@ interface TopicsRepository : Syncable {
* Gets data for a specific topic
*/
fun getTopic(id: String): Flow
-
- /**
- * Sets the user's currently followed topics
- */
- suspend fun setFollowedTopicIds(followedTopicIds: Set)
-
- /**
- * Toggles the user's newly followed/unfollowed topic
- */
- suspend fun toggleFollowedTopicId(followedTopicId: String, followed: Boolean)
-
- /**
- * Returns the users currently followed topics
- */
- fun getFollowedTopicIdsStream(): Flow>
}
diff --git a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/UserDataRepository.kt b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/UserDataRepository.kt
new file mode 100644
index 000000000..f07b4efbe
--- /dev/null
+++ b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/UserDataRepository.kt
@@ -0,0 +1,48 @@
+/*
+ * 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.data.repository
+
+import com.google.samples.apps.nowinandroid.core.model.data.UserData
+import kotlinx.coroutines.flow.Flow
+
+interface UserDataRepository {
+
+ /**
+ * Stream of [UserData]
+ */
+ val userDataStream: Flow
+
+ /**
+ * Sets the user's currently followed topics
+ */
+ suspend fun setFollowedTopicIds(followedTopicIds: Set)
+
+ /**
+ * Toggles the user's newly followed/unfollowed topic
+ */
+ suspend fun toggleFollowedTopicId(followedTopicId: String, followed: Boolean)
+
+ /**
+ * Sets the user's currently followed authors
+ */
+ suspend fun setFollowedAuthorIds(followedAuthorIds: Set)
+
+ /**
+ * Toggles the user's newly followed/unfollowed author
+ */
+ suspend fun toggleFollowedAuthorId(followedAuthorId: String, followed: Boolean)
+}
diff --git a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeAuthorsRepository.kt b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeAuthorsRepository.kt
index 4a0ebf0ba..a6e2f69d8 100644
--- a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeAuthorsRepository.kt
+++ b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeAuthorsRepository.kt
@@ -18,7 +18,6 @@ package com.google.samples.apps.nowinandroid.core.data.repository.fake
import com.google.samples.apps.nowinandroid.core.data.Synchronizer
import com.google.samples.apps.nowinandroid.core.data.repository.AuthorsRepository
-import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferencesDataSource
import com.google.samples.apps.nowinandroid.core.model.data.Author
import com.google.samples.apps.nowinandroid.core.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
@@ -41,7 +40,6 @@ import kotlinx.serialization.json.Json
*/
class FakeAuthorsRepository @Inject constructor(
@Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher,
- private val niaPreferences: NiaPreferencesDataSource,
private val networkJson: Json,
) : AuthorsRepository {
@@ -65,15 +63,5 @@ class FakeAuthorsRepository @Inject constructor(
return getAuthorsStream().map { it.first { author -> author.id == id } }
}
- override suspend fun setFollowedAuthorIds(followedAuthorIds: Set) {
- niaPreferences.setFollowedAuthorIds(followedAuthorIds)
- }
-
- override suspend fun toggleFollowedAuthorId(followedAuthorId: String, followed: Boolean) {
- niaPreferences.toggleFollowedAuthorId(followedAuthorId, followed)
- }
-
- override fun getFollowedAuthorIdsStream(): Flow> = niaPreferences.followedAuthorIds
-
override suspend fun syncWith(synchronizer: Synchronizer) = true
}
diff --git a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeTopicsRepository.kt b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeTopicsRepository.kt
index ec18600f0..7ee46fed6 100644
--- a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeTopicsRepository.kt
+++ b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeTopicsRepository.kt
@@ -18,7 +18,6 @@ package com.google.samples.apps.nowinandroid.core.data.repository.fake
import com.google.samples.apps.nowinandroid.core.data.Synchronizer
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
-import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferencesDataSource
import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.network.Dispatcher
import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers.IO
@@ -43,7 +42,6 @@ import kotlinx.serialization.json.Json
class FakeTopicsRepository @Inject constructor(
@Dispatcher(IO) private val ioDispatcher: CoroutineDispatcher,
private val networkJson: Json,
- private val niaPreferences: NiaPreferencesDataSource
) : TopicsRepository {
override fun getTopicsStream(): Flow> = flow> {
emit(
@@ -65,13 +63,5 @@ class FakeTopicsRepository @Inject constructor(
return getTopicsStream().map { it.first { topic -> topic.id == id } }
}
- override suspend fun setFollowedTopicIds(followedTopicIds: Set) =
- niaPreferences.setFollowedTopicIds(followedTopicIds)
-
- override suspend fun toggleFollowedTopicId(followedTopicId: String, followed: Boolean) =
- niaPreferences.toggleFollowedTopicId(followedTopicId, followed)
-
- override fun getFollowedTopicIdsStream() = niaPreferences.followedTopicIds
-
override suspend fun syncWith(synchronizer: Synchronizer) = true
}
diff --git a/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeUserDataRepository.kt b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeUserDataRepository.kt
new file mode 100644
index 000000000..2e214333f
--- /dev/null
+++ b/core-data/src/main/java/com/google/samples/apps/nowinandroid/core/data/repository/fake/FakeUserDataRepository.kt
@@ -0,0 +1,52 @@
+/*
+ * 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.data.repository.fake
+
+import com.google.samples.apps.nowinandroid.core.data.repository.AuthorsRepository
+import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
+import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferencesDataSource
+import com.google.samples.apps.nowinandroid.core.model.data.UserData
+import javax.inject.Inject
+import kotlinx.coroutines.flow.Flow
+
+/**
+ * Fake implementation of the [AuthorsRepository] that returns hardcoded authors.
+ *
+ * This allows us to run the app with fake data, without needing an internet connection or working
+ * backend.
+ */
+class FakeUserDataRepository @Inject constructor(
+ private val niaPreferencesDataSource: NiaPreferencesDataSource,
+) : UserDataRepository {
+
+ override val userDataStream: Flow =
+ niaPreferencesDataSource.userDataStream
+
+ override suspend fun setFollowedTopicIds(followedTopicIds: Set) =
+ niaPreferencesDataSource.setFollowedTopicIds(followedTopicIds)
+
+ override suspend fun toggleFollowedTopicId(followedTopicId: String, followed: Boolean) =
+ niaPreferencesDataSource.toggleFollowedTopicId(followedTopicId, followed)
+
+ override suspend fun setFollowedAuthorIds(followedAuthorIds: Set) {
+ niaPreferencesDataSource.setFollowedAuthorIds(followedAuthorIds)
+ }
+
+ override suspend fun toggleFollowedAuthorId(followedAuthorId: String, followed: Boolean) {
+ niaPreferencesDataSource.toggleFollowedAuthorId(followedAuthorId, followed)
+ }
+}
diff --git a/core-data/src/test/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstAuthorsRepositoryTest.kt b/core-data/src/test/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstAuthorsRepositoryTest.kt
index 1d7bc0407..61c5fb809 100644
--- a/core-data/src/test/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstAuthorsRepositoryTest.kt
+++ b/core-data/src/test/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstAuthorsRepositoryTest.kt
@@ -62,7 +62,6 @@ class OfflineFirstAuthorsRepositoryTest {
subject = OfflineFirstAuthorsRepository(
authorDao = authorDao,
network = network,
- niaPreferences = niaPreferencesDataSource,
)
}
diff --git a/core-data/src/test/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstTopicsRepositoryTest.kt b/core-data/src/test/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstTopicsRepositoryTest.kt
index 9481af62f..48570d5f0 100644
--- a/core-data/src/test/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstTopicsRepositoryTest.kt
+++ b/core-data/src/test/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstTopicsRepositoryTest.kt
@@ -62,8 +62,7 @@ class OfflineFirstTopicsRepositoryTest {
subject = OfflineFirstTopicsRepository(
topicDao = topicDao,
- network = network,
- niaPreferences = niaPreferences
+ network = network
)
}
@@ -79,17 +78,6 @@ class OfflineFirstTopicsRepositoryTest {
)
}
- @Test
- fun offlineFirstTopicsRepository_news_resources_for_interests_is_backed_by_news_resource_dao() =
- runTest {
- Assert.assertEquals(
- niaPreferences.followedTopicIds
- .first(),
- subject.getFollowedTopicIdsStream()
- .first()
- )
- }
-
@Test
fun offlineFirstTopicsRepository_sync_pulls_from_network() =
runTest {
@@ -183,50 +171,4 @@ class OfflineFirstTopicsRepositoryTest {
synchronizer.getChangeListVersions().topicVersion
)
}
-
- @Test
- fun offlineFirstTopicsRepository_toggle_followed_topics_logic_delegates_to_nia_preferences() =
- runTest {
- subject.toggleFollowedTopicId(followedTopicId = "0", followed = true)
-
- Assert.assertEquals(
- setOf("0"),
- subject.getFollowedTopicIdsStream()
- .first()
- )
-
- subject.toggleFollowedTopicId(followedTopicId = "1", followed = true)
-
- Assert.assertEquals(
- setOf("0", "1"),
- subject.getFollowedTopicIdsStream()
- .first()
- )
-
- Assert.assertEquals(
- niaPreferences.followedTopicIds
- .first(),
- subject.getFollowedTopicIdsStream()
- .first()
- )
- }
-
- @Test
- fun offlineFirstTopicsRepository_set_followed_topics_logic_delegates_to_nia_preferences() =
- runTest {
- subject.setFollowedTopicIds(followedTopicIds = setOf("1", "2"))
-
- Assert.assertEquals(
- setOf("1", "2"),
- subject.getFollowedTopicIdsStream()
- .first()
- )
-
- Assert.assertEquals(
- niaPreferences.followedTopicIds
- .first(),
- subject.getFollowedTopicIdsStream()
- .first()
- )
- }
}
diff --git a/core-data/src/test/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstUserDataRepositoryTest.kt b/core-data/src/test/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstUserDataRepositoryTest.kt
new file mode 100644
index 000000000..08e5294c6
--- /dev/null
+++ b/core-data/src/test/java/com/google/samples/apps/nowinandroid/core/data/repository/OfflineFirstUserDataRepositoryTest.kt
@@ -0,0 +1,99 @@
+/*
+ * 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.data.repository
+
+import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferencesDataSource
+import com.google.samples.apps.nowinandroid.core.datastore.test.testUserPreferencesDataStore
+import kotlinx.coroutines.flow.first
+import kotlinx.coroutines.flow.map
+import kotlinx.coroutines.test.runTest
+import org.junit.Assert.assertEquals
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.rules.TemporaryFolder
+
+class OfflineFirstUserDataRepositoryTest {
+ private lateinit var subject: OfflineFirstUserDataRepository
+
+ private lateinit var niaPreferencesDataSource: NiaPreferencesDataSource
+
+ @get:Rule
+ val tmpFolder: TemporaryFolder = TemporaryFolder.builder().assureDeletion().build()
+
+ @Before
+ fun setup() {
+ niaPreferencesDataSource = NiaPreferencesDataSource(
+ tmpFolder.testUserPreferencesDataStore()
+ )
+
+ subject = OfflineFirstUserDataRepository(
+ niaPreferencesDataSource = niaPreferencesDataSource
+ )
+ }
+
+ @Test
+ fun offlineFirstTopicsRepository_toggle_followed_topics_logic_delegates_to_nia_preferences() =
+ runTest {
+ subject.toggleFollowedTopicId(followedTopicId = "0", followed = true)
+
+ assertEquals(
+ setOf("0"),
+ subject.userDataStream
+ .map { it.followedTopics }
+ .first()
+ )
+
+ subject.toggleFollowedTopicId(followedTopicId = "1", followed = true)
+
+ assertEquals(
+ setOf("0", "1"),
+ subject.userDataStream
+ .map { it.followedTopics }
+ .first()
+ )
+
+ assertEquals(
+ niaPreferencesDataSource.followedTopicIds
+ .first(),
+ subject.userDataStream
+ .map { it.followedTopics }
+ .first()
+ )
+ }
+
+ @Test
+ fun offlineFirstTopicsRepository_set_followed_topics_logic_delegates_to_nia_preferences() =
+ runTest {
+ subject.setFollowedTopicIds(followedTopicIds = setOf("1", "2"))
+
+ assertEquals(
+ setOf("1", "2"),
+ subject.userDataStream
+ .map { it.followedTopics }
+ .first()
+ )
+
+ assertEquals(
+ niaPreferencesDataSource.followedTopicIds
+ .first(),
+ subject.userDataStream
+ .map { it.followedTopics }
+ .first()
+ )
+ }
+}
diff --git a/core-datastore/build.gradle.kts b/core-datastore/build.gradle.kts
index 52d7ebc7b..033005aa8 100644
--- a/core-datastore/build.gradle.kts
+++ b/core-datastore/build.gradle.kts
@@ -57,6 +57,7 @@ protobuf {
dependencies {
implementation(project(":core-common"))
+ implementation(project(":core-model"))
testImplementation(project(":core-testing"))
diff --git a/core-datastore/src/main/java/com/google/samples/apps/nowinandroid/core/datastore/NiaPreferencesDataSource.kt b/core-datastore/src/main/java/com/google/samples/apps/nowinandroid/core/datastore/NiaPreferencesDataSource.kt
index 938e85af6..8ce1fb3ee 100644
--- a/core-datastore/src/main/java/com/google/samples/apps/nowinandroid/core/datastore/NiaPreferencesDataSource.kt
+++ b/core-datastore/src/main/java/com/google/samples/apps/nowinandroid/core/datastore/NiaPreferencesDataSource.kt
@@ -18,6 +18,7 @@ package com.google.samples.apps.nowinandroid.core.datastore
import android.util.Log
import androidx.datastore.core.DataStore
+import com.google.samples.apps.nowinandroid.core.model.data.UserData
import java.io.IOException
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -143,4 +144,13 @@ class NiaPreferencesDataSource @Inject constructor(
true
}
.map { it.followedAuthorIdsList.toSet() }
+
+ val userDataStream = userPreferences.data
+ .map {
+ UserData(
+ bookmarkedNewsResources = emptySet(),
+ followedTopics = it.followedTopicIdsList.toSet(),
+ followedAuthors = it.followedAuthorIdsList.toSet(),
+ )
+ }
}
diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/UserData.kt b/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/UserData.kt
new file mode 100644
index 000000000..4535a14b4
--- /dev/null
+++ b/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/UserData.kt
@@ -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.
+ */
+
+package com.google.samples.apps.nowinandroid.core.model.data
+
+/**
+ * Class summarizing user interest data
+ */
+data class UserData(
+ val bookmarkedNewsResources: Set,
+ val followedTopics: Set,
+ val followedAuthors: Set,
+)
diff --git a/core-testing/src/main/java/com/google/samples/apps/nowinandroid/core/testing/repository/TestAuthorsRepository.kt b/core-testing/src/main/java/com/google/samples/apps/nowinandroid/core/testing/repository/TestAuthorsRepository.kt
index c3f69d921..13d01e480 100644
--- a/core-testing/src/main/java/com/google/samples/apps/nowinandroid/core/testing/repository/TestAuthorsRepository.kt
+++ b/core-testing/src/main/java/com/google/samples/apps/nowinandroid/core/testing/repository/TestAuthorsRepository.kt
@@ -25,12 +25,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.map
class TestAuthorsRepository : AuthorsRepository {
- /**
- * The backing hot flow for the list of followed author ids for testing.
- */
- private val _followedAuthorIds: MutableSharedFlow> =
- MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
-
/**
* The backing hot flow for the list of author ids for testing.
*/
@@ -43,21 +37,6 @@ class TestAuthorsRepository : AuthorsRepository {
return authorsFlow.map { authors -> authors.find { it.id == id }!! }
}
- override fun getFollowedAuthorIdsStream(): Flow> = _followedAuthorIds
-
- override suspend fun setFollowedAuthorIds(followedAuthorIds: Set) {
- _followedAuthorIds.tryEmit(followedAuthorIds)
- }
-
- override suspend fun toggleFollowedAuthorId(followedAuthorId: String, followed: Boolean) {
- getCurrentFollowedAuthors()?.let { current ->
- _followedAuthorIds.tryEmit(
- if (followed) current.plus(followedAuthorId)
- else current.minus(followedAuthorId)
- )
- }
- }
-
override suspend fun syncWith(synchronizer: Synchronizer) = true
/**
@@ -66,9 +45,4 @@ class TestAuthorsRepository : AuthorsRepository {
fun sendAuthors(authors: List) {
authorsFlow.tryEmit(authors)
}
-
- /**
- * A test-only API to allow querying the current followed authors.
- */
- fun getCurrentFollowedAuthors(): Set? = _followedAuthorIds.replayCache.firstOrNull()
}
diff --git a/core-testing/src/main/java/com/google/samples/apps/nowinandroid/core/testing/repository/TestTopicsRepository.kt b/core-testing/src/main/java/com/google/samples/apps/nowinandroid/core/testing/repository/TestTopicsRepository.kt
index 262c9687e..3aa064a2d 100644
--- a/core-testing/src/main/java/com/google/samples/apps/nowinandroid/core/testing/repository/TestTopicsRepository.kt
+++ b/core-testing/src/main/java/com/google/samples/apps/nowinandroid/core/testing/repository/TestTopicsRepository.kt
@@ -25,12 +25,6 @@ import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.map
class TestTopicsRepository : TopicsRepository {
- /**
- * The backing hot flow for the list of followed topic ids for testing.
- */
- private val _followedTopicIds: MutableSharedFlow> =
- MutableSharedFlow(replay = 1, onBufferOverflow = BufferOverflow.DROP_OLDEST)
-
/**
* The backing hot flow for the list of topics ids for testing.
*/
@@ -43,21 +37,6 @@ class TestTopicsRepository : TopicsRepository {
return topicsFlow.map { topics -> topics.find { it.id == id }!! }
}
- override suspend fun setFollowedTopicIds(followedTopicIds: Set) {
- _followedTopicIds.tryEmit(followedTopicIds)
- }
-
- override suspend fun toggleFollowedTopicId(followedTopicId: String, followed: Boolean) {
- getCurrentFollowedTopics()?.let { current ->
- _followedTopicIds.tryEmit(
- if (followed) current.plus(followedTopicId)
- else current.minus(followedTopicId)
- )
- }
- }
-
- override fun getFollowedTopicIdsStream(): Flow> = _followedTopicIds
-
/**
* A test-only API to allow controlling the list of topics from tests.
*/
@@ -65,10 +44,5 @@ class TestTopicsRepository : TopicsRepository {
topicsFlow.tryEmit(topics)
}
- /**
- * A test-only API to allow querying the current followed topics.
- */
- fun getCurrentFollowedTopics(): Set? = _followedTopicIds.replayCache.firstOrNull()
-
override suspend fun syncWith(synchronizer: Synchronizer) = true
}
diff --git a/core-testing/src/main/java/com/google/samples/apps/nowinandroid/core/testing/repository/TestUserDataRepository.kt b/core-testing/src/main/java/com/google/samples/apps/nowinandroid/core/testing/repository/TestUserDataRepository.kt
new file mode 100644
index 000000000..1cffbb369
--- /dev/null
+++ b/core-testing/src/main/java/com/google/samples/apps/nowinandroid/core/testing/repository/TestUserDataRepository.kt
@@ -0,0 +1,79 @@
+/*
+ * 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.testing.repository
+
+import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
+import com.google.samples.apps.nowinandroid.core.model.data.UserData
+import kotlinx.coroutines.channels.BufferOverflow.DROP_OLDEST
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.filterNotNull
+
+private val emptyUserData = UserData(
+ bookmarkedNewsResources = emptySet(),
+ followedTopics = emptySet(),
+ followedAuthors = emptySet()
+)
+
+class TestUserDataRepository : UserDataRepository {
+ /**
+ * The backing hot flow for the list of followed topic ids for testing.
+ */
+ private val _userData = MutableSharedFlow(replay = 1, onBufferOverflow = DROP_OLDEST)
+
+ private val currentUserData get() = _userData.replayCache.firstOrNull() ?: emptyUserData
+
+ override val userDataStream: Flow = _userData.filterNotNull()
+
+ override suspend fun setFollowedTopicIds(followedTopicIds: Set) {
+ _userData.tryEmit(currentUserData.copy(followedTopics = followedTopicIds))
+ }
+
+ override suspend fun toggleFollowedTopicId(followedTopicId: String, followed: Boolean) {
+ currentUserData.let { current ->
+ val followedTopics = if (followed) current.followedTopics + followedTopicId
+ else current.followedTopics - followedTopicId
+
+ _userData.tryEmit(current.copy(followedTopics = followedTopics))
+ }
+ }
+
+ override suspend fun setFollowedAuthorIds(followedAuthorIds: Set) {
+ _userData.tryEmit(currentUserData.copy(followedAuthors = followedAuthorIds))
+ }
+
+ override suspend fun toggleFollowedAuthorId(followedAuthorId: String, followed: Boolean) {
+ currentUserData.let { current ->
+ val followedAuthors = if (followed) current.followedAuthors + followedAuthorId
+ else current.followedAuthors - followedAuthorId
+
+ _userData.tryEmit(current.copy(followedAuthors = followedAuthors))
+ }
+ }
+
+ /**
+ * A test-only API to allow querying the current followed topics.
+ */
+ fun getCurrentFollowedTopics(): Set? =
+ _userData.replayCache.firstOrNull()?.followedTopics
+
+ /**
+ * A test-only API to allow querying the current followed authors.
+ */
+ fun getCurrentFollowedAuthors(): Set? =
+ _userData.replayCache.firstOrNull()?.followedAuthors
+}
diff --git a/feature-author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/AuthorViewModel.kt b/feature-author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/AuthorViewModel.kt
index 61329570c..3401c0529 100644
--- a/feature-author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/AuthorViewModel.kt
+++ b/feature-author/src/main/java/com/google/samples/apps/nowinandroid/feature/author/AuthorViewModel.kt
@@ -21,6 +21,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.samples.apps.nowinandroid.core.data.repository.AuthorsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.NewsRepository
+import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
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.NewsResource
@@ -33,13 +34,15 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
@HiltViewModel
class AuthorViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
- private val authorsRepository: AuthorsRepository,
+ private val userDataRepository: UserDataRepository,
+ authorsRepository: AuthorsRepository,
newsRepository: NewsRepository
) : ViewModel() {
@@ -49,7 +52,9 @@ class AuthorViewModel @Inject constructor(
// Observe the followed authors, as they could change over time.
private val followedAuthorIdsStream: Flow>> =
- authorsRepository.getFollowedAuthorIdsStream().asResult()
+ userDataRepository.userDataStream
+ .map { it.followedAuthors }
+ .asResult()
// Observe author information
private val author: Flow> = authorsRepository.getAuthorStream(
@@ -102,7 +107,7 @@ class AuthorViewModel @Inject constructor(
fun followAuthorToggle(followed: Boolean) {
viewModelScope.launch {
- authorsRepository.toggleFollowedAuthorId(authorId, followed)
+ userDataRepository.toggleFollowedAuthorId(authorId, followed)
}
}
}
diff --git a/feature-author/src/test/java/com/google/samples/apps/nowinandroid/feature/author/AuthorViewModelTest.kt b/feature-author/src/test/java/com/google/samples/apps/nowinandroid/feature/author/AuthorViewModelTest.kt
index 01f70c04f..9ab24160b 100644
--- a/feature-author/src/test/java/com/google/samples/apps/nowinandroid/feature/author/AuthorViewModelTest.kt
+++ b/feature-author/src/test/java/com/google/samples/apps/nowinandroid/feature/author/AuthorViewModelTest.kt
@@ -24,6 +24,7 @@ import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType.Video
import com.google.samples.apps.nowinandroid.core.testing.repository.TestAuthorsRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepository
+import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.util.TestDispatcherRule
import com.google.samples.apps.nowinandroid.feature.author.navigation.AuthorDestination
import kotlinx.coroutines.flow.first
@@ -40,6 +41,7 @@ class AuthorViewModelTest {
@get:Rule
val dispatcherRule = TestDispatcherRule()
+ private val userDataRepository = TestUserDataRepository()
private val authorsRepository = TestAuthorsRepository()
private val newsRepository = TestNewsRepository()
private lateinit var viewModel: AuthorViewModel
@@ -52,6 +54,7 @@ class AuthorViewModelTest {
AuthorDestination.authorIdArg to testInputAuthors[0].author.id
)
),
+ userDataRepository = userDataRepository,
authorsRepository = authorsRepository,
newsRepository = newsRepository
)
@@ -63,7 +66,7 @@ class AuthorViewModelTest {
awaitItem()
// To make sure AuthorUiState is success
authorsRepository.sendAuthors(testInputAuthors.map(FollowableAuthor::author))
- authorsRepository.setFollowedAuthorIds(setOf(testInputAuthors[1].author.id))
+ userDataRepository.setFollowedAuthorIds(setOf(testInputAuthors[1].author.id))
val item = awaitItem()
assertTrue(item.authorState is AuthorUiState.Success)
@@ -95,7 +98,7 @@ class AuthorViewModelTest {
@Test
fun uiStateAuthor_whenFollowedIdsSuccessAndAuthorLoading_thenShowLoading() = runTest {
viewModel.uiState.test {
- authorsRepository.setFollowedAuthorIds(setOf(testInputAuthors[1].author.id))
+ userDataRepository.setFollowedAuthorIds(setOf(testInputAuthors[1].author.id))
assertEquals(AuthorUiState.Loading, awaitItem().authorState)
}
}
@@ -106,7 +109,7 @@ class AuthorViewModelTest {
viewModel.uiState.test {
awaitItem()
authorsRepository.sendAuthors(testInputAuthors.map { it.author })
- authorsRepository.setFollowedAuthorIds(setOf(testInputAuthors[1].author.id))
+ userDataRepository.setFollowedAuthorIds(setOf(testInputAuthors[1].author.id))
val item = awaitItem()
assertTrue(item.authorState is AuthorUiState.Success)
assertTrue(item.newsState is NewsUiState.Loading)
@@ -119,7 +122,7 @@ class AuthorViewModelTest {
viewModel.uiState.test {
awaitItem()
authorsRepository.sendAuthors(testInputAuthors.map { it.author })
- authorsRepository.setFollowedAuthorIds(setOf(testInputAuthors[1].author.id))
+ userDataRepository.setFollowedAuthorIds(setOf(testInputAuthors[1].author.id))
newsRepository.sendNewsResources(sampleNewsResources)
val item = awaitItem()
assertTrue(item.authorState is AuthorUiState.Success)
@@ -134,7 +137,7 @@ class AuthorViewModelTest {
awaitItem()
authorsRepository.sendAuthors(testInputAuthors.map { it.author })
// Set which author IDs are followed, not including 0.
- authorsRepository.setFollowedAuthorIds(setOf(testInputAuthors[1].author.id))
+ userDataRepository.setFollowedAuthorIds(setOf(testInputAuthors[1].author.id))
viewModel.followAuthorToggle(true)
diff --git a/feature-foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModel.kt b/feature-foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModel.kt
index f7e36c430..8f7a424f2 100644
--- a/feature-foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModel.kt
+++ b/feature-foryou/src/main/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModel.kt
@@ -27,6 +27,7 @@ import androidx.lifecycle.viewmodel.compose.saveable
import com.google.samples.apps.nowinandroid.core.data.repository.AuthorsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.NewsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
+import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
import com.google.samples.apps.nowinandroid.core.model.data.FollowableAuthor
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
@@ -51,26 +52,25 @@ import kotlinx.coroutines.launch
@OptIn(SavedStateHandleSaveableApi::class)
@HiltViewModel
class ForYouViewModel @Inject constructor(
- private val authorsRepository: AuthorsRepository,
- private val topicsRepository: TopicsRepository,
+ authorsRepository: AuthorsRepository,
+ topicsRepository: TopicsRepository,
private val newsRepository: NewsRepository,
+ private val userDataRepository: UserDataRepository,
savedStateHandle: SavedStateHandle
) : ViewModel() {
private val followedInterestsState: StateFlow =
- combine(
- authorsRepository.getFollowedAuthorIdsStream(),
- topicsRepository.getFollowedTopicIdsStream(),
- ) { followedAuthors, followedTopics ->
- if (followedAuthors.isEmpty() && followedTopics.isEmpty()) {
- None
- } else {
- FollowedInterests(
- authorIds = followedAuthors,
- topicIds = followedTopics
- )
+ userDataRepository.userDataStream
+ .map { userData ->
+ if (userData.followedAuthors.isEmpty() && userData.followedTopics.isEmpty()) {
+ None
+ } else {
+ FollowedInterests(
+ authorIds = userData.followedAuthors,
+ topicIds = userData.followedTopics
+ )
+ }
}
- }
.stateIn(
scope = viewModelScope,
started = SharingStarted.WhileSubscribed(5_000),
@@ -232,8 +232,8 @@ class ForYouViewModel @Inject constructor(
}
viewModelScope.launch {
- topicsRepository.setFollowedTopicIds(inProgressTopicSelection)
- authorsRepository.setFollowedAuthorIds(inProgressAuthorSelection)
+ userDataRepository.setFollowedTopicIds(inProgressTopicSelection)
+ userDataRepository.setFollowedAuthorIds(inProgressAuthorSelection)
// Clear out the old selection, in case we return to onboarding
withMutableSnapshot {
inProgressTopicSelection = emptySet()
diff --git a/feature-foryou/src/test/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModelTest.kt b/feature-foryou/src/test/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModelTest.kt
index 89ec4f8c0..dba50dccb 100644
--- a/feature-foryou/src/test/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModelTest.kt
+++ b/feature-foryou/src/test/java/com/google/samples/apps/nowinandroid/feature/foryou/ForYouViewModelTest.kt
@@ -28,6 +28,7 @@ import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.testing.repository.TestAuthorsRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.TestTopicsRepository
+import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.util.TestDispatcherRule
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.test.advanceUntilIdle
@@ -42,6 +43,7 @@ class ForYouViewModelTest {
@get:Rule
val dispatcherRule = TestDispatcherRule()
+ private val userDataRepository = TestUserDataRepository()
private val authorsRepository = TestAuthorsRepository()
private val topicsRepository = TestTopicsRepository()
private val newsRepository = TestNewsRepository()
@@ -50,6 +52,7 @@ class ForYouViewModelTest {
@Before
fun setup() {
viewModel = ForYouViewModel(
+ userDataRepository = userDataRepository,
authorsRepository = authorsRepository,
topicsRepository = topicsRepository,
newsRepository = newsRepository,
@@ -125,7 +128,7 @@ class ForYouViewModelTest {
),
awaitItem()
)
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
}
}
@@ -139,7 +142,7 @@ class ForYouViewModelTest {
),
awaitItem()
)
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
}
}
@@ -149,9 +152,9 @@ class ForYouViewModelTest {
advanceUntilIdle()
expectMostRecentItem()
topicsRepository.sendTopics(sampleTopics)
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
authorsRepository.sendAuthors(sampleAuthors)
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
advanceUntilIdle()
assertEquals(
@@ -244,8 +247,8 @@ class ForYouViewModelTest {
.test {
topicsRepository.sendTopics(sampleTopics)
authorsRepository.sendAuthors(sampleAuthors)
- topicsRepository.setFollowedTopicIds(emptySet())
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
newsRepository.sendNewsResources(sampleNewsResources)
advanceUntilIdle()
@@ -340,9 +343,9 @@ class ForYouViewModelTest {
advanceUntilIdle()
expectMostRecentItem()
authorsRepository.sendAuthors(sampleAuthors)
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
topicsRepository.sendTopics(sampleTopics)
- topicsRepository.setFollowedTopicIds(setOf("0", "1"))
+ userDataRepository.setFollowedTopicIds(setOf("0", "1"))
assertEquals(
ForYouUiState(
@@ -380,9 +383,9 @@ class ForYouViewModelTest {
advanceUntilIdle()
expectMostRecentItem()
authorsRepository.sendAuthors(sampleAuthors)
- authorsRepository.setFollowedAuthorIds(setOf("0", "1"))
+ userDataRepository.setFollowedAuthorIds(setOf("0", "1"))
topicsRepository.sendTopics(sampleTopics)
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
assertEquals(
ForYouUiState(
@@ -418,9 +421,9 @@ class ForYouViewModelTest {
viewModel.uiState
.test {
topicsRepository.sendTopics(sampleTopics)
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
authorsRepository.sendAuthors(sampleAuthors)
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
newsRepository.sendNewsResources(sampleNewsResources)
advanceUntilIdle()
@@ -686,9 +689,9 @@ class ForYouViewModelTest {
viewModel.uiState
.test {
topicsRepository.sendTopics(sampleTopics)
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
authorsRepository.sendAuthors(sampleAuthors)
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
newsRepository.sendNewsResources(sampleNewsResources)
advanceUntilIdle()
@@ -954,9 +957,9 @@ class ForYouViewModelTest {
viewModel.uiState
.test {
topicsRepository.sendTopics(sampleTopics)
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
authorsRepository.sendAuthors(sampleAuthors)
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
newsRepository.sendNewsResources(sampleNewsResources)
viewModel.updateTopicSelection("1", isChecked = true)
viewModel.updateTopicSelection("1", isChecked = false)
@@ -1051,9 +1054,9 @@ class ForYouViewModelTest {
viewModel.uiState
.test {
topicsRepository.sendTopics(sampleTopics)
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
authorsRepository.sendAuthors(sampleAuthors)
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
newsRepository.sendNewsResources(sampleNewsResources)
viewModel.updateAuthorSelection("1", isChecked = true)
viewModel.updateAuthorSelection("1", isChecked = false)
@@ -1148,9 +1151,9 @@ class ForYouViewModelTest {
viewModel.uiState
.test {
topicsRepository.sendTopics(sampleTopics)
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
authorsRepository.sendAuthors(sampleAuthors)
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
newsRepository.sendNewsResources(sampleNewsResources)
viewModel.updateTopicSelection("1", isChecked = true)
@@ -1179,8 +1182,8 @@ class ForYouViewModelTest {
),
expectMostRecentItem()
)
- assertEquals(setOf("1"), topicsRepository.getCurrentFollowedTopics())
- assertEquals(emptySet(), authorsRepository.getCurrentFollowedAuthors())
+ assertEquals(setOf("1"), userDataRepository.getCurrentFollowedTopics())
+ assertEquals(emptySet(), userDataRepository.getCurrentFollowedAuthors())
}
}
@@ -1189,9 +1192,9 @@ class ForYouViewModelTest {
viewModel.uiState
.test {
topicsRepository.sendTopics(sampleTopics)
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
authorsRepository.sendAuthors(sampleAuthors)
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
newsRepository.sendNewsResources(sampleNewsResources)
viewModel.updateAuthorSelection("0", isChecked = true)
@@ -1216,8 +1219,8 @@ class ForYouViewModelTest {
),
expectMostRecentItem()
)
- assertEquals(emptySet(), topicsRepository.getCurrentFollowedTopics())
- assertEquals(setOf("0"), authorsRepository.getCurrentFollowedAuthors())
+ assertEquals(emptySet(), userDataRepository.getCurrentFollowedTopics())
+ assertEquals(setOf("0"), userDataRepository.getCurrentFollowedAuthors())
}
}
@@ -1226,9 +1229,9 @@ class ForYouViewModelTest {
viewModel.uiState
.test {
topicsRepository.sendTopics(sampleTopics)
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
authorsRepository.sendAuthors(sampleAuthors)
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
newsRepository.sendNewsResources(sampleNewsResources)
viewModel.updateAuthorSelection("1", isChecked = true)
viewModel.updateTopicSelection("1", isChecked = true)
@@ -1258,8 +1261,8 @@ class ForYouViewModelTest {
),
expectMostRecentItem()
)
- assertEquals(setOf("1"), topicsRepository.getCurrentFollowedTopics())
- assertEquals(setOf("1"), authorsRepository.getCurrentFollowedAuthors())
+ assertEquals(setOf("1"), userDataRepository.getCurrentFollowedTopics())
+ assertEquals(setOf("1"), userDataRepository.getCurrentFollowedAuthors())
}
}
@@ -1268,9 +1271,9 @@ class ForYouViewModelTest {
viewModel.uiState
.test {
topicsRepository.sendTopics(sampleTopics)
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
authorsRepository.sendAuthors(sampleAuthors)
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
newsRepository.sendNewsResources(sampleNewsResources)
viewModel.updateTopicSelection("1", isChecked = true)
viewModel.saveFollowedInterests()
@@ -1278,7 +1281,7 @@ class ForYouViewModelTest {
advanceUntilIdle()
expectMostRecentItem()
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
advanceUntilIdle()
assertEquals(
@@ -1371,9 +1374,9 @@ class ForYouViewModelTest {
viewModel.uiState
.test {
topicsRepository.sendTopics(sampleTopics)
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedTopicIds(emptySet())
authorsRepository.sendAuthors(sampleAuthors)
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
newsRepository.sendNewsResources(sampleNewsResources)
viewModel.updateAuthorSelection("1", isChecked = true)
viewModel.saveFollowedInterests()
@@ -1381,7 +1384,7 @@ class ForYouViewModelTest {
advanceUntilIdle()
expectMostRecentItem()
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
advanceUntilIdle()
assertEquals(
@@ -1473,9 +1476,9 @@ class ForYouViewModelTest {
viewModel.uiState
.test {
topicsRepository.sendTopics(sampleTopics)
- topicsRepository.setFollowedTopicIds(setOf("1"))
+ userDataRepository.setFollowedTopicIds(setOf("1"))
authorsRepository.sendAuthors(sampleAuthors)
- authorsRepository.setFollowedAuthorIds(setOf("1"))
+ userDataRepository.setFollowedAuthorIds(setOf("1"))
newsRepository.sendNewsResources(sampleNewsResources)
viewModel.updateNewsResourceSaved("2", true)
diff --git a/feature-interests/src/main/java/com/google/samples/apps/nowinandroid/feature/interests/InterestsViewModel.kt b/feature-interests/src/main/java/com/google/samples/apps/nowinandroid/feature/interests/InterestsViewModel.kt
index f2e419d53..c6c01c3ca 100644
--- a/feature-interests/src/main/java/com/google/samples/apps/nowinandroid/feature/interests/InterestsViewModel.kt
+++ b/feature-interests/src/main/java/com/google/samples/apps/nowinandroid/feature/interests/InterestsViewModel.kt
@@ -20,6 +20,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.samples.apps.nowinandroid.core.data.repository.AuthorsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
+import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
import com.google.samples.apps.nowinandroid.core.model.data.FollowableAuthor
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import dagger.hilt.android.lifecycle.HiltViewModel
@@ -35,8 +36,9 @@ import kotlinx.coroutines.launch
@HiltViewModel
class InterestsViewModel @Inject constructor(
- private val authorsRepository: AuthorsRepository,
- private val topicsRepository: TopicsRepository
+ private val userDataRepository: UserDataRepository,
+ authorsRepository: AuthorsRepository,
+ topicsRepository: TopicsRepository
) : ViewModel() {
private val _tabState = MutableStateFlow(
@@ -48,18 +50,17 @@ class InterestsViewModel @Inject constructor(
val tabState: StateFlow = _tabState.asStateFlow()
val uiState: StateFlow = combine(
+ userDataRepository.userDataStream,
authorsRepository.getAuthorsStream(),
- authorsRepository.getFollowedAuthorIdsStream(),
topicsRepository.getTopicsStream(),
- topicsRepository.getFollowedTopicIdsStream(),
- ) { availableAuthors, followedAuthorIdsState, availableTopics, followedTopicIdsState ->
+ ) { userData, availableAuthors, availableTopics ->
InterestsUiState.Interests(
authors = availableAuthors
.map { author ->
FollowableAuthor(
author = author,
- isFollowed = author.id in followedAuthorIdsState
+ isFollowed = author.id in userData.followedAuthors
)
}
.sortedBy { it.author.name },
@@ -67,7 +68,7 @@ class InterestsViewModel @Inject constructor(
.map { topic ->
FollowableTopic(
topic = topic,
- isFollowed = topic.id in followedTopicIdsState
+ isFollowed = topic.id in userData.followedTopics
)
}
.sortedBy { it.topic.name }
@@ -81,13 +82,13 @@ class InterestsViewModel @Inject constructor(
fun followTopic(followedTopicId: String, followed: Boolean) {
viewModelScope.launch {
- topicsRepository.toggleFollowedTopicId(followedTopicId, followed)
+ userDataRepository.toggleFollowedTopicId(followedTopicId, followed)
}
}
fun followAuthor(followedAuthorId: String, followed: Boolean) {
viewModelScope.launch {
- authorsRepository.toggleFollowedAuthorId(followedAuthorId, followed)
+ userDataRepository.toggleFollowedAuthorId(followedAuthorId, followed)
}
}
diff --git a/feature-interests/src/test/java/com/google/samples/apps/nowinandroid/interests/InterestsViewModelTest.kt b/feature-interests/src/test/java/com/google/samples/apps/nowinandroid/interests/InterestsViewModelTest.kt
index 4902e9b2e..a341f7fd6 100644
--- a/feature-interests/src/test/java/com/google/samples/apps/nowinandroid/interests/InterestsViewModelTest.kt
+++ b/feature-interests/src/test/java/com/google/samples/apps/nowinandroid/interests/InterestsViewModelTest.kt
@@ -23,6 +23,7 @@ import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.testing.repository.TestAuthorsRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.TestTopicsRepository
+import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.util.TestDispatcherRule
import com.google.samples.apps.nowinandroid.feature.interests.InterestsUiState
import com.google.samples.apps.nowinandroid.feature.interests.InterestsViewModel
@@ -37,13 +38,18 @@ class InterestsViewModelTest {
@get:Rule
val dispatcherRule = TestDispatcherRule()
+ private val userDataRepository = TestUserDataRepository()
private val authorsRepository = TestAuthorsRepository()
private val topicsRepository = TestTopicsRepository()
private lateinit var viewModel: InterestsViewModel
@Before
fun setup() {
- viewModel = InterestsViewModel(authorsRepository, topicsRepository)
+ viewModel = InterestsViewModel(
+ userDataRepository = userDataRepository,
+ authorsRepository = authorsRepository,
+ topicsRepository = topicsRepository,
+ )
}
@Test
@@ -57,8 +63,8 @@ class InterestsViewModelTest {
fun uiState_whenFollowedTopicsAreLoading_thenShowLoading() = runTest {
viewModel.uiState.test {
assertEquals(InterestsUiState.Loading, awaitItem())
- authorsRepository.setFollowedAuthorIds(setOf("1"))
- topicsRepository.setFollowedTopicIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(setOf("1"))
+ userDataRepository.setFollowedTopicIds(emptySet())
}
}
@@ -66,8 +72,8 @@ class InterestsViewModelTest {
fun uiState_whenFollowedAuthorsAreLoading_thenShowLoading() = runTest {
viewModel.uiState.test {
assertEquals(InterestsUiState.Loading, awaitItem())
- authorsRepository.setFollowedAuthorIds(emptySet())
- topicsRepository.setFollowedTopicIds(setOf("1"))
+ userDataRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedTopicIds(setOf("1"))
}
}
@@ -78,9 +84,9 @@ class InterestsViewModelTest {
.test {
awaitItem()
authorsRepository.sendAuthors(emptyList())
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
topicsRepository.sendTopics(testInputTopics.map { it.topic })
- topicsRepository.setFollowedTopicIds(setOf(testInputTopics[0].topic.id))
+ userDataRepository.setFollowedTopicIds(setOf(testInputTopics[0].topic.id))
assertEquals(
false,
@@ -106,9 +112,9 @@ class InterestsViewModelTest {
.test {
awaitItem()
authorsRepository.sendAuthors(testInputAuthors.map { it.author })
- authorsRepository.setFollowedAuthorIds(setOf(testInputAuthors[0].author.id))
+ userDataRepository.setFollowedAuthorIds(setOf(testInputAuthors[0].author.id))
topicsRepository.sendTopics(listOf())
- topicsRepository.setFollowedTopicIds(setOf())
+ userDataRepository.setFollowedTopicIds(setOf())
awaitItem()
viewModel.followAuthor(
@@ -130,9 +136,9 @@ class InterestsViewModelTest {
.test {
awaitItem()
authorsRepository.sendAuthors(emptyList())
- authorsRepository.setFollowedAuthorIds(emptySet())
+ userDataRepository.setFollowedAuthorIds(emptySet())
topicsRepository.sendTopics(testOutputTopics.map { it.topic })
- topicsRepository.setFollowedTopicIds(
+ userDataRepository.setFollowedTopicIds(
setOf(testOutputTopics[0].topic.id, testOutputTopics[1].topic.id)
)
@@ -160,11 +166,11 @@ class InterestsViewModelTest {
.test {
awaitItem()
authorsRepository.sendAuthors(testOutputAuthors.map { it.author })
- authorsRepository.setFollowedAuthorIds(
+ userDataRepository.setFollowedAuthorIds(
setOf(testOutputAuthors[0].author.id, testOutputAuthors[1].author.id)
)
topicsRepository.sendTopics(listOf())
- topicsRepository.setFollowedTopicIds(setOf())
+ userDataRepository.setFollowedTopicIds(setOf())
awaitItem()
viewModel.followAuthor(
diff --git a/feature-topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt b/feature-topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt
index 9e1bba01b..d647e4bf7 100644
--- a/feature-topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt
+++ b/feature-topic/src/main/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModel.kt
@@ -21,6 +21,7 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.google.samples.apps.nowinandroid.core.data.repository.NewsRepository
import com.google.samples.apps.nowinandroid.core.data.repository.TopicsRepository
+import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
import com.google.samples.apps.nowinandroid.core.model.data.Topic
@@ -33,13 +34,15 @@ import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch
@HiltViewModel
class TopicViewModel @Inject constructor(
savedStateHandle: SavedStateHandle,
- private val topicsRepository: TopicsRepository,
+ private val userDataRepository: UserDataRepository,
+ topicsRepository: TopicsRepository,
newsRepository: NewsRepository
) : ViewModel() {
@@ -47,7 +50,9 @@ class TopicViewModel @Inject constructor(
// Observe the followed topics, as they could change over time.
private val followedTopicIdsStream: Flow>> =
- topicsRepository.getFollowedTopicIdsStream().asResult()
+ userDataRepository.userDataStream
+ .map { it.followedTopics }
+ .asResult()
// Observe topic information
private val topic: Flow> = topicsRepository.getTopic(topicId).asResult()
@@ -97,7 +102,7 @@ class TopicViewModel @Inject constructor(
fun followTopicToggle(followed: Boolean) {
viewModelScope.launch {
- topicsRepository.toggleFollowedTopicId(topicId, followed)
+ userDataRepository.toggleFollowedTopicId(topicId, followed)
}
}
}
diff --git a/feature-topic/src/test/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModelTest.kt b/feature-topic/src/test/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModelTest.kt
index db340c1f7..bbc183003 100644
--- a/feature-topic/src/test/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModelTest.kt
+++ b/feature-topic/src/test/java/com/google/samples/apps/nowinandroid/feature/topic/TopicViewModelTest.kt
@@ -24,6 +24,7 @@ import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType.Vid
import com.google.samples.apps.nowinandroid.core.model.data.Topic
import com.google.samples.apps.nowinandroid.core.testing.repository.TestNewsRepository
import com.google.samples.apps.nowinandroid.core.testing.repository.TestTopicsRepository
+import com.google.samples.apps.nowinandroid.core.testing.repository.TestUserDataRepository
import com.google.samples.apps.nowinandroid.core.testing.util.TestDispatcherRule
import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicDestination
import kotlinx.coroutines.flow.first
@@ -40,6 +41,7 @@ class TopicViewModelTest {
@get:Rule
val dispatcherRule = TestDispatcherRule()
+ private val userDataRepository = TestUserDataRepository()
private val topicsRepository = TestTopicsRepository()
private val newsRepository = TestNewsRepository()
private lateinit var viewModel: TopicViewModel
@@ -49,6 +51,7 @@ class TopicViewModelTest {
viewModel = TopicViewModel(
savedStateHandle =
SavedStateHandle(mapOf(TopicDestination.topicIdArg to testInputTopics[0].topic.id)),
+ userDataRepository = userDataRepository,
topicsRepository = topicsRepository,
newsRepository = newsRepository
)
@@ -59,7 +62,7 @@ class TopicViewModelTest {
viewModel.uiState.test {
awaitItem()
topicsRepository.sendTopics(testInputTopics.map(FollowableTopic::topic))
- topicsRepository.setFollowedTopicIds(setOf(testInputTopics[1].topic.id))
+ userDataRepository.setFollowedTopicIds(setOf(testInputTopics[1].topic.id))
val item = awaitItem()
assertTrue(item.topicState is TopicUiState.Success)
@@ -89,7 +92,7 @@ class TopicViewModelTest {
@Test
fun uiStateTopic_whenFollowedIdsSuccessAndTopicLoading_thenShowLoading() = runTest {
viewModel.uiState.test {
- topicsRepository.setFollowedTopicIds(setOf(testInputTopics[1].topic.id))
+ userDataRepository.setFollowedTopicIds(setOf(testInputTopics[1].topic.id))
assertEquals(TopicUiState.Loading, awaitItem().topicState)
}
}
@@ -100,7 +103,7 @@ class TopicViewModelTest {
viewModel.uiState.test {
awaitItem()
topicsRepository.sendTopics(testInputTopics.map { it.topic })
- topicsRepository.setFollowedTopicIds(setOf(testInputTopics[1].topic.id))
+ userDataRepository.setFollowedTopicIds(setOf(testInputTopics[1].topic.id))
val item = awaitItem()
assertTrue(item.topicState is TopicUiState.Success)
assertTrue(item.newsState is NewsUiState.Loading)
@@ -113,7 +116,7 @@ class TopicViewModelTest {
viewModel.uiState.test {
awaitItem()
topicsRepository.sendTopics(testInputTopics.map { it.topic })
- topicsRepository.setFollowedTopicIds(setOf(testInputTopics[1].topic.id))
+ userDataRepository.setFollowedTopicIds(setOf(testInputTopics[1].topic.id))
newsRepository.sendNewsResources(sampleNewsResources)
val item = awaitItem()
assertTrue(item.topicState is TopicUiState.Success)
@@ -128,7 +131,7 @@ class TopicViewModelTest {
awaitItem()
topicsRepository.sendTopics(testInputTopics.map { it.topic })
// Set which topic IDs are followed, not including 0.
- topicsRepository.setFollowedTopicIds(setOf(testInputTopics[1].topic.id))
+ userDataRepository.setFollowedTopicIds(setOf(testInputTopics[1].topic.id))
viewModel.followTopicToggle(true)