mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2026-08-27 22:34:51 +00:00
share address
This commit is contained in:
+10
@@ -1174,6 +1174,13 @@ object ChatController {
|
||||
return null
|
||||
}
|
||||
|
||||
suspend fun apiShareMyAddress(rh: Long?, toChatType: ChatType, toChatId: Long, toScope: GroupChatScope?, sendAsGroup: Boolean): MsgContent? {
|
||||
val r = sendCmd(rh, CC.ApiShareMyAddress(toChatType, toChatId, toScope, sendAsGroup))
|
||||
if (r is API.Result && r.res is CR.ChatMsgContent) return r.res.msgContent
|
||||
apiErrorAlert("apiShareMyAddress", generalGetString(MR.strings.error_sharing_address), r)
|
||||
return null
|
||||
}
|
||||
|
||||
suspend fun apiPlanForwardChatItems(rh: Long?, fromChatType: ChatType, fromChatId: Long, fromScope: GroupChatScope?, chatItemIds: List<Long>): CR.ForwardPlan? {
|
||||
val r = sendCmd(rh, CC.ApiPlanForwardChatItems(fromChatType, fromChatId, fromScope, chatItemIds))
|
||||
if (r is API.Result && r.res is CR.ForwardPlan) return r.res
|
||||
@@ -3809,6 +3816,7 @@ sealed class CC {
|
||||
class ApiPlanForwardChatItems(val fromChatType: ChatType, val fromChatId: Long, val fromScope: GroupChatScope?, val chatItemIds: List<Long>): CC()
|
||||
class ApiForwardChatItems(val toChatType: ChatType, val toChatId: Long, val toScope: GroupChatScope?, val sendAsGroup: Boolean, val fromChatType: ChatType, val fromChatId: Long, val fromScope: GroupChatScope?, val itemIds: List<Long>, val ttl: Int?): CC()
|
||||
class ApiShareChatMsgContent(val shareChatType: ChatType, val shareChatId: Long, val toChatType: ChatType, val toChatId: Long, val toScope: GroupChatScope?, val sendAsGroup: Boolean): CC()
|
||||
class ApiShareMyAddress(val toChatType: ChatType, val toChatId: Long, val toScope: GroupChatScope?, val sendAsGroup: Boolean): CC()
|
||||
class ApiNewGroup(val userId: Long, val incognito: Boolean, val groupProfile: GroupProfile): CC()
|
||||
class ApiNewPublicGroup(val userId: Long, val incognito: Boolean, val relayIds: List<Long>, val groupProfile: GroupProfile): CC()
|
||||
class ApiGetGroupRelays(val groupId: Long): CC()
|
||||
@@ -4015,6 +4023,7 @@ sealed class CC {
|
||||
is ApiShareChatMsgContent -> {
|
||||
"/_share chat content ${chatRef(shareChatType, shareChatId, null)} ${chatRef(toChatType, toChatId, toScope)}${if (sendAsGroup) "(as_group=on)" else ""}"
|
||||
}
|
||||
is ApiShareMyAddress -> "/_share address ${chatRef(toChatType, toChatId, toScope)}${if (sendAsGroup) "(as_group=on)" else ""}"
|
||||
is ApiPlanForwardChatItems -> {
|
||||
"/_forward plan ${chatRef(fromChatType, fromChatId, fromScope)} ${chatItemIds.joinToString(",")}"
|
||||
}
|
||||
@@ -4206,6 +4215,7 @@ sealed class CC {
|
||||
is ApiGetReactionMembers -> "apiGetReactionMembers"
|
||||
is ApiForwardChatItems -> "apiForwardChatItems"
|
||||
is ApiShareChatMsgContent -> "apiShareChatMsgContent"
|
||||
is ApiShareMyAddress -> "apiShareMyAddress"
|
||||
is ApiPlanForwardChatItems -> "apiPlanForwardChatItems"
|
||||
is ApiNewGroup -> "apiNewGroup"
|
||||
is ApiNewPublicGroup -> "apiNewPublicGroup"
|
||||
|
||||
+17
@@ -526,6 +526,7 @@ fun ComposeView(
|
||||
is SharedContent.Text -> emptyList()
|
||||
is SharedContent.Forward -> emptyList()
|
||||
is SharedContent.ChatLink -> emptyList()
|
||||
is SharedContent.MyAddress -> emptyList()
|
||||
}
|
||||
// When sharing a file and pasting it in SimpleX itself, the file shouldn't be deleted before sending or before leaving the chat after sharing
|
||||
chatModel.filesToDelete.removeAll { file ->
|
||||
@@ -1543,6 +1544,22 @@ fun ComposeView(
|
||||
}
|
||||
}
|
||||
}
|
||||
is SharedContent.MyAddress -> {
|
||||
val cInfo = chat.chatInfo
|
||||
val sendAsGroup = cInfo.sendAsGroup
|
||||
withBGApi {
|
||||
val mc = chatModel.controller.apiShareMyAddress(
|
||||
chat.remoteHostId,
|
||||
cInfo.chatType, cInfo.apiId,
|
||||
cInfo.groupChatScope(), sendAsGroup
|
||||
)
|
||||
if (mc is MsgContent.MCChat) {
|
||||
composeState.value = composeState.value.copy(
|
||||
preview = ComposePreview.ChatLinkPreview(mc.chatLink, mc.ownerSig)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
null -> {}
|
||||
}
|
||||
chatModel.sharedContent.value = null
|
||||
|
||||
+5
-4
@@ -51,7 +51,7 @@ fun ShareListView(chatModel: ChatModel, stopped: Boolean) {
|
||||
}
|
||||
}
|
||||
}
|
||||
is SharedContent.ChatLink -> {
|
||||
is SharedContent.ChatLink, is SharedContent.MyAddress -> {
|
||||
hasSimplexLink = true
|
||||
}
|
||||
null -> {}
|
||||
@@ -99,9 +99,10 @@ private fun ShareListToolbar(chatModel: ChatModel, stopped: Boolean, onSearchVal
|
||||
}
|
||||
val users by remember { derivedStateOf { chatModel.users.filter { u -> u.user.activeUser || !u.user.hidden } } }
|
||||
val navButton: @Composable RowScope.() -> Unit = {
|
||||
val sharedContent = remember { chatModel.sharedContent }.value
|
||||
when {
|
||||
showSearch -> NavigationButtonBack(hideSearchOnBack)
|
||||
(users.size > 1 || chatModel.remoteHosts.isNotEmpty()) && remember { chatModel.sharedContent }.value !is SharedContent.Forward && remember { chatModel.sharedContent }.value !is SharedContent.ChatLink -> {
|
||||
(users.size > 1 || chatModel.remoteHosts.isNotEmpty()) && sharedContent !is SharedContent.Forward && sharedContent !is SharedContent.ChatLink && sharedContent !is SharedContent.MyAddress -> {
|
||||
val allRead = users
|
||||
.filter { u -> !u.user.activeUser && !u.user.hidden }
|
||||
.all { u -> u.unreadCount == 0 }
|
||||
@@ -127,7 +128,6 @@ private fun ShareListToolbar(chatModel: ChatModel, stopped: Boolean, onSearchVal
|
||||
}
|
||||
}
|
||||
else -> NavigationButtonBack(onButtonClicked = {
|
||||
val sharedContent = chatModel.sharedContent.value
|
||||
// Drop shared content
|
||||
chatModel.sharedContent.value = null
|
||||
if (sharedContent is SharedContent.Forward) {
|
||||
@@ -150,6 +150,7 @@ private fun ShareListToolbar(chatModel: ChatModel, stopped: Boolean, onSearchVal
|
||||
is SharedContent.File -> stringResource(MR.strings.share_file)
|
||||
is SharedContent.Forward -> if (v.chatItems.size > 1) stringResource(MR.strings.forward_multiple) else stringResource(MR.strings.forward_message)
|
||||
is SharedContent.ChatLink -> stringResource(MR.strings.share_channel)
|
||||
is SharedContent.MyAddress -> stringResource(MR.strings.share_address)
|
||||
null -> stringResource(MR.strings.share_message)
|
||||
},
|
||||
color = MaterialTheme.colors.onBackground,
|
||||
@@ -196,7 +197,7 @@ private fun ShareList(
|
||||
val oneHandUI = remember { appPrefs.oneHandUI.state }
|
||||
val chats by remember(search) {
|
||||
derivedStateOf {
|
||||
val sorted = chatModel.chats.value.toList().filter { it.chatInfo.ready && it.chatInfo.sendMsgEnabled && !(chatModel.sharedContent.value is SharedContent.ChatLink && it.chatInfo is ChatInfo.Local) }.sortedByDescending { it.chatInfo is ChatInfo.Local }
|
||||
val sorted = chatModel.chats.value.toList().filter { it.chatInfo.ready && it.chatInfo.sendMsgEnabled && !((chatModel.sharedContent.value is SharedContent.ChatLink || chatModel.sharedContent.value is SharedContent.MyAddress) && it.chatInfo is ChatInfo.Local) }.sortedByDescending { it.chatInfo is ChatInfo.Local }
|
||||
filteredChats(mutableStateOf(false), mutableStateOf<Set<String>>(emptySet()), search, sorted)
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -16,6 +16,7 @@ sealed class SharedContent {
|
||||
data class File(val text: String, val uri: URI): SharedContent()
|
||||
data class Forward(val chatItems: List<ChatItem>, val fromChatInfo: ChatInfo): SharedContent()
|
||||
data class ChatLink(val groupInfo: GroupInfo): SharedContent()
|
||||
object MyAddress: SharedContent()
|
||||
}
|
||||
|
||||
enum class AnimatedViewState {
|
||||
|
||||
+19
@@ -354,6 +354,14 @@ private fun UserAddressLayout(
|
||||
share(userAddress.connLinkContact.simplexChatUri(short = showShortLink.value))
|
||||
}
|
||||
}
|
||||
ShareViaChatButton {
|
||||
val shareViaChat = {
|
||||
chatModel.sharedContent.value = SharedContent.MyAddress
|
||||
chatModel.chatId.value = null
|
||||
ModalManager.closeAllModalsEverywhere()
|
||||
}
|
||||
if (userAddress.shouldBeUpgraded) showAddShortLinkAlert { shareViaChat() } else shareViaChat()
|
||||
}
|
||||
// ShareViaEmailButton { sendEmail(userAddress) }
|
||||
BusinessAddressToggle(addressSettingsState) { saveAddressSettings(addressSettingsState.value, savedAddressSettingsState) }
|
||||
AddressSettingsButton(user, userAddress, shareViaProfile, setProfileAddress, saveAddressSettings)
|
||||
@@ -438,6 +446,17 @@ private fun AddShortLinkButton(text: String, onClick: () -> Unit) {
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun ShareViaChatButton(onClick: () -> Unit) {
|
||||
SettingsActionItem(
|
||||
painterResource(MR.images.ic_forward),
|
||||
stringResource(MR.strings.share_via_chat),
|
||||
onClick,
|
||||
iconColor = MaterialTheme.colors.primary,
|
||||
textColor = MaterialTheme.colors.primary,
|
||||
)
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun CreateOneTimeLinkButton() {
|
||||
val closeAll = { ModalManager.start.closeModals() }
|
||||
|
||||
@@ -574,6 +574,7 @@
|
||||
<string name="forward_message">Forward message…</string>
|
||||
<string name="forward_multiple">Forward messages…</string>
|
||||
<string name="share_channel">Share channel…</string>
|
||||
<string name="share_address">Share address…</string>
|
||||
<string name="cannot_share_message_alert_title">Cannot send message</string>
|
||||
<string name="cannot_share_message_alert_text">Selected chat preferences prohibit this message.</string>
|
||||
<string name="share_via_chat">Share via chat</string>
|
||||
@@ -586,6 +587,7 @@
|
||||
<string name="chat_link_from_owner">(from owner)</string>
|
||||
<string name="chat_link_signed">(signed)</string>
|
||||
<string name="error_sharing_channel">Error sharing channel</string>
|
||||
<string name="error_sharing_address">Error sharing address</string>
|
||||
<string name="owner_verification_passed">Link signature verified.</string>
|
||||
<string name="owner_verification_failed">⚠️ Signature verification failed: %s.</string>
|
||||
|
||||
|
||||
@@ -398,6 +398,7 @@ data ChatCommand
|
||||
| APIPlanForwardChatItems {fromChatRef :: ChatRef, chatItemIds :: NonEmpty ChatItemId}
|
||||
| APIForwardChatItems {toChatRef :: ChatRef, sendAsGroup :: ShowGroupAsSender, fromChatRef :: ChatRef, chatItemIds :: NonEmpty ChatItemId, ttl :: Maybe Int}
|
||||
| APIShareChatMsgContent {shareChatRef :: ChatRef, toSendRef :: SendRef}
|
||||
| APIShareMyAddress {toSendRef :: SendRef}
|
||||
| APIUserRead UserId
|
||||
| UserRead
|
||||
| APIChatRead {chatRef :: ChatRef}
|
||||
@@ -563,6 +564,7 @@ data ChatCommand
|
||||
| ForwardGroupMessage {toChatName :: ChatName, fromGroupName :: GroupName, fromMemberName_ :: Maybe ContactName, forwardedMsg :: Text}
|
||||
| ForwardLocalMessage {toChatName :: ChatName, forwardedMsg :: Text}
|
||||
| SharePublicGroup {shareGroupName :: GroupName, toChatName :: ChatName}
|
||||
| ShareMyAddress {toChatName :: ChatName}
|
||||
| SendMessage SendName Text
|
||||
| SendMemberContactMessage GroupName ContactName Text
|
||||
| AcceptMemberContact ContactName
|
||||
|
||||
@@ -1168,6 +1168,15 @@ processChatCommand cxt nm = \case
|
||||
| asGroup = (CBChannel, smpEncode pgId)
|
||||
| otherwise = (CBGroup, smpEncode (pgId, memberId))
|
||||
APIShareChatMsgContent _ _ -> throwCmdError "sharing is only supported for public groups"
|
||||
APIShareMyAddress _ -> withUser $ \user -> do
|
||||
UserContactLink {connLinkContact = CCLink _ sl_, addressSettings} <- withFastStore (`getUserAddress` user)
|
||||
case sl_ of
|
||||
Nothing -> throwCmdError "your address has no short link to share"
|
||||
Just connLink -> do
|
||||
let business = businessAddress addressSettings
|
||||
profile = userProfileDirect user Nothing Nothing True
|
||||
text = safeDecodeUtf8 $ strEncode connLink
|
||||
pure $ CRChatMsgContent user MCChat {text, chatLink = MCLContact {connLink, profile, business}, ownerSig = Nothing}
|
||||
APIUserRead userId -> withUserId userId $ \user -> withFastStore' (`setUserChatsRead` user) >> ok user
|
||||
UserRead -> withUser $ \User {userId} -> processChatCommand cxt nm $ APIUserRead userId
|
||||
APIChatRead chatRef@(ChatRef cType chatId scope_) -> withUser $ \_ -> case cType of
|
||||
@@ -2447,6 +2456,18 @@ processChatCommand cxt nm = \case
|
||||
CRChatMsgContent _ mc ->
|
||||
processChatCommand cxt nm $ APISendMessages sendRef False Nothing False [composedMessage Nothing mc]
|
||||
r -> pure r
|
||||
ShareMyAddress toChatName -> withUser $ \user -> do
|
||||
toChatRef <- getChatRef user toChatName
|
||||
sendRef <- case toChatRef of
|
||||
ChatRef CTDirect ctId _ -> pure $ SRDirect ctId
|
||||
ChatRef CTGroup gId scope_ -> do
|
||||
gInfo <- withFastStore $ \db -> getGroupInfo db cxt user gId
|
||||
pure $ SRGroup gId scope_ (useRelays' gInfo)
|
||||
_ -> throwCmdError "unsupported share target"
|
||||
processChatCommand cxt nm (APIShareMyAddress sendRef) >>= \case
|
||||
CRChatMsgContent _ mc ->
|
||||
processChatCommand cxt nm $ APISendMessages sendRef False Nothing False [composedMessage Nothing mc]
|
||||
r -> pure r
|
||||
SendMessage sendName msg -> withUser $ \user -> do
|
||||
let mc = MCText msg
|
||||
case sendName of
|
||||
@@ -5353,6 +5374,7 @@ chatCommandP =
|
||||
"/_forward plan " *> (APIPlanForwardChatItems <$> chatRefP <*> _strP),
|
||||
"/_forward " *> (APIForwardChatItems <$> chatRefP <*> (" as_group=" *> onOffP <|> pure False) <* A.space <*> chatRefP <*> _strP <*> sendMessageTTLP),
|
||||
"/_share chat content " *> (APIShareChatMsgContent <$> chatRefP <* A.space <*> sendRefP),
|
||||
"/_share address " *> (APIShareMyAddress <$> sendRefP),
|
||||
"/_read user " *> (APIUserRead <$> A.decimal),
|
||||
"/read user" $> UserRead,
|
||||
"/_read chat " *> (APIChatRead <$> chatRefP),
|
||||
@@ -5550,6 +5572,7 @@ chatCommandP =
|
||||
ForwardGroupMessage <$> chatNameP <* " <- #" <*> displayNameP <*> pure Nothing <* A.space <*> msgTextP,
|
||||
ForwardLocalMessage <$> chatNameP <* " <- * " <*> msgTextP,
|
||||
"/share chat #" *> (SharePublicGroup <$> displayNameP <* A.space <*> chatNameP),
|
||||
"/share address " *> (ShareMyAddress <$> chatNameP),
|
||||
SendMessage <$> sendNameP <* A.space <*> msgTextP,
|
||||
"@#" *> (SendMemberContactMessage <$> displayNameP <* A.space <* char_ '@' <*> displayNameP <* A.space <*> msgTextP),
|
||||
"/accept_member_contact @" *> (AcceptMemberContact <$> displayNameP),
|
||||
|
||||
Reference in New Issue
Block a user