Better navigation animations and starting to make a theme

This commit is contained in:
Z. Charles Dziura 2024-11-09 12:56:06 -05:00
parent d19e489c9f
commit 39da8e66ef
16 changed files with 501 additions and 83 deletions

View file

@ -109,6 +109,7 @@ dependencies {
implementation(libs.hilt) implementation(libs.hilt)
kapt(libs.hilt.kapt) kapt(libs.hilt.kapt)
implementation(libs.hilt.compose) implementation(libs.hilt.compose)
implementation(libs.google.fonts)
testImplementation(libs.junit) testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit) androidTestImplementation(libs.androidx.junit)

View file

@ -4,6 +4,10 @@ import android.os.Bundle
import androidx.activity.ComponentActivity import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge import androidx.activity.enableEdgeToEdge
import androidx.compose.animation.AnimatedContentTransitionScope
import androidx.compose.animation.core.tween
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
@ -14,8 +18,8 @@ import androidx.navigation.compose.composable
import androidx.navigation.compose.navigation import androidx.navigation.compose.navigation
import androidx.navigation.compose.rememberNavController import androidx.navigation.compose.rememberNavController
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
import ing.bikeshedengineer.debtpirate.auth.presentation.login.LoginScreen import ing.bikeshedengineer.debtpirate.app.screen.auth.presentation.login.LoginScreen
import ing.bikeshedengineer.debtpirate.auth.presentation.register.RegistrationScreen import ing.bikeshedengineer.debtpirate.app.screen.auth.presentation.register.RegistrationScreen
import ing.bikeshedengineer.debtpirate.navigation.Destination import ing.bikeshedengineer.debtpirate.navigation.Destination
import ing.bikeshedengineer.debtpirate.navigation.NavigationAction import ing.bikeshedengineer.debtpirate.navigation.NavigationAction
import ing.bikeshedengineer.debtpirate.navigation.Navigator import ing.bikeshedengineer.debtpirate.navigation.Navigator
@ -51,8 +55,31 @@ class MainActivity : ComponentActivity() {
} }
DebtPirateTheme { DebtPirateTheme {
NavHost(navController = navController, startDestination = Destination.AuthGraph) { NavHost(
navigation<Destination.AuthGraph>(startDestination = Destination.LoginScreen) { navController = navController,
startDestination = Destination.AuthGraph,
enterTransition = {
slideIntoContainer(
AnimatedContentTransitionScope.SlideDirection.Start,
animationSpec = tween(350)
)
},
exitTransition = {
fadeOut(tween(350))
},
popEnterTransition = {
fadeIn(tween(350))
},
popExitTransition = {
slideOutOfContainer(
AnimatedContentTransitionScope.SlideDirection.End,
animationSpec = tween(350)
)
}
) {
navigation<Destination.AuthGraph>(
startDestination = Destination.LoginScreen
) {
composable<Destination.LoginScreen>() { LoginScreen() } composable<Destination.LoginScreen>() { LoginScreen() }
composable<Destination.RegistrationScreen>() { RegistrationScreen() } composable<Destination.RegistrationScreen>() { RegistrationScreen() }
} }

View file

@ -1,14 +1,14 @@
package ing.bikeshedengineer.debtpirate.auth.di package ing.bikeshedengineer.debtpirate.app.screen.auth.di
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import dagger.hilt.InstallIn import dagger.hilt.InstallIn
import dagger.hilt.android.components.ViewModelComponent import dagger.hilt.android.components.ViewModelComponent
import dagger.hilt.android.scopes.ViewModelScoped import dagger.hilt.android.scopes.ViewModelScoped
import ing.bikeshedengineer.debtpirate.auth.usecase.SubmitAccountRegistrationRequestUseCase import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.SubmitAccountRegistrationRequestUseCase
import ing.bikeshedengineer.debtpirate.auth.usecase.SubmitLoginCredentialsUseCase import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.SubmitLoginCredentialsUseCase
import ing.bikeshedengineer.debtpirate.auth.usecase.ValidateLoginCredentialsUseCase import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.ValidateLoginCredentialsUseCase
import ing.bikeshedengineer.debtpirate.auth.usecase.ValidateNewAccountRegistrationUseCase import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.ValidateNewAccountRegistrationUseCase
import ing.bikeshedengineer.debtpirate.data.repository.AuthRepository import ing.bikeshedengineer.debtpirate.data.repository.AuthRepository
import ing.bikeshedengineer.debtpirate.data.repository.UserRepository import ing.bikeshedengineer.debtpirate.data.repository.UserRepository

View file

@ -1,4 +1,4 @@
package ing.bikeshedengineer.debtpirate.auth.presentation.login package ing.bikeshedengineer.debtpirate.app.screen.auth.presentation.login
import android.annotation.SuppressLint import android.annotation.SuppressLint
import androidx.compose.foundation.background import androidx.compose.foundation.background
@ -20,6 +20,7 @@ import androidx.compose.material.icons.outlined.Password
import androidx.compose.material.icons.outlined.PersonAdd import androidx.compose.material.icons.outlined.PersonAdd
import androidx.compose.material3.Button import androidx.compose.material3.Button
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
@ -82,7 +83,7 @@ fun LoginScreen(
@Composable @Composable
private fun LoginScreenTopAppBar(modifier: Modifier = Modifier) { private fun LoginScreenTopAppBar(modifier: Modifier = Modifier) {
Box(modifier = modifier.background(Color.Green)) { Box(modifier = modifier.background(MaterialTheme.colorScheme.primaryContainer)) {
Text( Text(
text = "Hello from Login! I'm in a box!", text = "Hello from Login! I'm in a box!",
modifier = Modifier.align(Alignment.Center) modifier = Modifier.align(Alignment.Center)

View file

@ -1,13 +1,13 @@
package ing.bikeshedengineer.debtpirate.auth.presentation.login package ing.bikeshedengineer.debtpirate.app.screen.auth.presentation.login
import androidx.datastore.core.DataStore import androidx.datastore.core.DataStore
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import ing.bikeshedengineer.debtpirate.PrefsDataStore import ing.bikeshedengineer.debtpirate.PrefsDataStore
import ing.bikeshedengineer.debtpirate.auth.usecase.LoginCredentialsValidationResult import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.LoginCredentialsValidationResult
import ing.bikeshedengineer.debtpirate.auth.usecase.SubmitLoginCredentialsUseCase import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.SubmitLoginCredentialsUseCase
import ing.bikeshedengineer.debtpirate.auth.usecase.ValidateLoginCredentialsUseCase import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.ValidateLoginCredentialsUseCase
import ing.bikeshedengineer.debtpirate.domain.model.Token import ing.bikeshedengineer.debtpirate.domain.model.Token
import ing.bikeshedengineer.debtpirate.navigation.Destination import ing.bikeshedengineer.debtpirate.navigation.Destination
import ing.bikeshedengineer.debtpirate.navigation.Navigator import ing.bikeshedengineer.debtpirate.navigation.Navigator

View file

@ -1,4 +1,4 @@
package ing.bikeshedengineer.debtpirate.auth.presentation.register package ing.bikeshedengineer.debtpirate.app.screen.auth.presentation.register
import android.annotation.SuppressLint import android.annotation.SuppressLint
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
@ -19,10 +19,10 @@ import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.MediumTopAppBar
import androidx.compose.material3.OutlinedTextField import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold import androidx.compose.material3.Scaffold
import androidx.compose.material3.Text import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.TopAppBarDefaults
import androidx.compose.material3.rememberTopAppBarState import androidx.compose.material3.rememberTopAppBarState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
@ -104,7 +104,7 @@ fun RegistrationScreen(viewModel: RegistrationScreenViewModel = hiltViewModel<Re
@OptIn(ExperimentalMaterial3Api::class) @OptIn(ExperimentalMaterial3Api::class)
@Composable @Composable
private fun RegistrationTopAppBar(onNavigateUp: () -> Unit, modifier: Modifier = Modifier) { private fun RegistrationTopAppBar(onNavigateUp: () -> Unit, modifier: Modifier = Modifier) {
MediumTopAppBar( TopAppBar(
colors = TopAppBarDefaults.topAppBarColors( colors = TopAppBarDefaults.topAppBarColors(
containerColor = MaterialTheme.colorScheme.primaryContainer, containerColor = MaterialTheme.colorScheme.primaryContainer,
titleContentColor = MaterialTheme.colorScheme.primary, titleContentColor = MaterialTheme.colorScheme.primary,

View file

@ -1,11 +1,11 @@
package ing.bikeshedengineer.debtpirate.auth.presentation.register package ing.bikeshedengineer.debtpirate.app.screen.auth.presentation.register
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope import androidx.lifecycle.viewModelScope
import dagger.hilt.android.lifecycle.HiltViewModel import dagger.hilt.android.lifecycle.HiltViewModel
import ing.bikeshedengineer.debtpirate.auth.usecase.NewAccountRegistrationValidationResult import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.NewAccountRegistrationValidationResult
import ing.bikeshedengineer.debtpirate.auth.usecase.SubmitAccountRegistrationRequestUseCase import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.SubmitAccountRegistrationRequestUseCase
import ing.bikeshedengineer.debtpirate.auth.usecase.ValidateNewAccountRegistrationUseCase import ing.bikeshedengineer.debtpirate.app.screen.auth.usecase.ValidateNewAccountRegistrationUseCase
import ing.bikeshedengineer.debtpirate.navigation.Destination import ing.bikeshedengineer.debtpirate.navigation.Destination
import ing.bikeshedengineer.debtpirate.navigation.Navigator import ing.bikeshedengineer.debtpirate.navigation.Navigator
import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.MutableStateFlow
@ -81,7 +81,8 @@ class RegistrationScreenViewModel @Inject constructor(
if (fieldsAreValid) { if (fieldsAreValid) {
viewModelScope.launch { viewModelScope.launch {
try { try {
val result = submitAccountRegistrationRequest(emailAddress, name, confirmPassword) val result =
submitAccountRegistrationRequest(emailAddress, name, confirmPassword)
navigator.navigate(Destination.LoginScreen) navigator.navigate(Destination.LoginScreen)
resetFields() resetFields()

View file

@ -1,4 +1,4 @@
package ing.bikeshedengineer.debtpirate.auth.usecase package ing.bikeshedengineer.debtpirate.app.screen.auth.usecase
import android.util.Log import android.util.Log
import ing.bikeshedengineer.debtpirate.data.remote.model.user.UserCreatePostRequest import ing.bikeshedengineer.debtpirate.data.remote.model.user.UserCreatePostRequest

View file

@ -1,4 +1,4 @@
package ing.bikeshedengineer.debtpirate.auth.usecase package ing.bikeshedengineer.debtpirate.app.screen.auth.usecase
import android.util.Log import android.util.Log
import ing.bikeshedengineer.debtpirate.data.remote.model.auth.AuthLoginPostRequest import ing.bikeshedengineer.debtpirate.data.remote.model.auth.AuthLoginPostRequest

View file

@ -1,4 +1,4 @@
package ing.bikeshedengineer.debtpirate.auth.usecase package ing.bikeshedengineer.debtpirate.app.screen.auth.usecase
sealed class LoginCredentialsValidationResult { sealed class LoginCredentialsValidationResult {
object EmptyCredentials : LoginCredentialsValidationResult() object EmptyCredentials : LoginCredentialsValidationResult()

View file

@ -1,4 +1,4 @@
package ing.bikeshedengineer.debtpirate.auth.usecase package ing.bikeshedengineer.debtpirate.app.screen.auth.usecase
import android.util.Patterns import android.util.Patterns

View file

@ -2,10 +2,218 @@ package ing.bikeshedengineer.debtpirate.theme
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
val Purple80 = Color(0xFFD0BCFF) val primaryLight = Color(0xFF1E6A4F)
val PurpleGrey80 = Color(0xFFCCC2DC) val onPrimaryLight = Color(0xFFFFFFFF)
val Pink80 = Color(0xFFEFB8C8) val primaryContainerLight = Color(0xFFA8F2CF)
val onPrimaryContainerLight = Color(0xFF002115)
val secondaryLight = Color(0xFF37618E)
val onSecondaryLight = Color(0xFFFFFFFF)
val secondaryContainerLight = Color(0xFFD2E4FF)
val onSecondaryContainerLight = Color(0xFF001C37)
val tertiaryLight = Color(0xFF835414)
val onTertiaryLight = Color(0xFFFFFFFF)
val tertiaryContainerLight = Color(0xFFFFDDBA)
val onTertiaryContainerLight = Color(0xFF2B1700)
val errorLight = Color(0xFF8E4D30)
val onErrorLight = Color(0xFFFFFFFF)
val errorContainerLight = Color(0xFFFFDBCE)
val onErrorContainerLight = Color(0xFF370E00)
val backgroundLight = Color(0xFFF5FBF5)
val onBackgroundLight = Color(0xFF171D1A)
val surfaceLight = Color(0xFFF5FBF5)
val onSurfaceLight = Color(0xFF171D1A)
val surfaceVariantLight = Color(0xFFDBE5DD)
val onSurfaceVariantLight = Color(0xFF404944)
val outlineLight = Color(0xFF707973)
val outlineVariantLight = Color(0xFFBFC9C2)
val scrimLight = Color(0xFF000000)
val inverseSurfaceLight = Color(0xFF2C322E)
val inverseOnSurfaceLight = Color(0xFFECF2ED)
val inversePrimaryLight = Color(0xFF8CD5B4)
val surfaceDimLight = Color(0xFFD6DBD6)
val surfaceBrightLight = Color(0xFFF5FBF5)
val surfaceContainerLowestLight = Color(0xFFFFFFFF)
val surfaceContainerLowLight = Color(0xFFEFF5EF)
val surfaceContainerLight = Color(0xFFEAEFEA)
val surfaceContainerHighLight = Color(0xFFE4EAE4)
val surfaceContainerHighestLight = Color(0xFFDEE4DE)
val Purple40 = Color(0xFF6650a4) val primaryLightMediumContrast = Color(0xFF004D36)
val PurpleGrey40 = Color(0xFF625b71) val onPrimaryLightMediumContrast = Color(0xFFFFFFFF)
val Pink40 = Color(0xFF7D5260) val primaryContainerLightMediumContrast = Color(0xFF398164)
val onPrimaryContainerLightMediumContrast = Color(0xFFFFFFFF)
val secondaryLightMediumContrast = Color(0xFF164571)
val onSecondaryLightMediumContrast = Color(0xFFFFFFFF)
val secondaryContainerLightMediumContrast = Color(0xFF4F77A6)
val onSecondaryContainerLightMediumContrast = Color(0xFFFFFFFF)
val tertiaryLightMediumContrast = Color(0xFF613A00)
val onTertiaryLightMediumContrast = Color(0xFFFFFFFF)
val tertiaryContainerLightMediumContrast = Color(0xFF9D6A29)
val onTertiaryContainerLightMediumContrast = Color(0xFFFFFFFF)
val errorLightMediumContrast = Color(0xFF6C3218)
val onErrorLightMediumContrast = Color(0xFFFFFFFF)
val errorContainerLightMediumContrast = Color(0xFFA96244)
val onErrorContainerLightMediumContrast = Color(0xFFFFFFFF)
val backgroundLightMediumContrast = Color(0xFFF5FBF5)
val onBackgroundLightMediumContrast = Color(0xFF171D1A)
val surfaceLightMediumContrast = Color(0xFFF5FBF5)
val onSurfaceLightMediumContrast = Color(0xFF171D1A)
val surfaceVariantLightMediumContrast = Color(0xFFDBE5DD)
val onSurfaceVariantLightMediumContrast = Color(0xFF3C4540)
val outlineLightMediumContrast = Color(0xFF58615C)
val outlineVariantLightMediumContrast = Color(0xFF747D77)
val scrimLightMediumContrast = Color(0xFF000000)
val inverseSurfaceLightMediumContrast = Color(0xFF2C322E)
val inverseOnSurfaceLightMediumContrast = Color(0xFFECF2ED)
val inversePrimaryLightMediumContrast = Color(0xFF8CD5B4)
val surfaceDimLightMediumContrast = Color(0xFFD6DBD6)
val surfaceBrightLightMediumContrast = Color(0xFFF5FBF5)
val surfaceContainerLowestLightMediumContrast = Color(0xFFFFFFFF)
val surfaceContainerLowLightMediumContrast = Color(0xFFEFF5EF)
val surfaceContainerLightMediumContrast = Color(0xFFEAEFEA)
val surfaceContainerHighLightMediumContrast = Color(0xFFE4EAE4)
val surfaceContainerHighestLightMediumContrast = Color(0xFFDEE4DE)
val primaryLightHighContrast = Color(0xFF00281B)
val onPrimaryLightHighContrast = Color(0xFFFFFFFF)
val primaryContainerLightHighContrast = Color(0xFF004D36)
val onPrimaryContainerLightHighContrast = Color(0xFFFFFFFF)
val secondaryLightHighContrast = Color(0xFF002342)
val onSecondaryLightHighContrast = Color(0xFFFFFFFF)
val secondaryContainerLightHighContrast = Color(0xFF164571)
val onSecondaryContainerLightHighContrast = Color(0xFFFFFFFF)
val tertiaryLightHighContrast = Color(0xFF341D00)
val onTertiaryLightHighContrast = Color(0xFFFFFFFF)
val tertiaryContainerLightHighContrast = Color(0xFF613A00)
val onTertiaryContainerLightHighContrast = Color(0xFFFFFFFF)
val errorLightHighContrast = Color(0xFF421300)
val onErrorLightHighContrast = Color(0xFFFFFFFF)
val errorContainerLightHighContrast = Color(0xFF6C3218)
val onErrorContainerLightHighContrast = Color(0xFFFFFFFF)
val backgroundLightHighContrast = Color(0xFFF5FBF5)
val onBackgroundLightHighContrast = Color(0xFF171D1A)
val surfaceLightHighContrast = Color(0xFFF5FBF5)
val onSurfaceLightHighContrast = Color(0xFF000000)
val surfaceVariantLightHighContrast = Color(0xFFDBE5DD)
val onSurfaceVariantLightHighContrast = Color(0xFF1D2621)
val outlineLightHighContrast = Color(0xFF3C4540)
val outlineVariantLightHighContrast = Color(0xFF3C4540)
val scrimLightHighContrast = Color(0xFF000000)
val inverseSurfaceLightHighContrast = Color(0xFF2C322E)
val inverseOnSurfaceLightHighContrast = Color(0xFFFFFFFF)
val inversePrimaryLightHighContrast = Color(0xFFB1FCD8)
val surfaceDimLightHighContrast = Color(0xFFD6DBD6)
val surfaceBrightLightHighContrast = Color(0xFFF5FBF5)
val surfaceContainerLowestLightHighContrast = Color(0xFFFFFFFF)
val surfaceContainerLowLightHighContrast = Color(0xFFEFF5EF)
val surfaceContainerLightHighContrast = Color(0xFFEAEFEA)
val surfaceContainerHighLightHighContrast = Color(0xFFE4EAE4)
val surfaceContainerHighestLightHighContrast = Color(0xFFDEE4DE)
val primaryDark = Color(0xFF8CD5B4)
val onPrimaryDark = Color(0xFF003826)
val primaryContainerDark = Color(0xFF005139)
val onPrimaryContainerDark = Color(0xFFA8F2CF)
val secondaryDark = Color(0xFFA1C9FD)
val onSecondaryDark = Color(0xFF003259)
val secondaryContainerDark = Color(0xFF1B4975)
val onSecondaryContainerDark = Color(0xFFD2E4FF)
val tertiaryDark = Color(0xFFF9BA72)
val onTertiaryDark = Color(0xFF482A00)
val tertiaryContainerDark = Color(0xFF663E00)
val onTertiaryContainerDark = Color(0xFFFFDDBA)
val errorDark = Color(0xFFFFB598)
val onErrorDark = Color(0xFF552007)
val errorContainerDark = Color(0xFF71361C)
val onErrorContainerDark = Color(0xFFFFDBCE)
val backgroundDark = Color(0xFF0F1512)
val onBackgroundDark = Color(0xFFDEE4DE)
val surfaceDark = Color(0xFF0F1512)
val onSurfaceDark = Color(0xFFDEE4DE)
val surfaceVariantDark = Color(0xFF404944)
val onSurfaceVariantDark = Color(0xFFBFC9C2)
val outlineDark = Color(0xFF8A938D)
val outlineVariantDark = Color(0xFF404944)
val scrimDark = Color(0xFF000000)
val inverseSurfaceDark = Color(0xFFDEE4DE)
val inverseOnSurfaceDark = Color(0xFF2C322E)
val inversePrimaryDark = Color(0xFF1E6A4F)
val surfaceDimDark = Color(0xFF0F1512)
val surfaceBrightDark = Color(0xFF353B37)
val surfaceContainerLowestDark = Color(0xFF0A0F0C)
val surfaceContainerLowDark = Color(0xFF171D1A)
val surfaceContainerDark = Color(0xFF1B211E)
val surfaceContainerHighDark = Color(0xFF252B28)
val surfaceContainerHighestDark = Color(0xFF303632)
val primaryDarkMediumContrast = Color(0xFF90DAB8)
val onPrimaryDarkMediumContrast = Color(0xFF001B10)
val primaryContainerDarkMediumContrast = Color(0xFF569E80)
val onPrimaryContainerDarkMediumContrast = Color(0xFF000000)
val secondaryDarkMediumContrast = Color(0xFFA8CEFF)
val onSecondaryDarkMediumContrast = Color(0xFF00172E)
val secondaryContainerDarkMediumContrast = Color(0xFF6B93C4)
val onSecondaryContainerDarkMediumContrast = Color(0xFF000000)
val tertiaryDarkMediumContrast = Color(0xFFFEBF76)
val onTertiaryDarkMediumContrast = Color(0xFF241200)
val tertiaryContainerDarkMediumContrast = Color(0xFFBD8642)
val onTertiaryContainerDarkMediumContrast = Color(0xFF000000)
val errorDarkMediumContrast = Color(0xFFFFBBA0)
val onErrorDarkMediumContrast = Color(0xFF2E0B00)
val errorContainerDarkMediumContrast = Color(0xFFCA7D5D)
val onErrorContainerDarkMediumContrast = Color(0xFF000000)
val backgroundDarkMediumContrast = Color(0xFF0F1512)
val onBackgroundDarkMediumContrast = Color(0xFFDEE4DE)
val surfaceDarkMediumContrast = Color(0xFF0F1512)
val onSurfaceDarkMediumContrast = Color(0xFFF7FCF6)
val surfaceVariantDarkMediumContrast = Color(0xFF404944)
val onSurfaceVariantDarkMediumContrast = Color(0xFFC4CDC6)
val outlineDarkMediumContrast = Color(0xFF9CA59F)
val outlineVariantDarkMediumContrast = Color(0xFF7C857F)
val scrimDarkMediumContrast = Color(0xFF000000)
val inverseSurfaceDarkMediumContrast = Color(0xFFDEE4DE)
val inverseOnSurfaceDarkMediumContrast = Color(0xFF252B28)
val inversePrimaryDarkMediumContrast = Color(0xFF00533A)
val surfaceDimDarkMediumContrast = Color(0xFF0F1512)
val surfaceBrightDarkMediumContrast = Color(0xFF353B37)
val surfaceContainerLowestDarkMediumContrast = Color(0xFF0A0F0C)
val surfaceContainerLowDarkMediumContrast = Color(0xFF171D1A)
val surfaceContainerDarkMediumContrast = Color(0xFF1B211E)
val surfaceContainerHighDarkMediumContrast = Color(0xFF252B28)
val surfaceContainerHighestDarkMediumContrast = Color(0xFF303632)
val primaryDarkHighContrast = Color(0xFFEDFFF4)
val onPrimaryDarkHighContrast = Color(0xFF000000)
val primaryContainerDarkHighContrast = Color(0xFF90DAB8)
val onPrimaryContainerDarkHighContrast = Color(0xFF000000)
val secondaryDarkHighContrast = Color(0xFFFAFAFF)
val onSecondaryDarkHighContrast = Color(0xFF000000)
val secondaryContainerDarkHighContrast = Color(0xFFA8CEFF)
val onSecondaryContainerDarkHighContrast = Color(0xFF000000)
val tertiaryDarkHighContrast = Color(0xFFFFFAF8)
val onTertiaryDarkHighContrast = Color(0xFF000000)
val tertiaryContainerDarkHighContrast = Color(0xFFFEBF76)
val onTertiaryContainerDarkHighContrast = Color(0xFF000000)
val errorDarkHighContrast = Color(0xFFFFF9F8)
val onErrorDarkHighContrast = Color(0xFF000000)
val errorContainerDarkHighContrast = Color(0xFFFFBBA0)
val onErrorContainerDarkHighContrast = Color(0xFF000000)
val backgroundDarkHighContrast = Color(0xFF0F1512)
val onBackgroundDarkHighContrast = Color(0xFFDEE4DE)
val surfaceDarkHighContrast = Color(0xFF0F1512)
val onSurfaceDarkHighContrast = Color(0xFFFFFFFF)
val surfaceVariantDarkHighContrast = Color(0xFF404944)
val onSurfaceVariantDarkHighContrast = Color(0xFFF4FDF5)
val outlineDarkHighContrast = Color(0xFFC4CDC6)
val outlineVariantDarkHighContrast = Color(0xFFC4CDC6)
val scrimDarkHighContrast = Color(0xFF000000)
val inverseSurfaceDarkHighContrast = Color(0xFFDEE4DE)
val inverseOnSurfaceDarkHighContrast = Color(0xFF000000)
val inversePrimaryDarkHighContrast = Color(0xFF003121)
val surfaceDimDarkHighContrast = Color(0xFF0F1512)
val surfaceBrightDarkHighContrast = Color(0xFF353B37)
val surfaceContainerLowestDarkHighContrast = Color(0xFF0A0F0C)
val surfaceContainerLowDarkHighContrast = Color(0xFF171D1A)
val surfaceContainerDarkHighContrast = Color(0xFF1B211E)
val surfaceContainerHighDarkHighContrast = Color(0xFF252B28)
val surfaceContainerHighestDarkHighContrast = Color(0xFF303632)

View file

@ -8,28 +8,84 @@ import androidx.compose.material3.dynamicDarkColorScheme
import androidx.compose.material3.dynamicLightColorScheme import androidx.compose.material3.dynamicLightColorScheme
import androidx.compose.material3.lightColorScheme import androidx.compose.material3.lightColorScheme
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalContext
private val DarkColorScheme = darkColorScheme( private val lightScheme = lightColorScheme(
primary = Purple80, primary = primaryLight,
secondary = PurpleGrey80, onPrimary = onPrimaryLight,
tertiary = Pink80 primaryContainer = primaryContainerLight,
onPrimaryContainer = onPrimaryContainerLight,
secondary = secondaryLight,
onSecondary = onSecondaryLight,
secondaryContainer = secondaryContainerLight,
onSecondaryContainer = onSecondaryContainerLight,
tertiary = tertiaryLight,
onTertiary = onTertiaryLight,
tertiaryContainer = tertiaryContainerLight,
onTertiaryContainer = onTertiaryContainerLight,
error = errorLight,
onError = onErrorLight,
errorContainer = errorContainerLight,
onErrorContainer = onErrorContainerLight,
background = backgroundLight,
onBackground = onBackgroundLight,
surface = surfaceLight,
onSurface = onSurfaceLight,
surfaceVariant = surfaceVariantLight,
onSurfaceVariant = onSurfaceVariantLight,
outline = outlineLight,
outlineVariant = outlineVariantLight,
scrim = scrimLight,
inverseSurface = inverseSurfaceLight,
inverseOnSurface = inverseOnSurfaceLight,
inversePrimary = inversePrimaryLight,
surfaceDim = surfaceDimLight,
surfaceBright = surfaceBrightLight,
surfaceContainerLowest = surfaceContainerLowestLight,
surfaceContainerLow = surfaceContainerLowLight,
surfaceContainer = surfaceContainerLight,
surfaceContainerHigh = surfaceContainerHighLight,
surfaceContainerHighest = surfaceContainerHighestLight,
) )
private val LightColorScheme = lightColorScheme( private val darkScheme = darkColorScheme(
primary = Purple40, primary = primaryDark,
secondary = PurpleGrey40, onPrimary = onPrimaryDark,
tertiary = Pink40 primaryContainer = primaryContainerDark,
onPrimaryContainer = onPrimaryContainerDark,
/* Other default colors to override secondary = secondaryDark,
background = Color(0xFFFFFBFE), onSecondary = onSecondaryDark,
surface = Color(0xFFFFFBFE), secondaryContainer = secondaryContainerDark,
onPrimary = Color.White, onSecondaryContainer = onSecondaryContainerDark,
onSecondary = Color.White, tertiary = tertiaryDark,
onTertiary = Color.White, onTertiary = onTertiaryDark,
onBackground = Color(0xFF1C1B1F), tertiaryContainer = tertiaryContainerDark,
onSurface = Color(0xFF1C1B1F), onTertiaryContainer = onTertiaryContainerDark,
*/ error = errorDark,
onError = onErrorDark,
errorContainer = errorContainerDark,
onErrorContainer = onErrorContainerDark,
background = backgroundDark,
onBackground = onBackgroundDark,
surface = surfaceDark,
onSurface = onSurfaceDark,
surfaceVariant = surfaceVariantDark,
onSurfaceVariant = onSurfaceVariantDark,
outline = outlineDark,
outlineVariant = outlineVariantDark,
scrim = scrimDark,
inverseSurface = inverseSurfaceDark,
inverseOnSurface = inverseOnSurfaceDark,
inversePrimary = inversePrimaryDark,
surfaceDim = surfaceDimDark,
surfaceBright = surfaceBrightDark,
surfaceContainerLowest = surfaceContainerLowestDark,
surfaceContainerLow = surfaceContainerLowDark,
surfaceContainer = surfaceContainerDark,
surfaceContainerHigh = surfaceContainerHighDark,
surfaceContainerHighest = surfaceContainerHighestDark,
) )
@Composable @Composable
@ -37,17 +93,18 @@ fun DebtPirateTheme(
darkTheme: Boolean = isSystemInDarkTheme(), darkTheme: Boolean = isSystemInDarkTheme(),
// Dynamic color is available on Android 12+ // Dynamic color is available on Android 12+
dynamicColor: Boolean = true, dynamicColor: Boolean = true,
content: @Composable () -> Unit content: @Composable() () -> Unit
) { ) {
val colorScheme = when { // val colorScheme = when {
dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { // dynamicColor -> {
val context = LocalContext.current // val context = LocalContext.current
if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) // if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context)
} // }
// darkTheme -> darkScheme
// else -> lightScheme
// }
darkTheme -> DarkColorScheme val colorScheme = darkScheme
else -> LightColorScheme
}
MaterialTheme( MaterialTheme(
colorScheme = colorScheme, colorScheme = colorScheme,

View file

@ -1,34 +1,123 @@
package ing.bikeshedengineer.debtpirate.theme package ing.bikeshedengineer.debtpirate.theme
import androidx.compose.material3.Typography import androidx.compose.material3.Typography
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.googlefonts.Font
import androidx.compose.ui.text.googlefonts.GoogleFont
import androidx.compose.ui.unit.TextUnit
import androidx.compose.ui.unit.TextUnitType
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import ing.bikeshedengineer.debtpirate.R
val googleFontsProvider = GoogleFont.Provider(
providerAuthority = "com.google.android.gms.fonts",
providerPackage = "com.google.android.gms",
certificates = R.array.com_google_android_gms_fonts_certs
)
val robotoCondensedFontName = GoogleFont("Roboto Condensed")
val robotoCondensedFontFamily = FontFamily(
Font(
googleFont = robotoCondensedFontName,
fontProvider = googleFontsProvider,
weight = FontWeight.Light,
style = FontStyle.Normal
),
Font(
googleFont = robotoCondensedFontName,
fontProvider = googleFontsProvider,
weight = FontWeight.Normal,
style = FontStyle.Normal
),
Font(
googleFont = robotoCondensedFontName,
fontProvider = googleFontsProvider,
weight = FontWeight.Medium,
style = FontStyle.Normal
),
Font(
googleFont = robotoCondensedFontName,
fontProvider = googleFontsProvider,
weight = FontWeight.Bold,
style = FontStyle.Normal
)
)
val eczarFontName = GoogleFont("Eczar")
val eczarFontFamily = FontFamily(
Font(
googleFont = eczarFontName,
fontProvider = googleFontsProvider,
weight = FontWeight.Normal,
style = FontStyle.Normal
)
)
val baseline = Typography()
// Set of Material typography styles to start with // Set of Material typography styles to start with
val Typography = Typography( val Typography = Typography(
bodyLarge = TextStyle( displayLarge = baseline.displayLarge.copy(
fontFamily = FontFamily.Default, fontFamily = robotoCondensedFontFamily,
fontWeight = FontWeight.Normal, fontWeight = FontWeight.Light
fontSize = 16.sp, ),
lineHeight = 24.sp, displayMedium = baseline.displayMedium.copy(
letterSpacing = 0.5.sp fontFamily = robotoCondensedFontFamily,
) fontWeight = FontWeight.Light
/* Other default text styles to override ),
titleLarge = TextStyle( displaySmall = baseline.displaySmall.copy(
fontFamily = FontFamily.Default, fontFamily = robotoCondensedFontFamily,
fontWeight = FontWeight.Normal, fontWeight = FontWeight.Light
fontSize = 22.sp, ),
lineHeight = 28.sp, headlineLarge = baseline.headlineLarge.copy(
letterSpacing = 0.sp fontFamily = eczarFontFamily,
fontWeight = FontWeight.Bold
),
headlineMedium = baseline.headlineMedium.copy(
fontFamily = eczarFontFamily,
fontWeight = FontWeight.Bold
),
headlineSmall = baseline.headlineSmall.copy(
fontFamily = eczarFontFamily,
fontWeight = FontWeight.Bold
),
titleLarge = baseline.titleLarge.copy(
fontFamily = robotoCondensedFontFamily,
fontWeight = FontWeight.Normal,
letterSpacing = 0.8F.sp
),
titleMedium = baseline.titleMedium.copy(
fontFamily = robotoCondensedFontFamily,
fontWeight = FontWeight.Normal
),
titleSmall = baseline.titleSmall.copy(
fontFamily = robotoCondensedFontFamily,
fontWeight = FontWeight.Normal
),
bodyLarge = baseline.bodyLarge.copy(
fontFamily = robotoCondensedFontFamily,
fontWeight = FontWeight.Normal
),
bodyMedium = baseline.bodyMedium.copy(
fontFamily = eczarFontFamily,
fontWeight = FontWeight.Normal
),
bodySmall = baseline.bodySmall.copy(
fontFamily = robotoCondensedFontFamily,
fontWeight = FontWeight.Light
),
labelLarge = baseline.labelLarge.copy(
fontFamily = robotoCondensedFontFamily,
fontWeight = FontWeight.Bold
),
labelMedium = baseline.labelMedium.copy(
fontFamily = robotoCondensedFontFamily,
fontWeight = FontWeight.Normal
),
labelSmall = baseline.labelSmall.copy(
fontFamily = robotoCondensedFontFamily,
fontWeight = FontWeight.Normal
), ),
labelSmall = TextStyle(
fontFamily = FontFamily.Default,
fontWeight = FontWeight.Medium,
fontSize = 11.sp,
lineHeight = 16.sp,
letterSpacing = 0.5.sp
)
*/
) )

View file

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright 2022 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://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.
-->
<resources>
<array name="com_google_android_gms_fonts_certs">
<item>@array/com_google_android_gms_fonts_certs_dev</item>
<item>@array/com_google_android_gms_fonts_certs_prod</item>
</array>
<string-array name="com_google_android_gms_fonts_certs_dev">
<item>
MIIEqDCCA5CgAwIBAgIJANWFuGx90071MA0GCSqGSIb3DQEBBAUAMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTAeFw0wODA0MTUyMzM2NTZaFw0zNTA5MDEyMzM2NTZaMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbTCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBANbOLggKv+IxTdGNs8/TGFy0PTP6DHThvbbR24kT9ixcOd9W+EaBPWW+wPPKQmsHxajtWjmQwWfna8mZuSeJS48LIgAZlKkpFeVyxW0qMBujb8X8ETrWy550NaFtI6t9+u7hZeTfHwqNvacKhp1RbE6dBRGWynwMVX8XW8N1+UjFaq6GCJukT4qmpN2afb8sCjUigq0GuMwYXrFVee74bQgLHWGJwPmvmLHC69EH6kWr22ijx4OKXlSIx2xT1AsSHee70w5iDBiK4aph27yH3TxkXy9V89TDdexAcKk/cVHYNnDBapcavl7y0RiQ4biu8ymM8Ga/nmzhRKya6G0cGw8CAQOjgfwwgfkwHQYDVR0OBBYEFI0cxb6VTEM8YYY6FbBMvAPyT+CyMIHJBgNVHSMEgcEwgb6AFI0cxb6VTEM8YYY6FbBMvAPyT+CyoYGapIGXMIGUMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEQMA4GA1UEChMHQW5kcm9pZDEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDEiMCAGCSqGSIb3DQEJARYTYW5kcm9pZEBhbmRyb2lkLmNvbYIJANWFuGx90071MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEEBQADggEBABnTDPEF+3iSP0wNfdIjIz1AlnrPzgAIHVvXxunW7SBrDhEglQZBbKJEk5kT0mtKoOD1JMrSu1xuTKEBahWRbqHsXclaXjoBADb0kkjVEJu/Lh5hgYZnOjvlba8Ld7HCKePCVePoTJBdI4fvugnL8TsgK05aIskyY0hKI9L8KfqfGTl1lzOv2KoWD0KWwtAWPoGChZxmQ+nBli+gwYMzM1vAkP+aayLe0a1EQimlOalO762r0GXO0ks+UeXde2Z4e+8S/pf7pITEI/tP+MxJTALw9QUWEv9lKTk+jkbqxbsh8nfBUapfKqYn0eidpwq2AzVp3juYl7//fKnaPhJD9gs=
</item>
</string-array>
<string-array name="com_google_android_gms_fonts_certs_prod">
<item>
MIIEQzCCAyugAwIBAgIJAMLgh0ZkSjCNMA0GCSqGSIb3DQEBBAUAMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDAeFw0wODA4MjEyMzEzMzRaFw0zNjAxMDcyMzEzMzRaMHQxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtHb29nbGUgSW5jLjEQMA4GA1UECxMHQW5kcm9pZDEQMA4GA1UEAxMHQW5kcm9pZDCCASAwDQYJKoZIhvcNAQEBBQADggENADCCAQgCggEBAKtWLgDYO6IIrgqWbxJOKdoR8qtW0I9Y4sypEwPpt1TTcvZApxsdyxMJZ2JORland2qSGT2y5b+3JKkedxiLDmpHpDsz2WCbdxgxRczfey5YZnTJ4VZbH0xqWVW/8lGmPav5xVwnIiJS6HXk+BVKZF+JcWjAsb/GEuq/eFdpuzSqeYTcfi6idkyugwfYwXFU1+5fZKUaRKYCwkkFQVfcAs1fXA5V+++FGfvjJ/CxURaSxaBvGdGDhfXE28LWuT9ozCl5xw4Yq5OGazvV24mZVSoOO0yZ31j7kYvtwYK6NeADwbSxDdJEqO4k//0zOHKrUiGYXtqw/A0LFFtqoZKFjnkCAQOjgdkwgdYwHQYDVR0OBBYEFMd9jMIhF1Ylmn/Tgt9r45jk14alMIGmBgNVHSMEgZ4wgZuAFMd9jMIhF1Ylmn/Tgt9r45jk14aloXikdjB0MQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLR29vZ2xlIEluYy4xEDAOBgNVBAsTB0FuZHJvaWQxEDAOBgNVBAMTB0FuZHJvaWSCCQDC4IdGZEowjTAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBAUAA4IBAQBt0lLO74UwLDYKqs6Tm8/yzKkEu116FmH4rkaymUIE0P9KaMftGlMexFlaYjzmB2OxZyl6euNXEsQH8gjwyxCUKRJNexBiGcCEyj6z+a1fuHHvkiaai+KL8W1EyNmgjmyy8AW7P+LLlkR+ho5zEHatRbM/YAnqGcFh5iZBqpknHf1SKMXFh4dd239FJ1jWYfbMDMy3NS5CTMQ2XFI1MvcyUTdZPErjQfTbQe3aDQsQcafEQPD+nqActifKZ0Np0IS9L9kR/wbNvyz6ENwPiTrjV2KRkEjH78ZMcUQXg0L3BYHJ3lc69Vs5Ddf9uUGGMYldX3WfMBEmh/9iFBDAaTCK
</item>
</string-array>
</resources>

View file

@ -24,6 +24,7 @@ protoLite = "3.21.11"
okhttp = "4.10.0" okhttp = "4.10.0"
retrofit = "2.9.0" retrofit = "2.9.0"
hiltNavigationCompose = "1.2.0" hiltNavigationCompose = "1.2.0"
fonts = "1.7.5"
[libraries] [libraries]
androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" } androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activityCompose" }
@ -44,6 +45,7 @@ androidx-ui-test-junit4 = { group = "androidx.compose.ui", name = "ui-test-junit
androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } androidx-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" }
androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" } androidx-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling" }
androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" } androidx-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview" }
google-fonts = { group = "androidx.compose.ui", name = "ui-text-google-fonts", version.ref = "fonts" }
junit = { group = "junit", name = "junit", version.ref = "junit" } junit = { group = "junit", name = "junit", version.ref = "junit" }
kotlinx-serialization = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" } kotlinx-serialization = { group = "org.jetbrains.kotlinx", name = "kotlinx-serialization-json", version.ref = "kotlinxSerializationJson" }
lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycleRuntimeCompose" } lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "lifecycleRuntimeCompose" }