diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 05f7ed41f..6cd859aed 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -518,6 +518,8 @@ "event_formatter_widget_removed" = "%@ widget removed by %@"; "event_formatter_jitsi_widget_added" = "VoIP conference added by %@"; "event_formatter_jitsi_widget_removed" = "VoIP conference removed by %@"; +"event_formatter_rerequest_keys_part1_link" = "Re-request encryption keys"; +"event_formatter_rerequest_keys_part2" = " from your other devices."; // Others "or" = "or"; @@ -622,3 +624,8 @@ "deactivate_account_password_alert_title" = "Deactivate Account"; "deactivate_account_password_alert_message" = "To continue, please enter your password"; + +// Re-request confirmation dialog +"rerequest_keys_alert_title" = "Re-request encryption keys"; +"rerequest_keys_alert_message" = "Your key share request has been sent - please check your other devices for key share requests.\n\nKey share requests are sent to your other devices automatically. If you rejected or dismissed the key share request on your other devices, you can request the keys for this session again."; +"rerequest_keys_alert_button" = "Re-request"; diff --git a/Riot/Utils/EventFormatter.h b/Riot/Utils/EventFormatter.h index ba5d6a60c..d55c03257 100644 --- a/Riot/Utils/EventFormatter.h +++ b/Riot/Utils/EventFormatter.h @@ -16,6 +16,16 @@ #import +/** + Link string used in attributed strings to mark a keys re-request action. + */ +FOUNDATION_EXPORT NSString *const kEventFormatterOnReRequestKeysLinkAction; + +/** + Parameters separator in the link string. + */ +FOUNDATION_EXPORT NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator; + /** `EventFormatter` class inherits from `MXKEventFormatter` to define Vector formatting */ diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index ef1732e49..09f92f344 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -21,6 +21,13 @@ #import "WidgetManager.h" +#import "MXDecryptionResult.h" + +#pragma mark - Constants definitions + +NSString *const kEventFormatterOnReRequestKeysLinkAction = @"kEventFormatterOnReRequestKeysLinkAction"; +NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; + @interface EventFormatter () { /** @@ -107,7 +114,40 @@ } } - return [super attributedStringFromEvent:event withRoomState:roomState error:error]; + NSAttributedString *attributedString = [super attributedStringFromEvent:event withRoomState:roomState error:error]; + + if (event.sentState == MXEventSentStateSent + && [event.decryptionError.domain isEqualToString:MXDecryptingErrorDomain] + && event.decryptionError.code == MXDecryptingErrorUnknownInboundSessionIdCode) + { + // Append to the displayed error an attibuted string with a tappable link + // so that the user can try to fix the UTC + NSMutableAttributedString *attributedStringWithRerequestMessage = [attributedString mutableCopy]; + [attributedStringWithRerequestMessage appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n"]]; + + NSString *linkActionString = [NSString stringWithFormat:@"%@%@%@", kEventFormatterOnReRequestKeysLinkAction, + kEventFormatterOnReRequestKeysLinkActionSeparator, + event.eventId]; + + [attributedStringWithRerequestMessage appendAttributedString: + [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"event_formatter_rerequest_keys_part1_link", @"Vector", nil) + attributes:@{ + NSLinkAttributeName: linkActionString, + NSForegroundColorAttributeName: self.sendingTextColor, + NSFontAttributeName: self.encryptedMessagesTextFont + }]]; + + [attributedStringWithRerequestMessage appendAttributedString: + [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"event_formatter_rerequest_keys_part2", @"Vector", nil) + attributes:@{ + NSForegroundColorAttributeName: self.sendingTextColor, + NSFontAttributeName: self.encryptedMessagesTextFont + }]]; + + attributedString = attributedStringWithRerequestMessage; + } + + return attributedString; } - (NSAttributedString*)attributedStringFromEvents:(NSArray*)events withRoomState:(MXRoomState*)roomState error:(MXKEventFormatterError*)error diff --git a/Riot/ViewController/RoomViewController.m b/Riot/ViewController/RoomViewController.m index 093f89e17..0e45eaf38 100644 --- a/Riot/ViewController/RoomViewController.m +++ b/Riot/ViewController/RoomViewController.m @@ -117,6 +117,8 @@ #import "WidgetPickerViewController.h" #import "StickerPickerViewController.h" +#import "EventFormatter.h" + @interface RoomViewController () { // The expanded header @@ -2680,6 +2682,20 @@ NSString *fragment = [NSString stringWithFormat:@"/group/%@", [absoluteURLString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]; [[AppDelegate theDelegate] handleUniversalLinkFragment:fragment]; } + else if ([absoluteURLString hasPrefix:kEventFormatterOnReRequestKeysLinkAction]) + { + NSArray *arguments = [absoluteURLString componentsSeparatedByString:kEventFormatterOnReRequestKeysLinkActionSeparator]; + if (arguments.count > 1) + { + NSString *eventId = arguments[1]; + MXEvent *event = [self.roomDataSource eventWithEventId:eventId]; + + if (event) + { + [self showRerequestConfirmationAlert:event]; + } + } + } } return shouldDoAction; @@ -4582,5 +4598,35 @@ [self presentViewController:currentAlert animated:YES completion:nil]; } +#pragma mark - Re-request encryption keys + +- (void)showRerequestConfirmationAlert:(MXEvent*)event +{ + currentAlert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"rerequest_keys_alert_title", @"Vector", nil) + message:NSLocalizedStringFromTable(@"rerequest_keys_alert_message", @"Vector", nil) + preferredStyle:UIAlertControllerStyleAlert]; + + MXWeakify(self); + [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) + { + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; + }]]; + + [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"rerequest_keys_alert_button", @"Vector", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) + { + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; + + [self.mainSession.crypto reRequestRoomKeyForEvent:event]; + }]]; + + [self presentViewController:currentAlert animated:YES completion:nil]; +} + @end