|
|
|
@ -25,13 +25,15 @@ import com.google.samples.apps.nowinandroid.core.database.model.EpisodeEntity
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.database.model.PopulatedNewsResource
|
|
|
|
|
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.NiaPreferences
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.domain.changeListSync
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.domain.model.asEntity
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.domain.model.authorCrossReferences
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.domain.model.authorEntityShells
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.domain.model.episodeEntityShell
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.domain.model.topicCrossReferences
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.domain.model.topicEntityShells
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.domain.suspendRunCatching
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.model.data.NewsResource
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.network.NiANetwork
|
|
|
|
|
import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource
|
|
|
|
@ -48,6 +50,7 @@ class LocalNewsRepository @Inject constructor(
|
|
|
|
|
private val authorDao: AuthorDao,
|
|
|
|
|
private val topicDao: TopicDao,
|
|
|
|
|
private val network: NiANetwork,
|
|
|
|
|
private val niaPreferences: NiaPreferences,
|
|
|
|
|
) : NewsRepository {
|
|
|
|
|
|
|
|
|
|
override fun getNewsResourcesStream(): Flow<List<NewsResource>> =
|
|
|
|
@ -58,44 +61,53 @@ class LocalNewsRepository @Inject constructor(
|
|
|
|
|
newsResourceDao.getNewsResourcesStream(filterTopicIds = filterTopicIds)
|
|
|
|
|
.map { it.map(PopulatedNewsResource::asExternalModel) }
|
|
|
|
|
|
|
|
|
|
// TODO: Pass change list for incremental sync. See b/227206738
|
|
|
|
|
override suspend fun sync() = suspendRunCatching {
|
|
|
|
|
val networkNewsResources = network.getNewsResources()
|
|
|
|
|
override suspend fun sync() = changeListSync(
|
|
|
|
|
niaPreferences = niaPreferences,
|
|
|
|
|
versionReader = ChangeListVersions::newsResourceVersion,
|
|
|
|
|
changeListFetcher = { currentVersion ->
|
|
|
|
|
network.getNewsResourceChangeList(after = currentVersion)
|
|
|
|
|
},
|
|
|
|
|
versionUpdater = { latestVersion ->
|
|
|
|
|
copy(newsResourceVersion = latestVersion)
|
|
|
|
|
},
|
|
|
|
|
modelUpdater = { changedIds ->
|
|
|
|
|
val networkNewsResources = network.getNewsResources(ids = changedIds)
|
|
|
|
|
|
|
|
|
|
// Order of invocation matters to satisfy id and foreign key constraints!
|
|
|
|
|
// Order of invocation matters to satisfy id and foreign key constraints!
|
|
|
|
|
|
|
|
|
|
topicDao.insertOrIgnoreTopics(
|
|
|
|
|
topicEntities = networkNewsResources
|
|
|
|
|
.map(NetworkNewsResource::topicEntityShells)
|
|
|
|
|
.flatten()
|
|
|
|
|
.distinctBy(TopicEntity::id)
|
|
|
|
|
)
|
|
|
|
|
authorDao.insertOrIgnoreAuthors(
|
|
|
|
|
authorEntities = networkNewsResources
|
|
|
|
|
.map(NetworkNewsResource::authorEntityShells)
|
|
|
|
|
.flatten()
|
|
|
|
|
.distinctBy(AuthorEntity::id)
|
|
|
|
|
)
|
|
|
|
|
episodeDao.insertOrIgnoreEpisodes(
|
|
|
|
|
episodeEntities = networkNewsResources
|
|
|
|
|
.map(NetworkNewsResource::episodeEntityShell)
|
|
|
|
|
.distinctBy(EpisodeEntity::id)
|
|
|
|
|
)
|
|
|
|
|
newsResourceDao.upsertNewsResources(
|
|
|
|
|
newsResourceEntities = networkNewsResources
|
|
|
|
|
.map(NetworkNewsResource::asEntity)
|
|
|
|
|
)
|
|
|
|
|
newsResourceDao.insertOrIgnoreTopicCrossRefEntities(
|
|
|
|
|
newsResourceTopicCrossReferences = networkNewsResources
|
|
|
|
|
.map(NetworkNewsResource::topicCrossReferences)
|
|
|
|
|
.distinct()
|
|
|
|
|
.flatten()
|
|
|
|
|
)
|
|
|
|
|
newsResourceDao.insertOrIgnoreAuthorCrossRefEntities(
|
|
|
|
|
newsResourceAuthorCrossReferences = networkNewsResources
|
|
|
|
|
.map(NetworkNewsResource::authorCrossReferences)
|
|
|
|
|
.distinct()
|
|
|
|
|
.flatten()
|
|
|
|
|
)
|
|
|
|
|
}.isSuccess
|
|
|
|
|
topicDao.insertOrIgnoreTopics(
|
|
|
|
|
topicEntities = networkNewsResources
|
|
|
|
|
.map(NetworkNewsResource::topicEntityShells)
|
|
|
|
|
.flatten()
|
|
|
|
|
.distinctBy(TopicEntity::id)
|
|
|
|
|
)
|
|
|
|
|
authorDao.insertOrIgnoreAuthors(
|
|
|
|
|
authorEntities = networkNewsResources
|
|
|
|
|
.map(NetworkNewsResource::authorEntityShells)
|
|
|
|
|
.flatten()
|
|
|
|
|
.distinctBy(AuthorEntity::id)
|
|
|
|
|
)
|
|
|
|
|
episodeDao.insertOrIgnoreEpisodes(
|
|
|
|
|
episodeEntities = networkNewsResources
|
|
|
|
|
.map(NetworkNewsResource::episodeEntityShell)
|
|
|
|
|
.distinctBy(EpisodeEntity::id)
|
|
|
|
|
)
|
|
|
|
|
newsResourceDao.upsertNewsResources(
|
|
|
|
|
newsResourceEntities = networkNewsResources
|
|
|
|
|
.map(NetworkNewsResource::asEntity)
|
|
|
|
|
)
|
|
|
|
|
newsResourceDao.insertOrIgnoreTopicCrossRefEntities(
|
|
|
|
|
newsResourceTopicCrossReferences = networkNewsResources
|
|
|
|
|
.map(NetworkNewsResource::topicCrossReferences)
|
|
|
|
|
.distinct()
|
|
|
|
|
.flatten()
|
|
|
|
|
)
|
|
|
|
|
newsResourceDao.insertOrIgnoreAuthorCrossRefEntities(
|
|
|
|
|
newsResourceAuthorCrossReferences = networkNewsResources
|
|
|
|
|
.map(NetworkNewsResource::authorCrossReferences)
|
|
|
|
|
.distinct()
|
|
|
|
|
.flatten()
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|