Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 28 additions & 20 deletions LeanCloudTests/IMMessageTestCase.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1144,29 +1144,37 @@ class IMMessageTestCase: RTMBaseTestCase {
delay()

let getReadFlagExp = expectation(description: "get read flag timestamp")
((try? sendingTuple?.conversation.getMessageReceiptFlag(completion: { (result) in
XCTAssertTrue(Thread.isMainThread)
XCTAssertTrue(result.isSuccess)
XCTAssertNil(result.error)
XCTAssertNotNil(result.value?.readFlagTimestamp)
XCTAssertNotNil(result.value?.readFlagTimestamp)
XCTAssertEqual(result.value?.readFlagTimestamp, result.value?.deliveredFlagTimestamp)
XCTAssertEqual(result.value?.readFlagDate, result.value?.deliveredFlagDate)
XCTAssertGreaterThan(result.value?.readFlagTimestamp ?? 0, message.sentTimestamp ?? 0)
getReadFlagExp.fulfill()
})) as ()??)
getReadFlagExp.expectedFulfillmentCount = 2
sendingTuple?.delegator.conversationEvent = { client, conv, event in
switch event {
case .lastDeliveredAtUpdated:
XCTAssertNotNil(conv.lastDeliveredAt)
getReadFlagExp.fulfill()
case .lastReadAtUpdated:
XCTAssertNotNil(conv.lastReadAt)
getReadFlagExp.fulfill()
default:
break
}
}
try! sendingTuple?.conversation.fetchReceiptTimestamps()
wait(for: [getReadFlagExp], timeout: timeout)

let sendNeedRCPMessageExp = expectation(description: "send need RCP message")
sendNeedRCPMessageExp.expectedFulfillmentCount = 3
sendingTuple?.delegator.messageEvent = { client, conv, event in
if conv === sendingTuple?.conversation {
switch event {
sendNeedRCPMessageExp.expectedFulfillmentCount = 4
sendingTuple?.delegator.conversationEvent = { client, conv, event in
switch event {
case .lastDeliveredAtUpdated:
sendNeedRCPMessageExp.fulfill()
case .message(event: let messageEvent):
switch messageEvent {
case .delivered(toClientID: _, messageID: _, deliveredTimestamp: _):
sendNeedRCPMessageExp.fulfill()
default:
break
}
default:
break
}
}
receivingTuple?.delegator.conversationEvent = { client, conv, event in
Expand All @@ -1180,18 +1188,18 @@ class IMMessageTestCase: RTMBaseTestCase {
}
}
let needRCPMessage = IMMessage()
try? needRCPMessage.set(content: .string("test"))
((try? sendingTuple?.conversation.send(message: needRCPMessage, options: [.needReceipt], completion: { (result) in
try! needRCPMessage.set(content: .string("test"))
try! sendingTuple?.conversation.send(message: needRCPMessage, options: [.needReceipt], completion: { (result) in
XCTAssertTrue(result.isSuccess)
XCTAssertNil(result.error)
sendNeedRCPMessageExp.fulfill()
})) as ()??)
})
wait(for: [sendNeedRCPMessageExp], timeout: timeout)

delay()

let getDeliveredFlagExp = expectation(description: "get delivered flag timestamp")
((try? sendingTuple?.conversation.getMessageReceiptFlag(completion: { (result) in
try! sendingTuple?.conversation.getMessageReceiptFlag(completion: { (result) in
XCTAssertTrue(Thread.isMainThread)
XCTAssertTrue(result.isSuccess)
XCTAssertNil(result.error)
Expand All @@ -1201,7 +1209,7 @@ class IMMessageTestCase: RTMBaseTestCase {
XCTAssertNotEqual(result.value?.deliveredFlagDate, result.value?.readFlagDate)
XCTAssertGreaterThanOrEqual(result.value?.deliveredFlagTimestamp ?? 0, needRCPMessage.sentTimestamp ?? 0)
getDeliveredFlagExp.fulfill()
})) as ()??)
})
wait(for: [getDeliveredFlagExp], timeout: timeout)

let client = try! IMClient(ID: uuid, options: [])
Expand Down
129 changes: 58 additions & 71 deletions Sources/RTM/IMClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2202,36 +2202,42 @@ extension IMClient {

func process(rcpCommand: IMRcpCommand, serverTimestamp: Int64?) {
assert(self.specificAssertion)
guard let conversationID: String = (rcpCommand.hasCid ? rcpCommand.cid : nil) else {
guard let conversationID = (rcpCommand.hasCid ? rcpCommand.cid : nil) else {
return
}
self.getConversation(by: conversationID) { (client, result) in
assert(client.specificAssertion)
switch result {
case .success(value: let conversation):
guard
let messageID: String = (rcpCommand.hasID ? rcpCommand.id : nil),
let timestamp: Int64 = (rcpCommand.hasT ? rcpCommand.t : nil)
else
{ return }
guard let messageID = (rcpCommand.hasID ? rcpCommand.id : nil),
let timestamp = (rcpCommand.hasT ? rcpCommand.t : nil) else {
return
}
let fromID = (rcpCommand.hasFrom ? rcpCommand.from : nil)
let event: IMMessageEvent
if rcpCommand.hasRead, rcpCommand.read {
event = .read(
let isRead = (rcpCommand.hasRead ? rcpCommand.read : false)
let messageEvent: IMMessageEvent
if isRead {
messageEvent = .read(
byClientID: fromID,
messageID: messageID,
readTimestamp: timestamp
)
readTimestamp: timestamp)
} else {
event = .delivered(
messageEvent = .delivered(
toClientID: fromID,
messageID: messageID,
deliveredTimestamp: timestamp
)
deliveredTimestamp: timestamp)
}
client.localRecord.update(lastServerTimestamp: serverTimestamp)
client.localRecord.update(
lastServerTimestamp: serverTimestamp)
conversation.process(
rcpTimestamp: timestamp,
isRead: isRead,
client: client)
client.eventQueue.async {
client.delegate?.client(client, conversation: conversation, event: .message(event: event))
client.delegate?.client(
client, conversation: conversation,
event: .message(
event: messageEvent))
}
case .failure(error: let error):
Logger.shared.error(error)
Expand Down Expand Up @@ -2514,104 +2520,86 @@ extension IMClient: RTMConnectionDelegate {
// MARK: - Event

/// The session event about the client.
///
/// - sessionDidOpen: Session opened event.
/// - sessionDidResume: Session in resuming event.
/// - sessionDidPause: Session paused event.
/// - sessionDidClose: Session closed event.
public enum IMClientEvent {

/// Session opened event.
case sessionDidOpen

/// Session in resuming event.
case sessionDidResume

/// Session paused event.
case sessionDidPause(error: LCError)

/// Session closed event.
case sessionDidClose(error: LCError)
}

/// The event about the conversation that belong to the client.
///
/// - joined: The client joined the conversation.
/// - left: The client left the conversation.
/// - membersJoined: The members joined the conversation.
/// - membersLeft: The members left the conversation.
/// - memberInfoChanged: The info of the member in the conversaiton has changed.
/// - blocked: The client has been blocked in the conversation.
/// - unblocked: The client has been unblocked int the conversation.
/// - membersBlocked: The members have been blocked in the conversation.
/// - membersUnblocked: The members have been unblocked in the conversation.
/// - muted: The client has been muted in the conversation.
/// - unmuted: The client has been unmuted in the conversation.
/// - membersMuted: The members have been muted in the conversation.
/// - membersUnmuted: The members have been unmuted in the conversation.
/// - dataUpdated: The data of the conversation updated.
/// - lastMessageUpdated: The last message of the conversation updated.
/// - unreadMessageCountUpdated: The unread message count of the conversation updated.
/// - message: Events about message in the conversation.
/// The events about conversation that belong to the client.
public enum IMConversationEvent {

/// This client joined this conversation.
case joined(byClientID: String?, at: Date?)
/// This client left this conversation.
case left(byClientID: String?, at: Date?)
/// The members joined this conversation.
case membersJoined(members: [String], byClientID: String?, at: Date?)
/// The members left this conversation.
case membersLeft(members: [String], byClientID: String?, at: Date?)

/// The info of the member in this conversaiton has been changed.
case memberInfoChanged(info: IMConversation.MemberInfo, byClientID: String?, at: Date?)

/// The client in this conversation has been blocked.
case blocked(byClientID: String?, at: Date?)
/// The client int this conversation has been unblocked.
case unblocked(byClientID: String?, at: Date?)
/// The members in this conversation have been blocked.
case membersBlocked(members: [String], byClientID: String?, at: Date?)
/// The members in this conversation have been unblocked.
case membersUnblocked(members: [String], byClientID: String?, at: Date?)

/// The client in this conversation has been muted.
case muted(byClientID: String?, at: Date?)
/// The client in this conversation has been unmuted.
case unmuted(byClientID: String?, at: Date?)
/// The members in this conversation have been muted.
case membersMuted(members: [String], byClientID: String?, at: Date?)
/// The members in this conversation have been unmuted.
case membersUnmuted(members: [String], byClientID: String?, at: Date?)

/// The data of this conversation has been updated.
case dataUpdated(updatingData: [String: Any]?, updatedData: [String: Any]?, byClientID: String?, at: Date?)

/// The last message of this conversation has been updated, if *newMessage* is *false*, means the message has been modified.
case lastMessageUpdated(newMessage: Bool)

/// The last delivered time of message to other in this conversation has been updated.
case lastDeliveredAtUpdated
/// The last read time of message by other in this conversation has been updated.
case lastReadAtUpdated
/// The unread message count for this client in this conversation has been updated.
case unreadMessageCountUpdated

/// The events about message that belong to this conversation, @see `IMMessageEvent`.
case message(event: IMMessageEvent)
}

/// The event about the message that belong to the conversation.
///
/// - received: The client received message from the conversation.
/// - updated: The message in the conversation has been updated.
/// - delivered: The message sent to the conversation by the client has delivered to other.
/// - read: The message sent to the conversation by the client has been read by other.
/// The events about message that belong to the conversation.
public enum IMMessageEvent {

/// The new message received from this conversation.
case received(message: IMMessage)

/// The message in this conversation has been updated.
case updated(updatedMessage: IMMessage, reason: IMMessage.PatchedReason?)

/// The message has been delivered to other.
case delivered(toClientID: String?, messageID: String, deliveredTimestamp: Int64)

/// The message sent to other has been read.
case read(byClientID: String?, messageID: String, readTimestamp: Int64)
}

/// IM Client Delegate
public protocol IMClientDelegate: class {

/// Delegate function of the event about the client.
///
/// - Parameters:
/// - client: Which the event belong to.
/// - event: @see `IMClientEvent`
/// - client: Which the *event* belong to.
/// - event: Belong to the *client*, @see `IMClientEvent`.
func client(_ client: IMClient, event: IMClientEvent)

/// Delegate function of the event about the conversation.
///
/// - Parameters:
/// - client: Which the conversation belong to.
/// - conversation: Which the event belong to.
/// - event: @see `IMConversationEvent`
/// - client: Which the *conversation* belong to.
/// - conversation: Which the *event* belong to.
/// - event: Belong to the *conversation*, @see `IMConversationEvent`.
func client(_ client: IMClient, conversation: IMConversation, event: IMConversationEvent)

}

// MARK: - Signature
Expand All @@ -2626,7 +2614,6 @@ public protocol IMSignatureDelegate: class {
/// - action: @see `IMSignature.Action`.
/// - signatureHandler: The handler for the signature.
func client(_ client: IMClient, action: IMSignature.Action, signatureHandler: @escaping (IMClient, IMSignature?) -> Void)

}

public struct IMSignature {
Expand Down
Loading