Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support avatars in federated calls #1748

Merged
merged 10 commits into from
Aug 11, 2024
20 changes: 20 additions & 0 deletions NextcloudTalk.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,14 @@
1F1C999D2909846400EACF02 /* BGTaskHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD9182828C55A73009092AB /* BGTaskHelper.swift */; };
1F1C999E2909846400EACF02 /* BGTaskHelper.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1FD9182828C55A73009092AB /* BGTaskHelper.swift */; };
1F1DF8412C63C25900E5EA86 /* UnitNCDatabaseManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1DF8402C63C25900E5EA86 /* UnitNCDatabaseManager.swift */; };
1F1DF83C2C5C17AF00E5EA86 /* TalkActor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1DF83B2C5C17AF00E5EA86 /* TalkActor.swift */; };
1F1DF83D2C5C17AF00E5EA86 /* TalkActor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1DF83B2C5C17AF00E5EA86 /* TalkActor.swift */; };
1F1DF83E2C5C17AF00E5EA86 /* TalkActor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1DF83B2C5C17AF00E5EA86 /* TalkActor.swift */; };
1F1DF83F2C5C17AF00E5EA86 /* TalkActor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1DF83B2C5C17AF00E5EA86 /* TalkActor.swift */; };
1F1DF8432C64006E00E5EA86 /* SignalingParticipant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1DF8422C64006E00E5EA86 /* SignalingParticipant.swift */; };
1F1DF8442C64006E00E5EA86 /* SignalingParticipant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1DF8422C64006E00E5EA86 /* SignalingParticipant.swift */; };
1F1DF8452C64006E00E5EA86 /* SignalingParticipant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1DF8422C64006E00E5EA86 /* SignalingParticipant.swift */; };
1F1DF8462C64006E00E5EA86 /* SignalingParticipant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F1DF8422C64006E00E5EA86 /* SignalingParticipant.swift */; };
1F24B5A228E0648600654457 /* ReferenceGithubView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F24B5A128E0648600654457 /* ReferenceGithubView.swift */; };
1F24B5A428E0649200654457 /* ReferenceGithubView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1F24B5A328E0649200654457 /* ReferenceGithubView.xib */; };
1F35F8E02AEEB9DE00044BDA /* ShareConfirmationViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F35F8DF2AEEB9DE00044BDA /* ShareConfirmationViewController.swift */; };
Expand Down Expand Up @@ -665,6 +673,8 @@
1F1C0D8629AFB88800D17C6D /* VLCKitVideoViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = VLCKitVideoViewController.xib; sourceTree = "<group>"; };
1F1C0D8829AFB89900D17C6D /* VLCKitVideoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = VLCKitVideoViewController.swift; sourceTree = "<group>"; };
1F1DF8402C63C25900E5EA86 /* UnitNCDatabaseManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UnitNCDatabaseManager.swift; sourceTree = "<group>"; };
1F1DF83B2C5C17AF00E5EA86 /* TalkActor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TalkActor.swift; sourceTree = "<group>"; };
1F1DF8422C64006E00E5EA86 /* SignalingParticipant.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignalingParticipant.swift; sourceTree = "<group>"; };
1F24B5A128E0648600654457 /* ReferenceGithubView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ReferenceGithubView.swift; sourceTree = "<group>"; };
1F24B5A328E0649200654457 /* ReferenceGithubView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ReferenceGithubView.xib; sourceTree = "<group>"; };
1F35F8DF2AEEB9DE00044BDA /* ShareConfirmationViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareConfirmationViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1887,6 +1897,8 @@
2CD5F3232142781A006B71BF /* NCExternalSignalingController.m */,
2C69323B2923ECAA00017AD2 /* WSMessage.h */,
2C69323C2923ECAA00017AD2 /* WSMessage.m */,
1F1DF83B2C5C17AF00E5EA86 /* TalkActor.swift */,
1F1DF8422C64006E00E5EA86 /* SignalingParticipant.swift */,
1F8AAC312C518759004DA20A /* SignalingSettings.swift */,
1F8AAC362C519577004DA20A /* TurnServer.swift */,
1F8AAC3B2C519689004DA20A /* StunServer.swift */,
Expand Down Expand Up @@ -2714,6 +2726,7 @@
1F77A5F32AB9A43B007B6037 /* SwiftMarkdownObjCBridge.swift in Sources */,
1FF4DA832C025DBF00C1B952 /* NCAPISessionManager.swift in Sources */,
1FDFC9502BA50B9100670DF4 /* UIFontExtension.swift in Sources */,
1F1DF8462C64006E00E5EA86 /* SignalingParticipant.swift in Sources */,
1FF2FD832AB99F3B000C9905 /* NCAppBranding.m in Sources */,
1F77A5F82AB9A4CD007B6037 /* NCDeckCardParameter.m in Sources */,
1F77A5FD2AB9A4F3007B6037 /* ServerCapabilities.m in Sources */,
Expand All @@ -2737,6 +2750,7 @@
1F77A60A2AB9A5AE007B6037 /* NCUser.m in Sources */,
1F8AAC3F2C519689004DA20A /* StunServer.swift in Sources */,
1FF4DA992C0327FF00C1B952 /* NCWebImageDownloaderOperation.swift in Sources */,
1F1DF83F2C5C17AF00E5EA86 /* TalkActor.swift in Sources */,
1F1B504A2B90CF0800B0F2F4 /* TalkCapabilities.m in Sources */,
2C6955122B0CE1A10070F6E1 /* NCUtils.swift in Sources */,
1FF4DA8D2C0264B100C1B952 /* NCPushProxySessionManager.swift in Sources */,
Expand Down Expand Up @@ -2904,6 +2918,7 @@
2C21446E2BB5B54D005A6537 /* BaseChatTableViewCell+Location.swift in Sources */,
2C4230F72B207AB00013E1FA /* ContextChatViewController.swift in Sources */,
1F90DA0429E9A28E00E81E3D /* AvatarManager.swift in Sources */,
1F1DF8432C64006E00E5EA86 /* SignalingParticipant.swift in Sources */,
2CC1FF4428147F11009F7288 /* RoomSharedItemsTableViewController.swift in Sources */,
2CC1C38629C0945700C8436B /* DRCellSlideGestureRecognizer.m in Sources */,
1FF4DA9B2C032AAC00C1B952 /* RoomTableViewCell.swift in Sources */,
Expand Down Expand Up @@ -2984,6 +2999,7 @@
1F468E7828DCC7310099597B /* EmojiTextField.swift in Sources */,
80832B762A822E5100195A97 /* UserStatusSwiftUIView.swift in Sources */,
1FF4DA822C025DB900C1B952 /* NCAPISessionManager.swift in Sources */,
1F1DF83C2C5C17AF00E5EA86 /* TalkActor.swift in Sources */,
2C444708265E59BC00DF1DBC /* ShareItemController.m in Sources */,
2CA1CC951F014EF9002FE6A2 /* NCSettingsController.m in Sources */,
2C440D1120EA4A770005F9BB /* RoomInfoTableViewController.m in Sources */,
Expand Down Expand Up @@ -3036,6 +3052,7 @@
1F0B0A742BA265310073FF8D /* MentionSuggestion.swift in Sources */,
2C62B00D24C1BDC1007E460A /* NCPushNotification.m in Sources */,
1F1B50492B90CF0800B0F2F4 /* TalkCapabilities.m in Sources */,
1F1DF83E2C5C17AF00E5EA86 /* TalkActor.swift in Sources */,
1FB7B9912BF0CDF80093CE98 /* BannedActor.swift in Sources */,
2C62B01C24C1BDC9007E460A /* CCCertificate.m in Sources */,
2C4446F9265D5A0700DF1DBC /* NotificationCenterNotifications.m in Sources */,
Expand All @@ -3056,6 +3073,7 @@
1F35F8E12AEEB9DE00044BDA /* ShareConfirmationViewController.swift in Sources */,
1F90EFBE25FE39F800F3FA55 /* NCIntentController.m in Sources */,
1FF4DA842C025DC000C1B952 /* NCAPISessionManager.swift in Sources */,
1F1DF8452C64006E00E5EA86 /* SignalingParticipant.swift in Sources */,
2C3195C224C5E2100066F221 /* ShareTableViewCell.m in Sources */,
2CC1FF4A2818395F009F7288 /* NCDeckCardParameter.m in Sources */,
1FF136112BFB4F8C006A6101 /* NCRoom.swift in Sources */,
Expand Down Expand Up @@ -3104,6 +3122,7 @@
1FDFC94E2BA50B9100670DF4 /* UIFontExtension.swift in Sources */,
2C4446F4265D51A600DF1DBC /* NCPushNotificationsUtils.m in Sources */,
1FA38C9129A4B3C6008871B8 /* NCNotificationAction.swift in Sources */,
1F1DF83D2C5C17AF00E5EA86 /* TalkActor.swift in Sources */,
1F1B504D2B90CF0C00B0F2F4 /* FederatedCapabilities.m in Sources */,
2C4446DE2658158000DF1DBC /* NCChatBlock.m in Sources */,
2C5BFBF3288AA37F00E75118 /* NCPoll.m in Sources */,
Expand All @@ -3114,6 +3133,7 @@
1F8AAC382C519577004DA20A /* TurnServer.swift in Sources */,
2CC001C124A37AC500A20167 /* NCNotification.m in Sources */,
2C4446FD265D5DFA00DF1DBC /* ABContact.m in Sources */,
1F1DF8442C64006E00E5EA86 /* SignalingParticipant.swift in Sources */,
1F8AAC3D2C519689004DA20A /* StunServer.swift in Sources */,
2C4446F8265D5A0700DF1DBC /* NotificationCenterNotifications.m in Sources */,
2C6955142B0CE1A20070F6E1 /* NCUtils.swift in Sources */,
Expand Down
27 changes: 3 additions & 24 deletions NextcloudTalk/BaseChatTableViewCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -143,22 +143,8 @@ class BaseChatTableViewCell: UITableViewCell, ReactionsViewDelegate {
let date = Date(timeIntervalSince1970: TimeInterval(message.timestamp))
self.dateLabel.text = NCUtils.getTime(fromDate: date)

var actorDisplayName = message.actorDisplayName ?? ""

if actorDisplayName.isEmpty {
if message.actorId == "deleted_users", message.actorType == "deleted_users" {
actorDisplayName = NSLocalizedString("Deleted user", comment: "")
} else {
actorDisplayName = NSLocalizedString("Guest", comment: "")
}
}

var titleLabel = actorDisplayName.withTextColor(.secondaryLabel)

if message.actorType == "federated_users", let remoteServer = message.actorId.split(separator: "@").last {
let remoteServerString = " (\(String(remoteServer)))"
titleLabel.append(remoteServerString.withTextColor(.tertiaryLabel))
}
let messageActor = message.actor
let titleLabel = messageActor.attributedDisplayName

if let lastEditActorDisplayName = message.lastEditActorDisplayName, message.lastEditTimestamp > 0 {
var editedString = ""
Expand Down Expand Up @@ -195,14 +181,7 @@ class BaseChatTableViewCell: UITableViewCell, ReactionsViewDelegate {

let quoteString = parent.parsedMarkdownForChat()?.string ?? ""
self.quotedMessageView?.messageLabel.text = quoteString

var parentActorDisplayName = parent.actorDisplayName ?? ""

if parentActorDisplayName.isEmpty {
parentActorDisplayName = NSLocalizedString("Guest", comment: "")
}

self.quotedMessageView?.actorLabel.text = parentActorDisplayName
self.quotedMessageView?.actorLabel.attributedText = parent.actor.attributedDisplayName
self.quotedMessageView?.highlighted = parent.isMessage(from: activeAccount.userId)
self.quotedMessageView?.avatarView.setActorAvatar(forMessage: parent)
}
Expand Down
8 changes: 4 additions & 4 deletions NextcloudTalk/BaseChatViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1167,10 +1167,10 @@ import QuickLook
// TODO: Remove workaround for federated typing indicators.
guard let serverCapabilities = NCDatabaseManager.sharedInstance().serverCapabilities(forAccountId: self.room.accountId),
!serverCapabilities.typingPrivacy,
let signalingController = NCSettingsController.sharedInstance().externalSignalingController(forAccountId: self.room.accountId),
let participantMap = signalingController.getParticipantMap()
let signalingController = NCSettingsController.sharedInstance().externalSignalingController(forAccountId: self.room.accountId)
else { return }

let participantMap = signalingController.getParticipantMap()
let mySessionId = signalingController.sessionId()

for (key, _) in participantMap {
Expand All @@ -1184,10 +1184,10 @@ import QuickLook
func sendStoppedTypingMessageToAll() {
guard let serverCapabilities = NCDatabaseManager.sharedInstance().roomTalkCapabilities(for: self.room),
!serverCapabilities.typingPrivacy,
let signalingController = NCSettingsController.sharedInstance().externalSignalingController(forAccountId: self.room.accountId),
let participantMap = signalingController.getParticipantMap()
let signalingController = NCSettingsController.sharedInstance().externalSignalingController(forAccountId: self.room.accountId)
else { return }

let participantMap = signalingController.getParticipantMap()
let mySessionId = signalingController.sessionId()

for (key, _) in participantMap {
Expand Down
3 changes: 2 additions & 1 deletion NextcloudTalk/CallParticipantViewCell.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ extern CGFloat const kCallParticipantCellMinHeight;
@class CallParticipantViewCell;
@class MDCActivityIndicator;
@class AvatarImageView;
@class TalkActor;

@protocol CallParticipantViewCellDelegate <NSObject>
- (void)cellWantsToPresentScreenSharing:(CallParticipantViewCell *)participantCell;
Expand Down Expand Up @@ -47,7 +48,7 @@ extern CGFloat const kCallParticipantCellMinHeight;

- (void)setVideoView:(RTCMTLVideoView *)videoView;
- (void)setSpeaking:(BOOL)speaking;
- (void)setUserAvatar:(NSString *)userId withDisplayName:(NSString *)displayName;
- (void)setAvatarForActor:(TalkActor *)actor;
- (void)setRemoteVideoSize:(CGSize)size;
- (void)setRaiseHand:(BOOL)raised;
- (void)resizeRemoteVideoView;
Expand Down
12 changes: 6 additions & 6 deletions NextcloudTalk/CallParticipantViewCell.m
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,17 @@ - (void)toggleZoom
[self resizeRemoteVideoView];
}

- (void)setUserAvatar:(NSString *)userId withDisplayName:(NSString *)displayName
- (void)setAvatarForActor:(TalkActor *)actor
{
if (!userId || userId.length == 0) {
if (actor.id == nil || actor.id.length == 0) {
[self setBackgroundColor:[UIColor colorWithWhite:0.5 alpha:1]];
} else if (displayName.length > 0) {
[self setBackgroundColor:[[ColorGenerator shared] usernameToColor:displayName]];
} else if (actor.displayName && actor.displayName.length > 0) {
[self setBackgroundColor:[[ColorGenerator shared] usernameToColor:actor.displayName]];
} else {
[self setBackgroundColor:[[ColorGenerator shared] usernameToColor:userId]];
[self setBackgroundColor:[[ColorGenerator shared] usernameToColor:actor.id]];
}

[self.peerAvatarImageView setActorAvatarForId:userId withType:@"users" withDisplayName:@"" withRoomToken:nil];
[self.peerAvatarImageView setActorAvatarForId:actor.id withType:actor.type withDisplayName:actor.displayName withRoomToken:nil];
}

- (void)setDisplayName:(NSString *)displayName
Expand Down
9 changes: 7 additions & 2 deletions NextcloudTalk/CallViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -1930,12 +1930,17 @@ - (void)updateParticipantCell:(CallParticipantViewCell *)cell withPeerConnection
[cell.audioOffIndicator setAlpha:_isDetailedViewVisible ? 1.0 : 0.0];

[[WebRTCCommon shared] dispatch:^{
NSString *userId = [self->_callController getUserIdFromSessionId:peerConnection.peerId];
TalkActor *actor = [self->_callController getActorFromSessionId:peerConnection.peerId];

if ([actor.rawDisplayName isEqualToString:@""] && peerConnection.peerName && ![peerConnection.peerName isEqualToString:@""]) {
actor.rawDisplayName = peerConnection.peerName;
}

RTCIceConnectionState connectionState = peerConnection.isDummyPeer ?
RTCIceConnectionStateConnected : [peerConnection getPeerConnection].iceConnectionState;

dispatch_async(dispatch_get_main_queue(), ^{
[cell setUserAvatar:userId withDisplayName:peerConnection.peerName];
[cell setAvatarForActor:actor];
[cell setConnectionState:connectionState];
});
}];
Expand Down
3 changes: 2 additions & 1 deletion NextcloudTalk/NCCallController.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
@class RTCAudioTrack;
@class RTCVideoTrack;
@class NCCameraController;
@class TalkActor;

typedef void (^GetVideoEnabledStateCompletionBlock)(BOOL isEnabled);
typedef void (^GetAudioEnabledStateCompletionBlock)(BOOL isEnabled);
Expand Down Expand Up @@ -72,7 +73,7 @@ typedef void (^GetAudioEnabledStateCompletionBlock)(BOOL isEnabled);
- (void)stopRecording;
- (void)startScreenshare;
- (void)stopScreenshare;
- (NSString *)getUserIdFromSessionId:(NSString *)sessionId;
- (TalkActor * _Nullable)getActorFromSessionId:(NSString * _Nonnull)sessionId;
- (NSString *)signalingSessionId;
- (BOOL)isBackgroundBlurEnabled;
- (void)enableBackgroundBlur:(BOOL)enable;
Expand Down
48 changes: 23 additions & 25 deletions NextcloudTalk/NCCallController.m
Original file line number Diff line number Diff line change
Expand Up @@ -928,9 +928,9 @@ - (NCPeerConnection *)getOrCreatePeerConnectionWrapperForSessionId:(NSString *)s
peerConnectionWrapper.isOwnScreensharePeer = ownScreenshare;

// Try to get displayName early
NSString *displayName = [self getDisplayNameFromSessionId:sessionId];
if (displayName) {
[peerConnectionWrapper setPeerName:displayName];
TalkActor *actor = [self getActorFromSessionId:sessionId];
if (actor && ![actor.rawDisplayName isEqualToString:@""]) {
[peerConnectionWrapper setPeerName:actor.displayName];
}

// Do not add local stream when using a MCU or to screensharing peers
Expand Down Expand Up @@ -1311,16 +1311,26 @@ - (void)processSignalingMessage:(NCSignalingMessage *)signalingMessage
// If there is already a peer connection but a new offer is received with a different sid the existing
// peer connection is stale, so it needs to be removed and a new one created instead.
NCPeerConnection *peerConnectionWrapper = [self getPeerConnectionWrapperForSessionId:signalingMessage.from ofType:signalingMessage.roomType forOwnScreenshare:isAnswerToOwnScreenshare];
NSString *peerName;
if (signalingMessage.messageType == kNCSignalingMessageTypeOffer && peerConnectionWrapper &&
signalingMessage.sid.length > 0 && ![signalingMessage.sid isEqualToString:peerConnectionWrapper.sid]) {

// Remember the peerName for the new connectionWrapper
peerName = peerConnectionWrapper.peerName;
[self cleanPeerConnectionForSessionId:signalingMessage.from ofType:signalingMessage.roomType forOwnScreenshare:isAnswerToOwnScreenshare];
}

peerConnectionWrapper = [self getOrCreatePeerConnectionWrapperForSessionId:signalingMessage.from withSid:signalingMessage.sid ofType:signalingMessage.roomType forOwnScreenshare:isAnswerToOwnScreenshare];
NCSessionDescriptionMessage *sdpMessage = (NCSessionDescriptionMessage *)signalingMessage;
RTCSessionDescription *sessionDescription = sdpMessage.sessionDescription;
[peerConnectionWrapper setPeerName:sdpMessage.nick];
[peerConnectionWrapper setRemoteDescription:sessionDescription];

if (sdpMessage.nick && ![sdpMessage.nick isEqualToString:@""]) {
[peerConnectionWrapper setPeerName:sdpMessage.nick];
} else if (peerName) {
[peerConnectionWrapper setPeerName:peerName];
}

break;
}
case kNCSignalingMessageTypeCandidate:
Expand Down Expand Up @@ -1568,42 +1578,30 @@ - (NSMutableArray *)getInCallSessionsFromUsersInRoom:(NSArray *)users
return sessions;
}

- (NSString *)getUserIdFromSessionId:(NSString *)sessionId
- (TalkActor *)getActorFromSessionId:(NSString *)sessionId
{
[[WebRTCCommon shared] assertQueue];

if (_externalSignalingController) {
return [_externalSignalingController getUserIdFromSessionId:sessionId];
return [_externalSignalingController getParticipantFromSessionId:sessionId].actor;
}

NSInteger callAPIVersion = [[NCAPIController sharedInstance] callAPIVersionForAccount:_account];
NSString *userId = nil;

for (NSMutableDictionary *user in _peersInCall) {
NSString *userSessionId = [user objectForKey:@"sessionId"];
if ([userSessionId isEqualToString:sessionId]) {
userId = [user objectForKey:@"userId"];
TalkActor *actor = [[TalkActor alloc] initWithActorId:[user objectForKey:@"userId"] actorType:@"users" actorDisplayName:[user objectForKey:@"displayName"]];

if (callAPIVersion >= APIv3) {
userId = [user objectForKey:@"actorId"];
[actor setId:[user objectForKey:@"actorId"]];
[actor setType:[user objectForKey:@"actorType"]];
}
}
}
return userId;
}

- (NSString *)getDisplayNameFromSessionId:(NSString *)sessionId
{
[[WebRTCCommon shared] assertQueue];

if (_externalSignalingController) {
return [_externalSignalingController getDisplayNameFromSessionId:sessionId];
}
for (NSMutableDictionary *user in _peersInCall) {
NSString *userSessionId = [user objectForKey:@"sessionId"];
if ([userSessionId isEqualToString:sessionId]) {
return [user objectForKey:@"displayName"];
return actor;
}
}

return nil;
}

Expand Down
Loading
Loading