mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-03-30 20:45:49 +00:00
android: create address during onboarding (#2374)
* android: create address during onboarding * refactor --------- Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
41368c85bf
commit
649c104d29
@@ -17,7 +17,6 @@ import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
@@ -500,7 +499,8 @@ fun MainPage(
|
||||
}
|
||||
onboarding == OnboardingStage.Step1_SimpleXInfo -> SimpleXInfo(chatModel, onboarding = true)
|
||||
onboarding == OnboardingStage.Step2_CreateProfile -> CreateProfile(chatModel) {}
|
||||
onboarding == OnboardingStage.Step3_SetNotificationsMode -> SetNotificationsMode(chatModel)
|
||||
onboarding == OnboardingStage.Step3_CreateSimpleXAddress -> CreateSimpleXAddress(chatModel)
|
||||
onboarding == OnboardingStage.Step4_SetNotificationsMode -> SetNotificationsMode(chatModel)
|
||||
}
|
||||
ModalManager.shared.showInView()
|
||||
val invitation = chatModel.activeCallInvitation.value
|
||||
|
||||
@@ -125,7 +125,7 @@ fun createProfile(chatModel: ChatModel, displayName: String, fullName: String, c
|
||||
chatModel.currentUser.value = user
|
||||
if (chatModel.users.isEmpty()) {
|
||||
chatModel.controller.startChat(user)
|
||||
chatModel.onboardingStage.value = OnboardingStage.Step3_SetNotificationsMode
|
||||
chatModel.onboardingStage.value = OnboardingStage.Step3_CreateSimpleXAddress
|
||||
SimplexApp.context.chatModel.controller.ntfManager.createNtfChannelsMaybeShowAlert()
|
||||
} else {
|
||||
val users = chatModel.controller.listUsers()
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.Manifest
|
||||
import android.content.*
|
||||
import android.net.Uri
|
||||
import android.provider.MediaStore
|
||||
import android.util.Log
|
||||
import android.webkit.MimeTypeMap
|
||||
import android.widget.Toast
|
||||
import androidx.activity.compose.ManagedActivityResultLauncher
|
||||
@@ -48,6 +49,17 @@ fun copyText(cxt: Context, text: String) {
|
||||
clipboard?.setPrimaryClip(ClipData.newPlainText("text", text))
|
||||
}
|
||||
|
||||
fun sendEmail(context: Context, subject: String, body: CharSequence) {
|
||||
val emailIntent = Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"))
|
||||
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject)
|
||||
emailIntent.putExtra(Intent.EXTRA_TEXT, body)
|
||||
try {
|
||||
context.startActivity(emailIntent)
|
||||
} catch (e: ActivityNotFoundException) {
|
||||
Log.e(TAG, "No activity was found for handling email intent")
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun rememberSaveFileLauncher(cxt: Context, ciFile: CIFile?): ManagedActivityResultLauncher<String, Uri?> =
|
||||
rememberLauncherForActivityResult(
|
||||
|
||||
@@ -0,0 +1,168 @@
|
||||
package chat.simplex.app.views.onboarding
|
||||
|
||||
import SectionBottomSpacer
|
||||
import android.util.Log
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import androidx.compose.ui.res.stringResource
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import chat.simplex.app.R
|
||||
import chat.simplex.app.TAG
|
||||
import chat.simplex.app.model.ChatModel
|
||||
import chat.simplex.app.model.UserContactLinkRec
|
||||
import chat.simplex.app.ui.theme.*
|
||||
import chat.simplex.app.views.helpers.*
|
||||
import chat.simplex.app.views.newchat.QRCode
|
||||
|
||||
@Composable
|
||||
fun CreateSimpleXAddress(m: ChatModel) {
|
||||
val context = LocalContext.current
|
||||
var progressIndicator by remember { mutableStateOf(false) }
|
||||
val userAddress = remember { m.userAddress }
|
||||
|
||||
CreateSimpleXAddressLayout(
|
||||
userAddress.value,
|
||||
share = { address: String -> shareText(context, address) },
|
||||
sendEmail = { address ->
|
||||
sendEmail(
|
||||
context,
|
||||
generalGetString(R.string.email_invite_subject),
|
||||
generalGetString(R.string.email_invite_body).format(address.connReqContact)
|
||||
)
|
||||
},
|
||||
createAddress = {
|
||||
withApi {
|
||||
progressIndicator = true
|
||||
val connReqContact = m.controller.apiCreateUserAddress()
|
||||
if (connReqContact != null) {
|
||||
m.userAddress.value = UserContactLinkRec(connReqContact)
|
||||
try {
|
||||
val u = m.controller.apiSetProfileAddress(true)
|
||||
if (u != null) {
|
||||
m.updateUser(u)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
Log.e(TAG, "CreateSimpleXAddress apiSetProfileAddress: ${e.stackTraceToString()}")
|
||||
}
|
||||
progressIndicator = false
|
||||
}
|
||||
}
|
||||
},
|
||||
nextStep = {
|
||||
m.onboardingStage.value = OnboardingStage.Step4_SetNotificationsMode
|
||||
},
|
||||
)
|
||||
|
||||
if (progressIndicator) {
|
||||
ProgressIndicator()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CreateSimpleXAddressLayout(
|
||||
userAddress: UserContactLinkRec?,
|
||||
share: (String) -> Unit,
|
||||
sendEmail: (UserContactLinkRec) -> Unit,
|
||||
createAddress: () -> Unit,
|
||||
nextStep: () -> Unit,
|
||||
) {
|
||||
Column(
|
||||
Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(top = DEFAULT_PADDING),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
) {
|
||||
AppBarTitle(stringResource(R.string.simplex_address))
|
||||
|
||||
Spacer(Modifier.weight(1f))
|
||||
|
||||
if (userAddress != null) {
|
||||
QRCode(userAddress.connReqContact, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f))
|
||||
ShareAddressButton { share(userAddress.connReqContact) }
|
||||
Spacer(Modifier.weight(1f))
|
||||
ShareViaEmailButton { sendEmail(userAddress) }
|
||||
Spacer(Modifier.weight(1f))
|
||||
ContinueButton(nextStep)
|
||||
} else {
|
||||
CreateAddressButton(createAddress)
|
||||
TextBelowButton(stringResource(R.string.your_contacts_will_see_it))
|
||||
Spacer(Modifier.weight(1f))
|
||||
SkipButton(nextStep)
|
||||
}
|
||||
SectionBottomSpacer()
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CreateAddressButton(onClick: () -> Unit) {
|
||||
TextButton(onClick) {
|
||||
Text(stringResource(R.string.create_simplex_address), style = MaterialTheme.typography.h2, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ShareAddressButton(onClick: () -> Unit) {
|
||||
SimpleButtonFrame(onClick) {
|
||||
Icon(
|
||||
painterResource(R.drawable.ic_share_filled), generalGetString(R.string.share_verb), tint = MaterialTheme.colors.primary,
|
||||
modifier = Modifier.padding(end = 8.dp).size(18.dp)
|
||||
)
|
||||
Text(stringResource(R.string.share_verb), style = MaterialTheme.typography.caption, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ShareViaEmailButton(onClick: () -> Unit) {
|
||||
SimpleButtonFrame(onClick) {
|
||||
Icon(
|
||||
painterResource(R.drawable.ic_mail), generalGetString(R.string.share_verb), tint = MaterialTheme.colors.primary,
|
||||
modifier = Modifier.padding(end = 8.dp).size(30.dp)
|
||||
)
|
||||
Text(stringResource(R.string.invite_friends), style = MaterialTheme.typography.h6, color = MaterialTheme.colors.primary)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ContinueButton(onClick: () -> Unit) {
|
||||
SimpleButtonIconEnded(stringResource(R.string.continue_to_next_step), painterResource(R.drawable.ic_chevron_right), click = onClick)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun SkipButton(onClick: () -> Unit) {
|
||||
SimpleButtonIconEnded(stringResource(R.string.dont_create_address), painterResource(R.drawable.ic_chevron_right), click = onClick)
|
||||
TextBelowButton(stringResource(R.string.you_can_create_it_later))
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun TextBelowButton(text: String) {
|
||||
Text(
|
||||
text,
|
||||
Modifier
|
||||
.fillMaxWidth()
|
||||
.padding(horizontal = DEFAULT_PADDING * 3),
|
||||
style = MaterialTheme.typography.subtitle1,
|
||||
textAlign = TextAlign.Center,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ProgressIndicator() {
|
||||
Box(
|
||||
Modifier.fillMaxSize(),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
CircularProgressIndicator(
|
||||
Modifier
|
||||
.padding(horizontal = 2.dp)
|
||||
.size(30.dp),
|
||||
color = MaterialTheme.colors.secondary,
|
||||
strokeWidth = 3.dp
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
package chat.simplex.app.views.onboarding
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.material.MaterialTheme
|
||||
import androidx.compose.runtime.*
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -16,7 +14,8 @@ import kotlinx.coroutines.launch
|
||||
enum class OnboardingStage {
|
||||
Step1_SimpleXInfo,
|
||||
Step2_CreateProfile,
|
||||
Step3_SetNotificationsMode,
|
||||
Step3_CreateSimpleXAddress,
|
||||
Step4_SetNotificationsMode,
|
||||
OnboardingComplete
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ import androidx.compose.runtime.*
|
||||
import androidx.compose.runtime.saveable.rememberSaveable
|
||||
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.res.stringResource
|
||||
@@ -37,7 +36,7 @@ fun UserAddressView(
|
||||
shareViaProfile: Boolean = false,
|
||||
close: () -> Unit
|
||||
) {
|
||||
val cxt = LocalContext.current
|
||||
val context = LocalContext.current
|
||||
val shareViaProfile = remember { mutableStateOf(shareViaProfile) }
|
||||
var progressIndicator by remember { mutableStateOf(false) }
|
||||
val onCloseHandler: MutableState<(close: () -> Unit) -> Unit> = remember { mutableStateOf({ _ -> }) }
|
||||
@@ -71,7 +70,7 @@ fun UserAddressView(
|
||||
chatModel.userAddress.value = UserContactLinkRec(connReqContact)
|
||||
|
||||
AlertManager.shared.showAlertDialog(
|
||||
title = generalGetString(R.string.delete_address_with_contacts_question),
|
||||
title = generalGetString(R.string.share_address_with_contacts_question),
|
||||
text = generalGetString(R.string.add_address_to_your_profile),
|
||||
confirmText = generalGetString(R.string.share_verb),
|
||||
onConfirm = {
|
||||
@@ -95,7 +94,14 @@ fun UserAddressView(
|
||||
}
|
||||
}
|
||||
},
|
||||
share = { userAddress: String -> shareText(cxt, userAddress) },
|
||||
share = { userAddress: String -> shareText(context, userAddress) },
|
||||
sendEmail = { userAddress ->
|
||||
sendEmail(
|
||||
context,
|
||||
generalGetString(R.string.email_invite_subject),
|
||||
generalGetString(R.string.email_invite_body).format(userAddress.connReqContact)
|
||||
)
|
||||
},
|
||||
setProfileAddress = ::setProfileAddress,
|
||||
deleteAddress = {
|
||||
AlertManager.shared.showAlertDialog(
|
||||
@@ -125,7 +131,8 @@ fun UserAddressView(
|
||||
savedAAS.value = aas
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
if (viaCreateLinkView) {
|
||||
@@ -163,6 +170,7 @@ private fun UserAddressLayout(
|
||||
createAddress: () -> Unit,
|
||||
learnMore: () -> Unit,
|
||||
share: (String) -> Unit,
|
||||
sendEmail: (UserContactLinkRec) -> Unit,
|
||||
setProfileAddress: (Boolean) -> Unit,
|
||||
deleteAddress: () -> Unit,
|
||||
saveAas: (AutoAcceptState, MutableState<AutoAcceptState>) -> Unit,
|
||||
@@ -194,6 +202,7 @@ private fun UserAddressLayout(
|
||||
SectionView(stringResource(R.string.address_section_title).uppercase()) {
|
||||
QRCode(userAddress.connReqContact, Modifier.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF).aspectRatio(1f))
|
||||
ShareAddressButton { share(userAddress.connReqContact) }
|
||||
ShareViaEmailButton { sendEmail(userAddress) }
|
||||
ShareWithContactsButton(shareViaProfile, setProfileAddress)
|
||||
AutoAcceptToggle(autoAcceptState) { saveAas(autoAcceptState.value, autoAcceptStateSaved) }
|
||||
LearnMoreButton(learnMore)
|
||||
@@ -241,6 +250,17 @@ private fun LearnMoreButton(onClick: () -> Unit) {
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ShareViaEmailButton(onClick: () -> Unit) {
|
||||
SettingsActionItem(
|
||||
painterResource(R.drawable.ic_mail),
|
||||
stringResource(R.string.invite_friends),
|
||||
onClick,
|
||||
iconColor = MaterialTheme.colors.primary,
|
||||
textColor = MaterialTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ShareWithContactsButton(shareViaProfile: MutableState<Boolean>, setProfileAddress: (Boolean) -> Unit) {
|
||||
PreferenceToggleWithIcon(
|
||||
@@ -416,7 +436,8 @@ fun PreviewUserAddressLayoutNoAddress() {
|
||||
setProfileAddress = { _ -> },
|
||||
learnMore = {},
|
||||
shareViaProfile = remember { mutableStateOf(false) },
|
||||
onCloseHandler = remember { mutableStateOf({}) }
|
||||
onCloseHandler = remember { mutableStateOf({}) },
|
||||
sendEmail = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -449,7 +470,8 @@ fun PreviewUserAddressLayoutAddressCreated() {
|
||||
setProfileAddress = { _ -> },
|
||||
learnMore = {},
|
||||
shareViaProfile = remember { mutableStateOf(false) },
|
||||
onCloseHandler = remember { mutableStateOf({}) }
|
||||
onCloseHandler = remember { mutableStateOf({}) },
|
||||
sendEmail = {},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -595,7 +595,6 @@
|
||||
<string name="all_your_contacts_will_remain_connected">All your contacts will remain connected.</string>
|
||||
<string name="all_your_contacts_will_remain_connected_update_sent">All your contacts will remain connected. Profile update will be sent to your contacts.</string>
|
||||
<string name="share_link">Share link</string>
|
||||
<string name="delete_address_with_contacts_question">Share address with contacts?</string>
|
||||
<string name="add_address_to_your_profile">Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</string>
|
||||
<string name="create_address_and_let_people_connect">Create an address to let people connect with you.</string>
|
||||
<string name="create_simplex_address">Create SimpleX address</string>
|
||||
@@ -609,6 +608,15 @@
|
||||
<string name="save_settings_question">Save settings?</string>
|
||||
<string name="save_auto_accept_settings">Save auto-accept settings</string>
|
||||
<string name="delete_address">Delete address</string>
|
||||
<string name="invite_friends">Invite friends</string>
|
||||
<string name="email_invite_subject">Let\'s talk in SimpleX Chat</string>
|
||||
<string name="email_invite_body">Hi!\nConnect to me via SimpleX Chat: %s</string>
|
||||
|
||||
<!-- CreateSimpleXAddress.kt -->
|
||||
<string name="continue_to_next_step">Continue</string>
|
||||
<string name="dont_create_address">Don\'t create address</string>
|
||||
<string name="you_can_create_it_later">You can create it later</string>
|
||||
<string name="your_contacts_will_see_it">Your contacts in SimpleX will see it.\nYou can change it in Settings.</string>
|
||||
|
||||
<!-- User profile details - UserProfileView.kt -->
|
||||
<string name="display_name__field">Display name:</string>
|
||||
|
||||
Reference in New Issue
Block a user