diff --git a/app/build.gradle b/app/build.gradle index 7fe8e570a..d8640746a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -113,7 +113,8 @@ dependencies { implementation libs.androidx.activity.compose implementation libs.androidx.hilt.navigation.compose implementation libs.compose.foundation - implementation libs.compose.material + implementation libs.compose.material3 + implementation libs.compose.material3.windowsizeclass implementation libs.compose.ui implementation libs.androidx.profileinstaller diff --git a/app/dependencies/releaseRuntimeClasspath.txt b/app/dependencies/releaseRuntimeClasspath.txt index 665e3befb..58a5db7b1 100644 --- a/app/dependencies/releaseRuntimeClasspath.txt +++ b/app/dependencies/releaseRuntimeClasspath.txt @@ -23,6 +23,10 @@ androidx.compose.foundation:foundation-android:1.7.6 androidx.compose.foundation:foundation-layout-android:1.7.6 androidx.compose.foundation:foundation-layout:1.7.6 androidx.compose.foundation:foundation:1.7.6 +androidx.compose.material3:material3-android:1.3.1 +androidx.compose.material3:material3-window-size-class-android:1.3.1 +androidx.compose.material3:material3-window-size-class:1.3.1 +androidx.compose.material3:material3:1.3.1 androidx.compose.material:material-android:1.7.6 androidx.compose.material:material-icons-core-android:1.7.6 androidx.compose.material:material-icons-core:1.7.6 diff --git a/app/src/main/java/soup/movie/ui/main/MainActivity.kt b/app/src/main/java/soup/movie/ui/main/MainActivity.kt index 665cbc4eb..ce19dfe7b 100644 --- a/app/src/main/java/soup/movie/ui/main/MainActivity.kt +++ b/app/src/main/java/soup/movie/ui/main/MainActivity.kt @@ -19,17 +19,19 @@ import android.os.Bundle import androidx.activity.compose.setContent import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity +import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi +import androidx.compose.material3.windowsizeclass.calculateWindowSizeClass import androidx.core.view.WindowCompat import dagger.hilt.android.AndroidEntryPoint import soup.movie.R import soup.movie.core.designsystem.theme.MovieTheme -import soup.movie.core.designsystem.windowsizeclass.calculateWindowSizeClass @AndroidEntryPoint class MainActivity : AppCompatActivity() { private val viewModel: MainViewModel by viewModels() + @OptIn(ExperimentalMaterial3WindowSizeClassApi::class) override fun onCreate(savedInstanceState: Bundle?) { setTheme(R.style.Theme_Moop) super.onCreate(savedInstanceState) 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 137224f77..7e50afefb 100644 --- a/app/src/main/java/soup/movie/ui/main/MainNavGraph.kt +++ b/app/src/main/java/soup/movie/ui/main/MainNavGraph.kt @@ -15,13 +15,13 @@ */ package soup.movie.ui.main +import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass import androidx.compose.runtime.Composable import androidx.navigation.compose.NavHost import androidx.navigation.compose.composable import androidx.navigation.compose.rememberNavController import androidx.navigation.toRoute import kotlinx.serialization.Serializable -import soup.movie.core.designsystem.windowsizeclass.WindowWidthSizeClass import soup.movie.feature.detail.rememberDetailComposableFactory import soup.movie.feature.home.rememberHomeComposableFactory import soup.movie.feature.search.rememberSearchComposableFactory diff --git a/core/designsystem/build.gradle b/core/designsystem/build.gradle index d79e0ed8e..46d09ddcf 100644 --- a/core/designsystem/build.gradle +++ b/core/designsystem/build.gradle @@ -13,8 +13,8 @@ dependencies { implementation libs.kotlin.stdlib implementation libs.compose.foundation - implementation libs.compose.material implementation libs.compose.materialIconsExtended + implementation libs.compose.material3 implementation libs.compose.ui implementation libs.androidx.window diff --git a/core/designsystem/src/main/java/soup/movie/core/designsystem/UnelevatedButton.kt b/core/designsystem/src/main/java/soup/movie/core/designsystem/UnelevatedButton.kt deleted file mode 100644 index a5cd245aa..000000000 --- a/core/designsystem/src/main/java/soup/movie/core/designsystem/UnelevatedButton.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2023 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.core.designsystem - -import androidx.compose.foundation.BorderStroke -import androidx.compose.foundation.interaction.MutableInteractionSource -import androidx.compose.foundation.layout.PaddingValues -import androidx.compose.foundation.layout.RowScope -import androidx.compose.material.Button -import androidx.compose.material.ButtonColors -import androidx.compose.material.ButtonDefaults -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.tooling.preview.Preview -import soup.movie.core.designsystem.theme.MovieTheme - -@Composable -fun UnelevatedButton( - onClick: () -> Unit, - modifier: Modifier = Modifier, - enabled: Boolean = true, - interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, - shape: Shape = MaterialTheme.shapes.small, - border: BorderStroke? = null, - colors: ButtonColors = ButtonDefaults.buttonColors(), - contentPadding: PaddingValues = ButtonDefaults.ContentPadding, - content: @Composable RowScope.() -> Unit, -) = Button( - onClick = onClick, - modifier = modifier, - enabled = enabled, - interactionSource = interactionSource, - elevation = null, - shape = shape, - border = border, - colors = colors, - contentPadding = contentPadding, - content = content, -) - -@Preview -@Composable -private fun UnelevatedButtonPreview() { - MovieTheme { - UnelevatedButton(onClick = {}) { - Text(text = "Button") - } - } -} diff --git a/core/designsystem/src/main/java/soup/movie/core/designsystem/theme/Colors.kt b/core/designsystem/src/main/java/soup/movie/core/designsystem/theme/Colors.kt index 51a663dbf..18df86c57 100644 --- a/core/designsystem/src/main/java/soup/movie/core/designsystem/theme/Colors.kt +++ b/core/designsystem/src/main/java/soup/movie/core/designsystem/theme/Colors.kt @@ -15,18 +15,16 @@ */ package soup.movie.core.designsystem.theme -import androidx.compose.material.Colors -import androidx.compose.material.darkColors -import androidx.compose.material.lightColors -import androidx.compose.material.primarySurface +import androidx.compose.material3.ColorScheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Stable import androidx.compose.runtime.staticCompositionLocalOf import androidx.compose.ui.graphics.Color @Stable data class MovieColors( - internal val material: Colors, - val divider: Color, + internal val material: ColorScheme, val star: Color, val dim: Color, val cgv: Color, @@ -43,25 +41,17 @@ data class MovieColors( val ageTagUnknown: Color, ) { val primary: Color get() = material.primary - val primaryVariant: Color get() = material.primaryVariant val secondary: Color get() = material.secondary - val secondaryVariant: Color get() = material.secondaryVariant val background: Color get() = material.background val surface: Color get() = material.surface val error: Color get() = material.error - val onPrimary: Color get() = material.onPrimary - val onSecondary: Color get() = material.onSecondary val onBackground: Color get() = material.onBackground val onSurface: Color get() = material.onSurface val onError: Color get() = material.onError - val isLight: Boolean get() = material.isLight - - val primarySurface: Color get() = material.primarySurface } fun lightMovieColors( - material: Colors = lightColors(), - divider: Color = Color(0xFFF5F5F5), + material: ColorScheme = lightColorScheme(), star: Color = Color(0xFFFFC107), dim: Color = Color(0xDDFFFFFF), cgv: Color = Color.White, @@ -78,7 +68,6 @@ fun lightMovieColors( ageTagUnknown: Color = Color(0xFF9E9E9E), ): MovieColors = MovieColors( material = material, - divider = divider, star = star, dim = dim, cgv = cgv, @@ -96,8 +85,7 @@ fun lightMovieColors( ) fun darkMovieColors( - material: Colors = darkColors(), - divider: Color = Color(0xFF212121), + material: ColorScheme = darkColorScheme(), star: Color = Color(0xFFFFC107), dim: Color = Color(0xAA000000), cgv: Color = Color.White, @@ -114,7 +102,6 @@ fun darkMovieColors( ageTagUnknown: Color = Color(0xFFE0E0E0), ): MovieColors = MovieColors( material = material, - divider = divider, star = star, dim = dim, cgv = cgv, diff --git a/core/designsystem/src/main/java/soup/movie/core/designsystem/theme/Elevations.kt b/core/designsystem/src/main/java/soup/movie/core/designsystem/theme/Elevations.kt deleted file mode 100644 index 99e7cb176..000000000 --- a/core/designsystem/src/main/java/soup/movie/core/designsystem/theme/Elevations.kt +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2023 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.core.designsystem.theme - -import androidx.compose.runtime.Immutable -import androidx.compose.runtime.staticCompositionLocalOf -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.dp - -@Immutable -data class Elevations( - val card: Dp = 0.dp, - val bottomSheet: Dp = 0.dp, -) - -internal val LocalElevations = staticCompositionLocalOf { Elevations() } diff --git a/core/designsystem/src/main/java/soup/movie/core/designsystem/theme/Themes.kt b/core/designsystem/src/main/java/soup/movie/core/designsystem/theme/Themes.kt index 68d2dd0a0..d8a10d6b9 100644 --- a/core/designsystem/src/main/java/soup/movie/core/designsystem/theme/Themes.kt +++ b/core/designsystem/src/main/java/soup/movie/core/designsystem/theme/Themes.kt @@ -16,44 +16,20 @@ package soup.movie.core.designsystem.theme import androidx.compose.foundation.isSystemInDarkTheme -import androidx.compose.material.MaterialTheme -import androidx.compose.material.Shapes -import androidx.compose.material.Typography -import androidx.compose.material.darkColors -import androidx.compose.material.lightColors +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Shapes +import androidx.compose.material3.Typography +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable import androidx.compose.runtime.CompositionLocalProvider -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.dp private val LightMovieColors = lightMovieColors( - material = lightColors( - primary = Color.White, - primaryVariant = Color(0xFF9E9E9E), - onPrimary = Color.Black, - secondary = Color(0xFF2D7AF6), - onSecondary = Color.White, - ), + material = lightColorScheme(), ) private val DarkMovieColors = darkMovieColors( - material = darkColors( - primary = Color.Black, - primaryVariant = Color.Black, - onPrimary = Color.White, - secondary = Color(0xFF8EB5F0), - onSecondary = Color.Black, - ), -) - -private val LightElevations = Elevations( - card = 10.dp, - bottomSheet = 16.dp, -) - -private val DarkElevations = Elevations( - card = 1.dp, - bottomSheet = 0.dp, + material = darkColorScheme(), ) @Composable @@ -66,17 +42,9 @@ fun MovieTheme( } else { LightMovieColors } - val elevation = if (darkTheme) { - DarkElevations - } else { - LightElevations - } - CompositionLocalProvider( - LocalMovieColors provides colors, - LocalElevations provides elevation, - ) { + CompositionLocalProvider(LocalMovieColors provides colors) { MaterialTheme( - colors = colors.material, + colorScheme = colors.material, content = content, ) } @@ -95,8 +63,4 @@ object MovieTheme { val shapes: Shapes @Composable get() = MaterialTheme.shapes - - val elevations: Elevations - @Composable - get() = LocalElevations.current } diff --git a/core/designsystem/src/main/java/soup/movie/core/designsystem/windowsizeclass/WindowSizeClass.kt b/core/designsystem/src/main/java/soup/movie/core/designsystem/windowsizeclass/WindowSizeClass.kt deleted file mode 100644 index 1c3b4c049..000000000 --- a/core/designsystem/src/main/java/soup/movie/core/designsystem/windowsizeclass/WindowSizeClass.kt +++ /dev/null @@ -1,206 +0,0 @@ -/* - * 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.core.designsystem.windowsizeclass - -import android.app.Activity -import androidx.compose.runtime.Composable -import androidx.compose.runtime.Immutable -import androidx.compose.ui.graphics.toComposeRect -import androidx.compose.ui.platform.LocalConfiguration -import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.unit.Dp -import androidx.compose.ui.unit.DpSize -import androidx.compose.ui.unit.dp -import androidx.window.layout.WindowMetricsCalculator - -/** - * Calculates the window's [WindowSizeClass] for the provided [activity]. - * - * A new [WindowSizeClass] will be returned whenever a configuration change causes the width or - * height of the window to cross a breakpoint, such as when the device is rotated or the window - * is resized. - * - * @sample androidx.compose.material3.windowsizeclass.samples.AndroidWindowSizeClassSample - */ -@Composable -fun calculateWindowSizeClass(activity: Activity): WindowSizeClass { - // Observe view configuration changes and recalculate the size class on each change. We can't - // use Activity#onConfigurationChanged as this will sometimes fail to be called on different - // API levels, hence why this function needs to be @Composable so we can observe the - // ComposeView's configuration changes. - LocalConfiguration.current - val density = LocalDensity.current - val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity) - val size = with(density) { metrics.bounds.toComposeRect().size.toDpSize() } - return WindowSizeClass.calculateFromSize(size) -} - -/** - * Window size classes are a set of opinionated viewport breakpoints to design, develop, and test - * responsive application layouts against. - * For more details check Support different screen sizes documentation. - * - * WindowSizeClass contains a [WindowWidthSizeClass] and [WindowHeightSizeClass], representing the - * window size classes for this window's width and height respectively. - * - * See [calculateWindowSizeClass] to calculate the WindowSizeClass for an Activity's current window - * - * @property widthSizeClass width-based window size class ([WindowWidthSizeClass]) - * @property heightSizeClass height-based window size class ([WindowHeightSizeClass]) - */ -@Immutable -class WindowSizeClass private constructor( - val widthSizeClass: WindowWidthSizeClass, - val heightSizeClass: WindowHeightSizeClass, -) { - companion object { - /** - * Calculates [WindowSizeClass] for a given [size]. Should be used for testing purposes only - * - to calculate a [WindowSizeClass] for the Activity's current window see - * [calculateWindowSizeClass]. - * - * @param size of the window - * @return [WindowSizeClass] corresponding to the given width and height - */ - fun calculateFromSize(size: DpSize): WindowSizeClass { - val windowWidthSizeClass = WindowWidthSizeClass.fromWidth(size.width) - val windowHeightSizeClass = WindowHeightSizeClass.fromHeight(size.height) - return WindowSizeClass(windowWidthSizeClass, windowHeightSizeClass) - } - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (other == null || this::class != other::class) return false - - other as WindowSizeClass - - if (widthSizeClass != other.widthSizeClass) return false - if (heightSizeClass != other.heightSizeClass) return false - - return true - } - - override fun hashCode(): Int { - var result = widthSizeClass.hashCode() - result = 31 * result + heightSizeClass.hashCode() - return result - } - - override fun toString() = "WindowSizeClass($widthSizeClass, $heightSizeClass)" -} - -/** - * Width-based window size class. - * - * A window size class represents a breakpoint that can be used to build responsive layouts. Each - * window size class breakpoint represents a majority case for typical device scenarios so your - * layouts will work well on most devices and configurations. - * - * For more details see Window size classes documentation. - */ -@Immutable -@kotlin.jvm.JvmInline -value class WindowWidthSizeClass private constructor( - private val value: Int, -) : Comparable { - - override operator fun compareTo(other: WindowWidthSizeClass) = value.compareTo(other.value) - - override fun toString(): String { - return "WindowWidthSizeClass." + when (this) { - Compact -> "Compact" - Medium -> "Medium" - Expanded -> "Expanded" - else -> "" - } - } - - companion object { - /** Represents the majority of phones in portrait. */ - val Compact = WindowWidthSizeClass(0) - - /** - * Represents the majority of tablets in portrait and large unfolded inner displays in - * portrait. - */ - val Medium = WindowWidthSizeClass(1) - - /** - * Represents the majority of tablets in landscape and large unfolded inner displays in - * landscape. - */ - val Expanded = WindowWidthSizeClass(2) - - /** Calculates the [WindowWidthSizeClass] for a given [width] */ - internal fun fromWidth(width: Dp): WindowWidthSizeClass { - require(width >= 0.dp) { "Width must not be negative" } - return when { - width < 600.dp -> Compact - width < 840.dp -> Medium - else -> Expanded - } - } - } -} - -/** - * Height-based window size class. - * - * A window size class represents a breakpoint that can be used to build responsive layouts. Each - * window size class breakpoint represents a majority case for typical device scenarios so your - * layouts will work well on most devices and configurations. - * - * For more details see Window size classes documentation. - */ -@Immutable -@kotlin.jvm.JvmInline -value class WindowHeightSizeClass private constructor( - private val value: Int, -) : Comparable { - - override operator fun compareTo(other: WindowHeightSizeClass) = value.compareTo(other.value) - - override fun toString(): String { - return "WindowHeightSizeClass." + when (this) { - Compact -> "Compact" - Medium -> "Medium" - Expanded -> "Expanded" - else -> "" - } - } - - companion object { - /** Represents the majority of phones in landscape */ - val Compact = WindowHeightSizeClass(0) - - /** Represents the majority of tablets in landscape and majority of phones in portrait */ - val Medium = WindowHeightSizeClass(1) - - /** Represents the majority of tablets in portrait */ - val Expanded = WindowHeightSizeClass(2) - - /** Calculates the [WindowHeightSizeClass] for a given [height] */ - internal fun fromHeight(height: Dp): WindowHeightSizeClass { - require(height >= 0.dp) { "Height must not be negative" } - return when { - height < 480.dp -> Compact - height < 900.dp -> Medium - else -> Expanded - } - } - } -} diff --git a/feature/detail/impl/build.gradle b/feature/detail/impl/build.gradle index 8153ee9f3..f4ce0faa1 100644 --- a/feature/detail/impl/build.gradle +++ b/feature/detail/impl/build.gradle @@ -29,7 +29,7 @@ dependencies { implementation libs.androidx.hilt.navigation.compose implementation libs.androidx.navigation.compose implementation libs.compose.foundation - implementation libs.compose.material + implementation libs.compose.material3 implementation libs.compose.ui implementation libs.compose.animation.graphics implementation libs.readmore.material diff --git a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/BoxOffice.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/BoxOffice.kt index 7d7e88d88..f23c5a70a 100644 --- a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/BoxOffice.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/BoxOffice.kt @@ -21,9 +21,8 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Card -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.Text +import androidx.compose.material3.ElevatedCard +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -36,18 +35,14 @@ import androidx.compose.ui.unit.sp import soup.movie.core.designsystem.theme.MovieTheme import soup.movie.resources.R -@OptIn(ExperimentalMaterialApi::class) @Composable fun BoxOffice( uiModel: BoxOfficeItemUiModel, onClick: () -> Unit, ) { - Card( + ElevatedCard( onClick = onClick, modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 8.dp), - shape = RoundedCornerShape(16.dp), - backgroundColor = MovieTheme.colors.surface, - elevation = MovieTheme.elevations.card, ) { Row( modifier = Modifier @@ -61,13 +56,13 @@ fun BoxOffice( Text( text = "박스오피스", color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, modifier = Modifier.alpha(0.7f), ) Text( text = stringResource(R.string.rank, uiModel.rank), color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.subtitle1, + style = MovieTheme.typography.titleMedium, fontSize = 18.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(top = 2.dp), @@ -75,7 +70,7 @@ fun BoxOffice( Text( text = stringResource(R.string.rank_date, uiModel.rankDate), color = MovieTheme.colors.surface, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 12.sp, fontWeight = FontWeight.Bold, modifier = Modifier @@ -94,13 +89,13 @@ fun BoxOffice( Text( text = "누적 관객수", color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, modifier = Modifier.alpha(0.7f), ) Text( text = stringResource(R.string.audience, uiModel.audience), color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.subtitle1, + style = MovieTheme.typography.titleMedium, fontSize = 18.sp, fontWeight = FontWeight.Bold, modifier = Modifier.padding(top = 2.dp), @@ -108,7 +103,7 @@ fun BoxOffice( Text( text = stringResource(R.string.screen_days, uiModel.screenDays), color = MovieTheme.colors.surface, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 12.sp, fontWeight = FontWeight.Bold, modifier = Modifier diff --git a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailContent.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailContent.kt index e24672d1f..418fdd245 100644 --- a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailContent.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailContent.kt @@ -56,7 +56,6 @@ internal fun DetailContent( ) }, items = uiModel.items, - viewModel = viewModel, onItemClick = { item -> onItemClick(item) }, ) } diff --git a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailError.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailError.kt index 096df5efb..ba9902c73 100644 --- a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailError.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailError.kt @@ -24,8 +24,8 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredHeight import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.layout.wrapContentWidth -import androidx.compose.material.Text -import androidx.compose.material.TextButton +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -61,7 +61,7 @@ internal fun DetailError( .fillMaxWidth() .wrapContentHeight() .padding(horizontal = 16.dp), - style = MovieTheme.typography.h6, + style = MovieTheme.typography.headlineSmall, textAlign = TextAlign.Center, ) TextButton( diff --git a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailHeader.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailHeader.kt index 4372fcc91..783c62684 100644 --- a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailHeader.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailHeader.kt @@ -30,10 +30,9 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.requiredSize import androidx.compose.foundation.layout.requiredWidthIn import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Card -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.IconButton -import androidx.compose.material.Text +import androidx.compose.material3.Card +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -53,7 +52,6 @@ import soup.movie.feature.home.rememberHomeComposableFactory import soup.movie.model.MovieModel import soup.movie.resources.R -@OptIn(ExperimentalMaterialApi::class) @Composable internal fun DetailHeader( uiModel: HeaderUiModel, @@ -71,7 +69,7 @@ internal fun DetailHeader( .weight(1f) .padding(end = 8.dp, top = 12.dp, bottom = 12.dp), color = MovieTheme.colors.onBackground, - style = MovieTheme.typography.h6, + style = MovieTheme.typography.headlineSmall, fontSize = 18.sp, fontWeight = FontWeight.Bold, ) @@ -84,7 +82,6 @@ internal fun DetailHeader( Card( onClick = { onPosterClick(movie) }, shape = RoundedCornerShape(4.dp), - elevation = 0.dp, modifier = Modifier.padding(end = 18.dp), ) { AsyncImage( @@ -118,14 +115,14 @@ internal fun DetailHeader( Text( text = "개봉", color = MovieTheme.colors.onBackground, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 14.sp, modifier = Modifier.alpha(0.5f), ) Text( text = movie.openDate, color = MovieTheme.colors.onBackground, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 14.sp, modifier = Modifier.fillMaxWidth().padding(start = 8.dp), maxLines = 1, @@ -137,7 +134,7 @@ internal fun DetailHeader( Text( text = "등급", color = MovieTheme.colors.onBackground, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 14.sp, modifier = Modifier.alpha(0.5f), ) @@ -152,7 +149,7 @@ internal fun DetailHeader( }, ), color = MovieTheme.colors.onBackground, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 14.sp, modifier = Modifier.fillMaxWidth().padding(start = 8.dp), maxLines = 1, @@ -165,14 +162,14 @@ internal fun DetailHeader( Text( text = "장르", color = MovieTheme.colors.onBackground, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 14.sp, modifier = Modifier.alpha(0.5f), ) Text( text = genres.joinToString(separator = ", "), color = MovieTheme.colors.onBackground, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 14.sp, modifier = Modifier.fillMaxWidth().padding(start = 8.dp), maxLines = 1, @@ -186,14 +183,14 @@ internal fun DetailHeader( Text( text = "국가", color = MovieTheme.colors.onBackground, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 14.sp, modifier = Modifier.alpha(0.5f), ) Text( text = nations.joinToString(separator = ", "), color = MovieTheme.colors.onBackground, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 14.sp, modifier = Modifier.fillMaxWidth().padding(start = 8.dp), maxLines = 1, @@ -207,14 +204,14 @@ internal fun DetailHeader( Text( text = "러닝타임", color = MovieTheme.colors.onBackground, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 14.sp, modifier = Modifier.alpha(0.5f), ) Text( text = stringResource(R.string.time_minute, uiModel.showTm), color = MovieTheme.colors.onBackground, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 14.sp, modifier = Modifier.fillMaxWidth().padding(start = 8.dp), maxLines = 1, @@ -232,14 +229,14 @@ internal fun DetailHeader( Text( text = "배급", color = MovieTheme.colors.onBackground, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 14.sp, modifier = Modifier.alpha(0.5f), ) Text( text = companies, color = MovieTheme.colors.onBackground, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontSize = 14.sp, modifier = Modifier.fillMaxWidth().padding(start = 8.dp), maxLines = 1, diff --git a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailList.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailList.kt index 1235b0f81..a4a122c01 100644 --- a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailList.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailList.kt @@ -41,12 +41,11 @@ import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyRow import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Card -import androidx.compose.material.Chip -import androidx.compose.material.ChipDefaults -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.IconButton -import androidx.compose.material.Text +import androidx.compose.material3.AssistChip +import androidx.compose.material3.AssistChipDefaults +import androidx.compose.material3.ElevatedCard +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -76,7 +75,6 @@ import soup.movie.resources.R internal fun DetailList( header: @Composable () -> Unit, items: List, - viewModel: DetailViewModel, onItemClick: (ContentItemUiModel) -> Unit, ) { LazyColumn( @@ -158,39 +156,36 @@ internal fun DetailList( } } -@OptIn(ExperimentalMaterialApi::class) @Composable private fun Cgv( uiModel: CgvItemUiModel, onClick: () -> Unit, modifier: Modifier = Modifier, ) { - Card( + ElevatedCard( onClick = onClick, enabled = uiModel.hasInfo, modifier = modifier.padding(start = 12.dp, end = 4.dp, bottom = 8.dp), - shape = RoundedCornerShape(16.dp), - backgroundColor = MovieTheme.colors.surface, - elevation = MovieTheme.elevations.card, ) { Column( modifier = Modifier.padding(top = 4.dp, bottom = 6.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { - Chip( + AssistChip( onClick = onClick, - colors = ChipDefaults.chipColors( - backgroundColor = MovieTheme.colors.cgv, - contentColor = MovieTheme.colors.onCgv, + colors = AssistChipDefaults.assistChipColors( + containerColor = MovieTheme.colors.cgv, + labelColor = MovieTheme.colors.onCgv, ), border = BorderStroke(width = 1.dp, color = Color(0x229E9E9E)), - ) { - Text( - text = "CGV", - style = MovieTheme.typography.body2, - fontWeight = FontWeight.Bold, - ) - } + label = { + Text( + text = "CGV", + style = MovieTheme.typography.bodyMedium, + fontWeight = FontWeight.Bold, + ) + }, + ) Row( horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, @@ -199,7 +194,7 @@ private fun Cgv( Text( text = uiModel.rating, color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, modifier = Modifier.padding(start = 4.dp, end = 8.dp), ) @@ -208,38 +203,35 @@ private fun Cgv( } } -@OptIn(ExperimentalMaterialApi::class) @Composable private fun Lotte( uiModel: LotteItemUiModel, onClick: () -> Unit, modifier: Modifier = Modifier, ) { - Card( + ElevatedCard( onClick = onClick, enabled = uiModel.hasInfo, modifier = modifier.padding(start = 4.dp, end = 4.dp, bottom = 8.dp), - shape = RoundedCornerShape(16.dp), - backgroundColor = MovieTheme.colors.surface, - elevation = MovieTheme.elevations.card, ) { Column( modifier = Modifier.padding(top = 4.dp, bottom = 6.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { - Chip( + AssistChip( onClick = onClick, - colors = ChipDefaults.chipColors( - backgroundColor = MovieTheme.colors.lotte, - contentColor = MovieTheme.colors.onLotte, + colors = AssistChipDefaults.assistChipColors( + containerColor = MovieTheme.colors.lotte, + labelColor = MovieTheme.colors.onLotte, ), - ) { - Text( - text = "롯데시네마", - style = MovieTheme.typography.body2, - fontWeight = FontWeight.Bold, - ) - } + label = { + Text( + text = "롯데시네마", + style = MovieTheme.typography.bodyMedium, + fontWeight = FontWeight.Bold, + ) + }, + ) Row( horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, @@ -248,7 +240,7 @@ private fun Lotte( Text( text = uiModel.rating, color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, modifier = Modifier.padding(start = 4.dp, end = 8.dp), ) @@ -257,38 +249,35 @@ private fun Lotte( } } -@OptIn(ExperimentalMaterialApi::class) @Composable private fun Megabox( uiModel: MegaboxItemUiModel, onClick: () -> Unit, modifier: Modifier = Modifier, ) { - Card( + ElevatedCard( onClick = onClick, enabled = uiModel.hasInfo, modifier = modifier.padding(start = 4.dp, end = 12.dp, bottom = 8.dp), - shape = RoundedCornerShape(16.dp), - backgroundColor = MovieTheme.colors.surface, - elevation = MovieTheme.elevations.card, ) { Column( modifier = Modifier.padding(top = 4.dp, bottom = 6.dp), horizontalAlignment = Alignment.CenterHorizontally, ) { - Chip( + AssistChip( onClick = onClick, - colors = ChipDefaults.chipColors( - backgroundColor = MovieTheme.colors.megabox, - contentColor = MovieTheme.colors.onMegabox, + colors = AssistChipDefaults.assistChipColors( + containerColor = MovieTheme.colors.megabox, + labelColor = MovieTheme.colors.onMegabox, ), - ) { - Text( - text = "메가박스", - style = MovieTheme.typography.body2, - fontWeight = FontWeight.Bold, - ) - } + label = { + Text( + text = "메가박스", + style = MovieTheme.typography.bodyMedium, + fontWeight = FontWeight.Bold, + ) + }, + ) Row( horizontalArrangement = Arrangement.Center, verticalAlignment = Alignment.CenterVertically, @@ -297,7 +286,7 @@ private fun Megabox( Text( text = uiModel.rating, color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, modifier = Modifier.padding(start = 4.dp, end = 8.dp), ) @@ -306,18 +295,16 @@ private fun Megabox( } } -@OptIn(ExperimentalMaterialApi::class) @Composable private fun Plot( uiModel: PlotItemUiModel, onClick: () -> Unit, ) { - Card( + ElevatedCard( onClick = onClick, - modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 8.dp).fillMaxWidth(), - shape = RoundedCornerShape(16.dp), - backgroundColor = MovieTheme.colors.surface, - elevation = MovieTheme.elevations.card, + modifier = Modifier + .padding(start = 12.dp, end = 12.dp, bottom = 8.dp) + .fillMaxWidth(), ) { Column( modifier = Modifier.padding(16.dp), @@ -333,7 +320,7 @@ private fun Plot( maxLines = 1, overflow = TextOverflow.Ellipsis, color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.subtitle2, + style = MovieTheme.typography.titleMedium, fontWeight = FontWeight.Bold, modifier = Modifier.padding(start = 8.dp), ) @@ -344,7 +331,7 @@ private fun Plot( text = uiModel.plot, expanded = isExpanded, color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, modifier = Modifier .clickable { isExpanded = !isExpanded @@ -361,18 +348,14 @@ private fun Plot( } } -@OptIn(ExperimentalMaterialApi::class) @Composable private fun Imdb( uiModel: ImdbItemUiModel, onClick: () -> Unit, ) { - Card( + ElevatedCard( onClick = onClick, modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 8.dp), - shape = RoundedCornerShape(16.dp), - backgroundColor = MovieTheme.colors.surface, - elevation = MovieTheme.elevations.card, ) { Row( modifier = Modifier.padding(top = 12.dp, bottom = 8.dp), @@ -391,7 +374,7 @@ private fun Imdb( Text( text = uiModel.imdb, color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, modifier = Modifier.padding(top = 6.dp), ) @@ -427,7 +410,7 @@ private fun Imdb( Text( text = uiModel.rottenTomatoes, color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, overflow = TextOverflow.Ellipsis, modifier = Modifier.padding(top = 6.dp), @@ -448,7 +431,7 @@ private fun Imdb( Text( text = uiModel.metascore, color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, fontWeight = FontWeight.Bold, modifier = Modifier.padding(top = 6.dp), ) @@ -479,18 +462,14 @@ private fun Cast( } } -@OptIn(ExperimentalMaterialApi::class) @Composable private fun Person( uiModel: PersonUiModel, onClick: () -> Unit, ) { - Card( + ElevatedCard( onClick = onClick, modifier = Modifier.padding(start = 4.dp, end = 4.dp, bottom = 8.dp), - shape = RoundedCornerShape(16.dp), - backgroundColor = MovieTheme.colors.surface, - elevation = MovieTheme.elevations.card, ) { Column( modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), @@ -499,16 +478,14 @@ private fun Person( Text( text = uiModel.name, maxLines = 1, - color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.subtitle2, + style = MovieTheme.typography.titleMedium, fontWeight = FontWeight.Bold, ) if (uiModel.cast.isNotEmpty()) { Text( text = uiModel.cast, maxLines = 1, - color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.subtitle2, + style = MovieTheme.typography.titleMedium, ) } } @@ -520,33 +497,38 @@ private fun TrailerHeader( uiModel: TrailerHeaderItemUiModel, onPrivacyTipClick: () -> Unit, ) { - Card( + ElevatedCard( modifier = Modifier.padding(start = 12.dp, end = 12.dp), shape = RoundedCornerShape(topStart = 16.dp, topEnd = 16.dp), - backgroundColor = MovieTheme.colors.surface, - elevation = MovieTheme.elevations.card, ) { Row( - modifier = Modifier.fillMaxWidth().requiredHeight(48.dp), + modifier = Modifier + .fillMaxWidth() + .requiredHeight(48.dp), verticalAlignment = Alignment.CenterVertically, ) { Image( painter = painterResource(MovieIcons.YouTube), contentDescription = null, - modifier = Modifier.requiredWidth(48.dp).fillMaxHeight(), + modifier = Modifier + .requiredWidth(48.dp) + .fillMaxHeight(), contentScale = ContentScale.Inside, ) Text( text = stringResource(R.string.trailer_search_result, uiModel.movieTitle), maxLines = 1, - color = MovieTheme.colors.onSurface, - style = MovieTheme.typography.subtitle2, + style = MovieTheme.typography.titleMedium, fontWeight = FontWeight.Bold, overflow = TextOverflow.Ellipsis, - modifier = Modifier.padding(start = 4.dp).weight(1f), + modifier = Modifier + .padding(start = 4.dp) + .weight(1f), ) IconButton( - modifier = Modifier.requiredWidth(48.dp).fillMaxHeight(), + modifier = Modifier + .requiredWidth(48.dp) + .fillMaxHeight(), onClick = onPrivacyTipClick, ) { Image( @@ -561,18 +543,15 @@ private fun TrailerHeader( } } -@OptIn(ExperimentalMaterialApi::class) @Composable private fun TrailerItem( uiModel: TrailerItemUiModel, onClick: () -> Unit, ) { - Card( + ElevatedCard( onClick = onClick, modifier = Modifier.padding(start = 12.dp, end = 12.dp), shape = RectangleShape, - backgroundColor = MovieTheme.colors.surface, - elevation = MovieTheme.elevations.card, ) { Row( modifier = Modifier @@ -590,18 +569,20 @@ private fun TrailerItem( .fillMaxHeight(), ) Column( - modifier = Modifier.fillMaxSize().padding(start = 12.dp), + modifier = Modifier + .fillMaxSize() + .padding(start = 12.dp), ) { Text( text = uiModel.trailer.title, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, maxLines = 3, overflow = TextOverflow.Ellipsis, modifier = Modifier.padding(top = 2.dp), ) Text( text = uiModel.trailer.author, - style = MovieTheme.typography.caption, + style = MovieTheme.typography.bodySmall, maxLines = 1, overflow = TextOverflow.Ellipsis, modifier = Modifier.padding(top = 4.dp), @@ -611,20 +592,19 @@ private fun TrailerItem( } } -@OptIn(ExperimentalMaterialApi::class) @Composable private fun TrailerFooter( onClick: () -> Unit, ) { - Card( + ElevatedCard( onClick = onClick, modifier = Modifier.padding(start = 12.dp, end = 12.dp, bottom = 16.dp), shape = RoundedCornerShape(bottomStart = 16.dp, bottomEnd = 16.dp), - backgroundColor = MovieTheme.colors.surface, - elevation = MovieTheme.elevations.card, ) { Box( - modifier = Modifier.fillMaxWidth().requiredHeight(48.dp), + modifier = Modifier + .fillMaxWidth() + .requiredHeight(48.dp), contentAlignment = Alignment.Center, ) { Text( diff --git a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailScreen.kt b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailScreen.kt index 08743e227..2b790e5d9 100644 --- a/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailScreen.kt +++ b/feature/detail/impl/src/main/java/soup/movie/feature/detail/impl/DetailScreen.kt @@ -17,10 +17,10 @@ package soup.movie.feature.detail.impl import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.material.AlertDialog -import androidx.compose.material.ButtonDefaults -import androidx.compose.material.Text -import androidx.compose.material.TextButton +import androidx.compose.material3.AlertDialog +import androidx.compose.material3.ButtonDefaults +import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState diff --git a/feature/home/api/build.gradle b/feature/home/api/build.gradle index 26c521623..c2c452600 100644 --- a/feature/home/api/build.gradle +++ b/feature/home/api/build.gradle @@ -16,4 +16,5 @@ dependencies { implementation libs.kotlin.stdlib implementation libs.compose.foundation + implementation libs.compose.material3.windowsizeclass } 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 index 9c2e70ead..7c152677d 100644 --- 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 @@ -15,6 +15,7 @@ */ package soup.movie.feature.home +import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass import androidx.compose.runtime.Composable import androidx.compose.runtime.remember import androidx.compose.ui.Modifier @@ -23,7 +24,6 @@ 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 { diff --git a/feature/home/impl/build.gradle b/feature/home/impl/build.gradle index a73f3775c..19abf2f53 100644 --- a/feature/home/impl/build.gradle +++ b/feature/home/impl/build.gradle @@ -26,7 +26,8 @@ dependencies { implementation libs.androidx.hilt.navigation.compose implementation libs.compose.animation.graphics implementation libs.compose.foundation - implementation libs.compose.material + implementation libs.compose.material3 + implementation libs.compose.material3.windowsizeclass implementation libs.compose.ui testImplementation projects.testing 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 index 97395657a..2be95c1df 100644 --- 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 @@ -15,10 +15,10 @@ */ package soup.movie.feature.home.impl +import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass 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 diff --git a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeNavGraph.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeNavGraph.kt index e0bf71e0c..26f771076 100644 --- a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeNavGraph.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeNavGraph.kt @@ -22,20 +22,20 @@ import androidx.compose.animation.graphics.vector.AnimatedImageVector import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.systemBarsPadding -import androidx.compose.foundation.layout.width -import androidx.compose.material.BottomNavigation -import androidx.compose.material.BottomNavigationItem -import androidx.compose.material.ContentAlpha -import androidx.compose.material.Divider -import androidx.compose.material.Icon -import androidx.compose.material.NavigationRail -import androidx.compose.material.NavigationRailItem -import androidx.compose.material.Scaffold -import androidx.compose.material.Text +import androidx.compose.material3.Icon +import androidx.compose.material3.NavigationBar +import androidx.compose.material3.NavigationBarItem +import androidx.compose.material3.NavigationBarItemDefaults +import androidx.compose.material3.NavigationRail +import androidx.compose.material3.NavigationRailItem +import androidx.compose.material3.NavigationRailItemDefaults +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.VerticalDivider +import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -46,8 +46,6 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel 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.impl.favorite.HomeFavoriteScreen import soup.movie.model.MovieModel import soup.movie.resources.R @@ -145,10 +143,10 @@ private fun CompactScreen( Scaffold( modifier = modifier, bottomBar = { - BottomNavigation { + NavigationBar { tabs.forEach { tab -> val selected = currentTab == tab - BottomNavigationItem( + NavigationBarItem( icon = { when (tab) { MainTabUiModel.Home -> { @@ -187,8 +185,7 @@ private fun CompactScreen( onTabSelected(tab) } }, - selectedContentColor = MovieTheme.colors.secondary, - unselectedContentColor = MovieTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled), + colors = NavigationBarItemDefaults.colors(), ) } } @@ -210,9 +207,7 @@ private fun MediumScreen( Row( modifier = modifier.fillMaxSize(), ) { - NavigationRail( - elevation = 24.dp, - ) { + NavigationRail { tabs.forEach { tab -> val selected = currentTab == tab NavigationRailItem( @@ -254,12 +249,11 @@ private fun MediumScreen( onTabSelected(tab) } }, - selectedContentColor = MovieTheme.colors.secondary, - unselectedContentColor = MovieTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled), + colors = NavigationRailItemDefaults.colors(), ) } } - Divider(modifier = Modifier.width(1.dp).fillMaxHeight()) + VerticalDivider(thickness = 1.dp) content(PaddingValues()) } } diff --git a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeScreen.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeScreen.kt index e36218190..67e6b800a 100644 --- a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeScreen.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/HomeScreen.kt @@ -22,20 +22,19 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.requiredSize +import androidx.compose.foundation.layout.requiredHeight import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.grid.rememberLazyGridState -import androidx.compose.material.BottomSheetScaffold -import androidx.compose.material.BottomSheetValue -import androidx.compose.material.ContentAlpha -import androidx.compose.material.Divider -import androidx.compose.material.FloatingActionButton -import androidx.compose.material.Icon -import androidx.compose.material.IconButton -import androidx.compose.material.Text -import androidx.compose.material.TopAppBar -import androidx.compose.material.rememberBottomSheetScaffoldState -import androidx.compose.material.rememberBottomSheetState +import androidx.compose.material3.BottomSheetScaffold +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.FloatingActionButton +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.SheetValue +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.VerticalDivider +import androidx.compose.material3.rememberBottomSheetScaffoldState import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf @@ -58,6 +57,7 @@ import soup.movie.feature.home.impl.plan.HomePlanList import soup.movie.model.MovieModel import soup.movie.resources.R +@OptIn(ExperimentalMaterial3Api::class) @Composable fun HomeScreen( viewModel: HomeViewModel, @@ -77,19 +77,17 @@ fun HomeScreen( } } } - val bottomSheetScaffoldState = rememberBottomSheetScaffoldState( - bottomSheetState = rememberBottomSheetState(BottomSheetValue.Collapsed), - ) + val bottomSheetScaffoldState = rememberBottomSheetScaffoldState() val bottomSheetState = bottomSheetScaffoldState.bottomSheetState val bottomSheetVisible by remember { derivedStateOf { - bottomSheetState.isExpanded + bottomSheetState.currentValue == SheetValue.Expanded } } BackHandler(enabled = bottomSheetVisible || isTopAtCurrentTab.not() || selectedTab != HomeTabUiModel.Now) { if (bottomSheetVisible) { coroutineScope.launch { - bottomSheetState.collapse() + bottomSheetState.partialExpand() } } if (isTopAtCurrentTab.not()) { @@ -104,7 +102,6 @@ fun HomeScreen( BottomSheetScaffold( scaffoldState = bottomSheetScaffoldState, sheetPeekHeight = 0.dp, - sheetElevation = MovieTheme.elevations.bottomSheet, sheetContent = { HomeFilterScreen(viewModel = hiltViewModel()) }, @@ -122,10 +119,11 @@ fun HomeScreen( Row(verticalAlignment = Alignment.CenterVertically) { homeTabs.forEachIndexed { index, homeTab -> if (index > 0) { - Divider( + VerticalDivider( + thickness = 2.dp, modifier = Modifier .padding(horizontal = 16.dp) - .requiredSize(2.dp, 16.dp), + .requiredHeight(16.dp), color = MovieTheme.colors.onSurface, ) } @@ -139,7 +137,7 @@ fun HomeScreen( color = if (selected) { MovieTheme.colors.onSurface } else { - MovieTheme.colors.onSurface.copy(alpha = ContentAlpha.disabled) + MovieTheme.colors.onSurface.copy(alpha = 0.38f) }, modifier = Modifier .clickable { diff --git a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/HomeFavoriteScreen.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/HomeFavoriteScreen.kt index a658fcfa4..f0b6ea9b1 100644 --- a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/HomeFavoriteScreen.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/HomeFavoriteScreen.kt @@ -21,11 +21,12 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.foundation.lazy.grid.rememberLazyGridState -import androidx.compose.material.Icon -import androidx.compose.material.IconButton -import androidx.compose.material.Scaffold -import androidx.compose.material.Text -import androidx.compose.material.TopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.derivedStateOf @@ -42,6 +43,7 @@ import soup.movie.feature.home.impl.tab.NoMovieItems import soup.movie.model.MovieModel import soup.movie.resources.R +@OptIn(ExperimentalMaterial3Api::class) @Composable fun HomeFavoriteScreen( viewModel: HomeFavoriteViewModel, diff --git a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieTextTag.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieTextTag.kt index 805485eb3..d36433638 100644 --- a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieTextTag.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/favorite/MovieTextTag.kt @@ -21,7 +21,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Text +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier diff --git a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/HomeFilterScreen.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/HomeFilterScreen.kt index 0e4759b5d..89aeca700 100644 --- a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/HomeFilterScreen.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/HomeFilterScreen.kt @@ -29,8 +29,9 @@ import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentHeight import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Divider -import androidx.compose.material.Text +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue @@ -41,7 +42,6 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import soup.movie.core.designsystem.theme.MovieTheme import soup.movie.resources.R @Composable @@ -63,8 +63,7 @@ fun HomeFilterScreen( @Composable private fun HomeFilterDivider() { - Divider( - color = MovieTheme.colors.divider, + HorizontalDivider( modifier = Modifier.padding(horizontal = 16.dp), ) } @@ -73,9 +72,7 @@ private fun HomeFilterDivider() { private fun HomeFilterCategory(text: String) { Text( text = text, - color = MovieTheme.colors.onBackground, - fontSize = 17.sp, - fontWeight = FontWeight.Bold, + style = MaterialTheme.typography.titleMedium, ) } diff --git a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/TheaterFilterChip.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/TheaterFilterChip.kt index 14d099102..c7f878695 100644 --- a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/TheaterFilterChip.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/filter/TheaterFilterChip.kt @@ -17,10 +17,9 @@ package soup.movie.feature.home.impl.filter import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image -import androidx.compose.material.ChipDefaults -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.FilterChip -import androidx.compose.material.Text +import androidx.compose.material3.FilterChip +import androidx.compose.material3.FilterChipDefaults +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -31,7 +30,6 @@ import androidx.compose.ui.unit.sp import soup.movie.core.designsystem.icon.MovieIcons import soup.movie.core.designsystem.theme.MovieTheme -@OptIn(ExperimentalMaterialApi::class) @Composable fun CgvFilterChip( text: String, @@ -59,21 +57,21 @@ fun CgvFilterChip( }, enabled = enabled, border = BorderStroke(width = 1.dp, color = Color(0x229E9E9E)), - colors = ChipDefaults.filterChipColors( - selectedBackgroundColor = MovieTheme.colors.cgv, - selectedContentColor = MovieTheme.colors.onCgv, - backgroundColor = Color(0x55FFFFFF), - contentColor = Color(0x66000000), + colors = FilterChipDefaults.filterChipColors( + selectedContainerColor = MovieTheme.colors.cgv, + selectedLabelColor = MovieTheme.colors.onCgv, + containerColor = Color(0x55FFFFFF), + labelColor = Color(0x66000000), ), - ) { - Text( - text = text, - fontSize = 14.sp, - ) - } + label = { + Text( + text = text, + fontSize = 14.sp, + ) + }, + ) } -@OptIn(ExperimentalMaterialApi::class) @Composable fun LotteFilterChip( text: String, @@ -94,21 +92,21 @@ fun LotteFilterChip( ) }, enabled = enabled, - colors = ChipDefaults.filterChipColors( - selectedBackgroundColor = Color(0xFFED1D24), - selectedContentColor = Color.White, - backgroundColor = Color(0x66ED1D24), - contentColor = Color(0x77FFFFFF), + colors = FilterChipDefaults.filterChipColors( + selectedContainerColor = Color(0xFFED1D24), + selectedLabelColor = Color.White, + containerColor = Color(0x66ED1D24), + labelColor = Color(0x77FFFFFF), ), - ) { - Text( - text = text, - fontSize = 14.sp, - ) - } + label = { + Text( + text = text, + fontSize = 14.sp, + ) + }, + ) } -@OptIn(ExperimentalMaterialApi::class) @Composable fun MegaboxFilterChip( text: String, @@ -130,16 +128,17 @@ fun MegaboxFilterChip( ) }, enabled = enabled, - colors = ChipDefaults.filterChipColors( - selectedBackgroundColor = Color(0xFF352263), - selectedContentColor = Color.White, - backgroundColor = Color(0x77352263), - contentColor = Color(0x77FFFFFF), + colors = FilterChipDefaults.filterChipColors( + selectedContainerColor = Color(0xFF352263), + selectedLabelColor = Color.White, + containerColor = Color(0x77352263), + labelColor = Color(0x77FFFFFF), ), - ) { - Text( - text = text, - fontSize = 14.sp, - ) - } + label = { + Text( + text = text, + fontSize = 14.sp, + ) + }, + ) } diff --git a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/ContentLoadingProgressBar.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/ContentLoadingProgressBar.kt index c8dad56f6..a52ba1ba5 100644 --- a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/ContentLoadingProgressBar.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/ContentLoadingProgressBar.kt @@ -25,9 +25,9 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.CircleShape -import androidx.compose.material.Icon -import androidx.compose.material.Surface -import androidx.compose.material.contentColorFor +import androidx.compose.material3.Icon +import androidx.compose.material3.Surface +import androidx.compose.material3.contentColorFor import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment @@ -55,7 +55,7 @@ fun ContentLoadingProgressBar( shape = shape, color = backgroundColor, contentColor = contentColor, - elevation = elevation, + tonalElevation = elevation, ) { Box( modifier = Modifier.fillMaxSize(), diff --git a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/HomeContentsScreen.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/HomeContentsScreen.kt index e93208b0a..30aa03695 100644 --- a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/HomeContentsScreen.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/HomeContentsScreen.kt @@ -29,10 +29,9 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.foundation.lazy.grid.rememberLazyGridState -import androidx.compose.material.ExperimentalMaterialApi -import androidx.compose.material.Icon -import androidx.compose.material.Surface -import androidx.compose.material.Text +import androidx.compose.material3.Icon +import androidx.compose.material3.Surface +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -99,7 +98,6 @@ fun HomeContentsScreen( } } -@OptIn(ExperimentalMaterialApi::class) @Composable private fun CommonError( onClick: () -> Unit, @@ -127,7 +125,7 @@ private fun CommonError( fontWeight = FontWeight.Bold, overflow = TextOverflow.Ellipsis, maxLines = 1, - style = MovieTheme.typography.caption, + style = MovieTheme.typography.bodySmall, ) } } diff --git a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/MovieList.kt b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/MovieList.kt index f599bbe64..264214b96 100644 --- a/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/MovieList.kt +++ b/feature/home/impl/src/main/java/soup/movie/feature/home/impl/tab/MovieList.kt @@ -16,7 +16,6 @@ package soup.movie.feature.home.impl.tab import androidx.compose.foundation.ExperimentalFoundationApi -import androidx.compose.foundation.Image import androidx.compose.foundation.combinedClickable import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column @@ -29,12 +28,12 @@ import androidx.compose.foundation.lazy.grid.LazyGridState import androidx.compose.foundation.lazy.grid.LazyVerticalGrid import androidx.compose.foundation.lazy.grid.items import androidx.compose.foundation.lazy.grid.rememberLazyGridState -import androidx.compose.material.Surface -import androidx.compose.material.Text +import androidx.compose.material3.Icon +import androidx.compose.material3.Surface +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.ColorFilter import androidx.compose.ui.layout.ContentScale import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp @@ -88,9 +87,7 @@ private fun MovieItem( ) { Surface( modifier = modifier, - color = MovieTheme.colors.onSurface.copy(alpha = 0.1f), - shape = MovieTheme.shapes.medium, - elevation = 0.dp, + shape = MovieTheme.shapes.small, ) { Box { AsyncImage( @@ -130,15 +127,13 @@ fun NoMovieItems( modifier = modifier, horizontalAlignment = Alignment.CenterHorizontally, ) { - Image( + Icon( MovieIcons.ViewModule, contentDescription = null, - colorFilter = ColorFilter.tint(color = MovieTheme.colors.onBackground), modifier = Modifier.size(72.dp), ) Text( text = stringResource(R.string.no_movies_description), - color = MovieTheme.colors.onBackground, ) } } diff --git a/feature/search/impl/build.gradle b/feature/search/impl/build.gradle index 4e2832e6d..628ad655c 100644 --- a/feature/search/impl/build.gradle +++ b/feature/search/impl/build.gradle @@ -18,7 +18,7 @@ dependencies { implementation projects.feature.home.api implementation libs.compose.foundation - implementation libs.compose.material + implementation libs.compose.material3 implementation libs.compose.ui implementation libs.androidx.hilt.navigation.compose diff --git a/feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchScreen.kt b/feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchScreen.kt index 34eddb97e..3079234b9 100644 --- a/feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchScreen.kt +++ b/feature/search/impl/src/main/java/soup/movie/feature/search/impl/SearchScreen.kt @@ -23,28 +23,21 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.systemBarsPadding import androidx.compose.foundation.text.KeyboardActions import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.foundation.text.selection.LocalTextSelectionColors -import androidx.compose.foundation.text.selection.TextSelectionColors -import androidx.compose.material.AppBarDefaults -import androidx.compose.material.ContentAlpha -import androidx.compose.material.Icon -import androidx.compose.material.IconButton -import androidx.compose.material.Scaffold -import androidx.compose.material.Surface -import androidx.compose.material.Text -import androidx.compose.material.TextField -import androidx.compose.material.TextFieldDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TextField +import androidx.compose.material3.TextFieldDefaults import androidx.compose.runtime.Composable -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue -import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusRequester import androidx.compose.ui.focus.focusRequester -import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalFocusManager import androidx.compose.ui.res.stringResource @@ -70,70 +63,51 @@ fun SearchScreen( topBar = { Surface( modifier = Modifier.fillMaxWidth().height(56.dp), - color = MovieTheme.colors.primarySurface, - elevation = AppBarDefaults.TopAppBarElevation, + color = MovieTheme.colors.primary, ) { val focusManager = LocalFocusManager.current - val handleColor = MovieTheme.colors.secondary - val contentAlpha = ContentAlpha.medium - val customTextSelectionColors = remember(handleColor, contentAlpha) { - TextSelectionColors( - handleColor = handleColor, - backgroundColor = handleColor.copy(alpha = contentAlpha), - ) + val focusRequester = FocusRequester() + LaunchedEffect(Unit) { + focusRequester.requestFocus() } - CompositionLocalProvider(LocalTextSelectionColors provides customTextSelectionColors) { - val focusRequester = FocusRequester() - LaunchedEffect(Unit) { - focusRequester.requestFocus() - } - val query by viewModel.query.collectAsState() - TextField( - value = query, - onValueChange = { viewModel.onQueryChanged(it) }, - modifier = Modifier.fillMaxSize() - .focusRequester(focusRequester), - keyboardOptions = KeyboardOptions( - keyboardType = KeyboardType.Text, - imeAction = ImeAction.Search, - ), - keyboardActions = KeyboardActions( - onSearch = { - focusManager.clearFocus() - }, - ), - singleLine = true, - placeholder = { - Text(stringResource(R.string.search_hint)) - }, - leadingIcon = { - IconButton(onClick = upPress) { - Icon( - MovieIcons.ArrowBack, - contentDescription = null, - ) - } + val query by viewModel.query.collectAsState() + TextField( + value = query, + onValueChange = { viewModel.onQueryChanged(it) }, + modifier = Modifier.fillMaxSize() + .focusRequester(focusRequester), + keyboardOptions = KeyboardOptions( + keyboardType = KeyboardType.Text, + imeAction = ImeAction.Search, + ), + keyboardActions = KeyboardActions( + onSearch = { + focusManager.clearFocus() }, - trailingIcon = { - IconButton(onClick = { viewModel.onQueryChanged("") }) { - Icon( - MovieIcons.Close, - contentDescription = null, - ) - } - }, - colors = TextFieldDefaults.textFieldColors( - cursorColor = MovieTheme.colors.secondary, - backgroundColor = Color.Transparent, - focusedIndicatorColor = Color.Transparent, - unfocusedIndicatorColor = Color.Transparent, - disabledIndicatorColor = Color.Transparent, - leadingIconColor = MovieTheme.colors.onSurface, - trailingIconColor = MovieTheme.colors.onSurface, - ), - ) - } + ), + singleLine = true, + placeholder = { + Text(stringResource(R.string.search_hint)) + }, + leadingIcon = { + IconButton(onClick = upPress) { + Icon( + MovieIcons.ArrowBack, + contentDescription = null, + ) + } + }, + trailingIcon = { + IconButton(onClick = { viewModel.onQueryChanged("") }) { + Icon( + MovieIcons.Close, + contentDescription = null, + ) + } + }, + colors = TextFieldDefaults.colors(), + ) } }, ) { paddingValues -> diff --git a/feature/settings/impl/build.gradle b/feature/settings/impl/build.gradle index 71d9314d6..8965fd1fe 100644 --- a/feature/settings/impl/build.gradle +++ b/feature/settings/impl/build.gradle @@ -24,7 +24,7 @@ dependencies { implementation libs.androidx.appcompat implementation libs.androidx.hilt.navigation.compose implementation libs.compose.foundation - implementation libs.compose.material + implementation libs.compose.material3 implementation libs.compose.ui implementation libs.androidx.navigation.compose implementation libs.materialmotion.compose.core diff --git a/feature/settings/impl/src/main/java/soup/movie/feature/settings/impl/home/SettingsScreen.kt b/feature/settings/impl/src/main/java/soup/movie/feature/settings/impl/home/SettingsScreen.kt index c1921dfee..e51bbdb19 100644 --- a/feature/settings/impl/src/main/java/soup/movie/feature/settings/impl/home/SettingsScreen.kt +++ b/feature/settings/impl/src/main/java/soup/movie/feature/settings/impl/home/SettingsScreen.kt @@ -27,27 +27,31 @@ import androidx.compose.foundation.layout.requiredHeight import androidx.compose.foundation.layout.size import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.ButtonDefaults -import androidx.compose.material.Divider -import androidx.compose.material.Icon -import androidx.compose.material.IconButton -import androidx.compose.material.Scaffold -import androidx.compose.material.Text -import androidx.compose.material.TopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.FilledTonalButton +import androidx.compose.material3.HorizontalDivider +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.runtime.collectAsState import androidx.compose.runtime.getValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource -import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.tooling.preview.PreviewLightDark import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp -import soup.movie.core.designsystem.UnelevatedButton import soup.movie.core.designsystem.icon.MovieIcons import soup.movie.core.designsystem.theme.MovieTheme import soup.movie.core.designsystem.util.debounce import soup.movie.feature.settings.impl.theme.stringResIdOf +import soup.movie.feature.theme.ThemeOption import soup.movie.resources.R @Composable @@ -55,6 +59,21 @@ fun SettingsScreen( viewModel: SettingsViewModel, onThemeEditClick: () -> Unit, modifier: Modifier = Modifier, +) { + val theme by viewModel.themeUiModel.collectAsState() + SettingsScreen( + themeUiModel = theme, + onThemeEditClick = onThemeEditClick, + modifier = modifier, + ) +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +private fun SettingsScreen( + themeUiModel: ThemeSettingUiModel?, + onThemeEditClick: () -> Unit, + modifier: Modifier = Modifier, ) { Scaffold( modifier = modifier, @@ -64,15 +83,14 @@ fun SettingsScreen( ) }, ) { paddingValues -> - val theme by viewModel.themeUiModel.collectAsState() Column( modifier = Modifier .padding(paddingValues) .padding(horizontal = 16.dp) .verticalScroll(rememberScrollState()), ) { - SettingsThemeItem(theme, onClick = onThemeEditClick) - SettingsDivider() + SettingsThemeItem(theme = themeUiModel, onClick = onThemeEditClick) + HorizontalDivider() } } } @@ -105,24 +123,20 @@ private fun SettingsThemeItem( Icon( MovieIcons.Palette, contentDescription = null, - tint = MovieTheme.colors.onBackground, ) } } Spacer(modifier = Modifier.height(12.dp)) Box(modifier = Modifier.requiredHeight(48.dp)) { - UnelevatedButton( + FilledTonalButton( onClick = { debounce(onClick) }, modifier = Modifier.fillMaxSize(), - colors = ButtonDefaults.buttonColors( - backgroundColor = MovieTheme.colors.surface, - ), ) { Text( text = text, modifier = Modifier.fillMaxWidth(), fontSize = 17.sp, - style = MovieTheme.typography.body2, + style = MovieTheme.typography.bodyMedium, ) } } @@ -137,13 +151,29 @@ private fun SettingsCategory( Text( text = text, modifier = modifier.fillMaxWidth(), - color = MovieTheme.colors.onBackground, - fontSize = 17.sp, - fontWeight = FontWeight.Bold, + style = MaterialTheme.typography.titleMedium, ) } +@Preview @Composable -private fun SettingsDivider() { - Divider(color = MovieTheme.colors.divider) +private fun SettingsCategoryPreview() { + MaterialTheme { + Surface { + SettingsCategory(text = "Category") + } + } +} + +@PreviewLightDark +@Composable +private fun SettingsScreenPreview() { + MovieTheme { + SettingsScreen( + themeUiModel = ThemeSettingUiModel( + themeOption = ThemeOption.System, + ), + onThemeEditClick = {}, + ) + } } diff --git a/feature/settings/impl/src/main/java/soup/movie/feature/settings/impl/theme/ThemeOptionScreen.kt b/feature/settings/impl/src/main/java/soup/movie/feature/settings/impl/theme/ThemeOptionScreen.kt index a9495ff6f..ebc0ace40 100644 --- a/feature/settings/impl/src/main/java/soup/movie/feature/settings/impl/theme/ThemeOptionScreen.kt +++ b/feature/settings/impl/src/main/java/soup/movie/feature/settings/impl/theme/ThemeOptionScreen.kt @@ -23,9 +23,10 @@ import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState import androidx.compose.foundation.verticalScroll -import androidx.compose.material.Scaffold -import androidx.compose.material.Text -import androidx.compose.material.TopAppBar +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource @@ -37,6 +38,7 @@ import soup.movie.core.designsystem.util.debounce import soup.movie.feature.theme.ThemeOption import soup.movie.resources.R +@OptIn(ExperimentalMaterial3Api::class) @Composable fun ThemeOptionScreen( items: List, diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 5893473eb..6859a6147 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -97,8 +97,9 @@ androidx-work-testing = { module = "androidx.work:work-testing", version.ref = " compose-bom = { module = "androidx.compose:compose-bom", version.ref = "compose-bom" } compose-foundation = { module = "androidx.compose.foundation:foundation" } -compose-material = { module = "androidx.compose.material:material" } compose-materialIconsExtended = { module = "androidx.compose.material:material-icons-extended" } +compose-material3 = { module = "androidx.compose.material3:material3" } +compose-material3-windowsizeclass = { module = "androidx.compose.material3:material3-window-size-class" } compose-ui = { module = "androidx.compose.ui:ui" } compose-ui-tooling = { module = "androidx.compose.ui:ui-tooling" } compose-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" }