From f2e7b1377544f62349d48b94c1e087364e5dae97 Mon Sep 17 00:00:00 2001 From: Severiano Jaramillo Date: Sun, 28 Apr 2024 19:22:04 -0700 Subject: [PATCH] Add Android app project --- app/build.gradle.kts | 68 +++++++++++++ app/proguard-rules.pro | 21 ++++ app/src/main/AndroidManifest.xml | 24 +++++ .../main/java/net/agorise/kee/MainActivity.kt | 20 ++++ .../kee/ui/component/nodestatus/NodeStatus.kt | 29 ++++++ .../kee/ui/component/topappbar/TopAppBar.kt | 38 ++++++++ .../agorise/kee/ui/screen/home/HomeScreen.kt | 63 ++++++++++++ .../importaccount/ImportAccountScreen.kt | 96 +++++++++++++++++++ .../importaccount/ImportAccountScreenModel.kt | 39 ++++++++ .../java/net/agorise/kee/ui/theme/Color.kt | 68 +++++++++++++ .../java/net/agorise/kee/ui/theme/Theme.kt | 89 +++++++++++++++++ .../drawable-v24/ic_launcher_foreground.xml | 17 ++++ app/src/main/res/drawable/ic_kee_logo.xml | 15 +++ .../res/mipmap-anydpi-v26/ic_launcher.xml | 6 ++ .../mipmap-anydpi-v26/ic_launcher_round.xml | 6 ++ app/src/main/res/values/colors.xml | 5 + app/src/main/res/values/strings.xml | 3 + build.gradle.kts | 1 + gradle/libs.versions.toml | 10 ++ settings.gradle.kts | 1 + 20 files changed, 619 insertions(+) create mode 100644 app/build.gradle.kts create mode 100644 app/proguard-rules.pro create mode 100644 app/src/main/AndroidManifest.xml create mode 100644 app/src/main/java/net/agorise/kee/MainActivity.kt create mode 100644 app/src/main/java/net/agorise/kee/ui/component/nodestatus/NodeStatus.kt create mode 100644 app/src/main/java/net/agorise/kee/ui/component/topappbar/TopAppBar.kt create mode 100644 app/src/main/java/net/agorise/kee/ui/screen/home/HomeScreen.kt create mode 100644 app/src/main/java/net/agorise/kee/ui/screen/importaccount/ImportAccountScreen.kt create mode 100644 app/src/main/java/net/agorise/kee/ui/screen/importaccount/ImportAccountScreenModel.kt create mode 100644 app/src/main/java/net/agorise/kee/ui/theme/Color.kt create mode 100644 app/src/main/java/net/agorise/kee/ui/theme/Theme.kt create mode 100644 app/src/main/res/drawable-v24/ic_launcher_foreground.xml create mode 100644 app/src/main/res/drawable/ic_kee_logo.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml create mode 100644 app/src/main/res/values/colors.xml create mode 100644 app/src/main/res/values/strings.xml diff --git a/app/build.gradle.kts b/app/build.gradle.kts new file mode 100644 index 0000000..a495fed --- /dev/null +++ b/app/build.gradle.kts @@ -0,0 +1,68 @@ +plugins { + alias(libs.plugins.androidApplication) + alias(libs.plugins.jetbrainsKotlinAndroid) +} + +android { + namespace = "net.agorise.kee" + compileSdk = libs.versions.android.compileSdk.get().toInt() + + defaultConfig { + applicationId = "net.agorise.kee" + minSdk = libs.versions.android.minSdk.get().toInt() + targetSdk = libs.versions.android.targetSdk.get().toInt() + versionCode = 1 + versionName = "1.0" + + testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" + vectorDrawables { + useSupportLibrary = true + } + } + + buildTypes { + release { + isMinifyEnabled = false + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro" + ) + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_11 + targetCompatibility = JavaVersion.VERSION_11 + } + kotlinOptions { + jvmTarget = "11" + } + buildFeatures { + compose = true + } + composeOptions { + kotlinCompilerExtensionVersion = libs.versions.composeCompiler.get() + } + packaging { + resources { + excludes += "/META-INF/{AL2.0,LGPL2.1}" + } + } +} + +dependencies { + implementation(projects.shared.preferences) + implementation(projects.shared.stargate) + + implementation(platform(libs.compose.bom)) + implementation(libs.androidx.activity.compose) + implementation(libs.androidx.core.ktx) + implementation(libs.compose.ui) + implementation(libs.compose.ui.graphics) + implementation(libs.compose.ui.tooling.preview) + implementation(libs.compose.material3) + implementation(libs.voyager.navigator) + implementation(libs.voyager.screenmodel) + + debugImplementation(libs.compose.ui.tooling) + debugImplementation(libs.compose.ui.test.manifest) +} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro new file mode 100644 index 0000000..481bb43 --- /dev/null +++ b/app/proguard-rules.pro @@ -0,0 +1,21 @@ +# Add project specific ProGuard rules here. +# You can control the set of applied configuration files using the +# proguardFiles setting in build.gradle. +# +# For more details, see +# http://developer.android.com/guide/developing/tools/proguard.html + +# If your project uses WebView with JS, uncomment the following +# and specify the fully qualified class name to the JavaScript interface +# class: +#-keepclassmembers class fqcn.of.javascript.interface.for.webview { +# public *; +#} + +# Uncomment this to preserve the line number information for +# debugging stack traces. +#-keepattributes SourceFile,LineNumberTable + +# If you keep the line number information, uncomment this to +# hide the original source file name. +#-renamesourcefileattribute SourceFile \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml new file mode 100644 index 0000000..91a1667 --- /dev/null +++ b/app/src/main/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + diff --git a/app/src/main/java/net/agorise/kee/MainActivity.kt b/app/src/main/java/net/agorise/kee/MainActivity.kt new file mode 100644 index 0000000..067bc25 --- /dev/null +++ b/app/src/main/java/net/agorise/kee/MainActivity.kt @@ -0,0 +1,20 @@ +package net.agorise.kee + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import cafe.adriel.voyager.navigator.Navigator +import net.agorise.kee.ui.screen.home.HomeScreen + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + enableEdgeToEdge() + + setContent { + Navigator(HomeScreen()) + } + } +} diff --git a/app/src/main/java/net/agorise/kee/ui/component/nodestatus/NodeStatus.kt b/app/src/main/java/net/agorise/kee/ui/component/nodestatus/NodeStatus.kt new file mode 100644 index 0000000..0305c17 --- /dev/null +++ b/app/src/main/java/net/agorise/kee/ui/component/nodestatus/NodeStatus.kt @@ -0,0 +1,29 @@ +package net.agorise.kee.ui.component.nodestatus + +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import net.agorise.kee.ui.theme.KeeTheme + +@Composable +fun NodeStatus(blockCount: Int? = null) { + val text = if (blockCount == null) { + "Not connected" + } else { + "Block #: $blockCount" + } + Text(text, color = MaterialTheme.colorScheme.onBackground) +} + +@Preview +@Composable +private fun NodeStatusLightPreview() = KeeTheme(useDarkTheme = false) { + NodeStatus() +} + +@Preview +@Composable +private fun NodeStatusDarkPreview() = KeeTheme(useDarkTheme = true) { + NodeStatus() +} diff --git a/app/src/main/java/net/agorise/kee/ui/component/topappbar/TopAppBar.kt b/app/src/main/java/net/agorise/kee/ui/component/topappbar/TopAppBar.kt new file mode 100644 index 0000000..fd01ede --- /dev/null +++ b/app/src/main/java/net/agorise/kee/ui/component/topappbar/TopAppBar.kt @@ -0,0 +1,38 @@ +package net.agorise.kee.ui.component.topappbar + +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.material3.TopAppBar +import androidx.compose.material3.TopAppBarDefaults.topAppBarColors +import androidx.compose.runtime.Composable +import androidx.compose.ui.tooling.preview.Preview +import net.agorise.kee.ui.theme.KeeTheme + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun KeeTopAppBar( + title: String, +) { + TopAppBar( + colors = topAppBarColors( + containerColor = MaterialTheme.colorScheme.primaryContainer, + titleContentColor = MaterialTheme.colorScheme.primary + ), + title = { + Text(title) + } + ) +} + +@Preview +@Composable +private fun TopAppBarLightPreview() = KeeTheme(useDarkTheme = false) { + KeeTopAppBar("Kee Wallet") +} + +@Preview +@Composable +private fun TopAppBarDarkPreview() = KeeTheme(useDarkTheme = true) { + KeeTopAppBar("Kee Wallet") +} diff --git a/app/src/main/java/net/agorise/kee/ui/screen/home/HomeScreen.kt b/app/src/main/java/net/agorise/kee/ui/screen/home/HomeScreen.kt new file mode 100644 index 0000000..645ce3a --- /dev/null +++ b/app/src/main/java/net/agorise/kee/ui/screen/home/HomeScreen.kt @@ -0,0 +1,63 @@ +package net.agorise.kee.ui.screen.home + +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.* +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import cafe.adriel.voyager.core.screen.Screen +import cafe.adriel.voyager.navigator.LocalNavigator +import net.agorise.kee.ui.component.topappbar.KeeTopAppBar +import net.agorise.kee.ui.screen.importaccount.ImportAccountScreen +import net.agorise.kee.ui.theme.KeeTheme +import net.agorise.shared.preferences.KeePreferences + +class HomeScreen : Screen { + + @Composable + override fun Content() = KeeTheme { + HomeScreenContent() + } +} + +@Composable +private fun HomeScreenContent() { + val navigator = LocalNavigator.current + + // Navigate to Import Account screen immediately if there is no active account + if (KeePreferences.isAccountActive().not()) { + navigator?.replace(ImportAccountScreen()) + } + + Scaffold( + topBar = { KeeTopAppBar("Kee Wallet") } + ) { innerPadding -> + Column( + modifier = Modifier.padding(innerPadding).padding(16.dp), + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + Text("Welcome to Kee") + + Button( + onClick = { navigator?.replace(ImportAccountScreen()) } + ) { + Text("Import Account") + } + } + } +} + +@Preview +@Composable +private fun HomeScreenContentLightPreview() = KeeTheme(useDarkTheme = false) { + HomeScreenContent() +} + +@Preview +@Composable +private fun HomeScreenContentDarkPreview() = KeeTheme(useDarkTheme = true) { + HomeScreenContent() +} diff --git a/app/src/main/java/net/agorise/kee/ui/screen/importaccount/ImportAccountScreen.kt b/app/src/main/java/net/agorise/kee/ui/screen/importaccount/ImportAccountScreen.kt new file mode 100644 index 0000000..e60a2ae --- /dev/null +++ b/app/src/main/java/net/agorise/kee/ui/screen/importaccount/ImportAccountScreen.kt @@ -0,0 +1,96 @@ +package net.agorise.kee.ui.screen.importaccount + +import androidx.compose.foundation.layout.* +import androidx.compose.material3.* +import androidx.compose.runtime.* +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import cafe.adriel.voyager.core.model.rememberScreenModel +import cafe.adriel.voyager.core.screen.Screen +import cafe.adriel.voyager.navigator.LocalNavigator +import net.agorise.kee.R +import net.agorise.kee.ui.component.nodestatus.NodeStatus +import net.agorise.kee.ui.component.topappbar.KeeTopAppBar +import net.agorise.kee.ui.screen.home.HomeScreen +import net.agorise.kee.ui.theme.KeeTheme + +private const val RECOVERY_WORDS_COUNT = 25 + +class ImportAccountScreen : Screen { + @Composable + override fun Content() = KeeTheme { + val screenModel = rememberScreenModel { ImportAccountScreenModel() } + + val state by screenModel.state.collectAsState() + + ImportAccountScreenContent(state) + } +} + +@Composable +private fun ImportAccountScreenContent(state: ImportAccountScreenModel.State) { + val navigator = LocalNavigator.current + + Scaffold( + topBar = { KeeTopAppBar("Import Account") } + ) { innerPadding -> + Column( + modifier = Modifier + .padding(innerPadding) + .consumeWindowInsets(innerPadding) + .padding(top = 16.dp, start = 16.dp, end = 16.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.spacedBy(16.dp) + ) { + var recoveryText by remember { mutableStateOf("") } + val recoveryWords = recoveryText.split(" ").filter { it.isNotBlank() } + + Icon( + painter = painterResource(R.drawable.ic_kee_logo), + contentDescription = null, + tint = MaterialTheme.colorScheme.primary, + modifier = Modifier.padding(top = 16.dp).size(80.dp) + ) + Text("Enter your recovery words below") + OutlinedTextField( + value = recoveryText, + onValueChange = { recoveryText = it }, + modifier = Modifier.fillMaxWidth(), + minLines = 5, + maxLines = 5, + supportingText = { + Text( + text = "${recoveryWords.count()}/${RECOVERY_WORDS_COUNT} words", + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.End, + ) + } + ) + Button( + enabled = recoveryWords.size == RECOVERY_WORDS_COUNT, + modifier = Modifier.padding(top = 16.dp), + onClick = { navigator?.replace(HomeScreen()) } + ) { + Text("Import Account") + } + Spacer(modifier = Modifier.weight(1f)) + NodeStatus(state.blockCount) + } + } +} + +@Preview +@Composable +private fun ImportAccountScreenContentLightPreview() = KeeTheme(useDarkTheme = false) { + ImportAccountScreenContent(ImportAccountScreenModel.State()) +} + +@Preview +@Composable +private fun ImportAccountScreenContentDarkPreview() = KeeTheme(useDarkTheme = true) { + ImportAccountScreenContent(ImportAccountScreenModel.State(blockCount = 265482)) +} diff --git a/app/src/main/java/net/agorise/kee/ui/screen/importaccount/ImportAccountScreenModel.kt b/app/src/main/java/net/agorise/kee/ui/screen/importaccount/ImportAccountScreenModel.kt new file mode 100644 index 0000000..24955b2 --- /dev/null +++ b/app/src/main/java/net/agorise/kee/ui/screen/importaccount/ImportAccountScreenModel.kt @@ -0,0 +1,39 @@ +package net.agorise.kee.ui.screen.importaccount + +import cafe.adriel.voyager.core.model.StateScreenModel +import cafe.adriel.voyager.core.model.screenModelScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.IO +import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.onEach +import kotlinx.coroutines.flow.receiveAsFlow +import kotlinx.coroutines.launch +import net.agorise.shared.stargate.StargateBridge + +class ImportAccountScreenModel : StateScreenModel(State()) { + + data class State( + val blockCount: Int? = null, + ) + + private val stargateBridge = StargateBridge() + + init { + screenModelScope.launch(Dispatchers.IO) { + stargateBridge.start() + } + + listenForBlockCount() + } + + private fun listenForBlockCount() { + stargateBridge.blockCountChannel.receiveAsFlow().onEach { blockCount -> + mutableState.value = state.value.copy(blockCount = blockCount) + }.launchIn(screenModelScope) + } + + override fun onDispose() { + super.onDispose() + stargateBridge.stop() + } +} diff --git a/app/src/main/java/net/agorise/kee/ui/theme/Color.kt b/app/src/main/java/net/agorise/kee/ui/theme/Color.kt new file mode 100644 index 0000000..fd450e3 --- /dev/null +++ b/app/src/main/java/net/agorise/kee/ui/theme/Color.kt @@ -0,0 +1,68 @@ +package net.agorise.kee.ui.theme + +import androidx.compose.ui.graphics.Color + +// Color used to generate the theme using the Material Theme Builder tool +// val seed = Color(0xFF7F6289) + +val md_theme_light_primary = Color(0xFF7E4895) +val md_theme_light_onPrimary = Color(0xFFFFFFFF) +val md_theme_light_primaryContainer = Color(0xFFF8D8FF) +val md_theme_light_onPrimaryContainer = Color(0xFF320047) +val md_theme_light_secondary = Color(0xFF69596D) +val md_theme_light_onSecondary = Color(0xFFFFFFFF) +val md_theme_light_secondaryContainer = Color(0xFFF1DCF4) +val md_theme_light_onSecondaryContainer = Color(0xFF231728) +val md_theme_light_tertiary = Color(0xFF815250) +val md_theme_light_onTertiary = Color(0xFFFFFFFF) +val md_theme_light_tertiaryContainer = Color(0xFFFFDAD8) +val md_theme_light_onTertiaryContainer = Color(0xFF331111) +val md_theme_light_error = Color(0xFFBA1A1A) +val md_theme_light_errorContainer = Color(0xFFFFDAD6) +val md_theme_light_onError = Color(0xFFFFFFFF) +val md_theme_light_onErrorContainer = Color(0xFF410002) +val md_theme_light_background = Color(0xFFFFFBFF) +val md_theme_light_onBackground = Color(0xFF1E1B1E) +val md_theme_light_surface = Color(0xFFFFFBFF) +val md_theme_light_onSurface = Color(0xFF1E1B1E) +val md_theme_light_surfaceVariant = Color(0xFFEBDFEA) +val md_theme_light_onSurfaceVariant = Color(0xFF4C444D) +val md_theme_light_outline = Color(0xFF7D747D) +val md_theme_light_inverseOnSurface = Color(0xFFF6EFF3) +val md_theme_light_inverseSurface = Color(0xFF332F33) +val md_theme_light_inversePrimary = Color(0xFFEBB2FF) +val md_theme_light_shadow = Color(0xFF000000) +val md_theme_light_surfaceTint = Color(0xFF7E4895) +val md_theme_light_outlineVariant = Color(0xFFCEC3CD) +val md_theme_light_scrim = Color(0xFF000000) + +val md_theme_dark_primary = Color(0xFFEBB2FF) +val md_theme_dark_onPrimary = Color(0xFF4B1763) +val md_theme_dark_primaryContainer = Color(0xFF64307B) +val md_theme_dark_onPrimaryContainer = Color(0xFFF8D8FF) +val md_theme_dark_secondary = Color(0xFFD4C0D7) +val md_theme_dark_onSecondary = Color(0xFF392C3D) +val md_theme_dark_secondaryContainer = Color(0xFF504255) +val md_theme_dark_onSecondaryContainer = Color(0xFFF1DCF4) +val md_theme_dark_tertiary = Color(0xFFF5B7B5) +val md_theme_dark_onTertiary = Color(0xFF4C2524) +val md_theme_dark_tertiaryContainer = Color(0xFF663B3A) +val md_theme_dark_onTertiaryContainer = Color(0xFFFFDAD8) +val md_theme_dark_error = Color(0xFFFFB4AB) +val md_theme_dark_errorContainer = Color(0xFF93000A) +val md_theme_dark_onError = Color(0xFF690005) +val md_theme_dark_onErrorContainer = Color(0xFFFFDAD6) +val md_theme_dark_background = Color(0xFF1E1B1E) +val md_theme_dark_onBackground = Color(0xFFE8E0E5) +val md_theme_dark_surface = Color(0xFF1E1B1E) +val md_theme_dark_onSurface = Color(0xFFE8E0E5) +val md_theme_dark_surfaceVariant = Color(0xFF4C444D) +val md_theme_dark_onSurfaceVariant = Color(0xFFCEC3CD) +val md_theme_dark_outline = Color(0xFF978E97) +val md_theme_dark_inverseOnSurface = Color(0xFF1E1B1E) +val md_theme_dark_inverseSurface = Color(0xFFE8E0E5) +val md_theme_dark_inversePrimary = Color(0xFF7E4895) +val md_theme_dark_shadow = Color(0xFF000000) +val md_theme_dark_surfaceTint = Color(0xFFEBB2FF) +val md_theme_dark_outlineVariant = Color(0xFF4C444D) +val md_theme_dark_scrim = Color(0xFF000000) diff --git a/app/src/main/java/net/agorise/kee/ui/theme/Theme.kt b/app/src/main/java/net/agorise/kee/ui/theme/Theme.kt new file mode 100644 index 0000000..15c19e1 --- /dev/null +++ b/app/src/main/java/net/agorise/kee/ui/theme/Theme.kt @@ -0,0 +1,89 @@ +package net.agorise.kee.ui.theme + +import androidx.compose.foundation.isSystemInDarkTheme +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.darkColorScheme +import androidx.compose.material3.lightColorScheme +import androidx.compose.runtime.Composable + +private val LightColors = lightColorScheme( + primary = md_theme_light_primary, + onPrimary = md_theme_light_onPrimary, + primaryContainer = md_theme_light_primaryContainer, + onPrimaryContainer = md_theme_light_onPrimaryContainer, + secondary = md_theme_light_secondary, + onSecondary = md_theme_light_onSecondary, + secondaryContainer = md_theme_light_secondaryContainer, + onSecondaryContainer = md_theme_light_onSecondaryContainer, + tertiary = md_theme_light_tertiary, + onTertiary = md_theme_light_onTertiary, + tertiaryContainer = md_theme_light_tertiaryContainer, + onTertiaryContainer = md_theme_light_onTertiaryContainer, + error = md_theme_light_error, + errorContainer = md_theme_light_errorContainer, + onError = md_theme_light_onError, + onErrorContainer = md_theme_light_onErrorContainer, + background = md_theme_light_background, + onBackground = md_theme_light_onBackground, + surface = md_theme_light_surface, + onSurface = md_theme_light_onSurface, + surfaceVariant = md_theme_light_surfaceVariant, + onSurfaceVariant = md_theme_light_onSurfaceVariant, + outline = md_theme_light_outline, + inverseOnSurface = md_theme_light_inverseOnSurface, + inverseSurface = md_theme_light_inverseSurface, + inversePrimary = md_theme_light_inversePrimary, + surfaceTint = md_theme_light_surfaceTint, + outlineVariant = md_theme_light_outlineVariant, + scrim = md_theme_light_scrim, +) + + +private val DarkColors = darkColorScheme( + primary = md_theme_dark_primary, + onPrimary = md_theme_dark_onPrimary, + primaryContainer = md_theme_dark_primaryContainer, + onPrimaryContainer = md_theme_dark_onPrimaryContainer, + secondary = md_theme_dark_secondary, + onSecondary = md_theme_dark_onSecondary, + secondaryContainer = md_theme_dark_secondaryContainer, + onSecondaryContainer = md_theme_dark_onSecondaryContainer, + tertiary = md_theme_dark_tertiary, + onTertiary = md_theme_dark_onTertiary, + tertiaryContainer = md_theme_dark_tertiaryContainer, + onTertiaryContainer = md_theme_dark_onTertiaryContainer, + error = md_theme_dark_error, + errorContainer = md_theme_dark_errorContainer, + onError = md_theme_dark_onError, + onErrorContainer = md_theme_dark_onErrorContainer, + background = md_theme_dark_background, + onBackground = md_theme_dark_onBackground, + surface = md_theme_dark_surface, + onSurface = md_theme_dark_onSurface, + surfaceVariant = md_theme_dark_surfaceVariant, + onSurfaceVariant = md_theme_dark_onSurfaceVariant, + outline = md_theme_dark_outline, + inverseOnSurface = md_theme_dark_inverseOnSurface, + inverseSurface = md_theme_dark_inverseSurface, + inversePrimary = md_theme_dark_inversePrimary, + surfaceTint = md_theme_dark_surfaceTint, + outlineVariant = md_theme_dark_outlineVariant, + scrim = md_theme_dark_scrim, +) + +@Composable +fun KeeTheme( + useDarkTheme: Boolean = isSystemInDarkTheme(), + content: @Composable () -> Unit +) { + val colors = if (!useDarkTheme) { + LightColors + } else { + DarkColors + } + + MaterialTheme( + colorScheme = colors, + content = content + ) +} diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml new file mode 100644 index 0000000..8bc72bb --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml @@ -0,0 +1,17 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_kee_logo.xml b/app/src/main/res/drawable/ic_kee_logo.xml new file mode 100644 index 0000000..7cb34d8 --- /dev/null +++ b/app/src/main/res/drawable/ic_kee_logo.xml @@ -0,0 +1,15 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..ef49c99 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml new file mode 100644 index 0000000..ef49c99 --- /dev/null +++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..bdba231 --- /dev/null +++ b/app/src/main/res/values/colors.xml @@ -0,0 +1,5 @@ + + + #7E4895 + #F8D8FF + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml new file mode 100644 index 0000000..d2a597a --- /dev/null +++ b/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + Kee + diff --git a/build.gradle.kts b/build.gradle.kts index 52cf9fa..3e249e6 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -5,4 +5,5 @@ plugins { alias(libs.plugins.androidLibrary) apply false alias(libs.plugins.jetbrainsCompose) apply false alias(libs.plugins.kotlinMultiplatform) apply false + alias(libs.plugins.jetbrainsKotlinAndroid) apply false } \ No newline at end of file diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index ec1688e..2f03127 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -6,15 +6,24 @@ android-targetSdk = "34" androidx-activityCompose = "1.8.2" compose = "1.6.4" compose-plugin = "1.6.1" +composeCompiler = "1.5.12" +composeBom = "2024.04.01" coroutines = "1.8.0" cryptography = "0.3.0" kotlin = "1.9.23" ktor = "2.3.9" multiplatform-settings = "1.1.1" voyager = "1.0.0" +coreKtx = "1.13.0" [libraries] androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "androidx-activityCompose" } +androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" } +compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "composeBom" } +compose-material3 = { group = "androidx.compose.material3", name = "material3" } +compose-ui = { group = "androidx.compose.ui", name = "ui" } +compose-ui-graphics = { group = "androidx.compose.ui", name = "ui-graphics" } +compose-ui-test-manifest = { group = "androidx.compose.ui", name = "ui-test-manifest" } compose-ui-tooling = { group = "androidx.compose.ui", name = "ui-tooling", version.ref = "compose" } compose-ui-tooling-preview = { group = "androidx.compose.ui", name = "ui-tooling-preview", version.ref = "compose" } coroutines-core = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-core", version.ref = "coroutines" } @@ -33,3 +42,4 @@ androidApplication = { id = "com.android.application", version.ref = "agp" } androidLibrary = { id = "com.android.library", version.ref = "agp" } jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" } kotlinMultiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" } +jetbrainsKotlinAndroid = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } diff --git a/settings.gradle.kts b/settings.gradle.kts index 56aca6f..39db460 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -22,3 +22,4 @@ include(":composeApp") include(":shared:crypto") include(":shared:preferences") include(":shared:stargate") +include(":app")