mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
android, desktop: offer to create 1-time link on address views (#5253)
This commit is contained in:
+1
-1
@@ -174,7 +174,7 @@ private fun ModalData.NewChatSheetLayout(
|
||||
val actionButtonsOriginal = listOf(
|
||||
Triple(
|
||||
painterResource(MR.images.ic_add_link),
|
||||
stringResource(MR.strings.add_contact_tab),
|
||||
stringResource(MR.strings.create_1_time_link),
|
||||
addContact,
|
||||
),
|
||||
Triple(
|
||||
|
||||
+1
-1
@@ -98,7 +98,7 @@ fun ModalData.NewChatView(rh: RemoteHostInfo?, selection: NewChatOption, showQRC
|
||||
val tabTitles = NewChatOption.values().map {
|
||||
when(it) {
|
||||
NewChatOption.INVITE ->
|
||||
stringResource(MR.strings.add_contact_tab)
|
||||
stringResource(MR.strings.one_time_link_short)
|
||||
NewChatOption.CONNECT ->
|
||||
stringResource(MR.strings.connect_via_link)
|
||||
}
|
||||
|
||||
+54
-8
@@ -3,29 +3,57 @@ package chat.simplex.common.views.usersettings
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.shape.CircleShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.*
|
||||
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.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import chat.simplex.common.platform.ColumnWithScrollBar
|
||||
import chat.simplex.common.platform.chatModel
|
||||
import chat.simplex.common.ui.theme.DEFAULT_PADDING
|
||||
import chat.simplex.common.ui.theme.DEFAULT_PADDING_HALF
|
||||
import dev.icerock.moko.resources.compose.stringResource
|
||||
import chat.simplex.common.views.helpers.*
|
||||
import chat.simplex.common.views.onboarding.ReadableText
|
||||
import chat.simplex.common.views.onboarding.ReadableTextWithLink
|
||||
import chat.simplex.common.views.newchat.*
|
||||
import chat.simplex.common.views.onboarding.*
|
||||
import chat.simplex.res.MR
|
||||
import dev.icerock.moko.resources.compose.painterResource
|
||||
|
||||
@Composable
|
||||
fun UserAddressLearnMore(showCreateAddressButton: Boolean = false) {
|
||||
ColumnWithScrollBar(Modifier .padding(horizontal = DEFAULT_PADDING)) {
|
||||
AppBarTitle(stringResource(MR.strings.simplex_address), withPadding = false)
|
||||
ReadableText(MR.strings.you_can_share_your_address)
|
||||
AppBarTitle(stringResource(MR.strings.address_or_1_time_link), withPadding = false)
|
||||
|
||||
Row {
|
||||
Icon(painterResource(MR.images.ic_mail), null, tint = MaterialTheme.colors.secondary)
|
||||
Spacer(Modifier.width(DEFAULT_PADDING_HALF))
|
||||
ReadableText(MR.strings.share_address_publicly, style = MaterialTheme.typography.h3.copy(fontWeight = FontWeight.Bold))
|
||||
}
|
||||
ReadableText(MR.strings.share_simplex_address_on_social_media)
|
||||
ReadableText(MR.strings.you_wont_lose_your_contacts_if_delete_address)
|
||||
ReadableText(MR.strings.you_can_accept_or_reject_connection)
|
||||
ReadableTextWithLink(MR.strings.read_more_in_user_guide_with_link, "https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address")
|
||||
|
||||
Row(Modifier.padding(top = DEFAULT_PADDING_HALF)) {
|
||||
Icon(painterResource(MR.images.ic_add_link), null, tint = MaterialTheme.colors.secondary)
|
||||
Spacer(Modifier.width(DEFAULT_PADDING_HALF))
|
||||
ReadableText(MR.strings.share_1_time_link_with_a_friend, style = MaterialTheme.typography.h3.copy(fontWeight = FontWeight.Bold))
|
||||
}
|
||||
ReadableText(MR.strings.one_time_link_can_be_used_with_one_contact_only)
|
||||
ReadableText(MR.strings.you_can_set_connection_name_to_remember)
|
||||
|
||||
if (!showCreateAddressButton) {
|
||||
Row(Modifier.padding(top = DEFAULT_PADDING_HALF)) {
|
||||
Icon(painterResource(MR.images.ic_shield), null, tint = MaterialTheme.colors.secondary)
|
||||
Spacer(Modifier.width(DEFAULT_PADDING_HALF))
|
||||
ReadableText(MR.strings.connection_security, style = MaterialTheme.typography.h3.copy(fontWeight = FontWeight.Bold))
|
||||
}
|
||||
ReadableText(MR.strings.simplex_address_and_1_time_links_are_safe_to_share)
|
||||
ReadableText(MR.strings.to_protect_against_your_link_replaced_compare_codes)
|
||||
ReadableTextWithLink(MR.strings.read_more_in_user_guide_with_link, "https://simplex.chat/docs/guide/making-connections.html#comparison-of-1-time-invitation-links-and-simplex-contact-addresses")
|
||||
}
|
||||
|
||||
if (showCreateAddressButton) {
|
||||
Spacer(Modifier.weight(1f))
|
||||
@@ -33,7 +61,7 @@ fun UserAddressLearnMore(showCreateAddressButton: Boolean = false) {
|
||||
Button(
|
||||
onClick = {
|
||||
ModalManager.start.showModalCloseable { close ->
|
||||
UserAddressView(chatModel = chatModel, shareViaProfile = false, autoCreateAddress = true, close = close)
|
||||
UserAddressView(chatModel = chatModel, shareViaProfile = false, autoCreateAddress = true, close = { ModalManager.start.closeModals() })
|
||||
}
|
||||
},
|
||||
shape = CircleShape,
|
||||
@@ -42,6 +70,24 @@ fun UserAddressLearnMore(showCreateAddressButton: Boolean = false) {
|
||||
) {
|
||||
Text(stringResource(MR.strings.create_simplex_address), style = MaterialTheme.typography.h2, color = Color.White, fontSize = 18.sp, fontWeight = FontWeight.Medium)
|
||||
}
|
||||
|
||||
val closeAll = { ModalManager.start.closeModals() }
|
||||
TextButton(
|
||||
onClick = {
|
||||
ModalManager.start.showModalCloseable(endButtons = { AddContactLearnMoreButton() }) { _ ->
|
||||
NewChatView(chatModel.currentRemoteHost.value, NewChatOption.INVITE, close = closeAll)
|
||||
}
|
||||
},
|
||||
Modifier.padding(top = DEFAULT_PADDING, bottom = DEFAULT_PADDING * 2).clip(CircleShape)
|
||||
) {
|
||||
Text(
|
||||
stringResource(MR.strings.create_1_time_link),
|
||||
Modifier.padding(start = DEFAULT_PADDING_HALF, end = DEFAULT_PADDING_HALF, bottom = 5.dp),
|
||||
color = MaterialTheme.colors.primary,
|
||||
fontWeight = FontWeight.Medium,
|
||||
textAlign = TextAlign.Center
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+117
-36
@@ -31,7 +31,6 @@ import chat.simplex.res.MR
|
||||
@Composable
|
||||
fun UserAddressView(
|
||||
chatModel: ChatModel,
|
||||
viaCreateLinkView: Boolean = false,
|
||||
shareViaProfile: Boolean = false,
|
||||
autoCreateAddress: Boolean = false,
|
||||
close: () -> Unit
|
||||
@@ -39,7 +38,6 @@ fun UserAddressView(
|
||||
// TODO close when remote host changes
|
||||
val shareViaProfile = remember { mutableStateOf(shareViaProfile) }
|
||||
var progressIndicator by remember { mutableStateOf(false) }
|
||||
val onCloseHandler: MutableState<(close: () -> Unit) -> Unit> = remember { mutableStateOf({ _ -> }) }
|
||||
val user = remember { chatModel.currentUser }
|
||||
KeyChangeEffect(user.value?.remoteHostId, user.value?.userId) {
|
||||
close()
|
||||
@@ -82,7 +80,7 @@ fun UserAddressView(
|
||||
}
|
||||
|
||||
LaunchedEffect(autoCreateAddress) {
|
||||
if (autoCreateAddress) {
|
||||
if (chatModel.userAddress.value == null && autoCreateAddress) {
|
||||
createAddress()
|
||||
}
|
||||
}
|
||||
@@ -94,7 +92,6 @@ fun UserAddressView(
|
||||
user = user.value,
|
||||
userAddress = userAddress.value,
|
||||
shareViaProfile,
|
||||
onCloseHandler,
|
||||
createAddress = { createAddress() },
|
||||
learnMore = {
|
||||
ModalManager.start.showModal {
|
||||
@@ -105,7 +102,7 @@ fun UserAddressView(
|
||||
sendEmail = { userAddress ->
|
||||
uriHandler.sendEmail(
|
||||
generalGetString(MR.strings.email_invite_subject),
|
||||
generalGetString(MR.strings.email_invite_body).format(simplexChatLink( userAddress.connReqContact))
|
||||
generalGetString(MR.strings.email_invite_body).format(simplexChatLink(userAddress.connReqContact))
|
||||
)
|
||||
},
|
||||
setProfileAddress = ::setProfileAddress,
|
||||
@@ -141,12 +138,8 @@ fun UserAddressView(
|
||||
)
|
||||
}
|
||||
|
||||
if (viaCreateLinkView) {
|
||||
ModalView(close = close) {
|
||||
showLayout()
|
||||
} else {
|
||||
ModalView(close = { onCloseHandler.value(close) }) {
|
||||
showLayout()
|
||||
}
|
||||
}
|
||||
|
||||
if (progressIndicator) {
|
||||
@@ -173,7 +166,6 @@ private fun UserAddressLayout(
|
||||
user: User?,
|
||||
userAddress: UserContactLinkRec?,
|
||||
shareViaProfile: MutableState<Boolean>,
|
||||
onCloseHandler: MutableState<(close: () -> Unit) -> Unit>,
|
||||
createAddress: () -> Unit,
|
||||
learnMore: () -> Unit,
|
||||
share: (String) -> Unit,
|
||||
@@ -190,45 +182,41 @@ private fun UserAddressLayout(
|
||||
verticalArrangement = Arrangement.SpaceEvenly
|
||||
) {
|
||||
if (userAddress == null) {
|
||||
SectionView {
|
||||
SectionView(generalGetString(MR.strings.for_social_media).uppercase()) {
|
||||
CreateAddressButton(createAddress)
|
||||
SectionTextFooter(stringResource(MR.strings.create_address_and_let_people_connect))
|
||||
}
|
||||
|
||||
SectionDividerSpaced()
|
||||
SectionView(generalGetString(MR.strings.or_to_share_privately).uppercase()) {
|
||||
CreateOneTimeLinkButton()
|
||||
}
|
||||
|
||||
SectionDividerSpaced(maxTopPadding = true, maxBottomPadding = false)
|
||||
SectionView {
|
||||
LearnMoreButton(learnMore)
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
onCloseHandler.value = { close -> close() }
|
||||
}
|
||||
} else {
|
||||
val autoAcceptState = remember { mutableStateOf(AutoAcceptState(userAddress)) }
|
||||
val autoAcceptStateSaved = remember { mutableStateOf(autoAcceptState.value) }
|
||||
SectionView(stringResource(MR.strings.address_section_title).uppercase()) {
|
||||
SectionView(stringResource(MR.strings.for_social_media).uppercase()) {
|
||||
SimpleXLinkQRCode(userAddress.connReqContact)
|
||||
ShareAddressButton { share(simplexChatLink(userAddress.connReqContact)) }
|
||||
ShareViaEmailButton { sendEmail(userAddress) }
|
||||
ShareWithContactsButton(shareViaProfile, setProfileAddress)
|
||||
AutoAcceptToggle(autoAcceptState) { saveAas(autoAcceptState.value, autoAcceptStateSaved) }
|
||||
LearnMoreButton(learnMore)
|
||||
// ShareViaEmailButton { sendEmail(userAddress) }
|
||||
AddressSettingsButton(user, userAddress, shareViaProfile, setProfileAddress, saveAas)
|
||||
}
|
||||
if (autoAcceptState.value.enable) {
|
||||
SectionDividerSpaced()
|
||||
AutoAcceptSection(autoAcceptState, autoAcceptStateSaved, saveAas)
|
||||
|
||||
SectionDividerSpaced()
|
||||
SectionView(generalGetString(MR.strings.or_to_share_privately).uppercase()) {
|
||||
CreateOneTimeLinkButton()
|
||||
}
|
||||
SectionDividerSpaced(maxBottomPadding = false)
|
||||
SectionView {
|
||||
LearnMoreButton(learnMore)
|
||||
}
|
||||
|
||||
SectionDividerSpaced(maxBottomPadding = false)
|
||||
|
||||
SectionView {
|
||||
DeleteAddressButton(deleteAddress)
|
||||
SectionTextFooter(stringResource(MR.strings.your_contacts_will_remain_connected))
|
||||
}
|
||||
LaunchedEffect(Unit) {
|
||||
onCloseHandler.value = { close ->
|
||||
if (autoAcceptState.value == autoAcceptStateSaved.value) close()
|
||||
else showUnsavedChangesAlert({ saveAas(autoAcceptState.value, autoAcceptStateSaved); close() }, close)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
SectionBottomSpacer()
|
||||
@@ -246,11 +234,27 @@ private fun CreateAddressButton(onClick: () -> Unit) {
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CreateOneTimeLinkButton() {
|
||||
val closeAll = { ModalManager.start.closeModals() }
|
||||
SettingsActionItem(
|
||||
painterResource(MR.images.ic_add_link),
|
||||
stringResource(MR.strings.create_1_time_link),
|
||||
click = {
|
||||
ModalManager.start.showModalCloseable(endButtons = { AddContactLearnMoreButton() }) { _ ->
|
||||
NewChatView(chatModel.currentRemoteHost.value, NewChatOption.INVITE, close = closeAll)
|
||||
}
|
||||
},
|
||||
iconColor = MaterialTheme.colors.primary,
|
||||
textColor = MaterialTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun LearnMoreButton(onClick: () -> Unit) {
|
||||
SettingsActionItem(
|
||||
painterResource(MR.images.ic_info),
|
||||
stringResource(MR.strings.learn_more_about_address),
|
||||
stringResource(MR.strings.simplex_address_or_1_time_link),
|
||||
onClick,
|
||||
)
|
||||
}
|
||||
@@ -266,6 +270,85 @@ fun ShareViaEmailButton(onClick: () -> Unit) {
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun AddressSettingsButton(
|
||||
user: User?,
|
||||
userAddress: UserContactLinkRec,
|
||||
shareViaProfile: MutableState<Boolean>,
|
||||
setProfileAddress: (Boolean) -> Unit,
|
||||
saveAas: (AutoAcceptState, MutableState<AutoAcceptState>) -> Unit,
|
||||
) {
|
||||
SettingsActionItem(
|
||||
painterResource(MR.images.ic_settings),
|
||||
stringResource(MR.strings.address_settings),
|
||||
click = {
|
||||
ModalManager.start.showCustomModal { close ->
|
||||
UserAddressSettings(user, userAddress, shareViaProfile, setProfileAddress, saveAas, close = close)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ModalData.UserAddressSettings(
|
||||
user: User?,
|
||||
userAddress: UserContactLinkRec,
|
||||
shareViaProfile: MutableState<Boolean>,
|
||||
setProfileAddress: (Boolean) -> Unit,
|
||||
saveAas: (AutoAcceptState, MutableState<AutoAcceptState>) -> Unit,
|
||||
close: () -> Unit
|
||||
) {
|
||||
val autoAcceptState = remember { stateGetOrPut("autoAcceptState") { (AutoAcceptState(userAddress)) } }
|
||||
val autoAcceptStateSaved = remember { stateGetOrPut("autoAcceptStateSaved") { (autoAcceptState.value) } }
|
||||
|
||||
fun onClose(close: () -> Unit): Boolean = if (autoAcceptState.value == autoAcceptStateSaved.value) {
|
||||
chatModel.centerPanelBackgroundClickHandler = null
|
||||
close()
|
||||
false
|
||||
} else {
|
||||
showUnsavedChangesAlert(
|
||||
save = {
|
||||
saveAas(autoAcceptState.value, autoAcceptStateSaved)
|
||||
chatModel.centerPanelBackgroundClickHandler = null
|
||||
close()
|
||||
},
|
||||
revert = {
|
||||
chatModel.centerPanelBackgroundClickHandler = null
|
||||
close()
|
||||
}
|
||||
)
|
||||
true
|
||||
}
|
||||
|
||||
LaunchedEffect(Unit) {
|
||||
// Enables unsaved changes alert on this view.
|
||||
chatModel.centerPanelBackgroundClickHandler = {
|
||||
onClose(close = { ModalManager.start.closeModals() })
|
||||
}
|
||||
}
|
||||
|
||||
ModalView(close = { onClose(close) }) {
|
||||
ColumnWithScrollBar {
|
||||
AppBarTitle(stringResource(MR.strings.address_settings), hostDevice(user?.remoteHostId))
|
||||
Column(
|
||||
Modifier.fillMaxWidth().padding(bottom = DEFAULT_PADDING_HALF),
|
||||
horizontalAlignment = Alignment.CenterHorizontally,
|
||||
verticalArrangement = Arrangement.SpaceEvenly
|
||||
) {
|
||||
SectionView {
|
||||
ShareWithContactsButton(shareViaProfile, setProfileAddress)
|
||||
AutoAcceptToggle(autoAcceptState) { saveAas(autoAcceptState.value, autoAcceptStateSaved) }
|
||||
}
|
||||
|
||||
if (autoAcceptState.value.enable) {
|
||||
SectionDividerSpaced()
|
||||
AutoAcceptSection(autoAcceptState, autoAcceptStateSaved, saveAas)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun ShareWithContactsButton(shareViaProfile: MutableState<Boolean>, setProfileAddress: (Boolean) -> Unit) {
|
||||
PreferenceToggleWithIcon(
|
||||
@@ -441,7 +524,6 @@ fun PreviewUserAddressLayoutNoAddress() {
|
||||
setProfileAddress = { _ -> },
|
||||
learnMore = {},
|
||||
shareViaProfile = remember { mutableStateOf(false) },
|
||||
onCloseHandler = remember { mutableStateOf({}) },
|
||||
sendEmail = {},
|
||||
)
|
||||
}
|
||||
@@ -475,7 +557,6 @@ fun PreviewUserAddressLayoutAddressCreated() {
|
||||
setProfileAddress = { _ -> },
|
||||
learnMore = {},
|
||||
shareViaProfile = remember { mutableStateOf(false) },
|
||||
onCloseHandler = remember { mutableStateOf({}) },
|
||||
sendEmail = {},
|
||||
)
|
||||
}
|
||||
|
||||
@@ -675,10 +675,19 @@
|
||||
<string name="if_you_cant_meet_in_person">If you can\'t meet in person, show QR code in a video call, or share the link.</string>
|
||||
|
||||
<!-- User Address Learn More - UserAddressLearnMore.kt -->
|
||||
<string name="share_address_publicly">Share address publicly</string>
|
||||
<string name="share_simplex_address_on_social_media">Share SimpleX address on social media.</string>
|
||||
<string name="you_can_share_your_address">You can share your address as a link or QR code - anybody can connect to you.</string>
|
||||
<string name="you_wont_lose_your_contacts_if_delete_address">You won\'t lose your contacts if you later delete your address.</string>
|
||||
<string name="share_1_time_link_with_a_friend">Share 1-time link with a friend</string>
|
||||
<string name="one_time_link_can_be_used_with_one_contact_only"><![CDATA[1-time link can be used <i>with one contact only</i> - share in person or via any messenger.]]></string>
|
||||
<string name="you_can_set_connection_name_to_remember">You can set connection name, to remember who the link was shared with.</string>
|
||||
<string name="connection_security">Connection security</string>
|
||||
<string name="simplex_address_and_1_time_links_are_safe_to_share">SimpleX address and 1-time links are safe to share via any messenger.</string>
|
||||
<string name="to_protect_against_your_link_replaced_compare_codes">To protect against your link being replaced, you can compare contact security codes.</string>
|
||||
<string name="you_can_accept_or_reject_connection">When people request to connect, you can accept or reject it.</string>
|
||||
<string name="read_more_in_user_guide_with_link"><![CDATA[Read more in <font color="#0088ff">User Guide</font>.]]></string>
|
||||
<string name="address_or_1_time_link">Address or 1-time link?</string>
|
||||
|
||||
<!-- PasteToConnect.kt -->
|
||||
<string name="connect_via_link">Connect via link</string>
|
||||
@@ -917,6 +926,11 @@
|
||||
<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>
|
||||
<string name="for_social_media">For social media</string>
|
||||
<string name="or_to_share_privately">Or to share privately</string>
|
||||
<string name="simplex_address_or_1_time_link">SimpleX address or 1-time link?</string>
|
||||
<string name="create_1_time_link">Create 1-time link</string>
|
||||
<string name="address_settings">Address settings</string>
|
||||
|
||||
<!-- CreateSimpleXAddress.kt -->
|
||||
<string name="continue_to_next_step">Continue</string>
|
||||
|
||||
Reference in New Issue
Block a user