diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 95d799a33..a9f2a0e48 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,7 +1,6 @@ -import com.android.build.gradle.internal.cxx.configure.gradleLocalProperties +import java.io.FileInputStream import org.apache.commons.io.output.ByteArrayOutputStream import org.jetbrains.kotlin.konan.properties.Properties -import java.io.FileInputStream @Suppress("dsl_scope_violation") plugins { @@ -28,14 +27,6 @@ val currentTime: Long by lazy { System.currentTimeMillis() } -val admobAppId: String? by lazy { - gradleLocalProperties(rootDir).getProperty("ADMOB_APP_ID") -} - -val admobBannerId: String? by lazy { - gradleLocalProperties(rootDir).getProperty("ADMOB_BANNER_ID") -} - val gitVersion: groovy.lang.Closure by extra val versionDetails: groovy.lang.Closure by extra val versionLastTag: String = versionDetails().lastTag @@ -69,8 +60,6 @@ android { resourceConfigurations.addAll(listOf("en", "ru")) buildConfigField("String", "VERSION_DATE", "\"$currentTime\"") - buildConfigField("String", "ADMOB_APP_ID", "\"$admobAppId\"") - buildConfigField("String", "ADMOB_BANNER_ID", "\"$admobBannerId\"") setProperty("archivesBaseName", "Movies-v$versionName($versionCode)") } diff --git a/app/src/main/kotlin/org/michaelbel/movies/MainActivity.kt b/app/src/main/kotlin/org/michaelbel/movies/MainActivity.kt index da7395507..1bc9c8a40 100644 --- a/app/src/main/kotlin/org/michaelbel/movies/MainActivity.kt +++ b/app/src/main/kotlin/org/michaelbel/movies/MainActivity.kt @@ -4,9 +4,7 @@ import android.os.Bundle import androidx.activity.compose.setContent import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity -import androidx.compose.runtime.CompositionLocalProvider import androidx.compose.runtime.getValue -import androidx.compose.ui.platform.LocalLayoutDirection import androidx.compose.ui.unit.LayoutDirection import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.view.WindowCompat @@ -15,6 +13,7 @@ import androidx.navigation.NavHostController import androidx.navigation.compose.rememberNavController import dagger.hilt.android.AndroidEntryPoint import org.michaelbel.movies.common.theme.AppTheme +import org.michaelbel.movies.navigation.ktx.addOnDestinationChangedListener import org.michaelbel.movies.ui.shortcuts.installShortcuts import org.michaelbel.movies.ui.theme.MoviesTheme @@ -40,20 +39,16 @@ internal class MainActivity: AppCompatActivity() { val layoutDirection: LayoutDirection by viewModel.layoutDirection.collectAsStateWithLifecycle() val navHostController: NavHostController = rememberNavController().apply { - addOnDestinationChangedListener { _, destination, arguments -> - viewModel.analyticsTrackDestination(destination, arguments) - } + addOnDestinationChangedListener(viewModel::analyticsTrackDestination) } MoviesTheme( theme = currentTheme, dynamicColors = dynamicColors ) { - CompositionLocalProvider(LocalLayoutDirection provides layoutDirection) { - MainActivityContent( - navHostController = navHostController - ) - } + MainActivityContent( + navHostController = navHostController + ) } } } diff --git a/app/src/main/kotlin/org/michaelbel/movies/MainActivityContent.kt b/app/src/main/kotlin/org/michaelbel/movies/MainActivityContent.kt index f1a84d7e7..0d4f67d68 100644 --- a/app/src/main/kotlin/org/michaelbel/movies/MainActivityContent.kt +++ b/app/src/main/kotlin/org/michaelbel/movies/MainActivityContent.kt @@ -4,15 +4,15 @@ import androidx.compose.runtime.Composable import androidx.navigation.NavHostController import androidx.navigation.compose.NavHost import androidx.navigation.compose.rememberNavController -import org.michaelbel.movies.auth.AccountDestination -import org.michaelbel.movies.auth.AuthDestination import org.michaelbel.movies.auth.accountGraph import org.michaelbel.movies.auth.authGraph -import org.michaelbel.movies.details.DetailsDestination +import org.michaelbel.movies.auth.navigateToAccount +import org.michaelbel.movies.auth.navigateToAuth import org.michaelbel.movies.details.detailsGraph +import org.michaelbel.movies.details.navigateToDetails import org.michaelbel.movies.feed.FeedDestination import org.michaelbel.movies.feed.feedGraph -import org.michaelbel.movies.settings.SettingsDestination +import org.michaelbel.movies.settings.navigateToSettings import org.michaelbel.movies.settings.settingsGraph @Composable @@ -25,30 +25,22 @@ internal fun MainActivityContent( startDestination = startDestination ) { authGraph( - onBackClick = navHostController::popBackStack + navigateBack = navHostController::popBackStack ) accountGraph( - onBackClick = navHostController::popBackStack + navigateBack = navHostController::popBackStack ) feedGraph( - navigateToAuth = { - navHostController.navigate(AuthDestination.route) - }, - navigateToAccount = { - navHostController.navigate(AccountDestination.route) - }, - navigateToSettings = { - navHostController.navigate(SettingsDestination.route) - }, - navigateToDetails = { movieId -> - navHostController.navigate(DetailsDestination.createNavigationRoute(movieId)) - } + navigateToAuth = navHostController::navigateToAuth, + navigateToAccount = navHostController::navigateToAccount, + navigateToSettings = navHostController::navigateToSettings, + navigateToDetails = navHostController::navigateToDetails ) detailsGraph( - onBackClick = navHostController::popBackStack + navigateBack = navHostController::popBackStack ) settingsGraph( - onBackClick = navHostController::popBackStack + navigateBack = navHostController::popBackStack ) } } \ No newline at end of file diff --git a/benchmark/build.gradle.kts b/benchmark/build.gradle.kts index c56cdf195..388112de3 100644 --- a/benchmark/build.gradle.kts +++ b/benchmark/build.gradle.kts @@ -28,6 +28,11 @@ android { } } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } + targetProjectPath = ":app" experimentalProperties["android.experimental.self-instrumenting"] = true } diff --git a/build.gradle.kts b/build.gradle.kts index 4a6ea330e..74b824c07 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,4 +1,3 @@ -@Suppress("dsl_scope_violation") plugins { alias(libs.plugins.application) apply false alias(libs.plugins.library) apply false @@ -14,19 +13,4 @@ plugins { alias(libs.plugins.spotless) alias(libs.plugins.detekt) alias(libs.plugins.palantir.git) - alias(libs.plugins.ben.manes.versions) - alias(libs.plugins.littlerobots.version.catalog.update) -} - -/** - * https://github.com/littlerobots/version-catalog-update-plugin - * ./gradlew versionCatalogUpdate - */ -versionCatalogUpdate { - sortByKey.set(false) - keep { - keepUnusedVersions.set(true) - keepUnusedLibraries.set(true) - keepUnusedPlugins.set(true) - } } \ No newline at end of file diff --git a/core/ads/.gitignore b/core/ads/.gitignore deleted file mode 100644 index 42afabfd2..000000000 --- a/core/ads/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/build \ No newline at end of file diff --git a/core/ads/build.gradle.kts b/core/ads/build.gradle.kts deleted file mode 100644 index 86b545ec5..000000000 --- a/core/ads/build.gradle.kts +++ /dev/null @@ -1,39 +0,0 @@ -@Suppress("dsl_scope_violation") -plugins { - alias(libs.plugins.library) - alias(libs.plugins.kotlin) -} - -android { - namespace = "org.michaelbel.movies.ads" - - defaultConfig { - minSdk = libs.versions.min.sdk.get().toInt() - compileSdk = libs.versions.compile.sdk.get().toInt() - } - - buildTypes { - create("benchmark") { - signingConfig = signingConfigs.getByName("debug") - matchingFallbacks += listOf("release") - initWith(getByName("release")) - } - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_17 - targetCompatibility = JavaVersion.VERSION_17 - } - - lint { - quiet = true - abortOnError = false - ignoreWarnings = true - checkDependencies = true - lintConfig = file("${project.rootDir}/config/codestyle/lint.xml") - } -} - -dependencies { - /*api(libs.play.services.ads)*/ -} \ No newline at end of file diff --git a/core/ads/src/main/AndroidManifest.xml b/core/ads/src/main/AndroidManifest.xml deleted file mode 100644 index 1d26c87a1..000000000 --- a/core/ads/src/main/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/core/ads/src/main/res/values/admob_config.xml b/core/ads/src/main/res/values/admob_config.xml deleted file mode 100644 index 4ac02b180..000000000 --- a/core/ads/src/main/res/values/admob_config.xml +++ /dev/null @@ -1,6 +0,0 @@ - - - ca-app-pub-3651393080934289~1447245983 - ca-app-pub-3651393080934289/4775379452 - ca-app-pub-3940256099942544/6300978111 - \ No newline at end of file diff --git a/core/common/build.gradle.kts b/core/common/build.gradle.kts index 2a7c77555..06b942c1d 100644 --- a/core/common/build.gradle.kts +++ b/core/common/build.gradle.kts @@ -65,6 +65,7 @@ dependencies { api(libs.timber) implementation(libs.bundles.appcompat) implementation(libs.firebase.crashlytics) + implementation(libs.firebase.messaging) implementation(libs.androidx.startup.runtime) implementation(libs.androidx.browser) diff --git a/core/entities/src/main/kotlin/org/michaelbel/movies/entities/TmdbConfig.kt b/core/entities/src/main/kotlin/org/michaelbel/movies/entities/TmdbConfig.kt index aaf19792a..61c9a0388 100644 --- a/core/entities/src/main/kotlin/org/michaelbel/movies/entities/TmdbConfig.kt +++ b/core/entities/src/main/kotlin/org/michaelbel/movies/entities/TmdbConfig.kt @@ -1,7 +1,10 @@ package org.michaelbel.movies.entities +const val TMDB_URL = "https://themoviedb.org" const val TMDB_TERMS_OF_USE = "https://themoviedb.org/documentation/website/terms-of-use" const val TMDB_PRIVACY_POLICY = "https://themoviedb.org/privacy-policy" +const val TMDB_REGISTER = "https://themoviedb.org/signup" +const val TMDB_RESET_PASSWORD = "https://themoviedb.org/reset-password" const val TMDB_MOVIE_URL = "https://themoviedb.org/movie/%d" val tmdbApiKey: String diff --git a/core/navigation/src/main/kotlin/org/michaelbel/movies/navigation/ktx/NavHostControllerKtx.kt b/core/navigation/src/main/kotlin/org/michaelbel/movies/navigation/ktx/NavHostControllerKtx.kt new file mode 100644 index 000000000..f99cb5b0f --- /dev/null +++ b/core/navigation/src/main/kotlin/org/michaelbel/movies/navigation/ktx/NavHostControllerKtx.kt @@ -0,0 +1,13 @@ +package org.michaelbel.movies.navigation.ktx + +import android.os.Bundle +import androidx.navigation.NavDestination +import androidx.navigation.NavHostController + +fun NavHostController.addOnDestinationChangedListener( + listener: (destination: NavDestination, arguments: Bundle?) -> Unit +) { + addOnDestinationChangedListener { _, destination, arguments -> + listener(destination, arguments) + } +} \ No newline at end of file diff --git a/core/ui/src/main/kotlin/org/michaelbel/movies/ui/icons/MoviesIcons.kt b/core/ui/src/main/kotlin/org/michaelbel/movies/ui/icons/MoviesIcons.kt index 604ee670c..1728851cb 100644 --- a/core/ui/src/main/kotlin/org/michaelbel/movies/ui/icons/MoviesIcons.kt +++ b/core/ui/src/main/kotlin/org/michaelbel/movies/ui/icons/MoviesIcons.kt @@ -5,7 +5,6 @@ import androidx.compose.material.icons.filled.MovieFilter import androidx.compose.material.icons.outlined.AccountCircle import androidx.compose.material.icons.outlined.ArrowBack import androidx.compose.material.icons.outlined.Close -import androidx.compose.material.icons.outlined.ErrorOutline import androidx.compose.material.icons.outlined.Info import androidx.compose.material.icons.outlined.Language import androidx.compose.material.icons.outlined.LocationOn @@ -28,7 +27,6 @@ object MoviesIcons { val ArrowBack = Icons.Outlined.ArrowBack val Close = Icons.Outlined.Close val Info = Icons.Outlined.Info - val Error = Icons.Outlined.ErrorOutline val Language = Icons.Outlined.Language val LocationOn = Icons.Outlined.LocationOn val MovieFilter = Icons.Filled.MovieFilter diff --git a/feature/account-impl/src/main/kotlin/org/michaelbel/movies/account/ui/AccountScreenContent.kt b/feature/account-impl/src/main/kotlin/org/michaelbel/movies/account/ui/AccountScreenContent.kt index 320125e33..b4d8df738 100644 --- a/feature/account-impl/src/main/kotlin/org/michaelbel/movies/account/ui/AccountScreenContent.kt +++ b/feature/account-impl/src/main/kotlin/org/michaelbel/movies/account/ui/AccountScreenContent.kt @@ -43,9 +43,7 @@ fun AccountRoute( loading = viewModel.loading, onBackClick = onBackClick, onLogoutClick = { - viewModel.onLogoutClick { - onBackClick() - } + viewModel.onLogoutClick(onBackClick) }, modifier = modifier ) @@ -177,7 +175,7 @@ internal fun AccountScreenContent( ) } else { Text( - text = stringResource(R.string.account_logout).uppercase(), + text = stringResource(R.string.account_logout), ) } } diff --git a/feature/account/src/main/kotlin/org/michaelbel/movies/auth/AccountDestination.kt b/feature/account/src/main/kotlin/org/michaelbel/movies/auth/AccountDestination.kt new file mode 100644 index 000000000..55ae76c3f --- /dev/null +++ b/feature/account/src/main/kotlin/org/michaelbel/movies/auth/AccountDestination.kt @@ -0,0 +1,10 @@ +package org.michaelbel.movies.auth + +import org.michaelbel.movies.navigation.MoviesNavigationDestination + +internal object AccountDestination: MoviesNavigationDestination { + + override val route: String = "account" + + override val destination: String = "account" +} \ No newline at end of file diff --git a/feature/account/src/main/kotlin/org/michaelbel/movies/auth/AccountNavigation.kt b/feature/account/src/main/kotlin/org/michaelbel/movies/auth/AccountNavigation.kt index 364c8ce89..0e7678c3c 100644 --- a/feature/account/src/main/kotlin/org/michaelbel/movies/auth/AccountNavigation.kt +++ b/feature/account/src/main/kotlin/org/michaelbel/movies/auth/AccountNavigation.kt @@ -1,20 +1,17 @@ package org.michaelbel.movies.auth import androidx.compose.ui.window.DialogProperties +import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.dialog import org.michaelbel.movies.account.ui.AccountRoute -import org.michaelbel.movies.navigation.MoviesNavigationDestination -object AccountDestination: MoviesNavigationDestination { - - override val route: String = "account" - - override val destination: String = "account" +fun NavController.navigateToAccount() { + navigate(AccountDestination.route) } fun NavGraphBuilder.accountGraph( - onBackClick: () -> Unit + navigateBack: () -> Unit ) { dialog( route = AccountDestination.route, @@ -23,7 +20,7 @@ fun NavGraphBuilder.accountGraph( ) ) { AccountRoute( - onBackClick = onBackClick + onBackClick = navigateBack ) } } \ No newline at end of file diff --git a/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/AuthErrorBox.kt b/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/AuthErrorBox.kt deleted file mode 100644 index 1616d291f..000000000 --- a/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/AuthErrorBox.kt +++ /dev/null @@ -1,64 +0,0 @@ -package org.michaelbel.movies.auth.ui - -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.material3.Icon -import androidx.compose.material3.MaterialTheme -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.tooling.preview.PreviewParameter -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import org.michaelbel.movies.auth.ktx.text -import org.michaelbel.movies.auth.ui.preview.ThrowablePreviewParameterProvider -import org.michaelbel.movies.ui.icons.MoviesIcons -import org.michaelbel.movies.ui.preview.DevicePreviews -import org.michaelbel.movies.ui.theme.MoviesTheme - -@Composable -fun AuthErrorBox( - error: Throwable?, - modifier: Modifier = Modifier -) { - Row( - modifier = modifier, - horizontalArrangement = Arrangement.Start, - verticalAlignment = Alignment.CenterVertically - ) { - Icon( - imageVector = MoviesIcons.Error, - contentDescription = null, - modifier = Modifier.size(24.dp), - tint = MaterialTheme.colorScheme.error - ) - - Text( - text = error.text, - modifier = Modifier.padding(start = 4.dp), - color = MaterialTheme.colorScheme.error, - fontSize = 13.sp, - textAlign = TextAlign.Start, - lineHeight = 13.sp - ) - } -} - -@Composable -@DevicePreviews -private fun AuthErrorBoxPreview( - @PreviewParameter(ThrowablePreviewParameterProvider::class) error: Throwable -) { - MoviesTheme { - AuthErrorBox( - error = error, - modifier = Modifier - .background(MaterialTheme.colorScheme.primaryContainer) - ) - } -} \ No newline at end of file diff --git a/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/AuthLinksBox.kt b/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/AuthLinksBox.kt index 12090b7bc..066bd0613 100644 --- a/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/AuthLinksBox.kt +++ b/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/AuthLinksBox.kt @@ -1,7 +1,5 @@ package org.michaelbel.movies.auth.ui -import androidx.activity.compose.rememberLauncherForActivityResult -import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -17,27 +15,19 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp import org.michaelbel.movies.auth_impl.R -import org.michaelbel.movies.common.browser.openUrl -import org.michaelbel.movies.entities.TMDB_PRIVACY_POLICY -import org.michaelbel.movies.entities.TMDB_TERMS_OF_USE import org.michaelbel.movies.ui.ktx.clickableWithoutRipple import org.michaelbel.movies.ui.preview.DevicePreviews import org.michaelbel.movies.ui.theme.MoviesTheme @Composable fun AuthLinksBox( + onTermsOfUseClick: () -> Unit, + onPrivacyPolicyClick: () -> Unit, modifier: Modifier = Modifier ) { - val toolbarColor: Int = MaterialTheme.colorScheme.primary.toArgb() - - val resultContract = rememberLauncherForActivityResult( - ActivityResultContracts.StartActivityForResult() - ) {} - Column( modifier = modifier, verticalArrangement = Arrangement.Top, @@ -58,7 +48,7 @@ fun AuthLinksBox( modifier = Modifier .padding(vertical = 16.dp) .clickableWithoutRipple { - openUrl(resultContract, toolbarColor, TMDB_TERMS_OF_USE) + onTermsOfUseClick() }, maxLines = 1, style = MaterialTheme.typography.bodyMedium.copy( @@ -79,7 +69,7 @@ fun AuthLinksBox( modifier = Modifier .padding(vertical = 16.dp) .clickableWithoutRipple { - openUrl(resultContract, toolbarColor, TMDB_PRIVACY_POLICY) + onPrivacyPolicyClick() }, maxLines = 1, style = MaterialTheme.typography.bodyMedium.copy( @@ -95,6 +85,8 @@ fun AuthLinksBox( private fun AuthLinksBoxPreview() { MoviesTheme { AuthLinksBox( + onTermsOfUseClick = {}, + onPrivacyPolicyClick = {}, modifier = Modifier .background(MaterialTheme.colorScheme.primaryContainer) ) diff --git a/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/AuthScreenContent.kt b/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/AuthScreenContent.kt index fb190124d..8839d97af 100644 --- a/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/AuthScreenContent.kt +++ b/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/AuthScreenContent.kt @@ -1,5 +1,7 @@ package org.michaelbel.movies.auth.ui +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.fadeIn import androidx.compose.animation.fadeOut @@ -17,6 +19,7 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.MaterialTheme import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.Text +import androidx.compose.material3.TextButton import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -26,11 +29,8 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier import androidx.compose.ui.focus.FocusDirection import androidx.compose.ui.focus.FocusManager -import androidx.compose.ui.focus.FocusRequester -import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.toArgb import androidx.compose.ui.platform.LocalFocusManager -import androidx.compose.ui.platform.LocalSoftwareKeyboardController -import androidx.compose.ui.platform.SoftwareKeyboardController import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction @@ -42,8 +42,17 @@ import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.Dimension import androidx.hilt.navigation.compose.hiltViewModel import org.michaelbel.movies.auth.AuthViewModel +import org.michaelbel.movies.auth.ktx.text import org.michaelbel.movies.auth_impl.R +import org.michaelbel.movies.common.browser.openUrl +import org.michaelbel.movies.domain.exceptions.CreateSessionWithLoginException +import org.michaelbel.movies.entities.TMDB_PRIVACY_POLICY +import org.michaelbel.movies.entities.TMDB_REGISTER +import org.michaelbel.movies.entities.TMDB_RESET_PASSWORD +import org.michaelbel.movies.entities.TMDB_TERMS_OF_USE +import org.michaelbel.movies.entities.TMDB_URL import org.michaelbel.movies.ui.icons.MoviesIcons +import org.michaelbel.movies.ui.ktx.clickableWithoutRipple @Composable fun AuthRoute( @@ -56,9 +65,7 @@ fun AuthRoute( loading = viewModel.loading, onBackClick = onBackClick, onSignInClick = { username, password -> - viewModel.onSignInClick(username, password) { - onBackClick() - } + viewModel.onSignInClick(username, password, onBackClick) }, modifier = modifier ) @@ -72,9 +79,12 @@ internal fun AuthScreenContent( onSignInClick: (String, String) -> Unit, modifier: Modifier = Modifier ) { + val resultContract = rememberLauncherForActivityResult( + ActivityResultContracts.StartActivityForResult() + ) {} + val toolbarColor: Int = MaterialTheme.colorScheme.primary.toArgb() + val focusManager: FocusManager = LocalFocusManager.current - val focusRequester: FocusRequester = remember { FocusRequester() } - val keyboardController: SoftwareKeyboardController? = LocalSoftwareKeyboardController.current var username: String by remember { mutableStateOf("") } var password: String by remember { mutableStateOf("") } @@ -94,8 +104,8 @@ internal fun AuthScreenContent( logo, usernameField, passwordField, - resetPasswordText, - errorBox, + resetPasswordButton, + signUpButton, signInButton, divider, loginButton, @@ -124,6 +134,9 @@ internal fun AuthScreenContent( start.linkTo(parent.start, 16.dp) top.linkTo(toolbar.bottom, 8.dp) end.linkTo(parent.end, 16.dp) + } + .clickableWithoutRipple { + openUrl(resultContract, toolbarColor, TMDB_URL) }, tint = MaterialTheme.colorScheme.onPrimaryContainer ) @@ -140,19 +153,19 @@ internal fun AuthScreenContent( start.linkTo(parent.start, 16.dp) top.linkTo(logo.bottom, 8.dp) end.linkTo(parent.end, 16.dp) - } + }, /*.autofill( autofillTypes = listOf(AutofillType.Username), onFill = { usernameFilled -> username = usernameFilled } )*/ - .focusRequester(focusRequester), label = { Text( text = stringResource(R.string.auth_label_username) ) }, + isError = error != null, keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Text, imeAction = ImeAction.Next @@ -162,6 +175,7 @@ internal fun AuthScreenContent( focusManager.moveFocus(FocusDirection.Down) } ), + singleLine = true, maxLines = 1 ) @@ -177,14 +191,13 @@ internal fun AuthScreenContent( start.linkTo(parent.start, 16.dp) top.linkTo(usernameField.bottom, 4.dp) end.linkTo(parent.end, 16.dp) - } + }, /*.autofill( autofillTypes = listOf(AutofillType.Password), onFill = { passwordFilled -> password = passwordFilled } )*/ - .focusRequester(focusRequester), label = { Text( text = stringResource(R.string.auth_label_password) @@ -208,6 +221,15 @@ internal fun AuthScreenContent( } } }, + supportingText = { + if (error != null) { + Text( + text = error.text, + color = MaterialTheme.colorScheme.error + ) + } + }, + isError = error != null, visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(), keyboardOptions = KeyboardOptions( keyboardType = KeyboardType.Password, @@ -215,44 +237,60 @@ internal fun AuthScreenContent( ), keyboardActions = KeyboardActions( onDone = { - keyboardController?.hide() + focusManager.clearFocus() onSignInClick(username, password) } ), + singleLine = true, maxLines = 1 ) AnimatedVisibility( - visible = error != null, + visible = error != null && error is CreateSessionWithLoginException, modifier = Modifier - .constrainAs(errorBox) { - width = Dimension.fillToConstraints + .constrainAs(resetPasswordButton) { + width = Dimension.wrapContent height = Dimension.wrapContent - start.linkTo(parent.start, 16.dp) - top.linkTo(passwordField.bottom, 8.dp) - end.linkTo(parent.end, 16.dp) + start.linkTo(parent.start, 6.dp) + top.linkTo(passwordField.bottom, 4.dp) }, enter = fadeIn(), exit = fadeOut() ) { - AuthErrorBox( - error = error - ) + TextButton( + onClick = { + openUrl(resultContract, toolbarColor, TMDB_RESET_PASSWORD) + } + ) { + Text( + text = stringResource(R.string.auth_reset_password) + ) + } } - /*Text( - text = stringResource(R.string.auth_reset_password), + AnimatedVisibility( + visible = error != null && error is CreateSessionWithLoginException, modifier = Modifier - .constrainAs(resetPasswordText) { + .constrainAs(signUpButton) { width = Dimension.wrapContent height = Dimension.wrapContent - start.linkTo(parent.start, 18.dp) - top.linkTo(passwordField.bottom, 8.dp) + start.linkTo(resetPasswordButton.end, 2.dp) + top.linkTo(resetPasswordButton.top) + bottom.linkTo(resetPasswordButton.bottom) }, - color = MaterialTheme.colorScheme.onPrimaryContainer, - fontSize = 12.sp, - maxLines = 1 - )*/ + enter = fadeIn(), + exit = fadeOut() + ) { + TextButton( + onClick = { + openUrl(resultContract, toolbarColor, TMDB_REGISTER) + } + ) { + Text( + text = stringResource(R.string.auth_sign_up) + ) + } + } Button( onClick = { @@ -263,7 +301,7 @@ internal fun AuthScreenContent( width = Dimension.fillToConstraints height = Dimension.wrapContent start.linkTo(parent.start, 16.dp) - top.linkTo(if (error != null) errorBox.bottom else passwordField.bottom, 32.dp) + top.linkTo(if (error != null && error is CreateSessionWithLoginException) resetPasswordButton.bottom else passwordField.bottom, 16.dp) end.linkTo(parent.end, 16.dp) }, enabled = username.isNotEmpty() && password.isNotEmpty() && !loading, @@ -280,7 +318,7 @@ internal fun AuthScreenContent( ) } else { Text( - text = stringResource(R.string.auth_sign_in).uppercase(), + text = stringResource(R.string.auth_sign_in) ) } } @@ -324,6 +362,12 @@ internal fun AuthScreenContent( }*/ AuthLinksBox( + onTermsOfUseClick = { + openUrl(resultContract, toolbarColor, TMDB_TERMS_OF_USE) + }, + onPrivacyPolicyClick = { + openUrl(resultContract, toolbarColor, TMDB_PRIVACY_POLICY) + }, modifier = Modifier .constrainAs(linksBox) { width = Dimension.fillToConstraints diff --git a/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/preview/ThrowablePreviewParameterProvider.kt b/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/preview/ThrowablePreviewParameterProvider.kt deleted file mode 100644 index 35b648335..000000000 --- a/feature/auth-impl/src/main/kotlin/org/michaelbel/movies/auth/ui/preview/ThrowablePreviewParameterProvider.kt +++ /dev/null @@ -1,16 +0,0 @@ -package org.michaelbel.movies.auth.ui.preview - -import androidx.compose.ui.tooling.preview.PreviewParameterProvider -import org.michaelbel.movies.domain.exceptions.AccountDetailsException -import org.michaelbel.movies.domain.exceptions.CreateRequestTokenException -import org.michaelbel.movies.domain.exceptions.CreateSessionException -import org.michaelbel.movies.domain.exceptions.CreateSessionWithLoginException - -internal class ThrowablePreviewParameterProvider: PreviewParameterProvider { - override val values: Sequence = sequenceOf( - CreateRequestTokenException, - CreateSessionWithLoginException, - CreateSessionException, - AccountDetailsException - ) -} \ No newline at end of file diff --git a/feature/auth-impl/src/main/res/values-ru/strings.xml b/feature/auth-impl/src/main/res/values-ru/strings.xml index 7c434fc1b..b607a8ad6 100644 --- a/feature/auth-impl/src/main/res/values-ru/strings.xml +++ b/feature/auth-impl/src/main/res/values-ru/strings.xml @@ -5,6 +5,7 @@ Пароль Сбросить пароль Войти + Зарегистрироваться Войти с Themoviedb Terms of Use Privacy Policy diff --git a/feature/auth-impl/src/main/res/values/strings.xml b/feature/auth-impl/src/main/res/values/strings.xml index 793c09f4d..794c4587a 100644 --- a/feature/auth-impl/src/main/res/values/strings.xml +++ b/feature/auth-impl/src/main/res/values/strings.xml @@ -5,6 +5,7 @@ Password Reset Password Sign in + Sign up Login with Themoviedb Terms of Use Privacy Policy diff --git a/feature/auth/src/main/kotlin/org/michaelbel/movies/auth/AuthDestination.kt b/feature/auth/src/main/kotlin/org/michaelbel/movies/auth/AuthDestination.kt new file mode 100644 index 000000000..45c6ef6e4 --- /dev/null +++ b/feature/auth/src/main/kotlin/org/michaelbel/movies/auth/AuthDestination.kt @@ -0,0 +1,10 @@ +package org.michaelbel.movies.auth + +import org.michaelbel.movies.navigation.MoviesNavigationDestination + +internal object AuthDestination: MoviesNavigationDestination { + + override val route: String = "auth" + + override val destination: String = "auth" +} \ No newline at end of file diff --git a/feature/auth/src/main/kotlin/org/michaelbel/movies/auth/AuthNavigation.kt b/feature/auth/src/main/kotlin/org/michaelbel/movies/auth/AuthNavigation.kt index 907e0cb69..d1cf37e50 100644 --- a/feature/auth/src/main/kotlin/org/michaelbel/movies/auth/AuthNavigation.kt +++ b/feature/auth/src/main/kotlin/org/michaelbel/movies/auth/AuthNavigation.kt @@ -1,20 +1,17 @@ package org.michaelbel.movies.auth import androidx.compose.ui.window.DialogProperties +import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.dialog import org.michaelbel.movies.auth.ui.AuthRoute -import org.michaelbel.movies.navigation.MoviesNavigationDestination -object AuthDestination: MoviesNavigationDestination { - - override val route: String = "auth" - - override val destination: String = "auth" +fun NavController.navigateToAuth() { + navigate(AuthDestination.route) } fun NavGraphBuilder.authGraph( - onBackClick: () -> Unit + navigateBack: () -> Unit ) { dialog( route = AuthDestination.route, @@ -23,7 +20,7 @@ fun NavGraphBuilder.authGraph( ) ) { AuthRoute( - onBackClick = onBackClick + onBackClick = navigateBack ) } } \ No newline at end of file diff --git a/feature/details-impl/build.gradle.kts b/feature/details-impl/build.gradle.kts index 280ed4544..0c8f34e08 100644 --- a/feature/details-impl/build.gradle.kts +++ b/feature/details-impl/build.gradle.kts @@ -55,7 +55,6 @@ android { dependencies { api(project(":core:navigation")) api(project(":core:ui")) - implementation(project(":core:ads")) implementation(project(":core:common")) implementation(project(":core:domain")) implementation(project(":core:network")) diff --git a/feature/details-impl/src/main/kotlin/org/michaelbel/movies/details/ui/DetailsAdvert.kt b/feature/details-impl/src/main/kotlin/org/michaelbel/movies/details/ui/DetailsAdvert.kt deleted file mode 100644 index f411b74ba..000000000 --- a/feature/details-impl/src/main/kotlin/org/michaelbel/movies/details/ui/DetailsAdvert.kt +++ /dev/null @@ -1,37 +0,0 @@ -package org.michaelbel.movies.details.ui - -/*@Composable -internal fun DetailsAdvert( - modifier: Modifier = Modifier, - adRequest: AdRequest -) { - Column( - modifier = modifier, - verticalArrangement = Arrangement.Bottom, - horizontalAlignment = Alignment.CenterHorizontally - ) { - AndroidView( - factory = { context -> - AdView(context).apply { - adUnitId = context.getString(R.string.admobBannerTestUnitId) - setAdSize(AdSize.LARGE_BANNER) - loadAd(adRequest) - } - }, - modifier = Modifier - .padding(top = 8.dp) - ) - } -} - -@Composable -@DevicePreviews -private fun DetailsAdvertPreview() { - MoviesTheme { - DetailsAdvert( - modifier = Modifier - .fillMaxSize(), - adRequest = AdRequest.Builder().build() - ) - } -}*/ \ No newline at end of file diff --git a/feature/details-impl/src/main/kotlin/org/michaelbel/movies/details/ui/DetailsContent.kt b/feature/details-impl/src/main/kotlin/org/michaelbel/movies/details/ui/DetailsContent.kt index affaed5b1..fb9a28af3 100644 --- a/feature/details-impl/src/main/kotlin/org/michaelbel/movies/details/ui/DetailsContent.kt +++ b/feature/details-impl/src/main/kotlin/org/michaelbel/movies/details/ui/DetailsContent.kt @@ -47,8 +47,7 @@ fun DetailsContent( var isNoImageVisible: Boolean by remember { mutableStateOf(false) } ConstraintLayout( - modifier = modifier - .verticalScroll(scrollState) + modifier = modifier.verticalScroll(scrollState) ) { val (image, noImageText, title, overview) = createRefs() diff --git a/feature/details/src/main/kotlin/org/michaelbel/movies/details/DetailsDestination.kt b/feature/details/src/main/kotlin/org/michaelbel/movies/details/DetailsDestination.kt new file mode 100644 index 000000000..50ee7726a --- /dev/null +++ b/feature/details/src/main/kotlin/org/michaelbel/movies/details/DetailsDestination.kt @@ -0,0 +1,16 @@ +package org.michaelbel.movies.details + +import org.michaelbel.movies.navigation.MoviesNavigationDestination + +internal object DetailsDestination: MoviesNavigationDestination { + + const val movieIdArg = "movieId" + + override val route: String = "movie/{$movieIdArg}" + + override val destination: String = "movie" + + fun createNavigationRoute(movieId: Int): String { + return "movie/$movieId" + } +} \ No newline at end of file diff --git a/feature/details/src/main/kotlin/org/michaelbel/movies/details/DetailsNavigation.kt b/feature/details/src/main/kotlin/org/michaelbel/movies/details/DetailsNavigation.kt index ab1a80e68..cedb10af7 100644 --- a/feature/details/src/main/kotlin/org/michaelbel/movies/details/DetailsNavigation.kt +++ b/feature/details/src/main/kotlin/org/michaelbel/movies/details/DetailsNavigation.kt @@ -1,6 +1,7 @@ package org.michaelbel.movies.details import androidx.navigation.NamedNavArgument +import androidx.navigation.NavController import androidx.navigation.NavDeepLink import androidx.navigation.NavGraphBuilder import androidx.navigation.NavType @@ -8,7 +9,6 @@ import androidx.navigation.compose.composable import androidx.navigation.navArgument import androidx.navigation.navDeepLink import org.michaelbel.movies.details.ui.DetailsRoute -import org.michaelbel.movies.navigation.MoviesNavigationDestination private val DETAILS_MOVIE_NAV_ARGUMENT: NamedNavArgument = navArgument( name = DetailsDestination.movieIdArg, @@ -21,21 +21,12 @@ private val DETAILS_MOVIE_DEEP_LINK: NavDeepLink = navDeepLink { uriPattern = "https://www.themoviedb.org/movie/{movieId}}" } -object DetailsDestination: MoviesNavigationDestination { - - const val movieIdArg = "movieId" - - override val route: String = "movie/{$movieIdArg}" - - override val destination: String = "movie" - - fun createNavigationRoute(movieId: Int): String { - return "movie/$movieId" - } +fun NavController.navigateToDetails(movieId: Int) { + navigate(DetailsDestination.createNavigationRoute(movieId)) } fun NavGraphBuilder.detailsGraph( - onBackClick: () -> Unit + navigateBack: () -> Unit ) { composable( route = DetailsDestination.route, @@ -43,7 +34,7 @@ fun NavGraphBuilder.detailsGraph( deepLinks = listOf(DETAILS_MOVIE_DEEP_LINK) ) { DetailsRoute( - onBackClick = onBackClick + onBackClick = navigateBack ) } } \ No newline at end of file diff --git a/feature/feed-impl/src/main/kotlin/org/michaelbel/movies/feed/ui/FeedScreenContent.kt b/feature/feed-impl/src/main/kotlin/org/michaelbel/movies/feed/ui/FeedScreenContent.kt index 09df85ecb..338222d97 100644 --- a/feature/feed-impl/src/main/kotlin/org/michaelbel/movies/feed/ui/FeedScreenContent.kt +++ b/feature/feed-impl/src/main/kotlin/org/michaelbel/movies/feed/ui/FeedScreenContent.kt @@ -28,6 +28,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.paging.compose.LazyPagingItems import androidx.paging.compose.collectAsLazyPagingItems +import java.net.UnknownHostException import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.launch import org.michaelbel.movies.domain.data.entity.AccountDb @@ -42,7 +43,6 @@ import org.michaelbel.movies.ui.ktx.clickableWithoutRipple import org.michaelbel.movies.ui.ktx.isFailure import org.michaelbel.movies.ui.ktx.isLoading import org.michaelbel.movies.ui.ktx.throwable -import java.net.UnknownHostException @Composable fun FeedRoute( @@ -145,8 +145,7 @@ private fun FeedScreenContent( when { pagingItems.isLoading -> { FeedLoading( - modifier = Modifier - .fillMaxSize(), + modifier = Modifier.fillMaxSize(), paddingValues = paddingValues ) } diff --git a/feature/feed/src/main/kotlin/org/michaelbel/movies/feed/FeedDestination.kt b/feature/feed/src/main/kotlin/org/michaelbel/movies/feed/FeedDestination.kt new file mode 100644 index 000000000..0ebd7f387 --- /dev/null +++ b/feature/feed/src/main/kotlin/org/michaelbel/movies/feed/FeedDestination.kt @@ -0,0 +1,10 @@ +package org.michaelbel.movies.feed + +import org.michaelbel.movies.navigation.MoviesNavigationDestination + +object FeedDestination: MoviesNavigationDestination { + + override val route: String = "feed" + + override val destination: String = "feed" +} \ No newline at end of file diff --git a/feature/feed/src/main/kotlin/org/michaelbel/movies/feed/FeedNavigation.kt b/feature/feed/src/main/kotlin/org/michaelbel/movies/feed/FeedNavigation.kt index da218e56c..dbe25a6d1 100644 --- a/feature/feed/src/main/kotlin/org/michaelbel/movies/feed/FeedNavigation.kt +++ b/feature/feed/src/main/kotlin/org/michaelbel/movies/feed/FeedNavigation.kt @@ -3,14 +3,6 @@ package org.michaelbel.movies.feed import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import org.michaelbel.movies.feed.ui.FeedRoute -import org.michaelbel.movies.navigation.MoviesNavigationDestination - -object FeedDestination: MoviesNavigationDestination { - - override val route: String = "feed" - - override val destination: String = "feed" -} fun NavGraphBuilder.feedGraph( navigateToAccount: () -> Unit, diff --git a/feature/settings-impl/build.gradle.kts b/feature/settings-impl/build.gradle.kts index 8843c8187..56d385dcb 100644 --- a/feature/settings-impl/build.gradle.kts +++ b/feature/settings-impl/build.gradle.kts @@ -58,7 +58,6 @@ dependencies { api(project(":core:navigation")) api(project(":core:common")) api(project(":core:ui")) - implementation(project(":core:ads")) implementation(project(":core:domain")) testImplementation(libs.junit) diff --git a/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsLanguageDialog.kt b/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsLanguageDialog.kt index 900e1bd7e..2383ea8a8 100644 --- a/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsLanguageDialog.kt +++ b/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsLanguageDialog.kt @@ -42,13 +42,11 @@ fun SettingLanguageDialog( confirmButton = { TextButton( onClick = onDismissRequest, - modifier = Modifier - .testTag("ConfirmTextButton") + modifier = Modifier.testTag("ConfirmTextButton") ) { Text( text = stringResource(R.string.settings_action_cancel), - modifier = Modifier - .testTag("ConfirmText"), + modifier = Modifier.testTag("ConfirmText"), style = MaterialTheme.typography.labelLarge.copy( color = MaterialTheme.colorScheme.primary ) @@ -59,15 +57,13 @@ fun SettingLanguageDialog( Icon( imageVector = MoviesIcons.Language, contentDescription = null, - modifier = Modifier - .testTag("Icon") + modifier = Modifier.testTag("Icon") ) }, title = { Text( text = stringResource(R.string.settings_language), - modifier = Modifier - .testTag("Title"), + modifier = Modifier.testTag("Title"), style = MaterialTheme.typography.headlineSmall.copy( color = MaterialTheme.colorScheme.onSurface ) @@ -122,14 +118,12 @@ private fun SettingLanguageDialogContent( selectedColor = MaterialTheme.colorScheme.primary, unselectedColor = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.6F) ), - modifier = Modifier - .padding(start = 16.dp) + modifier = Modifier.padding(start = 16.dp) ) Text( text = language.languageText, - modifier = Modifier - .padding(start = 8.dp), + modifier = Modifier.padding(start = 8.dp), style = MaterialTheme.typography.bodyLarge.copy( color = MaterialTheme.colorScheme.onBackground ) diff --git a/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsNetworkRequestDelayBox.kt b/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsNetworkRequestDelayBox.kt index 2c3f7d975..bd2d70c4b 100644 --- a/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsNetworkRequestDelayBox.kt +++ b/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsNetworkRequestDelayBox.kt @@ -18,11 +18,11 @@ import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import androidx.constraintlayout.compose.ConstraintLayout import androidx.constraintlayout.compose.Dimension +import kotlin.math.roundToInt import org.michaelbel.movies.settings_impl.R import org.michaelbel.movies.ui.preview.DevicePreviews import org.michaelbel.movies.ui.preview.provider.SliderPreviewParameterProvider import org.michaelbel.movies.ui.theme.MoviesTheme -import kotlin.math.roundToInt @Composable fun SettingsNetworkRequestDelayBox( @@ -34,8 +34,7 @@ fun SettingsNetworkRequestDelayBox( sliderPosition = delay.toFloat() ConstraintLayout( - modifier = modifier - .testTag("ConstraintLayout") + modifier = modifier.testTag("ConstraintLayout") ) { val (title, value, slider) = createRefs() diff --git a/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsPostNotificationsBox.kt b/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsPostNotificationsBox.kt index 3b20fc672..c259eb18b 100644 --- a/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsPostNotificationsBox.kt +++ b/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsPostNotificationsBox.kt @@ -41,7 +41,9 @@ fun SettingsPostNotificationsBox( ) { val context: Context = LocalContext.current val notificationManager: NotificationManager = context.notificationManager - var areNotificationsEnabled: Boolean by remember { mutableStateOf(notificationManager.areNotificationsEnabled()) } + var areNotificationsEnabled: Boolean by remember { + mutableStateOf(notificationManager.areNotificationsEnabled()) + } val resultContract = rememberLauncherForActivityResult( ActivityResultContracts.StartActivityForResult() diff --git a/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsScreenContent.kt b/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsScreenContent.kt index 0fd3e41d9..6ef0628c5 100644 --- a/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsScreenContent.kt +++ b/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsScreenContent.kt @@ -172,8 +172,7 @@ private fun SettingsScreenContent( modifier = modifier, topBar = { SettingsToolbar( - modifier = Modifier - .statusBarsPadding(), + modifier = Modifier.statusBarsPadding(), onNavigationIconClick = onBackClick ) }, diff --git a/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsThemeDialog.kt b/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsThemeDialog.kt index 7108e505f..03bb01a25 100644 --- a/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsThemeDialog.kt +++ b/feature/settings-impl/src/main/kotlin/org/michaelbel/movies/settings/ui/SettingsThemeDialog.kt @@ -43,13 +43,11 @@ internal fun SettingThemeDialog( confirmButton = { TextButton( onClick = onDismissRequest, - modifier = Modifier - .testTag("ConfirmTextButton") + modifier = Modifier.testTag("ConfirmTextButton") ) { Text( text = stringResource(R.string.settings_action_cancel), - modifier = Modifier - .testTag("ConfirmText"), + modifier = Modifier.testTag("ConfirmText"), style = MaterialTheme.typography.labelLarge.copy( color = MaterialTheme.colorScheme.primary ) @@ -60,15 +58,13 @@ internal fun SettingThemeDialog( Icon( painter = painterResource(MoviesIcons.ThemeLightDark), contentDescription = null, - modifier = Modifier - .testTag("Icon") + modifier = Modifier.testTag("Icon") ) }, title = { Text( text = stringResource(R.string.settings_theme), - modifier = Modifier - .testTag("Title"), + modifier = Modifier.testTag("Title"), style = MaterialTheme.typography.headlineSmall.copy( color = MaterialTheme.colorScheme.onSurface ) @@ -123,14 +119,12 @@ private fun SettingThemeDialogContent( selectedColor = MaterialTheme.colorScheme.primary, unselectedColor = MaterialTheme.colorScheme.onBackground.copy(alpha = 0.6F) ), - modifier = Modifier - .padding(start = 16.dp) + modifier = Modifier.padding(start = 16.dp) ) Text( text = theme.themeText, - modifier = Modifier - .padding(start = 8.dp), + modifier = Modifier.padding(start = 8.dp), style = MaterialTheme.typography.bodyLarge.copy( color = MaterialTheme.colorScheme.onBackground ) diff --git a/feature/settings/src/main/kotlin/org/michaelbel/movies/settings/SettingsDestination.kt b/feature/settings/src/main/kotlin/org/michaelbel/movies/settings/SettingsDestination.kt new file mode 100644 index 000000000..a95eb616a --- /dev/null +++ b/feature/settings/src/main/kotlin/org/michaelbel/movies/settings/SettingsDestination.kt @@ -0,0 +1,10 @@ +package org.michaelbel.movies.settings + +import org.michaelbel.movies.navigation.MoviesNavigationDestination + +internal object SettingsDestination: MoviesNavigationDestination { + + override val route: String = "settings" + + override val destination: String = "settings" +} \ No newline at end of file diff --git a/feature/settings/src/main/kotlin/org/michaelbel/movies/settings/SettingsNavigation.kt b/feature/settings/src/main/kotlin/org/michaelbel/movies/settings/SettingsNavigation.kt index 2920db433..db3edd3b6 100644 --- a/feature/settings/src/main/kotlin/org/michaelbel/movies/settings/SettingsNavigation.kt +++ b/feature/settings/src/main/kotlin/org/michaelbel/movies/settings/SettingsNavigation.kt @@ -1,10 +1,10 @@ package org.michaelbel.movies.settings +import androidx.navigation.NavController import androidx.navigation.NavDeepLink import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable import androidx.navigation.navDeepLink -import org.michaelbel.movies.navigation.MoviesNavigationDestination import org.michaelbel.movies.settings.ui.SettingsRoute import org.michaelbel.movies.ui.shortcuts.INTENT_ACTION_SETTINGS @@ -12,22 +12,19 @@ private val SETTINGS_SHORTCUT_NAV_DEEP_LINK: NavDeepLink = navDeepLink { uriPattern = INTENT_ACTION_SETTINGS } -object SettingsDestination: MoviesNavigationDestination { - - override val route: String = "settings" - - override val destination: String = "settings" +fun NavController.navigateToSettings() { + navigate(SettingsDestination.route) } fun NavGraphBuilder.settingsGraph( - onBackClick: () -> Unit + navigateBack: () -> Unit ) { composable( route = SettingsDestination.route, deepLinks = listOf(SETTINGS_SHORTCUT_NAV_DEEP_LINK) ) { SettingsRoute( - onBackClick = onBackClick + onBackClick = navigateBack ) } } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index e5b68e605..d4fe88b65 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -1,53 +1,48 @@ # Compose to Kotlin Compatibility Map: # https://d.android.com/jetpack/androidx/releases/compose-kotlin [versions] -# @keep min-sdk = "21" -# @keep compile-sdk = "33" -# @keep target-sdk = "33" -# @pin -gradle = "8.0.0" -# @pin update when updating compose compiler -kotlin = "1.8.20" -kotlin-ksp = "1.8.20-1.0.11" -kotlin-coroutines = "1.6.4" -kotlin-serialization = "1.5.0" -# @pin update when updating kotlin -compose-compiler = "1.4.6" +gradle = "8.0.1" +kotlin = "1.8.21" +kotlin-ksp = "1.8.21-1.0.11" +kotlin-coroutines = "1.7.1" +kotlin-serialization = "1.5.1" +compose-compiler = "1.4.7" detekt = "1.22.0" spotless = "6.18.0" google-services = "4.3.15" -play-services-ads = "22.0.0" +play-services-ads = "22.1.0" play-services-base = "18.2.0" firebase-analytics = "21.2.2" firebase-appdistribution = "3.2.0" -firebase-config = "21.3.0" +firebase-config = "21.4.0" firebase-crashlytics-plugin = "2.9.4" -firebase-crashlytics = "18.3.6" +firebase-crashlytics = "18.3.7" +firebase-messaging = "23.1.2" play-core = "1.8.1" accompanist = "0.30.1" -material = "1.8.0" +material = "1.9.0" material-compose-theme-adapter = "1.2.1" -hilt = "2.45" -androidx-compose-foundation = "1.4.2" -androidx-compose-runtime = "1.4.2" -androidx-compose-ui = "1.4.2" -androidx-compose-compiler = "1.4.6" -androidx-compose-material = "1.4.2" -androidx-compose-material3 = "1.0.1" +hilt = "2.46.1" +androidx-compose-foundation = "1.4.3" +androidx-compose-runtime = "1.4.3" +androidx-compose-ui = "1.4.3" +androidx-compose-compiler = "1.4.7" +androidx-compose-material = "1.4.3" +androidx-compose-material3 = "1.1.0" androidx-appcompat = "1.7.0-alpha02" androidx-activity = "1.7.1" androidx-browser = "1.5.0" -androidx-core = "1.10.0" +androidx-core = "1.10.1" androidx-core-splashscreen = "1.0.1" androidx-constraintlayout = "1.0.1" androidx-lifecycle = "2.6.1" androidx-hilt-navigation-compose = "1.0.0" androidx-hilt-work = "1.0.0" androidx-navigation = "2.5.3" -androidx-paging = "1.0.0-alpha18" +androidx-paging = "1.0.0-alpha19" androidx-datastore = "1.0.0" androidx-startup = "1.1.1" androidx-room = "2.5.1" @@ -56,7 +51,7 @@ androidx-test-ext = "1.1.5" androidx-test-uiautomator = "2.2.0" androidx-espresso-core = "3.5.1" androidx-benchmark = "1.1.1" -androidx-profile-installer = "1.3.0" +androidx-profile-installer = "1.3.1" androidx-work = "2.8.1" coil = "2.3.0" okhttp = "4.11.0" @@ -68,8 +63,6 @@ javapoet = "1.13.0" junit = "4.13.2" lint-checks = "1.2.0" palantir-git = "3.0.0" -ben-manes-versions = "0.46.0" -littlerobots-version-catalog-update = "0.8.0" [libraries] kotlin-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlin-coroutines" } @@ -81,6 +74,7 @@ play-services-base = { module = "com.google.android.gms:play-services-base", ver firebase-analytics = { module = "com.google.firebase:firebase-analytics-ktx", version.ref = "firebase-analytics" } firebase-config = { module = "com.google.firebase:firebase-config-ktx", version.ref = "firebase-config" } firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics-ktx", version.ref = "firebase-crashlytics" } +firebase-messaging = { module = "com.google.firebase:firebase-messaging-ktx", version.ref = "firebase-messaging" } play-core = { module = "com.google.android.play:core-ktx", version.ref = "play-core" } accompanist-appcompat-theme = { module = "com.google.accompanist:accompanist-appcompat-theme", version.ref = "accompanist" } accompanist-drawablepainter = { module = "com.google.accompanist:accompanist-drawablepainter", version.ref = "accompanist" } @@ -214,6 +208,4 @@ androidx-navigation-safeargs = { id = "androidx.navigation.safeargs.kotlin", ver application = { id = "com.android.application", version.ref = "gradle" } library = { id = "com.android.library", version.ref = "gradle" } test = { id = "com.android.test", version.ref = "gradle" } -palantir-git = { id = "com.palantir.git-version", version.ref = "palantir-git" } -ben-manes-versions = { id = "com.github.ben-manes.versions", version.ref = "ben-manes-versions" } -littlerobots-version-catalog-update = { id = "nl.littlerobots.version-catalog-update", version.ref = "littlerobots-version-catalog-update" } \ No newline at end of file +palantir-git = { id = "com.palantir.git-version", version.ref = "palantir-git" } \ No newline at end of file diff --git a/readme.md b/readme.md index 79d29ca27..236123d70 100644 --- a/readme.md +++ b/readme.md @@ -23,7 +23,7 @@ TMDB_API_KEY=your_own_tmdb_api_key ## Download [](https://play.google.com/store/apps/details?id=org.michaelbel.moviemade) -[](https://github.com/michaelbel/movies/releases/download/1.4.5/Movies-v1.4.5.1178.-release.apk) +[](https://github.com/michaelbel/movies/releases/download/1.4.6/Movies-v1.4.6.1196.-release.apk) ## Technologies @@ -32,8 +32,8 @@ TMDB_API_KEY=your_own_tmdb_api_key - [x] [Clean Architecture](https://d.android.com/topic/architecture) - [x] [TMDB API](https://developers.themoviedb.org/3/getting-started) - [x] [KTS Gradle Files](https://d.android.com/studio/build/migrate-to-kts) -- [x] [Kotlin Symbol Processing API](https://d.android.com/studio/build/migrate-to-ksp) 1.8.20-1.0.11 -- [x] [Gradle Plugin](https://d.android.com/studio/releases/gradle-plugin) 8.0.0 +- [x] [Kotlin Symbol Processing API](https://d.android.com/studio/build/migrate-to-ksp) +- [x] [Gradle Plugin](https://d.android.com/studio/releases/gradle-plugin) - [x] Gradle Version Catalog - [x] MinSDK 21 - [x] TargetSDK 33 @@ -42,46 +42,47 @@ TMDB_API_KEY=your_own_tmdb_api_key - [x] [Dark Theme](https://d.android.com/develop/ui/views/theming/darktheme) - [x] [Dynamic Colors](https://d.android.com/develop/ui/views/theming/dynamic-colors) - [x] [Themed App Icon](https://d.android.com/develop/ui/views/launch/icon_design_adaptive) -- [x] 100% [Kotlin](https://d.android.com/kotlin) 1.8.20 -- [x] 100% [Jetpack Compose](https://d.android.com/jetpack/compose) 1.4.6 -- [x] [Accompanist](https://github.com/google/accompanist) 0.30.1 +- [x] 100% [Kotlin](https://d.android.com/kotlin) +- [x] 100% [Jetpack Compose](https://d.android.com/jetpack/compose) +- [x] [Accompanist](https://github.com/google/accompanist) - [x] [Compose PreviewParameterProvider](https://d.android.com/jetpack/compose/tooling#previewparameter) - [x] [Downloadable Fonts](https://d.android.com/develop/ui/views/text-and-emoji/downloadable-fonts) -- [x] [KotlinX Coroutines](https://github.com/Kotlin/kotlinx.coroutines) 1.6.4 -- [x] [KotlinX Serialization](https://github.com/Kotlin/kotlinx.serialization) 1.5.0 -- [x] [Appcompat](https://d.android.com/jetpack/androidx/releases/appcompat) 1.6.0-rc01 -- [x] [Dagger Hilt](https://github.com/google/dagger) 2.45 +- [x] [KotlinX Coroutines](https://github.com/Kotlin/kotlinx.coroutines) +- [x] [KotlinX Serialization](https://github.com/Kotlin/kotlinx.serialization) +- [x] [Appcompat](https://d.android.com/jetpack/androidx/releases/appcompat) +- [x] [Dagger Hilt](https://github.com/google/dagger) - [x] [ViewModel](https://d.android.com/topic/libraries/architecture/viewmodel) -- [x] [Lifecycle](https://d.android.com/topic/libraries/architecture/lifecycle) 2.6.0-alpha03 -- [x] [Room](https://d.android.com/training/data-storage/room) 2.5.1 -- [x] [WorkManager](https://d.android.com/topic/libraries/architecture/workmanager) 2.8.1 -- [x] [DataStore](https://d.android.com/datastore) 1.0.0 -- [x] [Startup](https://d.android.com/jetpack/androidx/releases/startup) 1.1.1 -- [x] [Navigation](https://d.android.com/guide/navigation) 2.5.3 -- [x] [Paging](https://d.android.com/topic/libraries/architecture/paging/v3-overview) (RemoteMediator & PagingSource) 1.0.0-alpha18 +- [x] [Lifecycle](https://d.android.com/topic/libraries/architecture/lifecycle) +- [x] [Room](https://d.android.com/training/data-storage/room) +- [x] [WorkManager](https://d.android.com/topic/libraries/architecture/workmanager) +- [x] [DataStore](https://d.android.com/datastore) +- [x] [Startup](https://d.android.com/jetpack/androidx/releases/startup) +- [x] [Navigation](https://d.android.com/guide/navigation) +- [x] [Paging](https://d.android.com/topic/libraries/architecture/paging/v3-overview) (RemoteMediator & PagingSource) - [x] [ConstraintLayout](https://d.android.com/develop/ui/views/layout/constraint-layout) -- [x] [Browser](https://d.android.com/jetpack/androidx/releases/browser) 1.5.0 -- [x] [OkHttp](https://github.com/square/okhttp) 4.11.0 -- [x] [Retrofit](https://github.com/square/retrofit) 2.9.0 -- [x] [Retrofit Kotlinx Converter Serialization](https://github.com/JakeWharton/retrofit2-kotlinx-serialization-converter) 0.8.0 -- [x] [Chucker](https://github.com/ChuckerTeam/chucker) 3.5.2 -- [x] [Coil](https://github.com/coil-kt/coil) 2.3.0 -- [x] [Timber](https://github.com/JakeWharton/timber) 5.0.1 -- [x] [Firebase Crashlytics](https://firebase.google.com/products/crashlytics) 18.3.6 -- [x] [Firebase App Distribution](https://firebase.google.com/products/app-distribution) 3.2.0 -- [x] [Firebase Remote Config](https://firebase.google.com/products/remote-config) 21.3.0 -- [x] [Google Analytics for Firebase](https://firebase.google.com/products/analytics) 21.2.2 +- [x] [Browser](https://d.android.com/jetpack/androidx/releases/browser) +- [x] [OkHttp](https://github.com/square/okhttp) +- [x] [Retrofit](https://github.com/square/retrofit) +- [x] [Retrofit Kotlinx Converter Serialization](https://github.com/JakeWharton/retrofit2-kotlinx-serialization-converter) +- [x] [Chucker](https://github.com/ChuckerTeam/chucker) +- [x] [Coil](https://github.com/coil-kt/coil) +- [x] [Timber](https://github.com/JakeWharton/timber) +- [x] [Firebase Crashlytics](https://firebase.google.com/products/crashlytics) +- [x] [Firebase App Distribution](https://firebase.google.com/products/app-distribution) +- [x] [Firebase Remote Config](https://firebase.google.com/products/remote-config) +- [ ] [Firebase Messaging](https://firebase.google.com/products/cloud-messaging) +- [x] [Google Analytics for Firebase](https://firebase.google.com/products/analytics) - [x] [In-App Reviews](https://d.android.com/guide/playcore/in-app-review) - [x] [App Shortcuts](https://d.android.com/develop/ui/views/launch/shortcuts) - [x] [Dependabot](https://github.com/dependabot) - [x] [Github Actions](https://github.com/michaelbel/movies/tree/develop/.github/workflows) CI/CD - [x] [Github Releases](https://github.com/michaelbel/movies/releases) - [x] [Lint](https://d.android.com/studio/write/lint) -- [x] [Detekt](https://github.com/detekt/detekt) 1.22.0 -- [x] [Spotless](https://github.com/diffplug/spotless) 6.18.0 +- [x] [Detekt](https://github.com/detekt/detekt) +- [x] [Spotless](https://github.com/diffplug/spotless) - [x] [Distribute App via Telegram Bot](https://github.com/appleboy/telegram-action) - [x] [Non-Transitive R classes](https://d.android.com/studio/build/optimize-your-build#use-non-transitive-r-classes) -- [x] [SplashScreen API](https://d.android.com/develop/ui/views/launch/splash-screen) 1.0.1 +- [x] [SplashScreen API](https://d.android.com/develop/ui/views/launch/splash-screen) - [x] [Per-App Language Preferences](https://d.android.com/guide/topics/resources/app-languages) - [x] [Settings Panel](https://d.android.com/reference/android/provider/Settings.Panel) - [x] [Benchmark](https://d.android.com/topic/performance/benchmarking/benchmarking-overview) diff --git a/settings.gradle.kts b/settings.gradle.kts index a7ac6ed81..f7cea792e 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -21,7 +21,6 @@ include( ":benchmark", - ":core:ads", ":core:analytics", ":core:common", ":core:domain",