From a4445f673af6c435788a8e4b03c3b869673b8f2e Mon Sep 17 00:00:00 2001 From: Thomas Butler <58192340+trbutler4@users.noreply.github.com> Date: Fri, 18 Oct 2024 01:03:54 -0500 Subject: [PATCH] Wallet app cleanup (#98) * refactor file structure, begin refactoring app flow * add .idea to gitignore * adding navigation * make create account and import account composable screens instead of activities * refactor everything to composable routes * more routes * correct routing --- .gitignore | 2 + .../.idea/deploymentTargetSelector.xml | 3 + wallet_app/android/app/build.gradle.kts | 18 + .../android/app/src/main/AndroidManifest.xml | 22 +- .../walletapp/AccountBalanceActivity.kt | 141 ------ .../com/example/walletapp/AccountPassword.kt | 170 -------- .../com/example/walletapp/AddTokenActivity.kt | 162 ------- .../com/example/walletapp/MainActivity.kt | 172 -------- .../walletapp/RecoveryPhraseActivity.kt | 304 ------------- .../com/example/walletapp/model/Account.kt | 5 + .../java/com/example/walletapp/model/Token.kt | 6 + .../java/com/example/walletapp/model/User.kt | 13 + .../java/com/example/walletapp/theme/Color.kt | 12 - .../com/example/walletapp/ui/MainActivity.kt | 21 + .../com/example/walletapp/ui/WalletApp.kt | 110 +++++ .../walletapp/ui/account/AddTokenScreen.kt | 144 ++++++ .../{ => ui/account}/CoinViewModel.kt | 2 +- .../account/WalletScreen.kt} | 412 +++++++++--------- .../walletapp/ui/components/StarknetLogo.kt | 27 ++ .../ui/components/TransparentButton.kt | 52 +++ .../onboarding/CreateAccountScreen.kt} | 205 ++++----- .../onboarding/CreatePinScreen.kt} | 193 ++++---- .../FinalizeAccountCreationScreen.kt} | 114 ++--- .../onboarding/ImportAccountScreen.kt} | 266 +++++------ .../ui/onboarding/OnboardingScreen.kt | 92 ++++ .../com/example/walletapp/ui/theme/Color.kt | 19 + .../example/walletapp/{ => ui}/theme/Theme.kt | 26 +- .../example/walletapp/{ => ui}/theme/Type.kt | 0 .../transfer/ReceiveScreen.kt} | 42 +- .../transfer/SendScreen.kt} | 31 +- .../walletapp/{ => utils}/StarknetClient.kt | 9 +- .../example/walletapp/utils/WalletAppUtils.kt | 21 + .../app/src/main/res/layout/activity_main.xml | 19 - .../app/src/main/res/values/strings.xml | 4 +- wallet_app/android/gradle/libs.versions.toml | 12 + 35 files changed, 1124 insertions(+), 1727 deletions(-) delete mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/AccountBalanceActivity.kt delete mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/AccountPassword.kt delete mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/AddTokenActivity.kt delete mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/MainActivity.kt delete mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/RecoveryPhraseActivity.kt create mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/model/Account.kt create mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/model/Token.kt create mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/model/User.kt delete mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/theme/Color.kt create mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/ui/MainActivity.kt create mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/ui/WalletApp.kt create mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/ui/account/AddTokenScreen.kt rename wallet_app/android/app/src/main/java/com/example/walletapp/{ => ui/account}/CoinViewModel.kt (97%) rename wallet_app/android/app/src/main/java/com/example/walletapp/{WalletActivity.kt => ui/account/WalletScreen.kt} (51%) create mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/ui/components/StarknetLogo.kt create mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/ui/components/TransparentButton.kt rename wallet_app/android/app/src/main/java/com/example/walletapp/{CreateAccountActivity.kt => ui/onboarding/CreateAccountScreen.kt} (67%) rename wallet_app/android/app/src/main/java/com/example/walletapp/{CreatePinActivity.kt => ui/onboarding/CreatePinScreen.kt} (55%) rename wallet_app/android/app/src/main/java/com/example/walletapp/{AccountInfoActivity.kt => ui/onboarding/FinalizeAccountCreationScreen.kt} (77%) rename wallet_app/android/app/src/main/java/com/example/walletapp/{ImportExistingKeyActivity.kt => ui/onboarding/ImportAccountScreen.kt} (54%) create mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/OnboardingScreen.kt create mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/ui/theme/Color.kt rename wallet_app/android/app/src/main/java/com/example/walletapp/{ => ui}/theme/Theme.kt (68%) rename wallet_app/android/app/src/main/java/com/example/walletapp/{ => ui}/theme/Type.kt (100%) rename wallet_app/android/app/src/main/java/com/example/walletapp/{ReceiverActivity.kt => ui/transfer/ReceiveScreen.kt} (68%) rename wallet_app/android/app/src/main/java/com/example/walletapp/{SendActivity.kt => ui/transfer/SendScreen.kt} (84%) rename wallet_app/android/app/src/main/java/com/example/walletapp/{ => utils}/StarknetClient.kt (89%) create mode 100644 wallet_app/android/app/src/main/java/com/example/walletapp/utils/WalletAppUtils.kt delete mode 100644 wallet_app/android/app/src/main/res/layout/activity_main.xml diff --git a/.gitignore b/.gitignore index 02c67342..f6a762cd 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,5 @@ lightclientservice/local.properties lightclientservice/.idea **/*.so + +**/.idea/* diff --git a/wallet_app/android/.idea/deploymentTargetSelector.xml b/wallet_app/android/.idea/deploymentTargetSelector.xml index 8fa3d395..3d841a5a 100644 --- a/wallet_app/android/.idea/deploymentTargetSelector.xml +++ b/wallet_app/android/.idea/deploymentTargetSelector.xml @@ -13,6 +13,9 @@ + + \ No newline at end of file diff --git a/wallet_app/android/app/build.gradle.kts b/wallet_app/android/app/build.gradle.kts index c5a38050..8072c8cc 100644 --- a/wallet_app/android/app/build.gradle.kts +++ b/wallet_app/android/app/build.gradle.kts @@ -1,3 +1,4 @@ +import kotlinx.serialization.serializer import java.util.Properties plugins { @@ -5,12 +6,18 @@ plugins { alias(libs.plugins.jetbrains.kotlin.android) id("kotlin-kapt") id("org.jmailen.kotlinter") + kotlin("plugin.serialization") version "2.0.21" } android { namespace = "com.example.walletapp" compileSdk = 34 + dataBinding { + enable = true + } + + buildFeatures { compose = true buildConfig = true @@ -63,10 +70,21 @@ android { } dependencies { + // Navigation stuff + implementation(libs.androidx.navigation.compose.v283) + implementation(libs.androidx.navigation.compose.v283) + implementation(libs.androidx.navigation.fragment) + implementation(libs.androidx.navigation.ui) + implementation(libs.androidx.navigation.dynamic.features.fragment) + androidTestImplementation(libs.androidx.navigation.testing) + implementation("com.swmansion.starknet:starknet:0.12.1@aar"){ isTransitive = true } + // for data binding + implementation(libs.common) + implementation(libs.androidx.core.ktx) implementation(libs.androidx.appcompat) implementation(libs.material) diff --git a/wallet_app/android/app/src/main/AndroidManifest.xml b/wallet_app/android/app/src/main/AndroidManifest.xml index 24776d9a..f3e65a07 100644 --- a/wallet_app/android/app/src/main/AndroidManifest.xml +++ b/wallet_app/android/app/src/main/AndroidManifest.xml @@ -16,7 +16,8 @@ android:networkSecurityConfig="@xml/network_security_config" tools:targetApi="31"> @@ -25,14 +26,14 @@ - @@ -48,30 +49,21 @@ android:exported="true" android:theme="@style/Theme.Walletapp"/> - - - - - - - diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/AccountBalanceActivity.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/AccountBalanceActivity.kt deleted file mode 100644 index e45adf2c..00000000 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/AccountBalanceActivity.kt +++ /dev/null @@ -1,141 +0,0 @@ -package com.example.walletapp - -import android.app.Activity -import android.os.Bundle -import android.util.Log -import android.widget.Toast -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.width -import androidx.compose.material.Button -import androidx.compose.material.Surface -import androidx.compose.material.Text -import androidx.compose.material.TextField -import androidx.compose.material.TextFieldDefaults -import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Color.Companion.Transparent -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.core.graphics.toColorInt -import androidx.core.view.WindowCompat -import com.example.walletapp.BuildConfig -import com.example.walletapp.ui.theme.WalletappTheme -import com.swmansion.starknet.data.types.Felt -import com.swmansion.starknet.provider.exceptions.RpcRequestFailedException -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - - -class AccountBalanceActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - - WindowCompat.setDecorFitsSystemWindows(window, true) - setContent { - WalletappTheme { - Surface(modifier = Modifier.fillMaxSize()) { - AccountBalanceScreenView() - } - } - } - } - - @Composable - fun AccountBalanceScreenView(){ - val context = (LocalContext.current as Activity) - - var accountAddress by remember { mutableStateOf("0x02dc260794e4c2eeae87b1403a88385a72c18a5844d220b88117b2965a8cf3a5") } - - var balance by remember { mutableStateOf("")} - - val scope = CoroutineScope(Dispatchers.IO) - - val starknetClient = StarknetClient(BuildConfig.RPC_URL) - - - Column(modifier = Modifier - .fillMaxSize() - .background(Color("#0C0C4F".toColorInt())) - .padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center) - { - TextField( - value = accountAddress, - onValueChange = { accountAddress = it }, - label = { Text("Account Address", - fontSize = 16.sp, - color = Color.White, - modifier=Modifier.padding(10.dp), - fontWeight = FontWeight.Bold) }, - modifier=Modifier.padding(15.dp), - colors = TextFieldDefaults.textFieldColors( - textColor = Color("#ffffff".toColorInt()), - disabledTextColor = Transparent, - backgroundColor = Transparent, - focusedIndicatorColor = Transparent, - unfocusedIndicatorColor = Transparent, - disabledIndicatorColor = Transparent - ) - - ) - - Spacer(modifier = Modifier.height(16.dp)) - Row(){ - Button(onClick = { - - scope.launch { - // Catch any errors and display message in the UI - try { - val accountAddress2 = Felt.fromHex( accountAddress) - - // Get the balance of the account - val balancefinal = starknetClient.getEthBalance(accountAddress2) - Log.d("balance","${balancefinal}") - withContext(Dispatchers.Main) { balance= "${starknetClient.weiToEther(balancefinal)} ETH" } - } catch (e: RpcRequestFailedException) { - withContext(Dispatchers.Main) { Toast.makeText(applicationContext, "${e.code}: ${e.message}", Toast.LENGTH_LONG).show() } - } catch (e: Exception) { - withContext(Dispatchers.Main) { Toast.makeText(applicationContext, e.message, Toast.LENGTH_LONG).show() } - } - } - }) { - Text("Get Balance") - } - Spacer(modifier = Modifier.width(10.dp)) - Button(onClick = { - context.finish() - }) { - Text("Back to home") - } - - } - - Spacer(modifier = Modifier.height(20.dp)) - Text("Balance : ${(balance)}",color= Color.White,fontSize = 20.sp,fontWeight = FontWeight.Bold) - - - } - } -} \ No newline at end of file diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/AccountPassword.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/AccountPassword.kt deleted file mode 100644 index 3551ace7..00000000 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/AccountPassword.kt +++ /dev/null @@ -1,170 +0,0 @@ -package com.example.walletapp - -import android.app.Activity -import android.content.Intent -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.text.KeyboardOptions -import androidx.compose.material3.IconButton -import androidx.compose.material3.Button -import androidx.compose.material3.ButtonDefaults -import androidx.compose.material3.TextField -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.remember -import androidx.compose.ui.unit.dp -import androidx.compose.material3.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.input.ImeAction -import androidx.compose.ui.text.input.KeyboardType -import androidx.compose.ui.unit.sp -import androidx.core.graphics.toColorInt -import androidx.core.view.WindowCompat -import com.example.walletapp.ui.theme.WalletappTheme - -class AccountPasswordActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - WindowCompat.setDecorFitsSystemWindows(window, true) - setContent { - WalletappTheme { - Surface(modifier = Modifier.fillMaxSize()) { - AccountPasswordScreenView( - modifier = Modifier.padding(10.dp) - ) - } - } - } - } - - @Composable - fun AccountPasswordScreenView(modifier: Modifier){ - val (password, setPassword) = remember { mutableStateOf("") } - val (confirmPassword, setConfirmPassword) = remember { mutableStateOf("") } - val context = (LocalContext.current as Activity) - - Column( - modifier = Modifier - .fillMaxSize() - .background(Color("#0C0C4F".toColorInt())) - .padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Spacer(modifier = Modifier.height(20.dp)) - Row( - modifier = Modifier - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { - IconButton(onClick = { }) { - Image( - painter = painterResource(R.drawable.arrow_back_ios), - contentDescription = null, - modifier = Modifier.size(20.dp) - ) - } - Text( - text = "Create Wallet Password", - color = Color.White, - fontSize = 18.sp, - fontFamily = FontFamily(Font(R.font.inter_regular)), - modifier = Modifier.weight(2f), - ) - } - Spacer(modifier = Modifier.height(40.dp)) - Text( - text = "Include letters, numbers & symbol for a strong password ", - fontFamily = FontFamily(Font(R.font.inter_regular)), - color = Color.White, - fontSize = 14.sp - ) - Spacer(modifier = Modifier.height(20.dp)) - TextField( - value = password, - onValueChange = { newValue -> setPassword(newValue) }, - textStyle = TextStyle( - fontFamily = FontFamily(Font(R.font.inter_regular)), - color = Color.White, - fontSize = 15.sp - ), - placeholder = { - Text( - text = "Enter your password *", - fontFamily = FontFamily(Font(R.font.inter_regular)), - color = Color.White, - fontSize = 15.sp - ) - }, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, // Number-only keyboard - imeAction = ImeAction.Done), - modifier = Modifier.fillMaxWidth(), - ) - - Spacer(modifier = Modifier.height(20.dp)) - - TextField( - value = confirmPassword, - onValueChange = { newValue -> setConfirmPassword(newValue) }, - textStyle = TextStyle( - fontFamily = FontFamily(Font(R.font.inter_regular)), - color = Color.White, - fontSize = 15.sp - ), - placeholder = { - Text( - text = "Confirm Password *", - fontFamily = FontFamily(Font(R.font.inter_regular)), - color = Color.White, - fontSize = 15.sp - ) - }, - keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number, // Number-only keyboard - imeAction = ImeAction.Done), - modifier = Modifier.fillMaxWidth(), - ) - Spacer(modifier = Modifier.weight(1f)) - Image( - painterResource(id = R.drawable.progress_1), - contentDescription ="progress", - modifier = Modifier.fillMaxWidth().height(6.dp)) - - Spacer(modifier = Modifier.height(20.dp)) - Button( - onClick = { val i = Intent(context, RecoveryPhraseActivity::class.java) - context.startActivity(i) }, - colors = ButtonDefaults.buttonColors(Color("#1B1B76".toColorInt())), - modifier = Modifier - .fillMaxWidth() - .height(49.dp) - - ) { - Text(text = "Next", color = Color.White) - } - Spacer(modifier = Modifier.height(15.dp)) - } - - } -} diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/AddTokenActivity.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/AddTokenActivity.kt deleted file mode 100644 index 64b435d0..00000000 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/AddTokenActivity.kt +++ /dev/null @@ -1,162 +0,0 @@ -package com.example.walletapp - -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Button -import androidx.compose.material.ButtonDefaults -import androidx.compose.material.Surface -import androidx.compose.material.Text -import androidx.compose.material.TextField -import androidx.compose.material.TextFieldDefaults -import androidx.compose.runtime.Composable -import androidx.compose.runtime.mutableStateOf -import androidx.compose.runtime.saveable.rememberSaveable -import androidx.compose.ui.text.TextStyle -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.core.graphics.toColorInt -import androidx.core.view.WindowCompat -import com.example.walletapp.ui.theme.WalletappTheme - -class AddTokenActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - WindowCompat.setDecorFitsSystemWindows(window, true) - setContent { - WalletappTheme { - Surface(modifier = Modifier.fillMaxSize()) { - AddTokenScreenView(modifier = Modifier.padding(10.dp)) - } - - } - } - } -} - -@Composable -fun SimpleTextField( - value: String, - onValueChange: (String) -> Unit, - label: String, - placeholder: String -) { - Column( - modifier = Modifier.fillMaxWidth() - ) { - Text( - text = label, - color = Color.White, - fontFamily = FontFamily(Font(R.font.publicsans_regular)), - fontSize = 16.sp, - modifier = Modifier.padding(bottom = 10.dp) - ) - TextField( - value = value, - onValueChange = onValueChange, - placeholder = { Text(text = placeholder) }, - colors = TextFieldDefaults.outlinedTextFieldColors( - backgroundColor = Color("#1B1B76".toColorInt()), - focusedBorderColor = Color.Transparent, - unfocusedBorderColor = Color.Transparent, - textColor = Color.Black, - placeholderColor = Color("#A9A9A9".toColorInt()) - ), - shape = RoundedCornerShape(15.dp), - modifier = Modifier.fillMaxWidth(), - textStyle = TextStyle( - color = Color.Black, - fontSize = 16.sp - ) - ) - } -} - -@Composable -fun AddTokenScreenView(modifier: Modifier) { - val contactAddress = rememberSaveable { mutableStateOf("") } - val name = rememberSaveable { mutableStateOf("") } - val symbol = rememberSaveable { mutableStateOf("") } - val decimals = rememberSaveable { mutableStateOf("") } - - Column( - modifier = Modifier - .fillMaxSize() - .background(Color("#0C0C4F".toColorInt())) - .padding(horizontal = 16.dp, vertical = 24.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Top - ) { - Text( - text = "Add Token", - fontFamily = FontFamily(Font(R.font.publicsans_bold)), - color = Color.White, - fontSize = 28.sp - ) - - Spacer(modifier = Modifier.height(40.dp)) - - Column( - modifier = Modifier - .fillMaxWidth() - .padding(horizontal = 16.dp) - ) { - SimpleTextField( - value = contactAddress.value, - onValueChange = { contactAddress.value = it }, - label = "Contact Address", - placeholder = "0x123" - ) - Spacer(modifier = Modifier.height(16.dp)) - SimpleTextField( - value = name.value, - onValueChange = { name.value = it }, - label = "Name", - placeholder = "Name" - ) - Spacer(modifier = Modifier.height(16.dp)) - SimpleTextField( - value = symbol.value, - onValueChange = { symbol.value = it }, - label = "Symbol", - placeholder = "TOK" - ) - Spacer(modifier = Modifier.height(16.dp)) - SimpleTextField( - value = decimals.value, - onValueChange = { decimals.value = it }, - label = "Decimals", - placeholder = "18" - ) - } - - Spacer(modifier = Modifier.weight(1f)) - - Button( - onClick = { /* Handle confirm action */ }, - colors = ButtonDefaults.buttonColors(backgroundColor = Color("#1B1B76".toColorInt())), - modifier = Modifier - .fillMaxWidth() - .padding(start = 30.dp, end = 30.dp) - ) { - Text(text = "Confirm", color = Color.White) - } - } -} - diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/MainActivity.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/MainActivity.kt deleted file mode 100644 index 077151a9..00000000 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/MainActivity.kt +++ /dev/null @@ -1,172 +0,0 @@ -package com.example.walletapp - -import android.app.Activity -import android.content.Intent -import android.os.Bundle -import android.widget.Toast -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge -import androidx.compose.foundation.Image -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Arrangement -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.Spacer -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height -import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.Button -import androidx.compose.material.ButtonDefaults -import androidx.compose.material.Surface -import androidx.compose.material3.Text -import androidx.compose.runtime.Composable -import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.platform.LocalContext -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.core.graphics.toColorInt -import androidx.core.view.WindowCompat -import com.example.walletapp.ui.activity.CreateAccountActivity -import com.example.walletapp.ui.theme.WalletappTheme -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext - -class MainActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - WindowCompat.setDecorFitsSystemWindows(window, true) - setContent { - WalletappTheme { - Surface(modifier = Modifier.fillMaxSize()) { - CreateAccount( - modifier = Modifier.padding(10.dp) - ) - } - } - } - } -} - - -@Composable -fun StarknetLogo (modifier: Modifier = Modifier) { - Image( - painter = painterResource(id = R.drawable.starknet_icon ), - contentDescription = "Starknet Logo", - modifier = modifier.size(123.dp) ) -} -@Composable -fun CreateAccount( modifier: Modifier) { - val context = (LocalContext.current as Activity) - val scope = rememberCoroutineScope() - val starknetClient = StarknetClient(BuildConfig.RPC_URL) - - Column( - modifier = Modifier - .fillMaxSize() - .background(Color("#0C0C4F".toColorInt())) - .padding(20.dp) - ) { - Text( - text = "Starknet Wallet", - fontFamily = FontFamily(Font(R.font.inter_regular)), - color = Color.White, - fontSize = 28.sp, - modifier = Modifier - .align(Alignment.CenterHorizontally) - .padding(top = 70.dp) - ) - Spacer(modifier = Modifier.height(50.dp)) - StarknetLogo( - modifier = Modifier.align(Alignment.CenterHorizontally) - ) - Spacer(modifier = Modifier.weight(1f)) - Column( - modifier = Modifier.fillMaxWidth(), - verticalArrangement = Arrangement.spacedBy(8.dp) // Adjust space between buttons - ) { - Button( - onClick = { val i = Intent(context, CreateAccountActivity::class.java) - context.startActivity(i) }, - colors = ButtonDefaults.buttonColors(backgroundColor = Color("#1B1B76".toColorInt())), - shape = RoundedCornerShape(10.dp), - modifier = Modifier - .fillMaxWidth() - .height(48.dp) - ) { - Text( - text = "Create a New Wallet", - fontFamily = FontFamily(Font(R.font.inter_regular)), - color = Color.White, - fontSize = 17.sp - ) - } - - Spacer(modifier = Modifier.height(10.dp)) - - - Button( - onClick = { val i = Intent(context, ImportExistingKeyActivity::class.java) - context.startActivity(i) }, - colors = ButtonDefaults.buttonColors(backgroundColor = Color("#EC796B".toColorInt())), - shape = RoundedCornerShape(10.dp), - modifier = Modifier - .fillMaxWidth() - .height(49.dp) - ) { - Text( - text = "Import Starknet Wallet", - fontFamily = FontFamily(Font(R.font.inter_regular)), - color = Color.White, - fontSize = 17.sp - ) - } - Spacer(modifier = Modifier.height(10.dp)) - - // New button for deploying Starknet account - Button( - onClick = { - scope.launch { - try { - starknetClient.deployAccount() - - withContext(Dispatchers.Main) { - Toast.makeText(context, "Account deployed successfully!", Toast.LENGTH_LONG).show() - } - } catch (e: Exception) { - withContext(Dispatchers.Main) { - Toast.makeText(context, "Error deploying account: ${e.message}", Toast.LENGTH_LONG).show() - } - } - } - }, - colors = ButtonDefaults.buttonColors(backgroundColor = Color("#4CAF50".toColorInt())), - shape = RoundedCornerShape(10.dp), - modifier = Modifier - .fillMaxWidth() - .height(49.dp) - ) { - Text( - text = "My Starknet Wallet", - fontFamily = FontFamily(Font(R.font.inter_regular)), - color = Color.White, - fontSize = 17.sp - ) - } - } - - Spacer(modifier = Modifier.height(15.dp)) - } -} - diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/RecoveryPhraseActivity.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/RecoveryPhraseActivity.kt deleted file mode 100644 index f403227b..00000000 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/RecoveryPhraseActivity.kt +++ /dev/null @@ -1,304 +0,0 @@ -package com.example.walletapp -import android.app.Activity -import android.content.Intent -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.compose.foundation.Image -import androidx.compose.ui.platform.LocalContext -import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* -import androidx.compose.foundation.lazy.grid.GridCells -import androidx.compose.foundation.lazy.grid.LazyVerticalGrid -import androidx.compose.foundation.lazy.grid.items -import androidx.compose.foundation.shape.CircleShape -import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.* -import androidx.compose.runtime.* -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.res.painterResource -import androidx.compose.ui.text.font.Font -import androidx.compose.ui.text.font.FontFamily -import androidx.compose.ui.text.style.TextAlign -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.core.graphics.toColorInt -import androidx.core.view.WindowCompat -import androidx.navigation.NavController -import androidx.navigation.compose.rememberNavController -import androidx.compose.runtime.Composable -import androidx.compose.material3.Text -import androidx.compose.foundation.layout.fillMaxWidth -import com.example.walletapp.ui.theme.WalletappTheme - -class RecoveryPhraseActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - WindowCompat.setDecorFitsSystemWindows(window, true) - setContent { - WalletappTheme { - val navController = rememberNavController() - Surface(modifier = Modifier.fillMaxSize()) { - RecoveryPhraseScreenView( - modifier = Modifier.padding(10.dp), - navController = navController - ) - } - } - } - } - - @Composable - fun RecoveryPhraseScreenView(modifier: Modifier, navController: NavController) { - var isVisible by remember { mutableStateOf(false) } - var showDialog by remember { mutableStateOf(false) } - - Column( - modifier = Modifier - .fillMaxSize() - .background(Color("#0C0C4F".toColorInt())) - .padding(16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { - Spacer(modifier = Modifier.height(20.dp)) - Row( - modifier = Modifier - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically - ) { - IconButton(onClick = { navController.popBackStack() }) { - Image( - painter = painterResource(R.drawable.arrow_back_ios), - contentDescription = null, - modifier = Modifier.size(20.dp) - ) - } - Text( - text = "Secret Recovery Seed Phrase", - color = Color.White, - fontSize = 18.sp, - fontFamily = FontFamily(Font(R.font.inter_regular)), - modifier = Modifier.weight(2f), - ) - } - Spacer(modifier = Modifier.height(20.dp)) - Text( - text = "Secure it now! This is your only way to recover your wallet if your Starknet wallet is deleted, or if your device is lost, stolen, or becomes unusable.", - fontFamily = FontFamily(Font(R.font.inter_regular)), - color = Color.White, - textAlign = TextAlign.Center, - fontSize = 14.sp - ) - Spacer(modifier = Modifier.height(40.dp)) - - if (isVisible) SeedPhrases() else { - Column( - modifier = Modifier.fillMaxWidth(), - horizontalAlignment = Alignment.CenterHorizontally, - ) { - Image( - painter = painterResource(id = R.drawable.warning_sign), - contentDescription = "warning", - modifier = Modifier.size(60.dp) - ) - Spacer(modifier = Modifier.height(40.dp)) - Text( - text = "Hope no one is looking at your screen", - fontFamily = FontFamily(Font(R.font.inter_regular)), - color = Color.White, - textAlign = TextAlign.Center, - fontSize = 15.sp - ) - } - } - - Spacer(modifier = Modifier.height(50.dp)) - - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceBetween - ) { - Button( - onClick = { isVisible = !isVisible }, - colors = ButtonDefaults.buttonColors(backgroundColor = Color("#1B1B76".toColorInt())), - shape = RoundedCornerShape(8.dp), - modifier = Modifier - .width(150.dp) - .height(40.dp) - ) { - Image( - painter = painterResource(if (isVisible) R.drawable.visibility_off else R.drawable.visibility), - contentDescription = null, - modifier = Modifier.size(20.dp) - ) - Spacer(modifier = Modifier.size(10.dp)) - Text( - text = if (isVisible) "Hide" else "Show", - fontFamily = FontFamily(Font(R.font.inter_regular)), - color = Color.White, - fontSize = 14.sp - ) - } - - Button( - onClick = { /* Handle copy action */ }, - colors = ButtonDefaults.buttonColors(backgroundColor = Color("#1B1B76".toColorInt())), - shape = RoundedCornerShape(8.dp), - modifier = Modifier - .width(150.dp) - .height(40.dp) - ) { - Image( - painter = painterResource(id = R.drawable.copy), - contentDescription = "copy", - modifier = Modifier.size(20.dp) - ) - Spacer(modifier = Modifier.size(10.dp)) - Text( - text = "Copy", - fontFamily = FontFamily(Font(R.font.publicsans_bold)), - color = Color.White, - fontSize = 14.sp - ) - } - } - - Spacer(modifier = Modifier.weight(1f)) - Image( - painter = painterResource(id = R.drawable.progress_2), - contentDescription = "progress", - modifier = Modifier - .fillMaxWidth() - .height(6.dp) - ) - - Spacer(modifier = Modifier.height(20.dp)) - Button( - onClick = { showDialog = !showDialog }, - colors = ButtonDefaults.buttonColors(backgroundColor = Color("#1B1B76".toColorInt())), - modifier = Modifier - .fillMaxWidth() - .height(49.dp) - ) { - Text(text = "Next", color = Color.White, fontSize = 17.sp) - } - - if (showDialog) { - CustomDialog(onDismiss = { showDialog = false }) - } - Spacer(modifier = Modifier.height(15.dp)) - } - } - - @Composable - fun SeedPhrases() { - LazyVerticalGrid( - columns = GridCells.Fixed(2), - contentPadding = PaddingValues(8.dp), - modifier = Modifier.fillMaxWidth() - ) { - items(generateSeedWords()) { item -> - Row( - modifier = Modifier - .padding(8.dp) - .fillMaxWidth(), - horizontalArrangement = Arrangement.Start, - verticalAlignment = Alignment.CenterVertically - ) { - Box( - modifier = Modifier - .size(32.dp) - .background(Color("#1B1B76".toColorInt()), shape = CircleShape) - .wrapContentSize(Alignment.Center) - ) { - Text( - text = "${item.number}", - fontSize = 14.sp, - color = Color.White, - modifier = Modifier.align(Alignment.Center) - ) - } - Spacer(modifier = Modifier.width(8.dp)) - Text(text = item.text, fontSize = 16.sp, color = Color.White) - } - } - } - } -} - -data class SeedWordItem(val number: Int, val text: String) - -fun generateSeedWords(): List { - val randomWords = listOf( - "apple", "banana", "cherry", "date", "elderberry", "fig", "grape", "honeydew", - "kiwi", "lemon", "mango", "nectarine", "orange", "papaya", "quince", "raspberry", - "strawberry", "tangerine", "ugli", "vanilla", "watermelon", "xigua", "yellow", "zucchini" - ) - return List(12) { SeedWordItem(it + 1, randomWords.random()) } -} - -@Composable -fun CustomDialog(onDismiss: () -> Unit) { - val context = (LocalContext.current as Activity) - AlertDialog( - onDismissRequest = onDismiss, - title = { - Column( - modifier = Modifier - .fillMaxWidth() - .padding(bottom = 16.dp), - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center - ) { -// Image( -// painter = painterResource(id = R.drawable.check_symbol), -// contentDescription = "success", -// modifier = Modifier -// .size(80.dp) -// .background(Color.White, shape = CircleShape) -// .padding(8.dp) -// .align(Alignment.CenterHorizontally) -// ) - Spacer(modifier = Modifier.height(8.dp)) - Text( - text = "Congratulations!", - fontSize = 20.sp, - color = Color.White, - textAlign = TextAlign.Center - ) - } - }, - text = { - Text( - text = "You’re done creating your wallet", - color = Color.White, - fontSize = 18.sp, - textAlign = TextAlign.Center - ) - }, - confirmButton = { - Button( - onClick = { val i = Intent(context, WalletActivity::class.java) - context.startActivity(i) }, - modifier = Modifier - .fillMaxWidth() - .height(48.dp), - colors = ButtonDefaults.buttonColors(backgroundColor = Color("#2C74DD".toColorInt())) - ) { - Text( - text = "Let’s start!", - color = Color.White - ) - } - }, - shape = RoundedCornerShape(16.dp), - backgroundColor = Color("#0C0C4F".toColorInt()), - contentColor = Color.White, - modifier = Modifier - .width(500.dp) - .padding(8.dp) - ) -} \ No newline at end of file diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/model/Account.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/model/Account.kt new file mode 100644 index 00000000..bd90c779 --- /dev/null +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/model/Account.kt @@ -0,0 +1,5 @@ +package com.example.walletapp.model + +class Account { + var address: String = "" +} \ No newline at end of file diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/model/Token.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/model/Token.kt new file mode 100644 index 00000000..30c7d2d6 --- /dev/null +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/model/Token.kt @@ -0,0 +1,6 @@ +package com.example.walletapp.model + +class Token { + var address: String = "" + var symbol: String = "" +} \ No newline at end of file diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/model/User.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/model/User.kt new file mode 100644 index 00000000..628d9d14 --- /dev/null +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/model/User.kt @@ -0,0 +1,13 @@ +package com.example.walletapp.model + +class User { + private var accounts: Array = emptyArray(); + + fun hasAccount(): Boolean { + return accounts.isNotEmpty() + } + + fun getAccounts(): Array { + return accounts + } +} diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/theme/Color.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/theme/Color.kt deleted file mode 100644 index a17c0843..00000000 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/theme/Color.kt +++ /dev/null @@ -1,12 +0,0 @@ -package com.example.walletapp.ui.theme - -import androidx.compose.ui.graphics.Color - -val Purple80 = Color(0xFFD0BCFF) -val PurpleGrey80 = Color(0xFFCCC2DC) -val Pink80 = Color(0xFFEFB8C8) - -val Purple40 = Color(0xFF6650a4) -val PurpleGrey40 = Color(0xFF625b71) -val Pink40 = Color(0xFF7D5260) - diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/ui/MainActivity.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/MainActivity.kt new file mode 100644 index 00000000..4fde3df0 --- /dev/null +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/MainActivity.kt @@ -0,0 +1,21 @@ +package com.example.walletapp.ui + +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.activity.enableEdgeToEdge +import androidx.core.view.WindowCompat + +class MainActivity : ComponentActivity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + enableEdgeToEdge() + WindowCompat.setDecorFitsSystemWindows(window, true) + setContent { + WalletApp() + } + } +} + + + diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/ui/WalletApp.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/WalletApp.kt new file mode 100644 index 00000000..a4cbc9ee --- /dev/null +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/WalletApp.kt @@ -0,0 +1,110 @@ +package com.example.walletapp.ui + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import com.example.walletapp.ui.account.AddTokenScreen +import com.example.walletapp.ui.account.WalletScreen +import com.example.walletapp.ui.activity.FinalizeAccountCreationScreen +import com.example.walletapp.ui.onboarding.CreateAccountScreen +import com.example.walletapp.ui.onboarding.CreatePinScreen +import com.example.walletapp.ui.onboarding.ImportAccountScreen +import com.example.walletapp.ui.onboarding.border.OnboardingScreen +import com.example.walletapp.ui.theme.WalletappTheme +import com.example.walletapp.ui.transfer.ReceiveScreen +import com.example.walletapp.ui.transfer.SendScreen +import kotlinx.serialization.Serializable + +// main user account view +@Serializable +object Wallet +@Serializable +object AddToken + +// onboarding flow +@Serializable +object Onboarding +@Serializable +object CreateAccount +@Serializable +object ImportAccount +@Serializable +object CreatePin +@Serializable +object FinalizeAccountCreation + +// token transfer flow +@Serializable +object Send +@Serializable +object Receive + +@Composable +fun WalletApp() { + WalletappTheme { + + // TODO: get this information from a data store + val hasAccount = false + + fun getStart(): Any { + return if (hasAccount) { + Wallet + } else { + Onboarding + } + } + + val navController = rememberNavController() + NavHost(navController, startDestination = getStart()) { + + composable { + OnboardingScreen( + onNavigateCreateAccount = { navController.navigate( route = CreateAccount ) }, + onNavigateImportAccount = { navController.navigate( route = ImportAccount ) } + ) + } + composable { + CreateAccountScreen( + onContinue = { navController.navigate( route = FinalizeAccountCreation )} + ) + } + composable { + FinalizeAccountCreationScreen( + onContinue = { navController.navigate( route = CreatePin )} + ) + } + composable { + ImportAccountScreen( + onFinishAccountImport = { navController.navigate( route = CreatePin ) } + ) + } + composable { + CreatePinScreen( + onContinue = { navController.navigate( route = Wallet )} + ) + } + + composable { + WalletScreen( + onNewTokenPress = { navController.navigate( route = AddToken ) }, + onReceivePress = { navController.navigate( route = Receive ) }, + onSendPress = { navController.navigate( route = Send ) } + ) + } + composable { + AddTokenScreen( + onConfirm = { navController.navigateUp() } + ) + } + + composable { + SendScreen() + } + composable { + ReceiveScreen(modifier = Modifier) + } + } + } +} \ No newline at end of file diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/ui/account/AddTokenScreen.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/account/AddTokenScreen.kt new file mode 100644 index 00000000..67942fa1 --- /dev/null +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/account/AddTokenScreen.kt @@ -0,0 +1,144 @@ +package com.example.walletapp.ui.account + +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.Surface +import androidx.compose.material.Text +import androidx.compose.material.TextField +import androidx.compose.material.TextFieldDefaults +import androidx.compose.runtime.Composable +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.ui.text.TextStyle +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.graphics.toColorInt +import com.example.walletapp.R + +@Composable +fun AddTokenScreen(onConfirm: () -> Unit) { + Surface(modifier = Modifier.fillMaxSize()) { + val contactAddress = rememberSaveable { mutableStateOf("") } + val name = rememberSaveable { mutableStateOf("") } + val symbol = rememberSaveable { mutableStateOf("") } + val decimals = rememberSaveable { mutableStateOf("") } + + Column( + modifier = Modifier + .fillMaxSize() + .background(Color("#0C0C4F".toColorInt())) + .padding(horizontal = 16.dp, vertical = 24.dp), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Top + ) { + Text( + text = "Add Token", + fontFamily = FontFamily(Font(R.font.publicsans_bold)), + color = Color.White, + fontSize = 28.sp + ) + + Spacer(modifier = Modifier.height(40.dp)) + + Column( + modifier = Modifier + .fillMaxWidth() + .padding(horizontal = 16.dp) + ) { + SimpleTextField( + value = contactAddress.value, + onValueChange = { contactAddress.value = it }, + label = "Contact Address", + placeholder = "0x123" + ) + Spacer(modifier = Modifier.height(16.dp)) + SimpleTextField( + value = name.value, + onValueChange = { name.value = it }, + label = "Name", + placeholder = "Name" + ) + Spacer(modifier = Modifier.height(16.dp)) + SimpleTextField( + value = symbol.value, + onValueChange = { symbol.value = it }, + label = "Symbol", + placeholder = "TOK" + ) + Spacer(modifier = Modifier.height(16.dp)) + SimpleTextField( + value = decimals.value, + onValueChange = { decimals.value = it }, + label = "Decimals", + placeholder = "18" + ) + } + + Spacer(modifier = Modifier.weight(1f)) + + // TODO: handle saving the token data + Button( + onClick = onConfirm, + colors = ButtonDefaults.buttonColors(backgroundColor = Color("#1B1B76".toColorInt())), + modifier = Modifier + .fillMaxWidth() + .padding(start = 30.dp, end = 30.dp) + ) { + Text(text = "Confirm", color = Color.White) + } + } + } +} + +@Composable +fun SimpleTextField( + value: String, + onValueChange: (String) -> Unit, + label: String, + placeholder: String +) { + Column( + modifier = Modifier.fillMaxWidth() + ) { + Text( + text = label, + color = Color.White, + fontFamily = FontFamily(Font(R.font.publicsans_regular)), + fontSize = 16.sp, + modifier = Modifier.padding(bottom = 10.dp) + ) + TextField( + value = value, + onValueChange = onValueChange, + placeholder = { Text(text = placeholder) }, + colors = TextFieldDefaults.outlinedTextFieldColors( + backgroundColor = Color("#1B1B76".toColorInt()), + focusedBorderColor = Color.Transparent, + unfocusedBorderColor = Color.Transparent, + textColor = Color.Black, + placeholderColor = Color("#A9A9A9".toColorInt()) + ), + shape = RoundedCornerShape(15.dp), + modifier = Modifier.fillMaxWidth(), + textStyle = TextStyle( + color = Color.Black, + fontSize = 16.sp + ) + ) + } +} + diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/CoinViewModel.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/account/CoinViewModel.kt similarity index 97% rename from wallet_app/android/app/src/main/java/com/example/walletapp/CoinViewModel.kt rename to wallet_app/android/app/src/main/java/com/example/walletapp/ui/account/CoinViewModel.kt index 634f2f4e..3b20a6ff 100644 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/CoinViewModel.kt +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/account/CoinViewModel.kt @@ -1,4 +1,4 @@ -package com.example.walletapp +package com.example.walletapp.ui.account import androidx.lifecycle.ViewModel diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/WalletActivity.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/account/WalletScreen.kt similarity index 51% rename from wallet_app/android/app/src/main/java/com/example/walletapp/WalletActivity.kt rename to wallet_app/android/app/src/main/java/com/example/walletapp/ui/account/WalletScreen.kt index 3d6d1632..ea9468ab 100644 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/WalletActivity.kt +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/account/WalletScreen.kt @@ -1,11 +1,7 @@ -package com.example.walletapp +package com.example.walletapp.ui.account import android.app.Activity -import android.content.Intent -import android.os.Bundle import android.widget.Toast -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent import androidx.compose.foundation.Image import androidx.compose.ui.graphics.painter.Painter import androidx.compose.foundation.background @@ -39,8 +35,6 @@ import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.graphics.toColorInt -import androidx.core.view.WindowCompat -import com.example.walletapp.ui.theme.WalletappTheme import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowDropDown import androidx.compose.material.* @@ -52,257 +46,245 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.window.Popup import androidx.compose.ui.window.PopupProperties import androidx.lifecycle.viewmodel.compose.viewModel +import com.example.walletapp.BuildConfig +import com.example.walletapp.R +import com.example.walletapp.utils.StarknetClient +import com.example.walletapp.utils.toDoubleWithTwoDecimal +import com.example.walletapp.utils.weiToEther import com.swmansion.starknet.data.types.Felt import com.swmansion.starknet.provider.exceptions.RpcRequestFailedException import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.withContext -import java.math.BigDecimal -import java.text.DecimalFormat - - -class WalletActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - WindowCompat.setDecorFitsSystemWindows(window, true) - setContent { - WalletappTheme { - Surface(modifier = Modifier.fillMaxSize()) { - Wallet( - modifier = Modifier.padding(10.dp), - ) - } - } - } - } + +@Composable +fun WalletScreen( + onNewTokenPress: () -> Unit, + onSendPress: () -> Unit, + onReceivePress: () -> Unit +) { + Surface(modifier = Modifier.fillMaxSize()) { + Wallet( + modifier = Modifier.padding(10.dp), + onNewTokenPress = onNewTokenPress, + onSendPress = onSendPress, + onReceivePress = onReceivePress + ) + } } - @Composable - fun Wallet(modifier: Modifier) { - val networkList = listOf("Starknet Mainnet", "Test Networks") - var selectedNetworkIndex by remember { mutableStateOf(0) } - val context = (LocalContext.current as Activity) - val address=BuildConfig.ACCOUNT_ADDRESS - val accountAddress = Felt.fromHex(address) - val starknetClient = StarknetClient(BuildConfig.RPC_URL) - var balance by remember { mutableStateOf("") } +@Composable +fun Wallet(modifier: Modifier, onNewTokenPress: () -> Unit, onReceivePress: () -> Unit, onSendPress: () -> Unit) { + val networkList = listOf("Starknet Mainnet", "Test Networks") + var selectedNetworkIndex by remember { mutableStateOf(0) } + val context = (LocalContext.current as Activity) + val address= BuildConfig.ACCOUNT_ADDRESS + val accountAddress = Felt.fromHex(address) + val starknetClient = StarknetClient(BuildConfig.RPC_URL) + var balance by remember { mutableStateOf("") } + + val coinViewModel: CoinViewModel = viewModel() + + val coinsPrices : HashMap = rememberSaveable { + hashMapOf() + } - val coinViewModel: CoinViewModel = viewModel() + val prices by coinViewModel.prices + val errorMessage by coinViewModel.errorMessage - val coinsPrices : HashMap = rememberSaveable { - hashMapOf() - } - - val prices by coinViewModel.prices - val errorMessage by coinViewModel.errorMessage + LaunchedEffect(Unit) { + coinViewModel.getTokenPrices(ids = "starknet,ethereum", vsCurrencies = "usd") // Fetch starknet and bitcoin prices in USD + } - LaunchedEffect(Unit) { - coinViewModel.getTokenPrices(ids = "starknet,ethereum", vsCurrencies = "usd") // Fetch starknet and bitcoin prices in USD + LaunchedEffect (Unit){ + try { + // Get the balance of the account + val getBalance = starknetClient.getEthBalance(accountAddress) + withContext(Dispatchers.Main) { + balance = weiToEther(getBalance).toDoubleWithTwoDecimal() + } + } catch (e: RpcRequestFailedException) { + withContext(Dispatchers.Main) { Toast.makeText(context, "${e.code}: ${e.message}", Toast.LENGTH_LONG).show() } + } catch (e: Exception) { + withContext(Dispatchers.Main) { Toast.makeText(context, e.message, Toast.LENGTH_LONG).show() } } - - LaunchedEffect (Unit){ - try { - // Get the balance of the account - val getBalance = starknetClient.getEthBalance(accountAddress) - withContext(Dispatchers.Main) { - balance = starknetClient.weiToEther(getBalance).toDoubleWithTwoDecimal() - } - } catch (e: RpcRequestFailedException) { - withContext(Dispatchers.Main) { Toast.makeText(context, "${e.code}: ${e.message}", Toast.LENGTH_LONG).show() } - } catch (e: Exception) { - withContext(Dispatchers.Main) { Toast.makeText(context, e.message, Toast.LENGTH_LONG).show() } + } + if (errorMessage.isNotEmpty()) { + Text( + text = errorMessage, + color = MaterialTheme.colors.error, + modifier = Modifier.padding(16.dp) + ) + } else { + Column(modifier = Modifier.padding(16.dp)) { + prices.forEach { (token, price) -> + coinsPrices[token] = price.toDoubleWithTwoDecimal() + Spacer(modifier = Modifier.height(8.dp)) } } - if (errorMessage.isNotEmpty()) { - Text( - text = errorMessage, - color = MaterialTheme.colors.error, - modifier = Modifier.padding(16.dp) - ) - } else { - Column(modifier = Modifier.padding(16.dp)) { - prices.forEach { (token, price) -> - coinsPrices[token] = price.toDoubleWithTwoDecimal() - Spacer(modifier = Modifier.height(8.dp)) + } + + Column( + modifier = Modifier + .fillMaxSize() + .background(Color("#0C0C4F".toColorInt())) + .padding(20.dp) + ) { + + Box( + modifier = Modifier.fillMaxWidth(), // Ensure Box takes full width of the parent + contentAlignment = Alignment.Center // Center contents horizontally + ) { + SwitchNetwork( + networkList, + selectedNetworkIndex, + modifier = Modifier, + onItemClick = { index -> + selectedNetworkIndex = index } - } + ) } - Column( + + Text( + text ="$11,625.48", + fontFamily = FontFamily(Font(R.font.publicsans_bold)), + color = Color.White, + fontSize = 24.sp, modifier = Modifier - .fillMaxSize() - .background(Color("#0C0C4F".toColorInt())) - .padding(20.dp) - ) { + .align(Alignment.CenterHorizontally) + .padding(top = 70.dp) + ) + Text( + text = address.take(10) + ".....", + fontFamily = FontFamily(Font(R.font.inter_regular)), + color = Color.White, + fontSize = 14.sp, + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + + Spacer(modifier = Modifier.height(32.dp)) + + + WalletCard( + icon = painterResource(id = R.drawable.ic_ethereum), + amount = coinsPrices["ethereum"]?.let { "$ $it" } ?: "", + exchange = balance, + type = "ETH" + ) + + // TOOD(#82): load actual balance + WalletCard( + icon = painterResource(id = R.drawable.token2), + amount = coinsPrices["starknet"]?.let { "$ $it" } ?: "", + exchange ="4.44", + type = "STRK" + ) + + Spacer(modifier = Modifier.height(32.dp)) + + Text( + text = "+ New Token", + fontFamily = FontFamily(Font(R.font.publicsans_bold)), + color = Color.White, + fontSize = 14.sp, + modifier = Modifier + .clickable { + onNewTokenPress() + } + .background(Color.Transparent) + .padding(10.dp) + .align(Alignment.CenterHorizontally) + ) - Box( - modifier = Modifier.fillMaxWidth(), // Ensure Box takes full width of the parent - contentAlignment = Alignment.Center // Center contents horizontally + + Spacer(modifier = Modifier.weight(1f)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.SpaceEvenly + ) { + Button( + onClick = onReceivePress, + colors = ButtonDefaults.buttonColors(backgroundColor = Color("#1B1B76".toColorInt())), + shape = RoundedCornerShape(15.dp), ) { - SwitchNetwork( - networkList, - selectedNetworkIndex, - modifier = Modifier, - onItemClick = { index -> - selectedNetworkIndex = index - } + Text( + text = "Receive", fontFamily = FontFamily(Font(R.font.publicsans_bold)), + color = Color.White, + fontSize = 14.sp ) } + Button( + onClick = onSendPress, + colors = ButtonDefaults.buttonColors(backgroundColor = Color("#1B1B76".toColorInt())), + shape = RoundedCornerShape(15.dp), + ) { + Text( + text = "Send", fontFamily = FontFamily(Font(R.font.publicsans_bold)), + color = Color.White, + fontSize = 14.sp + ) + } + } + Spacer(modifier = Modifier.height(15.dp)) + } +} - Text( - text ="$11,625.48", - fontFamily = FontFamily(Font(R.font.publicsans_bold)), - color = Color.White, - fontSize = 24.sp, - modifier = Modifier - .align(Alignment.CenterHorizontally) - .padding(top = 70.dp) - ) - Text( - text = address.take(10) + ".....", - fontFamily = FontFamily(Font(R.font.inter_regular)), - color = Color.White, - fontSize = 14.sp, - modifier = Modifier.align(Alignment.CenterHorizontally) - ) - - Spacer(modifier = Modifier.height(32.dp)) - - - WalletCard( - icon = painterResource(id = R.drawable.ic_ethereum), - amount = coinsPrices["ethereum"]?.let { "$ $it" } ?: "", - exchange = balance, - type = "ETH" - ) - // TOOD(#82): load actual balance - WalletCard( - icon = painterResource(id = R.drawable.token2), - amount = coinsPrices["starknet"]?.let { "$ $it" } ?: "", - exchange ="4.44", - type = "STRK" - ) - Spacer(modifier = Modifier.height(32.dp)) - Text( - text = "+ New Token", - fontFamily = FontFamily(Font(R.font.publicsans_bold)), - color = Color.White, - fontSize = 14.sp, - modifier = Modifier - .clickable { - val intent = Intent(context, AddTokenActivity::class.java) - context.startActivity(intent) - } - .background(Color.Transparent) - .padding(10.dp) - .align(Alignment.CenterHorizontally) +@Composable +fun WalletCard(icon: Painter, amount: String, exchange: String, type: String) { + Card( + backgroundColor = Color(0xFF1E1E96), + modifier = Modifier + .fillMaxWidth() + .padding(vertical = 8.dp) + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .padding(16.dp) + .fillMaxWidth() + ) { + Image( + painter = icon, // replace with your Ethereum icon + contentDescription = null, ) + Spacer(modifier = Modifier.weight(1f)) + Column(modifier = Modifier, horizontalAlignment = Alignment.End) { + Text( + text = amount, + fontFamily = FontFamily(Font(R.font.inter_regular)), + color = Color.White, + fontSize = 18.sp + ) - Spacer(modifier = Modifier.weight(1f)) - Row( - modifier = Modifier.fillMaxWidth(), - horizontalArrangement = Arrangement.SpaceEvenly - ) { - Button( - onClick = { - val i = Intent(context, ReceiverActivity::class.java) - context.startActivity(i) - }, - colors = ButtonDefaults.buttonColors(backgroundColor = Color("#1B1B76".toColorInt())), - shape = RoundedCornerShape(15.dp), - ) { + Row { Text( - text = "Receive", fontFamily = FontFamily(Font(R.font.publicsans_bold)), + text = exchange, + fontFamily = FontFamily(Font(R.font.publicsans_bold)), color = Color.White, fontSize = 14.sp ) - } - Button( - onClick = { - val i = Intent(context, SendActivity::class.java) - context.startActivity(i) - }, - - colors = ButtonDefaults.buttonColors(backgroundColor = Color("#1B1B76".toColorInt())), - shape = RoundedCornerShape(15.dp), - ) { - Text( - text = "Send", fontFamily = FontFamily(Font(R.font.publicsans_bold)), - color = Color.White, - fontSize = 14.sp - ) - } - } - Spacer(modifier = Modifier.height(15.dp)) - } - } -// Function to format BigDecimal to Double with 2 decimal places -fun BigDecimal.toDoubleWithTwoDecimal(): String { - val decimalFormat = DecimalFormat("#.00") - return decimalFormat.format(this.toDouble()) -} -fun Double.toDoubleWithTwoDecimal(): String { - val decimalFormat = DecimalFormat("#.00") - val formattedValue = decimalFormat.format(this) - return if (this < 1) "0$formattedValue" else formattedValue -} - - @Composable - fun WalletCard(icon: Painter, amount: String, exchange: String, type: String) { - Card( - backgroundColor = Color(0xFF1E1E96), - modifier = Modifier - .fillMaxWidth() - .padding(vertical = 8.dp) - ) { - Row( - verticalAlignment = Alignment.CenterVertically, - modifier = Modifier - .padding(16.dp) - .fillMaxWidth() - ) { - Image( - painter = icon, // replace with your Ethereum icon - contentDescription = null, - ) - Spacer(modifier = Modifier.weight(1f)) - Column(modifier = Modifier, horizontalAlignment = Alignment.End) { + Spacer(modifier=Modifier.width(2.dp)) Text( - text = amount, - fontFamily = FontFamily(Font(R.font.inter_regular)), + text = type, + fontFamily = FontFamily(Font(R.font.publicsans_bold)), color = Color.White, - fontSize = 18.sp + fontSize = 12.sp ) - - Row { - Text( - text = exchange, - fontFamily = FontFamily(Font(R.font.publicsans_bold)), - color = Color.White, - fontSize = 14.sp - ) - Spacer(modifier=Modifier.width(2.dp)) - Text( - text = type, - fontFamily = FontFamily(Font(R.font.publicsans_bold)), - color = Color.White, - fontSize = 12.sp - ) - - } - } + } } } +} @Composable fun SwitchNetwork( diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/ui/components/StarknetLogo.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/components/StarknetLogo.kt new file mode 100644 index 00000000..3bc7dce4 --- /dev/null +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/components/StarknetLogo.kt @@ -0,0 +1,27 @@ +package com.example.walletapp.ui.components + +import androidx.compose.foundation.Image +import androidx.compose.foundation.layout.size +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.example.walletapp.R +import com.example.walletapp.ui.theme.WalletappTheme + +@Composable +fun StarknetLogo (modifier: Modifier = Modifier) { + Image( + painter = painterResource(id = R.drawable.starknet_icon), + contentDescription = "Starknet Logo", + modifier = modifier.size(123.dp) ) +} + +@Composable +@Preview +fun PreviewStarknetLogo() { + WalletappTheme { + StarknetLogo() + } +} diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/ui/components/TransparentButton.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/components/TransparentButton.kt new file mode 100644 index 00000000..e301806d --- /dev/null +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/components/TransparentButton.kt @@ -0,0 +1,52 @@ +package com.example.walletapp.ui.components + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.example.walletapp.R +import com.example.walletapp.ui.theme.WalletappTheme +import com.example.walletapp.ui.theme.WhiteFlare + +@Composable +fun TransparentButton( + label: String, + onClick: () -> Unit +) { + OutlinedButton( + onClick = onClick, + shape = RoundedCornerShape(10.dp), + border = BorderStroke(1.dp, WhiteFlare), + modifier = Modifier + .fillMaxWidth() + .height(48.dp) + ) { + Text( + text = label, + fontFamily = FontFamily(Font(R.font.inter_regular)), + color = Color.White, + fontSize = 17.sp + ) + } +} + +@Preview +@Composable +fun PreviewTransparentButton() { + WalletappTheme { + Surface { + TransparentButton(label = "Button Label", onClick = {}) + } + } +} \ No newline at end of file diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/CreateAccountActivity.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/CreateAccountScreen.kt similarity index 67% rename from wallet_app/android/app/src/main/java/com/example/walletapp/CreateAccountActivity.kt rename to wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/CreateAccountScreen.kt index d98b5f14..f436361e 100644 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/CreateAccountActivity.kt +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/CreateAccountScreen.kt @@ -1,25 +1,31 @@ -package com.example.walletapp.ui.activity +package com.example.walletapp.ui.onboarding import android.app.Activity import android.content.Intent -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.core.graphics.toColorInt +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.Icon +import androidx.compose.material.LinearProgressIndicator import androidx.compose.material.OutlinedTextField +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.material.TextFieldDefaults +import androidx.compose.material.TopAppBar import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowForward @@ -27,103 +33,105 @@ import androidx.compose.material.icons.filled.Refresh import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.SheetState -import androidx.compose.runtime.mutableStateOf +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.graphics.toColorInt import com.example.walletapp.R -import com.example.walletapp.ui.theme.WalletappTheme import kotlinx.coroutines.CoroutineScope -class CreateAccountActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContent { - WalletappTheme { - var progress by remember { mutableStateOf(0.5f) } - Scaffold( - topBar = { - TopAppBar( - backgroundColor = Color("#0C0C4F".toColorInt()), - contentColor = Color.White, - elevation = 4.dp - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(top = 32.dp, start = 16.dp, end = 16.dp), - - ) { - Icon( - imageVector = Icons.Filled.ArrowBack, - contentDescription = "Backward Arrow", - modifier = Modifier.padding(start = 8.dp), - tint = Color.White - ) - - Box( - modifier = Modifier.fillMaxWidth(), - contentAlignment = Alignment.Center, - ) { - - Text( - text = "Create Account", - color = Color.White, - fontSize = 20.sp - ) - - } - - } - } - } - ) { paddingValues -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - .background(color = Color("#0C0C4F".toColorInt())) - .padding(top = 30.dp, start = 16.dp, end = 16.dp ) +@Composable +fun CreateAccountScreen( + onContinue: () -> Unit +) { + var progress by remember { mutableStateOf(0.5f) } + Scaffold( + topBar = { + TopAppBar( + backgroundColor = Color("#0C0C4F".toColorInt()), + contentColor = Color.White, + elevation = 4.dp + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 32.dp, start = 16.dp, end = 16.dp), + + ) { + Icon( + imageVector = Icons.Filled.ArrowBack, + contentDescription = "Backward Arrow", + modifier = Modifier.padding(start = 8.dp), + tint = Color.White + ) + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center, ) { Text( - text = if (progress < 1.0f) "1 of 2" else "2 of 2", - style = TextStyle(color = Color("#EC796B".toColorInt()), fontWeight = FontWeight.ExtraBold, fontSize = 16.sp, textAlign = TextAlign.Center ) - + text = "Create Account", + color = Color.White, + fontSize = 20.sp ) - Spacer(modifier = Modifier.height(5.dp)) - LinearProgressIndicator( - progress = progress, - modifier = Modifier.fillMaxWidth(), - color = Color("#EC796B".toColorInt()) + } + + } + } + } + ) { paddingValues -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + .background(color = Color("#0C0C4F".toColorInt())) + .padding(top = 30.dp, start = 16.dp, end = 16.dp ) + + ) { + + Text( + text = if (progress < 1.0f) "1 of 2" else "2 of 2", + style = TextStyle(color = Color("#EC796B".toColorInt()), fontWeight = FontWeight.ExtraBold, fontSize = 16.sp, textAlign = TextAlign.Center ) + ) - ) + Spacer(modifier = Modifier.height(5.dp)) + LinearProgressIndicator( + progress = progress, + modifier = Modifier.fillMaxWidth(), + color = Color("#EC796B".toColorInt()) - if (progress < 1.0f) { - CreateWallet( - modifier = Modifier.padding(top = 16.dp), - onNext = { - progress = 1.0f - } - ) - } else { - GenerateKey(modifier = Modifier.padding(top = 16.dp)) - } + ) + if (progress < 1.0f) { + CreateWallet( + modifier = Modifier.padding(top = 16.dp), + onNext = { + progress = 1.0f } - } + ) + } else { + GenerateKey(modifier = Modifier.padding(top = 16.dp), onContinue) } + + } } } @@ -169,11 +177,11 @@ fun CreateWallet(modifier: Modifier = Modifier, onNext: () -> Unit) { ) ) - }, + }, modifier = Modifier .fillMaxWidth() .background(Color.Transparent) - , + , shape = RoundedCornerShape(8.dp), colors = TextFieldDefaults.outlinedTextFieldColors( backgroundColor = Color(0xFF1B1B76), @@ -213,7 +221,7 @@ fun CreateWallet(modifier: Modifier = Modifier, onNext: () -> Unit) { @OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class) @Composable -fun GenerateKey(modifier: Modifier = Modifier) { +fun GenerateKey(modifier: Modifier = Modifier, onContinue: () -> Unit) { val scope = rememberCoroutineScope() var openBottomSheet by remember { mutableStateOf(false) } val sheetState = rememberModalBottomSheetState() @@ -277,7 +285,8 @@ fun GenerateKey(modifier: Modifier = Modifier) { openBottomSheet = openBottomSheet, onDismissRequest = { openBottomSheet = false }, sheetState = sheetState, - scope = scope + scope = scope, + onContinue = onContinue ) } @@ -292,8 +301,9 @@ fun GenerateKey(modifier: Modifier = Modifier) { fun GeneratekeySheet( openBottomSheet: Boolean, onDismissRequest: () -> Unit, - sheetState: SheetState , - scope: CoroutineScope + sheetState: SheetState, + scope: CoroutineScope, + onContinue: () -> Unit ) { val context = (LocalContext.current as Activity) @@ -305,7 +315,7 @@ fun GeneratekeySheet( containerColor = Color("#141462".toColorInt()), modifier= Modifier.height(364.dp), - ) { + ) { Column( horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, @@ -314,7 +324,7 @@ fun GeneratekeySheet( .background(color = Color("#141462".toColorInt())) ) { - Text( text = "Generating private key", style = TextStyle(fontWeight = FontWeight.ExtraBold, fontSize = 25.sp, textAlign = TextAlign.Center, color = Color.White)) + Text( text = "Generating private key", style = TextStyle(fontWeight = FontWeight.ExtraBold, fontSize = 25.sp, textAlign = TextAlign.Center, color = Color.White)) Spacer(modifier = Modifier.height(8.dp)) Text( text = "Private key generated successfully", style = TextStyle(fontWeight = FontWeight.Medium, fontSize = 16.sp, textAlign = TextAlign.Center, color = Color("#8D8DBB".toColorInt()))) @@ -331,8 +341,7 @@ fun GeneratekeySheet( Spacer(modifier = Modifier.height(40.dp)) Button( - onClick = { val i = Intent(context, AccountInfoActivity::class.java) - context.startActivity(i) }, + onClick = onContinue, contentPadding = ButtonDefaults.ContentPadding, shape = RoundedCornerShape(8.dp), colors = ButtonDefaults.buttonColors(backgroundColor = Color("#EC796B".toColorInt()), contentColor = Color.White), diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/CreatePinActivity.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/CreatePinScreen.kt similarity index 55% rename from wallet_app/android/app/src/main/java/com/example/walletapp/CreatePinActivity.kt rename to wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/CreatePinScreen.kt index bf262705..1e9e6857 100644 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/CreatePinActivity.kt +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/CreatePinScreen.kt @@ -1,11 +1,6 @@ -package com.example.walletapp +package com.example.walletapp.ui.onboarding import android.app.Activity -import android.content.Intent -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.Image import androidx.compose.foundation.background @@ -33,138 +28,127 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.graphics.toColorInt -import com.example.walletapp.ui.activity.AccountInfoActivity -import com.example.walletapp.ui.theme.WalletappTheme +import com.example.walletapp.R import kotlinx.coroutines.launch import kotlinx.coroutines.delay -class CreatePinActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContent { - WalletappTheme { - Surface( - modifier = Modifier.fillMaxSize() - .background(Color("#0C0C4F".toColorInt())) - .padding(20.dp) - - - ) { - CreatePinView( - modifier = Modifier - ) - } - } - } - - } -} - @Composable -fun CreatePinView(modifier: Modifier = Modifier) { +fun CreatePinScreen(onContinue: () -> Unit) { val context = (LocalContext.current as Activity) var passcode by remember { mutableStateOf("") } var hiddenPasscode by remember { mutableStateOf("") } val maxDigits = 6 val coroutineScope = rememberCoroutineScope() - Column ( - horizontalAlignment = Alignment.CenterHorizontally, - modifier = Modifier - .background(Color("#0C0C4F".toColorInt())) - .padding(top = 70.dp) + Surface(modifier = Modifier.fillMaxSize()) { - ) { - Row( - modifier = Modifier.fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.Center - ){ - Image( - painter = painterResource(id = R.drawable.starknet_icon), - contentDescription = "starknet", - modifier = Modifier - .size(36.dp) - ) + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .background(Color("#0C0C4F".toColorInt())) + .padding(top = 70.dp) - Spacer(modifier = Modifier.width(10.dp)) + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.Center + ) { + Image( + painter = painterResource(id = R.drawable.starknet_icon), + contentDescription = "starknet", + modifier = Modifier + .size(36.dp) + ) - Text(text = "Starknet Wallet", style = TextStyle(color = Color.White, fontSize = 25.sp, - fontWeight = FontWeight.Medium)) - } + Spacer(modifier = Modifier.width(10.dp)) + Text( + text = "Starknet Wallet", style = TextStyle( + color = Color.White, fontSize = 25.sp, + fontWeight = FontWeight.Medium + ) + ) + } - Spacer(modifier = Modifier.height(93.dp)) + Spacer(modifier = Modifier.height(93.dp)) - Text(text = "Create PIN-code", style = TextStyle(color = Color.White, fontSize = 25.sp, - fontWeight = FontWeight.Medium)) - Spacer(modifier = Modifier.height(5.dp)) - Text(text = "6 characters", style = TextStyle(color = Color("#A3A3C1".toColorInt()), fontSize = 13.sp, - fontWeight = FontWeight.Medium)) + Text( + text = "Create PIN-code", style = TextStyle( + color = Color.White, fontSize = 25.sp, + fontWeight = FontWeight.Medium + ) + ) + Spacer(modifier = Modifier.height(5.dp)) + Text( + text = "6 characters", style = TextStyle( + color = Color("#A3A3C1".toColorInt()), fontSize = 13.sp, + fontWeight = FontWeight.Medium + ) + ) - Spacer(modifier = Modifier.height(31.dp)) - PasscodeCircles(passcode, hiddenPasscode, maxDigits) - Spacer(modifier = Modifier.height(48.dp)) + Spacer(modifier = Modifier.height(31.dp)) + PasscodeCircles(passcode, hiddenPasscode, maxDigits) - NumericKeypad(onDigitClick = { digit -> - if (passcode.length < maxDigits) { - passcode += digit - hiddenPasscode += digit - coroutineScope.launch { - delay(500L) - hiddenPasscode = hiddenPasscode.dropLast(1) + "*" + Spacer(modifier = Modifier.height(48.dp)) + + NumericKeypad(onDigitClick = { digit -> + if (passcode.length < maxDigits) { + passcode += digit + hiddenPasscode += digit + coroutineScope.launch { + delay(500L) + hiddenPasscode = hiddenPasscode.dropLast(1) + "*" + } } - } - }, onDeleteClick = { - if (passcode.isNotEmpty()) { - passcode = passcode.dropLast(1) - hiddenPasscode = hiddenPasscode.dropLast(1) - } - }) + }, onDeleteClick = { + if (passcode.isNotEmpty()) { + passcode = passcode.dropLast(1) + hiddenPasscode = hiddenPasscode.dropLast(1) + } + }) - Spacer(modifier = Modifier.height(102.dp)) + Spacer(modifier = Modifier.height(102.dp)) - Button( - onClick = { val i = Intent(context, WalletActivity::class.java) - context.startActivity(i) }, - contentPadding = ButtonDefaults.ContentPadding, - shape = RoundedCornerShape(8.dp), - colors = ButtonDefaults.buttonColors(backgroundColor = Color("#EC796B".toColorInt()), contentColor = Color.White), - modifier = Modifier - .fillMaxWidth() - .height(49.dp) - ) { - Row( - verticalAlignment = Alignment.CenterVertically + Button( + onClick = onContinue, + contentPadding = ButtonDefaults.ContentPadding, + shape = RoundedCornerShape(8.dp), + colors = ButtonDefaults.buttonColors( + backgroundColor = Color("#EC796B".toColorInt()), + contentColor = Color.White + ), + modifier = Modifier + .fillMaxWidth() + .height(49.dp) ) { - Text("Continue") - Icon( - imageVector = Icons.Filled.ArrowForward, - contentDescription = "Forward Arrow", - modifier = Modifier.padding(start = 8.dp), - tint = Color.White - ) + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Text("Continue") + Icon( + imageVector = Icons.Filled.ArrowForward, + contentDescription = "Forward Arrow", + modifier = Modifier.padding(start = 8.dp), + tint = Color.White + ) + } } + } } - - - - - } @@ -256,10 +240,3 @@ fun KeypadButton(text: String, onClick: () -> Unit) { ) } } - - - - - - - diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/AccountInfoActivity.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/FinalizeAccountCreationScreen.kt similarity index 77% rename from wallet_app/android/app/src/main/java/com/example/walletapp/AccountInfoActivity.kt rename to wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/FinalizeAccountCreationScreen.kt index 3a5561a9..7cca9059 100644 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/AccountInfoActivity.kt +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/FinalizeAccountCreationScreen.kt @@ -1,11 +1,6 @@ package com.example.walletapp.ui.activity import android.app.Activity -import android.content.Intent -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.border @@ -29,81 +24,68 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight -import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.graphics.toColorInt -import com.example.walletapp.CreatePinActivity -import com.example.walletapp.ImportExistingKeyActivity import com.example.walletapp.R -import com.example.walletapp.ui.theme.WalletappTheme -import org.bouncycastle.math.raw.Mod - -class AccountInfoActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContent { - WalletappTheme { - Scaffold( - topBar = { - TopAppBar( - backgroundColor = Color("#0C0C4F".toColorInt()), - contentColor = Color.White, - elevation = 4.dp - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(top = 32.dp, start = 16.dp, end = 16.dp), - - ) { - Icon( - imageVector = Icons.Filled.ArrowBack, - contentDescription = "Backward Arrow", - modifier = Modifier.padding(start = 8.dp), - tint = Color.White - ) - Box( - modifier = Modifier.fillMaxWidth(), - contentAlignment = Alignment.Center, - ) { - - Text( - text = "Create Account", - color = Color.White, - fontSize = 20.sp - ) - - } - - } - } - } - ) { paddingValues -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - .background(color = Color("#0C0C4F".toColorInt())) - .padding(top = 50.dp, start = 16.dp, end = 16.dp ) - ) { +@Composable +fun FinalizeAccountCreationScreen(onContinue: () -> Unit) { + Scaffold( + topBar = { + TopAppBar( + backgroundColor = Color("#0C0C4F".toColorInt()), + contentColor = Color.White, + elevation = 4.dp + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 32.dp, start = 16.dp, end = 16.dp), - Spacer(modifier = Modifier.height(5.dp)) - AccountInfoView() + ) { + Icon( + imageVector = Icons.Filled.ArrowBack, + contentDescription = "Backward Arrow", + modifier = Modifier.padding(start = 8.dp), + tint = Color.White + ) + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center, + ) { + Text( + text = "Create Account", + color = Color.White, + fontSize = 20.sp + ) } + } } + } + ) { paddingValues -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + .background(color = Color("#0C0C4F".toColorInt())) + .padding(top = 50.dp, start = 16.dp, end = 16.dp ) + + ) { + + Spacer(modifier = Modifier.height(5.dp)) + AccountInfoView(onContinue) + } } } @Composable -fun AccountInfoView() { +fun AccountInfoView(onContinue: () -> Unit) { val context = (LocalContext.current as Activity) @@ -232,8 +214,7 @@ fun AccountInfoView() { Button( - onClick = { val i = Intent(context, ImportExistingKeyActivity::class.java) - context.startActivity(i) }, + onClick = { /* TOOD */ }, colors = ButtonDefaults.buttonColors(backgroundColor = Color("#1B1B76".toColorInt()), contentColor = Color.White), modifier = Modifier.fillMaxWidth() .background(color = Color("#1B1B76".toColorInt())) @@ -326,8 +307,7 @@ fun AccountInfoView() { Button( - onClick = { val i = Intent(context, CreatePinActivity::class.java) - context.startActivity(i) }, + onClick = onContinue, contentPadding = ButtonDefaults.ContentPadding, shape = RoundedCornerShape(8.dp), colors = ButtonDefaults.buttonColors(backgroundColor = Color("#EC796B".toColorInt()), contentColor = Color.White), diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/ImportExistingKeyActivity.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/ImportAccountScreen.kt similarity index 54% rename from wallet_app/android/app/src/main/java/com/example/walletapp/ImportExistingKeyActivity.kt rename to wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/ImportAccountScreen.kt index f3c05512..287bfe07 100644 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/ImportExistingKeyActivity.kt +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/ImportAccountScreen.kt @@ -1,127 +1,134 @@ -package com.example.walletapp +package com.example.walletapp.ui.onboarding + import android.app.Activity import android.content.Intent -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.Image import androidx.compose.foundation.background -import androidx.compose.foundation.layout.* +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.layout.width import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.* -import androidx.compose.runtime.Composable -import androidx.compose.runtime.remember -import androidx.compose.ui.Alignment -import androidx.compose.ui.Modifier -import androidx.compose.ui.graphics.Color -import androidx.compose.ui.unit.dp -import androidx.compose.ui.unit.sp -import androidx.core.graphics.toColorInt +import androidx.compose.material.Button +import androidx.compose.material.ButtonDefaults +import androidx.compose.material.ExperimentalMaterialApi +import androidx.compose.material.Icon +import androidx.compose.material.LinearProgressIndicator import androidx.compose.material.OutlinedTextField +import androidx.compose.material.Scaffold +import androidx.compose.material.Text +import androidx.compose.material.TextFieldDefaults +import androidx.compose.material.TopAppBar import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material.icons.filled.ArrowForward import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.SheetState -import androidx.compose.runtime.mutableStateOf +import androidx.compose.material3.rememberModalBottomSheetState +import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope -import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.graphics.toColorInt import com.example.walletapp.R -import com.example.walletapp.ui.theme.WalletappTheme import kotlinx.coroutines.CoroutineScope -class ImportExistingKeyActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - setContent { - WalletappTheme { - var progress by remember { mutableStateOf(0.5f) } - Scaffold( - topBar = { - TopAppBar( - backgroundColor = Color("#0C0C4F".toColorInt()), - contentColor = Color.White, - elevation = 4.dp - ) { - Row( - modifier = Modifier - .fillMaxWidth() - .padding(top = 32.dp, start = 16.dp, end = 16.dp), - - ) { - Icon( - imageVector = Icons.Filled.ArrowBack, - contentDescription = "Backward Arrow", - modifier = Modifier.padding(start = 8.dp), - tint = Color.White - ) - - Box( - modifier = Modifier.fillMaxWidth(), - contentAlignment = Alignment.Center, - ) { - - Text( - text = "Import existing wallet", - color = Color.White, - fontSize = 20.sp - ) - - } - - } - } - } - ) { paddingValues -> - Column( - modifier = Modifier - .fillMaxSize() - .padding(paddingValues) - .background(color = Color("#0C0C4F".toColorInt())) - .padding(top = 30.dp, start = 16.dp, end = 16.dp ) +@Composable +fun ImportAccountScreen( onFinishAccountImport: () -> Unit) { + var progress by remember { mutableStateOf(0.5f) } + Scaffold( + topBar = { + TopAppBar( + backgroundColor = Color("#0C0C4F".toColorInt()), + contentColor = Color.White, + elevation = 4.dp + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .padding(top = 32.dp, start = 16.dp, end = 16.dp), ) { + Icon( + imageVector = Icons.Filled.ArrowBack, + contentDescription = "Backward Arrow", + modifier = Modifier.padding(start = 8.dp), + tint = Color.White + ) - Text( - text = if (progress < 1.0f) "1 of 2" else "2 of 2", - style = TextStyle(color = Color("#EC796B".toColorInt()), fontWeight = FontWeight.ExtraBold, fontSize = 16.sp, textAlign = TextAlign.Center ) + Box( + modifier = Modifier.fillMaxWidth(), + contentAlignment = Alignment.Center, + ) { + Text( + text = "Import existing wallet", + color = Color.White, + fontSize = 20.sp ) - Spacer(modifier = Modifier.height(5.dp)) - LinearProgressIndicator( - progress = progress, - modifier = Modifier.fillMaxWidth(), - color = Color("#EC796B".toColorInt()) + } + + } + } + } + ) { paddingValues -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + .background(color = Color("#0C0C4F".toColorInt())) + .padding(top = 30.dp, start = 16.dp, end = 16.dp ) + ) { - ) + Text( + text = if (progress < 1.0f) "1 of 2" else "2 of 2", + style = TextStyle(color = Color("#EC796B".toColorInt()), fontWeight = FontWeight.ExtraBold, fontSize = 16.sp, textAlign = TextAlign.Center ) + + ) + + Spacer(modifier = Modifier.height(5.dp)) + LinearProgressIndicator( + progress = progress, + modifier = Modifier.fillMaxWidth(), + color = Color("#EC796B".toColorInt()) - if (progress < 1.0f) { - PrivateKeyView( - modifier = Modifier.padding(top = 16.dp), - onNext = { - progress = 1.0f - } - ) - } else { - CreateNameView(modifier = Modifier.padding(top = 16.dp)) - } + ) + if (progress < 1.0f) { + PrivateKeyView( + modifier = Modifier.padding(top = 16.dp), + onNext = { + progress = 1.0f } - } + ) + } else { + CreateNameView(modifier = Modifier.padding(top = 16.dp), onFinishAccountImport) } + + } } } @@ -186,7 +193,7 @@ fun PrivateKeyView(modifier: Modifier = Modifier, onNext: () -> Unit) { Spacer(modifier = Modifier.weight(1f)) Button( - onClick = { openBottomSheet = true }, + onClick = onNext, contentPadding = ButtonDefaults.ContentPadding, shape = RoundedCornerShape(8.dp), colors = ButtonDefaults.buttonColors(backgroundColor = Color("#EC796B".toColorInt()), contentColor = Color.White), @@ -205,20 +212,7 @@ fun PrivateKeyView(modifier: Modifier = Modifier, onNext: () -> Unit) { } } - Spacer(modifier = Modifier.height(20.dp)) - - - - if (openBottomSheet) { - ConfirmSheet( - onNext = onNext, - openBottomSheet = openBottomSheet, - onDismissRequest = { openBottomSheet = false }, - sheetState = sheetState, - scope = scope - ) - } } } @@ -226,7 +220,7 @@ fun PrivateKeyView(modifier: Modifier = Modifier, onNext: () -> Unit) { @OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class) @Composable -fun CreateNameView(modifier: Modifier = Modifier) { +fun CreateNameView(modifier: Modifier = Modifier, onFinishAccountImport: () -> Unit) { val borderColor = Color("#1B1B76".toColorInt()) var accountName by remember { mutableStateOf("") } val context = (LocalContext.current as Activity) @@ -281,9 +275,8 @@ fun CreateNameView(modifier: Modifier = Modifier) { Spacer(modifier = Modifier.weight(1f)) Button( - onClick = { val i = Intent(context, CreatePinActivity::class.java) - context.startActivity(i) }, - contentPadding = ButtonDefaults.ContentPadding, + onClick = onFinishAccountImport, + contentPadding = ButtonDefaults.ContentPadding, shape = RoundedCornerShape(8.dp), colors = ButtonDefaults.buttonColors( backgroundColor = Color("#EC796B".toColorInt()), @@ -317,64 +310,3 @@ fun CreateNameView(modifier: Modifier = Modifier) { } -@OptIn(ExperimentalMaterialApi::class, ExperimentalMaterial3Api::class) -@Composable -fun ConfirmSheet( - onNext: () -> Unit, - openBottomSheet: Boolean, - onDismissRequest: () -> Unit, - sheetState: SheetState , - scope: CoroutineScope -) { - - if (openBottomSheet) { - ModalBottomSheet( - onDismissRequest = onDismissRequest, - sheetState = sheetState, - containerColor = Color("#141462".toColorInt()), - modifier= Modifier.height(364.dp), - - ) { - Column( - horizontalAlignment = Alignment.CenterHorizontally, - verticalArrangement = Arrangement.Center, - modifier = Modifier - .padding(16.dp) - .background(color = Color("#141462".toColorInt())) - ) { - - Text( text = "Generating private key", style = TextStyle(fontWeight = FontWeight.ExtraBold, fontSize = 25.sp, textAlign = TextAlign.Center, color = Color.White)) - Spacer(modifier = Modifier.height(8.dp)) - Text( text = "Private key generated successfully", style = TextStyle(fontWeight = FontWeight.Medium, fontSize = 16.sp, textAlign = TextAlign.Center, color = Color("#8D8DBB".toColorInt()))) - - Spacer(modifier = Modifier.height(30.dp)) - - Image( - painter = painterResource(id = R.drawable.approved), - contentDescription = "QR Code", - modifier = Modifier - .size(93.dp) - - ) - - Spacer(modifier = Modifier.height(40.dp)) - - Button( - onClick = { onNext() }, - contentPadding = ButtonDefaults.ContentPadding, - shape = RoundedCornerShape(8.dp), - colors = ButtonDefaults.buttonColors(backgroundColor = Color("#EC796B".toColorInt()), contentColor = Color.White), - modifier = Modifier - .fillMaxWidth() - .height(49.dp) - ) { - Text(text = "Continue") - } - - } - } - } - - -} - diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/OnboardingScreen.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/OnboardingScreen.kt new file mode 100644 index 00000000..76590e65 --- /dev/null +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/onboarding/OnboardingScreen.kt @@ -0,0 +1,92 @@ +package com.example.walletapp.ui.onboarding + +.border + +import android.app.Activity +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.font.Font +import androidx.compose.ui.text.font.FontFamily +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.core.graphics.toColorInt +import com.example.walletapp.R +import com.example.walletapp.ui.components.StarknetLogo +import com.example.walletapp.ui.components.TransparentButton +import com.example.walletapp.ui.theme.WalletappTheme +import com.example.walletapp.ui.theme.WhiteFlare + + +@Composable +fun OnboardingScreen ( + onNavigateCreateAccount: () -> Unit, + onNavigateImportAccount: () -> Unit +) { + Column( + modifier = Modifier + .fillMaxSize() + .background(Color("#0C0C4F".toColorInt())) + .padding(20.dp) + ) { + Text( + text = "Get Started", + fontFamily = FontFamily(Font(R.font.inter_regular)), + fontSize = 28.sp, + color = WhiteFlare, + modifier = Modifier + .align(Alignment.CenterHorizontally) + .padding(top = 70.dp) + ) + Spacer(modifier = Modifier.height(50.dp)) + StarknetLogo( + modifier = Modifier.align(Alignment.CenterHorizontally) + ) + Spacer(modifier = Modifier.weight(1f)) + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(8.dp) // Adjust space between buttons + ) { + TransparentButton( + label = "Create a New Account", + onClick = onNavigateCreateAccount + ) + + Spacer(modifier = Modifier.height(10.dp)) + + TransparentButton( + label = "Import Existing Account", + onClick = onNavigateImportAccount + ) + Spacer(modifier = Modifier.height(10.dp)) + } + + Spacer(modifier = Modifier.height(15.dp)) + } +} + +@Composable +@Preview +fun PreviewOnboardingScreen() { + WalletappTheme { + Surface { + OnboardingScreen( + onNavigateCreateAccount = { println("create new account pressed") }, + onNavigateImportAccount = { println("import existing account pressed")} + ) + } + } +} + diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/ui/theme/Color.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/theme/Color.kt new file mode 100644 index 00000000..a6ec3a87 --- /dev/null +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/theme/Color.kt @@ -0,0 +1,19 @@ +package com.example.walletapp.ui.theme + +import android.graphics.drawable.GradientDrawable +import android.graphics.drawable.GradientDrawable.Orientation +import androidx.compose.ui.graphics.Color + +val Purple80 = Color(0xFFD0BCFF) +val PurpleGrey80 = Color(0xFFCCC2DC) +val Pink80 = Color(0xFFEFB8C8) +val StarknetBlue = Color(0xFF0C0C4F) + +val Purple40 = Color(0xFF6650a4) +val PurpleGrey40 = Color(0xFF625b71) +val Pink40 = Color(0xFF7D5260) + + +// from starknet brand resources: https://www.starknet.io/media-kit/ +val InfiniteBlue = Color(0xFF0C0C4F) +val WhiteFlare = Color(0xFFFBFBFB) \ No newline at end of file diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/theme/Theme.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/theme/Theme.kt similarity index 68% rename from wallet_app/android/app/src/main/java/com/example/walletapp/theme/Theme.kt rename to wallet_app/android/app/src/main/java/com/example/walletapp/ui/theme/Theme.kt index 48b76479..4477e895 100644 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/theme/Theme.kt +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/theme/Theme.kt @@ -1,26 +1,24 @@ package com.example.walletapp.ui.theme -import android.app.Activity -import android.os.Build -import androidx.compose.foundation.isSystemInDarkTheme import androidx.compose.material3.MaterialTheme import androidx.compose.material3.darkColorScheme -import androidx.compose.material3.dynamicDarkColorScheme -import androidx.compose.material3.dynamicLightColorScheme -import androidx.compose.material3.lightColorScheme import androidx.compose.runtime.Composable -import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.graphics.Color private val DarkColorScheme = darkColorScheme( primary = Purple80, secondary = PurpleGrey80, - tertiary = Pink80 + tertiary = Pink80, + background = StarknetBlue, + surface = Color.Black, + outline = WhiteFlare ) +/* private val LightColorScheme = lightColorScheme( primary = Purple40, secondary = PurpleGrey40, - tertiary = Pink40 + tertiary = Pink40, /* Other default colors to override background = Color(0xFFFFFBFE), @@ -32,14 +30,15 @@ private val LightColorScheme = lightColorScheme( onSurface = Color(0xFF1C1B1F), */ ) + */ @Composable fun WalletappTheme( - darkTheme: Boolean = isSystemInDarkTheme(), - // Dynamic color is available on Android 12+ - dynamicColor: Boolean = true, content: @Composable () -> Unit ) { + + // TODO: support dynamic cclor themes + /* val colorScheme = when { dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { val context = LocalContext.current @@ -49,9 +48,10 @@ fun WalletappTheme( darkTheme -> DarkColorScheme else -> LightColorScheme } + */ MaterialTheme( - colorScheme = colorScheme, + colorScheme = DarkColorScheme, typography = Typography, content = content ) diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/theme/Type.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/theme/Type.kt similarity index 100% rename from wallet_app/android/app/src/main/java/com/example/walletapp/theme/Type.kt rename to wallet_app/android/app/src/main/java/com/example/walletapp/ui/theme/Type.kt diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/ReceiverActivity.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/transfer/ReceiveScreen.kt similarity index 68% rename from wallet_app/android/app/src/main/java/com/example/walletapp/ReceiverActivity.kt rename to wallet_app/android/app/src/main/java/com/example/walletapp/ui/transfer/ReceiveScreen.kt index 6834b00a..7dc8189c 100644 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/ReceiverActivity.kt +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/transfer/ReceiveScreen.kt @@ -1,12 +1,6 @@ -package com.example.walletapp +package com.example.walletapp.ui.transfer import android.content.ClipData -import android.content.ClipboardManager -import android.content.Context -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.clickable @@ -24,33 +18,22 @@ import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.ClipEntry +import androidx.compose.ui.platform.ClipboardManager +import androidx.compose.ui.platform.LocalClipboardManager import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.graphics.toColorInt -import androidx.core.view.WindowCompat -import com.example.walletapp.ui.theme.WalletappTheme +import com.example.walletapp.R -class ReceiverActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - WindowCompat.setDecorFitsSystemWindows(window, true) - setContent { - WalletappTheme { - Surface(modifier = Modifier.fillMaxSize()) { - ReceiverScreenView( - modifier = Modifier.padding(10.dp) - ) - } - } - } - } +@Composable +fun ReceiveScreen(modifier: Modifier) { + val clipboard: ClipboardManager = LocalClipboardManager.current - @Composable - fun ReceiverScreenView(modifier: Modifier){ + Surface(modifier = Modifier.fillMaxSize()) { Column( modifier = Modifier .fillMaxSize() @@ -91,12 +74,11 @@ class ReceiverActivity : ComponentActivity() { color = Color.White, fontSize = 15.sp, modifier = Modifier.clickable { - val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - val clip = ClipData.newPlainText("Wallet Address", "0xfoo...123") // Replace with actual wallet address - clipboard.setPrimaryClip(clip) + val clip = ClipEntry(ClipData.newPlainText("Wallet Address", "0xfoo...123")) // TODO: Replace with actual wallet address + clipboard.setClip(clip) } ) } - } + } \ No newline at end of file diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/SendActivity.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/transfer/SendScreen.kt similarity index 84% rename from wallet_app/android/app/src/main/java/com/example/walletapp/SendActivity.kt rename to wallet_app/android/app/src/main/java/com/example/walletapp/ui/transfer/SendScreen.kt index 9a205691..1a011aae 100644 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/SendActivity.kt +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/ui/transfer/SendScreen.kt @@ -1,9 +1,5 @@ -package com.example.walletapp +package com.example.walletapp.ui.transfer -import android.os.Bundle -import androidx.activity.ComponentActivity -import androidx.activity.compose.setContent -import androidx.activity.enableEdgeToEdge import androidx.compose.foundation.Image import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement @@ -42,27 +38,11 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.sp import androidx.core.graphics.toColorInt -import androidx.core.view.WindowCompat -import com.example.walletapp.ui.theme.WalletappTheme +import com.example.walletapp.R -class SendActivity : ComponentActivity() { - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - enableEdgeToEdge() - WindowCompat.setDecorFitsSystemWindows(window, true) - setContent { - WalletappTheme { - Surface(modifier = Modifier.fillMaxSize()) { - SendScreenView( - modifier = Modifier.padding(10.dp) - ) - } - } - } - } - - @Composable - fun SendScreenView(modifier: Modifier){ +@Composable +fun SendScreen() { + Surface(modifier = Modifier.fillMaxSize()) { /* TODO(34) send tokens */ var amount by rememberSaveable { @@ -142,6 +122,5 @@ class SendActivity : ComponentActivity() { Text(text = "Confirm", color = Color.White) } } - } } \ No newline at end of file diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/StarknetClient.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/utils/StarknetClient.kt similarity index 89% rename from wallet_app/android/app/src/main/java/com/example/walletapp/StarknetClient.kt rename to wallet_app/android/app/src/main/java/com/example/walletapp/utils/StarknetClient.kt index 13e22658..99eb1c4d 100644 --- a/wallet_app/android/app/src/main/java/com/example/walletapp/StarknetClient.kt +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/utils/StarknetClient.kt @@ -1,5 +1,6 @@ -package com.example.walletapp +package com.example.walletapp.utils +import com.example.walletapp.BuildConfig import com.swmansion.starknet.account.StandardAccount import com.swmansion.starknet.data.types.Call import com.swmansion.starknet.data.types.Felt @@ -15,7 +16,7 @@ class StarknetClient(private val rpcUrl: String) { private val provider = JsonRpcProvider(rpcUrl) private val privateKey= BuildConfig.PRIVATE_KEY - private val accountAddress=BuildConfig.ACCOUNT_ADDRESS + private val accountAddress= BuildConfig.ACCOUNT_ADDRESS suspend fun deployAccount() { @@ -69,8 +70,4 @@ class StarknetClient(private val rpcUrl: String) { // TODO(#24) } - fun weiToEther(wei: Uint256): BigDecimal { - val weiInEther = BigDecimal("1000000000000000000") // 10^18 - return BigDecimal(wei.value.toString()).divide(weiInEther) - } } diff --git a/wallet_app/android/app/src/main/java/com/example/walletapp/utils/WalletAppUtils.kt b/wallet_app/android/app/src/main/java/com/example/walletapp/utils/WalletAppUtils.kt new file mode 100644 index 00000000..b1fe16df --- /dev/null +++ b/wallet_app/android/app/src/main/java/com/example/walletapp/utils/WalletAppUtils.kt @@ -0,0 +1,21 @@ +package com.example.walletapp.utils + +import com.swmansion.starknet.data.types.Uint256 +import java.math.BigDecimal +import java.text.DecimalFormat + +// Function to format BigDecimal to Double with 2 decimal places +fun BigDecimal.toDoubleWithTwoDecimal(): String { + val decimalFormat = DecimalFormat("#.00") + return decimalFormat.format(this.toDouble()) +} +fun Double.toDoubleWithTwoDecimal(): String { + val decimalFormat = DecimalFormat("#.00") + val formattedValue = decimalFormat.format(this) + return if (this < 1) "0$formattedValue" else formattedValue +} + +fun weiToEther(wei: Uint256): BigDecimal { + val weiInEther = BigDecimal("1000000000000000000") // 10^18 + return BigDecimal(wei.value.toString()).divide(weiInEther) +} diff --git a/wallet_app/android/app/src/main/res/layout/activity_main.xml b/wallet_app/android/app/src/main/res/layout/activity_main.xml deleted file mode 100644 index 86a5d977..00000000 --- a/wallet_app/android/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/wallet_app/android/app/src/main/res/values/strings.xml b/wallet_app/android/app/src/main/res/values/strings.xml index deb31a5a..f0013b57 100644 --- a/wallet_app/android/app/src/main/res/values/strings.xml +++ b/wallet_app/android/app/src/main/res/values/strings.xml @@ -1,3 +1,5 @@ + + - walletapp + SNPhone Wallet App \ No newline at end of file diff --git a/wallet_app/android/gradle/libs.versions.toml b/wallet_app/android/gradle/libs.versions.toml index a6fa483c..3bbea0dd 100644 --- a/wallet_app/android/gradle/libs.versions.toml +++ b/wallet_app/android/gradle/libs.versions.toml @@ -1,6 +1,7 @@ [versions] activityCompose = "1.9.1" agp = "8.5.2" +common = "1.1.1" converterGson = "2.9.0" core = "4.8.7" hiltAndroid = "2.51" @@ -20,6 +21,11 @@ material = "1.12.0" activity = "1.9.1" constraintlayout = "2.1.4" navigationCompose = "2.7.7" +navigationComposeVersion = "2.8.3" +navigationDynamicFeaturesFragment = "2.8.3" +navigationFragment = "2.8.3" +navigationTesting = "2.8.3" +navigationUi = "2.8.3" retrofit = "2.9.0" [libraries] @@ -32,9 +38,15 @@ androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle- androidx-material = { module = "androidx.compose.material:material" } androidx-material3 = { module = "androidx.compose.material3:material3" } androidx-navigation-compose = { module = "androidx.navigation:navigation-compose", version.ref = "navigationCompose" } +androidx-navigation-compose-v283 = { module = "androidx.navigation:navigation-compose", version.ref = "navigationComposeVersion" } +androidx-navigation-dynamic-features-fragment = { module = "androidx.navigation:navigation-dynamic-features-fragment", version.ref = "navigationDynamicFeaturesFragment" } +androidx-navigation-fragment = { module = "androidx.navigation:navigation-fragment", version.ref = "navigationFragment" } +androidx-navigation-testing = { module = "androidx.navigation:navigation-testing", version.ref = "navigationTesting" } +androidx-navigation-ui = { module = "androidx.navigation:navigation-ui", version.ref = "navigationUi" } androidx-runtime-livedata = { module = "androidx.compose.runtime:runtime-livedata" } androidx-ui-tooling = { module = "androidx.compose.ui:ui-tooling" } androidx-ui-tooling-preview = { module = "androidx.compose.ui:ui-tooling-preview" } +common = { module = "android.arch.lifecycle:common", version.ref = "common" } converter-gson = { module = "com.squareup.retrofit2:converter-gson", version.ref = "converterGson" } core = { module = "org.web3j:core", version.ref = "core" } hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hiltAndroid" }