From 91f1789bf22f0e4aa8a9c2c6bbbe2aec968a9ea5 Mon Sep 17 00:00:00 2001 From: Michelle Linington Date: Mon, 16 Nov 2020 17:32:34 -0800 Subject: [PATCH] Add GroupCallMessage interaction finder. Build GroupCallMessage participant strings --- Signal/src/Calls/CallService.swift | 5 +- .../src/Calls/UserInterface/CallHeader.swift | 4 +- .../Group/GroupCallMemberSheet.swift | 2 +- .../translations/en.lproj/Localizable.strings | 15 ++++- .../src/Messages/OWSGroupCallMessage.m | 60 +++++++++++++++++-- .../Database/Records/InteractionFinder.swift | 26 ++++++++ 6 files changed, 99 insertions(+), 13 deletions(-) diff --git a/Signal/src/Calls/CallService.swift b/Signal/src/Calls/CallService.swift index 0da5429eba..6724657664 100644 --- a/Signal/src/Calls/CallService.swift +++ b/Signal/src/Calls/CallService.swift @@ -606,7 +606,7 @@ extension CallService: CallObserver { self.fetchGroupMembershipProof(for: groupThread) }.done(on: .main) { proof in call.groupCall.updateMembershipProof(proof: proof) - }.catch { error in + }.catch(on: .main) { error in owsFailDebug("Failed to fetch group call credentials \(error)") } } @@ -659,8 +659,7 @@ extension CallService { fileprivate func updateGroupCallMessageWithInfo(_ info: PeekInfo, for thread: TSGroupThread) { databaseStorage.write { writeTx in - // TODO: Build InteractionFinder method to find unended OWSGroupCallMessages for the current thread - let results: [OWSGroupCallMessage] = [] + let results: [OWSGroupCallMessage] = GRDBInteractionFinder.unendedCallsForGroupThread(thread, transaction: writeTx) // Update everything that doesn't match the current call era to mark as ended results diff --git a/Signal/src/Calls/UserInterface/CallHeader.swift b/Signal/src/Calls/UserInterface/CallHeader.swift index f9fcf1d336..d4a20ad425 100644 --- a/Signal/src/Calls/UserInterface/CallHeader.swift +++ b/Signal/src/Calls/UserInterface/CallHeader.swift @@ -203,13 +203,13 @@ class CallHeader: UIView { case 2: let formatString = NSLocalizedString( "GROUP_CALL_TWO_PEOPLE_HERE_FORMAT", - comment: "Text explaining that there are two people in the group call. Embeds {member name}" + comment: "Text explaining that there are two people in the group call. Embeds two {member name}s" ) callTitleText = String(format: formatString, memberNames[0], memberNames[1]) default: let formatString = NSLocalizedString( "GROUP_CALL_MANY_PEOPLE_HERE_FORMAT", - comment: "Text explaining that there are three or more people in the group call. Embeds {member name}" + comment: "Text explaining that there are more than three people in the group call. Embeds two {member name}s and memberCount-2" ) callTitleText = String(format: formatString, memberNames[0], memberNames[1], memberNames.count - 2) } diff --git a/Signal/src/Calls/UserInterface/Group/GroupCallMemberSheet.swift b/Signal/src/Calls/UserInterface/Group/GroupCallMemberSheet.swift index b1b009ecfe..0a9b41f064 100644 --- a/Signal/src/Calls/UserInterface/Group/GroupCallMemberSheet.swift +++ b/Signal/src/Calls/UserInterface/Group/GroupCallMemberSheet.swift @@ -317,7 +317,7 @@ class GroupCallMemberSheet: UIViewController { let thread = TSContactThread.getWithContactAddress(localAddress, transaction: transaction) let displayName = NSLocalizedString( "GROUP_CALL_YOU", - comment: "Text describing the local user in the group call members sheet." + comment: "Text describing the local user as a participant in a group call." ) let comparableName = displayName diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 1e49217f0e..8496cc4ae4 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -1519,13 +1519,16 @@ /* Message indicating that a feature can only be used by group admins. */ "GROUP_ADMIN_ONLY_WARNING" = "Only admins can change this option."; +/* Text in conversation view for a group call that has since ended */ +"GROUP_CALL_ENDED_MESSAGE" = "Group call"; + /* Button to join an ongoing group call */ "GROUP_CALL_JOIN_BUTTON" = "Join Call"; /* String indicating how many people are current in the call */ "GROUP_CALL_MANY_IN_THIS_CALL_FORMAT" = "In this call ยท %ld people"; -/* Text explaining that there are three or more people in the group call. Embeds {member name} */ +/* Text explaining that there are more than three people in the group call. Embeds two {member name}s and memberCount-2 */ "GROUP_CALL_MANY_PEOPLE_HERE_FORMAT" = "%@, %@, and %ld others are in this call"; /* Text explaining that you are the only person currently in the group call */ @@ -1564,13 +1567,19 @@ /* Button to start a group call */ "GROUP_CALL_START_BUTTON" = "Start Call"; -/* Text explaining that there are two people in the group call. Embeds {member name} */ +/* Text explaining that someone started a group call. Embeds {{call originator display name}} */ +"GROUP_CALL_STARTED_MESSAGE" = "%@ started a group call"; + +/* Text explaining that there are three people in the group call. Embeds two {member name}s */ +"GROUP_CALL_THREE_PEOPLE_HERE_FORMAT" = "%@, %@, and 1 other in this call"; + +/* Text explaining that there are two people in the group call. Embeds two {member name}s */ "GROUP_CALL_TWO_PEOPLE_HERE_FORMAT" = "%@ and %@ are in this call"; /* An error displayed to the user when the group call unexpectedly ends. */ "GROUP_CALL_UNEXPECTEDLY_ENDED" = "The connection to the call unexpectedly ended."; -/* Text describing the local user in the group call members sheet. */ +/* Text describing the local user as a participant in a group call. */ "GROUP_CALL_YOU" = "You"; /* Text describing the local user in the group call members sheet when connected from another device. */ diff --git a/SignalServiceKit/src/Messages/OWSGroupCallMessage.m b/SignalServiceKit/src/Messages/OWSGroupCallMessage.m index 39ee053b53..d0b5f2871a 100644 --- a/SignalServiceKit/src/Messages/OWSGroupCallMessage.m +++ b/SignalServiceKit/src/Messages/OWSGroupCallMessage.m @@ -145,14 +145,45 @@ NS_ASSUME_NONNULL_BEGIN - (NSString *)previewTextWithTransaction:(SDSAnyReadTransaction *)transaction { - // TODO: Return "Originator started the call" here - return @"Call started"; + NSString *creatorDisplayName = [self participantNameForAddress:self.creatorAddress]; + NSString *formatString = NSLocalizedString(@"GROUP_CALL_STARTED_MESSAGE", @"Text explaining that someone started a group call. Embeds {{call creator display name}}"); + return [NSString stringWithFormat:formatString, creatorDisplayName]; } - (NSString *)systemTextWithTransaction:(SDSAnyReadTransaction *)transaction { - // TODO: Return the dynamic list of participants, etc. here - return @"Some text for in the conversation"; + NSString *memberString = nil; + BOOL isCreatorInCall = [self.joinedMemberUuids containsObject:self.creatorUuid]; + + if (self.hasEnded) { + memberString = NSLocalizedString(@"GROUP_CALL_ENDED_MESSAGE", @"Text in conversation view for a group call that has since ended"); + + } else if (self.joinedMemberUuids.count >= 4) { + NSString *formatString = NSLocalizedString(@"GROUP_CALL_MANY_PEOPLE_HERE_FORMAT", @"Text explaining that there are more than three people in the group call. Embeds two {member name}s and memberCount-2"); + memberString = [NSString stringWithFormat:formatString, [self participantNameAtIndex:0], [self participantNameAtIndex:1], (self.joinedMemberUuids.count - 2)]; + + } else if (self.joinedMemberUuids.count == 3) { + NSString *formatString = NSLocalizedString(@"GROUP_CALL_THREE_PEOPLE_HERE_FORMAT", @"Text explaining that there are three people in the group call. Embeds two {member name}s"); + memberString = [NSString stringWithFormat:formatString, [self participantNameAtIndex:0], [self participantNameAtIndex:1]]; + + } else if (self.joinedMemberUuids.count == 2) { + NSString *formatString = NSLocalizedString(@"GROUP_CALL_TWO_PEOPLE_HERE_FORMAT", @"Text explaining that there are two people in the group call. Embeds two {member name}s"); + memberString = [NSString stringWithFormat:formatString, [self participantNameAtIndex:0], [self participantNameAtIndex:1]]; + + } else if (isCreatorInCall) { + // If the originator is the only participant, the wording is "X started a group call" instead of "X is in a group call" + NSString *formatString = NSLocalizedString(@"GROUP_CALL_STARTED_MESSAGE", @"Text explaining that someone started a group call. Embeds {{call originator display name}}"); + memberString = [NSString stringWithFormat:formatString, [self participantNameAtIndex:0]]; + + } else if (self.joinedMemberUuids.count == 1) { + NSString *formatString = NSLocalizedString(@"GROUP_CALL_ONE_PERSON_HERE_FORMAT", @"Text explaining that there is one person in the group call. Embeds {member name}"); + memberString = [NSString stringWithFormat:formatString, [self participantNameAtIndex:0]]; + + } else { + memberString = NSLocalizedString(@"GROUP_CALL_ENDED_MESSAGE", @"Text in conversation view for a group call that has since ended"); + } + + return memberString; } @@ -172,6 +203,27 @@ NS_ASSUME_NONNULL_BEGIN }]; } +#pragma mark - Private + +- (NSString *)participantNameAtIndex:(NSUInteger)index +{ + if (self.joinedMemberAddresses.count <= index) { + OWSFailDebug(@"Out of bounds"); + return nil; + } + SignalServiceAddress *address = self.joinedMemberAddresses[index]; + return [self participantNameForAddress:address]; +} + +- (NSString *)participantNameForAddress:(SignalServiceAddress *)address +{ + if (address.isLocalAddress) { + return NSLocalizedString(@"GROUP_CALL_YOU", "Text describing the local user as a participant in a group call."); + } else { + return [SSKEnvironment.shared.contactsManager displayNameForAddress:address]; + } +} + @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift b/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift index ec1e2bb4ff..382cf4ecd1 100644 --- a/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift +++ b/SignalServiceKit/src/Storage/Database/Records/InteractionFinder.swift @@ -909,6 +909,32 @@ public class GRDBInteractionFinder: NSObject, InteractionFinderAdapter { return result } + public static func unendedCallsForGroupThread(_ thread: TSThread, transaction: SDSAnyReadTransaction) -> [OWSGroupCallMessage] { + let sql: String = """ + SELECT * + FROM \(InteractionRecord.databaseTableName) + WHERE \(interactionColumn: .recordType) IS \(SDSRecordType.groupCallMessage.rawValue) + AND \(interactionColumn: .hasEnded) IS FALSE + AND \(interactionColumn: .threadUniqueId) = ? + """ + + var groupCalls: [OWSGroupCallMessage] = [] + let cursor = OWSGroupCallMessage.grdbFetchCursor(sql: sql, arguments: [thread.uniqueId], transaction: transaction.unwrapGrdbRead) + + do { + while let interaction = try cursor.next() { + guard let groupCall = interaction as? OWSGroupCallMessage, !groupCall.hasEnded else { + owsFailDebug("Unexpectedly result: \(interaction.timestamp)") + continue + } + groupCalls.append(groupCall) + } + } catch { + owsFailDebug("unexpected error \(error)") + } + return groupCalls + } + static func attemptingOutInteractionIds(transaction: ReadTransaction) -> [String] { let sql: String = """ SELECT \(interactionColumn: .uniqueId)