add AChatItem to snd file events (#601)

This commit is contained in:
Evgeny Poberezkin 2022-05-05 10:37:53 +01:00 committed by GitHub
parent 76a9b5b8d4
commit cf04a9fed3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 91 additions and 39 deletions

View File

@ -1063,3 +1063,9 @@ enum class FormatColor(val color: String) {
white -> MaterialTheme.colors.onBackground
}
}
@Serializable
class SndFileTransfer() {}
@Serializable
class FileTransferMeta() {}

View File

@ -689,6 +689,11 @@ sealed class CR {
@Serializable @SerialName("rcvFileAccepted") class RcvFileAccepted(val chatItem: AChatItem): CR()
@Serializable @SerialName("rcvFileStart") class RcvFileStart(val chatItem: AChatItem): CR()
@Serializable @SerialName("rcvFileComplete") class RcvFileComplete(val chatItem: AChatItem): CR()
@Serializable @SerialName("sndFileStart") class SndFileStart(val chatItem: AChatItem, val sndFileTransfer: SndFileTransfer): CR()
@Serializable @SerialName("sndFileComplete") class SndFileComplete(val chatItem: AChatItem, val sndFileTransfer: SndFileTransfer): CR()
@Serializable @SerialName("sndFileCancelled") class SndFileCancelled(val chatItem: AChatItem, val sndFileTransfer: SndFileTransfer): CR()
@Serializable @SerialName("sndFileRcvCancelled") class SndFileRcvCancelled(val chatItem: AChatItem, val sndFileTransfer: SndFileTransfer): CR()
@Serializable @SerialName("sndGroupFileCancelled") class SndGroupFileCancelled(val chatItem: AChatItem, val fileTransferMeta: FileTransferMeta, val sndFileTransfers: List<SndFileTransfer>): CR()
@Serializable @SerialName("newContactConnection") class NewContactConnection(val connection: PendingContactConnection): CR()
@Serializable @SerialName("contactConnectionDeleted") class ContactConnectionDeleted(val connection: PendingContactConnection): CR()
@Serializable @SerialName("cmdOk") class CmdOk: CR()
@ -736,6 +741,11 @@ sealed class CR {
is RcvFileAccepted -> "rcvFileAccepted"
is RcvFileStart -> "rcvFileStart"
is RcvFileComplete -> "rcvFileComplete"
is SndFileCancelled -> "sndFileCancelled"
is SndFileComplete -> "sndFileComplete"
is SndFileRcvCancelled -> "sndFileRcvCancelled"
is SndFileStart -> "sndFileStart"
is SndGroupFileCancelled -> "sndGroupFileCancelled"
is NewContactConnection -> "newContactConnection"
is ContactConnectionDeleted -> "contactConnectionDeleted"
is CmdOk -> "cmdOk"
@ -784,6 +794,11 @@ sealed class CR {
is RcvFileAccepted -> json.encodeToString(chatItem)
is RcvFileStart -> json.encodeToString(chatItem)
is RcvFileComplete -> json.encodeToString(chatItem)
is SndFileCancelled -> json.encodeToString(chatItem)
is SndFileComplete -> json.encodeToString(chatItem)
is SndFileRcvCancelled -> json.encodeToString(chatItem)
is SndFileStart -> json.encodeToString(chatItem)
is SndGroupFileCancelled -> json.encodeToString(chatItem)
is NewContactConnection -> json.encodeToString(connection)
is ContactConnectionDeleted -> json.encodeToString(connection)
is CmdOk -> noDetails()

View File

@ -167,9 +167,16 @@ enum ChatResponse: Decodable, Error {
case chatItemStatusUpdated(chatItem: AChatItem)
case chatItemUpdated(chatItem: AChatItem)
case chatItemDeleted(deletedChatItem: AChatItem, toChatItem: AChatItem)
// receiving file events
case rcvFileAccepted(chatItem: AChatItem)
case rcvFileStart(chatItem: AChatItem)
case rcvFileComplete(chatItem: AChatItem)
// sending file events
case sndFileStart(chatItem: AChatItem, sndFileTransfer: SndFileTransfer)
case sndFileComplete(chatItem: AChatItem, sndFileTransfer: SndFileTransfer)
case sndFileCancelled(chatItem: AChatItem, sndFileTransfer: SndFileTransfer)
case sndFileRcvCancelled(chatItem: AChatItem, sndFileTransfer: SndFileTransfer)
case sndGroupFileCancelled(chatItem: AChatItem, fileTransferMeta: FileTransferMeta, sndFileTransfers: [SndFileTransfer])
case ntfTokenStatus(status: NtfTknStatus)
case newContactConnection(connection: PendingContactConnection)
case contactConnectionDeleted(connection: PendingContactConnection)
@ -219,6 +226,11 @@ enum ChatResponse: Decodable, Error {
case .rcvFileAccepted: return "rcvFileAccepted"
case .rcvFileStart: return "rcvFileStart"
case .rcvFileComplete: return "rcvFileComplete"
case .sndFileStart: return "sndFileStart"
case .sndFileComplete: return "sndFileComplete"
case .sndFileCancelled: return "sndFileCancelled"
case .sndFileRcvCancelled: return "sndFileRcvCancelled"
case .sndGroupFileCancelled: return "sndGroupFileCancelled"
case .ntfTokenStatus: return "ntfTokenStatus"
case .newContactConnection: return "newContactConnection"
case .contactConnectionDeleted: return "contactConnectionDeleted"
@ -271,6 +283,11 @@ enum ChatResponse: Decodable, Error {
case let .rcvFileAccepted(chatItem): return String(describing: chatItem)
case let .rcvFileStart(chatItem): return String(describing: chatItem)
case let .rcvFileComplete(chatItem): return String(describing: chatItem)
case let .sndFileStart(chatItem, _): return String(describing: chatItem)
case let .sndFileComplete(chatItem, _): return String(describing: chatItem)
case let .sndFileCancelled(chatItem, _): return String(describing: chatItem)
case let .sndFileRcvCancelled(chatItem, _): return String(describing: chatItem)
case let .sndGroupFileCancelled(chatItem, _, _): return String(describing: chatItem)
case let .ntfTokenStatus(status): return String(describing: status)
case let .newContactConnection(connection): return String(describing: connection)
case let .contactConnectionDeleted(connection): return String(describing: connection)

View File

@ -799,3 +799,11 @@ enum NtfTknStatus: String, Decodable {
case active = "ACTIVE"
case expired = "EXPIRED"
}
struct SndFileTransfer: Decodable {
}
struct FileTransferMeta: Decodable {
}

View File

@ -318,12 +318,12 @@ processChatCommand = \case
(ct@Contact {localDisplayName = c}, CChatItem msgDir deletedItem@ChatItem {meta = CIMeta {itemSharedMsgId}, file}) <- withStore $ \st -> (,) <$> getContact st userId chatId <*> getDirectChatItem st userId chatId itemId
case (mode, msgDir, itemSharedMsgId) of
(CIDMInternal, _, _) -> do
deleteFile userId file
deleteFile user file
toCi <- withStore $ \st -> deleteDirectChatItemInternal st userId ct itemId
pure $ CRChatItemDeleted (AChatItem SCTDirect msgDir (DirectChat ct) deletedItem) toCi
(CIDMBroadcast, SMDSnd, Just itemSharedMId) -> do
SndMessage {msgId} <- sendDirectContactMessage ct (XMsgDel itemSharedMId)
deleteFile userId file
deleteFile user file
toCi <- withStore $ \st -> deleteDirectChatItemSndBroadcast st userId ct itemId msgId
setActive $ ActiveC c
pure $ CRChatItemDeleted (AChatItem SCTDirect msgDir (DirectChat ct) deletedItem) toCi
@ -334,12 +334,12 @@ processChatCommand = \case
CChatItem msgDir deletedItem@ChatItem {meta = CIMeta {itemSharedMsgId}, file} <- withStore $ \st -> getGroupChatItem st user chatId itemId
case (mode, msgDir, itemSharedMsgId) of
(CIDMInternal, _, _) -> do
deleteFile userId file
deleteFile user file
toCi <- withStore $ \st -> deleteGroupChatItemInternal st user gInfo itemId
pure $ CRChatItemDeleted (AChatItem SCTGroup msgDir (GroupChat gInfo) deletedItem) toCi
(CIDMBroadcast, SMDSnd, Just itemSharedMId) -> do
SndMessage {msgId} <- sendGroupMessage gInfo ms (XMsgDel itemSharedMId)
deleteFile userId file
deleteFile user file
toCi <- withStore $ \st -> deleteGroupChatItemSndBroadcast st user gInfo itemId msgId
setActive $ ActiveG gName
pure $ CRChatItemDeleted (AChatItem SCTGroup msgDir (GroupChat gInfo) deletedItem) toCi
@ -347,10 +347,10 @@ processChatCommand = \case
CTContactRequest -> pure $ chatCmdError "not supported"
CTContactConnection -> pure $ chatCmdError "not supported"
where
deleteFile :: MsgDirectionI d => UserId -> Maybe (CIFile d) -> m ()
deleteFile userId file =
deleteFile :: MsgDirectionI d => User -> Maybe (CIFile d) -> m ()
deleteFile user file =
forM_ file $ \CIFile {fileId, filePath, fileStatus} -> do
cancelFiles userId [(fileId, AFS msgDirection fileStatus)]
cancelFiles user [(fileId, AFS msgDirection fileStatus)]
withFilesFolder $ \filesFolder ->
deleteFiles filesFolder [filePath]
APIChatRead (ChatRef cType chatId) fromToIds -> withChatLock $ case cType of
@ -358,7 +358,7 @@ processChatCommand = \case
CTGroup -> withStore (\st -> updateGroupChatItemsRead st chatId fromToIds) $> CRCmdOk
CTContactRequest -> pure $ chatCmdError "not supported"
CTContactConnection -> pure $ chatCmdError "not supported"
APIDeleteChat (ChatRef cType chatId) -> withUser $ \User {userId} -> case cType of
APIDeleteChat (ChatRef cType chatId) -> withUser $ \user@User {userId} -> case cType of
CTDirect -> do
ct@Contact {localDisplayName} <- withStore $ \st -> getContact st userId chatId
withStore (\st -> getContactGroupNames st userId ct) >>= \case
@ -366,7 +366,7 @@ processChatCommand = \case
files <- withStore $ \st -> getContactFiles st userId ct
conns <- withStore $ \st -> getContactConnections st userId ct
withChatLock . procCmd $ do
cancelFiles userId (map (\(fId, fStatus, _) -> (fId, fStatus)) files)
cancelFiles user (map (\(fId, fStatus, _) -> (fId, fStatus)) files)
withFilesFolder $ \filesFolder -> do
deleteFiles filesFolder (map (\(_, _, fPath) -> fPath) files)
withAgent $ \a -> forM_ conns $ \conn ->
@ -633,9 +633,9 @@ processChatCommand = \case
ChatErrorAgent (SMP SMP.AUTH) -> pure $ CRRcvFileAcceptedSndCancelled ft
ChatErrorAgent (CONN DUPLICATE) -> pure $ CRRcvFileAcceptedSndCancelled ft
e -> throwError e
CancelFile fileId -> withUser $ \User {userId} -> do
CancelFile fileId -> withUser $ \user@User {userId} -> do
ft <- withStore (\st -> getFileTransfer st userId fileId)
withChatLock . procCmd $ cancelFile userId fileId ft
withChatLock . procCmd $ cancelFile user fileId ft
FileStatus fileId ->
CRFileTransferStatus <$> withUser (\User {userId} -> withStore $ \st -> getFileTransferProgress st userId fileId)
ShowProfile -> withUser $ \User {profile} -> pure $ CRUserProfile profile
@ -722,8 +722,8 @@ processChatCommand = \case
let fsFilePath = filesFolder <> "/" <> filePath
removeFile fsFilePath `E.catch` \(_ :: E.SomeException) ->
removePathForcibly fsFilePath `E.catch` \(_ :: E.SomeException) -> pure ()
cancelFiles :: UserId -> [(Int64, ACIFileStatus)] -> m ()
cancelFiles userId files =
cancelFiles :: User -> [(Int64, ACIFileStatus)] -> m ()
cancelFiles user@User {userId} files =
forM_ files $ \(fileId, status) -> do
case status of
AFS _ CIFSSndStored -> cancelById fileId
@ -734,14 +734,15 @@ processChatCommand = \case
where
cancelById fileId = do
ft <- withStore (\st -> getFileTransfer st userId fileId)
void $ cancelFile userId fileId ft
cancelFile :: UserId -> Int64 -> FileTransfer -> m ChatResponse
cancelFile userId fileId ft =
void $ cancelFile user fileId ft
cancelFile :: User -> Int64 -> FileTransfer -> m ChatResponse
cancelFile user@User {userId} fileId ft =
case ft of
FTSnd ftm fts -> do
cancelFileTransfer CIFSSndCancelled
forM_ fts $ \ft' -> cancelSndFileTransfer ft'
pure $ CRSndGroupFileCancelled ftm fts
ci <- withStore $ \st -> getChatItemByFileId st user fileId
pure $ CRSndGroupFileCancelled ci ftm fts
FTRcv ftr -> do
cancelFileTransfer CIFSRcvCancelled
cancelRcvFileTransfer ftr
@ -957,7 +958,7 @@ subscribeUserConnections agentSubscribe user@User {userId} = do
a <- asks smpAgent
when (fileStatus == FSConnected) . unlessM (isFileActive fileId sndFiles) $
withAgentLock a . withLock l $
sendFileChunk ft
sendFileChunk user ft
subscribeRcvFile ft@RcvFileTransfer {fileStatus} =
case fileStatus of
RFSAccepted fInfo -> resume fInfo
@ -1226,16 +1227,20 @@ processAgentMessage (Just user@User {userId, profile}) agentConnId agentMessage
| otherwise -> messageError "x.file.acpt: fileName is different from expected"
_ -> messageError "CONF from file connection must have x.file.acpt"
CON -> do
withStore $ \st -> updateSndFileStatus st ft FSConnected
toView $ CRSndFileStart ft
sendFileChunk ft
ci <- withStore $ \st -> do
updateSndFileStatus st ft FSConnected
getChatItemByFileId st user fileId
toView $ CRSndFileStart ci ft
sendFileChunk user ft
SENT msgId -> do
withStore $ \st -> updateSndFileChunkSent st ft msgId
unless (fileStatus == FSCancelled) $ sendFileChunk ft
unless (fileStatus == FSCancelled) $ sendFileChunk user ft
MERR _ err -> do
cancelSndFileTransfer ft
case err of
SMP SMP.AUTH -> unless (fileStatus == FSCancelled) $ toView $ CRSndFileRcvCancelled ft
SMP SMP.AUTH -> unless (fileStatus == FSCancelled) $ do
ci <- withStore $ \st -> getChatItemByFileId st user fileId
toView $ CRSndFileRcvCancelled ci ft
_ -> throwChatError $ CEFileSend fileId err
MSG meta _ ->
withAckMessage agentConnId meta $ pure ()
@ -1756,16 +1761,17 @@ processAgentMessage (Just user@User {userId, profile}) agentConnId agentMessage
parseChatMessage :: ByteString -> Either ChatError ChatMessage
parseChatMessage = first (ChatError . CEInvalidChatMessage) . strDecode
sendFileChunk :: ChatMonad m => SndFileTransfer -> m ()
sendFileChunk ft@SndFileTransfer {fileId, fileStatus, agentConnId = AgentConnId acId} =
sendFileChunk :: ChatMonad m => User -> SndFileTransfer -> m ()
sendFileChunk user ft@SndFileTransfer {fileId, fileStatus, agentConnId = AgentConnId acId} =
unless (fileStatus == FSComplete || fileStatus == FSCancelled) $
withStore (`createSndFileChunk` ft) >>= \case
Just chunkNo -> sendFileChunkNo ft chunkNo
Nothing -> do
withStore $ \st -> do
ci <- withStore $ \st -> do
updateSndFileStatus st ft FSComplete
deleteSndFileChunks st ft
toView $ CRSndFileComplete ft
getChatItemByFileId st user fileId
toView $ CRSndFileComplete ci ft
closeFileHandle fileId sndFiles
withAgent (`deleteConnection` acId)

View File

@ -219,11 +219,11 @@ data ChatResponse
| CRRcvFileComplete {chatItem :: AChatItem}
| CRRcvFileCancelled {rcvFileTransfer :: RcvFileTransfer}
| CRRcvFileSndCancelled {rcvFileTransfer :: RcvFileTransfer}
| CRSndFileStart {sndFileTransfer :: SndFileTransfer}
| CRSndFileComplete {sndFileTransfer :: SndFileTransfer}
| CRSndFileCancelled {sndFileTransfer :: SndFileTransfer}
| CRSndFileRcvCancelled {sndFileTransfer :: SndFileTransfer}
| CRSndGroupFileCancelled {fileTransferMeta :: FileTransferMeta, sndFileTransfers :: [SndFileTransfer]}
| CRSndFileStart {chatItem :: AChatItem, sndFileTransfer :: SndFileTransfer}
| CRSndFileComplete {chatItem :: AChatItem, sndFileTransfer :: SndFileTransfer}
| CRSndFileCancelled {chatItem :: AChatItem, sndFileTransfer :: SndFileTransfer}
| CRSndFileRcvCancelled {chatItem :: AChatItem, sndFileTransfer :: SndFileTransfer}
| CRSndGroupFileCancelled {chatItem :: AChatItem, fileTransferMeta :: FileTransferMeta, sndFileTransfers :: [SndFileTransfer]}
| CRUserProfileUpdated {fromProfile :: Profile, toProfile :: Profile}
| CRContactConnecting {contact :: Contact}
| CRContactConnected {contact :: Contact}

View File

@ -94,7 +94,7 @@ responseToView testView = \case
CRGroupDeletedUser g -> [ttyGroup' g <> ": you deleted the group"]
CRRcvFileAccepted ci -> savingFile' ci
CRRcvFileAcceptedSndCancelled ft -> viewRcvFileSndCancelled ft
CRSndGroupFileCancelled ftm fts -> viewSndGroupFileCancelled ftm fts
CRSndGroupFileCancelled _ ftm fts -> viewSndGroupFileCancelled ftm fts
CRRcvFileCancelled ft -> receivingFile_ "cancelled" ft
CRUserProfileUpdated p p' -> viewUserProfileUpdated p p'
CRContactUpdated c c' -> viewContactUpdated c c'
@ -103,10 +103,10 @@ responseToView testView = \case
CRRcvFileStart ci -> receivingFile_' "started" ci
CRRcvFileComplete ci -> receivingFile_' "completed" ci
CRRcvFileSndCancelled ft -> viewRcvFileSndCancelled ft
CRSndFileStart ft -> sendingFile_ "started" ft
CRSndFileComplete ft -> sendingFile_ "completed" ft
CRSndFileCancelled ft -> sendingFile_ "cancelled" ft
CRSndFileRcvCancelled ft@SndFileTransfer {recipientDisplayName = c} ->
CRSndFileStart _ ft -> sendingFile_ "started" ft
CRSndFileComplete _ ft -> sendingFile_ "completed" ft
CRSndFileCancelled _ ft -> sendingFile_ "cancelled" ft
CRSndFileRcvCancelled _ ft@SndFileTransfer {recipientDisplayName = c} ->
[ttyContact c <> " cancelled receiving " <> sndFile ft]
CRContactConnecting _ -> []
CRContactConnected ct -> [ttyFullContact ct <> ": contact is connected"]

View File

@ -53,10 +53,10 @@ testChatApiNoUser = withTmpFiles $ do
testChatApi :: IO ()
testChatApi = withTmpFiles $ do
let f = chatStoreFile testDBPrefix
let f = chatStoreFile $ testDBPrefix <> "1"
st <- createStore f 1 True
Right _ <- runExceptT $ createUser st aliceProfile True
cc <- chatInit testDBPrefix
cc <- chatInit $ testDBPrefix <> "1"
chatSendCmd cc "/u" `shouldReturn` activeUser
chatSendCmd cc "/u alice Alice" `shouldReturn` activeUserExists
chatSendCmd cc "/_start" `shouldReturn` chatStarted