Merge pull request #595 from android/jr/track-viewed
Add visual indicator of read/unread news resourcespull/674/head
commit
3e66e3d7e8
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.data.di
|
||||
|
||||
import com.google.samples.apps.nowinandroid.core.data.repository.CompositeUserNewsResourceRepository
|
||||
import com.google.samples.apps.nowinandroid.core.data.repository.UserNewsResourceRepository
|
||||
import dagger.Binds
|
||||
import dagger.Module
|
||||
import dagger.hilt.InstallIn
|
||||
import dagger.hilt.components.SingletonComponent
|
||||
|
||||
@Module
|
||||
@InstallIn(SingletonComponent::class)
|
||||
interface UserNewsResourceRepositoryModule {
|
||||
@Binds
|
||||
fun bindsUserNewsResourceRepository(
|
||||
userDataRepository: CompositeUserNewsResourceRepository,
|
||||
): UserNewsResourceRepository
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.data.repository
|
||||
|
||||
import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource
|
||||
import com.google.samples.apps.nowinandroid.core.model.data.mapToUserNewsResources
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import kotlinx.coroutines.flow.flatMapLatest
|
||||
import kotlinx.coroutines.flow.flowOf
|
||||
import kotlinx.coroutines.flow.map
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* Implements a [UserNewsResourceRepository] by combining a [NewsRepository] with a
|
||||
* [UserDataRepository].
|
||||
*/
|
||||
class CompositeUserNewsResourceRepository @Inject constructor(
|
||||
val newsRepository: NewsRepository,
|
||||
val userDataRepository: UserDataRepository,
|
||||
) : UserNewsResourceRepository {
|
||||
|
||||
/**
|
||||
* Returns available news resources (joined with user data) matching the given query.
|
||||
*/
|
||||
override fun observeAll(
|
||||
query: NewsResourceQuery,
|
||||
): Flow<List<UserNewsResource>> =
|
||||
newsRepository.getNewsResources(query)
|
||||
.combine(userDataRepository.userData) { newsResources, userData ->
|
||||
newsResources.mapToUserNewsResources(userData)
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns available news resources (joined with user data) for the followed topics.
|
||||
*/
|
||||
override fun observeAllForFollowedTopics(): Flow<List<UserNewsResource>> =
|
||||
userDataRepository.userData.map { it.followedTopics }.distinctUntilChanged()
|
||||
.flatMapLatest { followedTopics ->
|
||||
when {
|
||||
followedTopics.isEmpty() -> flowOf(emptyList())
|
||||
else -> observeAll(NewsResourceQuery(filterTopicIds = followedTopics))
|
||||
}
|
||||
}
|
||||
|
||||
override fun observeAllBookmarked(): Flow<List<UserNewsResource>> =
|
||||
userDataRepository.userData.map { it.bookmarkedNewsResources }.distinctUntilChanged()
|
||||
.flatMapLatest { bookmarkedNewsResources ->
|
||||
when {
|
||||
bookmarkedNewsResources.isEmpty() -> flowOf(emptyList())
|
||||
else -> observeAll(NewsResourceQuery(filterNewsIds = bookmarkedNewsResources))
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package com.google.samples.apps.nowinandroid.core.data.repository
|
||||
|
||||
import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
|
||||
/**
|
||||
* Data layer implementation for [UserNewsResource]
|
||||
*/
|
||||
interface UserNewsResourceRepository {
|
||||
/**
|
||||
* Returns available news resources as a stream.
|
||||
*/
|
||||
fun observeAll(
|
||||
query: NewsResourceQuery = NewsResourceQuery(
|
||||
filterTopicIds = null,
|
||||
filterNewsIds = null,
|
||||
),
|
||||
): Flow<List<UserNewsResource>>
|
||||
|
||||
/**
|
||||
* Returns available news resources for the user's followed topics as a stream.
|
||||
*/
|
||||
fun observeAllForFollowedTopics(): Flow<List<UserNewsResource>>
|
||||
|
||||
/**
|
||||
* Returns the user's bookmarked news resources as a stream.
|
||||
*/
|
||||
fun observeAllBookmarked(): Flow<List<UserNewsResource>>
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
/*
|
||||
* 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.domain
|
||||
|
||||
import com.google.samples.apps.nowinandroid.core.data.repository.NewsRepository
|
||||
import com.google.samples.apps.nowinandroid.core.data.repository.NewsResourceQuery
|
||||
import com.google.samples.apps.nowinandroid.core.data.repository.UserDataRepository
|
||||
import com.google.samples.apps.nowinandroid.core.domain.model.UserNewsResource
|
||||
import com.google.samples.apps.nowinandroid.core.domain.model.mapToUserNewsResources
|
||||
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
|
||||
import com.google.samples.apps.nowinandroid.core.model.data.UserData
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.combine
|
||||
import kotlinx.coroutines.flow.filterNot
|
||||
import javax.inject.Inject
|
||||
|
||||
/**
|
||||
* A use case responsible for obtaining news resources with their associated bookmarked (also known
|
||||
* as "saved") state.
|
||||
*/
|
||||
class GetUserNewsResourcesUseCase @Inject constructor(
|
||||
private val newsRepository: NewsRepository,
|
||||
private val userDataRepository: UserDataRepository,
|
||||
) {
|
||||
/**
|
||||
* Returns a list of UserNewsResources which match the supplied set of topic ids.
|
||||
*
|
||||
* @param query - Summary of query parameters for news resources.
|
||||
*/
|
||||
operator fun invoke(
|
||||
query: NewsResourceQuery = NewsResourceQuery(),
|
||||
): Flow<List<UserNewsResource>> =
|
||||
newsRepository.getNewsResources(
|
||||
query = query,
|
||||
).mapToUserNewsResources(userDataRepository.userData)
|
||||
}
|
||||
|
||||
private fun Flow<List<NewsResource>>.mapToUserNewsResources(
|
||||
userDataStream: Flow<UserData>,
|
||||
): Flow<List<UserNewsResource>> =
|
||||
filterNot { it.isEmpty() }
|
||||
.combine(userDataStream) { newsResources, userData ->
|
||||
newsResources.mapToUserNewsResources(userData)
|
||||
}
|
Loading…
Reference in new issue