Skip to content
Snippets Groups Projects
Commit c0b0b063 authored by Andreas Traczyk's avatar Andreas Traczyk
Browse files

conversations: respond to message status changes


- Provides a UI elements that respond to states(sending, failure)
  for each outgoing message.

- Updates the message models' statuses at loading to correct
  erroneously stored data.

- Ignores the message status IDLE which is not intended
  for client use.

Change-Id: Ie6027d59ae519b96de204ba8d98bc2dd8eb9b4e4
Reviewed-by: default avatarKateryna Kostiuk <kateryna.kostiuk@savoirfairelinux.com>
parent 3ad3fb19
No related branches found
No related tags found
No related merge requests found
Showing with 144 additions and 15 deletions
...@@ -22,7 +22,6 @@ ...@@ -22,7 +22,6 @@
typedef NS_ENUM(int, MessageStatus) { typedef NS_ENUM(int, MessageStatus) {
MessageStatusUnknown = 0, MessageStatusUnknown = 0,
MessageStatusIdle,
MessageStatusSending, MessageStatusSending,
MessageStatusSent, MessageStatusSent,
MessageStatusRead, MessageStatusRead,
......
...@@ -59,10 +59,10 @@ static id <MessagesAdapterDelegate> _delegate; ...@@ -59,10 +59,10 @@ static id <MessagesAdapterDelegate> _delegate;
confHandlers.insert(exportable_callback<ConfigurationSignal::AccountMessageStatusChanged>([&](const std::string& account_id, uint64_t message_id, const std::string& to, int state) { confHandlers.insert(exportable_callback<ConfigurationSignal::AccountMessageStatusChanged>([&](const std::string& account_id, uint64_t message_id, const std::string& to, int state) {
if (MessagesAdapter.delegate) { if (MessagesAdapter.delegate) {
NSString* fromAccountId = [NSString stringWithUTF8String:account_id.c_str()]; NSString* fromAccountId = [NSString stringWithUTF8String:account_id.c_str()];
NSString* toAccount = [NSString stringWithUTF8String:to.c_str()]; NSString* toUri = [NSString stringWithUTF8String:to.c_str()];
[MessagesAdapter.delegate messageStatusChanged:(MessageStatus)state [MessagesAdapter.delegate messageStatusChanged:(MessageStatus)state
for:message_id from:fromAccountId for:message_id from:fromAccountId
to:toAccount]; to:toUri];
} }
})); }));
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
import UIKit import UIKit
import Reusable import Reusable
import RxSwift
class MessageCell: UITableViewCell, NibReusable { class MessageCell: UITableViewCell, NibReusable {
...@@ -33,4 +34,8 @@ class MessageCell: UITableViewCell, NibReusable { ...@@ -33,4 +34,8 @@ class MessageCell: UITableViewCell, NibReusable {
@IBOutlet weak var timeLabel: UILabel! @IBOutlet weak var timeLabel: UILabel!
@IBOutlet weak var leftDivider: UIView! @IBOutlet weak var leftDivider: UIView!
@IBOutlet weak var rightDivider: UIView! @IBOutlet weak var rightDivider: UIView!
@IBOutlet weak var sendingIndicator: UIActivityIndicatorView!
@IBOutlet weak var failedStatusLabel: UILabel!
let disposeBag = DisposeBag()
} }
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
<rect key="frame" x="0.0" y="0.0" width="510" height="47"/> <rect key="frame" x="0.0" y="0.0" width="510" height="47"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="3QB-g7-MaS" id="Dkz-SA-3Af"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="3QB-g7-MaS" id="Dkz-SA-3Af">
<rect key="frame" x="0.0" y="0.0" width="510" height="46.5"/> <rect key="frame" x="0.0" y="0.0" width="510" height="47"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<view clipsSubviews="YES" contentMode="scaleToFill" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="xVQ-Jk-Sxy" customClass="MessageBubble" customModule="Ring" customModuleProvider="target"> <view clipsSubviews="YES" contentMode="scaleToFill" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="xVQ-Jk-Sxy" customClass="MessageBubble" customModule="Ring" customModuleProvider="target">
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
<rect key="frame" x="0.0" y="0.0" width="510" height="47"/> <rect key="frame" x="0.0" y="0.0" width="510" height="47"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM"> <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="510" height="46.5"/> <rect key="frame" x="0.0" y="0.0" width="510" height="47"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>
<subviews> <subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hdz-AQ-xHI" userLabel="Bottom Corner"> <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hdz-AQ-xHI" userLabel="Bottom Corner">
...@@ -80,15 +80,27 @@ ...@@ -80,15 +80,27 @@
<nil key="textColor"/> <nil key="textColor"/>
<nil key="highlightedColor"/> <nil key="highlightedColor"/>
</label> </label>
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" animating="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="78h-fZ-7yf" userLabel="Sending Indicator">
<rect key="frame" x="275.5" y="16" width="20" height="20"/>
</activityIndicatorView>
<label hidden="YES" opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Failed" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="P5a-HI-uhr" userLabel="Failed Status Label">
<rect key="frame" x="253" y="16" width="42.5" height="19.5"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" red="0.94117647058823528" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews> </subviews>
<constraints> <constraints>
<constraint firstAttribute="bottom" secondItem="kZJ-Ay-LTR" secondAttribute="bottom" constant="8" id="1QQ-bu-6Bl" userLabel="Bubble Bottom Constraint"/> <constraint firstAttribute="bottom" secondItem="kZJ-Ay-LTR" secondAttribute="bottom" constant="8" id="1QQ-bu-6Bl" userLabel="Bubble Bottom Constraint"/>
<constraint firstItem="h8N-aw-5lV" firstAttribute="leading" secondItem="ogn-wv-fZy" secondAttribute="trailing" constant="16" id="1jW-JR-t5r"/> <constraint firstItem="h8N-aw-5lV" firstAttribute="leading" secondItem="ogn-wv-fZy" secondAttribute="trailing" constant="16" id="1jW-JR-t5r"/>
<constraint firstItem="78h-fZ-7yf" firstAttribute="trailing" secondItem="kZJ-Ay-LTR" secondAttribute="leading" constant="-8" id="4ME-jl-Uol"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" priority="1" constant="64" id="99Y-bR-Ioq"/> <constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" priority="1" constant="64" id="99Y-bR-Ioq"/>
<constraint firstItem="kZJ-Ay-LTR" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" priority="1" constant="16" id="Eso-cy-OYs"/> <constraint firstItem="kZJ-Ay-LTR" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" priority="1" constant="16" id="Eso-cy-OYs"/>
<constraint firstItem="ogn-wv-fZy" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" constant="-2" id="Fxg-Wa-Rb9"/> <constraint firstItem="ogn-wv-fZy" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" constant="-2" id="Fxg-Wa-Rb9"/>
<constraint firstItem="78h-fZ-7yf" firstAttribute="top" secondItem="kZJ-Ay-LTR" secondAttribute="top" constant="8" id="Gei-s7-aWx"/>
<constraint firstItem="2U4-l3-KET" firstAttribute="centerY" secondItem="ogn-wv-fZy" secondAttribute="centerY" id="J6Y-Ti-HDv"/> <constraint firstItem="2U4-l3-KET" firstAttribute="centerY" secondItem="ogn-wv-fZy" secondAttribute="centerY" id="J6Y-Ti-HDv"/>
<constraint firstItem="EMh-bG-ilg" firstAttribute="trailing" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" id="MY3-Aj-94K"/> <constraint firstItem="EMh-bG-ilg" firstAttribute="trailing" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" id="MY3-Aj-94K"/>
<constraint firstItem="P5a-HI-uhr" firstAttribute="top" secondItem="kZJ-Ay-LTR" secondAttribute="top" constant="8" id="O07-uI-R80"/>
<constraint firstItem="ogn-wv-fZy" firstAttribute="centerX" secondItem="H2p-sc-9uM" secondAttribute="centerX" id="RaG-SO-xFo"/> <constraint firstItem="ogn-wv-fZy" firstAttribute="centerX" secondItem="H2p-sc-9uM" secondAttribute="centerX" id="RaG-SO-xFo"/>
<constraint firstAttribute="trailing" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" constant="16" id="TCY-7X-mFs"/> <constraint firstAttribute="trailing" secondItem="kZJ-Ay-LTR" secondAttribute="trailing" constant="16" id="TCY-7X-mFs"/>
<constraint firstItem="h8N-aw-5lV" firstAttribute="centerY" secondItem="ogn-wv-fZy" secondAttribute="centerY" id="Xdu-7c-MbP"/> <constraint firstItem="h8N-aw-5lV" firstAttribute="centerY" secondItem="ogn-wv-fZy" secondAttribute="centerY" id="Xdu-7c-MbP"/>
...@@ -99,6 +111,7 @@ ...@@ -99,6 +111,7 @@
<constraint firstItem="kZJ-Ay-LTR" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="64" id="nWe-5k-Qpn"/> <constraint firstItem="kZJ-Ay-LTR" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="64" id="nWe-5k-Qpn"/>
<constraint firstItem="2U4-l3-KET" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="16" id="uoy-US-ksI"/> <constraint firstItem="2U4-l3-KET" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="16" id="uoy-US-ksI"/>
<constraint firstItem="EMh-bG-ilg" firstAttribute="top" secondItem="kZJ-Ay-LTR" secondAttribute="top" id="zEh-jv-0Ha"/> <constraint firstItem="EMh-bG-ilg" firstAttribute="top" secondItem="kZJ-Ay-LTR" secondAttribute="top" id="zEh-jv-0Ha"/>
<constraint firstItem="P5a-HI-uhr" firstAttribute="trailing" secondItem="kZJ-Ay-LTR" secondAttribute="leading" constant="-8" id="zI5-Gc-i6d"/>
<constraint firstItem="hdz-AQ-xHI" firstAttribute="bottom" secondItem="kZJ-Ay-LTR" secondAttribute="bottom" id="zWA-Jg-F6Q"/> <constraint firstItem="hdz-AQ-xHI" firstAttribute="bottom" secondItem="kZJ-Ay-LTR" secondAttribute="bottom" id="zWA-Jg-F6Q"/>
</constraints> </constraints>
</tableViewCellContentView> </tableViewCellContentView>
...@@ -107,9 +120,11 @@ ...@@ -107,9 +120,11 @@
<outlet property="bubble" destination="kZJ-Ay-LTR" id="hdG-fG-L69"/> <outlet property="bubble" destination="kZJ-Ay-LTR" id="hdG-fG-L69"/>
<outlet property="bubbleBottomConstraint" destination="1QQ-bu-6Bl" id="woo-UQ-wXK"/> <outlet property="bubbleBottomConstraint" destination="1QQ-bu-6Bl" id="woo-UQ-wXK"/>
<outlet property="bubbleTopConstraint" destination="jhd-A8-c1o" id="cll-eA-OC5"/> <outlet property="bubbleTopConstraint" destination="jhd-A8-c1o" id="cll-eA-OC5"/>
<outlet property="failedStatusLabel" destination="P5a-HI-uhr" id="6Sq-NU-j0d"/>
<outlet property="leftDivider" destination="2U4-l3-KET" id="y4j-CT-gez"/> <outlet property="leftDivider" destination="2U4-l3-KET" id="y4j-CT-gez"/>
<outlet property="messageLabel" destination="lyR-7c-S2k" id="hd3-pz-Pwh"/> <outlet property="messageLabel" destination="lyR-7c-S2k" id="hd3-pz-Pwh"/>
<outlet property="rightDivider" destination="h8N-aw-5lV" id="9pc-93-BG6"/> <outlet property="rightDivider" destination="h8N-aw-5lV" id="9pc-93-BG6"/>
<outlet property="sendingIndicator" destination="78h-fZ-7yf" id="GrK-FT-q39"/>
<outlet property="timeLabel" destination="ogn-wv-fZy" id="7yt-vi-cSp"/> <outlet property="timeLabel" destination="ogn-wv-fZy" id="7yt-vi-cSp"/>
<outlet property="topCorner" destination="EMh-bG-ilg" id="nHl-hn-BZ1"/> <outlet property="topCorner" destination="EMh-bG-ilg" id="nHl-hn-BZ1"/>
</connections> </connections>
......
...@@ -384,6 +384,19 @@ class ConversationViewController: UIViewController, UITextFieldDelegate, Storybo ...@@ -384,6 +384,19 @@ class ConversationViewController: UIViewController, UITextFieldDelegate, Storybo
} else if self.messageViewModels?.count == indexPath.row + 1 { } else if self.messageViewModels?.count == indexPath.row + 1 {
cell.bubbleBottomConstraint.constant = 16 cell.bubbleBottomConstraint.constant = 16
} }
if messageVM.bubblePosition() == .sent {
messageVM.status.asObservable()
.observeOn(MainScheduler.instance)
.map { value in value == MessageStatus.sending ? true : false }
.bind(to: cell.sendingIndicator.rx.isAnimating)
.disposed(by: disposeBag)
messageVM.status.asObservable()
.observeOn(MainScheduler.instance)
.map { value in value == MessageStatus.failure ? false : true }
.bind(to: cell.failedStatusLabel.rx.isHidden)
.disposed(by: disposeBag)
}
} }
} }
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
*/ */
import RxSwift import RxSwift
import SwiftyBeaver
enum BubblePosition { enum BubblePosition {
case received case received
...@@ -42,17 +43,41 @@ enum GeneratedMessageType: String { ...@@ -42,17 +43,41 @@ enum GeneratedMessageType: String {
class MessageViewModel { class MessageViewModel {
fileprivate let log = SwiftyBeaver.self
fileprivate let accountService: AccountsService fileprivate let accountService: AccountsService
fileprivate let conversationsService: ConversationsService
fileprivate var message: MessageModel fileprivate var message: MessageModel
var timeStringShown: String? var timeStringShown: String?
var sequencing: MessageSequencing = .unknown var sequencing: MessageSequencing = .unknown
private let disposeBag = DisposeBag()
init(withInjectionBag injectionBag: InjectionBag, init(withInjectionBag injectionBag: InjectionBag,
withMessage message: MessageModel) { withMessage message: MessageModel) {
self.accountService = injectionBag.accountService self.accountService = injectionBag.accountService
self.conversationsService = injectionBag.conversationsService
self.message = message self.message = message
self.timeStringShown = nil self.timeStringShown = nil
self.status.onNext(message.status)
// subscribe to message status updates for outgoing messages
self.conversationsService
.sharedResponseStream
.filter({ messageUpdateEvent in
let account = self.accountService.getAccount(fromAccountId: messageUpdateEvent.getEventInput(.id)!)
let accountHelper = AccountModelHelper(withAccount: account!)
return messageUpdateEvent.eventType == ServiceEventType.messageStateChanged &&
messageUpdateEvent.getEventInput(.messageId) == self.message.id &&
accountHelper.ringId == self.message.author
})
.subscribe(onNext: { [unowned self] messageUpdateEvent in
if let status: MessageStatus = messageUpdateEvent.getEventInput(.messageStatus) {
self.status.onNext(status)
}
})
.disposed(by: self.disposeBag)
} }
var content: String { var content: String {
...@@ -67,9 +92,7 @@ class MessageViewModel { ...@@ -67,9 +92,7 @@ class MessageViewModel {
return UInt64(self.message.id)! return UInt64(self.message.id)!
} }
var status: MessageStatus { var status = BehaviorSubject<MessageStatus>(value: .unknown)
return self.message.status
}
func bubblePosition() -> BubblePosition { func bubblePosition() -> BubblePosition {
if self.message.isGenerated { if self.message.isGenerated {
......
...@@ -33,6 +33,9 @@ class ConversationsService: MessagesAdapterDelegate { ...@@ -33,6 +33,9 @@ class ConversationsService: MessagesAdapterDelegate {
fileprivate let disposeBag = DisposeBag() fileprivate let disposeBag = DisposeBag()
fileprivate let textPlainMIMEType = "text/plain" fileprivate let textPlainMIMEType = "text/plain"
fileprivate let responseStream = PublishSubject<ServiceEvent>()
var sharedResponseStream: Observable<ServiceEvent>
private var realm: Realm! private var realm: Realm!
fileprivate let results: Results<ConversationModel> fileprivate let results: Results<ConversationModel>
...@@ -40,6 +43,8 @@ class ConversationsService: MessagesAdapterDelegate { ...@@ -40,6 +43,8 @@ class ConversationsService: MessagesAdapterDelegate {
var conversations: Observable<Results<ConversationModel>> var conversations: Observable<Results<ConversationModel>>
init(withMessageAdapter adapter: MessagesAdapter) { init(withMessageAdapter adapter: MessagesAdapter) {
self.responseStream.disposed(by: disposeBag)
self.sharedResponseStream = responseStream.share()
guard let realm = try? Realm() else { guard let realm = try? Realm() else {
fatalError("Enable to instantiate Realm") fatalError("Enable to instantiate Realm")
...@@ -50,8 +55,31 @@ class ConversationsService: MessagesAdapterDelegate { ...@@ -50,8 +55,31 @@ class ConversationsService: MessagesAdapterDelegate {
results = realm.objects(ConversationModel.self) results = realm.objects(ConversationModel.self)
conversations = Observable.collection(from: results, synchronousStart: true) conversations = Observable.collection(from: results, synchronousStart: true)
MessagesAdapter.delegate = self MessagesAdapter.delegate = self
/**
If the app was closed prior to messages receiving a "stable"
status, incorrect status values will remain in the database.
Get updated message status from the daemon for each
message as conversations are loaded from the database.
Only sent messages having an 'unknown' or 'sending' status
are considered for updating.
*/
for conversation in results.toArray() {
for message in (conversation.messages) {
if message.id != "" && (message.status == .unknown || message.status == .sending ) {
let updatedMessageStatus = self.status(forMessageId: message.id)
if updatedMessageStatus != message.status {
self.setMessageStatus(withMessage: message, withStatus: updatedMessageStatus)
.subscribe(onCompleted: { [] in
print("Message status updated - load")
})
.disposed(by: self.disposeBag)
}
}
}
}
} }
func sendMessage(withContent content: String, func sendMessage(withContent content: String,
...@@ -142,8 +170,8 @@ class ConversationsService: MessagesAdapterDelegate { ...@@ -142,8 +170,8 @@ class ConversationsService: MessagesAdapterDelegate {
}) })
} }
func status(forMessageId messageId: UInt64) -> MessageStatus { func status(forMessageId messageId: String) -> MessageStatus {
return self.messageAdapter.status(forMessageId: messageId) return self.messageAdapter.status(forMessageId: UInt64(messageId)!)
} }
func setMessagesAsRead(forConversation conversation: ConversationModel) -> Completable { func setMessagesAsRead(forConversation conversation: ConversationModel) -> Completable {
...@@ -172,6 +200,24 @@ class ConversationsService: MessagesAdapterDelegate { ...@@ -172,6 +200,24 @@ class ConversationsService: MessagesAdapterDelegate {
}) })
} }
func setMessageStatus(withMessage message: MessageModel,
withStatus status: MessageStatus) -> Completable {
return Completable.create(subscribe: { [unowned self] completable in
do {
try self.realm.write {
message.status = status
}
completable(.completed)
} catch let error {
self.log.error("\(error)")
}
return Disposables.create { }
})
}
func deleteConversation(conversation: ConversationModel) { func deleteConversation(conversation: ConversationModel) {
do { do {
...@@ -211,8 +257,33 @@ class ConversationsService: MessagesAdapterDelegate { ...@@ -211,8 +257,33 @@ class ConversationsService: MessagesAdapterDelegate {
func messageStatusChanged(_ status: MessageStatus, func messageStatusChanged(_ status: MessageStatus,
for messageId: UInt64, for messageId: UInt64,
from senderAccountId: String, from accountId: String,
to receiverAccount: String) { to uri: String) {
log.debug("messageStatusChanged: \(status.rawValue) for: \(messageId) from: \(senderAccountId) to: \(receiverAccount)")
//Get conversations for this sender
let conversation = self.results.filter({ conversation in
return conversation.recipientRingId == uri &&
conversation.accountId == accountId
}).first
//Find message
if let message = conversation?.messages.filter({ messages in
return !messages.id.isEmpty && messages.id == String(messageId) && messages.status != status
}).first {
self.setMessageStatus(withMessage: message,
withStatus: status)
.subscribe(onCompleted: { [unowned self] in
self.log.info("Message status updated")
var event = ServiceEvent(withEventType: .messageStateChanged)
event.addEventInput(.messageStatus, value: status)
event.addEventInput(.messageId, value: String(messageId))
event.addEventInput(.id, value: accountId)
event.addEventInput(.uri, value: uri)
self.responseStream.onNext(event)
})
.disposed(by: disposeBag)
}
log.debug("messageStatusChanged: \(status.rawValue) for: \(messageId) from: \(accountId) to: \(uri)")
} }
} }
...@@ -23,6 +23,6 @@ ...@@ -23,6 +23,6 @@
func didReceiveMessage(_ message: [String: String], from senderAccount: String, func didReceiveMessage(_ message: [String: String], from senderAccount: String,
to receiverAccountId: String) to receiverAccountId: String)
func messageStatusChanged(_ status: MessageStatus, for messageId: UInt64, from senderAccountId: String, func messageStatusChanged(_ status: MessageStatus, for messageId: UInt64, from accountId: String,
to receiverAccount: String) to uri: String)
} }
...@@ -29,6 +29,7 @@ enum ServiceEventType { ...@@ -29,6 +29,7 @@ enum ServiceEventType {
case accountsChanged case accountsChanged
case registrationStateChanged case registrationStateChanged
case presenceUpdated case presenceUpdated
case messageStateChanged
} }
/** /**
...@@ -40,6 +41,8 @@ enum ServiceEventInput { ...@@ -40,6 +41,8 @@ enum ServiceEventInput {
case registrationState case registrationState
case uri case uri
case presenceStatus case presenceStatus
case messageStatus
case messageId
} }
/** /**
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment