|
|
@ -27,16 +27,18 @@ import com.google.samples.apps.nowinandroid.core.domain.model.FollowableTopic
|
|
|
|
import com.google.samples.apps.nowinandroid.core.domain.model.SaveableNewsResource
|
|
|
|
import com.google.samples.apps.nowinandroid.core.domain.model.SaveableNewsResource
|
|
|
|
import com.google.samples.apps.nowinandroid.core.model.data.Topic
|
|
|
|
import com.google.samples.apps.nowinandroid.core.model.data.Topic
|
|
|
|
import com.google.samples.apps.nowinandroid.core.result.Result
|
|
|
|
import com.google.samples.apps.nowinandroid.core.result.Result
|
|
|
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.result.Result.Error
|
|
|
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.result.Result.Loading
|
|
|
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.result.Result.Success
|
|
|
|
import com.google.samples.apps.nowinandroid.core.result.asResult
|
|
|
|
import com.google.samples.apps.nowinandroid.core.result.asResult
|
|
|
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.ui.stateInViewModelScope
|
|
|
|
import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicArgs
|
|
|
|
import com.google.samples.apps.nowinandroid.feature.topic.navigation.TopicArgs
|
|
|
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
|
|
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
|
|
|
import javax.inject.Inject
|
|
|
|
import javax.inject.Inject
|
|
|
|
import kotlinx.coroutines.flow.Flow
|
|
|
|
import kotlinx.coroutines.flow.Flow
|
|
|
|
import kotlinx.coroutines.flow.SharingStarted
|
|
|
|
|
|
|
|
import kotlinx.coroutines.flow.StateFlow
|
|
|
|
import kotlinx.coroutines.flow.StateFlow
|
|
|
|
import kotlinx.coroutines.flow.combine
|
|
|
|
import kotlinx.coroutines.flow.combine
|
|
|
|
import kotlinx.coroutines.flow.map
|
|
|
|
import kotlinx.coroutines.flow.map
|
|
|
|
import kotlinx.coroutines.flow.stateIn
|
|
|
|
|
|
|
|
import kotlinx.coroutines.launch
|
|
|
|
import kotlinx.coroutines.launch
|
|
|
|
|
|
|
|
|
|
|
|
@HiltViewModel
|
|
|
|
@HiltViewModel
|
|
|
@ -45,7 +47,6 @@ class TopicViewModel @Inject constructor(
|
|
|
|
stringDecoder: StringDecoder,
|
|
|
|
stringDecoder: StringDecoder,
|
|
|
|
private val userDataRepository: UserDataRepository,
|
|
|
|
private val userDataRepository: UserDataRepository,
|
|
|
|
topicsRepository: TopicsRepository,
|
|
|
|
topicsRepository: TopicsRepository,
|
|
|
|
// newsRepository: NewsRepository,
|
|
|
|
|
|
|
|
getSaveableNewsResourcesStream: GetSaveableNewsResourcesStreamUseCase
|
|
|
|
getSaveableNewsResourcesStream: GetSaveableNewsResourcesStreamUseCase
|
|
|
|
) : ViewModel() {
|
|
|
|
) : ViewModel() {
|
|
|
|
|
|
|
|
|
|
|
@ -55,36 +56,22 @@ class TopicViewModel @Inject constructor(
|
|
|
|
topicId = topicArgs.topicId,
|
|
|
|
topicId = topicArgs.topicId,
|
|
|
|
userDataRepository = userDataRepository,
|
|
|
|
userDataRepository = userDataRepository,
|
|
|
|
topicsRepository = topicsRepository
|
|
|
|
topicsRepository = topicsRepository
|
|
|
|
)
|
|
|
|
).stateInViewModelScope(viewModelScope, initialValue = TopicUiState.Loading)
|
|
|
|
.stateIn(
|
|
|
|
|
|
|
|
scope = viewModelScope,
|
|
|
|
|
|
|
|
started = SharingStarted.WhileSubscribed(5_000),
|
|
|
|
|
|
|
|
initialValue = TopicUiState.Loading
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val newUiState: StateFlow<NewsUiState> = newsUiStateStream(
|
|
|
|
val newUiState: StateFlow<NewsUiState> = newsUiStateStream(
|
|
|
|
topicId = topicArgs.topicId,
|
|
|
|
topicId = topicArgs.topicId,
|
|
|
|
userDataRepository = userDataRepository,
|
|
|
|
userDataRepository = userDataRepository,
|
|
|
|
getSaveableNewsResourcesStream = getSaveableNewsResourcesStream
|
|
|
|
getSaveableNewsResourcesStream = getSaveableNewsResourcesStream
|
|
|
|
)
|
|
|
|
).stateInViewModelScope(viewModelScope, initialValue = NewsUiState.Loading)
|
|
|
|
.stateIn(
|
|
|
|
|
|
|
|
scope = viewModelScope,
|
|
|
|
|
|
|
|
started = SharingStarted.WhileSubscribed(5_000),
|
|
|
|
|
|
|
|
initialValue = NewsUiState.Loading
|
|
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fun followTopicToggle(followed: Boolean) {
|
|
|
|
fun followTopicToggle(followed: Boolean) = viewModelScope.launch {
|
|
|
|
viewModelScope.launch {
|
|
|
|
|
|
|
|
userDataRepository.toggleFollowedTopicId(topicArgs.topicId, followed)
|
|
|
|
userDataRepository.toggleFollowedTopicId(topicArgs.topicId, followed)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fun bookmarkNews(newsResourceId: String, bookmarked: Boolean) {
|
|
|
|
fun bookmarkNews(newsResourceId: String, bookmarked: Boolean) = viewModelScope.launch {
|
|
|
|
viewModelScope.launch {
|
|
|
|
|
|
|
|
userDataRepository.updateNewsResourceBookmark(newsResourceId, bookmarked)
|
|
|
|
userDataRepository.updateNewsResourceBookmark(newsResourceId, bookmarked)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun topicUiStateStream(
|
|
|
|
private fun topicUiStateStream(
|
|
|
|
topicId: String,
|
|
|
|
topicId: String,
|
|
|
@ -92,8 +79,8 @@ private fun topicUiStateStream(
|
|
|
|
topicsRepository: TopicsRepository,
|
|
|
|
topicsRepository: TopicsRepository,
|
|
|
|
): Flow<TopicUiState> {
|
|
|
|
): Flow<TopicUiState> {
|
|
|
|
// Observe the followed topics, as they could change over time.
|
|
|
|
// Observe the followed topics, as they could change over time.
|
|
|
|
val followedTopicIdsStream: Flow<Set<String>> =
|
|
|
|
val followedTopicIdsStream: Flow<Set<String>> = userDataRepository
|
|
|
|
userDataRepository.userDataStream
|
|
|
|
.userDataStream
|
|
|
|
.map { it.followedTopics }
|
|
|
|
.map { it.followedTopics }
|
|
|
|
|
|
|
|
|
|
|
|
// Observe topic information
|
|
|
|
// Observe topic information
|
|
|
@ -108,8 +95,15 @@ private fun topicUiStateStream(
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.asResult()
|
|
|
|
.asResult()
|
|
|
|
.map { followedTopicToTopicResult ->
|
|
|
|
.map { followedTopicToTopicResult ->
|
|
|
|
when (followedTopicToTopicResult) {
|
|
|
|
handleTopicResult(followedTopicToTopicResult, topicId)
|
|
|
|
is Result.Success -> {
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun handleTopicResult(
|
|
|
|
|
|
|
|
followedTopicToTopicResult: Result<Pair<Set<String>, Topic>>,
|
|
|
|
|
|
|
|
topicId: String
|
|
|
|
|
|
|
|
) = when (followedTopicToTopicResult) {
|
|
|
|
|
|
|
|
is Success -> {
|
|
|
|
val (followedTopics, topic) = followedTopicToTopicResult.data
|
|
|
|
val (followedTopics, topic) = followedTopicToTopicResult.data
|
|
|
|
val followed = followedTopics.contains(topicId)
|
|
|
|
val followed = followedTopics.contains(topicId)
|
|
|
|
TopicUiState.Success(
|
|
|
|
TopicUiState.Success(
|
|
|
@ -119,14 +113,8 @@ private fun topicUiStateStream(
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
is Result.Loading -> {
|
|
|
|
is Loading -> TopicUiState.Loading
|
|
|
|
TopicUiState.Loading
|
|
|
|
is Error -> TopicUiState.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
is Result.Error -> {
|
|
|
|
|
|
|
|
TopicUiState.Error
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private fun newsUiStateStream(
|
|
|
|
private fun newsUiStateStream(
|
|
|
@ -156,12 +144,8 @@ private fun newsUiStateStream(
|
|
|
|
val (news, bookmarks) = newsToBookmarksResult.data
|
|
|
|
val (news, bookmarks) = newsToBookmarksResult.data
|
|
|
|
NewsUiState.Success(news)
|
|
|
|
NewsUiState.Success(news)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
is Result.Loading -> {
|
|
|
|
is Result.Loading -> NewsUiState.Loading
|
|
|
|
NewsUiState.Loading
|
|
|
|
is Result.Error -> NewsUiState.Error
|
|
|
|
}
|
|
|
|
|
|
|
|
is Result.Error -> {
|
|
|
|
|
|
|
|
NewsUiState.Error
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|