mirror of
https://github.com/simplex-chat/simplex-chat.git
synced 2024-12-17 17:20:21 +01:00
Merge branch 'master' into master-ios
This commit is contained in:
@@ -176,7 +176,7 @@ private fun ChatListToolbar(chatModel: ChatModel, drawerState: DrawerState, user
|
||||
BackHandler(onBack = hideSearchOnBack)
|
||||
}
|
||||
val barButtons = arrayListOf<@Composable RowScope.() -> Unit>()
|
||||
if (chatModel.chats.size >= 8) {
|
||||
if (chatModel.chats.size > 0) {
|
||||
barButtons.add {
|
||||
IconButton({ showSearch = true }) {
|
||||
Icon(painterResource(R.drawable.ic_search_500), stringResource(android.R.string.search_go).capitalize(Locale.current), tint = MaterialTheme.colors.primary)
|
||||
|
||||
@@ -29,11 +29,7 @@ struct ChatListView: View {
|
||||
if chatModel.chats.isEmpty {
|
||||
onboardingButtons()
|
||||
}
|
||||
if chatModel.chats.count > 8 {
|
||||
chatList.searchable(text: $searchText)
|
||||
} else {
|
||||
chatList
|
||||
}
|
||||
chatListView
|
||||
}
|
||||
}
|
||||
if userPickerVisible {
|
||||
@@ -47,18 +43,12 @@ struct ChatListView: View {
|
||||
}
|
||||
}
|
||||
|
||||
var chatList: some View {
|
||||
List {
|
||||
ForEach(filteredChats(), id: \.viewId) { chat in
|
||||
ChatListNavLink(chat: chat)
|
||||
.padding(.trailing, -16)
|
||||
.disabled(chatModel.chatRunning != true)
|
||||
}
|
||||
}
|
||||
.onChange(of: chatModel.chatId) { _ in
|
||||
if chatModel.chatId == nil, let chatId = chatModel.chatToTop {
|
||||
chatModel.chatToTop = nil
|
||||
chatModel.popChat(chatId)
|
||||
private var chatListView: some View {
|
||||
VStack {
|
||||
if chatModel.chats.count > 0 {
|
||||
chatList.searchable(text: $searchText)
|
||||
} else {
|
||||
chatList
|
||||
}
|
||||
}
|
||||
.onChange(of: chatModel.appOpenUrl) { _ in connectViaUrl() }
|
||||
@@ -116,6 +106,22 @@ struct ChatListView: View {
|
||||
}
|
||||
}
|
||||
|
||||
private var chatList: some View {
|
||||
List {
|
||||
ForEach(filteredChats(), id: \.viewId) { chat in
|
||||
ChatListNavLink(chat: chat)
|
||||
.padding(.trailing, -16)
|
||||
.disabled(chatModel.chatRunning != true)
|
||||
}
|
||||
}
|
||||
.onChange(of: chatModel.chatId) { _ in
|
||||
if chatModel.chatId == nil, let chatId = chatModel.chatToTop {
|
||||
chatModel.chatToTop = nil
|
||||
chatModel.popChat(chatId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func unreadBadge(_ text: Text? = Text(" "), size: CGFloat = 18) -> some View {
|
||||
Circle()
|
||||
.frame(width: size, height: size)
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
</trans-unit>
|
||||
<trans-unit id="%lld file(s) with total size of %@" xml:space="preserve">
|
||||
<source>%lld file(s) with total size of %@</source>
|
||||
<target>合計サイズ %@ の %lld 件のファイル</target>
|
||||
<target>%lld 個のファイル(合計サイズ: %@)</target>
|
||||
<note>No comment provided by engineer.</note>
|
||||
</trans-unit>
|
||||
<trans-unit id="%lld members" xml:space="preserve">
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
"%lld contact(s) selected" = "%lld 件の連絡先が選択されました";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"%lld file(s) with total size of %@" = "合計サイズ %@ の %lld 件のファイル";
|
||||
"%lld file(s) with total size of %@" = "%lld 個のファイル(合計サイズ: %@)";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"%lld members" = "%lld 人のメンバー";
|
||||
|
||||
+18
-16
@@ -2738,7 +2738,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
|
||||
_ -> messageError $ "unsupported message: " <> T.pack (show event)
|
||||
CONF confId _ connInfo -> do
|
||||
-- confirming direct connection with a member
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage connInfo
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage conn connInfo
|
||||
case chatMsgEvent of
|
||||
XGrpMemInfo _memId _memProfile -> do
|
||||
-- TODO check member ID
|
||||
@@ -2747,7 +2747,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
|
||||
allowAgentConnectionAsync user conn confId XOk
|
||||
_ -> messageError "CONF from member must have x.grp.mem.info"
|
||||
INFO connInfo -> do
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage connInfo
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage conn connInfo
|
||||
case chatMsgEvent of
|
||||
XGrpMemInfo _memId _memProfile -> do
|
||||
-- TODO check member ID
|
||||
@@ -2863,7 +2863,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
|
||||
_ -> throwChatError $ CECommandError "unexpected cmdFunction"
|
||||
CRContactUri _ -> throwChatError $ CECommandError "unexpected ConnectionRequestUri type"
|
||||
CONF confId _ connInfo -> do
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage connInfo
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage conn connInfo
|
||||
case memberCategory m of
|
||||
GCInviteeMember ->
|
||||
case chatMsgEvent of
|
||||
@@ -2884,7 +2884,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
|
||||
| otherwise -> messageError "x.grp.mem.info: memberId is different from expected"
|
||||
_ -> messageError "CONF from member must have x.grp.mem.info"
|
||||
INFO connInfo -> do
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage connInfo
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage conn connInfo
|
||||
case chatMsgEvent of
|
||||
XGrpMemInfo memId _memProfile
|
||||
| sameMemberId memId m -> do
|
||||
@@ -3028,7 +3028,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
|
||||
-- SMP CONF for SndFileConnection happens for direct file protocol
|
||||
-- when recipient of the file "joins" connection created by the sender
|
||||
CONF confId _ connInfo -> do
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage connInfo
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage conn connInfo
|
||||
case chatMsgEvent of
|
||||
-- TODO save XFileAcpt message
|
||||
XFileAcpt name
|
||||
@@ -3098,7 +3098,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
|
||||
-- when sender of the file "joins" connection created by the recipient
|
||||
-- (sender doesn't create connections for all group members)
|
||||
CONF confId _ connInfo -> do
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage connInfo
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage conn connInfo
|
||||
case chatMsgEvent of
|
||||
XOk -> allowAgentConnectionAsync user conn confId XOk -- [async agent commands] no continuation needed, but command should be asynchronous for stability
|
||||
_ -> pure ()
|
||||
@@ -3161,7 +3161,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
|
||||
processUserContactRequest :: ACommand 'Agent e -> ConnectionEntity -> Connection -> UserContact -> m ()
|
||||
processUserContactRequest agentMsg connEntity conn UserContact {userContactLinkId} = case agentMsg of
|
||||
REQ invId _ connInfo -> do
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage connInfo
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage conn connInfo
|
||||
case chatMsgEvent of
|
||||
XContact p xContactId_ -> profileContactRequest invId p xContactId_
|
||||
XInfo p -> profileContactRequest invId p Nothing
|
||||
@@ -3959,7 +3959,7 @@ processAgentMessageConn user@User {userId} corrId agentConnId agentMessage = do
|
||||
|
||||
saveConnInfo :: Connection -> ConnInfo -> m ()
|
||||
saveConnInfo activeConn connInfo = do
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage connInfo
|
||||
ChatMessage {chatMsgEvent} <- parseChatMessage activeConn connInfo
|
||||
case chatMsgEvent of
|
||||
XInfo p -> do
|
||||
ct <- withStore $ \db -> createDirectContact db user activeConn p
|
||||
@@ -4153,16 +4153,18 @@ sendFileInline_ FileTransferMeta {filePath, chunkSize} sharedMsgId sendMsg =
|
||||
else sendChunks (chunkNo + 1) rest
|
||||
chSize = fromIntegral chunkSize
|
||||
|
||||
parseChatMessage :: ChatMonad m => ByteString -> m (ChatMessage 'Json)
|
||||
parseChatMessage = parseChatMessage_
|
||||
parseChatMessage :: ChatMonad m => Connection -> ByteString -> m (ChatMessage 'Json)
|
||||
parseChatMessage conn = parseChatMessage_ conn Nothing
|
||||
{-# INLINE parseChatMessage #-}
|
||||
|
||||
parseAChatMessage :: ChatMonad m => ByteString -> m AChatMessage
|
||||
parseAChatMessage = parseChatMessage_
|
||||
parseAChatMessage :: ChatMonad m => Connection -> MsgMeta -> ByteString -> m AChatMessage
|
||||
parseAChatMessage conn msgMeta = parseChatMessage_ conn (Just msgMeta)
|
||||
{-# INLINE parseAChatMessage #-}
|
||||
|
||||
parseChatMessage_ :: (ChatMonad m, StrEncoding s) => ByteString -> m s
|
||||
parseChatMessage_ s = liftEither . first (ChatError . CEInvalidChatMessage (safeDecodeUtf8 s)) $ strDecode s
|
||||
parseChatMessage_ :: (ChatMonad m, StrEncoding s) => Connection -> Maybe MsgMeta -> ByteString -> m s
|
||||
parseChatMessage_ conn msgMeta s = liftEither . first (ChatError . errType) $ strDecode s
|
||||
where
|
||||
errType = CEInvalidChatMessage conn (msgMetaToJson <$> msgMeta) (safeDecodeUtf8 s)
|
||||
|
||||
sendFileChunk :: ChatMonad m => User -> SndFileTransfer -> m ()
|
||||
sendFileChunk user ft@SndFileTransfer {fileId, fileStatus, agentConnId = AgentConnId acId} =
|
||||
@@ -4376,8 +4378,8 @@ sendPendingGroupMessages user GroupMember {groupMemberId, localDisplayName} conn
|
||||
_ -> pure ()
|
||||
|
||||
saveRcvMSG :: ChatMonad m => Connection -> ConnOrGroupId -> MsgMeta -> MsgBody -> CommandId -> m RcvMessage
|
||||
saveRcvMSG Connection {connId} connOrGroupId agentMsgMeta msgBody agentAckCmdId = do
|
||||
ACMsg _ ChatMessage {msgId = sharedMsgId_, chatMsgEvent} <- parseAChatMessage msgBody
|
||||
saveRcvMSG conn@Connection {connId} connOrGroupId agentMsgMeta msgBody agentAckCmdId = do
|
||||
ACMsg _ ChatMessage {msgId = sharedMsgId_, chatMsgEvent} <- parseAChatMessage conn agentMsgMeta msgBody
|
||||
let agentMsgId = fst $ recipient agentMsgMeta
|
||||
newMsg = NewMessage {chatMsgEvent, msgBody}
|
||||
rcvMsgDelivery = RcvMsgDelivery {connId, agentMsgId, agentMsgMeta, agentAckCmdId}
|
||||
|
||||
@@ -779,7 +779,7 @@ data ChatErrorType
|
||||
| CEChatNotStopped
|
||||
| CEChatStoreChanged
|
||||
| CEInvalidConnReq
|
||||
| CEInvalidChatMessage {messageData :: Text, message :: String}
|
||||
| CEInvalidChatMessage {connection :: Connection, msgMeta :: Maybe MsgMetaJSON, messageData :: Text, message :: String}
|
||||
| CEContactNotReady {contact :: Contact}
|
||||
| CEContactDisabled {contact :: Contact}
|
||||
| CEConnectionDisabled {connection :: Connection}
|
||||
|
||||
@@ -1384,7 +1384,12 @@ viewChatError logLevel = \case
|
||||
CEChatNotStopped -> ["error: chat not stopped"]
|
||||
CEChatStoreChanged -> ["error: chat store changed, please restart chat"]
|
||||
CEInvalidConnReq -> viewInvalidConnReq
|
||||
CEInvalidChatMessage msg e -> [plain $ "chat message error: " <> e <> " (" <> T.unpack (T.take 120 msg) <> ")"]
|
||||
CEInvalidChatMessage Connection {connId} msgMeta_ msg e ->
|
||||
[ plain $
|
||||
("chat message error: " <> e <> " (" <> T.unpack (T.take 120 msg) <> ")")
|
||||
<> (", connection id: " <> show connId)
|
||||
<> maybe "" (\MsgMetaJSON {rcvId} -> ", agent msg rcv id: " <> show rcvId) msgMeta_
|
||||
]
|
||||
CEContactNotReady c -> [ttyContact' c <> ": not ready"]
|
||||
CEContactDisabled Contact {localDisplayName = c} -> [ttyContact c <> ": disabled, to enable: " <> highlight ("/enable " <> c) <> ", to delete: " <> highlight ("/d " <> c)]
|
||||
CEConnectionDisabled Connection {connId, connType} -> [plain $ "connection " <> textEncode connType <> " (" <> tshow connId <> ") is disabled" | logLevel <= CLLWarning]
|
||||
|
||||
Reference in New Issue
Block a user