diff --git a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/NiADatabase.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/NiADatabase.kt index 7494c4c44..9b5480ced 100644 --- a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/NiADatabase.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/NiADatabase.kt @@ -23,15 +23,15 @@ import com.google.samples.apps.nowinandroid.core.database.dao.AuthorDao import com.google.samples.apps.nowinandroid.core.database.dao.EpisodeDao import com.google.samples.apps.nowinandroid.core.database.dao.NewsResourceDao import com.google.samples.apps.nowinandroid.core.database.dao.TopicDao +import com.google.samples.apps.nowinandroid.core.database.model.AuthorEntity +import com.google.samples.apps.nowinandroid.core.database.model.EpisodeAuthorCrossRef +import com.google.samples.apps.nowinandroid.core.database.model.EpisodeEntity +import com.google.samples.apps.nowinandroid.core.database.model.NewsResourceAuthorCrossRef +import com.google.samples.apps.nowinandroid.core.database.model.NewsResourceEntity +import com.google.samples.apps.nowinandroid.core.database.model.NewsResourceTopicCrossRef +import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity import com.google.samples.apps.nowinandroid.core.database.util.InstantConverter import com.google.samples.apps.nowinandroid.core.database.util.NewsResourceTypeConverter -import com.google.samples.apps.nowinandroid.core.model.entities.AuthorEntity -import com.google.samples.apps.nowinandroid.core.model.entities.EpisodeAuthorCrossRef -import com.google.samples.apps.nowinandroid.core.model.entities.EpisodeEntity -import com.google.samples.apps.nowinandroid.core.model.entities.NewsResourceAuthorCrossRef -import com.google.samples.apps.nowinandroid.core.model.entities.NewsResourceEntity -import com.google.samples.apps.nowinandroid.core.model.entities.NewsResourceTopicCrossRef -import com.google.samples.apps.nowinandroid.core.model.entities.TopicEntity @Database( entities = [ diff --git a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/AuthorDao.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/AuthorDao.kt index a985f1c2d..6fb70e56e 100644 --- a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/AuthorDao.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/AuthorDao.kt @@ -19,7 +19,7 @@ package com.google.samples.apps.nowinandroid.core.database.dao import androidx.room.Dao import androidx.room.Insert import androidx.room.Query -import com.google.samples.apps.nowinandroid.core.model.entities.AuthorEntity +import com.google.samples.apps.nowinandroid.core.database.model.AuthorEntity import kotlinx.coroutines.flow.Flow /** diff --git a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/EpisodeDao.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/EpisodeDao.kt index 2fc5398ae..17aadc6e0 100644 --- a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/EpisodeDao.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/EpisodeDao.kt @@ -19,8 +19,9 @@ package com.google.samples.apps.nowinandroid.core.database.dao import androidx.room.Dao import androidx.room.Insert import androidx.room.Query +import com.google.samples.apps.nowinandroid.core.database.model.EpisodeEntity +import com.google.samples.apps.nowinandroid.core.database.model.PopulatedEpisode import com.google.samples.apps.nowinandroid.core.model.data.Episode -import com.google.samples.apps.nowinandroid.core.model.entities.EpisodeEntity import kotlinx.coroutines.flow.Flow /** @@ -29,7 +30,7 @@ import kotlinx.coroutines.flow.Flow @Dao interface EpisodeDao { @Query(value = "SELECT * FROM episodes") - fun getEpisodesStream(): Flow> + fun getEpisodesStream(): Flow> @Insert suspend fun saveEpisodeEntities(entities: List) diff --git a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/NewsResourceDao.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/NewsResourceDao.kt index dcd4ffba8..15f21f6e9 100644 --- a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/NewsResourceDao.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/NewsResourceDao.kt @@ -19,8 +19,9 @@ package com.google.samples.apps.nowinandroid.core.database.dao import androidx.room.Dao import androidx.room.Insert import androidx.room.Query +import com.google.samples.apps.nowinandroid.core.database.model.NewsResourceEntity +import com.google.samples.apps.nowinandroid.core.database.model.PopulatedNewsResource import com.google.samples.apps.nowinandroid.core.model.data.NewsResource -import com.google.samples.apps.nowinandroid.core.model.entities.NewsResourceEntity import kotlinx.coroutines.flow.Flow /** @@ -29,7 +30,7 @@ import kotlinx.coroutines.flow.Flow @Dao interface NewsResourceDao { @Query(value = "SELECT * FROM news_resources") - fun getNewsResourcesStream(): Flow> + fun getNewsResourcesStream(): Flow> @Query( value = """ @@ -37,7 +38,7 @@ interface NewsResourceDao { WHERE id IN (:filterTopicIds) """ ) - fun getNewsResourcesStream(filterTopicIds: Set): Flow> + fun getNewsResourcesStream(filterTopicIds: Set): Flow> @Insert suspend fun saveNewsResourceEntities(entities: List) diff --git a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/TopicDao.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/TopicDao.kt index 5bf7e4439..c710b4b75 100644 --- a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/TopicDao.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/dao/TopicDao.kt @@ -19,7 +19,7 @@ package com.google.samples.apps.nowinandroid.core.database.dao import androidx.room.Dao import androidx.room.Insert import androidx.room.Query -import com.google.samples.apps.nowinandroid.core.model.entities.TopicEntity +import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity import kotlinx.coroutines.flow.Flow /** diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/AuthorEntity.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/AuthorEntity.kt similarity index 82% rename from core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/AuthorEntity.kt rename to core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/AuthorEntity.kt index eba77d4f8..be219fd78 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/AuthorEntity.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/AuthorEntity.kt @@ -14,12 +14,13 @@ * limitations under the License. */ -package com.google.samples.apps.nowinandroid.core.model.entities +package com.google.samples.apps.nowinandroid.core.database.model import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.Index import androidx.room.PrimaryKey +import com.google.samples.apps.nowinandroid.core.model.data.Author /** * Defines an author for either an [EpisodeEntity] or [NewsResourceEntity]. @@ -38,3 +39,9 @@ data class AuthorEntity( @ColumnInfo(name = "image_url") val imageUrl: String, ) + +fun AuthorEntity.asExternalModel() = Author( + id = id, + name = name, + imageUrl = imageUrl, +) diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/EpisodeAuthorCrossRef.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/EpisodeAuthorCrossRef.kt similarity index 95% rename from core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/EpisodeAuthorCrossRef.kt rename to core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/EpisodeAuthorCrossRef.kt index edcd0fe2e..225415b69 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/EpisodeAuthorCrossRef.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/EpisodeAuthorCrossRef.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.google.samples.apps.nowinandroid.core.model.entities +package com.google.samples.apps.nowinandroid.core.database.model import androidx.room.ColumnInfo import androidx.room.Entity diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/EpisodeEntity.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/EpisodeEntity.kt similarity index 94% rename from core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/EpisodeEntity.kt rename to core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/EpisodeEntity.kt index be9a9935c..eddddcb33 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/EpisodeEntity.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/EpisodeEntity.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.google.samples.apps.nowinandroid.core.model.entities +package com.google.samples.apps.nowinandroid.core.database.model import androidx.room.ColumnInfo import androidx.room.Entity diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/NewsResourceAuthorCrossRef.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/NewsResourceAuthorCrossRef.kt similarity index 95% rename from core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/NewsResourceAuthorCrossRef.kt rename to core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/NewsResourceAuthorCrossRef.kt index ee3d4bc3c..fb394159e 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/NewsResourceAuthorCrossRef.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/NewsResourceAuthorCrossRef.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.google.samples.apps.nowinandroid.core.model.entities +package com.google.samples.apps.nowinandroid.core.database.model import androidx.room.ColumnInfo import androidx.room.Entity diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/NewsResourceEntity.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/NewsResourceEntity.kt similarity index 74% rename from core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/NewsResourceEntity.kt rename to core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/NewsResourceEntity.kt index 80375d539..8e306f769 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/NewsResourceEntity.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/NewsResourceEntity.kt @@ -14,12 +14,14 @@ * limitations under the License. */ -package com.google.samples.apps.nowinandroid.core.model.entities +package com.google.samples.apps.nowinandroid.core.database.model import androidx.room.ColumnInfo import androidx.room.Entity import androidx.room.ForeignKey import androidx.room.PrimaryKey +import com.google.samples.apps.nowinandroid.core.model.data.NewsResource +import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType import kotlinx.datetime.Instant /** @@ -47,5 +49,17 @@ data class NewsResourceEntity( val url: String, @ColumnInfo(name = "publish_date") val publishDate: Instant, - val type: String, + val type: NewsResourceType, +) + +fun NewsResourceEntity.asExternalModel() = NewsResource( + id = id, + episodeId = episodeId, + title = title, + content = content, + url = url, + publishDate = publishDate, + type = type, + authors = listOf(), + topics = listOf() ) diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/NewsResourceTopicCrossRef.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/NewsResourceTopicCrossRef.kt similarity index 95% rename from core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/NewsResourceTopicCrossRef.kt rename to core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/NewsResourceTopicCrossRef.kt index 4629707a3..6912d6685 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/NewsResourceTopicCrossRef.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/NewsResourceTopicCrossRef.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.google.samples.apps.nowinandroid.core.model.entities +package com.google.samples.apps.nowinandroid.core.database.model import androidx.room.ColumnInfo import androidx.room.Entity diff --git a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/PopulatedEpisode.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/PopulatedEpisode.kt new file mode 100644 index 000000000..1a700f883 --- /dev/null +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/PopulatedEpisode.kt @@ -0,0 +1,55 @@ +/* + * 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.database.model + +import androidx.room.Embedded +import androidx.room.Junction +import androidx.room.Relation +import com.google.samples.apps.nowinandroid.core.model.data.Episode + +/** + * External data layer representation of an NiA episode + */ +data class PopulatedEpisode( + @Embedded + val entity: EpisodeEntity, + @Relation( + parentColumn = "id", + entityColumn = "episode_id" + ) + val newsResources: List, + @Relation( + parentColumn = "id", + entityColumn = "id", + associateBy = Junction( + value = EpisodeAuthorCrossRef::class, + parentColumn = "episode_id", + entityColumn = "author_id", + ) + ) + val authors: List +) + +fun PopulatedEpisode.asExternalModel() = Episode( + id = entity.id, + name = entity.name, + publishDate = entity.publishDate, + alternateVideo = entity.alternateVideo, + alternateAudio = entity.alternateAudio, + newsResources = newsResources.map(NewsResourceEntity::asExternalModel), + authors = authors.map(AuthorEntity::asExternalModel) +) diff --git a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/PopulatedNewsResource.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/PopulatedNewsResource.kt new file mode 100644 index 000000000..3aab17da8 --- /dev/null +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/PopulatedNewsResource.kt @@ -0,0 +1,67 @@ +/* + * 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.database.model + +import androidx.room.Embedded +import androidx.room.Junction +import androidx.room.Relation +import com.google.samples.apps.nowinandroid.core.model.data.NewsResource + +/** + * External data layer representation of a fully populated NiA news resource + */ +data class PopulatedNewsResource( + @Embedded + val entity: NewsResourceEntity, + @Relation( + parentColumn = "episode_id", + entityColumn = "id" + ) + val episode: EpisodeEntity, + @Relation( + parentColumn = "id", + entityColumn = "id", + associateBy = Junction( + value = NewsResourceAuthorCrossRef::class, + parentColumn = "news_resource_id", + entityColumn = "author_id", + ) + ) + val authors: List, + @Relation( + parentColumn = "id", + entityColumn = "id", + associateBy = Junction( + value = NewsResourceTopicCrossRef::class, + parentColumn = "news_resource_id", + entityColumn = "topic_id", + ) + ) + val topics: List +) + +fun PopulatedNewsResource.asExternalModel() = NewsResource( + id = entity.id, + episodeId = entity.episodeId, + title = entity.title, + content = entity.content, + url = entity.url, + publishDate = entity.publishDate, + type = entity.type, + authors = authors.map(AuthorEntity::asExternalModel), + topics = topics.map(TopicEntity::asExternalModel) +) diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/TopicEntity.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/TopicEntity.kt similarity index 80% rename from core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/TopicEntity.kt rename to core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/TopicEntity.kt index 6cb2553c8..162d97d86 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/entities/TopicEntity.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/model/TopicEntity.kt @@ -14,11 +14,12 @@ * limitations under the License. */ -package com.google.samples.apps.nowinandroid.core.model.entities +package com.google.samples.apps.nowinandroid.core.database.model import androidx.room.Entity import androidx.room.Index import androidx.room.PrimaryKey +import com.google.samples.apps.nowinandroid.core.model.data.Topic /** * Defines a topic a user may follow. @@ -37,3 +38,10 @@ data class TopicEntity( val description: String, val followed: Boolean, ) + +fun TopicEntity.asExternalModel() = Topic( + id = id, + name = name, + description = description, + followed = followed, +) diff --git a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/util/Converters.kt b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/util/Converters.kt index dc7949eae..e09915d46 100644 --- a/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/util/Converters.kt +++ b/core-database/src/main/java/com/google/samples/apps/nowinandroid/core/database/util/Converters.kt @@ -18,6 +18,7 @@ package com.google.samples.apps.nowinandroid.core.database.util import androidx.room.TypeConverter import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType +import com.google.samples.apps.nowinandroid.core.model.data.asNewsResourceType import kotlinx.datetime.Instant class InstantConverter { @@ -36,10 +37,5 @@ class NewsResourceTypeConverter { value?.let(NewsResourceType::name) @TypeConverter - fun stringToNewsResourceType(name: String?): NewsResourceType = when (name) { - null -> NewsResourceType.Unknown - else -> NewsResourceType.values() - .firstOrNull { type -> type.name == name } - ?: NewsResourceType.Unknown - } + fun stringToNewsResourceType(name: String?): NewsResourceType = name.asNewsResourceType() } diff --git a/core-domain/build.gradle b/core-domain/build.gradle index fe0a7612e..36e7b6f52 100644 --- a/core-domain/build.gradle +++ b/core-domain/build.gradle @@ -39,11 +39,13 @@ android { dependencies { implementation project(':core-model') + implementation project(':core-database') implementation project(':core-datastore') implementation project(':core-network') testImplementation project(':core-testing') + implementation libs.kotlinx.datetime implementation libs.kotlinx.coroutines.android implementation libs.kotlinx.serialization.json diff --git a/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/model/Author.kt b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/model/Author.kt new file mode 100644 index 000000000..4cf2e93ed --- /dev/null +++ b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/model/Author.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.domain.model + +import com.google.samples.apps.nowinandroid.core.database.model.AuthorEntity +import com.google.samples.apps.nowinandroid.core.network.model.NetworkAuthor + +fun NetworkAuthor.asEntity() = AuthorEntity( + id = id, + name = name, + imageUrl = imageUrl +) diff --git a/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/model/Episode.kt b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/model/Episode.kt new file mode 100644 index 000000000..b07b96861 --- /dev/null +++ b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/model/Episode.kt @@ -0,0 +1,37 @@ +/* + * 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.model + +import com.google.samples.apps.nowinandroid.core.database.model.EpisodeEntity +import com.google.samples.apps.nowinandroid.core.network.model.NetworkEpisode +import com.google.samples.apps.nowinandroid.core.network.model.NetworkEpisodeExpanded + +fun NetworkEpisode.asEntity() = EpisodeEntity( + id = id, + name = name, + publishDate = publishDate, + alternateVideo = alternateVideo, + alternateAudio = alternateAudio, +) + +fun NetworkEpisodeExpanded.asEntity() = EpisodeEntity( + id = id, + name = name, + publishDate = publishDate, + alternateVideo = alternateVideo, + alternateAudio = alternateAudio, +) diff --git a/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/model/NewsResource.kt b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/model/NewsResource.kt new file mode 100644 index 000000000..711e69c7a --- /dev/null +++ b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/model/NewsResource.kt @@ -0,0 +1,41 @@ +/* + * 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.model + +import com.google.samples.apps.nowinandroid.core.database.model.NewsResourceEntity +import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource +import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResourceExpanded + +fun NetworkNewsResource.asEntity() = NewsResourceEntity( + id = id, + episodeId = episodeId, + title = title, + content = content, + url = url, + publishDate = publishDate, + type = type, +) + +fun NetworkNewsResourceExpanded.asEntity() = NewsResourceEntity( + id = id, + episodeId = episodeId, + title = title, + content = content, + url = url, + publishDate = publishDate, + type = type, +) diff --git a/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/model/Topic.kt b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/model/Topic.kt new file mode 100644 index 000000000..b12c53b81 --- /dev/null +++ b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/model/Topic.kt @@ -0,0 +1,27 @@ +/* + * 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.model + +import com.google.samples.apps.nowinandroid.core.database.model.TopicEntity +import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic + +fun NetworkTopic.asEntity() = TopicEntity( + id = id, + name = name, + description = description, + followed = followed +) diff --git a/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/repository/FakeTopicsRepository.kt b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/repository/FakeTopicsRepository.kt index 9c8cf8ab2..f0e0616bc 100644 --- a/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/repository/FakeTopicsRepository.kt +++ b/core-domain/src/main/java/com/google/samples/apps/nowinandroid/core/domain/repository/FakeTopicsRepository.kt @@ -18,9 +18,9 @@ package com.google.samples.apps.nowinandroid.core.domain.repository import com.google.samples.apps.nowinandroid.core.datastore.NiaPreferences import com.google.samples.apps.nowinandroid.core.model.data.Topic -import com.google.samples.apps.nowinandroid.core.model.network.NetworkTopic import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers import com.google.samples.apps.nowinandroid.core.network.fake.FakeDataSource +import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic import javax.inject.Inject import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.flow diff --git a/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/database/model/PopulatedEpisodeKtTest.kt b/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/database/model/PopulatedEpisodeKtTest.kt new file mode 100644 index 000000000..526c5ff74 --- /dev/null +++ b/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/database/model/PopulatedEpisodeKtTest.kt @@ -0,0 +1,90 @@ +/* + * 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.database.model + +import com.google.samples.apps.nowinandroid.core.model.data.Author +import com.google.samples.apps.nowinandroid.core.model.data.Episode +import com.google.samples.apps.nowinandroid.core.model.data.NewsResource +import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType.Video +import kotlinx.datetime.Instant +import org.junit.Assert.assertEquals +import org.junit.Test + +class PopulatedEpisodeKtTest { + @Test + fun populated_episode_can_be_mapped_to_episode() { + val populatedEpisode = PopulatedEpisode( + entity = EpisodeEntity( + id = 0, + name = "Test", + publishDate = Instant.fromEpochMilliseconds(1), + alternateAudio = "audio", + alternateVideo = "video" + ), + newsResources = listOf( + NewsResourceEntity( + id = 1, + episodeId = 0, + title = "news", + content = "Hilt", + url = "url", + type = Video, + publishDate = Instant.fromEpochMilliseconds(1), + ) + ), + authors = listOf( + AuthorEntity( + id = 2, + name = "name", + imageUrl = "imageUrl" + ) + ), + ) + val episode = populatedEpisode.asExternalModel() + + assertEquals( + Episode( + id = 0, + name = "Test", + publishDate = Instant.fromEpochMilliseconds(1), + alternateAudio = "audio", + alternateVideo = "video", + newsResources = listOf( + NewsResource( + id = 1, + episodeId = 0, + title = "news", + content = "Hilt", + url = "url", + type = Video, + publishDate = Instant.fromEpochMilliseconds(1), + authors = listOf(), + topics = listOf() + ) + ), + authors = listOf( + Author( + id = 2, + name = "name", + imageUrl = "imageUrl" + ) + ), + ), + episode + ) + } +} diff --git a/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/database/model/PopulatedNewsResourceKtTest.kt b/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/database/model/PopulatedNewsResourceKtTest.kt new file mode 100644 index 000000000..510ae3c5e --- /dev/null +++ b/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/database/model/PopulatedNewsResourceKtTest.kt @@ -0,0 +1,93 @@ +/* + * 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.database.model + +import com.google.samples.apps.nowinandroid.core.model.data.Author +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.model.data.Topic +import kotlinx.datetime.Instant +import org.junit.Assert.assertEquals +import org.junit.Test + +class PopulatedNewsResourceKtTest { + @Test + fun populated_news_resource_can_be_mapped_to_news_resource() { + val populatedNewsResource = PopulatedNewsResource( + entity = NewsResourceEntity( + id = 1, + episodeId = 0, + title = "news", + content = "Hilt", + url = "url", + type = Video, + publishDate = Instant.fromEpochMilliseconds(1), + ), + episode = EpisodeEntity( + id = 4, + name = "episode 4", + publishDate = Instant.fromEpochMilliseconds(2), + alternateAudio = "audio", + alternateVideo = "video", + ), + authors = listOf( + AuthorEntity( + id = 2, + name = "name", + imageUrl = "imageUrl" + ) + ), + topics = listOf( + TopicEntity( + id = 3, + name = "name", + description = "description", + followed = true, + ) + ), + ) + val newsResource = populatedNewsResource.asExternalModel() + + assertEquals( + NewsResource( + id = 1, + episodeId = 0, + title = "news", + content = "Hilt", + url = "url", + type = Video, + publishDate = Instant.fromEpochMilliseconds(1), + authors = listOf( + Author( + id = 2, + name = "name", + imageUrl = "imageUrl" + ) + ), + topics = listOf( + Topic( + id = 3, + name = "name", + description = "description", + followed = true, + ) + ) + ), + newsResource + ) + } +} diff --git a/core-model/src/test/java/com/google/samples/apps/nowinandroid/core/model/NetworkEntityKtTest.kt b/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/model/NetworkEntityKtTest.kt similarity index 69% rename from core-model/src/test/java/com/google/samples/apps/nowinandroid/core/model/NetworkEntityKtTest.kt rename to core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/model/NetworkEntityKtTest.kt index e62ff7c3c..2ebda718c 100644 --- a/core-model/src/test/java/com/google/samples/apps/nowinandroid/core/model/NetworkEntityKtTest.kt +++ b/core-domain/src/test/java/com/google/samples/apps/nowinandroid/core/domain/model/NetworkEntityKtTest.kt @@ -14,16 +14,15 @@ * limitations under the License. */ -package com.google.samples.apps.nowinandroid.core.model - -import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType -import com.google.samples.apps.nowinandroid.core.model.network.NetworkAuthor -import com.google.samples.apps.nowinandroid.core.model.network.NetworkEpisode -import com.google.samples.apps.nowinandroid.core.model.network.NetworkEpisodeExpanded -import com.google.samples.apps.nowinandroid.core.model.network.NetworkNewsResource -import com.google.samples.apps.nowinandroid.core.model.network.NetworkNewsResourceExpanded -import com.google.samples.apps.nowinandroid.core.model.network.NetworkTopic -import com.google.samples.apps.nowinandroid.core.model.network.asEntity +package com.google.samples.apps.nowinandroid.core.domain.model + +import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType.Article +import com.google.samples.apps.nowinandroid.core.network.model.NetworkAuthor +import com.google.samples.apps.nowinandroid.core.network.model.NetworkEpisode +import com.google.samples.apps.nowinandroid.core.network.model.NetworkEpisodeExpanded +import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource +import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResourceExpanded +import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic import kotlinx.datetime.Instant import org.junit.Assert.assertEquals import org.junit.Test @@ -60,15 +59,16 @@ class NetworkEntityKtTest { @Test fun network_news_resource_can_be_mapped_to_news_resource_entity() { - val networkModel = NetworkNewsResource( - id = 0, - episodeId = 2, - title = "title", - content = "content", - url = "url", - publishDate = Instant.fromEpochMilliseconds(1), - type = NewsResourceType.Article.displayText, - ) + val networkModel = + NetworkNewsResource( + id = 0, + episodeId = 2, + title = "title", + content = "content", + url = "url", + publishDate = Instant.fromEpochMilliseconds(1), + type = Article, + ) val entity = networkModel.asEntity() assertEquals(0, entity.id) @@ -77,17 +77,18 @@ class NetworkEntityKtTest { assertEquals("content", entity.content) assertEquals("url", entity.url) assertEquals(Instant.fromEpochMilliseconds(1), entity.publishDate) - assertEquals(NewsResourceType.Article.displayText, entity.type) - - val expandedNetworkModel = NetworkNewsResourceExpanded( - id = 0, - episodeId = 2, - title = "title", - content = "content", - url = "url", - publishDate = Instant.fromEpochMilliseconds(1), - type = NewsResourceType.Article.displayText, - ) + assertEquals(Article, entity.type) + + val expandedNetworkModel = + NetworkNewsResourceExpanded( + id = 0, + episodeId = 2, + title = "title", + content = "content", + url = "url", + publishDate = Instant.fromEpochMilliseconds(1), + type = Article, + ) val entityFromExpanded = expandedNetworkModel.asEntity() @@ -97,7 +98,7 @@ class NetworkEntityKtTest { assertEquals("content", entityFromExpanded.content) assertEquals("url", entityFromExpanded.url) assertEquals(Instant.fromEpochMilliseconds(1), entityFromExpanded.publishDate) - assertEquals(NewsResourceType.Article.displayText, entityFromExpanded.type) + assertEquals(Article, entityFromExpanded.type) } @Test @@ -117,13 +118,14 @@ class NetworkEntityKtTest { assertEquals("alternateAudio", entity.alternateAudio) assertEquals(Instant.fromEpochMilliseconds(1), entity.publishDate) - val expandedNetworkModel = NetworkEpisodeExpanded( - id = 0, - name = "name", - publishDate = Instant.fromEpochMilliseconds(1), - alternateVideo = "alternateVideo", - alternateAudio = "alternateAudio", - ) + val expandedNetworkModel = + NetworkEpisodeExpanded( + id = 0, + name = "name", + publishDate = Instant.fromEpochMilliseconds(1), + alternateVideo = "alternateVideo", + alternateAudio = "alternateAudio", + ) val entityFromExpanded = expandedNetworkModel.asEntity() diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/Author.kt b/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/Author.kt new file mode 100644 index 000000000..76b6e7c2a --- /dev/null +++ b/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/Author.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 + +/** + * External data layer representation of an NiA Author + */ +data class Author( + val id: Int, + val name: String, + val imageUrl: String, +) diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/Episode.kt b/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/Episode.kt index 6cf5677aa..f1e4fb336 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/Episode.kt +++ b/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/Episode.kt @@ -16,33 +16,17 @@ package com.google.samples.apps.nowinandroid.core.model.data -import androidx.room.Embedded -import androidx.room.Junction -import androidx.room.Relation -import com.google.samples.apps.nowinandroid.core.model.entities.AuthorEntity -import com.google.samples.apps.nowinandroid.core.model.entities.EpisodeAuthorCrossRef -import com.google.samples.apps.nowinandroid.core.model.entities.EpisodeEntity -import com.google.samples.apps.nowinandroid.core.model.entities.NewsResourceEntity +import kotlinx.datetime.Instant /** * External data layer representation of an NiA episode */ data class Episode( - @Embedded - val entity: EpisodeEntity, - @Relation( - parentColumn = "id", - entityColumn = "episode_id" - ) - val newsResources: List, - @Relation( - parentColumn = "id", - entityColumn = "id", - associateBy = Junction( - value = EpisodeAuthorCrossRef::class, - parentColumn = "episode_id", - entityColumn = "author_id", - ) - ) - val authors: List + val id: Int, + val name: String, + val publishDate: Instant, + val alternateVideo: String?, + val alternateAudio: String?, + val newsResources: List, + val authors: List ) diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/NewsResource.kt b/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/NewsResource.kt index 6a9bae94f..47eb0c803 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/NewsResource.kt +++ b/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/NewsResource.kt @@ -16,45 +16,19 @@ package com.google.samples.apps.nowinandroid.core.model.data -import androidx.room.Embedded -import androidx.room.Junction -import androidx.room.Relation -import com.google.samples.apps.nowinandroid.core.model.entities.AuthorEntity -import com.google.samples.apps.nowinandroid.core.model.entities.EpisodeEntity -import com.google.samples.apps.nowinandroid.core.model.entities.NewsResourceAuthorCrossRef -import com.google.samples.apps.nowinandroid.core.model.entities.NewsResourceEntity -import com.google.samples.apps.nowinandroid.core.model.entities.NewsResourceTopicCrossRef -import com.google.samples.apps.nowinandroid.core.model.entities.TopicEntity +import kotlinx.datetime.Instant /** * External data layer representation of a fully populated NiA news resource */ data class NewsResource( - @Embedded - val entity: NewsResourceEntity, - @Relation( - parentColumn = "episode_id", - entityColumn = "id" - ) - val episode: EpisodeEntity, - @Relation( - parentColumn = "id", - entityColumn = "id", - associateBy = Junction( - value = NewsResourceAuthorCrossRef::class, - parentColumn = "news_resource_id", - entityColumn = "author_id", - ) - ) - val authors: List, - @Relation( - parentColumn = "id", - entityColumn = "id", - associateBy = Junction( - value = NewsResourceTopicCrossRef::class, - parentColumn = "news_resource_id", - entityColumn = "topic_id", - ) - ) - val topics: List + val id: Int, + val episodeId: Int, + val title: String, + val content: String, + val url: String, + val publishDate: Instant, + val type: NewsResourceType, + val authors: List, + val topics: List ) diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/NewsResourceType.kt b/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/NewsResourceType.kt index ea839982d..a6a175ff3 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/NewsResourceType.kt +++ b/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/data/NewsResourceType.kt @@ -20,44 +20,61 @@ package com.google.samples.apps.nowinandroid.core.model.data * Type for [NewsResource] */ enum class NewsResourceType( + val serializedName: String, val displayText: String, // TODO: descriptions should probably be string resources val description: String ) { Video( + serializedName = "Video 📺", displayText = "Video 📺", description = "A video published on YouTube" ), APIChange( + serializedName = "API change", displayText = "API change", description = "An addition, deprecation or change to the Android platform APIs." ), Article( + serializedName = "Article 📚", displayText = "Article 📚", description = "An article, typically on Medium or the official Android blog" ), Codelab( + serializedName = "Codelab", displayText = "Codelab", description = "A new or updated codelab" ), Podcast( + serializedName = "Podcast 🎙", displayText = "Podcast 🎙", description = "A podcast" ), Docs( + serializedName = "Docs 📑", displayText = "Docs 📑", description = "A new or updated piece of documentation" ), Event( + serializedName = "Event 📆", displayText = "Event 📆", description = "Information about a developer event e.g. Android Developer Summit" ), DAC( + serializedName = "DAC", displayText = "DAC", description = "Android version features - Information about features in an Android" ), Unknown( + serializedName = "Unknown", displayText = "Unknown", description = "Unknown" ) } + +fun String?.asNewsResourceType() = when (this) { + null -> NewsResourceType.Unknown + else -> NewsResourceType.values() + .firstOrNull { type -> type.serializedName == this } + ?: NewsResourceType.Unknown +} diff --git a/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/NiANetwork.kt b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/NiANetwork.kt index e8e4949c5..32599344c 100644 --- a/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/NiANetwork.kt +++ b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/NiANetwork.kt @@ -16,8 +16,8 @@ package com.google.samples.apps.nowinandroid.core.network -import com.google.samples.apps.nowinandroid.core.model.network.NetworkNewsResource -import com.google.samples.apps.nowinandroid.core.model.network.NetworkTopic +import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource +import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic /** * Interface representing network calls to the NIA backend diff --git a/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/fake/FakeData.kt b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/fake/FakeData.kt index 475d70715..ddb9b8eca 100644 --- a/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/fake/FakeData.kt +++ b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/fake/FakeData.kt @@ -16,8 +16,9 @@ package com.google.samples.apps.nowinandroid.core.network.fake -import com.google.samples.apps.nowinandroid.core.model.network.NetworkTopic -import com.google.samples.apps.nowinandroid.core.model.network.NetworkNewsResource +import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType.Video +import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic +import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource import kotlinx.datetime.LocalDateTime import kotlinx.datetime.TimeZone import kotlinx.datetime.toInstant @@ -45,7 +46,7 @@ object FakeDataSource { second = 0, nanosecond = 0 ).toInstant(TimeZone.UTC), - type = "Video \uD83D\uDCFA", + type = Video, topics = listOf(0), ) diff --git a/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/fake/FakeNiANetwork.kt b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/fake/FakeNiANetwork.kt index ff6957e07..b0c36f478 100644 --- a/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/fake/FakeNiANetwork.kt +++ b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/fake/FakeNiANetwork.kt @@ -16,10 +16,10 @@ package com.google.samples.apps.nowinandroid.core.network.fake -import com.google.samples.apps.nowinandroid.core.model.network.NetworkNewsResource -import com.google.samples.apps.nowinandroid.core.model.network.NetworkTopic import com.google.samples.apps.nowinandroid.core.network.NiANetwork import com.google.samples.apps.nowinandroid.core.network.NiaDispatchers +import com.google.samples.apps.nowinandroid.core.network.model.NetworkNewsResource +import com.google.samples.apps.nowinandroid.core.network.model.NetworkTopic import javax.inject.Inject import kotlinx.coroutines.withContext import kotlinx.serialization.Serializable diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/NetworkAuthor.kt b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/NetworkAuthor.kt similarity index 73% rename from core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/NetworkAuthor.kt rename to core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/NetworkAuthor.kt index b31057e0a..4ec4da518 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/NetworkAuthor.kt +++ b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/NetworkAuthor.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package com.google.samples.apps.nowinandroid.core.model.network +package com.google.samples.apps.nowinandroid.core.network.model -import com.google.samples.apps.nowinandroid.core.model.entities.AuthorEntity +import com.google.samples.apps.nowinandroid.core.model.data.Author import kotlinx.serialization.Serializable /** - * Network representation of [AuthorEntity] + * Network representation of [Author] */ @Serializable data class NetworkAuthor( @@ -28,9 +28,3 @@ data class NetworkAuthor( val name: String, val imageUrl: String, ) - -fun NetworkAuthor.asEntity() = AuthorEntity( - id = id, - name = name, - imageUrl = imageUrl -) diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/NetworkEpisode.kt b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/NetworkEpisode.kt similarity index 64% rename from core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/NetworkEpisode.kt rename to core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/NetworkEpisode.kt index b36000904..b1efe2dcc 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/NetworkEpisode.kt +++ b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/NetworkEpisode.kt @@ -14,19 +14,18 @@ * limitations under the License. */ -package com.google.samples.apps.nowinandroid.core.model.network +package com.google.samples.apps.nowinandroid.core.network.model -import androidx.room.PrimaryKey -import com.google.samples.apps.nowinandroid.core.model.entities.EpisodeEntity +import com.google.samples.apps.nowinandroid.core.model.data.Episode +import com.google.samples.apps.nowinandroid.core.network.model.util.InstantSerializer import kotlinx.datetime.Instant import kotlinx.serialization.Serializable /** - * Network representation of [EpisodeEntity] when fetched from /networkepisodes + * Network representation of [Episode] when fetched from /episodes */ @Serializable data class NetworkEpisode( - @PrimaryKey val id: Int, val name: String, @Serializable(InstantSerializer::class) @@ -38,11 +37,10 @@ data class NetworkEpisode( ) /** - * Network representation of [EpisodeEntity] when fetched from /networkepisodes{id} + * Network representation of [Episode] when fetched from /episodes/{id} */ @Serializable data class NetworkEpisodeExpanded( - @PrimaryKey val id: Int, val name: String, @Serializable(InstantSerializer::class) @@ -52,19 +50,3 @@ data class NetworkEpisodeExpanded( val newsResources: List = listOf(), val authors: List = listOf(), ) - -fun NetworkEpisode.asEntity() = EpisodeEntity( - id = id, - name = name, - publishDate = publishDate, - alternateVideo = alternateVideo, - alternateAudio = alternateAudio, -) - -fun NetworkEpisodeExpanded.asEntity() = EpisodeEntity( - id = id, - name = name, - publishDate = publishDate, - alternateVideo = alternateVideo, - alternateAudio = alternateAudio, -) diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/NetworkNewsResource.kt b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/NetworkNewsResource.kt similarity index 63% rename from core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/NetworkNewsResource.kt rename to core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/NetworkNewsResource.kt index 97248dcd1..d227fc9a2 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/NetworkNewsResource.kt +++ b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/NetworkNewsResource.kt @@ -14,14 +14,17 @@ * limitations under the License. */ -package com.google.samples.apps.nowinandroid.core.model.network +package com.google.samples.apps.nowinandroid.core.network.model -import com.google.samples.apps.nowinandroid.core.model.entities.NewsResourceEntity +import com.google.samples.apps.nowinandroid.core.model.data.NewsResource +import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType +import com.google.samples.apps.nowinandroid.core.network.model.util.InstantSerializer +import com.google.samples.apps.nowinandroid.core.network.model.util.NewsResourceTypeSerializer import kotlinx.datetime.Instant import kotlinx.serialization.Serializable /** - * Network representation of [NewsResourceEntity] when fetched from /networkresources + * Network representation of [NewsResource] when fetched from /newsresources */ @Serializable data class NetworkNewsResource( @@ -32,13 +35,14 @@ data class NetworkNewsResource( val url: String, @Serializable(InstantSerializer::class) val publishDate: Instant, - val type: String, + @Serializable(NewsResourceTypeSerializer::class) + val type: NewsResourceType, val authors: List = listOf(), val topics: List = listOf(), ) /** - * Network representation of [NewsResourceEntity] when fetched from /networkresources{id} + * Network representation of [NewsResource] when fetched from /newsresources/{id} */ @Serializable data class NetworkNewsResourceExpanded( @@ -49,27 +53,8 @@ data class NetworkNewsResourceExpanded( val url: String, @Serializable(InstantSerializer::class) val publishDate: Instant, - val type: String, + @Serializable(NewsResourceTypeSerializer::class) + val type: NewsResourceType, val authors: List = listOf(), val topics: List = listOf(), ) - -fun NetworkNewsResource.asEntity() = NewsResourceEntity( - id = id, - episodeId = episodeId, - title = title, - content = content, - url = url, - publishDate = publishDate, - type = type, -) - -fun NetworkNewsResourceExpanded.asEntity() = NewsResourceEntity( - id = id, - episodeId = episodeId, - title = title, - content = content, - url = url, - publishDate = publishDate, - type = type, -) diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/NetworkTopic.kt b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/NetworkTopic.kt similarity index 72% rename from core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/NetworkTopic.kt rename to core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/NetworkTopic.kt index ce6221c06..95860e790 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/NetworkTopic.kt +++ b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/NetworkTopic.kt @@ -14,13 +14,13 @@ * limitations under the License. */ -package com.google.samples.apps.nowinandroid.core.model.network +package com.google.samples.apps.nowinandroid.core.network.model -import com.google.samples.apps.nowinandroid.core.model.entities.TopicEntity +import com.google.samples.apps.nowinandroid.core.model.data.Topic import kotlinx.serialization.Serializable /** - * Network representation of [TopicEntity] + * Network representation of [Topic] */ @Serializable data class NetworkTopic( @@ -29,10 +29,3 @@ data class NetworkTopic( val description: String = "", val followed: Boolean = false, ) - -fun NetworkTopic.asEntity() = TopicEntity( - id = id, - name = name, - description = description, - followed = followed -) diff --git a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/InstantSerializer.kt b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/util/InstantSerializer.kt similarity index 95% rename from core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/InstantSerializer.kt rename to core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/util/InstantSerializer.kt index 4ccaebb7b..f093998cf 100644 --- a/core-model/src/main/java/com/google/samples/apps/nowinandroid/core/model/network/InstantSerializer.kt +++ b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/util/InstantSerializer.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package com.google.samples.apps.nowinandroid.core.model.network +package com.google.samples.apps.nowinandroid.core.network.model.util import kotlinx.datetime.Instant import kotlinx.datetime.toInstant diff --git a/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/util/NewsResourceTypeSerializer.kt b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/util/NewsResourceTypeSerializer.kt new file mode 100644 index 000000000..fbc526753 --- /dev/null +++ b/core-network/src/main/java/com/google/samples/apps/nowinandroid/core/network/model/util/NewsResourceTypeSerializer.kt @@ -0,0 +1,39 @@ +/* + * 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.network.model.util + +import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType +import com.google.samples.apps.nowinandroid.core.model.data.asNewsResourceType +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind.STRING +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder + +object NewsResourceTypeSerializer : KSerializer { + override fun deserialize(decoder: Decoder): NewsResourceType = + decoder.decodeString().asNewsResourceType() + + override val descriptor: SerialDescriptor = PrimitiveSerialDescriptor( + serialName = "type", + kind = STRING + ) + + override fun serialize(encoder: Encoder, value: NewsResourceType) = + encoder.encodeString(value.name) +} diff --git a/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt index a8429a5ba..4e741e601 100644 --- a/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt +++ b/core-ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/NewsResourceCard.kt @@ -37,11 +37,10 @@ import androidx.compose.ui.semantics.onClick import androidx.compose.ui.semantics.semantics import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp +import com.google.samples.apps.nowinandroid.core.model.data.Author import com.google.samples.apps.nowinandroid.core.model.data.NewsResource -import com.google.samples.apps.nowinandroid.core.model.entities.AuthorEntity -import com.google.samples.apps.nowinandroid.core.model.entities.EpisodeEntity -import com.google.samples.apps.nowinandroid.core.model.entities.NewsResourceEntity -import com.google.samples.apps.nowinandroid.core.model.entities.TopicEntity +import com.google.samples.apps.nowinandroid.core.model.data.NewsResourceType.Article +import com.google.samples.apps.nowinandroid.core.model.data.Topic import com.google.samples.apps.nowinandroid.core.ui.theme.NiaTheme import kotlinx.datetime.Instant @@ -59,12 +58,12 @@ fun NewsResourceCardExpanded( modifier = Modifier.padding(16.dp) ) { Row { - NewsResourceTitle(newsResource.entity.title, modifier = Modifier.fillMaxWidth((.8f))) + NewsResourceTitle(newsResource.title, modifier = Modifier.fillMaxWidth((.8f))) Spacer(modifier = Modifier.weight(1f)) BookmarkButton(isBookmarked, onToggleBookmark) } Spacer(modifier = Modifier.height(12.dp)) - NewsResourceShortDescription(newsResource.entity.content) + NewsResourceShortDescription(newsResource.content) } } @@ -174,31 +173,22 @@ fun ExpandedNewsResourcePreview() { } private val newsResource = NewsResource( - NewsResourceEntity( - id = 1, - episodeId = 1, - title = "Title", - content = "Content", - url = "url", - publishDate = Instant.DISTANT_FUTURE, - type = "type", - ), - EpisodeEntity( - id = 1, - name = "Title", - publishDate = Instant.DISTANT_FUTURE, - alternateVideo = "alternateVideo", - alternateAudio = "alternateAudio", - ), - listOf( - AuthorEntity( + id = 1, + episodeId = 1, + title = "Title", + content = "Content", + url = "url", + publishDate = Instant.DISTANT_FUTURE, + type = Article, + authors = listOf( + Author( id = 1, name = "Name", imageUrl = "imageUrl" ) ), - listOf( - TopicEntity( + topics = listOf( + Topic( id = 1, name = "Name", description = "Description", diff --git a/feature-following/src/test/java/com/google/samples/apps/nowinandroid/following/FollowingViewModelTest.kt b/feature-following/src/test/java/com/google/samples/apps/nowinandroid/following/FollowingViewModelTest.kt index b5104d259..36b87c16e 100644 --- a/feature-following/src/test/java/com/google/samples/apps/nowinandroid/following/FollowingViewModelTest.kt +++ b/feature-following/src/test/java/com/google/samples/apps/nowinandroid/following/FollowingViewModelTest.kt @@ -145,6 +145,7 @@ private val testOutputTopics = listOf( Topic( id = 2, name = TOPIC_3_NAME, - description = TOPIC_DESC + description = TOPIC_DESC, + followed = false, ) ) 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 1e0cd3333..be959eca3 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 @@ -109,7 +109,7 @@ class ForYouViewModelTest { Topic( id = 2, name = "Tools", - description = "" + description = "", ) to false ), feed = emptyList()