Skip to content
Draft
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
94 changes: 87 additions & 7 deletions NextcloudTalk/Chat/NCChatController.m
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,14 @@

@interface NCChatController ()

@property (nonatomic, assign) BOOL startProcessingChatRelayMessages;
@property (nonatomic, assign) BOOL stopChatMessagesPoll;
@property (nonatomic, strong) TalkAccount *account;
@property (nonatomic, strong) NSURLSessionTask *getHistoryTask;
@property (nonatomic, strong) NSURLSessionTask *pullMessagesTask;
@property (nonatomic, strong) NSMutableArray *chatRelayMessagesBuffer;
@property (nonatomic, strong) dispatch_queue_t chatRelayMessagesQueue;
@property (nonatomic, strong) NCExternalSignalingController *externalSignalingController;

@end

Expand All @@ -42,9 +46,7 @@ - (instancetype)initForRoom:(NCRoom *)room
{
self = [super init];
if (self) {
_room = room;
_account = [[NCDatabaseManager sharedInstance] talkAccountForAccountId:_room.accountId];

[self commonInitForRoom:room];
[[AllocationTracker shared] addAllocation:@"NCChatController"];
}

Expand All @@ -55,19 +57,31 @@ - (instancetype)initForThreadId:(NSInteger)threadId inRoom:(NCRoom *)room
{
self = [super init];
if (self) {
_room = room;
_threadId = threadId;
_account = [[NCDatabaseManager sharedInstance] talkAccountForAccountId:_room.accountId];

[self commonInitForRoom:room];
[[AllocationTracker shared] addAllocation:@"NCChatController"];
}

return self;
}

- (void)commonInitForRoom:(NCRoom *)room
{
_room = room;
_account = [[NCDatabaseManager sharedInstance] talkAccountForAccountId:_room.accountId];

_externalSignalingController = [[NCSettingsController sharedInstance] externalSignalingControllerForAccountId:_account.accountId];
if (_externalSignalingController.hasChatRelay) {
_chatRelayMessagesQueue = dispatch_queue_create("chat.relay.message.queue", DISPATCH_QUEUE_SERIAL);
_chatRelayMessagesBuffer = [NSMutableArray new];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didReceiveChatMessageFromExternalSignaling:) name:NSNotification.ExtSignalingDidReceiveChatMessage object:nil];
}
}

- (void)dealloc
{
[[AllocationTracker shared] removeAllocation:@"NCChatController"];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}

- (BOOL)isThreadController
Expand Down Expand Up @@ -404,6 +418,24 @@ - (NSArray *)sortedMessagesFromMessageArray:(NSArray *)messages
return sortedMessages;
}

#pragma mark - External Signaling Controller

- (void)didReceiveChatMessageFromExternalSignaling:(NSNotification *)notification
{
NSString *roomToken = [notification.userInfo objectForKey:@"roomid"];
NSDictionary *messageDict = [[[notification.userInfo objectForKey:@"data"] objectForKey:@"chat"] objectForKey:@"comment"];
if ([roomToken isEqualToString:_room.token]) {
dispatch_async(_chatRelayMessagesQueue, ^{
if (!self->_startProcessingChatRelayMessages) {
[self->_chatRelayMessagesBuffer addObject:messageDict];
return;
}

[self handleChatRelayMessage:messageDict];
});
}
}

#pragma mark - Chat

- (NSArray<NCChatMessage *> * _Nonnull)getTemporaryMessages
Expand Down Expand Up @@ -901,12 +933,59 @@ - (void)startReceivingChatMessagesFromMessagesId:(NSInteger)messageId withTimeou
[self checkLastCommonReadMessage:lastCommonReadMessage];

if (error.code != -999) {
BOOL shouldStartLongPolling = statusCode == 304;
NCChatBlock *lastChatBlock = [self chatBlocksForRoomOrThread].lastObject;
[self startReceivingChatMessagesFromMessagesId:lastChatBlock.newestMessageId withTimeout:YES];

if (shouldStartLongPolling && self->_externalSignalingController.hasChatRelay) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong name of the variable?

NSLog(@"Starting chat relay");
[self startProcessingChatRelayMessagesFromMessagesId:lastChatBlock.newestMessageId];
return;
}

[self startReceivingChatMessagesFromMessagesId:lastChatBlock.newestMessageId withTimeout:shouldStartLongPolling];
}
}];
}

- (void)startProcessingChatRelayMessagesFromMessagesId:(NSInteger)messageId
{
dispatch_async(self.chatRelayMessagesQueue, ^{
self.startProcessingChatRelayMessages = YES;
[self flushChatRelayMessagesBuffer];
});
}

- (void)flushChatRelayMessagesBuffer
{
if (self.chatRelayMessagesBuffer.count == 0) {
NSLog(@"No messages store in chat relay messages buffer");
return;
}

[self.chatRelayMessagesBuffer sortUsingDescriptors:@[
[NSSortDescriptor sortDescriptorWithKey:@"id" ascending:YES]
]];

for (NSDictionary *messageDict in self.chatRelayMessagesBuffer) {
[self handleChatRelayMessage:messageDict];
}

[self.chatRelayMessagesBuffer removeAllObjects];
}

- (void)handleChatRelayMessage:(NSDictionary *)messageDict
{
NCChatBlock *lastChatBlock = [self chatBlocksForRoomOrThread].lastObject;
NSInteger lastNewestMessageId = lastChatBlock.newestMessageId;
NCChatMessage *message = [NCChatMessage messageWithDictionary:messageDict andAccountId:self->_account.accountId];
if (message) {
[self updateLastChatBlockWithNewestKnown:message.messageId];
[self storeMessages:@[messageDict]];

[self checkForNewMessagesFromMessageId:lastNewestMessageId];
}
}

- (void)startReceivingNewChatMessages
{
NCChatBlock *lastChatBlock = [self chatBlocksForRoomOrThread].lastObject;
Expand All @@ -915,6 +994,7 @@ - (void)startReceivingNewChatMessages

- (void)stopReceivingNewChatMessages
{
_startProcessingChatRelayMessages = NO;
_stopChatMessagesPoll = YES;
[_pullMessagesTask cancel];
}
Expand Down
16 changes: 15 additions & 1 deletion NextcloudTalk/WebRTC/NCExternalSignalingController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,17 @@ import Foundation
@objc func externalSignalingController(_ externalSignalingController: NCExternalSignalingController, shouldSwitchToCall roomToken: String)
}

@objc extension NSNotification {
public static let ExtSignalingDidReceiveChatMessage = Notification.Name.extSignalingDidReceiveChatMessage
}

extension Notification.Name {
static let extSignalingDidUpdateParticipants = Notification.Name(rawValue: "NCExternalSignalingControllerDidUpdateParticipantsNotification")
static let extSignalingDidReceiveJoinOfParticipant = Notification.Name(rawValue: "NCExternalSignalingControllerDidReceiveJoinOfParticipantNotification")
static let extSignalingDidReceiveLeaveOfParticipant = Notification.Name(rawValue: "NCExternalSignalingControllerDidReceiveLeaveOfParticipantNotification")
static let extSignalingDidReceiveStartedTyping = Notification.Name(rawValue: "NCExternalSignalingControllerDidReceiveStartedTypingNotification")
static let extSignalingDidReceiveStoppedTyping = Notification.Name(rawValue: "NCExternalSignalingControllerDidReceiveStoppedTypingNotification")
static let extSignalingDidReceiveChatMessage = Notification.Name(rawValue: "NCExternalSignalingControllerDidReceiveChatMessageNotification")
}

public typealias SendMessageCompletionBlock = (_ task: URLSessionWebSocketTask?, _ status: NCExternalSignalingSendMessageStatus) -> Void
Expand All @@ -38,6 +43,7 @@ public enum NCExternalSignalingSendMessageStatus {
public private(set) var account: TalkAccount
public private(set) var disconnected: Bool = true
public private(set) var hasMCU: Bool = false
public private(set) var hasChatRelay: Bool = false
public private(set) var sessionId: String?
public private(set) var participantsMap = [String: SignalingParticipant]()

Expand Down Expand Up @@ -280,6 +286,9 @@ public enum NCExternalSignalingSendMessageStatus {
"userid": account.userId,
"ticket": ticket
]
],
"features": [
"chat-relay"
]
]
]
Expand All @@ -289,7 +298,10 @@ public enum NCExternalSignalingSendMessageStatus {
"type": "hello",
"hello": [
"version": "1.0",
"resumeid": resumeId
"resumeid": resumeId,
"features": [
"chat-relay"
]
]
]
}
Expand Down Expand Up @@ -333,6 +345,7 @@ public enum NCExternalSignalingSendMessageStatus {
}

self.hasMCU = serverFeatures.contains(where: { $0 == "mcu" })
self.hasChatRelay = serverFeatures.contains(where: { $0 == "chat-relay" })

DispatchQueue.main.async {
let bgTask = BGTaskHelper.startBackgroundTask(withName: "NCUpdateSignalingVersionTransaction")
Expand Down Expand Up @@ -616,6 +629,7 @@ public enum NCExternalSignalingSendMessageStatus {

if messageType == "chat" {
print("Chat message received")
NotificationCenter.default.post(name: .extSignalingDidReceiveChatMessage, object: self, userInfo: messageDict)
} else if messageType == "recording" {
self.delegate?.externalSignalingController(self, didReceivedSignalingMessage: messageDict)
} else {
Expand Down
Loading