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")