mirror of
https://github.com/vector-im/element-ios.git
synced 2024-09-29 07:42:40 +00:00
Move all the view controllers related to the communities
This commit is contained in:
parent
5c8ebf04f1
commit
ebcb53df42
14 changed files with 0 additions and 4240 deletions
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations 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 "SegmentedViewController.h"
|
||||
|
||||
@interface GroupDetailsViewController : SegmentedViewController
|
||||
|
||||
@property (strong, readonly, nonatomic) MXGroup *group;
|
||||
@property (strong, readonly, nonatomic) MXSession *mxSession;
|
||||
|
||||
/**
|
||||
Returns the `UINib` object initialized for a `GroupDetailsViewController`.
|
||||
|
||||
@return The initialized `UINib` object or `nil` if there were errors during initialization
|
||||
or the nib file could not be located.
|
||||
*/
|
||||
+ (UINib *)nib;
|
||||
|
||||
/**
|
||||
Creates and returns a new `GroupDetailsViewController` object.
|
||||
|
||||
@discussion This is the designated initializer for programmatic instantiation.
|
||||
@return An initialized `GroupDetailsViewController` object if successful, `nil` otherwise.
|
||||
*/
|
||||
+ (instancetype)groupDetailsViewController;
|
||||
|
||||
/**
|
||||
Set the group for which the details are displayed.
|
||||
Provide the related matrix session.
|
||||
|
||||
@param group
|
||||
@param mxSession
|
||||
*/
|
||||
- (void)setGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession;
|
||||
|
||||
@end
|
||||
|
|
@ -1,206 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations 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 "GroupDetailsViewController.h"
|
||||
|
||||
#import "GroupHomeViewController.h"
|
||||
#import "GroupParticipantsViewController.h"
|
||||
#import "GroupRoomsViewController.h"
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@interface GroupDetailsViewController ()
|
||||
{
|
||||
GroupHomeViewController *groupHomeViewController;
|
||||
GroupParticipantsViewController *groupParticipantsViewController;
|
||||
GroupRoomsViewController *groupRoomsViewController;
|
||||
|
||||
/**
|
||||
mask view while processing a request
|
||||
*/
|
||||
UIActivityIndicatorView * pendingMaskSpinnerView;
|
||||
|
||||
/**
|
||||
Current alert (if any).
|
||||
*/
|
||||
UIAlertController *currentAlert;
|
||||
|
||||
/**
|
||||
The current visibility of the status bar in this view controller.
|
||||
*/
|
||||
BOOL isStatusBarHidden;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation GroupDetailsViewController
|
||||
|
||||
#pragma mark - Class methods
|
||||
|
||||
+ (UINib *)nib
|
||||
{
|
||||
return [UINib nibWithNibName:NSStringFromClass(self.class)
|
||||
bundle:[NSBundle bundleForClass:self.class]];
|
||||
}
|
||||
|
||||
+ (instancetype)groupDetailsViewController
|
||||
{
|
||||
return [[[self class] alloc] initWithNibName:NSStringFromClass(self.class)
|
||||
bundle:[NSBundle bundleForClass:self.class]];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)finalizeInit
|
||||
{
|
||||
[super finalizeInit];
|
||||
|
||||
// Setup `MXKViewControllerHandling` properties
|
||||
self.enableBarTintColorStatusChange = NO;
|
||||
self.rageShakeManager = [RageShakeManager sharedManager];
|
||||
|
||||
self.sectionHeaderTintColor = kRiotColorBlue;
|
||||
|
||||
// Keep visible the status bar by default.
|
||||
isStatusBarHidden = NO;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
NSMutableArray* viewControllers = [[NSMutableArray alloc] init];
|
||||
NSMutableArray* titles = [[NSMutableArray alloc] init];
|
||||
|
||||
// home tab
|
||||
[titles addObject: NSLocalizedStringFromTable(@"group_details_home", @"Vector", nil)];
|
||||
groupHomeViewController = [GroupHomeViewController groupHomeViewController];
|
||||
if (_group)
|
||||
{
|
||||
[groupHomeViewController setGroup:_group withMatrixSession:_mxSession];
|
||||
}
|
||||
[viewControllers addObject:groupHomeViewController];
|
||||
|
||||
// People tab
|
||||
[titles addObject: NSLocalizedStringFromTable(@"group_details_people", @"Vector", nil)];
|
||||
groupParticipantsViewController = [GroupParticipantsViewController groupParticipantsViewController];
|
||||
if (_group)
|
||||
{
|
||||
[groupParticipantsViewController setGroup:_group withMatrixSession:_mxSession];
|
||||
}
|
||||
[viewControllers addObject:groupParticipantsViewController];
|
||||
|
||||
// Rooms tab
|
||||
[titles addObject: NSLocalizedStringFromTable(@"group_details_rooms", @"Vector", nil)];
|
||||
groupRoomsViewController = [GroupRoomsViewController groupRoomsViewController];
|
||||
if (_group)
|
||||
{
|
||||
[groupRoomsViewController setGroup:_group withMatrixSession:_mxSession];
|
||||
}
|
||||
[viewControllers addObject:groupRoomsViewController];
|
||||
|
||||
self.title = NSLocalizedStringFromTable(@"group_details_title", @"Vector", nil);
|
||||
[self initWithTitles:titles viewControllers:viewControllers defaultSelected:0];
|
||||
|
||||
[super viewDidLoad];
|
||||
}
|
||||
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle
|
||||
{
|
||||
return kRiotDesignStatusBarStyle;
|
||||
}
|
||||
|
||||
- (BOOL)prefersStatusBarHidden
|
||||
{
|
||||
// Return the current status bar visibility.
|
||||
return isStatusBarHidden;
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"GroupDetails"];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated
|
||||
{
|
||||
[super viewWillDisappear:animated];
|
||||
|
||||
// Consider the main navigation controller if the current view controller is embedded inside a split view controller.
|
||||
UINavigationController *mainNavigationController = self.navigationController;
|
||||
if (self.splitViewController.isCollapsed && self.splitViewController.viewControllers.count)
|
||||
{
|
||||
mainNavigationController = self.splitViewController.viewControllers.firstObject;
|
||||
}
|
||||
|
||||
if (mainNavigationController.navigationBar.tintColor == kRiotColorBlue)
|
||||
{
|
||||
// Restore default tintColor
|
||||
mainNavigationController.navigationBar.tintColor = kRiotColorGreen;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidLayoutSubviews
|
||||
{
|
||||
[super viewDidLayoutSubviews];
|
||||
|
||||
// Consider the main navigation controller if the current view controller is embedded inside a split view controller.
|
||||
UINavigationController *mainNavigationController = self.navigationController;
|
||||
if (self.splitViewController.isCollapsed && self.splitViewController.viewControllers.count)
|
||||
{
|
||||
mainNavigationController = self.splitViewController.viewControllers.firstObject;
|
||||
}
|
||||
mainNavigationController.navigationBar.tintColor = kRiotColorBlue;
|
||||
}
|
||||
|
||||
- (void)destroy
|
||||
{
|
||||
[super destroy];
|
||||
}
|
||||
|
||||
- (void)setGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession
|
||||
{
|
||||
_group = group;
|
||||
_mxSession = mxSession;
|
||||
|
||||
[self addMatrixSession:mxSession];
|
||||
|
||||
if (groupHomeViewController)
|
||||
{
|
||||
[groupHomeViewController setGroup:group withMatrixSession:mxSession];
|
||||
}
|
||||
if (groupParticipantsViewController)
|
||||
{
|
||||
[groupParticipantsViewController setGroup:group withMatrixSession:mxSession];
|
||||
}
|
||||
if (groupRoomsViewController)
|
||||
{
|
||||
[groupRoomsViewController setGroup:group withMatrixSession:mxSession];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)withdrawViewControllerAnimated:(BOOL)animated completion:(void (^)(void))completion
|
||||
{
|
||||
[super withdrawViewControllerAnimated:animated completion:completion];
|
||||
|
||||
// Fill the secondary navigation view controller of the split view controller if it is empty.
|
||||
UINavigationController *secondaryNavigationController = [AppDelegate theDelegate].secondaryNavigationController;
|
||||
if (secondaryNavigationController && !secondaryNavigationController.viewControllers.count)
|
||||
{
|
||||
[[AppDelegate theDelegate] restoreEmptyDetailsViewController];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,52 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13529"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="SegmentedViewController">
|
||||
<connections>
|
||||
<outlet property="selectionContainer" destination="ynH-uD-aQj" id="taa-CW-XgW"/>
|
||||
<outlet property="selectionContainerHeightConstraint" destination="fZ1-SQ-nxS" id="kQ4-n9-Gmt"/>
|
||||
<outlet property="selectionContainerTopConstraint" destination="eLe-5q-IfV" id="UhZ-9k-P1r"/>
|
||||
<outlet property="view" destination="1TG-Rn-axS" id="WxL-e2-rVK"/>
|
||||
<outlet property="viewControllerContainer" destination="Hbe-uP-aJY" id="mD3-w0-UXi"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="1TG-Rn-axS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="ynH-uD-aQj" userLabel="Selection Container">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="SegmentedVCSelectionContainer"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="44" id="fZ1-SQ-nxS"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Hbe-uP-aJY" userLabel="Selected UITableView Container">
|
||||
<rect key="frame" x="0.0" y="44" width="375" height="623"/>
|
||||
<color key="tintColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="SegmentedVCUITableViewContainer"/>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="SegmentedVCView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="Hbe-uP-aJY" secondAttribute="bottom" id="GHr-ci-L7A"/>
|
||||
<constraint firstItem="Hbe-uP-aJY" firstAttribute="leading" secondItem="ynH-uD-aQj" secondAttribute="leading" id="HTN-hD-pve"/>
|
||||
<constraint firstItem="ynH-uD-aQj" firstAttribute="width" secondItem="1TG-Rn-axS" secondAttribute="width" id="N0o-xo-47p"/>
|
||||
<constraint firstItem="Hbe-uP-aJY" firstAttribute="top" secondItem="ynH-uD-aQj" secondAttribute="bottom" id="Ovm-KQ-gUw"/>
|
||||
<constraint firstItem="Hbe-uP-aJY" firstAttribute="width" secondItem="1TG-Rn-axS" secondAttribute="width" id="YKU-mG-Loo"/>
|
||||
<constraint firstItem="ynH-uD-aQj" firstAttribute="leading" secondItem="1TG-Rn-axS" secondAttribute="leading" id="drw-gq-mYE"/>
|
||||
<constraint firstItem="ynH-uD-aQj" firstAttribute="top" secondItem="1TG-Rn-axS" secondAttribute="top" id="eLe-5q-IfV"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations 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 GroupHomeViewController : MXKViewController <UIGestureRecognizerDelegate>
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIView *mainHeaderContainer;
|
||||
@property (weak, nonatomic) IBOutlet MXKImageView *groupAvatar;
|
||||
@property (weak, nonatomic) IBOutlet UIView *groupAvatarMask;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *groupName;
|
||||
@property (weak, nonatomic) IBOutlet UIView *groupNameMask;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *groupDescription;
|
||||
@property (weak, nonatomic) IBOutlet UIView *countsContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIView *membersCountContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIView *roomsCountContainer;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *membersCountLabel;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *roomsCountLabel;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIView *inviteContainer;
|
||||
@property (weak, nonatomic) IBOutlet UILabel *inviteLabel;
|
||||
@property (weak, nonatomic) IBOutlet UIView *buttonsContainer;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *leftButton;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *rightButton;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIView *separatorView;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *separatorViewTopConstraint;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UITextView *groupLongDescription;
|
||||
|
||||
@property (strong, readonly, nonatomic) MXGroup *group;
|
||||
@property (strong, readonly, nonatomic) MXSession *mxSession;
|
||||
|
||||
/**
|
||||
Returns the `UINib` object initialized for a `GroupHomeViewController`.
|
||||
|
||||
@return The initialized `UINib` object or `nil` if there were errors during initialization
|
||||
or the nib file could not be located.
|
||||
*/
|
||||
+ (UINib *)nib;
|
||||
|
||||
/**
|
||||
Creates and returns a new `GroupHomeViewController` object.
|
||||
|
||||
@discussion This is the designated initializer for programmatic instantiation.
|
||||
@return An initialized `GroupHomeViewController` object if successful, `nil` otherwise.
|
||||
*/
|
||||
+ (instancetype)groupHomeViewController;
|
||||
|
||||
/**
|
||||
Set the group for which the details are displayed.
|
||||
Provide the related matrix session.
|
||||
|
||||
@param group
|
||||
@param mxSession
|
||||
*/
|
||||
- (void)setGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession;
|
||||
|
||||
@end
|
||||
|
|
@ -1,517 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations 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 "GroupHomeViewController.h"
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "RiotDesignValues.h"
|
||||
|
||||
#import "MXGroup+Riot.h"
|
||||
|
||||
@interface GroupHomeViewController ()
|
||||
{
|
||||
MXHTTPOperation *currentRequest;
|
||||
|
||||
/**
|
||||
The current visibility of the status bar in this view controller.
|
||||
*/
|
||||
BOOL isStatusBarHidden;
|
||||
|
||||
// Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change.
|
||||
id kRiotDesignValuesDidChangeThemeNotificationObserver;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation GroupHomeViewController
|
||||
|
||||
#pragma mark - Class methods
|
||||
|
||||
+ (UINib *)nib
|
||||
{
|
||||
return [UINib nibWithNibName:NSStringFromClass(self.class)
|
||||
bundle:[NSBundle bundleForClass:self.class]];
|
||||
}
|
||||
|
||||
+ (instancetype)groupHomeViewController
|
||||
{
|
||||
return [[[self class] alloc] initWithNibName:NSStringFromClass(self.class)
|
||||
bundle:[NSBundle bundleForClass:self.class]];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)finalizeInit
|
||||
{
|
||||
[super finalizeInit];
|
||||
|
||||
// Setup `MXKViewControllerHandling` properties
|
||||
self.enableBarTintColorStatusChange = NO;
|
||||
self.rageShakeManager = [RageShakeManager sharedManager];
|
||||
|
||||
// Keep visible the status bar by default.
|
||||
isStatusBarHidden = NO;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
[self.leftButton setTitle:NSLocalizedStringFromTable(@"decline", @"Vector", nil) forState:UIControlStateNormal];
|
||||
[self.leftButton setTitle:NSLocalizedStringFromTable(@"decline", @"Vector", nil) forState:UIControlStateHighlighted];
|
||||
[self.rightButton setTitle:NSLocalizedStringFromTable(@"join", @"Vector", nil) forState:UIControlStateNormal];
|
||||
[self.rightButton setTitle:NSLocalizedStringFromTable(@"join", @"Vector", nil) forState:UIControlStateHighlighted];
|
||||
|
||||
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
|
||||
[tap setNumberOfTouchesRequired:1];
|
||||
[tap setNumberOfTapsRequired:1];
|
||||
[tap setDelegate:self];
|
||||
[_groupNameMask addGestureRecognizer:tap];
|
||||
_groupNameMask.userInteractionEnabled = YES;
|
||||
|
||||
// Add tap to show the group avatar in fullscreen
|
||||
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
|
||||
[tap setNumberOfTouchesRequired:1];
|
||||
[tap setNumberOfTapsRequired:1];
|
||||
[tap setDelegate:self];
|
||||
[_groupAvatarMask addGestureRecognizer:tap];
|
||||
_groupAvatarMask.userInteractionEnabled = YES;
|
||||
|
||||
// Observe user interface theme change.
|
||||
kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
|
||||
|
||||
[self userInterfaceThemeDidChange];
|
||||
|
||||
}];
|
||||
[self userInterfaceThemeDidChange];
|
||||
}
|
||||
|
||||
- (void)userInterfaceThemeDidChange
|
||||
{
|
||||
self.defaultBarTintColor = kRiotSecondaryBgColor;
|
||||
self.barTitleColor = kRiotPrimaryTextColor;
|
||||
self.activityIndicator.backgroundColor = kRiotOverlayColor;
|
||||
|
||||
self.view.backgroundColor = kRiotPrimaryBgColor;
|
||||
self.mainHeaderContainer.backgroundColor = kRiotSecondaryBgColor;
|
||||
|
||||
_groupName.textColor = kRiotPrimaryTextColor;
|
||||
|
||||
_groupDescription.textColor = kRiotTopicTextColor;
|
||||
_groupDescription.numberOfLines = 0;
|
||||
|
||||
self.inviteLabel.textColor = kRiotTopicTextColor;
|
||||
self.inviteLabel.numberOfLines = 0;
|
||||
|
||||
self.separatorView.backgroundColor = kRiotSecondaryBgColor;
|
||||
|
||||
_groupLongDescription.textColor = kRiotSecondaryTextColor;
|
||||
_groupLongDescription.tintColor = kRiotColorBlue;
|
||||
|
||||
[self.leftButton.layer setCornerRadius:5];
|
||||
self.leftButton.clipsToBounds = YES;
|
||||
self.leftButton.backgroundColor = kRiotColorBlue;
|
||||
|
||||
[self.rightButton.layer setCornerRadius:5];
|
||||
self.rightButton.clipsToBounds = YES;
|
||||
self.rightButton.backgroundColor = kRiotColorBlue;
|
||||
}
|
||||
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle
|
||||
{
|
||||
return kRiotDesignStatusBarStyle;
|
||||
}
|
||||
|
||||
- (BOOL)prefersStatusBarHidden
|
||||
{
|
||||
// Return the current status bar visibility.
|
||||
return isStatusBarHidden;
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"GroupDetailsHome"];
|
||||
|
||||
if (_group)
|
||||
{
|
||||
// Restore the listeners on the group update.
|
||||
[self registerOnGroupChangeNotifications];
|
||||
|
||||
// Check whether the selected group is stored in the user's session, or if it is a group preview.
|
||||
// Replace the displayed group instance with the one stored in the session (if any).
|
||||
MXGroup *storedGroup = [_mxSession groupWithGroupId:_group.groupId];
|
||||
BOOL isPreview = (!storedGroup);
|
||||
|
||||
// Force refresh
|
||||
[self refreshDisplayWithGroup:(isPreview ? _group : storedGroup)];
|
||||
|
||||
// Prepare a block called on successful update in case of a group preview.
|
||||
// Indeed the group update notifications are triggered by the matrix session only for the user's groups.
|
||||
void (^success)(void) = ^void(void)
|
||||
{
|
||||
[self refreshDisplayWithGroup:_group];
|
||||
};
|
||||
|
||||
// Trigger a refresh on the group summary.
|
||||
[self.mxSession updateGroupSummary:_group success:(isPreview ? success : nil) failure:^(NSError *error) {
|
||||
|
||||
NSLog(@"[GroupHomeViewController] viewWillAppear: group summary update failed %@", _group.groupId);
|
||||
|
||||
}];
|
||||
// Trigger a refresh on the group members (ignore here the invited users).
|
||||
[self.mxSession updateGroupUsers:_group success:(isPreview ? success : nil) failure:^(NSError *error) {
|
||||
|
||||
NSLog(@"[GroupHomeViewController] viewWillAppear: group members update failed %@", _group.groupId);
|
||||
|
||||
}];
|
||||
// Trigger a refresh on the group rooms.
|
||||
[self.mxSession updateGroupRooms:_group success:(isPreview ? success : nil) failure:^(NSError *error) {
|
||||
|
||||
NSLog(@"[GroupHomeViewController] viewWillAppear: group rooms update failed %@", _group.groupId);
|
||||
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated
|
||||
{
|
||||
[super viewWillDisappear:animated];
|
||||
|
||||
[self cancelRegistrationOnGroupChangeNotifications];
|
||||
}
|
||||
|
||||
- (void)destroy
|
||||
{
|
||||
// Note: all observers are removed during super call.
|
||||
[super destroy];
|
||||
|
||||
_group = nil;
|
||||
_mxSession = nil;
|
||||
|
||||
[currentRequest cancel];
|
||||
currentRequest = nil;
|
||||
|
||||
if (kRiotDesignValuesDidChangeThemeNotificationObserver)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver];
|
||||
kRiotDesignValuesDidChangeThemeNotificationObserver = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession
|
||||
{
|
||||
if (_mxSession != mxSession)
|
||||
{
|
||||
[self cancelRegistrationOnGroupChangeNotifications];
|
||||
_mxSession = mxSession;
|
||||
|
||||
[self registerOnGroupChangeNotifications];
|
||||
}
|
||||
|
||||
[self addMatrixSession:mxSession];
|
||||
|
||||
[self refreshDisplayWithGroup:group];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)registerOnGroupChangeNotifications
|
||||
{
|
||||
if (_mxSession)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didUpdateGroupDetails:) name:kMXSessionDidUpdateGroupSummaryNotification object:_mxSession];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didUpdateGroupDetails:) name:kMXSessionDidUpdateGroupUsersNotification object:_mxSession];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didUpdateGroupDetails:) name:kMXSessionDidUpdateGroupRoomsNotification object:_mxSession];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cancelRegistrationOnGroupChangeNotifications
|
||||
{
|
||||
// Remove any pending observers
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionDidUpdateGroupSummaryNotification object:_mxSession];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionDidUpdateGroupUsersNotification object:_mxSession];
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionDidUpdateGroupRoomsNotification object:_mxSession];
|
||||
}
|
||||
|
||||
- (void)didUpdateGroupDetails:(NSNotification *)notif
|
||||
{
|
||||
MXGroup *group = notif.userInfo[kMXSessionNotificationGroupKey];
|
||||
if (group && [group.groupId isEqualToString:_group.groupId])
|
||||
{
|
||||
// Update the current displayed group instance with the one stored in the session
|
||||
[self refreshDisplayWithGroup:group];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)refreshDisplayWithGroup:(MXGroup*)group
|
||||
{
|
||||
_group = group;
|
||||
|
||||
if (_group)
|
||||
{
|
||||
[_group setGroupAvatarImageIn:_groupAvatar matrixSession:self.mxSession];
|
||||
|
||||
_groupName.text = _group.summary.profile.name;
|
||||
if (!_groupName.text.length)
|
||||
{
|
||||
_groupName.text = _group.groupId;
|
||||
}
|
||||
|
||||
_groupDescription.text = _group.summary.profile.shortDescription;
|
||||
|
||||
if (_group.users.totalUserCountEstimate == 1)
|
||||
{
|
||||
_membersCountLabel.text = NSLocalizedStringFromTable(@"group_home_one_member_format", @"Vector", nil);
|
||||
_membersCountContainer.hidden = NO;
|
||||
}
|
||||
else if (_group.users.totalUserCountEstimate > 1)
|
||||
{
|
||||
_membersCountLabel.text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"group_home_multi_members_format", @"Vector", nil), _group.users.totalUserCountEstimate];
|
||||
_membersCountContainer.hidden = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
_membersCountLabel.text = nil;
|
||||
_membersCountContainer.hidden = YES;
|
||||
}
|
||||
|
||||
if (_group.rooms.totalRoomCountEstimate == 1)
|
||||
{
|
||||
_roomsCountLabel.text = NSLocalizedStringFromTable(@"group_home_one_room_format", @"Vector", nil);
|
||||
_roomsCountContainer.hidden = NO;
|
||||
}
|
||||
else if (_group.rooms.totalRoomCountEstimate > 1)
|
||||
{
|
||||
_roomsCountLabel.text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"group_home_multi_rooms_format", @"Vector", nil), _group.rooms.totalRoomCountEstimate];
|
||||
_roomsCountContainer.hidden = NO;
|
||||
}
|
||||
else
|
||||
{
|
||||
_roomsCountLabel.text = nil;
|
||||
_roomsCountContainer.hidden = YES;
|
||||
}
|
||||
|
||||
_countsContainer.hidden = (_membersCountContainer.isHidden && _roomsCountContainer.isHidden);
|
||||
|
||||
if (_group.membership == MXMembershipInvite)
|
||||
{
|
||||
self.inviteContainer.hidden = NO;
|
||||
|
||||
if (_group.inviter)
|
||||
{
|
||||
NSString *inviter = _group.inviter;
|
||||
|
||||
if ([MXTools isMatrixUserIdentifier:inviter])
|
||||
{
|
||||
// Get the user that corresponds to this member
|
||||
MXUser *user = [self.mxSession userWithUserId:inviter];
|
||||
if (user.displayname.length)
|
||||
{
|
||||
inviter = user.displayname;
|
||||
}
|
||||
}
|
||||
|
||||
self.inviteLabel.text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"group_invitation_format", @"Vector", nil), inviter];
|
||||
}
|
||||
else
|
||||
{
|
||||
self.inviteLabel.text = nil;
|
||||
}
|
||||
|
||||
[self.inviteContainer layoutIfNeeded];
|
||||
|
||||
if (_separatorViewTopConstraint.constant != self.inviteContainer.frame.size.height)
|
||||
{
|
||||
_separatorViewTopConstraint.constant = self.inviteContainer.frame.size.height;
|
||||
[self.view layoutIfNeeded];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
self.inviteContainer.hidden = YES;
|
||||
if (_separatorViewTopConstraint.constant != 0)
|
||||
{
|
||||
_separatorViewTopConstraint.constant = 0;
|
||||
[self.view layoutIfNeeded];
|
||||
}
|
||||
}
|
||||
|
||||
if (_group.summary.profile.longDescription.length)
|
||||
{
|
||||
//@TODO: implement a specific html renderer to support h1/h2 and handle the Matrix media content URI (in the form of "mxc://...").
|
||||
MXKEventFormatter *eventFormatter = [[MXKEventFormatter alloc] initWithMatrixSession:self.mxSession];
|
||||
_groupLongDescription.attributedText = [eventFormatter renderHTMLString:_group.summary.profile.longDescription forEvent:nil];
|
||||
_groupLongDescription.contentOffset = CGPointZero;
|
||||
}
|
||||
else
|
||||
{
|
||||
_groupLongDescription.text = nil;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_groupAvatar.image = nil;
|
||||
|
||||
_groupName.text = nil;
|
||||
_groupDescription.text = nil;
|
||||
|
||||
self.inviteLabel.text = nil;
|
||||
_groupLongDescription.text = nil;
|
||||
|
||||
self.inviteContainer.hidden = YES;
|
||||
|
||||
_groupLongDescription.text = nil;
|
||||
_separatorViewTopConstraint.constant = 0;
|
||||
|
||||
_membersCountLabel.text = nil;
|
||||
_roomsCountLabel.text = nil;
|
||||
_countsContainer.hidden = YES;
|
||||
}
|
||||
|
||||
// Round image view for thumbnail
|
||||
_groupAvatar.layer.cornerRadius = _groupAvatar.frame.size.width / 2;
|
||||
_groupAvatar.clipsToBounds = YES;
|
||||
|
||||
_groupAvatar.defaultBackgroundColor = kRiotSecondaryBgColor;
|
||||
}
|
||||
|
||||
#pragma mark - Action
|
||||
|
||||
- (IBAction)onButtonPressed:(id)sender
|
||||
{
|
||||
if (!currentRequest)
|
||||
{
|
||||
if (sender == self.rightButton)
|
||||
{
|
||||
// Accept the invite
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[self startActivityIndicator];
|
||||
|
||||
currentRequest = [self.mxSession acceptGroupInvite:_group.groupId success:^{
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentRequest = nil;
|
||||
[self stopActivityIndicator];
|
||||
|
||||
[self refreshDisplayWithGroup:[_mxSession groupWithGroupId:_group.groupId]];
|
||||
}
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
NSLog(@"[GroupDetailsViewController] join group (%@) failed", _group.groupId);
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentRequest = nil;
|
||||
[self stopActivityIndicator];
|
||||
}
|
||||
|
||||
// Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
}];
|
||||
}
|
||||
else if (sender == self.leftButton)
|
||||
{
|
||||
// Decline the invite
|
||||
__weak typeof(self) weakSelf = self;
|
||||
[self startActivityIndicator];
|
||||
|
||||
currentRequest = [self.mxSession leaveGroup:_group.groupId success:^{
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentRequest = nil;
|
||||
[self stopActivityIndicator];
|
||||
|
||||
[self withdrawViewControllerAnimated:YES completion:nil];
|
||||
}
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
NSLog(@"[GroupDetailsViewController] leave group (%@) failed", _group.groupId);
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentRequest = nil;
|
||||
[self stopActivityIndicator];
|
||||
}
|
||||
|
||||
// Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
}];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleTapGesture:(UITapGestureRecognizer*)tapGestureRecognizer
|
||||
{
|
||||
UIView *view = tapGestureRecognizer.view;
|
||||
|
||||
if (view == _groupNameMask && _group.summary.profile.name)
|
||||
{
|
||||
if ([_groupName.text isEqualToString:_group.summary.profile.name])
|
||||
{
|
||||
// Display group's matrix id
|
||||
_groupName.text = _group.groupId;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Restore display name
|
||||
_groupName.text = _group.summary.profile.name;
|
||||
}
|
||||
}
|
||||
else if (view == _groupAvatarMask)
|
||||
{
|
||||
// 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;
|
||||
|
||||
isStatusBarHidden = NO;
|
||||
// Trigger status bar update
|
||||
[self setNeedsStatusBarAppearanceUpdate];
|
||||
}];
|
||||
|
||||
NSString *avatarURL = [self.mainSession.matrixRestClient urlOfContent:_group.summary.profile.avatarUrl];
|
||||
[avatarFullScreenView setImageURL:avatarURL
|
||||
withType:nil
|
||||
andImageOrientation:UIImageOrientationUp
|
||||
previewImage:self.groupAvatar.image];
|
||||
|
||||
[avatarFullScreenView showFullScreen];
|
||||
isStatusBarHidden = YES;
|
||||
|
||||
// Trigger status bar update
|
||||
[self setNeedsStatusBarAppearanceUpdate];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,282 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
||||
<capability name="Aspect ratio constraints" minToolsVersion="5.1"/>
|
||||
<capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="GroupHomeViewController">
|
||||
<connections>
|
||||
<outlet property="buttonsContainer" destination="EqU-yd-Ntb" id="SpC-UD-z6O"/>
|
||||
<outlet property="countsContainer" destination="hkg-GN-Tej" id="cWs-i0-bVQ"/>
|
||||
<outlet property="groupAvatar" destination="ehl-88-DfA" id="bKF-ij-hsH"/>
|
||||
<outlet property="groupAvatarMask" destination="kYc-LP-Nip" id="u4M-Yf-wQy"/>
|
||||
<outlet property="groupDescription" destination="jXh-2B-Bso" id="daH-OS-1BL"/>
|
||||
<outlet property="groupLongDescription" destination="oUL-bJ-tfM" id="ZA0-1e-RrG"/>
|
||||
<outlet property="groupName" destination="5UX-lR-Ac5" id="kzg-n6-ZXM"/>
|
||||
<outlet property="groupNameMask" destination="mKE-ro-fuy" id="0DZ-3m-LNx"/>
|
||||
<outlet property="inviteContainer" destination="nR4-eE-qJo" id="rsc-Gd-rLL"/>
|
||||
<outlet property="inviteLabel" destination="UHk-6Y-MSO" id="JO0-8a-h78"/>
|
||||
<outlet property="leftButton" destination="jTB-nL-KcP" id="iPW-qf-LbT"/>
|
||||
<outlet property="mainHeaderContainer" destination="AKb-7n-nhQ" id="RUh-ZE-ul2"/>
|
||||
<outlet property="membersCountContainer" destination="PgZ-iJ-yNZ" id="YKC-dF-QOE"/>
|
||||
<outlet property="membersCountLabel" destination="qJ8-8X-Xzm" id="LRd-io-EFg"/>
|
||||
<outlet property="rightButton" destination="xfk-oh-9db" id="JGC-zW-2vD"/>
|
||||
<outlet property="roomsCountContainer" destination="xkH-zg-3jY" id="xo8-mh-emk"/>
|
||||
<outlet property="roomsCountLabel" destination="XuG-pe-Lzn" id="Bbg-xa-lxp"/>
|
||||
<outlet property="separatorView" destination="dlP-kX-cll" id="TMm-OR-eFJ"/>
|
||||
<outlet property="separatorViewTopConstraint" destination="tSb-HY-8nq" id="jM0-gg-k1g"/>
|
||||
<outlet property="view" destination="1TG-Rn-axS" id="WxL-e2-rVK"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="1TG-Rn-axS">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="AKb-7n-nhQ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="106.5"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kYc-LP-Nip">
|
||||
<rect key="frame" x="8" y="5" width="80" height="80"/>
|
||||
<subviews>
|
||||
<view clipsSubviews="YES" contentMode="scaleAspectFill" translatesAutoresizingMaskIntoConstraints="NO" id="ehl-88-DfA" customClass="MXKImageView">
|
||||
<rect key="frame" x="10" y="10" width="60" height="60"/>
|
||||
<color key="backgroundColor" red="0.6886889638" green="1" blue="0.74383144840000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="MemberAvatar"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="ehl-88-DfA" secondAttribute="height" multiplier="1:1" id="KSI-3d-yr8"/>
|
||||
<constraint firstAttribute="width" constant="60" id="RFO-L1-XfN"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="ContactDetailsVCAvatarMask"/>
|
||||
<constraints>
|
||||
<constraint firstItem="ehl-88-DfA" firstAttribute="centerY" secondItem="kYc-LP-Nip" secondAttribute="centerY" id="120-Fe-9lk"/>
|
||||
<constraint firstAttribute="width" secondItem="kYc-LP-Nip" secondAttribute="height" multiplier="1:1" id="HNr-XL-fXe"/>
|
||||
<constraint firstItem="ehl-88-DfA" firstAttribute="centerX" secondItem="kYc-LP-Nip" secondAttribute="centerX" id="LMN-31-ZCn"/>
|
||||
<constraint firstAttribute="width" constant="80" id="zV6-TZ-Oan"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="5UX-lR-Ac5">
|
||||
<rect key="frame" x="92" y="18" width="43.5" height="20.5"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleHeadline"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="jXh-2B-Bso">
|
||||
<rect key="frame" x="92" y="44.5" width="37.5" height="18"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="RoomTopic"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleSubhead"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="mKE-ro-fuy">
|
||||
<rect key="frame" x="87" y="15" width="53.5" height="25.5"/>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="ContactDetailsVCNameLabelMask"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="hkg-GN-Tej">
|
||||
<rect key="frame" x="88" y="78.5" width="279" height="20"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="PgZ-iJ-yNZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="86.5" height="20"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="tab_groups_selected.png" translatesAutoresizingMaskIntoConstraints="NO" id="YI6-IK-PkI">
|
||||
<rect key="frame" x="4" y="2.5" width="15" height="15"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" secondItem="YI6-IK-PkI" secondAttribute="height" multiplier="1:1" id="azu-dv-Abo"/>
|
||||
<constraint firstAttribute="width" constant="15" id="zka-UU-93t"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="2 members" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qJ8-8X-Xzm">
|
||||
<rect key="frame" x="23" y="3.5" width="63.5" height="14"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" secondItem="qJ8-8X-Xzm" secondAttribute="height" constant="6" id="Aao-5S-pox"/>
|
||||
<constraint firstItem="qJ8-8X-Xzm" firstAttribute="leading" secondItem="YI6-IK-PkI" secondAttribute="trailing" constant="4" id="NOr-CS-0zv"/>
|
||||
<constraint firstAttribute="trailing" secondItem="qJ8-8X-Xzm" secondAttribute="trailing" id="ZwB-qD-I8A"/>
|
||||
<constraint firstItem="YI6-IK-PkI" firstAttribute="leading" secondItem="PgZ-iJ-yNZ" secondAttribute="leading" constant="4" id="bkS-hZ-KQv"/>
|
||||
<constraint firstItem="qJ8-8X-Xzm" firstAttribute="centerY" secondItem="PgZ-iJ-yNZ" secondAttribute="centerY" id="jdb-bW-4Oy"/>
|
||||
<constraint firstItem="YI6-IK-PkI" firstAttribute="centerY" secondItem="PgZ-iJ-yNZ" secondAttribute="centerY" id="vCJ-Yz-2eu"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="xkH-zg-3jY">
|
||||
<rect key="frame" x="94.5" y="0.0" width="68" height="20"/>
|
||||
<subviews>
|
||||
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="tab_rooms.png" translatesAutoresizingMaskIntoConstraints="NO" id="aZ9-Gu-utv">
|
||||
<rect key="frame" x="4" y="2.5" width="15" height="15"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="15" id="3df-1e-XMS"/>
|
||||
<constraint firstAttribute="width" secondItem="aZ9-Gu-utv" secondAttribute="height" multiplier="1:1" id="hnv-qQ-D9X"/>
|
||||
</constraints>
|
||||
</imageView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="2 rooms" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="XuG-pe-Lzn">
|
||||
<rect key="frame" x="22" y="3.5" width="46" height="14.5"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleCaption1"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="XuG-pe-Lzn" secondAttribute="trailing" id="021-fG-7GQ"/>
|
||||
<constraint firstItem="XuG-pe-Lzn" firstAttribute="leading" secondItem="aZ9-Gu-utv" secondAttribute="trailing" constant="3" id="3p6-oX-xHD"/>
|
||||
<constraint firstItem="XuG-pe-Lzn" firstAttribute="centerY" secondItem="xkH-zg-3jY" secondAttribute="centerY" id="GvC-ox-7fH"/>
|
||||
<constraint firstItem="aZ9-Gu-utv" firstAttribute="leading" secondItem="xkH-zg-3jY" secondAttribute="leading" constant="4" id="bbe-FJ-udn"/>
|
||||
<constraint firstItem="aZ9-Gu-utv" firstAttribute="centerY" secondItem="xkH-zg-3jY" secondAttribute="centerY" id="fwX-jo-52x"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="PgZ-iJ-yNZ" firstAttribute="leading" secondItem="hkg-GN-Tej" secondAttribute="leading" id="1Hr-5B-w2S"/>
|
||||
<constraint firstItem="PgZ-iJ-yNZ" firstAttribute="width" relation="lessThanOrEqual" secondItem="hkg-GN-Tej" secondAttribute="width" multiplier="0.5" id="1pU-62-CzD"/>
|
||||
<constraint firstItem="xkH-zg-3jY" firstAttribute="top" secondItem="hkg-GN-Tej" secondAttribute="top" id="46J-yD-cKS"/>
|
||||
<constraint firstAttribute="height" secondItem="PgZ-iJ-yNZ" secondAttribute="height" id="5AD-Zs-aXU"/>
|
||||
<constraint firstItem="xkH-zg-3jY" firstAttribute="leading" secondItem="PgZ-iJ-yNZ" secondAttribute="trailing" constant="8" id="Cds-AK-yuk"/>
|
||||
<constraint firstItem="xkH-zg-3jY" firstAttribute="width" relation="lessThanOrEqual" secondItem="hkg-GN-Tej" secondAttribute="width" multiplier="0.5" id="Jjt-EP-UFP"/>
|
||||
<constraint firstItem="xkH-zg-3jY" firstAttribute="height" secondItem="PgZ-iJ-yNZ" secondAttribute="height" id="JkC-AN-RWn"/>
|
||||
<constraint firstItem="PgZ-iJ-yNZ" firstAttribute="top" secondItem="hkg-GN-Tej" secondAttribute="top" id="ZyS-oe-dDv"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="xkH-zg-3jY" secondAttribute="trailing" id="aLt-Y9-7ZP"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="bottom" secondItem="hkg-GN-Tej" secondAttribute="bottom" constant="8" id="04P-82-XhO"/>
|
||||
<constraint firstItem="hkg-GN-Tej" firstAttribute="top" secondItem="jXh-2B-Bso" secondAttribute="bottom" constant="16" id="FVO-09-Pc5"/>
|
||||
<constraint firstItem="5UX-lR-Ac5" firstAttribute="top" secondItem="AKb-7n-nhQ" secondAttribute="top" constant="18" id="FlH-ol-0TP"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="kYc-LP-Nip" secondAttribute="bottom" priority="750" constant="10" id="G39-KZ-VFJ"/>
|
||||
<constraint firstItem="mKE-ro-fuy" firstAttribute="centerX" secondItem="5UX-lR-Ac5" secondAttribute="centerX" id="G8w-Th-eCj"/>
|
||||
<constraint firstItem="kYc-LP-Nip" firstAttribute="top" secondItem="AKb-7n-nhQ" secondAttribute="top" constant="5" id="IJD-FB-fWm"/>
|
||||
<constraint firstItem="jXh-2B-Bso" firstAttribute="leading" secondItem="kYc-LP-Nip" secondAttribute="trailing" constant="4" id="Ot2-58-G82"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="jXh-2B-Bso" secondAttribute="trailing" constant="8" id="QeR-3r-KrK"/>
|
||||
<constraint firstAttribute="trailing" secondItem="hkg-GN-Tej" secondAttribute="trailing" constant="8" id="RHn-bj-Dld"/>
|
||||
<constraint firstItem="kYc-LP-Nip" firstAttribute="leading" secondItem="AKb-7n-nhQ" secondAttribute="leading" constant="8" id="Y6V-cp-eRq"/>
|
||||
<constraint firstItem="hkg-GN-Tej" firstAttribute="leading" secondItem="kYc-LP-Nip" secondAttribute="trailing" id="Z8J-Tk-BGi"/>
|
||||
<constraint firstItem="5UX-lR-Ac5" firstAttribute="leading" secondItem="kYc-LP-Nip" secondAttribute="trailing" constant="4" id="fxX-Ak-zfG"/>
|
||||
<constraint firstItem="mKE-ro-fuy" firstAttribute="height" secondItem="5UX-lR-Ac5" secondAttribute="height" constant="5" id="jtN-q7-iqn"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="5UX-lR-Ac5" secondAttribute="trailing" constant="8" id="k8p-VY-5zr"/>
|
||||
<constraint firstItem="mKE-ro-fuy" firstAttribute="centerY" secondItem="5UX-lR-Ac5" secondAttribute="centerY" id="nzz-nn-a5u"/>
|
||||
<constraint firstItem="mKE-ro-fuy" firstAttribute="width" secondItem="5UX-lR-Ac5" secondAttribute="width" constant="10" id="o6d-6K-UUD"/>
|
||||
<constraint firstItem="jXh-2B-Bso" firstAttribute="top" secondItem="mKE-ro-fuy" secondAttribute="bottom" constant="4" id="wyz-Qr-ka3"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nR4-eE-qJo">
|
||||
<rect key="frame" x="0.0" y="106.5" width="375" height="105.5"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="UHk-6Y-MSO">
|
||||
<rect key="frame" x="167" y="15" width="42" height="20.5"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="PreviewLabel"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="EqU-yd-Ntb" userLabel="buttonsContainer">
|
||||
<rect key="frame" x="30" y="55.5" width="315" height="30"/>
|
||||
<subviews>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="jTB-nL-KcP" userLabel="Left Button">
|
||||
<rect key="frame" x="0.0" y="0.0" width="151" height="30"/>
|
||||
<color key="backgroundColor" red="0.6886889638" green="1" blue="0.74383144840000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="LeftButton"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="16"/>
|
||||
<state key="normal" title="Left button">
|
||||
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="onButtonPressed:" destination="-1" eventType="touchUpInside" id="gNs-ys-XsX"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xfk-oh-9db" userLabel="Right Button">
|
||||
<rect key="frame" x="164" y="0.0" width="151" height="30"/>
|
||||
<color key="backgroundColor" red="0.6886889638" green="1" blue="0.74383144840000004" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="RightButton"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="16"/>
|
||||
<state key="normal" title="Right Button">
|
||||
<color key="titleColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="onButtonPressed:" destination="-1" eventType="touchUpInside" id="88I-7i-Arx"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="xfk-oh-9db" firstAttribute="height" secondItem="EqU-yd-Ntb" secondAttribute="height" id="HRj-9b-sf9"/>
|
||||
<constraint firstItem="xfk-oh-9db" firstAttribute="width" secondItem="EqU-yd-Ntb" secondAttribute="width" multiplier="0.48" id="JXG-Qy-PTf"/>
|
||||
<constraint firstAttribute="trailing" secondItem="xfk-oh-9db" secondAttribute="trailing" id="KnR-27-pqz"/>
|
||||
<constraint firstItem="jTB-nL-KcP" firstAttribute="top" secondItem="EqU-yd-Ntb" secondAttribute="top" id="SvJ-kv-poF"/>
|
||||
<constraint firstItem="xfk-oh-9db" firstAttribute="top" secondItem="EqU-yd-Ntb" secondAttribute="top" id="WI3-b5-AgB"/>
|
||||
<constraint firstAttribute="height" constant="30" id="ZZd-YY-Gd2"/>
|
||||
<constraint firstItem="jTB-nL-KcP" firstAttribute="height" secondItem="EqU-yd-Ntb" secondAttribute="height" id="fxc-lx-cMI"/>
|
||||
<constraint firstItem="jTB-nL-KcP" firstAttribute="leading" secondItem="EqU-yd-Ntb" secondAttribute="leading" id="gQS-yN-cek"/>
|
||||
<constraint firstItem="jTB-nL-KcP" firstAttribute="width" secondItem="EqU-yd-Ntb" secondAttribute="width" multiplier="0.48" id="qmv-b5-hHq"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<constraints>
|
||||
<constraint firstItem="EqU-yd-Ntb" firstAttribute="leading" secondItem="nR4-eE-qJo" secondAttribute="leading" constant="30" id="0A0-CA-Han"/>
|
||||
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="UHk-6Y-MSO" secondAttribute="trailing" constant="31" id="1AA-2G-22p"/>
|
||||
<constraint firstItem="EqU-yd-Ntb" firstAttribute="top" secondItem="UHk-6Y-MSO" secondAttribute="bottom" constant="20" id="T4l-2m-fsZ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="EqU-yd-Ntb" secondAttribute="trailing" constant="30" id="cCk-lA-SDz"/>
|
||||
<constraint firstItem="UHk-6Y-MSO" firstAttribute="centerX" secondItem="nR4-eE-qJo" secondAttribute="centerX" id="dlW-cX-D6T"/>
|
||||
<constraint firstItem="UHk-6Y-MSO" firstAttribute="top" secondItem="nR4-eE-qJo" secondAttribute="top" constant="15" id="oNr-AR-g3d"/>
|
||||
<constraint firstItem="UHk-6Y-MSO" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="nR4-eE-qJo" secondAttribute="leading" constant="31" id="r7D-qk-LEG"/>
|
||||
<constraint firstAttribute="bottom" secondItem="EqU-yd-Ntb" secondAttribute="bottom" constant="20" id="zlf-mL-iWH"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dlP-kX-cll">
|
||||
<rect key="frame" x="0.0" y="204.5" width="375" height="1"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="BottomBorderView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="1" id="tUj-3s-NIW"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" adjustsFontForContentSizeCategory="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oUL-bJ-tfM">
|
||||
<rect key="frame" x="8" y="205.5" width="359" height="453.5"/>
|
||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||
<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" style="UICTFontTextStyleBody"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
<dataDetectorType key="dataDetectorTypes" link="YES"/>
|
||||
</textView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="SegmentedVCView"/>
|
||||
<constraints>
|
||||
<constraint firstItem="AKb-7n-nhQ" firstAttribute="top" secondItem="1TG-Rn-axS" secondAttribute="top" id="3NU-eX-o9z"/>
|
||||
<constraint firstAttribute="trailing" secondItem="oUL-bJ-tfM" secondAttribute="trailing" constant="8" id="4G6-iX-BjR"/>
|
||||
<constraint firstAttribute="bottom" secondItem="oUL-bJ-tfM" secondAttribute="bottom" constant="8" id="Cfg-1K-EMs"/>
|
||||
<constraint firstItem="AKb-7n-nhQ" firstAttribute="leading" secondItem="1TG-Rn-axS" secondAttribute="leading" id="O32-n9-j7o"/>
|
||||
<constraint firstItem="nR4-eE-qJo" firstAttribute="leading" secondItem="1TG-Rn-axS" secondAttribute="leading" id="QRs-15-AIO"/>
|
||||
<constraint firstItem="oUL-bJ-tfM" firstAttribute="leading" secondItem="1TG-Rn-axS" secondAttribute="leading" constant="8" id="bG6-iY-kCj"/>
|
||||
<constraint firstItem="nR4-eE-qJo" firstAttribute="top" secondItem="AKb-7n-nhQ" secondAttribute="bottom" id="e0J-TS-0Z2"/>
|
||||
<constraint firstAttribute="trailing" secondItem="AKb-7n-nhQ" secondAttribute="trailing" id="jEv-Pg-vBb"/>
|
||||
<constraint firstAttribute="trailing" secondItem="nR4-eE-qJo" secondAttribute="trailing" id="kB6-fy-TZ7"/>
|
||||
<constraint firstItem="dlP-kX-cll" firstAttribute="leading" secondItem="1TG-Rn-axS" secondAttribute="leading" id="p9g-6c-wFe"/>
|
||||
<constraint firstAttribute="trailing" secondItem="dlP-kX-cll" secondAttribute="trailing" id="qdC-Jn-j6W"/>
|
||||
<constraint firstItem="oUL-bJ-tfM" firstAttribute="top" secondItem="dlP-kX-cll" secondAttribute="bottom" id="qoC-BS-r0k"/>
|
||||
<constraint firstItem="dlP-kX-cll" firstAttribute="top" secondItem="AKb-7n-nhQ" secondAttribute="bottom" constant="98" id="tSb-HY-8nq"/>
|
||||
</constraints>
|
||||
<point key="canvasLocation" x="26.5" y="51.5"/>
|
||||
</view>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="tab_groups_selected.png" width="25" height="25"/>
|
||||
<image name="tab_rooms.png" width="25" height="25"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -1,85 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations 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 "ContactsTableViewController.h"
|
||||
|
||||
@class Contact;
|
||||
|
||||
/**
|
||||
'GroupParticipantsViewController' instance is used to list members of the group defined by the property 'mxGroup'.
|
||||
When this property is nil, the view controller is empty.
|
||||
*/
|
||||
@interface GroupParticipantsViewController : MXKViewController <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate, UIGestureRecognizerDelegate, ContactsTableViewControllerDelegate>
|
||||
{
|
||||
@protected
|
||||
/**
|
||||
Section indexes
|
||||
*/
|
||||
NSInteger participantsSection;
|
||||
NSInteger invitedSection;
|
||||
|
||||
/**
|
||||
The current list of joined members.
|
||||
*/
|
||||
NSMutableArray<Contact*> *actualParticipants;
|
||||
|
||||
/**
|
||||
The current list of invited members.
|
||||
*/
|
||||
NSMutableArray<Contact*> *invitedParticipants;
|
||||
}
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UITableView *tableView;
|
||||
@property (weak, nonatomic) IBOutlet UIView *searchBarHeader;
|
||||
@property (weak, nonatomic) IBOutlet UISearchBar *searchBarView;
|
||||
@property (weak, nonatomic) IBOutlet UIView *searchBarHeaderBorder;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *searchBarTopConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *tableViewBottomConstraint;
|
||||
|
||||
/**
|
||||
A matrix group (nil by default).
|
||||
*/
|
||||
@property (strong, readonly, nonatomic) MXGroup *group;
|
||||
@property (strong, readonly, nonatomic) MXSession *mxSession;
|
||||
|
||||
/**
|
||||
Returns the `UINib` object initialized for a `GroupParticipantsViewController`.
|
||||
|
||||
@return The initialized `UINib` object or `nil` if there were errors during initialization
|
||||
or the nib file could not be located.
|
||||
*/
|
||||
+ (UINib *)nib;
|
||||
|
||||
/**
|
||||
Creates and returns a new `GroupParticipantsViewController` object.
|
||||
|
||||
@discussion This is the designated initializer for programmatic instantiation.
|
||||
@return An initialized `GroupParticipantsViewController` object if successful, `nil` otherwise.
|
||||
*/
|
||||
+ (instancetype)groupParticipantsViewController;
|
||||
|
||||
/**
|
||||
Set the group for which the details are displayed.
|
||||
Provide the related matrix session.
|
||||
|
||||
@param group
|
||||
@param mxSession
|
||||
*/
|
||||
- (void)setGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession;
|
||||
|
||||
@end
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1,87 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13527"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="GroupParticipantsViewController">
|
||||
<connections>
|
||||
<outlet property="searchBarHeader" destination="Zm7-AB-ZtE" id="6ee-P0-twi"/>
|
||||
<outlet property="searchBarHeaderBorder" destination="gcy-W7-89G" id="tsy-SP-KaJ"/>
|
||||
<outlet property="searchBarTopConstraint" destination="sUb-hD-qXJ" id="rzi-JJ-nnP"/>
|
||||
<outlet property="searchBarView" destination="bsq-3U-VjV" id="x3M-wX-RW8"/>
|
||||
<outlet property="tableView" destination="kNf-Ll-jvH" id="uzM-uQ-peQ"/>
|
||||
<outlet property="tableViewBottomConstraint" destination="jLY-ml-Psl" id="Q2b-sC-Yqn"/>
|
||||
<outlet property="view" destination="iN0-l3-epB" id="csR-cn-S4h"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Zm7-AB-ZtE">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
|
||||
<subviews>
|
||||
<searchBar contentMode="redraw" searchBarStyle="minimal" translatesAutoresizingMaskIntoConstraints="NO" id="bsq-3U-VjV">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
|
||||
<textInputTraits key="textInputTraits" returnKeyType="done"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="accessibilityIdentifier" value="RoomParticipantsVCSearchBarView"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-1" id="UYv-bz-JBZ"/>
|
||||
</connections>
|
||||
</searchBar>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gcy-W7-89G">
|
||||
<rect key="frame" x="0.0" y="49" width="375" height="1"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="1" id="Rka-an-qn3"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="RoomParticipantsVCSearchBarHeader"/>
|
||||
<constraints>
|
||||
<constraint firstItem="gcy-W7-89G" firstAttribute="leading" secondItem="Zm7-AB-ZtE" secondAttribute="leading" id="4Yn-dN-O2U"/>
|
||||
<constraint firstItem="bsq-3U-VjV" firstAttribute="leading" secondItem="Zm7-AB-ZtE" secondAttribute="leading" id="6ze-Az-ymf"/>
|
||||
<constraint firstAttribute="bottom" secondItem="bsq-3U-VjV" secondAttribute="bottom" id="KDW-SI-sG6"/>
|
||||
<constraint firstAttribute="trailing" secondItem="bsq-3U-VjV" secondAttribute="trailing" id="ZlE-SL-UfQ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="gcy-W7-89G" secondAttribute="trailing" id="hqD-vA-OM5"/>
|
||||
<constraint firstAttribute="bottom" secondItem="gcy-W7-89G" secondAttribute="bottom" id="ibU-h7-mHt"/>
|
||||
<constraint firstAttribute="height" constant="50" id="kSM-fg-IHB"/>
|
||||
<constraint firstItem="bsq-3U-VjV" firstAttribute="top" secondItem="Zm7-AB-ZtE" secondAttribute="top" id="qpF-Za-XTL"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" keyboardDismissMode="onDrag" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="kNf-Ll-jvH">
|
||||
<rect key="frame" x="0.0" y="50" width="375" height="617"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="accessibilityIdentifier" value="RoomParticipantsVCTableView"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="-1" id="tlI-w1-VJw"/>
|
||||
<outlet property="delegate" destination="-1" id="xcS-Zy-x2X"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="RoomParticipantsVCView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="Zm7-AB-ZtE" secondAttribute="trailing" id="0W7-Iv-Cs1"/>
|
||||
<constraint firstAttribute="trailing" secondItem="kNf-Ll-jvH" secondAttribute="trailing" id="1KS-nO-Jys"/>
|
||||
<constraint firstItem="Zm7-AB-ZtE" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="Irh-6y-0cw"/>
|
||||
<constraint firstItem="kNf-Ll-jvH" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="hfq-4u-4J8"/>
|
||||
<constraint firstAttribute="bottom" secondItem="kNf-Ll-jvH" secondAttribute="bottom" id="jLY-ml-Psl"/>
|
||||
<constraint firstItem="Zm7-AB-ZtE" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="sUb-hD-qXJ"/>
|
||||
<constraint firstItem="kNf-Ll-jvH" firstAttribute="top" secondItem="Zm7-AB-ZtE" secondAttribute="bottom" id="tYv-VV-8dI"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations 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>
|
||||
|
||||
/**
|
||||
'GroupRoomsViewController' instance is used to list the rooms of the group defined by the property 'mxGroup'.
|
||||
When this property is nil, the view controller is empty.
|
||||
*/
|
||||
@interface GroupRoomsViewController : MXKViewController <UITableViewDelegate, UITableViewDataSource, UISearchBarDelegate>
|
||||
{
|
||||
@protected
|
||||
|
||||
/**
|
||||
The current list of the rooms.
|
||||
*/
|
||||
NSArray<MXGroupRoom*> *groupRooms;
|
||||
}
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UITableView *tableView;
|
||||
@property (weak, nonatomic) IBOutlet UIView *searchBarHeader;
|
||||
@property (weak, nonatomic) IBOutlet UISearchBar *searchBarView;
|
||||
@property (weak, nonatomic) IBOutlet UIView *searchBarHeaderBorder;
|
||||
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *searchBarTopConstraint;
|
||||
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *tableViewBottomConstraint;
|
||||
|
||||
/**
|
||||
A matrix group (nil by default).
|
||||
*/
|
||||
@property (strong, readonly, nonatomic) MXGroup *group;
|
||||
@property (strong, readonly, nonatomic) MXSession *mxSession;
|
||||
|
||||
/**
|
||||
Returns the `UINib` object initialized for a `GroupRoomsViewController`.
|
||||
|
||||
@return The initialized `UINib` object or `nil` if there were errors during initialization
|
||||
or the nib file could not be located.
|
||||
*/
|
||||
+ (UINib *)nib;
|
||||
|
||||
/**
|
||||
Creates and returns a new `GroupRoomsViewController` object.
|
||||
|
||||
@discussion This is the designated initializer for programmatic instantiation.
|
||||
@return An initialized `GroupRoomsViewController` object if successful, `nil` otherwise.
|
||||
*/
|
||||
+ (instancetype)groupRoomsViewController;
|
||||
|
||||
/**
|
||||
Set the group for which the rooms are listed.
|
||||
Provide the related matrix session.
|
||||
|
||||
@param group
|
||||
@param mxSession
|
||||
*/
|
||||
- (void)setGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession;
|
||||
|
||||
@end
|
||||
|
|
@ -1,623 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations 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 "GroupRoomsViewController.h"
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
#import "GroupRoomTableViewCell.h"
|
||||
|
||||
#import "RageShakeManager.h"
|
||||
|
||||
@interface GroupRoomsViewController ()
|
||||
{
|
||||
// Search result
|
||||
NSString *currentSearchText;
|
||||
NSMutableArray<MXGroupRoom*> *filteredGroupRooms;
|
||||
|
||||
// Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change.
|
||||
id kRiotDesignValuesDidChangeThemeNotificationObserver;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation GroupRoomsViewController
|
||||
|
||||
#pragma mark - Class methods
|
||||
|
||||
+ (UINib *)nib
|
||||
{
|
||||
return [UINib nibWithNibName:NSStringFromClass(self.class)
|
||||
bundle:[NSBundle bundleForClass:self.class]];
|
||||
}
|
||||
|
||||
+ (instancetype)groupRoomsViewController
|
||||
{
|
||||
return [[[self class] alloc] initWithNibName:NSStringFromClass(self.class)
|
||||
bundle:[NSBundle bundleForClass:self.class]];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)finalizeInit
|
||||
{
|
||||
[super finalizeInit];
|
||||
|
||||
// Setup `MXKViewControllerHandling` properties
|
||||
self.enableBarTintColorStatusChange = NO;
|
||||
self.rageShakeManager = [RageShakeManager sharedManager];
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
// Do any additional setup after loading the view, typically from a nib.
|
||||
|
||||
// Check whether the view controller has been pushed via storyboard
|
||||
if (!self.tableView)
|
||||
{
|
||||
// Instantiate view controller objects
|
||||
[[[self class] nib] instantiateWithOwner:self options:nil];
|
||||
}
|
||||
|
||||
// Adjust Top and Bottom constraints to take into account potential navBar and tabBar.
|
||||
[NSLayoutConstraint deactivateConstraints:@[_searchBarTopConstraint, _tableViewBottomConstraint]];
|
||||
|
||||
_searchBarTopConstraint = [NSLayoutConstraint constraintWithItem:self.topLayoutGuide
|
||||
attribute:NSLayoutAttributeBottom
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.searchBarHeader
|
||||
attribute:NSLayoutAttributeTop
|
||||
multiplier:1.0f
|
||||
constant:0.0f];
|
||||
|
||||
_tableViewBottomConstraint = [NSLayoutConstraint constraintWithItem:self.bottomLayoutGuide
|
||||
attribute:NSLayoutAttributeTop
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.tableView
|
||||
attribute:NSLayoutAttributeBottom
|
||||
multiplier:1.0f
|
||||
constant:0.0f];
|
||||
|
||||
[NSLayoutConstraint activateConstraints:@[_searchBarTopConstraint, _tableViewBottomConstraint]];
|
||||
|
||||
_searchBarView.placeholder = NSLocalizedStringFromTable(@"group_rooms_filter_rooms", @"Vector", nil);
|
||||
_searchBarView.returnKeyType = UIReturnKeyDone;
|
||||
_searchBarView.autocapitalizationType = UITextAutocapitalizationTypeNone;
|
||||
|
||||
// Search bar header is hidden when no group is provided
|
||||
_searchBarHeader.hidden = (self.group == nil);
|
||||
|
||||
// Enable self-sizing cells and section headers.
|
||||
self.tableView.rowHeight = UITableViewAutomaticDimension;
|
||||
self.tableView.estimatedRowHeight = 74;
|
||||
self.tableView.sectionHeaderHeight = 0;
|
||||
|
||||
// Hide line separators of empty cells
|
||||
self.tableView.tableFooterView = [[UIView alloc] init];
|
||||
|
||||
[self.tableView registerClass:GroupRoomTableViewCell.class forCellReuseIdentifier:@"RoomTableViewCellId"];
|
||||
|
||||
// Observe user interface theme change.
|
||||
kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
|
||||
|
||||
[self userInterfaceThemeDidChange];
|
||||
|
||||
}];
|
||||
[self userInterfaceThemeDidChange];
|
||||
}
|
||||
|
||||
- (void)userInterfaceThemeDidChange
|
||||
{
|
||||
self.defaultBarTintColor = kRiotSecondaryBgColor;
|
||||
self.barTitleColor = kRiotPrimaryTextColor;
|
||||
self.activityIndicator.backgroundColor = kRiotOverlayColor;
|
||||
|
||||
[self refreshSearchBarItemsColor:_searchBarView];
|
||||
|
||||
_searchBarHeaderBorder.backgroundColor = kRiotAuxiliaryColor;
|
||||
|
||||
// Check the table view style to select its bg color.
|
||||
self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor);
|
||||
self.view.backgroundColor = self.tableView.backgroundColor;
|
||||
|
||||
if (self.tableView.dataSource)
|
||||
{
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
}
|
||||
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle
|
||||
{
|
||||
return kRiotDesignStatusBarStyle;
|
||||
}
|
||||
|
||||
// This method is called when the viewcontroller is added or removed from a container view controller.
|
||||
- (void)didMoveToParentViewController:(nullable UIViewController *)parent
|
||||
{
|
||||
[super didMoveToParentViewController:parent];
|
||||
}
|
||||
|
||||
- (void)destroy
|
||||
{
|
||||
if (kRiotDesignValuesDidChangeThemeNotificationObserver)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver];
|
||||
kRiotDesignValuesDidChangeThemeNotificationObserver = nil;
|
||||
}
|
||||
|
||||
_group = nil;
|
||||
_mxSession = nil;
|
||||
|
||||
filteredGroupRooms = nil;
|
||||
|
||||
groupRooms = nil;
|
||||
|
||||
// Note: all observers are removed during super call.
|
||||
[super destroy];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"GroupDetailsRooms"];
|
||||
|
||||
if (_group)
|
||||
{
|
||||
// Restore the listeners on the group update.
|
||||
[self registerOnGroupChangeNotifications];
|
||||
|
||||
// Check whether the selected group is stored in the user's session, or if it is a group preview.
|
||||
// Replace the displayed group instance with the one stored in the session (if any).
|
||||
MXGroup *storedGroup = [_mxSession groupWithGroupId:_group.groupId];
|
||||
BOOL isPreview = (!storedGroup);
|
||||
|
||||
// Force refresh
|
||||
[self refreshDisplayWithGroup:(isPreview ? _group : storedGroup)];
|
||||
|
||||
// Prepare a block called on successful update in case of a group preview.
|
||||
// Indeed the group update notifications are triggered by the matrix session only for the user's groups.
|
||||
void (^success)(void) = ^void(void)
|
||||
{
|
||||
[self refreshDisplayWithGroup:_group];
|
||||
};
|
||||
|
||||
// Trigger a refresh on the group rooms.
|
||||
[self.mxSession updateGroupRooms:_group success:(isPreview ? success : nil) failure:^(NSError *error) {
|
||||
|
||||
NSLog(@"[GroupRoomsViewController] viewWillAppear: group rooms update failed %@", _group.groupId);
|
||||
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated
|
||||
{
|
||||
[super viewWillDisappear:animated];
|
||||
|
||||
[self cancelRegistrationOnGroupChangeNotifications];
|
||||
|
||||
// cancel any pending search
|
||||
[self searchBarCancelButtonClicked:_searchBarView];
|
||||
}
|
||||
|
||||
- (void)withdrawViewControllerAnimated:(BOOL)animated completion:(void (^)(void))completion
|
||||
{
|
||||
// Check whether the current view controller is displayed inside a segmented view controller in order to withdraw the right item
|
||||
if (self.parentViewController && [self.parentViewController isKindOfClass:SegmentedViewController.class])
|
||||
{
|
||||
[((SegmentedViewController*)self.parentViewController) withdrawViewControllerAnimated:animated completion:completion];
|
||||
}
|
||||
else
|
||||
{
|
||||
[super withdrawViewControllerAnimated:animated completion:completion];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession
|
||||
{
|
||||
// Cancel any pending search
|
||||
[self searchBarCancelButtonClicked:_searchBarView];
|
||||
|
||||
if (_mxSession != mxSession)
|
||||
{
|
||||
[self cancelRegistrationOnGroupChangeNotifications];
|
||||
_mxSession = mxSession;
|
||||
|
||||
[self registerOnGroupChangeNotifications];
|
||||
}
|
||||
|
||||
[self addMatrixSession:mxSession];
|
||||
|
||||
[self refreshDisplayWithGroup:group];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)registerOnGroupChangeNotifications
|
||||
{
|
||||
if (_mxSession)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didUpdateGroupRooms:) name:kMXSessionDidUpdateGroupRoomsNotification object:_mxSession];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cancelRegistrationOnGroupChangeNotifications
|
||||
{
|
||||
// Remove any pending observers
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionDidUpdateGroupRoomsNotification object:_mxSession];
|
||||
}
|
||||
|
||||
- (void)didUpdateGroupRooms:(NSNotification *)notif
|
||||
{
|
||||
MXGroup *group = notif.userInfo[kMXSessionNotificationGroupKey];
|
||||
if (group && [group.groupId isEqualToString:_group.groupId])
|
||||
{
|
||||
// Update the current displayed group instance with the one stored in the session.
|
||||
[self refreshDisplayWithGroup:group];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)refreshDisplayWithGroup:(MXGroup *)group
|
||||
{
|
||||
_group = group;
|
||||
|
||||
if (_group)
|
||||
{
|
||||
_searchBarHeader.hidden = NO;
|
||||
groupRooms = _group.rooms.chunk;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Search bar header is hidden when no group is provided
|
||||
_searchBarHeader.hidden = YES;
|
||||
groupRooms = nil;
|
||||
}
|
||||
|
||||
// Reload search result if any
|
||||
if (currentSearchText.length)
|
||||
{
|
||||
NSString *searchText = currentSearchText;
|
||||
currentSearchText = nil;
|
||||
|
||||
[self searchBar:_searchBarView textDidChange:searchText];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self refreshTableView];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startActivityIndicator
|
||||
{
|
||||
// Check whether the current view controller is displayed inside a segmented view controller in order to run the right activity view
|
||||
if (self.parentViewController && [self.parentViewController isKindOfClass:SegmentedViewController.class])
|
||||
{
|
||||
[((SegmentedViewController*)self.parentViewController) startActivityIndicator];
|
||||
|
||||
// Force stop the activity view of the view controller
|
||||
[self.activityIndicator stopAnimating];
|
||||
}
|
||||
else
|
||||
{
|
||||
[super startActivityIndicator];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)stopActivityIndicator
|
||||
{
|
||||
// Check whether the current view controller is displayed inside a segmented view controller in order to stop the right activity view
|
||||
if (self.parentViewController && [self.parentViewController isKindOfClass:SegmentedViewController.class])
|
||||
{
|
||||
[((SegmentedViewController*)self.parentViewController) stopActivityIndicator];
|
||||
|
||||
// Force stop the activity view of the view controller
|
||||
[self.activityIndicator stopAnimating];
|
||||
}
|
||||
else
|
||||
{
|
||||
[super stopActivityIndicator];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Internals
|
||||
|
||||
- (void)refreshTableView
|
||||
{
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
- (void)pushViewController:(UIViewController*)viewController
|
||||
{
|
||||
// Check whether the view controller is displayed inside a segmented one.
|
||||
if (self.parentViewController.navigationController)
|
||||
{
|
||||
// Hide back button title
|
||||
self.parentViewController.navigationItem.backBarButtonItem =[[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
|
||||
|
||||
[self.parentViewController.navigationController pushViewController:viewController animated:YES];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Hide back button title
|
||||
self.navigationItem.backBarButtonItem =[[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:nil];
|
||||
|
||||
[self.navigationController pushViewController:viewController animated:YES];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UITableView data source
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
|
||||
{
|
||||
NSInteger count = 0;
|
||||
|
||||
if (currentSearchText.length)
|
||||
{
|
||||
if (filteredGroupRooms.count)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (groupRooms.count)
|
||||
{
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
NSInteger count = 0;
|
||||
|
||||
if (currentSearchText.length)
|
||||
{
|
||||
count = filteredGroupRooms.count;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = groupRooms.count;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
GroupRoomTableViewCell* roomCell = [tableView dequeueReusableCellWithIdentifier:@"RoomTableViewCellId" forIndexPath:indexPath];
|
||||
roomCell.selectionStyle = UITableViewCellSelectionStyleNone;
|
||||
|
||||
MXGroupRoom *room;
|
||||
NSArray *rooms;
|
||||
|
||||
if (currentSearchText.length)
|
||||
{
|
||||
rooms = filteredGroupRooms;
|
||||
}
|
||||
else
|
||||
{
|
||||
rooms = groupRooms;
|
||||
}
|
||||
|
||||
if (indexPath.row < rooms.count)
|
||||
{
|
||||
room = rooms[indexPath.row];
|
||||
}
|
||||
|
||||
if (room)
|
||||
{
|
||||
[roomCell render:room withMatrixSession:self.mxSession];
|
||||
}
|
||||
|
||||
return roomCell;
|
||||
}
|
||||
|
||||
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView*)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath*)indexPath
|
||||
{
|
||||
// iOS8 requires this method to enable editing (see editActionsForRowAtIndexPath).
|
||||
}
|
||||
|
||||
#pragma mark - UITableView delegate
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
return tableView.estimatedRowHeight;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
cell.backgroundColor = kRiotPrimaryBgColor;
|
||||
|
||||
// Update the selected background view
|
||||
if (kRiotSelectedBgColor)
|
||||
{
|
||||
cell.selectedBackgroundView = [[UIView alloc] init];
|
||||
cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tableView.style == UITableViewStylePlain)
|
||||
{
|
||||
cell.selectedBackgroundView = nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.selectedBackgroundView.backgroundColor = nil;
|
||||
}
|
||||
}
|
||||
|
||||
// Refresh here the estimated row height
|
||||
tableView.estimatedRowHeight = cell.frame.size.height;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
}
|
||||
|
||||
//- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
//{
|
||||
// NSMutableArray* actions;
|
||||
//
|
||||
// // @TODO Add the swipe to remove this room from the community if the current user is admin
|
||||
// actions = [[NSMutableArray alloc] init];
|
||||
//
|
||||
// // Patch: Force the width of the button by adding whitespace characters into the title string.
|
||||
// UITableViewRowAction *leaveAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@" " handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
|
||||
//
|
||||
// // @TODO Remove the room
|
||||
//
|
||||
// }];
|
||||
//
|
||||
// leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)];
|
||||
// [actions insertObject:leaveAction atIndex:0];
|
||||
//
|
||||
// return actions;
|
||||
//}
|
||||
|
||||
#pragma mark - UISearchBar delegate
|
||||
|
||||
- (void)refreshSearchBarItemsColor:(UISearchBar *)searchBar
|
||||
{
|
||||
// bar tint color
|
||||
searchBar.barTintColor = searchBar.tintColor = kRiotColorBlue;
|
||||
searchBar.tintColor = kRiotColorBlue;
|
||||
|
||||
// FIXME: this all seems incredibly fragile and tied to gutwrenching the current UISearchBar internals.
|
||||
|
||||
// text color
|
||||
UITextField *searchBarTextField = [searchBar valueForKey:@"_searchField"];
|
||||
searchBarTextField.textColor = kRiotSecondaryTextColor;
|
||||
|
||||
// Magnifying glass icon.
|
||||
UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView;
|
||||
leftImageView.image = [leftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate];
|
||||
leftImageView.tintColor = kRiotColorBlue;
|
||||
|
||||
// remove the gray background color
|
||||
UIView *effectBackgroundTop = [searchBarTextField valueForKey:@"_effectBackgroundTop"];
|
||||
UIView *effectBackgroundBottom = [searchBarTextField valueForKey:@"_effectBackgroundBottom"];
|
||||
effectBackgroundTop.hidden = YES;
|
||||
effectBackgroundBottom.hidden = YES;
|
||||
|
||||
// place holder
|
||||
searchBarTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBarTextField.placeholder
|
||||
attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle),
|
||||
NSUnderlineColorAttributeName: kRiotColorBlue,
|
||||
NSForegroundColorAttributeName: kRiotColorBlue}];
|
||||
}
|
||||
|
||||
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
|
||||
{
|
||||
// Update search results.
|
||||
NSUInteger index;
|
||||
MXGroupRoom *groupRoom;
|
||||
|
||||
searchText = [searchText stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
||||
|
||||
if (!currentSearchText.length || [searchText hasPrefix:currentSearchText] == NO)
|
||||
{
|
||||
// Copy participants and invited participants
|
||||
filteredGroupRooms = [NSMutableArray arrayWithArray:groupRooms];
|
||||
}
|
||||
|
||||
currentSearchText = searchText;
|
||||
|
||||
// Filter group participants
|
||||
if (currentSearchText.length)
|
||||
{
|
||||
for (index = 0; index < filteredGroupRooms.count;)
|
||||
{
|
||||
groupRoom = filteredGroupRooms[index];
|
||||
|
||||
NSString *displayName = groupRoom.name;
|
||||
if (!displayName)
|
||||
{
|
||||
displayName = groupRoom.canonicalAlias;
|
||||
}
|
||||
if (!displayName)
|
||||
{
|
||||
displayName = groupRoom.roomId;
|
||||
}
|
||||
|
||||
if ([displayName rangeOfString:currentSearchText options:NSCaseInsensitiveSearch].location == NSNotFound)
|
||||
{
|
||||
[filteredGroupRooms removeObjectAtIndex:index];
|
||||
}
|
||||
else
|
||||
{
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
filteredGroupRooms = nil;
|
||||
}
|
||||
|
||||
// Refresh display
|
||||
[self refreshTableView];
|
||||
}
|
||||
|
||||
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
|
||||
{
|
||||
searchBar.showsCancelButton = YES;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
|
||||
{
|
||||
searchBar.showsCancelButton = NO;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
|
||||
{
|
||||
// "Done" key has been pressed.
|
||||
|
||||
// Dismiss keyboard
|
||||
[_searchBarView resignFirstResponder];
|
||||
}
|
||||
|
||||
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
|
||||
{
|
||||
if (currentSearchText)
|
||||
{
|
||||
currentSearchText = nil;
|
||||
filteredGroupRooms = nil;
|
||||
|
||||
[self refreshTableView];
|
||||
}
|
||||
|
||||
searchBar.text = nil;
|
||||
// Leave search
|
||||
[searchBar resignFirstResponder];
|
||||
}
|
||||
|
||||
@end
|
|
@ -1,87 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="13771" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13772"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="GroupRoomsViewController">
|
||||
<connections>
|
||||
<outlet property="searchBarHeader" destination="Zm7-AB-ZtE" id="6ee-P0-twi"/>
|
||||
<outlet property="searchBarHeaderBorder" destination="gcy-W7-89G" id="tsy-SP-KaJ"/>
|
||||
<outlet property="searchBarTopConstraint" destination="sUb-hD-qXJ" id="rzi-JJ-nnP"/>
|
||||
<outlet property="searchBarView" destination="bsq-3U-VjV" id="x3M-wX-RW8"/>
|
||||
<outlet property="tableView" destination="kNf-Ll-jvH" id="uzM-uQ-peQ"/>
|
||||
<outlet property="tableViewBottomConstraint" destination="jLY-ml-Psl" id="Q2b-sC-Yqn"/>
|
||||
<outlet property="view" destination="iN0-l3-epB" id="csR-cn-S4h"/>
|
||||
</connections>
|
||||
</placeholder>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||
<subviews>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Zm7-AB-ZtE">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
|
||||
<subviews>
|
||||
<searchBar contentMode="redraw" searchBarStyle="minimal" translatesAutoresizingMaskIntoConstraints="NO" id="bsq-3U-VjV">
|
||||
<rect key="frame" x="0.0" y="0.0" width="375" height="50"/>
|
||||
<textInputTraits key="textInputTraits" returnKeyType="done"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="accessibilityIdentifier" value="RoomParticipantsVCSearchBarView"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="delegate" destination="-1" id="UYv-bz-JBZ"/>
|
||||
</connections>
|
||||
</searchBar>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="gcy-W7-89G">
|
||||
<rect key="frame" x="0.0" y="49" width="375" height="1"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="height" constant="1" id="Rka-an-qn3"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</subviews>
|
||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="RoomParticipantsVCSearchBarHeader"/>
|
||||
<constraints>
|
||||
<constraint firstItem="gcy-W7-89G" firstAttribute="leading" secondItem="Zm7-AB-ZtE" secondAttribute="leading" id="4Yn-dN-O2U"/>
|
||||
<constraint firstItem="bsq-3U-VjV" firstAttribute="leading" secondItem="Zm7-AB-ZtE" secondAttribute="leading" id="6ze-Az-ymf"/>
|
||||
<constraint firstAttribute="bottom" secondItem="bsq-3U-VjV" secondAttribute="bottom" id="KDW-SI-sG6"/>
|
||||
<constraint firstAttribute="trailing" secondItem="bsq-3U-VjV" secondAttribute="trailing" id="ZlE-SL-UfQ"/>
|
||||
<constraint firstAttribute="trailing" secondItem="gcy-W7-89G" secondAttribute="trailing" id="hqD-vA-OM5"/>
|
||||
<constraint firstAttribute="bottom" secondItem="gcy-W7-89G" secondAttribute="bottom" id="ibU-h7-mHt"/>
|
||||
<constraint firstAttribute="height" constant="50" id="kSM-fg-IHB"/>
|
||||
<constraint firstItem="bsq-3U-VjV" firstAttribute="top" secondItem="Zm7-AB-ZtE" secondAttribute="top" id="qpF-Za-XTL"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" keyboardDismissMode="onDrag" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="kNf-Ll-jvH">
|
||||
<rect key="frame" x="0.0" y="50" width="375" height="617"/>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<userDefinedRuntimeAttributes>
|
||||
<userDefinedRuntimeAttribute type="string" keyPath="accessibilityIdentifier" value="RoomParticipantsVCTableView"/>
|
||||
</userDefinedRuntimeAttributes>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="-1" id="tlI-w1-VJw"/>
|
||||
<outlet property="delegate" destination="-1" id="xcS-Zy-x2X"/>
|
||||
</connections>
|
||||
</tableView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<accessibility key="accessibilityConfiguration" identifier="RoomParticipantsVCView"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="trailing" secondItem="Zm7-AB-ZtE" secondAttribute="trailing" id="0W7-Iv-Cs1"/>
|
||||
<constraint firstAttribute="trailing" secondItem="kNf-Ll-jvH" secondAttribute="trailing" id="1KS-nO-Jys"/>
|
||||
<constraint firstItem="Zm7-AB-ZtE" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="Irh-6y-0cw"/>
|
||||
<constraint firstItem="kNf-Ll-jvH" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="hfq-4u-4J8"/>
|
||||
<constraint firstAttribute="bottom" secondItem="kNf-Ll-jvH" secondAttribute="bottom" id="jLY-ml-Psl"/>
|
||||
<constraint firstItem="Zm7-AB-ZtE" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="sUb-hD-qXJ"/>
|
||||
<constraint firstItem="kNf-Ll-jvH" firstAttribute="top" secondItem="Zm7-AB-ZtE" secondAttribute="bottom" id="tYv-VV-8dI"/>
|
||||
</constraints>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
|
@ -1,52 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations 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>
|
||||
|
||||
/**
|
||||
The `GroupsViewController` screen is the view controller displayed when `Groups` tab is selected.
|
||||
*/
|
||||
@interface GroupsViewController : MXKGroupListViewController <MXKGroupListViewControllerDelegate>
|
||||
{
|
||||
@protected
|
||||
/**
|
||||
The group identifier related to the cell which is in editing mode (if any).
|
||||
*/
|
||||
NSString *editedGroupId;
|
||||
|
||||
/**
|
||||
Current alert (if any).
|
||||
*/
|
||||
UIAlertController *currentAlert;
|
||||
|
||||
/**
|
||||
The image view of the (+) button.
|
||||
*/
|
||||
UIImageView* plusButtonImageView;
|
||||
}
|
||||
|
||||
/**
|
||||
If YES, the table view will scroll at the top on the next data source refresh.
|
||||
It comes back to NO after each refresh.
|
||||
*/
|
||||
@property (nonatomic) BOOL shouldScrollToTopOnRefresh;
|
||||
|
||||
/**
|
||||
Tell whether the search bar at the top of the groups table is enabled. YES by default.
|
||||
*/
|
||||
@property (nonatomic) BOOL enableSearchBar;
|
||||
|
||||
@end
|
|
@ -1,799 +0,0 @@
|
|||
/*
|
||||
Copyright 2017 Vector Creations 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 "GroupsViewController.h"
|
||||
|
||||
#import "GroupTableViewCell.h"
|
||||
#import "GroupInviteTableViewCell.h"
|
||||
|
||||
#import "AppDelegate.h"
|
||||
|
||||
@interface GroupsViewController ()
|
||||
{
|
||||
// Tell whether a groups refresh is pending (suspended during editing mode).
|
||||
BOOL isRefreshPending;
|
||||
|
||||
// Observe UIApplicationDidEnterBackgroundNotification to cancel editing mode when app leaves the foreground state.
|
||||
id UIApplicationDidEnterBackgroundNotificationObserver;
|
||||
|
||||
// Observe kAppDelegateDidTapStatusBarNotification to handle tap on clock status bar.
|
||||
id kAppDelegateDidTapStatusBarNotificationObserver;
|
||||
|
||||
MXHTTPOperation *currentRequest;
|
||||
|
||||
// The fake search bar displayed at the top of the recents table. We switch on the actual search bar (self.groupsSearchBar)
|
||||
// when the user selects it.
|
||||
UISearchBar *tableSearchBar;
|
||||
|
||||
// Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change.
|
||||
id kRiotDesignValuesDidChangeThemeNotificationObserver;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation GroupsViewController
|
||||
|
||||
- (void)finalizeInit
|
||||
{
|
||||
[super finalizeInit];
|
||||
|
||||
// Setup `MXKViewControllerHandling` properties
|
||||
self.enableBarTintColorStatusChange = NO;
|
||||
self.rageShakeManager = [RageShakeManager sharedManager];
|
||||
|
||||
// Enable the search bar in the recents table, and remove the search option from the navigation bar.
|
||||
_enableSearchBar = YES;
|
||||
self.enableBarButtonSearch = NO;
|
||||
|
||||
// Create the fake search bar
|
||||
tableSearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 600, 44)];
|
||||
tableSearchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
|
||||
tableSearchBar.showsCancelButton = NO;
|
||||
tableSearchBar.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil);
|
||||
tableSearchBar.delegate = self;
|
||||
|
||||
// Set itself as delegate by default.
|
||||
self.delegate = self;
|
||||
}
|
||||
|
||||
- (void)viewDidLoad
|
||||
{
|
||||
[super viewDidLoad];
|
||||
|
||||
self.view.accessibilityIdentifier = @"GroupsVCView";
|
||||
self.groupsTableView.accessibilityIdentifier = @"GroupsVCTableView";
|
||||
|
||||
//Register here the customized cell view class used to render groups
|
||||
[self.groupsTableView registerNib:GroupTableViewCell.nib forCellReuseIdentifier:GroupTableViewCell.defaultReuseIdentifier];
|
||||
[self.groupsTableView registerNib:GroupInviteTableViewCell.nib forCellReuseIdentifier:GroupInviteTableViewCell.defaultReuseIdentifier];
|
||||
|
||||
// Hide line separators of empty cells
|
||||
self.groupsTableView.tableFooterView = [[UIView alloc] init];
|
||||
|
||||
// Enable self-sizing cells and section headers.
|
||||
self.groupsTableView.rowHeight = UITableViewAutomaticDimension;
|
||||
self.groupsTableView.estimatedRowHeight = 74;
|
||||
self.groupsTableView.sectionHeaderHeight = UITableViewAutomaticDimension;
|
||||
self.groupsTableView.estimatedSectionHeaderHeight = 30;
|
||||
self.groupsTableView.estimatedSectionFooterHeight = 0;
|
||||
|
||||
// Observe UIApplicationDidEnterBackgroundNotification to refresh bubbles when app leaves the foreground state.
|
||||
UIApplicationDidEnterBackgroundNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidEnterBackgroundNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
|
||||
|
||||
// Leave potential editing mode
|
||||
[self cancelEditionMode:isRefreshPending];
|
||||
|
||||
}];
|
||||
|
||||
self.groupsSearchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
|
||||
self.groupsSearchBar.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil);
|
||||
|
||||
// @TODO: Add programmatically the (+) button.
|
||||
//[self addPlusButton];
|
||||
|
||||
// Observe user interface theme change.
|
||||
kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
|
||||
|
||||
[self userInterfaceThemeDidChange];
|
||||
|
||||
}];
|
||||
[self userInterfaceThemeDidChange];
|
||||
}
|
||||
|
||||
- (void)userInterfaceThemeDidChange
|
||||
{
|
||||
self.defaultBarTintColor = kRiotSecondaryBgColor;
|
||||
self.barTitleColor = kRiotPrimaryTextColor;
|
||||
self.activityIndicator.backgroundColor = kRiotOverlayColor;
|
||||
|
||||
// Use the primary bg color for the recents table view in plain style.
|
||||
self.groupsTableView.backgroundColor = kRiotPrimaryBgColor;
|
||||
topview.backgroundColor = kRiotSecondaryBgColor;
|
||||
self.view.backgroundColor = kRiotPrimaryBgColor;
|
||||
|
||||
tableSearchBar.barStyle = self.groupsSearchBar.barStyle = kRiotDesignSearchBarStyle;
|
||||
tableSearchBar.tintColor = self.groupsSearchBar.tintColor = kRiotDesignSearchBarTintColor;
|
||||
|
||||
if (self.groupsTableView.dataSource)
|
||||
{
|
||||
// Force table refresh
|
||||
[self cancelEditionMode:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (UIStatusBarStyle)preferredStatusBarStyle
|
||||
{
|
||||
return kRiotDesignStatusBarStyle;
|
||||
}
|
||||
|
||||
- (void)destroy
|
||||
{
|
||||
[super destroy];
|
||||
|
||||
if (currentRequest)
|
||||
{
|
||||
[currentRequest cancel];
|
||||
currentRequest = nil;
|
||||
}
|
||||
|
||||
if (currentAlert)
|
||||
{
|
||||
[currentAlert dismissViewControllerAnimated:NO completion:nil];
|
||||
currentAlert = nil;
|
||||
}
|
||||
|
||||
if (UIApplicationDidEnterBackgroundNotificationObserver)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:UIApplicationDidEnterBackgroundNotificationObserver];
|
||||
UIApplicationDidEnterBackgroundNotificationObserver = nil;
|
||||
}
|
||||
|
||||
if (kRiotDesignValuesDidChangeThemeNotificationObserver)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver];
|
||||
kRiotDesignValuesDidChangeThemeNotificationObserver = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setEditing:(BOOL)editing animated:(BOOL)animated
|
||||
{
|
||||
[super setEditing:editing animated:animated];
|
||||
|
||||
self.groupsTableView.editing = editing;
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning
|
||||
{
|
||||
[super didReceiveMemoryWarning];
|
||||
// Dispose of any resources that can be recreated.
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated
|
||||
{
|
||||
[super viewWillAppear:animated];
|
||||
|
||||
// Screen tracking
|
||||
[[AppDelegate theDelegate] trackScreen:@"Groups"];
|
||||
|
||||
// Deselect the current selected row, it will be restored on viewDidAppear (if any)
|
||||
NSIndexPath *indexPath = [self.groupsTableView indexPathForSelectedRow];
|
||||
if (indexPath)
|
||||
{
|
||||
[self.groupsTableView deselectRowAtIndexPath:indexPath animated:NO];
|
||||
}
|
||||
|
||||
// Observe kAppDelegateDidTapStatusBarNotificationObserver.
|
||||
kAppDelegateDidTapStatusBarNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kAppDelegateDidTapStatusBarNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
|
||||
|
||||
[self scrollToTop:YES];
|
||||
|
||||
}];
|
||||
|
||||
[AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_groups", @"Vector", nil);
|
||||
[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar.tintColor = kRiotColorBlue;
|
||||
[AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorBlue;
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated
|
||||
{
|
||||
[super viewWillDisappear:animated];
|
||||
|
||||
// Leave potential editing mode
|
||||
[self cancelEditionMode:NO];
|
||||
|
||||
if (kAppDelegateDidTapStatusBarNotificationObserver)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:kAppDelegateDidTapStatusBarNotificationObserver];
|
||||
kAppDelegateDidTapStatusBarNotificationObserver = nil;
|
||||
}
|
||||
|
||||
if ([AppDelegate theDelegate].masterTabBarController.tabBar.tintColor == kRiotColorBlue)
|
||||
{
|
||||
// Restore default tintColor
|
||||
[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar.tintColor = kRiotColorGreen;
|
||||
[AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorGreen;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
[super viewDidAppear:animated];
|
||||
|
||||
// Release the current selected item (if any) except if the second view controller is still visible.
|
||||
if (self.splitViewController.isCollapsed)
|
||||
{
|
||||
// Release the current selected group (if any).
|
||||
[[AppDelegate theDelegate].masterTabBarController releaseSelectedItem];
|
||||
}
|
||||
else
|
||||
{
|
||||
// In case of split view controller where the primary and secondary view controllers are displayed side-by-side onscreen,
|
||||
// the selected group (if any) is highlighted.
|
||||
[self refreshCurrentSelectedCell:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidDisappear:(BOOL)animated
|
||||
{
|
||||
[super viewDidDisappear:animated];
|
||||
}
|
||||
|
||||
#pragma mark - Override MXKGroupListViewController
|
||||
|
||||
- (void)refreshGroupsTable
|
||||
{
|
||||
// Refresh the tabBar icon badges
|
||||
[[AppDelegate theDelegate].masterTabBarController refreshTabBarBadges];
|
||||
|
||||
isRefreshPending = NO;
|
||||
|
||||
if (editedGroupId)
|
||||
{
|
||||
// Check whether the user didn't leave the room
|
||||
if ([self.dataSource cellIndexPathWithGroupId:editedGroupId])
|
||||
{
|
||||
isRefreshPending = YES;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Cancel the editing mode, a new refresh will be triggered.
|
||||
[self cancelEditionMode:YES];
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
[self.groupsTableView reloadData];
|
||||
|
||||
// Check conditions to display the fake search bar into the table header
|
||||
if (_enableSearchBar && self.groupsSearchBar.isHidden && self.groupsTableView.tableHeaderView == nil)
|
||||
{
|
||||
// Add the search bar by hiding it by default.
|
||||
self.groupsTableView.tableHeaderView = tableSearchBar;
|
||||
self.groupsTableView.contentOffset = CGPointMake(0, self.groupsTableView.contentOffset.y + tableSearchBar.frame.size.height);
|
||||
}
|
||||
|
||||
if (_shouldScrollToTopOnRefresh)
|
||||
{
|
||||
[self scrollToTop:NO];
|
||||
_shouldScrollToTopOnRefresh = NO;
|
||||
}
|
||||
|
||||
// In case of split view controller where the primary and secondary view controllers are displayed side-by-side on screen,
|
||||
// the selected group (if any) is updated.
|
||||
if (!self.splitViewController.isCollapsed)
|
||||
{
|
||||
[self refreshCurrentSelectedCell:NO];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)hideSearchBar:(BOOL)hidden
|
||||
{
|
||||
[super hideSearchBar:hidden];
|
||||
|
||||
if (!hidden)
|
||||
{
|
||||
// Remove the fake table header view if any
|
||||
self.groupsTableView.tableHeaderView = nil;
|
||||
self.groupsTableView.contentInset = UIEdgeInsetsZero;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)refreshCurrentSelectedCell:(BOOL)forceVisible
|
||||
{
|
||||
// Update here the index of the current selected cell (if any) - Useful in landscape mode with split view controller.
|
||||
NSIndexPath *currentSelectedCellIndexPath = nil;
|
||||
MasterTabBarController *masterTabBarController = [AppDelegate theDelegate].masterTabBarController;
|
||||
if (masterTabBarController.currentGroupDetailViewController)
|
||||
{
|
||||
// Look for the rank of this selected group in displayed groups
|
||||
currentSelectedCellIndexPath = [self.dataSource cellIndexPathWithGroupId:masterTabBarController.selectedGroup.groupId];
|
||||
}
|
||||
|
||||
if (currentSelectedCellIndexPath)
|
||||
{
|
||||
// Select the right row
|
||||
[self.groupsTableView selectRowAtIndexPath:currentSelectedCellIndexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
|
||||
|
||||
if (forceVisible)
|
||||
{
|
||||
// Scroll table view to make the selected row appear at second position
|
||||
NSInteger topCellIndexPathRow = currentSelectedCellIndexPath.row ? currentSelectedCellIndexPath.row - 1: currentSelectedCellIndexPath.row;
|
||||
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:topCellIndexPathRow inSection:currentSelectedCellIndexPath.section];
|
||||
[self.groupsTableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NSIndexPath *indexPath = [self.groupsTableView indexPathForSelectedRow];
|
||||
if (indexPath)
|
||||
{
|
||||
[self.groupsTableView deselectRowAtIndexPath:indexPath animated:NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)cancelEditionMode:(BOOL)forceRefresh
|
||||
{
|
||||
if (self.groupsTableView.isEditing || self.isEditing)
|
||||
{
|
||||
// Leave editing mode first
|
||||
isRefreshPending = forceRefresh;
|
||||
[self setEditing:NO];
|
||||
}
|
||||
else if (forceRefresh)
|
||||
{
|
||||
// Clean
|
||||
editedGroupId = nil;
|
||||
|
||||
[self refreshGroupsTable];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - MXKDataSourceDelegate
|
||||
|
||||
- (Class<MXKCellRendering>)cellViewClassForCellData:(MXKCellData*)cellData
|
||||
{
|
||||
id<MXKGroupCellDataStoring> cellDataStoring = (id<MXKGroupCellDataStoring> )cellData;
|
||||
|
||||
if (cellDataStoring.group.membership != MXMembershipInvite)
|
||||
{
|
||||
return GroupTableViewCell.class;
|
||||
}
|
||||
else
|
||||
{
|
||||
return GroupInviteTableViewCell.class;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)cellReuseIdentifierForCellData:(MXKCellData*)cellData
|
||||
{
|
||||
Class class = [self cellViewClassForCellData:cellData];
|
||||
|
||||
if ([class respondsToSelector:@selector(defaultReuseIdentifier)])
|
||||
{
|
||||
return [class defaultReuseIdentifier];
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void)dataSource:(MXKDataSource *)dataSource didRecognizeAction:(NSString *)actionIdentifier inCell:(id<MXKCellRendering>)cell userInfo:(NSDictionary *)userInfo
|
||||
{
|
||||
// Handle here user actions on groups for Riot app
|
||||
if ([actionIdentifier isEqualToString:kGroupInviteTableViewCellPreviewButtonPressed])
|
||||
{
|
||||
// Retrieve the invited group
|
||||
MXGroup *invitedGroup = userInfo[kGroupInviteTableViewCellRoomKey];
|
||||
|
||||
// Display the room preview
|
||||
[[AppDelegate theDelegate].masterTabBarController selectGroup:invitedGroup inMatrixSession:self.mainSession];
|
||||
}
|
||||
else if ([actionIdentifier isEqualToString:kGroupInviteTableViewCellDeclineButtonPressed])
|
||||
{
|
||||
// Retrieve the invited group
|
||||
MXGroup *invitedGroup = userInfo[kGroupInviteTableViewCellRoomKey];
|
||||
|
||||
NSIndexPath *indexPath = [self.dataSource cellIndexPathWithGroupId:invitedGroup.groupId];
|
||||
if (indexPath)
|
||||
{
|
||||
[self.dataSource leaveGroupAtIndexPath:indexPath];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Keep default implementation for other actions if any
|
||||
if ([super respondsToSelector:@selector(cell:didRecognizeAction:userInfo:)])
|
||||
{
|
||||
[super dataSource:dataSource didRecognizeAction:actionIdentifier inCell:cell userInfo:userInfo];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UITableView delegate
|
||||
|
||||
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath;
|
||||
{
|
||||
[super tableView:tableView willDisplayCell:cell forRowAtIndexPath:indexPath];
|
||||
|
||||
cell.backgroundColor = kRiotPrimaryBgColor;
|
||||
|
||||
// Update the selected background view
|
||||
if (kRiotSelectedBgColor)
|
||||
{
|
||||
cell.selectedBackgroundView = [[UIView alloc] init];
|
||||
cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tableView.style == UITableViewStylePlain)
|
||||
{
|
||||
cell.selectedBackgroundView = nil;
|
||||
}
|
||||
else
|
||||
{
|
||||
cell.selectedBackgroundView.backgroundColor = nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (nullable UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
|
||||
{
|
||||
MXKTableViewHeaderFooterWithLabel *sectionHeader;
|
||||
|
||||
if (tableView.numberOfSections > 1)
|
||||
{
|
||||
sectionHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:MXKTableViewHeaderFooterWithLabel.defaultReuseIdentifier];
|
||||
sectionHeader.mxkContentView.backgroundColor = kRiotSecondaryBgColor;
|
||||
sectionHeader.mxkLabel.textColor = kRiotPrimaryTextColor;
|
||||
sectionHeader.mxkLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline];
|
||||
|
||||
NSString* title = [self.dataSource tableView:tableView titleForHeaderInSection:section];
|
||||
NSUInteger count = [self.dataSource tableView:tableView numberOfRowsInSection:section];
|
||||
if (count)
|
||||
{
|
||||
NSString *roomCount = [NSString stringWithFormat:@" %tu", count];
|
||||
NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title
|
||||
attributes:@{NSForegroundColorAttributeName: kRiotPrimaryTextColor}];
|
||||
[mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount
|
||||
attributes:@{NSForegroundColorAttributeName: kRiotAuxiliaryColor}]];
|
||||
|
||||
sectionHeader.mxkLabel.attributedText = mutableSectionTitle;
|
||||
}
|
||||
else
|
||||
{
|
||||
sectionHeader.mxkLabel.text = title;
|
||||
}
|
||||
}
|
||||
|
||||
return sectionHeader;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
UITableViewCell* cell = [self.groupsTableView cellForRowAtIndexPath:indexPath];
|
||||
|
||||
if ([cell isKindOfClass:[GroupInviteTableViewCell class]])
|
||||
{
|
||||
// hide the selection
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:NO];
|
||||
}
|
||||
else
|
||||
{
|
||||
[super tableView:tableView didSelectRowAtIndexPath:indexPath];
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
NSMutableArray* actions;
|
||||
|
||||
// add the swipe to delete only on joined group
|
||||
if (indexPath.section == self.dataSource.joinedGroupsSection)
|
||||
{
|
||||
// Store the identifier of the room related to the edited cell.
|
||||
id<MXKGroupCellDataStoring> cellData = [self.dataSource cellDataAtIndex:indexPath];
|
||||
editedGroupId = cellData.group.groupId;
|
||||
|
||||
actions = [[NSMutableArray alloc] init];
|
||||
|
||||
// Patch: Force the width of the button by adding whitespace characters into the title string.
|
||||
UITableViewRowAction *leaveAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDestructive title:@" " handler:^(UITableViewRowAction *action, NSIndexPath *indexPath){
|
||||
|
||||
[self.dataSource leaveGroupAtIndexPath:indexPath];
|
||||
|
||||
}];
|
||||
|
||||
leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)];
|
||||
[actions insertObject:leaveAction atIndex:0];
|
||||
}
|
||||
|
||||
return actions;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
[self cancelEditionMode:isRefreshPending];
|
||||
}
|
||||
|
||||
#pragma mark - UIScrollViewDelegate
|
||||
|
||||
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
|
||||
{
|
||||
[super scrollViewDidScroll:scrollView];
|
||||
|
||||
if (scrollView == self.groupsTableView)
|
||||
{
|
||||
if (!self.groupsSearchBar.isHidden)
|
||||
{
|
||||
if (!self.groupsSearchBar.text.length && (scrollView.contentOffset.y + scrollView.mxk_adjustedContentInset.top > self.groupsSearchBar.frame.size.height))
|
||||
{
|
||||
// Hide the search bar
|
||||
[self hideSearchBar:YES];
|
||||
|
||||
// Refresh display
|
||||
[self refreshGroupsTable];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Room handling
|
||||
|
||||
- (void)addPlusButton
|
||||
{
|
||||
// Add room options button
|
||||
plusButtonImageView = [[UIImageView alloc] init];
|
||||
[plusButtonImageView setTranslatesAutoresizingMaskIntoConstraints:NO];
|
||||
[self.view addSubview:plusButtonImageView];
|
||||
|
||||
plusButtonImageView.backgroundColor = [UIColor clearColor];
|
||||
plusButtonImageView.contentMode = UIViewContentModeCenter;
|
||||
plusButtonImageView.image = [UIImage imageNamed:@"create_group"];
|
||||
plusButtonImageView.layer.shadowOpacity = 0.3;
|
||||
plusButtonImageView.layer.shadowOffset = CGSizeMake(0, 3);
|
||||
|
||||
CGFloat side = 78.0f;
|
||||
NSLayoutConstraint* widthConstraint = [NSLayoutConstraint constraintWithItem:plusButtonImageView
|
||||
attribute:NSLayoutAttributeWidth
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1
|
||||
constant:side];
|
||||
|
||||
NSLayoutConstraint* heightConstraint = [NSLayoutConstraint constraintWithItem:plusButtonImageView
|
||||
attribute:NSLayoutAttributeHeight
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:nil
|
||||
attribute:NSLayoutAttributeNotAnAttribute
|
||||
multiplier:1
|
||||
constant:side];
|
||||
|
||||
NSLayoutConstraint* trailingConstraint = [NSLayoutConstraint constraintWithItem:plusButtonImageView
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:self.view
|
||||
attribute:NSLayoutAttributeTrailing
|
||||
multiplier:1
|
||||
constant:0];
|
||||
|
||||
NSLayoutConstraint* bottomConstraint = [NSLayoutConstraint constraintWithItem:self.bottomLayoutGuide
|
||||
attribute:NSLayoutAttributeTop
|
||||
relatedBy:NSLayoutRelationEqual
|
||||
toItem:plusButtonImageView
|
||||
attribute:NSLayoutAttributeBottom
|
||||
multiplier:1
|
||||
constant:9];
|
||||
|
||||
[NSLayoutConstraint activateConstraints:@[widthConstraint, heightConstraint, trailingConstraint, bottomConstraint]];
|
||||
|
||||
plusButtonImageView.userInteractionEnabled = YES;
|
||||
|
||||
// Handle tap gesture
|
||||
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onPlusButtonPressed)];
|
||||
[tap setNumberOfTouchesRequired:1];
|
||||
[tap setNumberOfTapsRequired:1];
|
||||
[plusButtonImageView addGestureRecognizer:tap];
|
||||
}
|
||||
|
||||
- (void)onPlusButtonPressed
|
||||
{
|
||||
__weak typeof(self) weakSelf = self;
|
||||
|
||||
[currentAlert dismissViewControllerAnimated:NO completion:nil];
|
||||
|
||||
currentAlert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
|
||||
// [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_recents_start_chat_with", @"Vector", nil)
|
||||
// style:UIAlertActionStyleDefault
|
||||
// handler:^(UIAlertAction * action) {
|
||||
//
|
||||
// if (weakSelf)
|
||||
// {
|
||||
// typeof(self) self = weakSelf;
|
||||
// self->currentAlert = nil;
|
||||
//
|
||||
// [self performSegueWithIdentifier:@"presentStartChat" sender:self];
|
||||
// }
|
||||
//
|
||||
// }]];
|
||||
//
|
||||
// [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_recents_create_empty_room", @"Vector", nil)
|
||||
// style:UIAlertActionStyleDefault
|
||||
// handler:^(UIAlertAction * action) {
|
||||
//
|
||||
// if (weakSelf)
|
||||
// {
|
||||
// typeof(self) self = weakSelf;
|
||||
// self->currentAlert = nil;
|
||||
//
|
||||
// [self createAnEmptyRoom];
|
||||
// }
|
||||
//
|
||||
// }]];
|
||||
//
|
||||
// [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_recents_join_room", @"Vector", nil)
|
||||
// style:UIAlertActionStyleDefault
|
||||
// handler:^(UIAlertAction * action) {
|
||||
//
|
||||
// if (weakSelf)
|
||||
// {
|
||||
// typeof(self) self = weakSelf;
|
||||
// self->currentAlert = nil;
|
||||
//
|
||||
// [self joinARoom];
|
||||
// }
|
||||
//
|
||||
// }]];
|
||||
|
||||
[currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentAlert = nil;
|
||||
}
|
||||
|
||||
}]];
|
||||
|
||||
[currentAlert popoverPresentationController].sourceView = plusButtonImageView;
|
||||
[currentAlert popoverPresentationController].sourceRect = plusButtonImageView.bounds;
|
||||
|
||||
[currentAlert mxk_setAccessibilityIdentifier:@"GroupsVCCreateRoomAlert"];
|
||||
[self presentViewController:currentAlert animated:YES completion:nil];
|
||||
}
|
||||
|
||||
//- (void)joinARoom
|
||||
//{
|
||||
// [currentAlert dismissViewControllerAnimated:NO completion:nil];
|
||||
//
|
||||
// __weak typeof(self) weakSelf = self;
|
||||
//
|
||||
// // Prompt the user to type a room id or room alias
|
||||
// currentAlert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"room_recents_join_room_title", @"Vector", nil)
|
||||
// message:NSLocalizedStringFromTable(@"room_recents_join_room_prompt", @"Vector", nil)
|
||||
// preferredStyle:UIAlertControllerStyleAlert];
|
||||
//
|
||||
// [currentAlert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
//
|
||||
// textField.secureTextEntry = NO;
|
||||
// textField.placeholder = nil;
|
||||
// textField.keyboardType = UIKeyboardTypeDefault;
|
||||
// }];
|
||||
//
|
||||
// [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
|
||||
// style:UIAlertActionStyleDefault
|
||||
// handler:^(UIAlertAction * action) {
|
||||
//
|
||||
// if (weakSelf)
|
||||
// {
|
||||
// typeof(self) self = weakSelf;
|
||||
// self->currentAlert = nil;
|
||||
// }
|
||||
//
|
||||
// }]];
|
||||
//
|
||||
// [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"join", @"Vector", nil)
|
||||
// style:UIAlertActionStyleDefault
|
||||
// handler:^(UIAlertAction * action) {
|
||||
//
|
||||
// if (weakSelf)
|
||||
// {
|
||||
// typeof(self) self = weakSelf;
|
||||
//
|
||||
// UITextField *textField = [self->currentAlert textFields].firstObject;
|
||||
// NSString *roomAliasOrId = textField.text;
|
||||
//
|
||||
// self->currentAlert = nil;
|
||||
//
|
||||
// [self.activityIndicator startAnimating];
|
||||
//
|
||||
// self->currentRequest = [self.mainSession joinRoom:textField.text success:^(MXRoom *room) {
|
||||
//
|
||||
// self->currentRequest = nil;
|
||||
// [self.activityIndicator stopAnimating];
|
||||
//
|
||||
// // Show the room
|
||||
// [[AppDelegate theDelegate] showRoom:room.state.roomId andEventId:nil withMatrixSession:self.mainSession];
|
||||
//
|
||||
// } failure:^(NSError *error) {
|
||||
//
|
||||
// NSLog(@"[RecentsViewController] Join joinARoom (%@) failed", roomAliasOrId);
|
||||
//
|
||||
// self->currentRequest = nil;
|
||||
// [self.activityIndicator stopAnimating];
|
||||
//
|
||||
// // Alert user
|
||||
// [[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
// }];
|
||||
// }
|
||||
//
|
||||
// }]];
|
||||
//
|
||||
// [currentAlert mxk_setAccessibilityIdentifier:@"RecentsVCJoinARoomAlert"];
|
||||
// [self presentViewController:currentAlert animated:YES completion:nil];
|
||||
//}
|
||||
|
||||
#pragma mark - Table view scrolling
|
||||
|
||||
- (void)scrollToTop:(BOOL)animated
|
||||
{
|
||||
[self.groupsTableView setContentOffset:CGPointMake(-self.groupsTableView.mxk_adjustedContentInset.left, -self.groupsTableView.mxk_adjustedContentInset.top) animated:animated];
|
||||
}
|
||||
|
||||
#pragma mark - MXKGroupListViewControllerDelegate
|
||||
|
||||
- (void)groupListViewController:(MXKGroupListViewController *)groupListViewController didSelectGroup:(MXGroup *)group inMatrixSession:(MXSession *)mxSession
|
||||
{
|
||||
// Open the room
|
||||
[[AppDelegate theDelegate].masterTabBarController selectGroup:group inMatrixSession:mxSession];
|
||||
}
|
||||
|
||||
#pragma mark - UISearchBarDelegate
|
||||
|
||||
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
|
||||
{
|
||||
if (searchBar == tableSearchBar)
|
||||
{
|
||||
[self hideSearchBar:NO];
|
||||
[self.groupsSearchBar becomeFirstResponder];
|
||||
return NO;
|
||||
}
|
||||
|
||||
return YES;
|
||||
|
||||
}
|
||||
|
||||
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
|
||||
{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
|
||||
[self.groupsSearchBar setShowsCancelButton:YES animated:NO];
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
|
||||
{
|
||||
[self.groupsSearchBar setShowsCancelButton:NO animated:NO];
|
||||
}
|
||||
|
||||
@end
|
Loading…
Reference in a new issue