From f9761a490be0134768ff987db955b2d2bc4ee81a Mon Sep 17 00:00:00 2001 From: droid-mon Date: Mon, 4 Dec 2023 11:01:08 +0530 Subject: [PATCH 001/382] new design revamp theme setup and landing page design --- app/build.gradle | 2 +- app/buildGradle/dependencies.gradle | 30 +- app/src/main/AndroidManifest.xml | 23 +- .../securesms/compose_temp/ColorTest.kt | 156 +++++++++++ .../securesms/compose_utils/Colors.kt | 89 +++++- .../compose_utils/CommonComponents.kt | 168 +++++++++++ .../compose_utils/MultilineTextField.kt | 40 +++ .../securesms/compose_utils/PinCodeView.kt | 83 ++++++ .../securesms/compose_utils/Theme.kt | 66 +++-- .../securesms/compose_utils/Typography.kt | 63 +++++ .../securesms/home/HomeActivityNew.kt | 9 + .../onboarding/LandingScreenActivity.kt | 261 ++++++++++++++++++ .../onboarding/ui/OnBoardingActivity.kt | 191 +++++++++++++ .../onboarding/ui/OnBoardingScreens.kt | 9 + .../securesms/onboarding/ui/PinCodeScreen.kt | 232 ++++++++++++++++ .../onboarding/ui/RestoreFromSeedScreen.kt | 199 +++++++++++++ .../onboarding/ui/RestoreSeedScreen.kt | 159 +++++++++++ .../main/res/drawable/ic_arrow_forward.xml | 12 +- app/src/main/res/drawable/ic_bchat_2.xml | 11 + app/src/main/res/drawable/ic_calendar.xml | 31 +++ .../main/res/drawable/ic_landing_bubble.xml | 26 ++ app/src/main/res/drawable/ic_password.xml | 67 +++++ app/src/main/res/drawable/ic_password_1.xml | 67 +++++ app/src/main/res/values/strings.xml | 1 + gradle.properties | 6 +- 25 files changed, 1943 insertions(+), 58 deletions(-) create mode 100644 app/src/main/java/com/thoughtcrimes/securesms/compose_temp/ColorTest.kt create mode 100644 app/src/main/java/com/thoughtcrimes/securesms/compose_utils/CommonComponents.kt create mode 100644 app/src/main/java/com/thoughtcrimes/securesms/compose_utils/MultilineTextField.kt create mode 100644 app/src/main/java/com/thoughtcrimes/securesms/compose_utils/PinCodeView.kt create mode 100644 app/src/main/java/com/thoughtcrimes/securesms/home/HomeActivityNew.kt create mode 100644 app/src/main/java/com/thoughtcrimes/securesms/onboarding/LandingScreenActivity.kt create mode 100644 app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/OnBoardingActivity.kt create mode 100644 app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/OnBoardingScreens.kt create mode 100644 app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/PinCodeScreen.kt create mode 100644 app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/RestoreFromSeedScreen.kt create mode 100644 app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/RestoreSeedScreen.kt create mode 100644 app/src/main/res/drawable/ic_bchat_2.xml create mode 100644 app/src/main/res/drawable/ic_calendar.xml create mode 100644 app/src/main/res/drawable/ic_landing_bubble.xml create mode 100644 app/src/main/res/drawable/ic_password.xml create mode 100644 app/src/main/res/drawable/ic_password_1.xml diff --git a/app/build.gradle b/app/build.gradle index 485ac7078..f61b36965 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -228,7 +228,7 @@ android { compose true } composeOptions { - kotlinCompilerExtensionVersion = "1.4.1" + kotlinCompilerExtensionVersion = "1.5.4" } externalNativeBuild { cmake { diff --git a/app/buildGradle/dependencies.gradle b/app/buildGradle/dependencies.gradle index 9494d82de..db8fa1c71 100644 --- a/app/buildGradle/dependencies.gradle +++ b/app/buildGradle/dependencies.gradle @@ -1,10 +1,10 @@ dependencies { - implementation 'androidx.appcompat:appcompat:$appcompatVersion' + implementation "androidx.appcompat:appcompat:$appcompatVersion" implementation 'androidx.recyclerview:recyclerview:1.2.1' - implementation 'com.google.android.material:material:$materialVersion' + implementation "com.google.android.material:material:$materialVersion" implementation 'androidx.legacy:legacy-support-v13:1.0.0' implementation 'androidx.cardview:cardview:1.0.0' - implementation 'androidx.preference:preference-ktx:$preferenceVersion' + implementation "androidx.preference:preference-ktx:$preferenceVersion" implementation 'androidx.legacy:legacy-preference-v14:1.0.0' implementation 'androidx.gridlayout:gridlayout:1.0.0' implementation 'androidx.exifinterface:exifinterface:1.3.4' @@ -105,12 +105,12 @@ dependencies { testImplementation 'org.powermock:powermock-module-junit4:1.6.1' testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.1' testImplementation 'org.powermock:powermock-classloading-xstream:1.6.1' - testImplementation 'androidx.test:core:$testCoreVersion' - testImplementation "androidx.arch.core:core-testing:2.1.0" + testImplementation "androidx.test:core:$testCoreVersion" + testImplementation "androidx.arch.core:core-testing:2.2.0" testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion" androidTestImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutinesVersion" // Core library - androidTestImplementation 'androidx.test:core:1.4.0' + androidTestImplementation 'androidx.test:core:1.5.0' androidTestImplementation('com.adevinta.android:barista:4.2.0') { exclude group: 'org.jetbrains.kotlin' } @@ -125,14 +125,14 @@ dependencies { androidTestImplementation 'com.google.truth:truth:1.1.3' // Espresso dependencies - androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-intents:3.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-web:3.4.0' - androidTestImplementation 'androidx.test.espresso.idling:idling-concurrent:3.4.0' - androidTestImplementation 'androidx.test.espresso:espresso-idling-resource:3.4.0' - androidTestUtil 'androidx.test:orchestrator:1.4.1' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' + androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.5.1' + androidTestImplementation 'androidx.test.espresso:espresso-intents:3.5.1' + androidTestImplementation 'androidx.test.espresso:espresso-accessibility:3.5.1' + androidTestImplementation 'androidx.test.espresso:espresso-web:3.5.1' + androidTestImplementation 'androidx.test.espresso.idling:idling-concurrent:3.5.1' + androidTestImplementation 'androidx.test.espresso:espresso-idling-resource:3.5.1' + androidTestUtil 'androidx.test:orchestrator:1.4.2' testImplementation 'org.robolectric:robolectric:4.4' testImplementation 'org.robolectric:shadows-multidex:4.4' @@ -158,6 +158,7 @@ dependencies { //compose def composeBom = platform('androidx.compose:compose-bom:2023.06.00') + def compose_nav_version = "2.5.3" implementation composeBom androidTestImplementation composeBom implementation 'androidx.compose.material3:material3' @@ -168,6 +169,7 @@ dependencies { implementation 'androidx.compose.ui:ui-tooling-preview' debugImplementation 'androidx.compose.ui:ui-tooling' implementation 'androidx.compose.material:material-icons-extended' + implementation "androidx.navigation:navigation-compose:$compose_nav_version" //memory leak dependency // debugImplementation 'com.squareup.leakcanary:leakcanary-android:2.12' diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index a99614c6a..67e0cffc5 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -326,7 +326,7 @@ - + @@ -513,6 +513,27 @@ android:exported="true" android:theme="@style/Theme.Bchat.DayNight.NoActionBar" /> + + + + + + + + + + + + + + + Unit, + modifier: Modifier = Modifier, + enabled: Boolean = true, + shape: Shape = ButtonDefaults.shape, + containerColor: Color = MaterialTheme.appColors.primaryButtonColor, + contentColor: Color = Color.White, + disabledContainerColor: Color = MaterialTheme.colorScheme.primary, + disabledContentColor: Color = MaterialTheme.appColors.disabledPrimaryButtonContentColor, + elevation: ButtonElevation? = ButtonDefaults.buttonElevation(), + border: BorderStroke? = null, + contentPadding: PaddingValues = ButtonDefaults.ContentPadding, + interactionSource: MutableInteractionSource = remember { MutableInteractionSource() }, + content: @Composable RowScope.() -> Unit +) { + Button( + onClick = onClick, + modifier = modifier, + enabled = enabled, + shape = shape, + colors = ButtonDefaults.buttonColors( + containerColor = containerColor, + contentColor = contentColor, + disabledContainerColor = disabledContainerColor, + disabledContentColor = disabledContentColor + ), + elevation = elevation, + border = border, + contentPadding = contentPadding, + interactionSource = interactionSource, + content = content + ) +} + +@Composable +fun BChatOutlinedTextField( + value: String, + modifier: Modifier = Modifier, + label: String? = null, + textColor: Color = MaterialTheme.appColors.textFieldTextColor, + fontSize: TextUnit = 14.sp, + fontWeight: FontWeight = FontWeight.Normal, + fontStyle: FontStyle = FontStyle.Normal, + singleLine: Boolean = true, + focusedBorderColor: Color = MaterialTheme.appColors.textFieldFocusedColor, + focusedLabelColor: Color = MaterialTheme.appColors.textFieldFocusedColor, + unFocusedBorderColor: Color = MaterialTheme.appColors.textFieldUnfocusedColor, + unFocusedLabelColor: Color = MaterialTheme.appColors.textFieldUnfocusedColor, + cursorColor: Color = MaterialTheme.appColors.textFieldCursorColor, + imeAction: ImeAction = ImeAction.Done, + keyboardType: KeyboardType = KeyboardType.Text, + keyboardActions: KeyboardActions = KeyboardActions.Default, + capitalization: KeyboardCapitalization = KeyboardCapitalization.None, + visualTransformation: VisualTransformation = VisualTransformation.None, + leadingIcon: @Composable (() -> Unit)? = null, + trailingIcon: @Composable (() -> Unit)? = null, + enabled: Boolean = true, + readOnly: Boolean = false, + shape: Shape = MaterialTheme.shapes.small, + placeHolder: String = "", + maxLen: Int = -1, + textAlign: TextAlign? = null, + onValueChange: (String) -> Unit +) { + OutlinedTextField( + value = value, + onValueChange = { + if (maxLen > -1) { + if (it.length <= maxLen) + onValueChange(it) + } else { + onValueChange(it) + } + }, + placeholder = { + Text( + text = placeHolder, + style = TextStyle( + fontFamily = OpenSans, + fontStyle = fontStyle, + fontSize = fontSize, + fontWeight = fontWeight, + color = MaterialTheme.appColors.editTextPlaceholder + ) + ) + }, + label = label?.let { + { + Text( + text = label, + style = TextStyle( + fontFamily = OpenSans, + fontStyle = fontStyle, + fontSize = fontSize, + fontWeight = fontWeight, + color = MaterialTheme.appColors.editTextPlaceholder + ) + ) + } + }, + singleLine = singleLine, + textStyle = TextStyle( + fontFamily = OpenSans, + fontStyle = fontStyle, + fontSize = fontSize, + fontWeight = fontWeight, + color = TextColor, + textAlign = textAlign, + ), + colors = OutlinedTextFieldDefaults.colors( + focusedBorderColor = focusedBorderColor, + unfocusedBorderColor = unFocusedBorderColor, + focusedLabelColor = focusedLabelColor, + unfocusedLabelColor = unFocusedLabelColor, + cursorColor = cursorColor + ), + keyboardOptions = KeyboardOptions.Default.copy( + keyboardType = keyboardType, + imeAction = imeAction, + capitalization = capitalization + ), + keyboardActions = keyboardActions, + visualTransformation = visualTransformation, + leadingIcon = leadingIcon, + trailingIcon = trailingIcon, + enabled = enabled, + readOnly = readOnly, + shape = shape, + modifier = Modifier + .then(modifier) + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/MultilineTextField.kt b/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/MultilineTextField.kt new file mode 100644 index 000000000..e08f094e3 --- /dev/null +++ b/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/MultilineTextField.kt @@ -0,0 +1,40 @@ +package com.thoughtcrimes.securesms.compose_utils + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.text.TextStyle + +@Composable +fun MultilineTextField( + value: String, + onValueChange: (String) -> Unit, + modifier: Modifier = Modifier, + textStyle: TextStyle = MaterialTheme.typography.bodyMedium, + hintText: String = "", + maxLines: Int = 4 +) { + BasicTextField( + value = value, + onValueChange = onValueChange, + maxLines = maxLines, + textStyle = textStyle, + decorationBox = { innerTextField -> + Box( + modifier = modifier + ) { + if (value.isEmpty()) { + Text( + text = hintText, + color = MaterialTheme.appColors.editTextHint + ) + } + innerTextField() + } + } + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/PinCodeView.kt b/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/PinCodeView.kt new file mode 100644 index 000000000..26487067f --- /dev/null +++ b/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/PinCodeView.kt @@ -0,0 +1,83 @@ +package com.thoughtcrimes.securesms.compose_utils + +import androidx.compose.foundation.BorderStroke +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.size +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Dp +import androidx.compose.ui.unit.dp + +@Composable +fun PinCodeView( + modifier: Modifier = Modifier, + length: Int = 4, + pin: String = "", + boxSize: Dp = 64.dp +) { + Row( + horizontalArrangement = Arrangement.spacedBy(16.dp, Alignment.CenterHorizontally), + modifier = modifier + ) { + repeat(length) { i -> + val value = if (pin.length - 1 >= i) pin[i].toString() else "" + Card( + border = BorderStroke( + width = 1.dp, + color = if (value.isNotEmpty()) + MaterialTheme.appColors.primaryButtonColor + else + MaterialTheme.colorScheme.outline + ), + colors = CardDefaults.cardColors( + containerColor = Color.Transparent + ), + modifier = Modifier + .size(boxSize) + .background( + color = Color.Transparent, + shape = RoundedCornerShape(25) + ) + ) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .fillMaxSize() + ) { + Text( + text = value, + style = MaterialTheme.typography.titleMedium, + textAlign = TextAlign.Center + ) + } + } + } + } +} + +@Preview +@Composable +fun PinCodePreview() { + PinCodeView( + pin = "1234", + modifier = Modifier + .fillMaxWidth() + ) +} \ No newline at end of file diff --git a/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/Theme.kt b/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/Theme.kt index 416cdb8de..9e7ecb31a 100644 --- a/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/Theme.kt +++ b/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/Theme.kt @@ -1,69 +1,67 @@ package com.thoughtcrimes.securesms.compose_utils 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.runtime.CompositionLocalProvider import androidx.compose.runtime.SideEffect import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.toArgb +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.platform.LocalView import androidx.core.view.WindowCompat -private val DarkColorScheme = darkColorScheme( - primary = Color(0xFF1c1c26), - secondary = Color(0xFF128D15), +private val darkColorScheme = darkColorScheme( + primary = Primary, + surfaceVariant = Primary, + outline = Outline ) -private val LightColorScheme = lightColorScheme( - primary = Color(0xFFEDEDED), - secondary = Color(0xFF128D15), - onPrimary = Color.White, - primaryContainer = Color.White, - onSecondary = Color.White, - background = Color.White, - - /* Other default colors to override - background = Color(0xFFFFFBFE), - surface = Color(0xFFFFFBFE), - onPrimary = Color.White, - onSecondary = Color.White, - onTertiary = Color.White, - onBackground = Color(0xFF1C1B1F), - onSurface = Color(0xFF1C1B1F), - */ +private val lightColorScheme = lightColorScheme( + primary = PrimaryLight, + surfaceVariant = SurfaceLight, + outline = OutlineLight ) @Composable fun BChatTheme( darkTheme: Boolean = isSystemInDarkTheme(), // Dynamic color is available on Android 12+ - dynamicColor: Boolean = true, + dynamicColor: Boolean = false, content: @Composable () -> Unit ) { val colorScheme = when { -// dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { -// val context = LocalContext.current -// if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) -// } - - darkTheme -> DarkColorScheme - else -> LightColorScheme + dynamicColor && Build.VERSION.SDK_INT >= Build.VERSION_CODES.S -> { + val context = LocalContext.current + if (darkTheme) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) + } + darkTheme -> darkColorScheme + else -> lightColorScheme } val view = LocalView.current if (!view.isInEditMode) { SideEffect { val window = (view.context as Activity).window window.statusBarColor = colorScheme.primary.toArgb() - WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = darkTheme + WindowCompat.getInsetsController(window, view).isAppearanceLightStatusBars = !darkTheme } } - MaterialTheme( - colorScheme = colorScheme, - typography = BChatTypography, - content = content - ) + val appColors = if (darkTheme) darkColors else lightColors + + CompositionLocalProvider( + LocalAppColors provides appColors + ) { + MaterialTheme( + colorScheme = colorScheme, + typography = if (darkTheme) BChatTypography else BChatTypographyLight, + content = content + ) + } } \ No newline at end of file diff --git a/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/Typography.kt b/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/Typography.kt index 2444eaec5..a59bd9fab 100644 --- a/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/Typography.kt +++ b/app/src/main/java/com/thoughtcrimes/securesms/compose_utils/Typography.kt @@ -75,4 +75,67 @@ val BChatTypography = Typography( fontFamily = OpenSans, color = TextColor ) +) + +val BChatTypographyLight = Typography( + displayLarge = defaultTypography.displayLarge.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + displayMedium = defaultTypography.displayMedium.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + displaySmall = defaultTypography.displaySmall.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + headlineLarge = defaultTypography.headlineLarge.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + headlineMedium = defaultTypography.headlineMedium.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + headlineSmall = defaultTypography.headlineSmall.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + bodyLarge = defaultTypography.bodyLarge.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + bodyMedium = defaultTypography.bodyMedium.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + bodySmall = defaultTypography.bodySmall.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + titleLarge = defaultTypography.titleLarge.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + titleMedium = defaultTypography.titleMedium.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + titleSmall = defaultTypography.titleSmall.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + labelLarge = defaultTypography.labelLarge.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + labelMedium = defaultTypography.labelMedium.copy( + fontFamily = OpenSans, + color = TextColorLight + ), + labelSmall = defaultTypography.labelSmall.copy( + fontFamily = OpenSans, + color = TextColorLight + ) ) \ No newline at end of file diff --git a/app/src/main/java/com/thoughtcrimes/securesms/home/HomeActivityNew.kt b/app/src/main/java/com/thoughtcrimes/securesms/home/HomeActivityNew.kt new file mode 100644 index 000000000..9522cea8e --- /dev/null +++ b/app/src/main/java/com/thoughtcrimes/securesms/home/HomeActivityNew.kt @@ -0,0 +1,9 @@ +package com.thoughtcrimes.securesms.home + +import androidx.activity.ComponentActivity + +class HomeActivityNew: ComponentActivity() { + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/thoughtcrimes/securesms/onboarding/LandingScreenActivity.kt b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/LandingScreenActivity.kt new file mode 100644 index 000000000..d53c4ef06 --- /dev/null +++ b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/LandingScreenActivity.kt @@ -0,0 +1,261 @@ +package com.thoughtcrimes.securesms.onboarding + +import android.content.Intent +import android.content.res.Configuration +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.Image +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.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.verticalScroll +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedButton +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Surface +import androidx.compose.material3.Text +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.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.SpanStyle +import androidx.compose.ui.text.buildAnnotatedString +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.withStyle +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import com.thoughtcrimes.securesms.compose_utils.BChatTheme +import com.thoughtcrimes.securesms.compose_utils.BChatTypography +import com.thoughtcrimes.securesms.compose_utils.OpenSans +import com.thoughtcrimes.securesms.compose_utils.PrimaryButton +import com.thoughtcrimes.securesms.compose_utils.appColors +import com.thoughtcrimes.securesms.onboarding.ui.OnBoardingActivity +import io.beldex.bchat.R + +class LandingScreenActivity: ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + BChatTheme { + Surface { + Scaffold( + containerColor = MaterialTheme.colorScheme.primary, + ) { + LandingScreen( + modifier = Modifier + .fillMaxSize() + .padding(it) + ) + } + } + } + } + } +} + +@Composable +fun LandingScreen( + modifier: Modifier = Modifier +) { + Column( + modifier = modifier + ) { + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier + .fillMaxWidth() + .weight(0.2f) + .padding(24.dp) + ) { + Image( + painter = painterResource(id = R.drawable.ic_bchat_logo), + contentDescription = "", + modifier = Modifier + .fillMaxWidth(0.3f) + ) + Spacer( + modifier = Modifier + .width(16.dp) + ) + Text( + buildAnnotatedString { + withStyle( + style = SpanStyle( + fontFamily = OpenSans, + fontWeight = FontWeight.ExtraBold, + fontSize = 56.sp, + color = MaterialTheme.appColors.primaryButtonColor + ) + ) { + append("B") + } + withStyle( + style = SpanStyle( + fontFamily = OpenSans, + fontWeight = FontWeight.ExtraBold, + fontSize = 56.sp, + color = MaterialTheme.appColors.tertiaryButtonColor + ) + ) { + append("Chat") + } + } + ) + } + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .fillMaxWidth() + .weight(0.3f) + ) { + Image( + painter = painterResource(id = R.drawable.ic_landing_bubble), + contentDescription = "", + modifier = Modifier + .align(Alignment.CenterEnd) + ) + Column( + modifier = Modifier + .fillMaxWidth() + .padding(24.dp) + ) { + Text( + text = "Hey You!\nChat anonymously now.", + style = BChatTypography.headlineSmall.copy( + color = MaterialTheme.appColors.onMainContainerTextColor, + fontWeight = FontWeight.ExtraBold + ) + ) + + Spacer(modifier = Modifier.height(16.dp)) + + Text( + text = "The Private Web 3 messaging app that protects your conversational freedom. Create an account instantly.", + style = BChatTypography.bodyMedium.copy( + color = MaterialTheme.appColors.onMainContainerTextColor + ) + ) + } + } + + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxWidth() + .weight(0.2f) + ) { + PrimaryButton( + onClick = { + + }, + modifier = Modifier + .fillMaxWidth(0.7f) + ) { + Text( + text = "Create Account", + style = BChatTypography.bodyLarge.copy( + color = Color.White + ), + modifier = Modifier + .padding(8.dp) + ) + } + + Spacer(modifier = Modifier.height(16.dp)) + + val context = LocalContext.current + OutlinedButton( + onClick = { + context.startActivity(Intent(context, OnBoardingActivity::class.java)) + }, + modifier = Modifier + .fillMaxWidth(0.7f) + ) { + Text( + text = "Restore Account", + style = BChatTypography.bodyLarge.copy( + color = MaterialTheme.appColors.onMainContainerTextColor + ), + modifier = Modifier + .padding(8.dp) + ) + } + } + + Box( + modifier = Modifier + .fillMaxWidth() + .weight(0.2f) + .padding( + start = 24.dp, + end = 24.dp, + top = 24.dp + ) + ) { + Text( + text = "Terms & Conditions", + style = BChatTypography.labelMedium.copy( + color = MaterialTheme.appColors.secondaryTextColor + ), + textAlign = TextAlign.Center, + modifier = Modifier + .fillMaxWidth() + .padding(8.dp) + ) + + Image( + painter = painterResource(id = R.drawable.ic_bchat_2), + contentDescription = "", + modifier = Modifier + .align(Alignment.BottomStart) + ) + } + } +} + +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +fun LandingScreenPreview() { + BChatTheme { + Scaffold { + LandingScreen( + modifier = Modifier + .fillMaxSize() + .padding(it) + ) + } + } +} + +@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO) +@Composable +fun LandingScreenPreviewLight() { + BChatTheme { + Scaffold { + LandingScreen( + modifier = Modifier + .fillMaxSize() + .padding(it) + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/OnBoardingActivity.kt b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/OnBoardingActivity.kt new file mode 100644 index 000000000..0b793d79c --- /dev/null +++ b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/OnBoardingActivity.kt @@ -0,0 +1,191 @@ +package com.thoughtcrimes.securesms.onboarding.ui + +import android.app.Activity +import android.os.Bundle +import androidx.activity.ComponentActivity +import androidx.activity.compose.setContent +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Box +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.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +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.platform.LocalContext +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.dp +import androidx.compose.ui.unit.sp +import androidx.navigation.NavHostController +import androidx.navigation.compose.NavHost +import androidx.navigation.compose.composable +import androidx.navigation.compose.rememberNavController +import com.thoughtcrimes.securesms.compose_utils.BChatTheme +import com.thoughtcrimes.securesms.compose_utils.appColors +import io.beldex.bchat.R + +class OnBoardingActivity: ComponentActivity() { + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + BChatTheme { + Surface { + Scaffold( + containerColor = MaterialTheme.colorScheme.primary + ) { + val navController = rememberNavController() + OnBoardingNavHost( + navController = navController, + modifier = Modifier + .padding(it) + ) + } + } + } + } + } +} + +@Composable +fun OnBoardingNavHost( + navController: NavHostController, + modifier: Modifier = Modifier +) { + val context = LocalContext.current + NavHost( + navController = navController, + startDestination = OnBoardingScreens.EnterPinCode.route + ) { + composable( + route = OnBoardingScreens.RestoreSeedScreen.route + ) { + ScreenContainer( + title = "Restore Seed", + onBackClick = { + (context as Activity).finish() + } + ) { + RestoreSeedScreen( + navigateToNextScreen = { + navController.navigate(OnBoardingScreens.RestoreFromSeedScreen.route) + } + ) + } + } + + composable( + route = OnBoardingScreens.RestoreFromSeedScreen.route + ) { + ScreenContainer( + title = "Restore From Seed", + onBackClick = { + navController.navigateUp() + } + ) { + RestoreFromSeedScreen( + navigateToPinCode = { + navController.navigate(OnBoardingScreens.EnterPinCode.route) + } + ) + } + } + + composable( + route = OnBoardingScreens.EnterPinCode.route + ) { + ScreenContainer( + title = "Create Password", + wrapInCard = false, + onBackClick = { + navController.navigateUp() + } + ) { + PinCodeScreen() + } + } + } +} + +@Composable +private fun ScreenContainer( + title: String, + wrapInCard: Boolean = true, + onBackClick: () -> Unit, + content: @Composable () -> Unit +) { + Column( + modifier = Modifier + .fillMaxSize() + ) { + Box( + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) { + Icon( + Icons.Default.ArrowBack, + contentDescription = stringResource(R.string.back), + tint = MaterialTheme.appColors.editTextColor, + modifier = Modifier + .align(Alignment.TopStart) + .clickable { + onBackClick() + } + ) + + Text( + text = title, + style = MaterialTheme.typography.titleMedium.copy( + color = MaterialTheme.appColors.editTextColor, + fontWeight = FontWeight.Bold, + fontSize = 18.sp + ), + modifier = Modifier + .align(Alignment.Center) + ) + } + + Spacer(modifier = Modifier.height(24.dp)) + + if (wrapInCard) { + CardContainer( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + ) { + content() + } + } else { + content() + } + } +} + +@Composable +private fun CardContainer( + modifier: Modifier = Modifier, + content: @Composable () -> Unit +) { + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.appColors.backgroundColor + ), + modifier = modifier + ) { + content() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/OnBoardingScreens.kt b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/OnBoardingScreens.kt new file mode 100644 index 000000000..ce89749b8 --- /dev/null +++ b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/OnBoardingScreens.kt @@ -0,0 +1,9 @@ +package com.thoughtcrimes.securesms.onboarding.ui + +sealed class OnBoardingScreens(val route: String) { + + data object RestoreSeedScreen: OnBoardingScreens("/on-boarding/restore") + data object RestoreFromSeedScreen: OnBoardingScreens("/on-boarding/restore-from-seed") + data object EnterPinCode: OnBoardingScreens("/on-boarding/pin-code") + +} \ No newline at end of file diff --git a/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/PinCodeScreen.kt b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/PinCodeScreen.kt new file mode 100644 index 000000000..683db9e6b --- /dev/null +++ b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/PinCodeScreen.kt @@ -0,0 +1,232 @@ +package com.thoughtcrimes.securesms.onboarding.ui + +import android.annotation.SuppressLint +import androidx.compose.foundation.Image +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +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.lazy.grid.GridCells +import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.outlined.Backspace +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +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.geometry.Size +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.layout.onSizeChanged +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.dp +import com.thoughtcrimes.securesms.compose_utils.BChatTheme +import com.thoughtcrimes.securesms.compose_utils.PinCodeView +import com.thoughtcrimes.securesms.compose_utils.PrimaryButton +import com.thoughtcrimes.securesms.compose_utils.appColors +import io.beldex.bchat.R + +@Composable +fun PinCodeScreen() { + var pin by remember { + mutableStateOf("") + } + Column( + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxSize() + ) { + Image( + painter = painterResource(id = R.drawable.ic_password), + contentDescription = "", + modifier = Modifier + .weight(0.2f) + ) + + Column( + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + modifier = Modifier + .weight(0.2f) + ) { + PinCodeView( + pin = pin, + modifier = Modifier + .fillMaxWidth() + .padding(16.dp) + ) + + Text( + text = "Enter your PIN", + style = MaterialTheme.typography.titleMedium + ) + } + + Spacer(modifier = Modifier.height(16.dp)) + + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.appColors.backgroundColor + ), + modifier = Modifier + .fillMaxWidth() + .weight(0.6f) + ) { + var cellSize by remember { + mutableStateOf(IntSize.Zero) + } + val density = LocalDensity.current + LazyVerticalGrid( + columns = GridCells.Fixed(3), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier + .fillMaxWidth() + .padding(32.dp) + ) { + repeat(12) { + when (val index = it + 1) { + 10 -> { + item { + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.appColors.editTextBackground + ) + ) { + + } + } + } + 11 -> { + item { + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.appColors.editTextBackground + ), + modifier = Modifier + .clickable { + pin += "0" + } + ) { + Text( + text = "0", + style = MaterialTheme.typography.titleLarge, + textAlign = TextAlign.Center, + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) + } + } + } + 12 -> { + item { + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.appColors.editTextBackground + ), + modifier = Modifier + .size( + width = with(density) { + cellSize.width.toDp() + }, + height = with(density) { + cellSize.height.toDp() + } + ) + .clickable { + if (pin.isNotEmpty()) { + pin = pin.substring(0, pin.length - 1) + } + } + ) { + Icon( + Icons.Outlined.Backspace, + contentDescription = "", + tint = MaterialTheme.appColors.editTextColor, + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) + } + } + } + else -> { + item { + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.appColors.editTextBackground + ), + modifier = Modifier + .onSizeChanged { size -> + cellSize = size + } + .clickable { + pin += "$index" + } + ) { + Text( + text = "$index", + style = MaterialTheme.typography.titleLarge, + textAlign = TextAlign.Center, + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) + } + } + } + } + } + } + + PrimaryButton( + onClick = {}, + enabled = true, + modifier = Modifier + .fillMaxWidth(0.8f) + .align(Alignment.CenterHorizontally) + ) { + Text( + text = "Continue", + style = MaterialTheme.typography.titleMedium.copy( + color = Color.White + ), + modifier = Modifier + .padding(4.dp) + ) + } + + Spacer(modifier = Modifier.height(16.dp)) + } + } +} + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Preview +@Composable +fun PinCodeScreenPreview() { + BChatTheme { + Scaffold { + PinCodeScreen() + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/RestoreFromSeedScreen.kt b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/RestoreFromSeedScreen.kt new file mode 100644 index 000000000..cee48059c --- /dev/null +++ b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/RestoreFromSeedScreen.kt @@ -0,0 +1,199 @@ +package com.thoughtcrimes.securesms.onboarding.ui + +import android.annotation.SuppressLint +import android.content.res.Configuration +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.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowForward +import androidx.compose.material.icons.filled.CalendarToday +import androidx.compose.material.icons.filled.ContentPaste +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text +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.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.thoughtcrimes.securesms.compose_utils.BChatOutlinedTextField +import com.thoughtcrimes.securesms.compose_utils.BChatTheme +import com.thoughtcrimes.securesms.compose_utils.MultilineTextField +import com.thoughtcrimes.securesms.compose_utils.PrimaryButton +import com.thoughtcrimes.securesms.compose_utils.appColors +import io.beldex.bchat.R + +@Composable +fun RestoreFromSeedScreen( + navigateToPinCode: () -> Unit +) { + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) { + var restoreFromHeight by remember { + mutableStateOf(false) + } + Column( + modifier = Modifier + .fillMaxWidth() + .weight(1f) + ) { + Text( + text = "Display Name", + style = MaterialTheme.typography.titleMedium.copy( + color = MaterialTheme.appColors.editTextColor + ) + ) + + Spacer(modifier = Modifier.height(8.dp)) + + BChatOutlinedTextField( + value = "", + onValueChange = {}, + label = "Enter name" + ) + + if (restoreFromHeight) { + Spacer(modifier = Modifier.height(16.dp)) + + Text( + text = "Pick a restore height", + style = MaterialTheme.typography.titleMedium + ) + + Spacer(modifier = Modifier.height(8.dp)) + + BChatOutlinedTextField( + value = "", + onValueChange = {}, + label = "Enter Block height to Restore", + keyboardType = KeyboardType.Number + ) + } else { + Spacer(modifier = Modifier.height(16.dp)) + + Text( + text = "Pick a Date", + style = MaterialTheme.typography.titleMedium + ) + + Spacer(modifier = Modifier.height(8.dp)) + + BChatOutlinedTextField( + value = "", + onValueChange = {}, + label = "Enter Date", + trailingIcon = { + Icon( + Icons.Filled.CalendarToday, + contentDescription = "" + ) + } + ) + } + + Spacer(modifier = Modifier.height(16.dp)) + + PrimaryButton( + onClick = { + restoreFromHeight = !restoreFromHeight + }, + modifier = Modifier + .align(Alignment.End) + ) { + Icon( + painter = painterResource(id = R.drawable.ic_calendar), + contentDescription = "" + ) + + Spacer(modifier = Modifier.width(8.dp)) + + Text( + text = if (!restoreFromHeight) + "Restore from Height" + else + "Restore from Date", + style = MaterialTheme.typography.titleSmall.copy( + color = Color.White + ), + modifier = Modifier + .padding( + vertical = 4.dp + ) + ) + + Spacer(modifier = Modifier.width(8.dp)) + + Icon( + painter = painterResource(id = R.drawable.ic_arrow_forward), + contentDescription = "" + ) + } + } + + PrimaryButton( + onClick = navigateToPinCode, + modifier = Modifier + .fillMaxWidth() + ) { + Text( + text = "Continue", + style = MaterialTheme.typography.titleMedium.copy( + color = Color.White + ), + modifier = Modifier + .padding(4.dp) + ) + } + } +} + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Preview +@Composable +fun RestoreFromSeedScreenPreview() { + BChatTheme() { + Scaffold { + RestoreFromSeedScreen( + navigateToPinCode = {} + ) + } + } +} + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Preview(uiMode = Configuration.UI_MODE_NIGHT_YES) +@Composable +fun RestoreFromSeedScreenPreviewLight() { + BChatTheme() { + Scaffold { + RestoreFromSeedScreen( + navigateToPinCode = {} + ) + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/RestoreSeedScreen.kt b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/RestoreSeedScreen.kt new file mode 100644 index 000000000..dbfa75890 --- /dev/null +++ b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/RestoreSeedScreen.kt @@ -0,0 +1,159 @@ +package com.thoughtcrimes.securesms.onboarding.ui + +import android.content.res.Configuration +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +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.width +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.foundation.text.BasicTextField +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ContentPaste +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.LocalContentColor +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.OutlinedTextField +import androidx.compose.material3.Text +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.draw.clip +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalClipboardManager +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import com.thoughtcrimes.securesms.compose_utils.BChatOutlinedTextField +import com.thoughtcrimes.securesms.compose_utils.BChatTheme +import com.thoughtcrimes.securesms.compose_utils.MultilineTextField +import com.thoughtcrimes.securesms.compose_utils.PrimaryButton +import com.thoughtcrimes.securesms.compose_utils.appColors + +@Composable +fun RestoreSeedScreen( + navigateToNextScreen: () -> Unit +) { + var seed by remember { + mutableStateOf("") + } + Column( + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + modifier = Modifier + .fillMaxSize() + .padding(16.dp) + ) { + Column( + verticalArrangement = Arrangement.Center, + modifier = Modifier + .fillMaxWidth() + .weight(1f) + ) { + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.appColors.editTextBackground + ), + modifier = Modifier + .fillMaxWidth() + .height(160.dp) + ) { + MultilineTextField( + value = seed, + onValueChange = { + seed = it + }, + hintText = "Enter your seed", + maxLines = 6, + textStyle = MaterialTheme.typography.titleMedium.copy( + color = MaterialTheme.appColors.editTextColor, + textAlign = TextAlign.Center + ), + modifier = Modifier + .fillMaxWidth() + .clip(RoundedCornerShape(8.dp)) + .padding(16.dp) + ) + } + + Spacer(modifier = Modifier.height(16.dp)) + + val clipboardManager = LocalClipboardManager.current + PrimaryButton( + onClick = { + clipboardManager.getText()?.text?.let { + seed = it + } + }, + modifier = Modifier + .fillMaxWidth(0.4f) + .align(Alignment.End) + ) { + Text( + text = "Paste Seed", + style = MaterialTheme.typography.titleSmall.copy( + color = Color.White + ), + modifier = Modifier + .padding( + vertical = 4.dp + ) + ) + + Spacer(modifier = Modifier.width(8.dp)) + + Icon( + Icons.Default.ContentPaste, + contentDescription = "" + ) + } + } + + PrimaryButton( + onClick = navigateToNextScreen, + enabled = seed.isNotEmpty(), + modifier = Modifier + .fillMaxWidth() + ) { + Text( + text = "Continue", + style = MaterialTheme.typography.titleMedium.copy( + color = Color.White + ), + modifier = Modifier + .padding(4.dp) + ) + } + } +} + +@Preview +@Composable +fun RestoreSeedScreenPreview() { + BChatTheme() { + RestoreSeedScreen( + navigateToNextScreen = {} + ) + } +} + +@Preview(uiMode = Configuration.UI_MODE_NIGHT_NO) +@Composable +fun RestoreSeedScreenPreviewLight() { + BChatTheme { + RestoreSeedScreen( + navigateToNextScreen = {} + ) + } +} \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_arrow_forward.xml b/app/src/main/res/drawable/ic_arrow_forward.xml index 08eaa521f..70f20ca24 100644 --- a/app/src/main/res/drawable/ic_arrow_forward.xml +++ b/app/src/main/res/drawable/ic_arrow_forward.xml @@ -1,5 +1,9 @@ - - + + diff --git a/app/src/main/res/drawable/ic_bchat_2.xml b/app/src/main/res/drawable/ic_bchat_2.xml new file mode 100644 index 000000000..0b15dc909 --- /dev/null +++ b/app/src/main/res/drawable/ic_bchat_2.xml @@ -0,0 +1,11 @@ + + + diff --git a/app/src/main/res/drawable/ic_calendar.xml b/app/src/main/res/drawable/ic_calendar.xml new file mode 100644 index 000000000..ef0e2a99c --- /dev/null +++ b/app/src/main/res/drawable/ic_calendar.xml @@ -0,0 +1,31 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_landing_bubble.xml b/app/src/main/res/drawable/ic_landing_bubble.xml new file mode 100644 index 000000000..dd17b7963 --- /dev/null +++ b/app/src/main/res/drawable/ic_landing_bubble.xml @@ -0,0 +1,26 @@ + + + + + + diff --git a/app/src/main/res/drawable/ic_password.xml b/app/src/main/res/drawable/ic_password.xml new file mode 100644 index 000000000..f4b7da104 --- /dev/null +++ b/app/src/main/res/drawable/ic_password.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_password_1.xml b/app/src/main/res/drawable/ic_password_1.xml new file mode 100644 index 000000000..7462db930 --- /dev/null +++ b/app/src/main/res/drawable/ic_password_1.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4da01ae5d..8f1b559eb 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1416,4 +1416,5 @@ Your wallet password can be used to access your wallet within BChat and authenti Yes, I Understand Enable Wallet Please enter a node address + Back diff --git a/gradle.properties b/gradle.properties index 4572fea74..d92011e74 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,9 +2,9 @@ android.useAndroidX=true android.enableJetifier=true org.gradle.jvmargs=-Xmx8g -kotlinVersion=1.8.0 +kotlinVersion=1.9.20 lifecycleVersion=2.6.1 -daggerVersion=2.44 +daggerVersion=2.48.1 gradlePluginVersion=7.4.2 googleServicesVersion=4.3.15 coroutinesVersion=1.6.4 @@ -21,5 +21,5 @@ preferenceVersion=1.2.0 coreVersion=1.8.0 junitVersion=4.13.2 mockitoKotlinVersion=4.0.0 -testCoreVersion=1.4.0 +testCoreVersion=1.5.0 pagingVersion=3.0.0 \ No newline at end of file From a33a24ee329bceab3f2627ccba6d530c9095d683 Mon Sep 17 00:00:00 2001 From: droid-mon Date: Wed, 6 Dec 2023 00:23:05 +0530 Subject: [PATCH 002/382] pincode screen overflow issue fixed --- .../securesms/onboarding/ui/PinCodeScreen.kt | 264 ++++++++++-------- 1 file changed, 154 insertions(+), 110 deletions(-) diff --git a/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/PinCodeScreen.kt b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/PinCodeScreen.kt index 683db9e6b..bec26ec8f 100644 --- a/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/PinCodeScreen.kt +++ b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/ui/PinCodeScreen.kt @@ -2,18 +2,20 @@ package com.thoughtcrimes.securesms.onboarding.ui import android.annotation.SuppressLint import androidx.compose.foundation.Image +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxWithConstraints 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.lazy.grid.GridCells import androidx.compose.foundation.lazy.grid.LazyVerticalGrid +import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material.icons.Icons import androidx.compose.material.icons.outlined.Backspace import androidx.compose.material3.Card @@ -29,7 +31,6 @@ import androidx.compose.runtime.remember import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier -import androidx.compose.ui.geometry.Size import androidx.compose.ui.graphics.Color import androidx.compose.ui.layout.onSizeChanged import androidx.compose.ui.platform.LocalDensity @@ -37,6 +38,7 @@ import androidx.compose.ui.res.painterResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.IntSize +import androidx.compose.ui.unit.coerceAtMost import androidx.compose.ui.unit.dp import com.thoughtcrimes.securesms.compose_utils.BChatTheme import com.thoughtcrimes.securesms.compose_utils.PinCodeView @@ -71,7 +73,11 @@ fun PinCodeScreen() { pin = pin, modifier = Modifier .fillMaxWidth() - .padding(16.dp) + ) + + Spacer( + modifier = Modifier + .height(16.dp) ) Text( @@ -82,140 +88,164 @@ fun PinCodeScreen() { Spacer(modifier = Modifier.height(16.dp)) - Card( - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.appColors.backgroundColor - ), + BoxWithConstraints( modifier = Modifier .fillMaxWidth() .weight(0.6f) ) { - var cellSize by remember { + val density = LocalDensity.current + val availableHeight = with(density) { + constraints.maxHeight.toDp() + } + var buttonSize by remember { mutableStateOf(IntSize.Zero) } - val density = LocalDensity.current - LazyVerticalGrid( - columns = GridCells.Fixed(3), - verticalArrangement = Arrangement.spacedBy(16.dp), - horizontalArrangement = Arrangement.spacedBy(16.dp), + val buttonHeight = with(density) { + buttonSize.height.toDp() + } + val heightLessSpacing = availableHeight - 96.dp - buttonHeight + val cellHeight = (heightLessSpacing / 4).coerceAtMost(64.dp) + Column( modifier = Modifier - .fillMaxWidth() - .padding(32.dp) + .fillMaxSize() + .background( + color = MaterialTheme.appColors.backgroundColor, + shape = RoundedCornerShape( + topStart = 16.dp, + topEnd = 16.dp + ) + ) ) { - repeat(12) { - when (val index = it + 1) { - 10 -> { - item { - Card( - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.appColors.editTextBackground - ) - ) { + LazyVerticalGrid( + columns = GridCells.Fixed(3), + verticalArrangement = Arrangement.spacedBy(16.dp), + horizontalArrangement = Arrangement.spacedBy(16.dp), + modifier = Modifier + .fillMaxWidth() + .padding( + horizontal = 32.dp, + vertical = 16.dp + ) + ) { + repeat(12) { + when (val index = it + 1) { + 10 -> { + item { + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.appColors.editTextBackground + ) + ) { + } } } - } - 11 -> { - item { - Card( - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.appColors.editTextBackground - ), - modifier = Modifier - .clickable { - pin += "0" - } - ) { - Text( - text = "0", - style = MaterialTheme.typography.titleLarge, - textAlign = TextAlign.Center, + 11 -> { + item { + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.appColors.editTextBackground + ), modifier = Modifier - .fillMaxSize() - .padding(16.dp) - ) + .height(cellHeight) + .clickable { + pin += "0" + } + ) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .fillMaxSize() + ) { + Text( + text = "0", + style = MaterialTheme.typography.titleLarge + ) + } + } } } - } - 12 -> { - item { - Card( - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.appColors.editTextBackground - ), - modifier = Modifier - .size( - width = with(density) { - cellSize.width.toDp() - }, - height = with(density) { - cellSize.height.toDp() - } - ) - .clickable { - if (pin.isNotEmpty()) { - pin = pin.substring(0, pin.length - 1) + 12 -> { + item { + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.appColors.editTextBackground + ), + modifier = Modifier + .height(cellHeight) + .clickable { + if (pin.isNotEmpty()) { + pin = pin.substring(0, pin.length - 1) + } } + ) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .fillMaxSize() + ) { + Icon( + Icons.Outlined.Backspace, + contentDescription = "", + tint = MaterialTheme.appColors.editTextColor + ) } - ) { - Icon( - Icons.Outlined.Backspace, - contentDescription = "", - tint = MaterialTheme.appColors.editTextColor, - modifier = Modifier - .fillMaxSize() - .padding(16.dp) - ) + } } } - } - else -> { - item { - Card( - colors = CardDefaults.cardColors( - containerColor = MaterialTheme.appColors.editTextBackground - ), - modifier = Modifier - .onSizeChanged { size -> - cellSize = size - } - .clickable { - pin += "$index" - } - ) { - Text( - text = "$index", - style = MaterialTheme.typography.titleLarge, - textAlign = TextAlign.Center, + else -> { + item { + Card( + colors = CardDefaults.cardColors( + containerColor = MaterialTheme.appColors.editTextBackground + ), modifier = Modifier - .fillMaxSize() - .padding(16.dp) - ) + .height(cellHeight) + .clickable { + pin += "$index" + } + ) { + Box( + contentAlignment = Alignment.Center, + modifier = Modifier + .fillMaxSize() + ) { + Text( + text = "$index", + style = MaterialTheme.typography.titleLarge + ) + } + } } } } } } - } - PrimaryButton( - onClick = {}, - enabled = true, - modifier = Modifier - .fillMaxWidth(0.8f) - .align(Alignment.CenterHorizontally) - ) { - Text( - text = "Continue", - style = MaterialTheme.typography.titleMedium.copy( - color = Color.White - ), + Spacer(modifier = Modifier.weight(1f)) + + PrimaryButton( + onClick = {}, + enabled = true, modifier = Modifier - .padding(4.dp) - ) - } + .fillMaxWidth(0.8f) + .align(Alignment.CenterHorizontally) + .onSizeChanged { + buttonSize = it + } + ) { + Text( + text = "Continue", + style = MaterialTheme.typography.titleMedium.copy( + color = Color.White + ), + modifier = Modifier + .padding(4.dp) + ) + } - Spacer(modifier = Modifier.height(16.dp)) + Spacer(modifier = Modifier.weight(1f)) + } } } } @@ -229,4 +259,18 @@ fun PinCodeScreenPreview() { PinCodeScreen() } } +} + +@SuppressLint("UnusedMaterial3ScaffoldPaddingParameter") +@Preview( + widthDp = 412, + heightDp = 732 +) +@Composable +fun PinCodeScreenPreview2() { + BChatTheme { + Scaffold { + PinCodeScreen() + } + } } \ No newline at end of file From 31c8c00707f42ffa3f3c7869672ea7ad37dc4c4a Mon Sep 17 00:00:00 2001 From: SteveJosephh21 Date: Wed, 6 Dec 2023 10:17:34 +0530 Subject: [PATCH 003/382] Latest UI updated for Restore account flow --- app/src/main/AndroidManifest.xml | 10 +- .../onboarding/LinkDeviceActivity.kt | 212 ---------------- .../RecoveryPhraseRestoreActivity.kt | 29 --- .../seed/RecoveryGetSeedDetailsActivity.kt | 2 + ...minent_filled_button_medium_background.xml | 2 +- ...inent_outline_button_medium_background.xml | 4 +- app/src/main/res/drawable/calendar.xml | 2 +- app/src/main/res/drawable/ic_paste_seed.xml | 12 + .../ic_restore_from_date_calendar.xml | 15 ++ .../res/drawable/ic_restore_from_height.xml | 40 +++ app/src/main/res/drawable/ic_right_arrow.xml | 5 + app/src/main/res/drawable/page_background.xml | 11 + ...minent_filled_button_medium_background.xml | 2 +- ...t_filled_button_medium_background_blue.xml | 2 +- ...inent_outline_button_medium_background.xml | 4 +- .../activity_recovery_phrase_restore.xml | 230 +++++++++--------- .../fragment_recovery_phrase.xml | 136 ----------- .../main/res/layout/activity_link_device.xml | 60 ----- .../activity_recovery_get_seed_details.xml | 84 ++++--- .../activity_recovery_phrase_restore.xml | 230 +++++++++--------- .../res/layout/fragment_recovery_phrase.xml | 63 ----- .../main/res/values-notnight-v21/colors.xml | 1 + .../main/res/values-notnight-v21/dimens.xml | 2 +- .../main/res/values-notnight-v23/dimens.xml | 2 +- app/src/main/res/values-sw400dp/dimens.xml | 2 +- app/src/main/res/values/colors.xml | 7 +- app/src/main/res/values/dimens.xml | 2 +- app/src/main/res/values/strings.xml | 12 +- 28 files changed, 381 insertions(+), 802 deletions(-) delete mode 100644 app/src/main/java/com/thoughtcrimes/securesms/onboarding/LinkDeviceActivity.kt create mode 100644 app/src/main/res/drawable/ic_paste_seed.xml create mode 100644 app/src/main/res/drawable/ic_restore_from_date_calendar.xml create mode 100644 app/src/main/res/drawable/ic_restore_from_height.xml create mode 100644 app/src/main/res/drawable/ic_right_arrow.xml create mode 100644 app/src/main/res/drawable/page_background.xml delete mode 100644 app/src/main/res/layout-sw400dp/fragment_recovery_phrase.xml delete mode 100644 app/src/main/res/layout/activity_link_device.xml delete mode 100644 app/src/main/res/layout/fragment_recovery_phrase.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 67e0cffc5..74e492345 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -278,12 +278,6 @@ android:screenOrientation="portrait" android:theme="@style/Theme.Bchat.DayNight.FlatActionBar" android:windowSoftInputMode="adjustResize" /> - - + @@ -521,7 +515,7 @@ - + diff --git a/app/src/main/java/com/thoughtcrimes/securesms/onboarding/LinkDeviceActivity.kt b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/LinkDeviceActivity.kt deleted file mode 100644 index 3776094b1..000000000 --- a/app/src/main/java/com/thoughtcrimes/securesms/onboarding/LinkDeviceActivity.kt +++ /dev/null @@ -1,212 +0,0 @@ -package com.thoughtcrimes.securesms.onboarding - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import android.text.InputType -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import android.view.inputmethod.EditorInfo -import android.view.inputmethod.InputMethodManager -import android.widget.Toast -import androidx.core.view.isVisible -import androidx.fragment.app.Fragment -import androidx.fragment.app.FragmentPagerAdapter -import androidx.lifecycle.lifecycleScope -import com.google.android.material.snackbar.Snackbar -import kotlinx.coroutines.Job -import kotlinx.coroutines.delay -import kotlinx.coroutines.flow.filter -import kotlinx.coroutines.launch -import io.beldex.bchat.R -import io.beldex.bchat.databinding.ActivityLinkDeviceBinding -import io.beldex.bchat.databinding.FragmentRecoveryPhraseBinding -import com.beldex.libbchat.utilities.TextSecurePreferences -import com.beldex.libsignal.crypto.MnemonicCodec -import com.beldex.libsignal.utilities.Hex -import com.beldex.libsignal.utilities.KeyHelper -import com.beldex.libsignal.utilities.Log -import com.beldex.libsignal.utilities.hexEncodedPublicKey -import com.thoughtcrimes.securesms.ApplicationContext -import com.thoughtcrimes.securesms.BaseActionBarActivity -import com.thoughtcrimes.securesms.crypto.KeyPairUtilities -import com.thoughtcrimes.securesms.crypto.MnemonicUtilities -import com.thoughtcrimes.securesms.util.ScanQRCodeWrapperFragment -import com.thoughtcrimes.securesms.util.ScanQRCodeWrapperFragmentDelegate -import com.thoughtcrimes.securesms.util.push -import com.thoughtcrimes.securesms.util.setUpActionBarBchatLogo - -class LinkDeviceActivity : BaseActionBarActivity(), ScanQRCodeWrapperFragmentDelegate { - private lateinit var binding: ActivityLinkDeviceBinding - private val adapter = LinkDeviceActivityAdapter(this) - private var restoreJob: Job? = null - - override fun onBackPressed() { - if (restoreJob?.isActive == true) return // Don't allow going back with a pending job - super.onBackPressed() - } - - // region Lifecycle - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - setUpActionBarBchatLogo("") - TextSecurePreferences.apply { - setHasViewedSeed(this@LinkDeviceActivity, true) - setConfigurationMessageSynced(this@LinkDeviceActivity, false) - setRestorationTime(this@LinkDeviceActivity, System.currentTimeMillis()) - setLastProfileUpdateTime(this@LinkDeviceActivity, 0) - } - binding = ActivityLinkDeviceBinding.inflate(layoutInflater) - setContentView(binding.root) - binding.viewPager.adapter = adapter - binding.tabLayout.setupWithViewPager(binding.viewPager) - } - // endregion - - // region Interaction - override fun handleQRCodeScanned(mnemonic: String) { - try { - val seed = Hex.fromStringCondensed(mnemonic) - continueWithSeed(seed) - } catch (e: Exception) { - Log.e("Beldex","Error getting seed from QR code", e) - Toast.makeText(this, R.string.invalid_qr_code, Toast.LENGTH_SHORT).show() - } - } - - fun continueWithMnemonic(mnemonic: String) { - val loadFileContents: (String) -> String = { fileName -> - MnemonicUtilities.loadFileContents(this, fileName) - } - try { - val hexEncodedSeed = MnemonicCodec(loadFileContents).decode(mnemonic) - val seed = Hex.fromStringCondensed(hexEncodedSeed) - continueWithSeed(seed) - } catch (error: Exception) { - val message = if (error is MnemonicCodec.DecodingError) { - error.description - } else { - "An error occurred." - } - Toast.makeText(this, message, Toast.LENGTH_LONG).show() - } - } - - private fun continueWithSeed(seed: ByteArray) { - - // only have one sync job running at a time (prevent QR from trying to spawn a new job) - if (restoreJob?.isActive == true) return - - restoreJob = lifecycleScope.launch { - // RestoreActivity handles seed this way - val keyPairGenerationResult = KeyPairUtilities.generate(seed) - val x25519KeyPair = keyPairGenerationResult.x25519KeyPair - KeyPairUtilities.store(this@LinkDeviceActivity, seed, keyPairGenerationResult.ed25519KeyPair, x25519KeyPair) - val userHexEncodedPublicKey = x25519KeyPair.hexEncodedPublicKey - val registrationID = KeyHelper.generateRegistrationId(false) - TextSecurePreferences.setLocalRegistrationId(this@LinkDeviceActivity, registrationID) - TextSecurePreferences.setLocalNumber(this@LinkDeviceActivity, userHexEncodedPublicKey) - TextSecurePreferences.setRestorationTime(this@LinkDeviceActivity, System.currentTimeMillis()) - TextSecurePreferences.setHasViewedSeed(this@LinkDeviceActivity, true) - - binding.loader.isVisible = true - val snackBar = Snackbar.make(binding.containerLayout, R.string.activity_link_device_skip_prompt,Snackbar.LENGTH_INDEFINITE) - .setAction(R.string.registration_activity__skip) { register(true) } - - val skipJob = launch { - delay(30_000L) - snackBar.show() - // show a dialog or something saying do you want to skip this bit? - } - // start polling and wait for updated message - ApplicationContext.getInstance(this@LinkDeviceActivity).apply { - startPollingIfNeeded() - } - TextSecurePreferences.events.filter { it == TextSecurePreferences.CONFIGURATION_SYNCED }.collect { - // handle we've synced - snackBar.dismiss() - skipJob.cancel() - register(false) - } - - binding.loader.isVisible = false - } - } - - private fun register(skipped: Boolean) { - restoreJob?.cancel() - binding.loader.isVisible = false - TextSecurePreferences.setLastConfigurationSyncTime(this, System.currentTimeMillis()) - val intent = Intent(this@LinkDeviceActivity, if (skipped) DisplayNameActivity::class.java else PNModeActivity::class.java) - intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK - push(intent) - } - // endregion -} - -// region Adapter -private class LinkDeviceActivityAdapter(private val activity: LinkDeviceActivity) : FragmentPagerAdapter(activity.supportFragmentManager) { - val recoveryPhraseFragment = RecoveryPhraseFragment() - - override fun getCount(): Int { - return 2 - } - - override fun getItem(index: Int): Fragment { - return when (index) { - 0 -> recoveryPhraseFragment - 1 -> { - val result = ScanQRCodeWrapperFragment() - result.delegate = activity - result.message = activity.getString(R.string.activity_link_device_qr_message) - result - } - else -> throw IllegalStateException() - } - } - - override fun getPageTitle(index: Int): CharSequence { - return when (index) { - 0 -> activity.getString(R.string.activity_link_device_recovery_phrase) - 1 -> activity.getString(R.string.activity_link_device_scan_qr_code) - else -> throw IllegalStateException() - } - } -} -// endregion - -// region Recovery Phrase Fragment -class RecoveryPhraseFragment : Fragment() { - private lateinit var binding: FragmentRecoveryPhraseBinding - - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - binding = FragmentRecoveryPhraseBinding.inflate(inflater, container, false) - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - with(binding) { - mnemonicEditText.imeOptions = EditorInfo.IME_ACTION_DONE or 16777216 // Always use incognito keyboard - mnemonicEditText.setRawInputType(InputType.TYPE_CLASS_TEXT) - mnemonicEditText.setOnEditorActionListener { v, actionID, _ -> - if (actionID == EditorInfo.IME_ACTION_DONE) { - val imm = v.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager - imm.hideSoftInputFromWindow(v.windowToken, 0) - handleContinueButtonTapped() - true - } else { - false - } - } - continueButton?.setOnClickListener { handleContinueButtonTapped() } - } - } - - private fun handleContinueButtonTapped() { - val mnemonic = binding.mnemonicEditText.text?.trim().toString() - (requireActivity() as LinkDeviceActivity).continueWithMnemonic(mnemonic) - } -} -// endregion diff --git a/app/src/main/java/com/thoughtcrimes/securesms/onboarding/RecoveryPhraseRestoreActivity.kt b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/RecoveryPhraseRestoreActivity.kt index 5d71f63ec..6929fb17a 100644 --- a/app/src/main/java/com/thoughtcrimes/securesms/onboarding/RecoveryPhraseRestoreActivity.kt +++ b/app/src/main/java/com/thoughtcrimes/securesms/onboarding/RecoveryPhraseRestoreActivity.kt @@ -3,18 +3,11 @@ package com.thoughtcrimes.securesms.onboarding import android.content.ClipboardManager import android.content.Context import android.content.Intent -import android.graphics.Typeface import android.net.Uri import android.os.Bundle import android.text.Editable import android.text.InputFilter -import android.text.Spannable -import android.text.SpannableStringBuilder import android.text.TextWatcher -import android.text.method.LinkMovementMethod -import android.text.style.ClickableSpan -import android.text.style.StyleSpan -import android.view.View import android.widget.Toast import com.beldex.libbchat.utilities.TextSecurePreferences import com.beldex.libsignal.crypto.MnemonicCodec @@ -57,23 +50,6 @@ class RecoveryPhraseRestoreActivity : BaseActionBarActivity() { Toast.makeText(this,"Please enter valid seed",Toast.LENGTH_SHORT).show() } } - val termsExplanation = SpannableStringBuilder("By using this service, you agree to our Terms of Service and Privacy Policy") - termsExplanation.setSpan(StyleSpan(Typeface.BOLD), 40, 56, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - termsExplanation.setSpan(object : ClickableSpan() { - - override fun onClick(widget: View) { - openURL("https://www.beldex.io/") - } - }, 40, 56, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - termsExplanation.setSpan(StyleSpan(Typeface.BOLD), 61, 75, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - termsExplanation.setSpan(object : ClickableSpan() { - - override fun onClick(widget: View) { - openURL("https://www.beldex.io/") - } - }, 61, 75, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE) - binding.termsTextView.movementMethod = LinkMovementMethod.getInstance() - binding.termsTextView.text = termsExplanation binding.mnemonicEditText.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {} @@ -101,11 +77,6 @@ class RecoveryPhraseRestoreActivity : BaseActionBarActivity() { binding.recoveryPhraseCountWord.text = "0/25" } - /* binding.recoveryPhrasePasteIcon?.setOnClickListener { - val clipboard = getSystemService(CLIPBOARD_SERVICE) as ClipboardManager - binding.mnemonicEditText.setText(clipboard.text.toString()) - }*/ - binding.recoveryPhrasePasteIcon.setOnClickListener { val clipboard = this.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager //since the clipboard contains plain text. diff --git a/app/src/main/java/com/thoughtcrimes/securesms/seed/RecoveryGetSeedDetailsActivity.kt b/app/src/main/java/com/thoughtcrimes/securesms/seed/RecoveryGetSeedDetailsActivity.kt index 0fc340ddc..a8a912228 100644 --- a/app/src/main/java/com/thoughtcrimes/securesms/seed/RecoveryGetSeedDetailsActivity.kt +++ b/app/src/main/java/com/thoughtcrimes/securesms/seed/RecoveryGetSeedDetailsActivity.kt @@ -224,12 +224,14 @@ class RecoveryGetSeedDetailsActivity : BaseActionBarActivity() { } binding.restoreFromDateButton.setOnClickListener { + binding.restoreFromSeedBlockHeightTitle.text = getString(R.string.restore_from_date_title) binding.restoreSeedWalletRestoreDateCard.visibility = View.VISIBLE binding.restoreSeedWalletRestoreHeightCard.visibility = View.GONE binding.restoreFromHeightButton.visibility = View.VISIBLE binding.restoreFromDateButton.visibility = View.GONE } binding.restoreFromHeightButton.setOnClickListener { + binding.restoreFromSeedBlockHeightTitle.text = getString(R.string.restore_from_height_title) binding.restoreSeedWalletRestoreDateCard.visibility = View.GONE binding.restoreSeedWalletRestoreHeightCard.visibility = View.VISIBLE binding.restoreFromHeightButton.visibility = View.GONE diff --git a/app/src/main/res/drawable-notnight/prominent_filled_button_medium_background.xml b/app/src/main/res/drawable-notnight/prominent_filled_button_medium_background.xml index 3ef537b17..cb824f931 100644 --- a/app/src/main/res/drawable-notnight/prominent_filled_button_medium_background.xml +++ b/app/src/main/res/drawable-notnight/prominent_filled_button_medium_background.xml @@ -5,7 +5,7 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable-notnight/prominent_outline_button_medium_background.xml b/app/src/main/res/drawable-notnight/prominent_outline_button_medium_background.xml index db01693cf..66c424213 100644 --- a/app/src/main/res/drawable-notnight/prominent_outline_button_medium_background.xml +++ b/app/src/main/res/drawable-notnight/prominent_outline_button_medium_background.xml @@ -5,7 +5,7 @@ - + - + \ No newline at end of file diff --git a/app/src/main/res/drawable/calendar.xml b/app/src/main/res/drawable/calendar.xml index 3501115f3..23f0bc0f6 100644 --- a/app/src/main/res/drawable/calendar.xml +++ b/app/src/main/res/drawable/calendar.xml @@ -5,5 +5,5 @@ android:viewportHeight="20"> + android:fillColor="#EBEBEB"/> diff --git a/app/src/main/res/drawable/ic_paste_seed.xml b/app/src/main/res/drawable/ic_paste_seed.xml new file mode 100644 index 000000000..241a928aa --- /dev/null +++ b/app/src/main/res/drawable/ic_paste_seed.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/ic_restore_from_date_calendar.xml b/app/src/main/res/drawable/ic_restore_from_date_calendar.xml new file mode 100644 index 000000000..849b3f3c4 --- /dev/null +++ b/app/src/main/res/drawable/ic_restore_from_date_calendar.xml @@ -0,0 +1,15 @@ + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_restore_from_height.xml b/app/src/main/res/drawable/ic_restore_from_height.xml new file mode 100644 index 000000000..74a98682c --- /dev/null +++ b/app/src/main/res/drawable/ic_restore_from_height.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_right_arrow.xml b/app/src/main/res/drawable/ic_right_arrow.xml new file mode 100644 index 000000000..22f26b72e --- /dev/null +++ b/app/src/main/res/drawable/ic_right_arrow.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/page_background.xml b/app/src/main/res/drawable/page_background.xml new file mode 100644 index 000000000..8145f296c --- /dev/null +++ b/app/src/main/res/drawable/page_background.xml @@ -0,0 +1,11 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/prominent_filled_button_medium_background.xml b/app/src/main/res/drawable/prominent_filled_button_medium_background.xml index 3ef537b17..cb824f931 100644 --- a/app/src/main/res/drawable/prominent_filled_button_medium_background.xml +++ b/app/src/main/res/drawable/prominent_filled_button_medium_background.xml @@ -5,7 +5,7 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/prominent_filled_button_medium_background_blue.xml b/app/src/main/res/drawable/prominent_filled_button_medium_background_blue.xml index 9c85c952e..a99d23fd3 100644 --- a/app/src/main/res/drawable/prominent_filled_button_medium_background_blue.xml +++ b/app/src/main/res/drawable/prominent_filled_button_medium_background_blue.xml @@ -5,7 +5,7 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/prominent_outline_button_medium_background.xml b/app/src/main/res/drawable/prominent_outline_button_medium_background.xml index 327d510cf..66c424213 100644 --- a/app/src/main/res/drawable/prominent_outline_button_medium_background.xml +++ b/app/src/main/res/drawable/prominent_outline_button_medium_background.xml @@ -5,7 +5,7 @@ - + - + \ No newline at end of file diff --git a/app/src/main/res/layout-sw400dp/activity_recovery_phrase_restore.xml b/app/src/main/res/layout-sw400dp/activity_recovery_phrase_restore.xml index b7169995e..653d9c75d 100644 --- a/app/src/main/res/layout-sw400dp/activity_recovery_phrase_restore.xml +++ b/app/src/main/res/layout-sw400dp/activity_recovery_phrase_restore.xml @@ -1,139 +1,131 @@ + android:background="@color/action_bar_background" + android:orientation="vertical"> - + android:layout_height="match_parent" + android:background="@drawable/page_background" + android:orientation="vertical"> - + - - - - - - - - + + + + + + + + + +