Skip to content

Commit

Permalink
ios: Multiuser calls
Browse files Browse the repository at this point in the history
  • Loading branch information
avently committed Jan 20, 2023
1 parent ad6aa10 commit 526a5bd
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 42 deletions.
5 changes: 2 additions & 3 deletions apps/ios/Shared/Model/NtfManager.swift
Expand Up @@ -37,12 +37,11 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject {
let chatModel = ChatModel.shared
let action = response.actionIdentifier
logger.debug("NtfManager.userNotificationCenter: didReceive: action \(action), categoryIdentifier \(content.categoryIdentifier)")
if let userId = content.userInfo["userId"] as? Int64,
userId != chatModel.currentUser?.userId {
if let userId = content.userInfo["userId"] as? Int64, userId != chatModel.currentUser?.userId {
chatModel.changeActiveUser(userId)
}
if content.categoryIdentifier == ntfCategoryContactRequest && action == ntfActionAcceptContact,
let chatId = content.userInfo["chatId"] as? String {
let chatId = content.userInfo["chatId"] as? String {
if case let .contactRequest(contactRequest) = chatModel.getChat(chatId)?.chatInfo {
Task { await acceptContactRequest(contactRequest) }
} else {
Expand Down
1 change: 0 additions & 1 deletion apps/ios/Shared/Views/Call/CallManager.swift
Expand Up @@ -36,7 +36,6 @@ class CallManager {

func answerIncomingCall(invitation: RcvCallInvitation) {
let m = ChatModel.shared
// TODO: change active user
m.callInvitations.removeValue(forKey: invitation.contact.id)
m.activeCall = Call(
direction: .incoming,
Expand Down
16 changes: 15 additions & 1 deletion apps/ios/Shared/Views/Call/IncomingCallView.swift
Expand Up @@ -56,6 +56,18 @@ struct IncomingCallView: View {
}
}
}
if m.users.count > 1 {
Divider()
HStack {
Spacer()
ProfileImage(imageStr: invitation.user.image, color: .white)
.frame(width: 20, height: 20)
Text(invitation.user.chatViewName)
.fontWeight(.regular)
.font(.subheadline)
.foregroundColor(.primary)
}
}
}
.padding(.horizontal, 16)
.padding(.vertical, 12)
Expand All @@ -82,6 +94,8 @@ struct IncomingCallView: View {
struct IncomingCallView_Previews: PreviewProvider {
static var previews: some View {
CallController.shared.activeCallInvitation = RcvCallInvitation.sampleData
return IncomingCallView()
let m = ChatModel()
m.updateUsers([UserInfo.sampleData, UserInfo.sampleData])
return IncomingCallView().environmentObject(m)
}
}
56 changes: 22 additions & 34 deletions apps/ios/SimpleX NSE/NotificationService.swift
Expand Up @@ -107,18 +107,16 @@ class NotificationService: UNNotificationServiceExtension {
let encNtfInfo = ntfData["message"] as? String,
let dbStatus = startChat() {
if case .ok = dbStatus,
let ntfMsgInfos = apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo) {
for ntfMsgInfo in ntfMsgInfos {
logger.debug("NotificationService: receiveNtfMessages: apiGetNtfMessage \(String(describing: ntfMsgInfo), privacy: .public)")
if let connEntity = ntfMsgInfo.connEntity {
setBestAttemptNtf(createConnectionEventNtf(ntfMsgInfo.user, connEntity))
if let id = connEntity.id {
Task {
logger.debug("NotificationService: receiveNtfMessages: in Task, connEntity id \(id, privacy: .public)")
await PendingNtfs.shared.createStream(id)
await PendingNtfs.shared.readStream(id, for: self, msgCount: ntfMsgInfo.ntfMessages.count)
deliverBestAttemptNtf()
}
let ntfMsgInfo = apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo) {
logger.debug("NotificationService: receiveNtfMessages: apiGetNtfMessage \(String(describing: ntfMsgInfo), privacy: .public)")
if let connEntity = ntfMsgInfo.connEntity {
setBestAttemptNtf(createConnectionEventNtf(ntfMsgInfo.user, connEntity))
if let id = connEntity.id {
Task {
logger.debug("NotificationService: receiveNtfMessages: in Task, connEntity id \(id, privacy: .public)")
await PendingNtfs.shared.createStream(id)
await PendingNtfs.shared.readStream(id, for: self, msgCount: ntfMsgInfo.ntfMessages.count)
deliverBestAttemptNtf()
}
}
}
Expand Down Expand Up @@ -258,15 +256,6 @@ func updateNetCfg() {
}
}

func listUsers() -> [UserInfo] {
let r = sendSimpleXCmd(.listUsers)
logger.debug("listUsers sendSimpleXCmd response: \(String(describing: r))")
switch r {
case let .usersList(users): return users
default: return []
}
}

func apiGetActiveUser() -> User? {
let r = sendSimpleXCmd(.showActiveUser)
logger.debug("apiGetActiveUser sendSimpleXCmd response: \(String(describing: r))")
Expand Down Expand Up @@ -300,21 +289,20 @@ func apiSetIncognito(incognito: Bool) throws {
throw r
}

func apiGetNtfMessage(nonce: String, encNtfInfo: String) -> [NtfMessages]? {
let users = listUsers()
if users.isEmpty {
logger.debug("no users")
return []
func apiGetNtfMessage(nonce: String, encNtfInfo: String) -> NtfMessages? {
guard apiGetActiveUser() != nil else {
logger.debug("no active user")
return nil
}
var result: [NtfMessages] = []
users.forEach {
let r = sendSimpleXCmd(.apiGetNtfMessage(userId: $0.user.userId, nonce: nonce, encNtfInfo: encNtfInfo))
if case let .ntfMessages(user, connEntity, msgTs, ntfMessages) = r {
result.append(NtfMessages(user: user, connEntity: connEntity, msgTs: msgTs, ntfMessages: ntfMessages))
}
logger.debug("apiGetNtfMessage ignored response: \(String.init(describing: r), privacy: .public)")
let r = sendSimpleXCmd(.apiGetNtfMessage(nonce: nonce, encNtfInfo: encNtfInfo))
if case let .ntfMessages(user, connEntity, msgTs, ntfMessages) = r, let user = user {
return NtfMessages(user: user, connEntity: connEntity, msgTs: msgTs, ntfMessages: ntfMessages)
} else if case let .chatCmdError(_, error) = r {
logger.debug("apiGetNtfMessage error response: \(String.init(describing: error), privacy: .public)")
} else {
logger.debug("apiGetNtfMessage ignored response: \(r.responseType, privacy: .public) \(String.init(describing: r).dropFirst(String.init(describing: r).count - 1000), privacy: .public)")
}
return result
return nil
}

func apiReceiveFile(fileId: Int64, inline: Bool) -> AChatItem? {
Expand Down
7 changes: 4 additions & 3 deletions apps/ios/SimpleXChat/APITypes.swift
Expand Up @@ -37,7 +37,7 @@ public enum ChatCommand {
case apiRegisterToken(token: DeviceToken, notificationMode: NotificationsMode)
case apiVerifyToken(token: DeviceToken, nonce: String, code: String)
case apiDeleteToken(token: DeviceToken)
case apiGetNtfMessage(userId: Int64, nonce: String, encNtfInfo: String)
case apiGetNtfMessage(nonce: String, encNtfInfo: String)
case apiNewGroup(userId: Int64, groupProfile: GroupProfile)
case apiAddMember(groupId: Int64, contactId: Int64, memberRole: GroupMemberRole)
case apiJoinGroup(groupId: Int64)
Expand Down Expand Up @@ -124,7 +124,7 @@ public enum ChatCommand {
case let .apiRegisterToken(token, notificationMode): return "/_ntf register \(token.cmdString) \(notificationMode.rawValue)"
case let .apiVerifyToken(token, nonce, code): return "/_ntf verify \(token.cmdString) \(nonce) \(code)"
case let .apiDeleteToken(token): return "/_ntf delete \(token.cmdString)"
case let .apiGetNtfMessage(userId, nonce, encNtfInfo): return "/_ntf message \(userId) \(nonce) \(encNtfInfo)"
case let .apiGetNtfMessage(nonce, encNtfInfo): return "/_ntf message \(nonce) \(encNtfInfo)"
case let .apiNewGroup(userId, groupProfile): return "/_group \(userId) \(encodeJSON(groupProfile))"
case let .apiAddMember(groupId, contactId, memberRole): return "/_add #\(groupId) \(contactId) \(memberRole)"
case let .apiJoinGroup(groupId): return "/_join #\(groupId)"
Expand Down Expand Up @@ -406,7 +406,7 @@ public enum ChatResponse: Decodable, Error {
case callInvitations(callInvitations: [RcvCallInvitation])
case ntfTokenStatus(status: NtfTknStatus)
case ntfToken(token: DeviceToken, status: NtfTknStatus, ntfMode: NotificationsMode)
case ntfMessages(user: User, connEntity: ConnectionEntity?, msgTs: Date?, ntfMessages: [NtfMsgInfo])
case ntfMessages(user: User?, connEntity: ConnectionEntity?, msgTs: Date?, ntfMessages: [NtfMsgInfo])
case newContactConnection(user: User, connection: PendingContactConnection)
case contactConnectionDeleted(user: User, connection: PendingContactConnection)
case cmdOk(user: User?)
Expand Down Expand Up @@ -1049,6 +1049,7 @@ public enum ChatError: Decodable {
public enum ChatErrorType: Decodable {
case noActiveUser
case activeUserExists
case differentActiveUser
case chatNotStarted
case invalidConnReq
case invalidChatMessage(message: String)
Expand Down

0 comments on commit 526a5bd

Please sign in to comment.