diff --git a/Jetcaster/core/data/src/main/java/com/example/jetcaster/core/data/database/model/EpisodeToPodcast.kt b/Jetcaster/core/data/src/main/java/com/example/jetcaster/core/data/database/model/EpisodeToPodcast.kt index 7945f2031..8958d23de 100644 --- a/Jetcaster/core/data/src/main/java/com/example/jetcaster/core/data/database/model/EpisodeToPodcast.kt +++ b/Jetcaster/core/data/src/main/java/com/example/jetcaster/core/data/database/model/EpisodeToPodcast.kt @@ -16,11 +16,13 @@ package com.example.jetcaster.core.data.database.model +import androidx.compose.runtime.Immutable import androidx.room.Embedded import androidx.room.Ignore import androidx.room.Relation import java.util.Objects +@Immutable class EpisodeToPodcast { @Embedded lateinit var episode: Episode diff --git a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/CategoryInfo.kt b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/CategoryInfo.kt index f462e4cb9..7ef368755 100644 --- a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/CategoryInfo.kt +++ b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/CategoryInfo.kt @@ -16,8 +16,10 @@ package com.example.jetcaster.core.model +import androidx.compose.runtime.Immutable import com.example.jetcaster.core.data.database.model.Category +@Immutable data class CategoryInfo(val id: Long, val name: String) const val CategoryTechnology = "Technology" diff --git a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/EpisodeInfo.kt b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/EpisodeInfo.kt index 8bf70ed11..5fcb4226e 100644 --- a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/EpisodeInfo.kt +++ b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/EpisodeInfo.kt @@ -16,6 +16,7 @@ package com.example.jetcaster.core.model +import androidx.compose.runtime.Immutable import com.example.jetcaster.core.data.database.model.Episode import java.time.Duration import java.time.OffsetDateTime @@ -23,6 +24,8 @@ import java.time.OffsetDateTime /** * External data layer representation of an episode. */ + +@Immutable data class EpisodeInfo( val uri: String = "", val podcastUri: String = "", diff --git a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/FilterableCategoriesModel.kt b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/FilterableCategoriesModel.kt index a35943792..d8975dbbe 100644 --- a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/FilterableCategoriesModel.kt +++ b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/FilterableCategoriesModel.kt @@ -16,9 +16,13 @@ package com.example.jetcaster.core.model +import androidx.compose.runtime.Immutable + /** * Model holding a list of categories and a selected category in the collection */ + +@Immutable data class FilterableCategoriesModel(val categories: List = emptyList(), val selectedCategory: CategoryInfo? = null) { val isEmpty = categories.isEmpty() || selectedCategory == null } diff --git a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/PodcastCategoryFilterResult.kt b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/PodcastCategoryFilterResult.kt index 871780034..2520a01d9 100644 --- a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/PodcastCategoryFilterResult.kt +++ b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/PodcastCategoryFilterResult.kt @@ -16,9 +16,12 @@ package com.example.jetcaster.core.model +import androidx.compose.runtime.Immutable + /** * A model holding top podcasts and matching episodes when filtering based on a category. */ +@Immutable data class PodcastCategoryFilterResult( val topPodcasts: List = emptyList(), val episodes: List = emptyList(), diff --git a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/PodcastInfo.kt b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/PodcastInfo.kt index 2150c06ec..7380c6f64 100644 --- a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/PodcastInfo.kt +++ b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/PodcastInfo.kt @@ -16,6 +16,7 @@ package com.example.jetcaster.core.model +import androidx.compose.runtime.Immutable import com.example.jetcaster.core.data.database.model.Podcast import com.example.jetcaster.core.data.database.model.PodcastWithExtraInfo import java.time.OffsetDateTime @@ -23,6 +24,7 @@ import java.time.OffsetDateTime /** * External data layer representation of a podcast. */ +@Immutable data class PodcastInfo( val uri: String = "", val title: String = "", diff --git a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/PodcastToEpisodeInfo.kt b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/PodcastToEpisodeInfo.kt index 2b69d1fe4..86aa1ccde 100644 --- a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/PodcastToEpisodeInfo.kt +++ b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/model/PodcastToEpisodeInfo.kt @@ -16,8 +16,10 @@ package com.example.jetcaster.core.model +import androidx.compose.runtime.Immutable import com.example.jetcaster.core.data.database.model.EpisodeToPodcast +@Immutable data class PodcastToEpisodeInfo(val episode: EpisodeInfo, val podcast: PodcastInfo) fun EpisodeToPodcast.asPodcastToEpisodeInfo(): PodcastToEpisodeInfo = PodcastToEpisodeInfo( diff --git a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/player/EpisodePlayer.kt b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/player/EpisodePlayer.kt index c01d64c61..874c5e360 100644 --- a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/player/EpisodePlayer.kt +++ b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/player/EpisodePlayer.kt @@ -16,11 +16,14 @@ package com.example.jetcaster.core.player +import androidx.compose.runtime.Immutable import com.example.jetcaster.core.player.model.PlayerEpisode import java.time.Duration import kotlinx.coroutines.flow.StateFlow val DefaultPlaybackSpeed = Duration.ofSeconds(1) + +@Immutable data class EpisodePlayerState( val currentEpisode: PlayerEpisode? = null, val queue: List = emptyList(), diff --git a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/player/model/PlayerEpisode.kt b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/player/model/PlayerEpisode.kt index adc1a21c0..f99f9a039 100644 --- a/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/player/model/PlayerEpisode.kt +++ b/Jetcaster/core/domain/src/main/java/com/example/jetcaster/core/player/model/PlayerEpisode.kt @@ -16,6 +16,7 @@ package com.example.jetcaster.core.player.model +import androidx.compose.runtime.Immutable import com.example.jetcaster.core.data.database.model.EpisodeToPodcast import com.example.jetcaster.core.model.EpisodeInfo import com.example.jetcaster.core.model.PodcastInfo @@ -25,6 +26,8 @@ import java.time.OffsetDateTime /** * Episode data with necessary information to be used within a player. */ + +@Immutable data class PlayerEpisode( val uri: String = "", val title: String = "", diff --git a/Jetcaster/mobile/build.gradle.kts b/Jetcaster/mobile/build.gradle.kts index 469fbe867..c24b53c16 100644 --- a/Jetcaster/mobile/build.gradle.kts +++ b/Jetcaster/mobile/build.gradle.kts @@ -97,6 +97,12 @@ android { excludes += "/META-INF/AL2.0" excludes += "/META-INF/LGPL2.1" } + + composeCompiler { + reportsDestination = layout.buildDirectory.dir("compose_compiler") + metricsDestination = layout.buildDirectory.dir("compose_compiler") + stabilityConfigurationFiles = listOf(rootProject.layout.projectDirectory.file("stability_config.conf")) + } } dependencies { diff --git a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/home/Home.kt b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/home/Home.kt index 15675e8a3..7b363bfce 100644 --- a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/home/Home.kt +++ b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/home/Home.kt @@ -118,8 +118,8 @@ import com.example.jetcaster.util.radialGradientScrim import java.time.Duration import java.time.LocalDateTime import java.time.OffsetDateTime -import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.toPersistentList +import kotlinx.collections.immutable.ImmutableList +import kotlinx.collections.immutable.toImmutableList import kotlinx.coroutines.launch @OptIn(ExperimentalMaterial3AdaptiveApi::class) @@ -373,7 +373,7 @@ private fun HomeScreenBackground(modifier: Modifier = Modifier, content: @Compos private fun HomeScreen( windowSizeClass: WindowSizeClass, isLoading: Boolean, - featuredPodcasts: PersistentList, + featuredPodcasts: ImmutableList, selectedHomeCategory: HomeCategory, homeCategories: List, filterableCategoriesModel: FilterableCategoriesModel, @@ -538,7 +538,7 @@ fun PillToolbar(selectedHomeCategory: HomeCategory, onHomeAction: (HomeAction) - @Composable private fun HomeContent( - featuredPodcasts: PersistentList, + featuredPodcasts: ImmutableList, selectedHomeCategory: HomeCategory, filterableCategoriesModel: FilterableCategoriesModel, podcastCategoryFilterResult: PodcastCategoryFilterResult, @@ -572,7 +572,7 @@ private fun HomeContent( @Composable private fun HomeContentGrid( - featuredPodcasts: PersistentList, + featuredPodcasts: ImmutableList, selectedHomeCategory: HomeCategory, filterableCategoriesModel: FilterableCategoriesModel, podcastCategoryFilterResult: PodcastCategoryFilterResult, @@ -630,7 +630,7 @@ private fun HomeContentGrid( @Composable private fun FollowedPodcastItem( - items: PersistentList, + items: ImmutableList, onPodcastUnfollowed: (PodcastInfo) -> Unit, navigateToPodcastDetails: (PodcastInfo) -> Unit, modifier: Modifier = Modifier, @@ -652,7 +652,7 @@ private fun FollowedPodcastItem( @OptIn(ExperimentalMaterial3Api::class) @Composable private fun FollowedPodcasts( - items: PersistentList, + items: ImmutableList, onPodcastUnfollowed: (PodcastInfo) -> Unit, navigateToPodcastDetails: (PodcastInfo) -> Unit, modifier: Modifier = Modifier, @@ -767,7 +767,7 @@ private fun PreviewHome() { HomeScreen( windowSizeClass = CompactWindowSizeClass, isLoading = true, - featuredPodcasts = PreviewPodcasts.toPersistentList(), + featuredPodcasts = PreviewPodcasts.toImmutableList(), homeCategories = HomeCategory.entries, selectedHomeCategory = HomeCategory.Discover, filterableCategoriesModel = FilterableCategoriesModel( diff --git a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/home/HomeViewModel.kt b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/home/HomeViewModel.kt index b3106ee1e..924b97792 100644 --- a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/home/HomeViewModel.kt +++ b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/home/HomeViewModel.kt @@ -38,7 +38,7 @@ import com.example.jetcaster.core.player.EpisodePlayer import com.example.jetcaster.core.player.model.PlayerEpisode import dagger.hilt.android.lifecycle.HiltViewModel import javax.inject.Inject -import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.ImmutableList import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.toPersistentList import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -229,7 +229,7 @@ sealed interface HomeAction { data class HomeScreenUiState( val isLoading: Boolean = true, val errorMessage: String? = null, - val featuredPodcasts: PersistentList = persistentListOf(), + val featuredPodcasts: ImmutableList = persistentListOf(), val selectedHomeCategory: HomeCategory = HomeCategory.Discover, val homeCategories: List = emptyList(), val filterableCategoriesModel: FilterableCategoriesModel = FilterableCategoriesModel(), diff --git a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/podcast/PodcastDetailsScreen.kt b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/podcast/PodcastDetailsScreen.kt index 33dcc13cc..c9890ab70 100644 --- a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/podcast/PodcastDetailsScreen.kt +++ b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/podcast/PodcastDetailsScreen.kt @@ -101,7 +101,7 @@ fun PodcastDetailsScreen( PodcastDetailsScreen( podcast = s.podcast, episodes = s.episodes, - toggleSubscribe = viewModel::toggleSusbcribe, + toggleSubscribe = viewModel::toggleSubscribe, onQueueEpisode = viewModel::onQueueEpisode, removeFromQueue = viewModel::deleteEpisode, navigateToPlayer = navigateToPlayer, diff --git a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/podcast/PodcastDetailsViewModel.kt b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/podcast/PodcastDetailsViewModel.kt index 9d4332743..d77b68d80 100644 --- a/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/podcast/PodcastDetailsViewModel.kt +++ b/Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/podcast/PodcastDetailsViewModel.kt @@ -17,6 +17,7 @@ package com.example.jetcaster.ui.podcast import android.net.Uri +import androidx.compose.runtime.Immutable import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.example.jetcaster.core.data.repository.EpisodeStore @@ -37,6 +38,7 @@ import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.stateIn import kotlinx.coroutines.launch +@Immutable sealed interface PodcastUiState { data object Loading : PodcastUiState data class Ready(val podcast: PodcastInfo, val episodes: List) : PodcastUiState @@ -71,7 +73,7 @@ class PodcastDetailsViewModel @AssistedInject constructor( initialValue = PodcastUiState.Loading, ) - fun toggleSusbcribe(podcast: PodcastInfo) { + fun toggleSubscribe(podcast: PodcastInfo) { viewModelScope.launch { podcastStore.togglePodcastFollowed(podcast.uri) } diff --git a/Jetcaster/stability_config.conf b/Jetcaster/stability_config.conf new file mode 100644 index 000000000..a2593c14d --- /dev/null +++ b/Jetcaster/stability_config.conf @@ -0,0 +1,2 @@ +java.time.* +kotlin.collections.* diff --git a/Jetcaster/tv/build.gradle.kts b/Jetcaster/tv/build.gradle.kts index 9b890da4f..ba509ef74 100644 --- a/Jetcaster/tv/build.gradle.kts +++ b/Jetcaster/tv/build.gradle.kts @@ -92,6 +92,12 @@ android { excludes += "/META-INF/{AL2.0,LGPL2.1}" } } + + composeCompiler { + reportsDestination = layout.buildDirectory.dir("compose_compiler") + metricsDestination = layout.buildDirectory.dir("compose_compiler") + stabilityConfigurationFiles = listOf(rootProject.layout.projectDirectory.file("stability_config.conf")) + } } dependencies { diff --git a/Jetcaster/wear/build.gradle b/Jetcaster/wear/build.gradle index a21e5a581..77580edf3 100644 --- a/Jetcaster/wear/build.gradle +++ b/Jetcaster/wear/build.gradle @@ -70,6 +70,12 @@ android { excludes += "rome-utils-" + libs.rometools.rome.get().version + ".jar" } } + + composeCompiler { + reportsDestination = layout.buildDirectory.dir("compose_compiler") + metricsDestination = layout.buildDirectory.dir("compose_compiler") + stabilityConfigurationFile = rootProject.layout.projectDirectory.file("stability_config.conf") + } } dependencies {