Merge pull request #788 from vector-im/vector_723

End-to-end encryption UI/UX
This commit is contained in:
giomfo 2016-11-16 10:48:04 +01:00 committed by GitHub
commit da7ba26933
7 changed files with 658 additions and 13 deletions

View file

@ -50,6 +50,8 @@
F003AA801C690628008B430C /* RoomAvatarTitleView.m in Sources */ = {isa = PBXBuildFile; fileRef = F003AA7E1C690628008B430C /* RoomAvatarTitleView.m */; };
F003AA811C690628008B430C /* RoomAvatarTitleView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F003AA7F1C690628008B430C /* RoomAvatarTitleView.xib */; };
F008D6FC1D0180FB0049444D /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = F008D6FB1D0180FB0049444D /* GoogleService-Info.plist */; };
F00ACC601DDB11CE0093F646 /* EncryptionInfoView.m in Sources */ = {isa = PBXBuildFile; fileRef = F00ACC5E1DDB11CE0093F646 /* EncryptionInfoView.m */; };
F00ACC611DDB11CE0093F646 /* EncryptionInfoView.xib in Resources */ = {isa = PBXBuildFile; fileRef = F00ACC5F1DDB11CE0093F646 /* EncryptionInfoView.xib */; };
F00C47861BFF77C800DBABC9 /* RecentTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F00C47841BFF77C800DBABC9 /* RecentTableViewCell.m */; };
F00C47871BFF77C800DBABC9 /* RecentTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F00C47851BFF77C800DBABC9 /* RecentTableViewCell.xib */; };
F00C478B1BFF854400DBABC9 /* RecentsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = F00C478A1BFF854400DBABC9 /* RecentsDataSource.m */; };
@ -469,6 +471,9 @@
F003AA7E1C690628008B430C /* RoomAvatarTitleView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RoomAvatarTitleView.m; path = RoomTitle/RoomAvatarTitleView.m; sourceTree = "<group>"; };
F003AA7F1C690628008B430C /* RoomAvatarTitleView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = RoomAvatarTitleView.xib; path = RoomTitle/RoomAvatarTitleView.xib; sourceTree = "<group>"; };
F008D6FB1D0180FB0049444D /* GoogleService-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "GoogleService-Info.plist"; sourceTree = "<group>"; };
F00ACC5D1DDB11CE0093F646 /* EncryptionInfoView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EncryptionInfoView.h; sourceTree = "<group>"; };
F00ACC5E1DDB11CE0093F646 /* EncryptionInfoView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EncryptionInfoView.m; sourceTree = "<group>"; };
F00ACC5F1DDB11CE0093F646 /* EncryptionInfoView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = EncryptionInfoView.xib; sourceTree = "<group>"; };
F00C47831BFF77C800DBABC9 /* RecentTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RecentTableViewCell.h; sourceTree = "<group>"; };
F00C47841BFF77C800DBABC9 /* RecentTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RecentTableViewCell.m; sourceTree = "<group>"; };
F00C47851BFF77C800DBABC9 /* RecentTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RecentTableViewCell.xib; sourceTree = "<group>"; };
@ -988,6 +993,7 @@
F001D7521B8207C000A162C3 /* Views */ = {
isa = PBXGroup;
children = (
F00ACC5C1DDB11CE0093F646 /* EncryptionInfoView */,
F083C4591D9E9C2400E5246C /* Search */,
F0CC4DBC1C4E26FA003BBE45 /* MediaAlbum */,
71F7F5191C23079100E7ED8F /* Contact */,
@ -1069,6 +1075,16 @@
path = RoomInputToolbar;
sourceTree = "<group>";
};
F00ACC5C1DDB11CE0093F646 /* EncryptionInfoView */ = {
isa = PBXGroup;
children = (
F00ACC5D1DDB11CE0093F646 /* EncryptionInfoView.h */,
F00ACC5E1DDB11CE0093F646 /* EncryptionInfoView.m */,
F00ACC5F1DDB11CE0093F646 /* EncryptionInfoView.xib */,
);
path = EncryptionInfoView;
sourceTree = "<group>";
};
F00C47821BFF77C800DBABC9 /* RoomList */ = {
isa = PBXGroup;
children = (
@ -1815,6 +1831,7 @@
F08714D91DC384810075F633 /* start_chat@2x.png in Resources */,
F09EAFB01DD2109B009C7EFB /* RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib in Resources */,
322574E51D86E0C1009181D3 /* InfoPlist.strings in Resources */,
F00ACC611DDB11CE0093F646 /* EncryptionInfoView.xib in Resources */,
F083C4931D9EAFC500E5246C /* file_photo_icon.png in Resources */,
F03BF6C51D8BF5B1002EF6A7 /* selection_tick.png in Resources */,
F03BF64A1D8BF5B1002EF6A7 /* admin_icon@2x.png in Resources */,
@ -2169,6 +2186,7 @@
F094AA301B78E42600B1FBBF /* AuthenticationViewController.m in Sources */,
F0FE6F7A1D63752A0004E747 /* CallViewController.m in Sources */,
F09EAFAB1DD2109B009C7EFB /* RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.m in Sources */,
F00ACC601DDB11CE0093F646 /* EncryptionInfoView.m in Sources */,
F0C34CB81C17145F00C36F09 /* MXKRoomBubbleTableViewCell+Vector.m in Sources */,
F083C49B1D9EB13500E5246C /* HomeFilesSearchViewController.m in Sources */,
);

View file

@ -189,6 +189,32 @@
"room_event_action_delete" = "Delete";
"room_event_action_cancel_upload" = "Cancel Upload";
"room_event_action_cancel_download" = "Cancel Download";
"room_event_action_view_encryption" = "Device Information";
// Encryption information
"room_event_encryption_info_title" = "End-to-end encryption information\n\n";
"room_event_encryption_info_event" = "Event information\n";
"room_event_encryption_info_event_user_id" = "User ID\n";
"room_event_encryption_info_event_identity_key" = "Curve25519 identity key\n";
"room_event_encryption_info_event_fingerprint_key" = "Claimed Ed25519 fingerprint key\n";
"room_event_encryption_info_event_algorithm" = "Algorithm\n";
"room_event_encryption_info_event_session_id" = "Session ID\n";
"room_event_encryption_info_event_decryption_error" = "Decryption error\n";
"room_event_encryption_info_event_unencrypted" = "unencrypted";
"room_event_encryption_info_event_none" = "none";
"room_event_encryption_info_device" = "\nSender device information\n";
"room_event_encryption_info_device_unknown" = "unknown device\n";
"room_event_encryption_info_device_name" = "Name\n";
"room_event_encryption_info_device_id" = "Device ID\n";
"room_event_encryption_info_device_verification" = "Verification\n";
"room_event_encryption_info_device_fingerprint" = "Ed25519 fingerprint\n";
"room_event_encryption_info_device_verified" = "Verified";
"room_event_encryption_info_device_not_verified" = "NOT verified";
"room_event_encryption_info_device_blocked" = "Blocked";
"room_event_encryption_info_verify" = "Verify";
"room_event_encryption_info_unverify" = "Unverify";
"room_event_encryption_info_block" = "Block";
"room_event_encryption_info_unblock" = "Unblock";
// Room Title
"room_title_new_room" = "New room";

View file

@ -90,6 +90,9 @@
#import "GBDeviceInfo_iOS.h"
#import "RoomEncryptedDataBubbleCell.h"
#import "EncryptionInfoView.h"
@interface RoomViewController ()
{
// The expanded header
@ -132,6 +135,9 @@
UIView *missedDiscussionsBadgeLabelBgView;
UIView *missedDiscussionsBarButtonCustomView;
// Potential encryption details view.
EncryptionInfoView *encryptionInfoView;
// Observe kAppDelegateDidTapStatusBarNotification to handle tap on clock status bar.
id kAppDelegateDidTapStatusBarNotificationObserver;
@ -488,6 +494,38 @@
contentInset.bottom = self.bottomLayoutGuide.length;
self.bubblesTableView.contentInset = contentInset;
// Check here whether a subview has been added or removed
if (encryptionInfoView)
{
if (encryptionInfoView.superview)
{
// Hide the potential expanded header when a subview is added.
self.showExpandedHeader = NO;
}
else
{
// Reset
encryptionInfoView = nil;
// Reload the full table to take into account a potential change on a device status.
[self.bubblesTableView reloadData];
}
}
if (eventDetailsView)
{
if (eventDetailsView.superview)
{
// Hide the potential expanded header when a subview is added.
self.showExpandedHeader = NO;
}
else
{
// Reset
eventDetailsView = nil;
}
}
// Check whether the expanded header is visible
if (self.expandedHeaderContainer.isHidden == NO)
{
@ -815,6 +853,17 @@
}
}
- (void)dismissTemporarySubViews
{
[super dismissTemporarySubViews];
if (encryptionInfoView)
{
[encryptionInfoView removeFromSuperview];
encryptionInfoView = nil;
}
}
- (void)destroy
{
self.navigationItem.rightBarButtonItem.enabled = NO;
@ -1033,7 +1082,9 @@
// - if the room data source does not manage a live timeline.
// - if the user's membership is not 'join'.
// - if the view controller is not embedded inside a split view controller yet.
if (isVisible && (isSizeTransitionInProgress == YES || !self.roomDataSource || !self.roomDataSource.isLive || (self.roomDataSource.room.state.membership != MXMembershipJoin) || !self.splitViewController))
// - if the encryption view is displayed
// - if the event details view is displayed
if (isVisible && (isSizeTransitionInProgress == YES || !self.roomDataSource || !self.roomDataSource.isLive || (self.roomDataSource.room.state.membership != MXMembershipJoin) || !self.splitViewController || encryptionInfoView.superview || eventDetailsView.superview))
{
NSLog(@"[Vector RoomVC] Show expanded header ignored");
return;
@ -1503,6 +1554,16 @@
// Shortcut: when clicking on an unsent media, show the action sheet to resend it
[self dataSource:dataSource didRecognizeAction:kMXKRoomBubbleCellVectorEditButtonPressed inCell:cell userInfo:@{kMXKRoomBubbleCellEventKey:((MXKRoomBubbleTableViewCell*)cell).bubbleData.attachment.event}];
}
else if ([actionIdentifier isEqualToString:kRoomEncryptedDataBubbleCellTapOnEncryptionIcon])
{
// Retrieve the tapped event
MXEvent *tappedEvent = userInfo[kMXKRoomBubbleCellEventKey];
if (tappedEvent)
{
[self showEncryptionInformation:tappedEvent];
}
}
else
{
// Keep default implementation for other actions
@ -1912,6 +1973,19 @@
[reasonAlert showInViewController:strongSelf];
}];
}
if (level == 1 && self.roomDataSource.room.state.isEncrypted)
{
[currentAlert addActionWithTitle:NSLocalizedStringFromTable(@"room_event_action_view_encryption", @"Vector", nil) style:MXKAlertActionStyleDefault handler:^(MXKAlert *alert) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf cancelEventSelection];
// Display encryption details
[strongSelf showEncryptionInformation:selectedEvent];
}];
}
if (level == 0)
{
@ -2996,5 +3070,58 @@
[self refreshActivitiesViewDisplay];
}
# pragma mark - Encryption Information view
- (void)showEncryptionInformation:(MXEvent *)event
{
[self dismissKeyboard];
// Remove potential existing subviews
[self dismissTemporarySubViews];
encryptionInfoView = [[EncryptionInfoView alloc] initWithEvent:event andMatrixSession:self.roomDataSource.mxSession];
// Add shadow on event details view
encryptionInfoView.layer.cornerRadius = 5;
encryptionInfoView.layer.shadowOffset = CGSizeMake(0, 1);
encryptionInfoView.layer.shadowOpacity = 0.5f;
// Add the view and define edge constraints
[self.view addSubview:encryptionInfoView];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:encryptionInfoView
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:self.topLayoutGuide
attribute:NSLayoutAttributeBottom
multiplier:1.0f
constant:10.0f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:encryptionInfoView
attribute:NSLayoutAttributeBottom
relatedBy:NSLayoutRelationEqual
toItem:self.bottomLayoutGuide
attribute:NSLayoutAttributeTop
multiplier:1.0f
constant:-10.0f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:encryptionInfoView
attribute:NSLayoutAttributeLeading
multiplier:1.0f
constant:-10.0f]];
[self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:encryptionInfoView
attribute:NSLayoutAttributeTrailing
multiplier:1.0f
constant:10.0f]];
[self.view setNeedsUpdateConstraints];
}
@end

View file

@ -0,0 +1,29 @@
/*
Copyright 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import <MatrixKit/MatrixKit.h>
@interface EncryptionInfoView : UIView
@property (weak, nonatomic) IBOutlet UITextView *textView;
@property (weak, nonatomic) IBOutlet UIButton *okButton;
@property (weak, nonatomic) IBOutlet UIButton *verifyButton;
@property (weak, nonatomic) IBOutlet UIButton *blockButton;
- (instancetype)initWithEvent:(MXEvent*)event andMatrixSession:(MXSession*)session;
@end

View file

@ -0,0 +1,355 @@
/*
Copyright 2016 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import "EncryptionInfoView.h"
#import "VectorDesignValues.h"
static NSAttributedString *verticalWhitespace = nil;
@interface EncryptionInfoView ()
{
/**
The displayed event
*/
MXEvent *mxEvent;
/**
The matrix session.
*/
MXSession *mxSession;
/**
The event device info
*/
MXDeviceInfo *deviceInfo;
}
@end
@implementation EncryptionInfoView
- (void)awakeFromNib
{
[super awakeFromNib];
// Localize string
[_okButton setTitle:[NSBundle mxk_localizedStringForKey:@"ok"] forState:UIControlStateNormal];
[_okButton setTitle:[NSBundle mxk_localizedStringForKey:@"ok"] forState:UIControlStateHighlighted];
}
- (instancetype)initWithEvent:(MXEvent*)event andMatrixSession:(MXSession*)session
{
NSArray *nibViews = [[NSBundle bundleForClass:[EncryptionInfoView class]] loadNibNamed:NSStringFromClass([EncryptionInfoView class])
owner:nil
options:nil];
self = nibViews.firstObject;
if (self)
{
mxEvent = event;
mxSession = session;
[self setTranslatesAutoresizingMaskIntoConstraints: NO];
if (mxEvent)
{
MXRoom *mxRoom = [mxSession roomWithRoomId:mxEvent.roomId];
if (mxRoom)
{
deviceInfo = [mxRoom eventDeviceInfo:mxEvent];
}
// Prepare text view content
NSMutableAttributedString *textViewAttributedString = [[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_title", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:17]}];
// Event information
NSMutableAttributedString *eventInformationString = [[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_event", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:15]}];
[eventInformationString appendAttributedString:[EncryptionInfoView verticalWhitespace]];
NSString *senderId = event.sender;
NSString *senderKey = event.senderKey;
NSString *claimedKey = event.keysClaimed[@"ed25519"];
NSString *algorithm = event.wireContent[@"algorithm"];
NSString *sessionId = event.wireContent[@"session_id"];
NSString *decryptionError;
if (event.decryptionError)
{
decryptionError = [NSString stringWithFormat:@"** %@ **", event.decryptionError.localizedDescription];
}
if (!senderKey.length)
{
senderKey = NSLocalizedStringFromTable(@"room_event_encryption_info_event_none", @"Vector", nil);
}
if (!claimedKey.length)
{
claimedKey = NSLocalizedStringFromTable(@"room_event_encryption_info_event_none", @"Vector", nil);
}
if (!algorithm.length)
{
algorithm = NSLocalizedStringFromTable(@"room_event_encryption_info_event_unencrypted", @"Vector", nil);
}
if (!sessionId.length)
{
sessionId = NSLocalizedStringFromTable(@"room_event_encryption_info_event_none", @"Vector", nil);
}
[eventInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_event_user_id", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}]];
[eventInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:senderId
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont systemFontOfSize:14]}]];
[eventInformationString appendAttributedString:[EncryptionInfoView verticalWhitespace]];
[eventInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_event_identity_key", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}]];
[eventInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:senderKey
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont systemFontOfSize:14]}]];
[eventInformationString appendAttributedString:[EncryptionInfoView verticalWhitespace]];
[eventInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_event_fingerprint_key", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}]];
[eventInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:claimedKey
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont systemFontOfSize:14]}]];
[eventInformationString appendAttributedString:[EncryptionInfoView verticalWhitespace]];
[eventInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_event_algorithm", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}]];
[eventInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:algorithm
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont systemFontOfSize:14]}]];
[eventInformationString appendAttributedString:[EncryptionInfoView verticalWhitespace]];
if (decryptionError.length)
{
[eventInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_event_decryption_error", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}]];
[eventInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:decryptionError
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont systemFontOfSize:14]}]];
[eventInformationString appendAttributedString:[EncryptionInfoView verticalWhitespace]];
}
[eventInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_event_session_id", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}]];
[eventInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:sessionId
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont systemFontOfSize:14]}]];
[eventInformationString appendAttributedString:[EncryptionInfoView verticalWhitespace]];
[textViewAttributedString appendAttributedString:eventInformationString];
// Device information
NSMutableAttributedString *deviceInformationString = [[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_device", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:15]}];
[deviceInformationString appendAttributedString:[EncryptionInfoView verticalWhitespace]];
if (deviceInfo)
{
NSString *name = deviceInfo.displayName;
NSString *deviceId = deviceInfo.deviceId;
NSMutableAttributedString *verification;
NSString *fingerprint = deviceInfo.fingerprint;
_verifyButton.hidden = NO;
_blockButton.hidden = NO;
switch (deviceInfo.verified)
{
case MXDeviceUnverified:
{
verification = [[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_device_not_verified", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}];
[_verifyButton setTitle:NSLocalizedStringFromTable(@"room_event_encryption_info_verify", @"Vector", nil) forState:UIControlStateNormal];
[_verifyButton setTitle:NSLocalizedStringFromTable(@"room_event_encryption_info_verify", @"Vector", nil) forState:UIControlStateHighlighted];
[_blockButton setTitle:NSLocalizedStringFromTable(@"room_event_encryption_info_block", @"Vector", nil) forState:UIControlStateNormal];
[_blockButton setTitle:NSLocalizedStringFromTable(@"room_event_encryption_info_block", @"Vector", nil) forState:UIControlStateHighlighted];
break;
}
case MXDeviceVerified:
{
verification = [[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_device_verified", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont systemFontOfSize:14]}];
[_verifyButton setTitle:NSLocalizedStringFromTable(@"room_event_encryption_info_unverify", @"Vector", nil) forState:UIControlStateNormal];
[_verifyButton setTitle:NSLocalizedStringFromTable(@"room_event_encryption_info_unverify", @"Vector", nil) forState:UIControlStateHighlighted];
[_blockButton setTitle:NSLocalizedStringFromTable(@"room_event_encryption_info_block", @"Vector", nil) forState:UIControlStateNormal];
[_blockButton setTitle:NSLocalizedStringFromTable(@"room_event_encryption_info_block", @"Vector", nil) forState:UIControlStateHighlighted];
break;
}
case MXDeviceBlocked:
{
verification = [[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_device_blocked", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}];
[_verifyButton setTitle:NSLocalizedStringFromTable(@"room_event_encryption_info_verify", @"Vector", nil) forState:UIControlStateNormal];
[_verifyButton setTitle:NSLocalizedStringFromTable(@"room_event_encryption_info_verify", @"Vector", nil) forState:UIControlStateHighlighted];
[_blockButton setTitle:NSLocalizedStringFromTable(@"room_event_encryption_info_unblock", @"Vector", nil) forState:UIControlStateNormal];
[_blockButton setTitle:NSLocalizedStringFromTable(@"room_event_encryption_info_unblock", @"Vector", nil) forState:UIControlStateHighlighted];
break;
}
default:
break;
}
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_device_name", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}]];
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:(name.length ? name : @"")
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont systemFontOfSize:14]}]];
[deviceInformationString appendAttributedString:[EncryptionInfoView verticalWhitespace]];
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_device_id", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}]];
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:deviceId
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont systemFontOfSize:14]}]];
[deviceInformationString appendAttributedString:[EncryptionInfoView verticalWhitespace]];
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_device_verification", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}]];
[deviceInformationString appendAttributedString:verification];
[deviceInformationString appendAttributedString:[EncryptionInfoView verticalWhitespace]];
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_device_fingerprint", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}]];
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:fingerprint
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont systemFontOfSize:14]}]];
[deviceInformationString appendAttributedString:[EncryptionInfoView verticalWhitespace]];
}
else
{
// Unknown device
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
initWithString:NSLocalizedStringFromTable(@"room_event_encryption_info_device_unknown", @"Vector", nil)
attributes:@{NSForegroundColorAttributeName : kVectorTextColorBlack,
NSFontAttributeName: [UIFont italicSystemFontOfSize:14]}]];
}
[textViewAttributedString appendAttributedString:deviceInformationString];
self.textView.attributedText = textViewAttributedString;
}
else
{
_textView.text = nil;
}
}
return self;
}
- (void)dealloc
{
mxEvent = nil;
mxSession = nil;
}
+ (NSAttributedString *)verticalWhitespace
{
if (verticalWhitespace == nil)
{
verticalWhitespace = [[NSAttributedString alloc] initWithString:@"\n\n" attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:4]}];
}
return verticalWhitespace;
}
#pragma mark - Actions
- (IBAction)onButtonPressed:(id)sender
{
if (sender == _okButton)
{
[self removeFromSuperview];
}
else
{
MXDeviceVerification verificationStatus;
if (sender == _verifyButton)
{
verificationStatus = ((deviceInfo.verified == MXDeviceVerified) ? MXDeviceUnverified : MXDeviceVerified);
}
else if (sender == _blockButton)
{
verificationStatus = ((deviceInfo.verified == MXDeviceBlocked) ? MXDeviceUnverified : MXDeviceBlocked);
}
else
{
// Unexpected case
NSLog(@"EncryptionInfoView: invalid button pressed.");
return;
}
[mxSession.crypto setDeviceVerification:verificationStatus forDevice:deviceInfo.deviceId ofUser:deviceInfo.userId];
[self removeFromSuperview];
}
}
@end

View file

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="16A323" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="8VI-1E-fge" customClass="EncryptionInfoView">
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" bounces="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4nG-AI-PEC">
<rect key="frame" x="10" y="10" width="580" height="540"/>
<subviews>
<textView autoresizesSubviews="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" bounces="NO" scrollEnabled="NO" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" editable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3Vk-Jx-L6Y">
<rect key="frame" x="0.0" y="0.0" width="3373" height="33"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
</textView>
</subviews>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="3Vk-Jx-L6Y" secondAttribute="bottom" id="Cpy-f6-QMy"/>
<constraint firstItem="3Vk-Jx-L6Y" firstAttribute="leading" secondItem="4nG-AI-PEC" secondAttribute="leading" id="S0R-He-sfC"/>
<constraint firstAttribute="trailing" secondItem="3Vk-Jx-L6Y" secondAttribute="trailing" id="fd7-Mq-LUm"/>
<constraint firstItem="3Vk-Jx-L6Y" firstAttribute="top" secondItem="4nG-AI-PEC" secondAttribute="top" id="u5W-iC-lJL"/>
</constraints>
</scrollView>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ump-1C-SzI">
<rect key="frame" x="60" y="560" width="30" height="30"/>
<state key="normal" title="OK">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="onButtonPressed:" destination="8VI-1E-fge" eventType="touchUpInside" id="t42-2S-MsY"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qkC-t0-Qd0">
<rect key="frame" x="355" y="560" width="40" height="30"/>
<state key="normal" title="Verify">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="onButtonPressed:" destination="8VI-1E-fge" eventType="touchUpInside" id="ljK-ul-fY2"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IdO-jn-iTV">
<rect key="frame" x="507" y="560" width="38" height="30"/>
<state key="normal" title="Block">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<action selector="onButtonPressed:" destination="8VI-1E-fge" eventType="touchUpInside" id="j21-e2-e3C"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="4nG-AI-PEC" firstAttribute="leading" secondItem="8VI-1E-fge" secondAttribute="leading" constant="10" id="3dP-o8-EvP"/>
<constraint firstAttribute="centerX" secondItem="qkC-t0-Qd0" secondAttribute="centerX" multiplier="0.8" id="7iU-9D-miY"/>
<constraint firstItem="IdO-jn-iTV" firstAttribute="top" secondItem="4nG-AI-PEC" secondAttribute="bottom" constant="10" id="8xY-z7-1ph"/>
<constraint firstItem="4nG-AI-PEC" firstAttribute="top" secondItem="8VI-1E-fge" secondAttribute="top" constant="10" id="AsZ-Vi-ffo"/>
<constraint firstAttribute="bottom" secondItem="qkC-t0-Qd0" secondAttribute="bottom" constant="10" id="DyR-rX-nt0"/>
<constraint firstAttribute="bottom" secondItem="Ump-1C-SzI" secondAttribute="bottom" constant="10" id="Nfo-nh-gvW"/>
<constraint firstAttribute="centerX" secondItem="Ump-1C-SzI" secondAttribute="centerX" multiplier="4" id="YMC-ob-tqT"/>
<constraint firstAttribute="bottom" secondItem="IdO-jn-iTV" secondAttribute="bottom" constant="10" id="YcV-iN-9WU"/>
<constraint firstAttribute="trailing" secondItem="4nG-AI-PEC" secondAttribute="trailing" constant="10" id="aQF-F6-6lU"/>
<constraint firstAttribute="centerX" secondItem="IdO-jn-iTV" secondAttribute="centerX" multiplier="0.57" id="gAm-ph-zPW"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<nil key="simulatedTopBarMetrics"/>
<nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="blockButton" destination="IdO-jn-iTV" id="HI0-ZU-esJ"/>
<outlet property="okButton" destination="Ump-1C-SzI" id="nXR-dU-t3K"/>
<outlet property="textView" destination="3Vk-Jx-L6Y" id="uOw-Bq-neN"/>
<outlet property="verifyButton" destination="qkC-t0-Qd0" id="6LD-04-WgO"/>
</connections>
</view>
</objects>
</document>

View file

@ -14,7 +14,7 @@
limitations under the License.
*/
#import"RoomEncryptedDataBubbleCell.h"
#import "RoomEncryptedDataBubbleCell.h"
NSString *const kRoomEncryptedDataBubbleCellTapOnEncryptionIcon = @"kRoomEncryptedDataBubbleCellTapOnEncryptionIcon";
@ -47,20 +47,23 @@ NSString *const kRoomEncryptedDataBubbleCellTapOnEncryptionIcon = @"kRoomEncrypt
MXRoom *room = [session roomWithRoomId:event.roomId];
MXDeviceInfo *deviceInfo = [room eventDeviceInfo:event];
switch (deviceInfo.verified)
if (deviceInfo)
{
case MXDeviceUnverified:
switch (deviceInfo.verified)
{
encryptionIcon = @"e2e_warning";
break;
case MXDeviceUnverified:
{
encryptionIcon = @"e2e_warning";
break;
}
case MXDeviceVerified:
{
encryptionIcon = @"e2e_verified";
break;
}
default:
break;
}
case MXDeviceVerified:
{
encryptionIcon = @"e2e_verified";
break;
}
default:
break;
}
}