Merge remote-tracking branch 'origin/develop' into release-v0.2.0

This commit is contained in:
giomfo
2016-09-15 10:56:21 +02:00
20 changed files with 455 additions and 99 deletions
@@ -34,6 +34,7 @@ typedef enum : NSUInteger
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *contactAvatarHeaderBackgroundHeightConstraint;
@property (weak, nonatomic) IBOutlet UIView *headerView;
@property (weak, nonatomic) IBOutlet UIView *contactAvatarMask;
@property (weak, nonatomic) IBOutlet UILabel *contactNameLabel;
@property (weak, nonatomic) IBOutlet UIView *contactNameLabelMask;
@@ -36,6 +36,9 @@
RoomMemberTitleView* contactTitleView;
MXKImageView *contactAvatar;
// HTTP Request
MXHTTPOperation *roomCreationRequest;
/**
Observe UIApplicationWillChangeStatusBarOrientationNotification to hide/show bubbles bg.
*/
@@ -117,7 +120,24 @@
contactAvatar = contactTitleView.memberAvatar;
contactAvatar.contentMode = UIViewContentModeScaleAspectFill;
contactAvatar.backgroundColor = [UIColor clearColor];
// Add tap to show the contact avatar in fullscreen
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
[tap setNumberOfTouchesRequired:1];
[tap setNumberOfTapsRequired:1];
[tap setDelegate:self];
[contactAvatar addGestureRecognizer:tap];
contactAvatar.userInteractionEnabled = YES;
// Need to listen tap gesture on the area part of the avatar image that is outside
// of the navigation bar, its parent but smaller view.
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
[tap setNumberOfTouchesRequired:1];
[tap setNumberOfTapsRequired:1];
[tap setDelegate:self];
[self.contactAvatarMask addGestureRecognizer:tap];
self.contactAvatarMask.userInteractionEnabled = YES;
// Add the title view and define edge constraints
contactTitleView.translatesAutoresizingMaskIntoConstraints = NO;
[self.navigationItem.titleView addSubview:contactTitleView];
@@ -215,6 +235,12 @@
{
[super destroy];
if (roomCreationRequest)
{
[roomCreationRequest cancel];
roomCreationRequest = nil;
}
[self cancelRegistrationOnContactChangeNotifications];
if (UIApplicationWillChangeStatusBarOrientationNotificationObserver)
@@ -236,6 +262,8 @@
- (void)viewDidLayoutSubviews
{
[super viewDidLayoutSubviews];
if (contactTitleView)
{
// Adjust the header height by taking into account the actual position of the member avatar in title view
@@ -380,7 +408,7 @@
}
else
{
image = [UIImage imageNamed:@"placeholder"];
image = [AvatarGenerator generateAvatarForText:_contact.displayName];
}
}
@@ -498,6 +526,11 @@
}
}
}
// Else check whether the contact has been instantiated with an email or a matrix id
else if ([MXTools isEmailAddress:_contact.displayName] || [MXTools isMatrixUserIdentifier:_contact.displayName])
{
[actionsArray addObject:@(ContactDetailsActionStartChat)];
}
return actionsArray.count;
}
@@ -642,7 +675,7 @@
NSLog(@"[ContactDetailsViewController] Ignore %@ failed: %@", strongSelf.firstMatrixId, error);
// Notify MatrixKit user
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error];
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
@@ -675,7 +708,7 @@
NSLog(@"[ContactDetailsViewController] Unignore %@ failed: %@", self.firstMatrixId, error);
// Notify MatrixKit user
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error];
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
break;
@@ -684,10 +717,73 @@
{
[self addPendingActionMask];
[[AppDelegate theDelegate] startPrivateOneToOneRoomWithUserId:self.firstMatrixId completion:^{
[self removePendingActionMask];
}];
if (_contact.matrixIdentifiers.count)
{
[[AppDelegate theDelegate] startPrivateOneToOneRoomWithUserId:self.firstMatrixId completion:^{
[self removePendingActionMask];
}];
}
else
{
// Create a new room
roomCreationRequest = [self.mainSession createRoom:nil
visibility:kMXRoomDirectoryVisibilityPrivate
roomAlias:nil
topic:nil
success:^(MXRoom *room) {
roomCreationRequest = nil;
NSString *participantId = _contact.displayName;
// Is it an email or a Matrix user ID?
if ([MXTools isEmailAddress:participantId])
{
[room inviteUserByEmail:participantId success:^{
NSLog(@"[ContactDetailsViewController] %@ has been invited (roomId: %@)", participantId, room.state.roomId);
} failure:^(NSError *error) {
NSLog(@"[ContactDetailsViewController] Invite %@ failed", participantId);
// Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
}
else
{
[room inviteUser:participantId success:^{
NSLog(@"[ContactDetailsViewController] %@ has been invited (roomId: %@)", participantId, room.state.roomId);
} failure:^(NSError *error) {
NSLog(@"[ContactDetailsViewController] Invite %@ failed", participantId);
// Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
}
[self removePendingActionMask];
[[AppDelegate theDelegate] showRoom:room.state.roomId andEventId:nil withMatrixSession:self.mainSession];
}
failure:^(NSError *error) {
NSLog(@"[ContactDetailsViewController] Create room failed: %@", error);
roomCreationRequest = nil;
[self removePendingActionMask];
// Notify user
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
}
break;
}
case ContactDetailsActionStartVoiceCall:
@@ -708,42 +804,46 @@
else
{
// Create a new room
[self.mainSession createRoom:nil
visibility:kMXRoomDirectoryVisibilityPrivate
roomAlias:nil
topic:nil
success:^(MXRoom *room) {
// Add the user
[room inviteUser:matrixId success:^{
// Delay the call in order to be sure that the room is ready
dispatch_async(dispatch_get_main_queue(), ^{
[room placeCallWithVideo:isVideoCall success:nil failure:nil];
[self removePendingActionMask];
});
} failure:^(NSError *error) {
NSLog(@"[ContactDetailsViewController] %@ invitation failed (roomId: %@): %@", matrixId, room.state.roomId, error);
[self removePendingActionMask];
// Notify MatrixKit user
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error];
}];
} failure:^(NSError *error) {
NSLog(@"[ContactDetailsViewController] Create room failed: %@", error);
[self removePendingActionMask];
// Notify MatrixKit user
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error];
}];
roomCreationRequest = [self.mainSession createRoom:nil
visibility:kMXRoomDirectoryVisibilityPrivate
roomAlias:nil
topic:nil
success:^(MXRoom *room) {
roomCreationRequest = nil;
// Add the user
[room inviteUser:matrixId success:^{
// Delay the call in order to be sure that the room is ready
dispatch_async(dispatch_get_main_queue(), ^{
[room placeCallWithVideo:isVideoCall success:nil failure:nil];
[self removePendingActionMask];
});
} failure:^(NSError *error) {
NSLog(@"[ContactDetailsViewController] %@ invitation failed (roomId: %@): %@", matrixId, room.state.roomId, error);
[self removePendingActionMask];
// Notify MatrixKit user
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
} failure:^(NSError *error) {
NSLog(@"[ContactDetailsViewController] Create room failed: %@", error);
roomCreationRequest = nil;
[self removePendingActionMask];
// Notify user
[[AppDelegate theDelegate] showErrorAsAlert:error];
}];
}
break;
}
@@ -774,6 +874,35 @@
self.contactNameLabel.text = _contact.displayName;
}
}
else if (view == contactAvatar || view == self.contactAvatarMask)
{
// Show the avatar in full screen
__block MXKImageView * avatarFullScreenView = [[MXKImageView alloc] initWithFrame:CGRectZero];
avatarFullScreenView.stretchable = YES;
[avatarFullScreenView setRightButtonTitle:[NSBundle mxk_localizedStringForKey:@"ok"] handler:^(MXKImageView* imageView, NSString* buttonTitle) {
[avatarFullScreenView dismissSelection];
[avatarFullScreenView removeFromSuperview];
avatarFullScreenView = nil;
}];
NSString *avatarURL = nil;
if (self.firstMatrixId)
{
MXUser *user = [self.mainSession userWithUserId:self.firstMatrixId];
avatarURL = [self.mainSession.matrixRestClient urlOfContent:user.avatarUrl];
}
// TODO: Display the orignal contact avatar when the contast is not a Matrix user
[avatarFullScreenView setImageURL:avatarURL
withType:nil
andImageOrientation:UIImageOrientationUp
previewImage:contactAvatar.image];
[avatarFullScreenView showFullScreen];
}
}
@end
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
@@ -10,6 +10,7 @@
<outlet property="bottomImageView" destination="7Dc-jk-9sT" id="BVN-bt-VXI"/>
<outlet property="contactAvatarHeaderBackground" destination="ouj-VM-zdT" id="bEq-oW-fal"/>
<outlet property="contactAvatarHeaderBackgroundHeightConstraint" destination="dBL-G6-Yec" id="WWx-dy-WtS"/>
<outlet property="contactAvatarMask" destination="xHv-tg-mOt" id="lX8-ju-K6W"/>
<outlet property="contactNameLabel" destination="92g-hC-6jB" id="bL5-VA-WkR"/>
<outlet property="contactNameLabelMask" destination="wEo-Mk-SgZ" id="M3W-zV-ka0"/>
<outlet property="contactStatusLabel" destination="5le-5e-Vml" id="KBV-pM-lBj"/>
@@ -33,6 +34,13 @@
<constraint firstAttribute="height" constant="117" id="dBL-G6-Yec"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xHv-tg-mOt">
<rect key="frame" x="250" y="0.0" width="100" height="125"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="width" constant="100" id="5BQ-kA-kNt"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="92g-hC-6jB">
<rect key="frame" x="278" y="125" width="45" height="21"/>
<constraints>
@@ -72,9 +80,12 @@
<constraint firstItem="5le-5e-Vml" firstAttribute="centerX" secondItem="YXr-As-Mqh" secondAttribute="centerX" id="bmA-Fq-uxO"/>
<constraint firstItem="5le-5e-Vml" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="YXr-As-Mqh" secondAttribute="leading" constant="42" id="ioz-jk-jrE"/>
<constraint firstAttribute="bottom" secondItem="5le-5e-Vml" secondAttribute="bottom" constant="18" id="j10-rX-tMf"/>
<constraint firstItem="xHv-tg-mOt" firstAttribute="centerX" secondItem="YXr-As-Mqh" secondAttribute="centerX" id="lJA-R3-SC8"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="5le-5e-Vml" secondAttribute="trailing" constant="42" id="mad-qx-tHe"/>
<constraint firstItem="xHv-tg-mOt" firstAttribute="bottom" secondItem="92g-hC-6jB" secondAttribute="top" id="ozQ-vh-hGU"/>
<constraint firstItem="92g-hC-6jB" firstAttribute="top" secondItem="ouj-VM-zdT" secondAttribute="bottom" constant="8" id="rKl-Gw-ajI"/>
<constraint firstItem="ouj-VM-zdT" firstAttribute="leading" secondItem="YXr-As-Mqh" secondAttribute="leading" id="rWQ-Ru-7Ej"/>
<constraint firstItem="xHv-tg-mOt" firstAttribute="top" secondItem="YXr-As-Mqh" secondAttribute="top" id="rvr-ll-VaD"/>
<constraint firstItem="ouj-VM-zdT" firstAttribute="top" secondItem="YXr-As-Mqh" secondAttribute="top" id="srY-tD-AhJ"/>
</constraints>
</view>
@@ -108,6 +108,37 @@
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshContactsList) name:kMXKContactManagerDidUpdateMatrixContactsNotification object:nil];
[self refreshContactsList];
// Handle here local contacts
#ifdef MX_USE_CONTACTS_SERVER_SYNC
if (![MXKAppSettings standardAppSettings].syncLocalContacts)
{
// If not requested yet, ask user permission to sync their local contacts
if (![MXKAppSettings standardAppSettings].syncLocalContacts && ![MXKAppSettings standardAppSettings].syncLocalContactsPermissionRequested)
{
[MXKAppSettings standardAppSettings].syncLocalContactsPermissionRequested = YES;
[MXKContactManager requestUserConfirmationForLocalContactsSyncInViewController:self completionHandler:^(BOOL granted) {
if (granted)
{
// Allow local contacts sync in order to add address book emails in search result
[MXKAppSettings standardAppSettings].syncLocalContacts = YES;
}
}];
}
}
#else
// If not requested yet, ask user permission to access their local contacts
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
{
// Try to load the local contacts list
dispatch_async(dispatch_get_main_queue(), ^{
[[MXKContactManager sharedManager] loadLocalContacts];
});
}
#endif
}
- (void)viewWillDisappear:(BOOL)animated
@@ -139,26 +170,41 @@
- (void)refreshContactsList
{
// Retrieve all known matrix users
matrixContacts = [NSMutableArray arrayWithArray:[MXKContactManager sharedManager].matrixContacts];
NSArray *contacts = [NSArray arrayWithArray:[MXKContactManager sharedManager].matrixContacts];
// Sort alphabetically the matrix contacts
// Retrieve all known email addresses from local contacts
NSArray *localEmailContacts = [MXKContactManager sharedManager].localEmailContacts;
matrixContacts = [NSMutableArray arrayWithCapacity:(contacts.count + localEmailContacts.count)];
// Add first email contacts
if (localEmailContacts.count)
{
[matrixContacts addObjectsFromArray:localEmailContacts];
}
if (contacts.count)
{
[matrixContacts addObjectsFromArray:contacts];
}
// Sort invitable contacts by displaying local email first
// ...and then alphabetically.
NSComparator comparator = ^NSComparisonResult(MXKContact *contactA, MXKContact *contactB) {
// Then order by name
if (contactA.sortingDisplayName.length && contactB.sortingDisplayName.length)
{
return [contactA.sortingDisplayName compare:contactB.sortingDisplayName options:NSCaseInsensitiveSearch];
}
else if (contactA.sortingDisplayName.length)
{
return NSOrderedAscending;
}
else if (contactB.sortingDisplayName.length)
BOOL isLocalEmailA = !contactA.matrixIdentifiers.count;
BOOL isLocalEmailB = !contactB.matrixIdentifiers.count;
if (!isLocalEmailA && isLocalEmailB)
{
return NSOrderedDescending;
}
return [contactA.displayName compare:contactB.displayName options:NSCaseInsensitiveSearch];
if (isLocalEmailA && !isLocalEmailB)
{
return NSOrderedAscending;
}
return [contactA.sortingDisplayName compare:contactB.sortingDisplayName options:NSCaseInsensitiveSearch];
};
[matrixContacts sortUsingComparator:comparator];
@@ -212,6 +258,9 @@
if (currentSearchText.length)
{
// Check whether the search input is a valid email or a Matrix user ID
BOOL isValidInput = ([MXTools isEmailAddress:currentSearchText] || [MXTools isMatrixUserIdentifier:currentSearchText]);
filteredContacts = [NSMutableArray array];
isMultiUseNameByDisplayName = [NSMutableDictionary dictionary];
@@ -219,11 +268,19 @@
{
if ([contact matchedWithPatterns:@[currentSearchText]])
{
[filteredContacts addObject:contact];
isMultiUseNameByDisplayName[contact.displayName] = (isMultiUseNameByDisplayName[contact.displayName] ? @(YES) : @(NO));
// Ignore the contact if it corresponds to the search input
if (!isValidInput || [contact.displayName isEqualToString:currentSearchText] == NO)
{
[filteredContacts addObject:contact];
isMultiUseNameByDisplayName[contact.displayName] = (isMultiUseNameByDisplayName[contact.displayName] ? @(YES) : @(NO));
}
}
}
// Show what the user is typing in a cell. So that he can click on it
MXKContact *contact = [[MXKContact alloc] initMatrixContactWithDisplayName:currentSearchText andMatrixID:nil];
[filteredContacts insertObject:contact atIndex:0];
}
else
{
@@ -275,6 +332,20 @@
if (contact)
{
participantCell.contentView.alpha = 1.0;
participantCell.userInteractionEnabled = YES;
if (currentSearchText.length && indexPath.row == 0)
{
// This is the text entered by the user
// Check whether the search input is a valid email or a Matrix user ID before adding the plus icon.
if (![MXTools isEmailAddress:currentSearchText] && ![MXTools isMatrixUserIdentifier:currentSearchText])
{
participantCell.contentView.alpha = 0.5;
participantCell.userInteractionEnabled = NO;
}
}
// Disambiguate the display name when it appears several times.
if (contact.displayName && [isMultiUseNameByDisplayName[contact.displayName] isEqualToNumber:@(YES)])
{
@@ -108,6 +108,8 @@
// Initialize here the data sources if a matrix session has been already set.
[self initializeDataSources];
self.searchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
}
- (void)dealloc
@@ -742,6 +744,7 @@
else if ([[segue identifier] isEqualToString:@"showContactDetails"])
{
ContactDetailsViewController *contactDetailsViewController = segue.destinationViewController;
contactDetailsViewController.enableVoipCall = YES;
contactDetailsViewController.contact = selectedContact;
}
else if ([[segue identifier] isEqualToString:@"showAuth"])
@@ -22,6 +22,7 @@
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *roomMemberAvatarHeaderBackgroundHeightConstraint;
@property (weak, nonatomic) IBOutlet UIView *memberHeaderView;
@property (weak, nonatomic) IBOutlet UIView *roomMemberAvatarMask;
@property (weak, nonatomic) IBOutlet UILabel *roomMemberNameLabel;
@property (weak, nonatomic) IBOutlet UIView *roomMemberNameLabelMask;
@@ -83,7 +83,24 @@
memberTitleView = [RoomMemberTitleView roomMemberTitleView];
self.memberThumbnail = memberTitleView.memberAvatar;
// Add tap to show the room member avatar in fullscreen
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
[tap setNumberOfTouchesRequired:1];
[tap setNumberOfTapsRequired:1];
[tap setDelegate:self];
[self.memberThumbnail addGestureRecognizer:tap];
self.memberThumbnail.userInteractionEnabled = YES;
// Need to listen tap gesture on the area part of the avatar image that is outside
// of the navigation bar, its parent but smaller view.
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
[tap setNumberOfTouchesRequired:1];
[tap setNumberOfTapsRequired:1];
[tap setDelegate:self];
[self.roomMemberAvatarMask addGestureRecognizer:tap];
self.roomMemberAvatarMask.userInteractionEnabled = YES;
// Add the title view and define edge constraints
memberTitleView.translatesAutoresizingMaskIntoConstraints = NO;
[self.navigationItem.titleView addSubview:memberTitleView];
@@ -598,7 +615,32 @@
self.roomMemberNameLabel.text = self.mxRoomMember.displayname;
}
}
else if (view == self.memberThumbnail || view == self.roomMemberAvatarMask)
{
// Show the avatar in full screen
__block MXKImageView * avatarFullScreenView = [[MXKImageView alloc] initWithFrame:CGRectZero];
avatarFullScreenView.stretchable = YES;
[avatarFullScreenView setRightButtonTitle:[NSBundle mxk_localizedStringForKey:@"ok"] handler:^(MXKImageView* imageView, NSString* buttonTitle) {
[avatarFullScreenView dismissSelection];
[avatarFullScreenView removeFromSuperview];
avatarFullScreenView = nil;
}];
NSString *avatarURL = nil;
if (self.mxRoomMember.avatarUrl)
{
avatarURL = [self.mainSession.matrixRestClient urlOfContent:self.mxRoomMember.avatarUrl];
}
[avatarFullScreenView setImageURL:avatarURL
withType:nil
andImageOrientation:UIImageOrientationUp
previewImage:self.memberThumbnail.image];
[avatarFullScreenView showFullScreen];
}
}
@end
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="10117" systemVersion="15G31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="10085"/>
@@ -11,6 +11,7 @@
<outlet property="memberHeaderView" destination="YXr-As-Mqh" id="Eqb-qr-iAo"/>
<outlet property="roomMemberAvatarHeaderBackground" destination="ouj-VM-zdT" id="YeD-zt-8y5"/>
<outlet property="roomMemberAvatarHeaderBackgroundHeightConstraint" destination="dBL-G6-Yec" id="QXZ-ZP-0Rn"/>
<outlet property="roomMemberAvatarMask" destination="MAS-3M-3cg" id="nLI-7d-5Hu"/>
<outlet property="roomMemberNameLabel" destination="92g-hC-6jB" id="gcP-wz-8FT"/>
<outlet property="roomMemberNameLabelMask" destination="wEo-Mk-SgZ" id="uEv-LU-eEI"/>
<outlet property="roomMemberStatusLabel" destination="5le-5e-Vml" id="ODo-tG-ewy"/>
@@ -33,6 +34,13 @@
<constraint firstAttribute="height" constant="117" id="dBL-G6-Yec"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="MAS-3M-3cg">
<rect key="frame" x="250" y="0.0" width="100" height="125"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="width" constant="100" id="fwv-qE-IV1"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="92g-hC-6jB">
<rect key="frame" x="278" y="125" width="45" height="21"/>
<constraints>
@@ -64,18 +72,38 @@
<constraint firstItem="wEo-Mk-SgZ" firstAttribute="centerY" secondItem="92g-hC-6jB" secondAttribute="centerY" id="3Zt-MD-sZK"/>
<constraint firstItem="5le-5e-Vml" firstAttribute="top" secondItem="92g-hC-6jB" secondAttribute="bottom" constant="7" id="5zX-1T-n38"/>
<constraint firstItem="92g-hC-6jB" firstAttribute="centerX" secondItem="YXr-As-Mqh" secondAttribute="centerX" id="7Is-d0-FZp"/>
<constraint firstItem="MAS-3M-3cg" firstAttribute="centerY" secondItem="YXr-As-Mqh" secondAttribute="centerY" id="Ciw-T9-XBe"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="92g-hC-6jB" secondAttribute="trailing" constant="32" id="Eyx-UF-fYc"/>
<constraint firstAttribute="trailing" secondItem="ouj-VM-zdT" secondAttribute="trailing" id="FRy-TL-gS2"/>
<constraint firstItem="wEo-Mk-SgZ" firstAttribute="centerX" secondItem="92g-hC-6jB" secondAttribute="centerX" id="K1f-RX-kpp"/>
<constraint firstItem="wEo-Mk-SgZ" firstAttribute="width" secondItem="YXr-As-Mqh" secondAttribute="width" id="P5e-q6-OIS"/>
<constraint firstItem="92g-hC-6jB" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="YXr-As-Mqh" secondAttribute="leading" constant="32" id="QZB-ue-Sih"/>
<constraint firstItem="MAS-3M-3cg" firstAttribute="centerY" secondItem="YXr-As-Mqh" secondAttribute="centerY" id="Vh6-q9-uJZ"/>
<constraint firstItem="5le-5e-Vml" firstAttribute="centerX" secondItem="YXr-As-Mqh" secondAttribute="centerX" id="bmA-Fq-uxO"/>
<constraint firstItem="5le-5e-Vml" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="YXr-As-Mqh" secondAttribute="leading" constant="42" id="ioz-jk-jrE"/>
<constraint firstAttribute="bottom" secondItem="5le-5e-Vml" secondAttribute="bottom" constant="18" id="j10-rX-tMf"/>
<constraint firstItem="MAS-3M-3cg" firstAttribute="top" secondItem="YXr-As-Mqh" secondAttribute="top" id="jJp-cP-Vgp"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="5le-5e-Vml" secondAttribute="trailing" constant="42" id="mad-qx-tHe"/>
<constraint firstItem="92g-hC-6jB" firstAttribute="top" secondItem="ouj-VM-zdT" secondAttribute="bottom" constant="8" id="rKl-Gw-ajI"/>
<constraint firstItem="ouj-VM-zdT" firstAttribute="leading" secondItem="YXr-As-Mqh" secondAttribute="leading" id="rWQ-Ru-7Ej"/>
<constraint firstItem="MAS-3M-3cg" firstAttribute="bottom" secondItem="92g-hC-6jB" secondAttribute="top" id="rgU-C1-YMW"/>
<constraint firstItem="ouj-VM-zdT" firstAttribute="top" secondItem="YXr-As-Mqh" secondAttribute="top" id="srY-tD-AhJ"/>
<constraint firstItem="MAS-3M-3cg" firstAttribute="centerX" secondItem="YXr-As-Mqh" secondAttribute="centerX" id="vNM-7Z-K2b"/>
<constraint firstAttribute="bottom" secondItem="MAS-3M-3cg" secondAttribute="bottom" id="xEt-kv-tJd"/>
</constraints>
<variation key="default">
<mask key="constraints">
<exclude reference="Ciw-T9-XBe"/>
<exclude reference="Vh6-q9-uJZ"/>
<exclude reference="xEt-kv-tJd"/>
</mask>
</variation>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="RBF-EK-dhz">
<rect key="frame" x="0.0" y="284" width="600" height="33"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="height" constant="33" id="40l-B3-pDk"/>
</constraints>
</view>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="group.png" translatesAutoresizingMaskIntoConstraints="NO" id="7Dc-jk-9sT">
@@ -98,9 +126,12 @@
<constraint firstAttribute="trailing" secondItem="7Dc-jk-9sT" secondAttribute="trailing" id="3C8-er-hQ7"/>
<constraint firstAttribute="trailing" secondItem="YXr-As-Mqh" secondAttribute="trailing" id="3DV-SV-Ifa"/>
<constraint firstItem="YXr-As-Mqh" firstAttribute="leading" secondItem="gX8-mM-6Ig" secondAttribute="leading" id="EbV-lF-mAx"/>
<constraint firstItem="RBF-EK-dhz" firstAttribute="centerY" secondItem="gX8-mM-6Ig" secondAttribute="centerY" id="PO0-bP-cQ5"/>
<constraint firstItem="RBF-EK-dhz" firstAttribute="trailing" secondItem="7Dc-jk-9sT" secondAttribute="trailing" id="RTr-1M-aeU"/>
<constraint firstItem="R6u-PR-DcU" firstAttribute="top" secondItem="YXr-As-Mqh" secondAttribute="bottom" id="VW4-0P-ALX"/>
<constraint firstAttribute="bottom" secondItem="R6u-PR-DcU" secondAttribute="bottom" id="X1a-xq-1Aa"/>
<constraint firstAttribute="trailing" secondItem="R6u-PR-DcU" secondAttribute="trailing" id="aMA-vf-GrY"/>
<constraint firstItem="RBF-EK-dhz" firstAttribute="leading" secondItem="7Dc-jk-9sT" secondAttribute="leading" id="dHb-9z-eww"/>
<constraint firstItem="YXr-As-Mqh" firstAttribute="top" secondItem="gX8-mM-6Ig" secondAttribute="top" id="l7z-od-LJm"/>
<constraint firstItem="7Dc-jk-9sT" firstAttribute="leading" secondItem="gX8-mM-6Ig" secondAttribute="leading" id="rNt-rC-Pxv"/>
<constraint firstItem="R6u-PR-DcU" firstAttribute="leading" secondItem="gX8-mM-6Ig" secondAttribute="leading" id="rbT-O1-m3d"/>
@@ -139,7 +139,7 @@
_searchBarView.placeholder = NSLocalizedStringFromTable(@"room_participants_invite_another_user", @"Vector", nil);
_searchBarView.returnKeyType = UIReturnKeyDone;
_searchBarView.autocapitalizationType = NO;
_searchBarView.autocapitalizationType = UITextAutocapitalizationTypeNone;
[self refreshSearchBarItemsColor:_searchBarView];
_searchBarHeaderBorder.backgroundColor = kVectorColorSilver;
@@ -1684,20 +1684,34 @@
{
self.isAddParticipantSearchBarEditing = YES;
searchBar.showsCancelButton = YES;
// Handle here local contacts
#ifdef MX_USE_CONTACTS_SERVER_SYNC
// If not requested yet, ask user permission to sync their local contacts
if (![MXKAppSettings standardAppSettings].syncLocalContacts && ![MXKAppSettings standardAppSettings].syncLocalContactsPermissionRequested)
{
[MXKAppSettings standardAppSettings].syncLocalContactsPermissionRequested = YES;
[MXKContactManager requestUserConfirmationForLocalContactsSyncInViewController:self completionHandler:^(BOOL granted) {
if (granted)
{
// Allow local contacts sync in order to add address book emails in search result
[MXKAppSettings standardAppSettings].syncLocalContacts = YES;
}
}];
if (granted)
{
// Allow local contacts sync in order to add address book emails in search result
[MXKAppSettings standardAppSettings].syncLocalContacts = YES;
}
}];
}
#else
// If not requested yet, ask user permission to access their local contacts
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
{
// Try to load the local contacts list
dispatch_async(dispatch_get_main_queue(), ^{
[[MXKContactManager sharedManager] loadLocalContacts];
});
}
#endif
return YES;
}
@@ -2060,6 +2060,7 @@
if (selectedContact)
{
ContactDetailsViewController *contactDetailsViewController = segue.destinationViewController;
contactDetailsViewController.enableVoipCall = YES;
contactDetailsViewController.contact = selectedContact;
selectedContact = nil;
@@ -27,6 +27,8 @@
#import <Photos/Photos.h>
#import <MediaPlayer/MediaPlayer.h>
#ifdef MX_USE_CONTACTS_SERVER_SYNC
#define SETTINGS_SECTION_SIGN_OUT_INDEX 0
#define SETTINGS_SECTION_USER_SETTINGS_INDEX 1
#define SETTINGS_SECTION_NOTIFICATIONS_SETTINGS_INDEX 2
@@ -37,6 +39,20 @@
#define SETTINGS_SECTION_LABS_INDEX 7
#define SETTINGS_SECTION_COUNT 7 // Not 8 because the LABS section is currently hidden
#else
#define SETTINGS_SECTION_SIGN_OUT_INDEX 0
#define SETTINGS_SECTION_USER_SETTINGS_INDEX 1
#define SETTINGS_SECTION_NOTIFICATIONS_SETTINGS_INDEX 2
#define SETTINGS_SECTION_IGNORED_USERS_INDEX 3
#define SETTINGS_SECTION_ADVANCED_INDEX 4
#define SETTINGS_SECTION_OTHER_INDEX 5
#define SETTINGS_SECTION_CONTACTS_INDEX 6
#define SETTINGS_SECTION_LABS_INDEX 7
#define SETTINGS_SECTION_COUNT 6 // Not 8 because the CONTACTS and LABS section is currently hidden
#endif
#define NOTIFICATION_SETTINGS_ENABLE_PUSH_INDEX 0
#define NOTIFICATION_SETTINGS_GLOBAL_SETTINGS_INDEX 1
//#define NOTIFICATION_SETTINGS_CONTAINING_MY_USER_NAME_INDEX 1
@@ -139,7 +139,7 @@
_searchBarView.placeholder = NSLocalizedStringFromTable(@"room_participants_invite_another_user", @"Vector", nil);
_searchBarView.returnKeyType = UIReturnKeyDone;
_searchBarView.autocapitalizationType = NO;
_searchBarView.autocapitalizationType = UITextAutocapitalizationTypeNone;
[self refreshSearchBarItemsColor:_searchBarView];
_searchBarHeaderBorder.backgroundColor = kVectorColorSilver;
@@ -589,11 +589,11 @@
// Invite this user if a room is defined
[room inviteUser:participantId success:^{
NSLog(@"[RoomCreation] %@ has been invited (roomId: %@)", participantId, room.state.roomId);
NSLog(@"[StartChatViewController] %@ has been invited (roomId: %@)", participantId, room.state.roomId);
} failure:^(NSError *error) {
NSLog(@"[RoomParticipantsVC] Invite %@ failed", participantId);
NSLog(@"[StartChatViewController] Invite %@ failed", participantId);
// Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
@@ -609,11 +609,11 @@
{
[room inviteUserByEmail:participantId success:^{
NSLog(@"[RoomCreation] %@ has been invited (roomId: %@)", participantId, room.state.roomId);
NSLog(@"[StartChatViewController] %@ has been invited (roomId: %@)", participantId, room.state.roomId);
} failure:^(NSError *error) {
NSLog(@"[RoomParticipantsVC] Invite %@ failed", participantId);
NSLog(@"[StartChatViewController] Invite %@ failed", participantId);
// Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
@@ -623,11 +623,11 @@
{
[room inviteUser:participantId success:^{
NSLog(@"[RoomCreation] %@ has been invited (roomId: %@)", participantId, room.state.roomId);
NSLog(@"[StartChatViewController] %@ has been invited (roomId: %@)", participantId, room.state.roomId);
} failure:^(NSError *error) {
NSLog(@"[RoomParticipantsVC] Invite %@ failed", participantId);
NSLog(@"[StartChatViewController] Invite %@ failed", participantId);
// Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
@@ -647,7 +647,7 @@
roomCreationRequest = nil;
[self stopActivityIndicator];
NSLog(@"[RoomCreation] Create room failed");
NSLog(@"[StartChatViewController] Create room failed");
// Alert user
[[AppDelegate theDelegate] showErrorAsAlert:error];
@@ -801,13 +801,15 @@
self.isAddParticipantSearchBarEditing = YES;
searchBar.showsCancelButton = NO;
// Handle here local contacts
#ifdef MX_USE_CONTACTS_SERVER_SYNC
if (![MXKAppSettings standardAppSettings].syncLocalContacts)
{
// If not requested yet, ask user permission to sync their local contacts
if (![MXKAppSettings standardAppSettings].syncLocalContacts && ![MXKAppSettings standardAppSettings].syncLocalContactsPermissionRequested)
{
[MXKAppSettings standardAppSettings].syncLocalContactsPermissionRequested = YES;
[MXKContactManager requestUserConfirmationForLocalContactsSyncInViewController:self completionHandler:^(BOOL granted) {
if (granted)
{
@@ -817,6 +819,18 @@
}];
}
}
#else
// If not requested yet, ask user permission to access their local contacts
if (ABAddressBookGetAuthorizationStatus() == kABAuthorizationStatusNotDetermined)
{
// Try to load the local contacts list
dispatch_async(dispatch_get_main_queue(), ^{
[[MXKContactManager sharedManager] loadLocalContacts];
});
}
#endif
return YES;
}