diff --git a/app/build.gradle b/app/build.gradle index e41969941..99fc8c3b2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -84,9 +84,12 @@ dependencies { implementation projects.core.logger implementation projects.data.repository.api implementation projects.data.model - implementation projects.feature.home - implementation projects.feature.detail - implementation projects.feature.search + implementation projects.feature.home.api + runtimeOnly projects.feature.home.impl + implementation projects.feature.detail.api + runtimeOnly projects.feature.detail.impl + implementation projects.feature.search.api + runtimeOnly projects.feature.search.impl implementation projects.feature.settings.api runtimeOnly projects.feature.settings.impl implementation projects.feature.navigator.api diff --git a/app/src/main/java/soup/movie/ui/main/MainNavGraph.kt b/app/src/main/java/soup/movie/ui/main/MainNavGraph.kt index 8336f91fb..7a7e395a8 100644 --- a/app/src/main/java/soup/movie/ui/main/MainNavGraph.kt +++ b/app/src/main/java/soup/movie/ui/main/MainNavGraph.kt @@ -16,19 +16,15 @@ package soup.movie.ui.main import androidx.compose.runtime.Composable -import androidx.hilt.navigation.compose.hiltViewModel import androidx.navigation.NavController import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import androidx.navigation.navArgument import soup.movie.core.designsystem.windowsizeclass.WindowWidthSizeClass -import soup.movie.feature.detail.DetailNavGraph -import soup.movie.feature.detail.DetailViewModel -import soup.movie.feature.home.HomeViewModel -import soup.movie.feature.home.MainScreen -import soup.movie.feature.search.SearchScreen -import soup.movie.feature.search.SearchViewModel +import soup.movie.feature.detail.rememberDetailComposableFactory +import soup.movie.feature.home.rememberHomeComposableFactory +import soup.movie.feature.search.rememberSearchComposableFactory private enum class Screen(val route: String) { Main("main"), @@ -50,10 +46,9 @@ fun MainNavGraph( startDestination = Screen.Main.route, ) { composable(Screen.Main.route) { - val viewModel = hiltViewModel() - MainScreen( + val factory = rememberHomeComposableFactory() + factory.HomeNavGraph( widthSizeClass = widthSizeClass, - viewModel = viewModel, onSearchClick = { navController.navigate(Screen.Search.route) }, @@ -63,9 +58,8 @@ fun MainNavGraph( ) } composable(Screen.Search.route) { - val viewModel = hiltViewModel() - SearchScreen( - viewModel = viewModel, + val factory = rememberSearchComposableFactory() + factory.SearchScreen( upPress = { navController.navigateUp() }, onItemClick = { navController.navigateToDetail(movieId = it.id) @@ -76,10 +70,8 @@ fun MainNavGraph( route = Screen.Detail.route + "/{movieId}", arguments = listOf(navArgument("movieId") { nullable = false }), ) { - val viewModel = hiltViewModel() - DetailNavGraph( - viewModel = viewModel, - ) + val factory = rememberDetailComposableFactory() + factory.DetailNavGraph() } } } diff --git a/feature/detail/.gitignore b/feature/detail/api/.gitignore similarity index 100% rename from feature/detail/.gitignore rename to feature/detail/api/.gitignore diff --git a/feature/detail/api/build.gradle b/feature/detail/api/build.gradle new file mode 100644 index 000000000..224a6ab97 --- /dev/null +++ b/feature/detail/api/build.gradle @@ -0,0 +1,19 @@ +plugins { + id "moop.android.library" + id "moop.android.compose" + id "moop.android.hilt" +} + +android { + namespace "soup.movie.feature.detail" +} + +dependencies { + implementation projects.core.kotlin + implementation projects.core.designsystem + implementation projects.core.resources + + implementation libs.kotlin.stdlib + + implementation libs.compose.foundation +} diff --git a/feature/detail/src/main/AndroidManifest.xml b/feature/detail/api/src/main/AndroidManifest.xml similarity index 100% rename from feature/detail/src/main/AndroidManifest.xml rename to feature/detail/api/src/main/AndroidManifest.xml diff --git a/feature/detail/api/src/main/java/soup/movie/feature/detail/DetailComposableFactory.kt b/feature/detail/api/src/main/java/soup/movie/feature/detail/DetailComposableFactory.kt new file mode 100644 index 000000000..a403c98c4 --- /dev/null +++ b/feature/detail/api/src/main/java/soup/movie/feature/detail/DetailComposableFactory.kt @@ -0,0 +1,45 @@ +/* + * Copyright 2024 SOUP + * + * 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 soup.movie.feature.detail + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.platform.LocalContext +import dagger.hilt.EntryPoint +import dagger.hilt.InstallIn +import dagger.hilt.android.EntryPointAccessors +import dagger.hilt.components.SingletonComponent + +interface DetailComposableFactory { + @Composable + fun DetailNavGraph() +} + +@Composable +fun rememberDetailComposableFactory(): DetailComposableFactory { + val context = LocalContext.current + return remember(context) { + EntryPointAccessors + .fromApplication(context, DetailComposableFactoryEntryPoint::class.java) + .detailComposableFactory() + } +} + +@EntryPoint +@InstallIn(SingletonComponent::class) +interface DetailComposableFactoryEntryPoint { + fun detailComposableFactory(): DetailComposableFactory +} diff --git a/feature/home/.gitignore b/feature/detail/impl/.gitignore similarity index 100% rename from feature/home/.gitignore rename to feature/detail/impl/.gitignore diff --git a/feature/detail/build.gradle b/feature/detail/impl/build.gradle similarity index 88% rename from feature/detail/build.gradle rename to feature/detail/impl/build.gradle index 4a4d04a41..f259b8c39 100644 --- a/feature/detail/build.gradle +++ b/feature/detail/impl/build.gradle @@ -5,7 +5,7 @@ plugins { } android { - namespace "soup.movie.feature.detail" + namespace "soup.movie.feature.detail.impl" } dependencies { @@ -18,7 +18,8 @@ dependencies { implementation projects.data.repository.api implementation projects.data.model implementation projects.domain - implementation projects.feature.home + implementation projects.feature.home.api + implementation projects.feature.detail.api implementation libs.kotlin.stdlib diff --git a/feature/home/src/main/AndroidManifest.xml b/feature/detail/impl/src/main/AndroidManifest.xml similarity index 100% rename from feature/home/src/main/AndroidManifest.xml rename to feature/detail/impl/src/main/AndroidManifest.xml diff --git a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailComposableFactoryImpl.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailComposableFactoryImpl.kt new file mode 100644 index 000000000..33383bf4f --- /dev/null +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailComposableFactoryImpl.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2024 SOUP + * + * 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 soup.movie.feature.detail.impl + +import androidx.compose.runtime.Composable +import androidx.hilt.navigation.compose.hiltViewModel +import soup.movie.feature.detail.DetailComposableFactory +import javax.inject.Inject + +class DetailComposableFactoryImpl @Inject constructor() : DetailComposableFactory { + + @Composable + override fun DetailNavGraph() { + DetailNavGraph( + viewModel = hiltViewModel(), + ) + } +} diff --git a/feature/detail/src/main/java/soup/movie/feature/detail/DetailContent.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailContent.kt similarity index 98% rename from feature/detail/src/main/java/soup/movie/feature/detail/DetailContent.kt rename to feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailContent.kt index 6a8e6b554..cf442ffad 100644 --- a/feature/detail/src/main/java/soup/movie/feature/detail/DetailContent.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailContent.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.detail +package soup.movie.feature.detail.impl import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize diff --git a/feature/detail/src/main/java/soup/movie/feature/detail/DetailError.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailError.kt similarity index 98% rename from feature/detail/src/main/java/soup/movie/feature/detail/DetailError.kt rename to feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailError.kt index 30edd2bae..096df5efb 100644 --- a/feature/detail/src/main/java/soup/movie/feature/detail/DetailError.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailError.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.detail +package soup.movie.feature.detail.impl import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement diff --git a/feature/detail/src/main/java/soup/movie/feature/detail/DetailEventModel.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailEventModel.kt similarity index 95% rename from feature/detail/src/main/java/soup/movie/feature/detail/DetailEventModel.kt rename to feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailEventModel.kt index 2cec1ddac..1fce56abe 100644 --- a/feature/detail/src/main/java/soup/movie/feature/detail/DetailEventModel.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailEventModel.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.detail +package soup.movie.feature.detail.impl import androidx.annotation.Keep import androidx.annotation.StringRes diff --git a/feature/detail/src/main/java/soup/movie/feature/detail/DetailHeader.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailHeader.kt similarity index 98% rename from feature/detail/src/main/java/soup/movie/feature/detail/DetailHeader.kt rename to feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailHeader.kt index a659b36f2..4372fcc91 100644 --- a/feature/detail/src/main/java/soup/movie/feature/detail/DetailHeader.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailHeader.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.detail +package soup.movie.feature.detail.impl import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi import androidx.compose.animation.graphics.res.animatedVectorResource @@ -49,8 +49,7 @@ import soup.movie.core.designsystem.theme.MovieTheme import soup.movie.core.imageloading.AsyncImage import soup.movie.domain.movie.getDDayLabel import soup.movie.domain.movie.isDDay -import soup.movie.feature.home.favorite.MovieAgeTag -import soup.movie.feature.home.favorite.MovieDDayTag +import soup.movie.feature.home.rememberHomeComposableFactory import soup.movie.model.MovieModel import soup.movie.resources.R @@ -62,6 +61,7 @@ internal fun DetailHeader( modifier: Modifier = Modifier, actions: @Composable () -> Unit = {}, ) { + val factory = rememberHomeComposableFactory() val movie: MovieModel = uiModel.movie Column(modifier = modifier) { Row(modifier = Modifier.fillMaxWidth().padding(horizontal = 16.dp)) { @@ -100,12 +100,12 @@ internal fun DetailHeader( ) } Column { - MovieAgeTag( + factory.MovieAgeTag( age = movie.age, modifier = Modifier.padding(top = 12.dp), ) if (movie.isDDay()) { - MovieDDayTag( + factory.MovieDDayTag( text = movie.getDDayLabel().orEmpty(), modifier = Modifier.padding(top = 4.dp), ) diff --git a/feature/detail/src/main/java/soup/movie/feature/detail/DetailList.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailList.kt similarity index 99% rename from feature/detail/src/main/java/soup/movie/feature/detail/DetailList.kt rename to feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailList.kt index a152704f0..b2737554b 100644 --- a/feature/detail/src/main/java/soup/movie/feature/detail/DetailList.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailList.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.detail +package soup.movie.feature.detail.impl import androidx.compose.animation.animateContentSize import androidx.compose.animation.core.tween diff --git a/feature/detail/src/main/java/soup/movie/feature/detail/DetailNavGraph.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailNavGraph.kt similarity index 98% rename from feature/detail/src/main/java/soup/movie/feature/detail/DetailNavGraph.kt rename to feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailNavGraph.kt index ecfe21e39..803602691 100644 --- a/feature/detail/src/main/java/soup/movie/feature/detail/DetailNavGraph.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailNavGraph.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.detail +package soup.movie.feature.detail.impl import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn diff --git a/feature/detail/src/main/java/soup/movie/feature/detail/DetailPoster.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailPoster.kt similarity index 98% rename from feature/detail/src/main/java/soup/movie/feature/detail/DetailPoster.kt rename to feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailPoster.kt index 420b4dafc..287b8083d 100644 --- a/feature/detail/src/main/java/soup/movie/feature/detail/DetailPoster.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailPoster.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.detail +package soup.movie.feature.detail.impl import androidx.activity.compose.BackHandler import androidx.compose.foundation.background diff --git a/feature/detail/src/main/java/soup/movie/feature/detail/DetailScreen.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailScreen.kt similarity index 99% rename from feature/detail/src/main/java/soup/movie/feature/detail/DetailScreen.kt rename to feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailScreen.kt index de1072616..c03fd9375 100644 --- a/feature/detail/src/main/java/soup/movie/feature/detail/DetailScreen.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailScreen.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.detail +package soup.movie.feature.detail.impl import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize diff --git a/feature/detail/src/main/java/soup/movie/feature/detail/DetailUiModel.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailUiModel.kt similarity index 98% rename from feature/detail/src/main/java/soup/movie/feature/detail/DetailUiModel.kt rename to feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailUiModel.kt index 40382de96..06f363470 100644 --- a/feature/detail/src/main/java/soup/movie/feature/detail/DetailUiModel.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailUiModel.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.detail +package soup.movie.feature.detail.impl import androidx.annotation.Keep import soup.movie.model.CompanyModel diff --git a/feature/detail/src/main/java/soup/movie/feature/detail/DetailViewModel.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailViewModel.kt similarity index 99% rename from feature/detail/src/main/java/soup/movie/feature/detail/DetailViewModel.kt rename to feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailViewModel.kt index ea1a2ed0f..ecc010f39 100644 --- a/feature/detail/src/main/java/soup/movie/feature/detail/DetailViewModel.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailViewModel.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.detail +package soup.movie.feature.detail.impl import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel diff --git a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/di/FeatureDetailModule.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/di/FeatureDetailModule.kt new file mode 100644 index 000000000..39a7623b2 --- /dev/null +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/di/FeatureDetailModule.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2024 SOUP + * + * 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 soup.movie.feature.detail.impl.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import soup.movie.feature.detail.DetailComposableFactory +import soup.movie.feature.detail.impl.DetailComposableFactoryImpl + +@Module +@InstallIn(SingletonComponent::class) +interface FeatureDetailModule { + + @Binds + fun bindsDetailComposableFactoryImpl( + impl: DetailComposableFactoryImpl, + ): DetailComposableFactory +} diff --git a/feature/search/.gitignore b/feature/home/api/.gitignore similarity index 100% rename from feature/search/.gitignore rename to feature/home/api/.gitignore diff --git a/feature/home/api/build.gradle b/feature/home/api/build.gradle new file mode 100644 index 000000000..26c521623 --- /dev/null +++ b/feature/home/api/build.gradle @@ -0,0 +1,19 @@ +plugins { + id "moop.android.library" + id "moop.android.compose" + id "moop.android.hilt" +} + +android { + namespace "soup.movie.feature.home" +} + +dependencies { + implementation projects.core.kotlin + implementation projects.core.designsystem + implementation projects.data.model + + implementation libs.kotlin.stdlib + + implementation libs.compose.foundation +} diff --git a/feature/search/src/main/AndroidManifest.xml b/feature/home/api/src/main/AndroidManifest.xml similarity index 100% rename from feature/search/src/main/AndroidManifest.xml rename to feature/home/api/src/main/AndroidManifest.xml diff --git a/feature/home/api/src/main/java/soup/movie/feature/home/HomeComposableFactory.kt b/feature/home/api/src/main/java/soup/movie/feature/home/HomeComposableFactory.kt new file mode 100644 index 000000000..e5db6a5e1 --- /dev/null +++ b/feature/home/api/src/main/java/soup/movie/feature/home/HomeComposableFactory.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2024 SOUP + * + * 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 soup.movie.feature.home + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import dagger.hilt.EntryPoint +import dagger.hilt.InstallIn +import dagger.hilt.android.EntryPointAccessors +import dagger.hilt.components.SingletonComponent +import soup.movie.core.designsystem.windowsizeclass.WindowWidthSizeClass +import soup.movie.model.MovieModel + +interface HomeComposableFactory { + + @Composable + fun HomeNavGraph( + widthSizeClass: WindowWidthSizeClass, + onSearchClick: () -> Unit, + onMovieItemClick: (MovieModel) -> Unit, + ) + + @Composable + fun MovieList( + movies: List, + onItemClick: (MovieModel) -> Unit, + onLongItemClick: (MovieModel) -> Unit, + modifier: Modifier, + ) + + @Composable + fun NoMovieItems( + modifier: Modifier, + ) + + @Composable + fun MovieAgeTag( + age: Int, + modifier: Modifier, + ) + + @Composable + fun MovieDDayTag( + text: String, + modifier: Modifier, + ) +} + +@Composable +fun rememberHomeComposableFactory(): HomeComposableFactory { + val context = LocalContext.current + return remember(context) { + EntryPointAccessors + .fromApplication(context, HomeComposableFactoryEntryPoint::class.java) + .homeComposableFactory() + } +} + +@EntryPoint +@InstallIn(SingletonComponent::class) +interface HomeComposableFactoryEntryPoint { + fun homeComposableFactory(): HomeComposableFactory +} diff --git a/feature/home/impl/.gitignore b/feature/home/impl/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/feature/home/impl/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature/home/build.gradle b/feature/home/impl/build.gradle similarity index 91% rename from feature/home/build.gradle rename to feature/home/impl/build.gradle index 82a6d43ab..86e9e9b6c 100644 --- a/feature/home/build.gradle +++ b/feature/home/impl/build.gradle @@ -5,7 +5,7 @@ plugins { } android { - namespace "soup.movie.feature.home" + namespace "soup.movie.feature.home.impl" } dependencies { @@ -18,6 +18,7 @@ dependencies { implementation projects.data.repository.api implementation projects.data.model implementation projects.domain + implementation projects.feature.home.api implementation projects.feature.settings.api implementation libs.kotlin.stdlib diff --git a/feature/home/impl/src/main/AndroidManifest.xml b/feature/home/impl/src/main/AndroidManifest.xml new file mode 100644 index 000000000..cc947c567 --- /dev/null +++ b/feature/home/impl/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeComposableFactoryImpl.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeComposableFactoryImpl.kt new file mode 100644 index 000000000..66a56698b --- /dev/null +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeComposableFactoryImpl.kt @@ -0,0 +1,87 @@ +/* + * Copyright 2024 SOUP + * + * 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 soup.movie.feature.home.impl + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.hilt.navigation.compose.hiltViewModel +import soup.movie.core.designsystem.windowsizeclass.WindowWidthSizeClass +import soup.movie.feature.home.HomeComposableFactory +import soup.movie.model.MovieModel +import javax.inject.Inject + +class HomeComposableFactoryImpl @Inject constructor() : HomeComposableFactory { + + @Composable + override fun HomeNavGraph( + widthSizeClass: WindowWidthSizeClass, + onSearchClick: () -> Unit, + onMovieItemClick: (MovieModel) -> Unit, + ) { + HomeNavGraph( + widthSizeClass = widthSizeClass, + viewModel = hiltViewModel(), + onSearchClick = onSearchClick, + onMovieItemClick = onMovieItemClick, + ) + } + + @Composable + override fun MovieList( + movies: List, + onItemClick: (MovieModel) -> Unit, + onLongItemClick: (MovieModel) -> Unit, + modifier: Modifier, + ) { + soup.movie.feature.home.impl.tab.MovieList( + movies = movies, + onItemClick = onItemClick, + onLongItemClick = onLongItemClick, + modifier = modifier, + ) + } + + @Composable + override fun NoMovieItems( + modifier: Modifier, + ) { + soup.movie.feature.home.impl.tab.NoMovieItems( + modifier = modifier, + ) + } + + @Composable + override fun MovieAgeTag( + age: Int, + modifier: Modifier, + ) { + soup.movie.feature.home.impl.favorite.MovieAgeTag( + age = age, + modifier = modifier, + ) + } + + @Composable + override fun MovieDDayTag( + text: String, + modifier: Modifier, + ) { + soup.movie.feature.home.impl.favorite.MovieDDayTag( + text = text, + modifier = modifier, + ) + } +} diff --git a/feature/home/src/main/java/soup/movie/feature/home/MainScreen.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeNavGraph.kt similarity index 98% rename from feature/home/src/main/java/soup/movie/feature/home/MainScreen.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeNavGraph.kt index 080c9d9b1..a3d5791f1 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/MainScreen.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeNavGraph.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home +package soup.movie.feature.home.impl import androidx.compose.animation.graphics.ExperimentalAnimationGraphicsApi import androidx.compose.animation.graphics.res.animatedVectorResource @@ -49,13 +49,13 @@ import soup.movie.core.designsystem.icon.MovieIcons import soup.movie.core.designsystem.showToast import soup.movie.core.designsystem.theme.MovieTheme import soup.movie.core.designsystem.windowsizeclass.WindowWidthSizeClass -import soup.movie.feature.home.favorite.HomeFavoriteList +import soup.movie.feature.home.impl.favorite.HomeFavoriteList import soup.movie.feature.settings.rememberSettingsComposableFactory import soup.movie.model.MovieModel import soup.movie.resources.R @Composable -fun MainScreen( +fun HomeNavGraph( widthSizeClass: WindowWidthSizeClass, viewModel: HomeViewModel, onSearchClick: () -> Unit, diff --git a/feature/home/src/main/java/soup/movie/feature/home/HomeScreen.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeScreen.kt similarity index 95% rename from feature/home/src/main/java/soup/movie/feature/home/HomeScreen.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeScreen.kt index c737c65f1..e36218190 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/HomeScreen.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeScreen.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home +package soup.movie.feature.home.impl import androidx.activity.compose.BackHandler import androidx.compose.foundation.clickable @@ -29,7 +29,6 @@ import androidx.compose.material.BottomSheetScaffold import androidx.compose.material.BottomSheetValue import androidx.compose.material.ContentAlpha import androidx.compose.material.Divider -import androidx.compose.material.ExperimentalMaterialApi import androidx.compose.material.FloatingActionButton import androidx.compose.material.Icon import androidx.compose.material.IconButton @@ -53,15 +52,14 @@ import kotlinx.coroutines.launch import soup.movie.core.designsystem.icon.MovieIcons import soup.movie.core.designsystem.showToast import soup.movie.core.designsystem.theme.MovieTheme -import soup.movie.feature.home.filter.HomeFilterScreen -import soup.movie.feature.home.now.HomeNowList -import soup.movie.feature.home.plan.HomePlanList +import soup.movie.feature.home.impl.filter.HomeFilterScreen +import soup.movie.feature.home.impl.now.HomeNowList +import soup.movie.feature.home.impl.plan.HomePlanList import soup.movie.model.MovieModel import soup.movie.resources.R -@OptIn(ExperimentalMaterialApi::class) @Composable -internal fun HomeScreen( +fun HomeScreen( viewModel: HomeViewModel, onSearchClick: () -> Unit, onMovieItemClick: (MovieModel) -> Unit, @@ -70,7 +68,7 @@ internal fun HomeScreen( val coroutineScope = rememberCoroutineScope() val selectedTab by viewModel.selectedHomeTab.collectAsState() - val homeTabs = HomeTabUiModel.values() + val homeTabs = remember { HomeTabUiModel.entries.toTypedArray() } val gridStates = homeTabs.map { rememberLazyGridState() } val isTopAtCurrentTab by remember { derivedStateOf { diff --git a/feature/home/src/main/java/soup/movie/feature/home/HomeUiModel.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeUiModel.kt similarity index 94% rename from feature/home/src/main/java/soup/movie/feature/home/HomeUiModel.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeUiModel.kt index 09301ece9..ecff402dc 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/HomeUiModel.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeUiModel.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home +package soup.movie.feature.home.impl enum class MainTabUiModel { Home, Favorite, Settings diff --git a/feature/home/src/main/java/soup/movie/feature/home/HomeViewModel.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeViewModel.kt similarity index 97% rename from feature/home/src/main/java/soup/movie/feature/home/HomeViewModel.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeViewModel.kt index 4077d69f9..b0737ef1d 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/HomeViewModel.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeViewModel.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home +package soup.movie.feature.home.impl import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope diff --git a/feature/home/src/main/java/soup/movie/feature/home/TextUnit.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/TextUnit.kt similarity index 95% rename from feature/home/src/main/java/soup/movie/feature/home/TextUnit.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/TextUnit.kt index ce1264863..479183dba 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/TextUnit.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/TextUnit.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home +package soup.movie.feature.home.impl import androidx.compose.runtime.Composable import androidx.compose.ui.platform.LocalDensity diff --git a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/di/FeatureHomeModule.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/di/FeatureHomeModule.kt new file mode 100644 index 000000000..56ed31fb9 --- /dev/null +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/di/FeatureHomeModule.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2024 SOUP + * + * 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 soup.movie.feature.home.impl.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import soup.movie.feature.home.HomeComposableFactory +import soup.movie.feature.home.impl.HomeComposableFactoryImpl + +@Module +@InstallIn(SingletonComponent::class) +interface FeatureHomeModule { + + @Binds + fun bindsHomeComposableFactory( + impl: HomeComposableFactoryImpl, + ): HomeComposableFactory +} diff --git a/feature/home/src/main/java/soup/movie/feature/home/domain/AppSettingsExt.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/domain/AppSettingsExt.kt similarity index 96% rename from feature/home/src/main/java/soup/movie/feature/home/domain/AppSettingsExt.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/domain/AppSettingsExt.kt index 8a604febc..7835b8e3e 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/domain/AppSettingsExt.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/domain/AppSettingsExt.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.domain +package soup.movie.feature.home.impl.domain import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.combine diff --git a/feature/home/src/main/java/soup/movie/feature/home/domain/MovieFilter.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/domain/MovieFilter.kt similarity index 97% rename from feature/home/src/main/java/soup/movie/feature/home/domain/MovieFilter.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/domain/MovieFilter.kt index 51ae7be66..c8d8fd056 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/domain/MovieFilter.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/domain/MovieFilter.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.domain +package soup.movie.feature.home.impl.domain import soup.movie.model.MovieModel import soup.movie.model.settings.AgeFilter diff --git a/feature/home/src/main/java/soup/movie/feature/home/favorite/HomeFavoriteList.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/HomeFavoriteList.kt similarity index 94% rename from feature/home/src/main/java/soup/movie/feature/home/favorite/HomeFavoriteList.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/HomeFavoriteList.kt index e869e8860..cdf2a370d 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/favorite/HomeFavoriteList.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/HomeFavoriteList.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.favorite +package soup.movie.feature.home.impl.favorite import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Box @@ -34,13 +34,13 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import kotlinx.coroutines.launch -import soup.movie.feature.home.tab.MovieList -import soup.movie.feature.home.tab.NoMovieItems +import soup.movie.feature.home.impl.tab.MovieList +import soup.movie.feature.home.impl.tab.NoMovieItems import soup.movie.model.MovieModel import soup.movie.resources.R @Composable -internal fun HomeFavoriteList( +fun HomeFavoriteList( viewModel: HomeFavoriteViewModel, modifier: Modifier = Modifier, state: LazyGridState = rememberLazyGridState(), diff --git a/feature/home/src/main/java/soup/movie/feature/home/favorite/HomeFavoriteViewModel.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/HomeFavoriteViewModel.kt similarity index 97% rename from feature/home/src/main/java/soup/movie/feature/home/favorite/HomeFavoriteViewModel.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/HomeFavoriteViewModel.kt index 36358bd65..54ae67462 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/favorite/HomeFavoriteViewModel.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/HomeFavoriteViewModel.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.favorite +package soup.movie.feature.home.impl.favorite import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope diff --git a/feature/home/src/main/java/soup/movie/feature/home/favorite/MovieAgeTag.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieAgeBadge.kt similarity index 69% rename from feature/home/src/main/java/soup/movie/feature/home/favorite/MovieAgeTag.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieAgeBadge.kt index aada7e580..b91015d32 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/favorite/MovieAgeTag.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieAgeBadge.kt @@ -1,5 +1,5 @@ /* - * Copyright 2021 SOUP + * Copyright 2024 SOUP * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.favorite +package soup.movie.feature.home.impl.favorite import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -25,10 +25,9 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.dp import soup.movie.core.designsystem.theme.MovieTheme -import soup.movie.feature.home.textUnit @Composable -internal fun MovieAgeBadge( +fun MovieAgeBadge( age: Int, modifier: Modifier = Modifier, ) { @@ -46,23 +45,3 @@ internal fun MovieAgeBadge( .border(1.dp, MovieTheme.colors.background, shape = RoundedCornerShape(5.dp)), ) } - -@Composable -fun MovieAgeTag( - age: Int, - modifier: Modifier = Modifier, -) { - val (text, color) = when { - age >= 19 -> "청불" to MovieTheme.colors.ageTag19 - age >= 15 -> "15" to MovieTheme.colors.ageTag15 - age >= 12 -> "12" to MovieTheme.colors.ageTag12 - age >= 0 -> "전체" to MovieTheme.colors.ageTagAll - else -> "미정" to MovieTheme.colors.ageTagUnknown - } - MovieTextTag( - text = text, - tagBackgroundColor = color, - modifier = modifier, - fontSize = 12.dp.textUnit, - ) -} diff --git a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieAgeTag.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieAgeTag.kt new file mode 100644 index 000000000..af2b9138c --- /dev/null +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieAgeTag.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2021 SOUP + * + * 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 soup.movie.feature.home.impl.favorite + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import soup.movie.core.designsystem.theme.MovieTheme +import soup.movie.feature.home.impl.textUnit + +@Composable +fun MovieAgeTag( + age: Int, + modifier: Modifier = Modifier, +) { + val (text, color) = when { + age >= 19 -> "청불" to MovieTheme.colors.ageTag19 + age >= 15 -> "15" to MovieTheme.colors.ageTag15 + age >= 12 -> "12" to MovieTheme.colors.ageTag12 + age >= 0 -> "전체" to MovieTheme.colors.ageTagAll + else -> "미정" to MovieTheme.colors.ageTagUnknown + } + MovieTextTag( + text = text, + tagBackgroundColor = color, + modifier = modifier, + fontSize = 12.dp.textUnit, + ) +} diff --git a/feature/home/src/main/java/soup/movie/feature/home/favorite/MovieDDayTag.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieDDayTag.kt similarity index 91% rename from feature/home/src/main/java/soup/movie/feature/home/favorite/MovieDDayTag.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieDDayTag.kt index a2851a33f..51f38c785 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/favorite/MovieDDayTag.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieDDayTag.kt @@ -13,13 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.favorite +package soup.movie.feature.home.impl.favorite import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.unit.dp import soup.movie.core.designsystem.theme.MovieTheme -import soup.movie.feature.home.textUnit +import soup.movie.feature.home.impl.textUnit @Composable fun MovieDDayTag( diff --git a/feature/home/src/main/java/soup/movie/feature/home/favorite/MovieTextTag.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieTextTag.kt similarity index 96% rename from feature/home/src/main/java/soup/movie/feature/home/favorite/MovieTextTag.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieTextTag.kt index 8cb447fb4..805485eb3 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/favorite/MovieTextTag.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieTextTag.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.favorite +package soup.movie.feature.home.impl.favorite import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -34,7 +34,7 @@ import androidx.compose.ui.unit.em import soup.movie.core.designsystem.theme.MovieTheme @Composable -internal fun MovieTextTag( +fun MovieTextTag( text: String, tagBackgroundColor: Color, modifier: Modifier = Modifier, diff --git a/feature/home/src/main/java/soup/movie/feature/home/filter/HomeFilterScreen.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/HomeFilterScreen.kt similarity index 99% rename from feature/home/src/main/java/soup/movie/feature/home/filter/HomeFilterScreen.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/HomeFilterScreen.kt index 2c9bde15b..a1803b14b 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/filter/HomeFilterScreen.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/HomeFilterScreen.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.filter +package soup.movie.feature.home.impl.filter import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -54,7 +54,7 @@ import soup.movie.core.designsystem.theme.MovieTheme import soup.movie.resources.R @Composable -internal fun HomeFilterScreen( +fun HomeFilterScreen( viewModel: HomeFilterViewModel, ) { LazyColumn( diff --git a/feature/home/src/main/java/soup/movie/feature/home/filter/HomeFilterUiModel.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/HomeFilterUiModel.kt similarity index 95% rename from feature/home/src/main/java/soup/movie/feature/home/filter/HomeFilterUiModel.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/HomeFilterUiModel.kt index e5a1ad61b..78c714000 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/filter/HomeFilterUiModel.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/HomeFilterUiModel.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.filter +package soup.movie.feature.home.impl.filter import androidx.annotation.Keep diff --git a/feature/home/src/main/java/soup/movie/feature/home/filter/HomeFilterViewModel.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/HomeFilterViewModel.kt similarity index 99% rename from feature/home/src/main/java/soup/movie/feature/home/filter/HomeFilterViewModel.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/HomeFilterViewModel.kt index 166ceb6d3..34f8a9dcd 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/filter/HomeFilterViewModel.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/HomeFilterViewModel.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.filter +package soup.movie.feature.home.impl.filter import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf diff --git a/feature/home/src/main/java/soup/movie/feature/home/filter/TheaterFilterChip.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/TheaterFilterChip.kt similarity index 97% rename from feature/home/src/main/java/soup/movie/feature/home/filter/TheaterFilterChip.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/TheaterFilterChip.kt index ff5c6742a..14d099102 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/filter/TheaterFilterChip.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/TheaterFilterChip.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.filter +package soup.movie.feature.home.impl.filter import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image @@ -33,7 +33,7 @@ import soup.movie.core.designsystem.theme.MovieTheme @OptIn(ExperimentalMaterialApi::class) @Composable -internal fun CgvFilterChip( +fun CgvFilterChip( text: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit, @@ -75,7 +75,7 @@ internal fun CgvFilterChip( @OptIn(ExperimentalMaterialApi::class) @Composable -internal fun LotteFilterChip( +fun LotteFilterChip( text: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit, @@ -110,7 +110,7 @@ internal fun LotteFilterChip( @OptIn(ExperimentalMaterialApi::class) @Composable -internal fun MegaboxFilterChip( +fun MegaboxFilterChip( text: String, checked: Boolean, onCheckedChange: (Boolean) -> Unit, diff --git a/feature/home/src/main/java/soup/movie/feature/home/now/HomeNowList.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/now/HomeNowList.kt similarity index 92% rename from feature/home/src/main/java/soup/movie/feature/home/now/HomeNowList.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/now/HomeNowList.kt index 9f9a8280a..0cecd3b77 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/now/HomeNowList.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/now/HomeNowList.kt @@ -13,18 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.now +package soup.movie.feature.home.impl.now import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import soup.movie.feature.home.tab.HomeContentsScreen +import soup.movie.feature.home.impl.tab.HomeContentsScreen import soup.movie.model.MovieModel @Composable -internal fun HomeNowList( +fun HomeNowList( viewModel: HomeNowViewModel, state: LazyGridState = rememberLazyGridState(), onItemClick: (MovieModel) -> Unit, diff --git a/feature/home/src/main/java/soup/movie/feature/home/now/HomeNowViewModel.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/now/HomeNowViewModel.kt similarity index 96% rename from feature/home/src/main/java/soup/movie/feature/home/now/HomeNowViewModel.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/now/HomeNowViewModel.kt index f17674745..f005d5d23 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/now/HomeNowViewModel.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/now/HomeNowViewModel.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.now +package soup.movie.feature.home.impl.now import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -26,7 +26,7 @@ import kotlinx.coroutines.flow.onStart import kotlinx.coroutines.launch import soup.movie.data.repository.MovieRepository import soup.movie.data.settings.AppSettings -import soup.movie.feature.home.domain.getMovieFilterFlow +import soup.movie.feature.home.impl.domain.getMovieFilterFlow import soup.movie.log.Logger import soup.movie.model.MovieModel import javax.inject.Inject diff --git a/feature/home/src/main/java/soup/movie/feature/home/plan/HomePlanList.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/plan/HomePlanList.kt similarity index 92% rename from feature/home/src/main/java/soup/movie/feature/home/plan/HomePlanList.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/plan/HomePlanList.kt index 843a1cd34..3520a5f9e 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/plan/HomePlanList.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/plan/HomePlanList.kt @@ -13,18 +13,18 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.plan +package soup.movie.feature.home.impl.plan import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.foundation.lazy.grid.rememberLazyGridState import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import soup.movie.feature.home.tab.HomeContentsScreen +import soup.movie.feature.home.impl.tab.HomeContentsScreen import soup.movie.model.MovieModel @Composable -internal fun HomePlanList( +fun HomePlanList( viewModel: HomePlanViewModel, state: LazyGridState = rememberLazyGridState(), onItemClick: (MovieModel) -> Unit, diff --git a/feature/home/src/main/java/soup/movie/feature/home/plan/HomePlanViewModel.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/plan/HomePlanViewModel.kt similarity index 96% rename from feature/home/src/main/java/soup/movie/feature/home/plan/HomePlanViewModel.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/plan/HomePlanViewModel.kt index 8c1ce1e4a..8113895b6 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/plan/HomePlanViewModel.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/plan/HomePlanViewModel.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.plan +package soup.movie.feature.home.impl.plan import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope @@ -27,7 +27,7 @@ import kotlinx.coroutines.launch import soup.movie.data.repository.MovieRepository import soup.movie.data.settings.AppSettings import soup.movie.domain.movie.getDDay -import soup.movie.feature.home.domain.getMovieFilterFlow +import soup.movie.feature.home.impl.domain.getMovieFilterFlow import soup.movie.log.Logger import soup.movie.model.MovieModel import javax.inject.Inject diff --git a/feature/home/src/main/java/soup/movie/feature/home/tab/ContentLoadingProgressBar.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/ContentLoadingProgressBar.kt similarity index 97% rename from feature/home/src/main/java/soup/movie/feature/home/tab/ContentLoadingProgressBar.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/ContentLoadingProgressBar.kt index 0e2eac2d9..c8dad56f6 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/tab/ContentLoadingProgressBar.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/ContentLoadingProgressBar.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.tab +package soup.movie.feature.home.impl.tab import androidx.compose.animation.core.LinearEasing import androidx.compose.animation.core.animateFloat @@ -43,7 +43,7 @@ import soup.movie.core.designsystem.icon.MovieIcons import soup.movie.core.designsystem.theme.MovieTheme @Composable -internal fun ContentLoadingProgressBar( +fun ContentLoadingProgressBar( modifier: Modifier = Modifier, backgroundColor: Color = MovieTheme.colors.surface, contentColor: Color = contentColorFor(backgroundColor), diff --git a/feature/home/src/main/java/soup/movie/feature/home/tab/HomeContentsScreen.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/HomeContentsScreen.kt similarity index 98% rename from feature/home/src/main/java/soup/movie/feature/home/tab/HomeContentsScreen.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/HomeContentsScreen.kt index 0b127a107..e93208b0a 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/tab/HomeContentsScreen.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/HomeContentsScreen.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.tab +package soup.movie.feature.home.impl.tab import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.core.tween @@ -48,7 +48,7 @@ import soup.movie.model.MovieModel import soup.movie.resources.R @Composable -internal fun HomeContentsScreen( +fun HomeContentsScreen( movies: List, onItemClick: (MovieModel) -> Unit, onItemLongClick: (MovieModel) -> Unit, diff --git a/feature/home/src/main/java/soup/movie/feature/home/tab/MovieList.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/MovieList.kt similarity index 96% rename from feature/home/src/main/java/soup/movie/feature/home/tab/MovieList.kt rename to feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/MovieList.kt index eb5ed764d..f599bbe64 100644 --- a/feature/home/src/main/java/soup/movie/feature/home/tab/MovieList.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/MovieList.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.home.tab +package soup.movie.feature.home.impl.tab import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.Image @@ -43,8 +43,8 @@ import soup.movie.core.designsystem.theme.MovieTheme import soup.movie.core.imageloading.AsyncImage import soup.movie.domain.movie.getDDayLabel import soup.movie.domain.movie.isDDay -import soup.movie.feature.home.favorite.MovieAgeBadge -import soup.movie.feature.home.favorite.MovieDDayTag +import soup.movie.feature.home.impl.favorite.MovieAgeBadge +import soup.movie.feature.home.impl.favorite.MovieDDayTag import soup.movie.model.MovieModel import soup.movie.resources.R diff --git a/feature/search/api/.gitignore b/feature/search/api/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/feature/search/api/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature/search/api/build.gradle b/feature/search/api/build.gradle new file mode 100644 index 000000000..2ef6c0840 --- /dev/null +++ b/feature/search/api/build.gradle @@ -0,0 +1,17 @@ +plugins { + id "moop.android.library" + id "moop.android.compose" + id "moop.android.hilt" +} + +android { + namespace "soup.movie.feature.search" +} + +dependencies { + implementation projects.core.kotlin + implementation projects.core.designsystem + implementation projects.data.model + + implementation libs.compose.foundation +} diff --git a/feature/search/api/src/main/AndroidManifest.xml b/feature/search/api/src/main/AndroidManifest.xml new file mode 100644 index 000000000..cc947c567 --- /dev/null +++ b/feature/search/api/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/feature/search/api/src/main/java/soup/movie/feature/search/SearchComposableFactory.kt b/feature/search/api/src/main/java/soup/movie/feature/search/SearchComposableFactory.kt new file mode 100644 index 000000000..45f705ccc --- /dev/null +++ b/feature/search/api/src/main/java/soup/movie/feature/search/SearchComposableFactory.kt @@ -0,0 +1,50 @@ +/* + * Copyright 2024 SOUP + * + * 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 soup.movie.feature.search + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.remember +import androidx.compose.ui.platform.LocalContext +import dagger.hilt.EntryPoint +import dagger.hilt.InstallIn +import dagger.hilt.android.EntryPointAccessors +import dagger.hilt.components.SingletonComponent +import soup.movie.model.MovieModel + +interface SearchComposableFactory { + + @Composable + fun SearchScreen( + upPress: () -> Unit, + onItemClick: (MovieModel) -> Unit, + ) +} + +@Composable +fun rememberSearchComposableFactory(): SearchComposableFactory { + val context = LocalContext.current + return remember(context) { + EntryPointAccessors + .fromApplication(context, SearchComposableFactoryEntryPoint::class.java) + .searchComposableFactory() + } +} + +@EntryPoint +@InstallIn(SingletonComponent::class) +interface SearchComposableFactoryEntryPoint { + fun searchComposableFactory(): SearchComposableFactory +} diff --git a/feature/search/impl/.gitignore b/feature/search/impl/.gitignore new file mode 100644 index 000000000..42afabfd2 --- /dev/null +++ b/feature/search/impl/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/feature/search/build.gradle b/feature/search/impl/build.gradle similarity index 75% rename from feature/search/build.gradle rename to feature/search/impl/build.gradle index 9b105db49..4e2832e6d 100644 --- a/feature/search/build.gradle +++ b/feature/search/impl/build.gradle @@ -5,7 +5,7 @@ plugins { } android { - namespace "soup.movie.feature.search" + namespace "soup.movie.feature.search.impl" } dependencies { @@ -14,12 +14,14 @@ dependencies { implementation projects.core.resources implementation projects.data.repository.api implementation projects.data.model - implementation projects.feature.home + implementation projects.feature.search.api + implementation projects.feature.home.api implementation libs.compose.foundation implementation libs.compose.material implementation libs.compose.ui + implementation libs.androidx.hilt.navigation.compose implementation libs.androidx.lifecycle.viewmodel testImplementation projects.testing diff --git a/feature/search/impl/src/main/AndroidManifest.xml b/feature/search/impl/src/main/AndroidManifest.xml new file mode 100644 index 000000000..cc947c567 --- /dev/null +++ b/feature/search/impl/src/main/AndroidManifest.xml @@ -0,0 +1 @@ + diff --git a/feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchComposableFactoryImpl.kt b/feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchComposableFactoryImpl.kt new file mode 100644 index 000000000..af4e6cca7 --- /dev/null +++ b/feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchComposableFactoryImpl.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2024 SOUP + * + * 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 soup.movie.feature.search.impl + +import androidx.compose.runtime.Composable +import androidx.hilt.navigation.compose.hiltViewModel +import soup.movie.feature.search.SearchComposableFactory +import soup.movie.model.MovieModel +import javax.inject.Inject + +class SearchComposableFactoryImpl @Inject constructor() : SearchComposableFactory { + + @Composable + override fun SearchScreen( + upPress: () -> Unit, + onItemClick: (MovieModel) -> Unit, + ) { + SearchScreen( + viewModel = hiltViewModel(), + upPress = upPress, + onItemClick = onItemClick, + ) + } +} diff --git a/feature/search/src/main/java/soup/movie/feature/search/SearchScreen.kt b/feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchScreen.kt similarity index 95% rename from feature/search/src/main/java/soup/movie/feature/search/SearchScreen.kt rename to feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchScreen.kt index 2f01858f3..34eddb97e 100644 --- a/feature/search/src/main/java/soup/movie/feature/search/SearchScreen.kt +++ b/feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchScreen.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.search +package soup.movie.feature.search.impl import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize @@ -54,8 +54,7 @@ import androidx.compose.ui.unit.dp import soup.movie.core.designsystem.icon.MovieIcons import soup.movie.core.designsystem.showToast import soup.movie.core.designsystem.theme.MovieTheme -import soup.movie.feature.home.tab.MovieList -import soup.movie.feature.home.tab.NoMovieItems +import soup.movie.feature.home.rememberHomeComposableFactory import soup.movie.model.MovieModel import soup.movie.resources.R @@ -65,6 +64,7 @@ fun SearchScreen( upPress: () -> Unit, onItemClick: (MovieModel) -> Unit, ) { + val factory = rememberHomeComposableFactory() Scaffold( modifier = Modifier.systemBarsPadding(), topBar = { @@ -148,10 +148,10 @@ fun SearchScreen( .padding(paddingValues), ) { if (model.hasNoItem) { - NoMovieItems(modifier = Modifier.align(Alignment.Center)) + factory.NoMovieItems(modifier = Modifier.align(Alignment.Center)) } else { val context = LocalContext.current - MovieList( + factory.MovieList( movies = model.movies, onItemClick = { onItemClick(it) @@ -159,6 +159,7 @@ fun SearchScreen( onLongItemClick = { context.showToast(it.title) }, + modifier = Modifier, ) } } diff --git a/feature/search/src/main/java/soup/movie/feature/search/SearchUiModel.kt b/feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchUiModel.kt similarity index 95% rename from feature/search/src/main/java/soup/movie/feature/search/SearchUiModel.kt rename to feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchUiModel.kt index 717307fa9..5474f6742 100644 --- a/feature/search/src/main/java/soup/movie/feature/search/SearchUiModel.kt +++ b/feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchUiModel.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.search +package soup.movie.feature.search.impl import soup.movie.model.MovieModel diff --git a/feature/search/src/main/java/soup/movie/feature/search/SearchViewModel.kt b/feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchViewModel.kt similarity index 98% rename from feature/search/src/main/java/soup/movie/feature/search/SearchViewModel.kt rename to feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchViewModel.kt index 439fdca82..5e5e8bb11 100644 --- a/feature/search/src/main/java/soup/movie/feature/search/SearchViewModel.kt +++ b/feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchViewModel.kt @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package soup.movie.feature.search +package soup.movie.feature.search.impl import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope diff --git a/feature/search/impl/src/main/java/soup/movie/feature/search/impl/di/FeatureSearchModule.kt b/feature/search/impl/src/main/java/soup/movie/feature/search/impl/di/FeatureSearchModule.kt new file mode 100644 index 000000000..c25680037 --- /dev/null +++ b/feature/search/impl/src/main/java/soup/movie/feature/search/impl/di/FeatureSearchModule.kt @@ -0,0 +1,33 @@ +/* + * Copyright 2022 SOUP + * + * 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 soup.movie.feature.search.impl.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import soup.movie.feature.search.SearchComposableFactory +import soup.movie.feature.search.impl.SearchComposableFactoryImpl + +@Module +@InstallIn(SingletonComponent::class) +interface FeatureSearchModule { + + @Binds + fun bindsSearchComposableFactory( + impl: SearchComposableFactoryImpl, + ): SearchComposableFactory +}