vector-im/element-ios/issues/5009 - Moved files around, cleaned up imports and logs.

This commit is contained in:
Stefan Ceriu
2021-10-14 12:57:32 +03:00
parent 967987f807
commit 635ebea083
20 changed files with 76 additions and 88 deletions

View File

@@ -0,0 +1,21 @@
/*
Copyright 2017 Aram Sargsyan
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 UIKit;
@interface FallbackViewController : UIViewController
@end

View File

@@ -0,0 +1,45 @@
/*
Copyright 2017 Aram Sargsyan
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 "FallbackViewController.h"
#import "ThemeService.h"
#ifdef IS_SHARE_EXTENSION
#import "RiotShareExtension-Swift.h"
#else
#import "Riot-Swift.h"
#endif
@interface FallbackViewController ()
@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UIImageView *logoImageView;
@end
@implementation FallbackViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.view.backgroundColor = ThemeService.shared.theme.backgroundColor;
self.titleLabel.textColor = ThemeService.shared.theme.textSecondaryColor;
self.titleLabel.text = [VectorL10n shareExtensionAuthPrompt];
self.logoImageView.tintColor = ThemeService.shared.theme.tintColor;
}
@end

View File

@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="16097" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina5_5" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="FallbackViewController">
<connections>
<outlet property="logoImageView" destination="bAn-eK-zqg" id="BgG-CU-1PZ"/>
<outlet property="titleLabel" destination="9jC-d4-VqL" id="J3Y-oL-e29"/>
<outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
<rect key="frame" x="0.0" y="0.0" width="414" height="736"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="4cM-h2-CkH">
<rect key="frame" x="62" y="147.33333333333334" width="290" height="441.33333333333326"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="horizontal_logo" translatesAutoresizingMaskIntoConstraints="NO" id="bAn-eK-zqg">
<rect key="frame" x="40" y="0.0" width="210" height="413.66666666666669"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="252" verticalCompressionResistancePriority="752" text="loc:prompt" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9jC-d4-VqL">
<rect key="frame" x="0.0" y="413.66666666666663" width="290" height="27.666666666666686"/>
<fontDescription key="fontDescription" type="system" pointSize="23"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="bAn-eK-zqg" secondAttribute="trailing" constant="20" id="5V5-75-4Cp"/>
<constraint firstItem="bAn-eK-zqg" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="4cM-h2-CkH" secondAttribute="leading" constant="20" id="C2v-9e-YjU"/>
<constraint firstAttribute="trailing" secondItem="9jC-d4-VqL" secondAttribute="trailing" id="DrH-g4-EBL"/>
<constraint firstItem="bAn-eK-zqg" firstAttribute="top" secondItem="4cM-h2-CkH" secondAttribute="top" id="HKr-Vy-i8P"/>
<constraint firstAttribute="bottom" secondItem="9jC-d4-VqL" secondAttribute="bottom" id="LNV-E1-kCG"/>
<constraint firstItem="9jC-d4-VqL" firstAttribute="leading" secondItem="4cM-h2-CkH" secondAttribute="leading" id="RGz-7h-0dt"/>
<constraint firstItem="9jC-d4-VqL" firstAttribute="top" secondItem="bAn-eK-zqg" secondAttribute="bottom" id="bgG-1y-R8q"/>
<constraint firstItem="bAn-eK-zqg" firstAttribute="centerX" secondItem="4cM-h2-CkH" secondAttribute="centerX" id="iSg-iT-8cZ"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="4cM-h2-CkH" firstAttribute="width" secondItem="i5M-Pr-FkT" secondAttribute="width" multiplier="0.7" id="8Lf-tE-JWS"/>
<constraint firstItem="4cM-h2-CkH" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="QsS-hg-ULo"/>
<constraint firstItem="4cM-h2-CkH" firstAttribute="centerY" secondItem="i5M-Pr-FkT" secondAttribute="centerY" id="taY-I3-zBr"/>
<constraint firstItem="4cM-h2-CkH" firstAttribute="height" secondItem="i5M-Pr-FkT" secondAttribute="height" multiplier="0.6" id="uaL-do-Rlq"/>
</constraints>
<point key="canvasLocation" x="33.5" y="64.5"/>
</view>
</objects>
<resources>
<image name="horizontal_logo" width="210" height="120"/>
</resources>
</document>

View File

@@ -0,0 +1,23 @@
/*
Copyright 2017 Aram Sargsyan
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 RecentRoomTableViewCell : MXKRecentTableViewCell
+ (CGFloat)cellHeight;
@end

View File

@@ -0,0 +1,95 @@
/*
Copyright 2017 Aram Sargsyan
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 "RecentRoomTableViewCell.h"
#import "MXRoomSummary+Riot.h"
#import "ThemeService.h"
#ifdef IS_SHARE_EXTENSION
#import "RiotShareExtension-Swift.h"
#else
#import "Riot-Swift.h"
#endif
@interface RecentRoomTableViewCell ()
@property (weak, nonatomic) IBOutlet MXKImageView *avatarImageView;
@property (weak, nonatomic) IBOutlet UILabel *roomTitleLabel;
@property (weak, nonatomic) IBOutlet UIImageView *encryptedRoomIcon;
@end
@implementation RecentRoomTableViewCell
#pragma mark - MXKRecentTableViewCell
+ (UINib *)nib
{
// Check whether a nib file is available
NSBundle *mainBundle = [NSBundle bundleForClass:self.class];
NSString *path = [mainBundle pathForResource:NSStringFromClass([self class]) ofType:@"nib"];
if (path)
{
return [UINib nibWithNibName:NSStringFromClass([self class]) bundle:mainBundle];
}
return nil;
}
- (void)awakeFromNib
{
[super awakeFromNib];
self.roomTitleLabel.textColor = ThemeService.shared.theme.textPrimaryColor;
self.contentView.backgroundColor = ThemeService.shared.theme.backgroundColor;
}
- (void)layoutSubviews
{
[super layoutSubviews];
// Round room avatars
[self.avatarImageView.layer setCornerRadius:self.avatarImageView.frame.size.width / 2];
self.avatarImageView.clipsToBounds = YES;
}
- (void)render:(MXKCellData *)cellData
{
// Sanity check: accept only object of MXKRecentCellData classes or sub-classes
NSParameterAssert([cellData isKindOfClass:[MXKRecentCellData class]]);
roomCellData = (id<MXKRecentCellDataStoring>)cellData;
if (roomCellData)
{
[roomCellData.roomSummary setRoomAvatarImageIn:self.avatarImageView];
self.roomTitleLabel.text = roomCellData.roomSummary.displayname;
if (!self.roomTitleLabel.text.length)
{
self.roomTitleLabel.text = [MatrixKitL10n roomDisplaynameEmptyRoom];
}
self.encryptedRoomIcon.hidden = YES;
}
}
+ (CGFloat)cellHeight
{
return 74;
}
@end

View File

@@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" id="3kk-d5-Wja" customClass="RecentRoomTableViewCell">
<rect key="frame" x="0.0" y="0.0" width="600" height="74"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="3kk-d5-Wja" id="b83-aU-AJ3">
<rect key="frame" x="0.0" y="0.0" width="600" height="74"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HJd-Am-cCx" customClass="MXKImageView">
<rect key="frame" x="22" y="16" width="42" height="42"/>
<color key="backgroundColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.95686274510000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="AvatarImageView"/>
<constraints>
<constraint firstAttribute="width" secondItem="HJd-Am-cCx" secondAttribute="height" multiplier="1:1" id="CVW-Lp-6O4"/>
<constraint firstAttribute="width" constant="42" id="Xp0-5S-1wI"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vBS-iO-8H6">
<rect key="frame" x="78" y="27" width="33" height="20"/>
<accessibility key="accessibilityConfiguration" identifier="TitleLabel"/>
<constraints>
<constraint firstAttribute="height" constant="20" id="H21-1K-fGz"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<imageView hidden="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="e2e_verified" translatesAutoresizingMaskIntoConstraints="NO" id="hqD-YY-LWz">
<rect key="frame" x="58" y="45" width="11" height="13"/>
<accessibility key="accessibilityConfiguration" identifier="EncryptedRoomIcon"/>
<constraints>
<constraint firstAttribute="height" constant="13" id="8jQ-rK-hf2"/>
<constraint firstAttribute="width" constant="11" id="Mai-xD-TqV"/>
</constraints>
</imageView>
</subviews>
<constraints>
<constraint firstItem="HJd-Am-cCx" firstAttribute="leading" secondItem="b83-aU-AJ3" secondAttribute="leadingMargin" constant="6" id="4df-2f-865"/>
<constraint firstItem="hqD-YY-LWz" firstAttribute="top" secondItem="b83-aU-AJ3" secondAttribute="topMargin" constant="34" id="Cdm-v3-js8"/>
<constraint firstItem="hqD-YY-LWz" firstAttribute="leading" secondItem="b83-aU-AJ3" secondAttribute="leadingMargin" constant="42" id="UIE-13-LGw"/>
<constraint firstItem="HJd-Am-cCx" firstAttribute="centerY" secondItem="b83-aU-AJ3" secondAttribute="centerY" id="flh-LO-k3n"/>
<constraint firstItem="vBS-iO-8H6" firstAttribute="centerY" secondItem="b83-aU-AJ3" secondAttribute="centerY" id="ocY-mt-0n0"/>
<constraint firstAttribute="trailingMargin" relation="greaterThanOrEqual" secondItem="vBS-iO-8H6" secondAttribute="trailing" constant="15" id="qqy-zs-Ccy"/>
<constraint firstItem="vBS-iO-8H6" firstAttribute="leading" secondItem="HJd-Am-cCx" secondAttribute="trailing" constant="14" id="quv-47-R9n"/>
</constraints>
</tableViewCellContentView>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="RoomTableViewCell"/>
<connections>
<outlet property="avatarImageView" destination="HJd-Am-cCx" id="Mv2-Kb-aG4"/>
<outlet property="encryptedRoomIcon" destination="hqD-YY-LWz" id="Ikp-Sf-Vlc"/>
<outlet property="roomTitleLabel" destination="vBS-iO-8H6" id="0J9-p3-Lzx"/>
</connections>
<point key="canvasLocation" x="-53" y="-43"/>
</tableViewCell>
</objects>
<resources>
<image name="e2e_verified" width="10" height="12"/>
</resources>
</document>

View File

@@ -0,0 +1,25 @@
/*
Copyright 2017 Aram Sargsyan
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 <UIKit/UIKit.h>
#import "MXRoom+Riot.h"
#import "ShareDataSource.h"
@class RoomsListViewController;
@interface RoomsListViewController : MXKRecentListViewController
@end

View File

@@ -0,0 +1,227 @@
/*
Copyright 2017 Aram Sargsyan
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>
#import "RoomsListViewController.h"
#import "RecentRoomTableViewCell.h"
#import "RecentCellData.h"
#import "ThemeService.h"
#ifdef IS_SHARE_EXTENSION
#import "RiotShareExtension-Swift.h"
#else
#import "Riot-Swift.h"
#endif
@interface RoomsListViewController ()
// The fake search bar displayed at the top of the recents table. We switch on the actual search bar (self.recentsSearchBar)
// when the user selects it.
@property (nonatomic) UISearchBar *tableSearchBar;
@end
@implementation RoomsListViewController
#pragma mark - Class methods
+ (UINib *)nib
{
return [UINib nibWithNibName:NSStringFromClass([RoomsListViewController class])
bundle:[NSBundle bundleForClass:[RoomsListViewController class]]];
}
+ (instancetype)recentListViewController
{
return [[[self class] alloc] initWithNibName:NSStringFromClass([RoomsListViewController class])
bundle:[NSBundle bundleForClass:[RoomsListViewController class]]];
}
- (void)finalizeInit
{
[super finalizeInit];
self.enableBarButtonSearch = NO;
// Create the fake search bar
_tableSearchBar = [[UISearchBar alloc] initWithFrame:CGRectMake(0, 0, 600, 44)];
_tableSearchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
_tableSearchBar.showsCancelButton = NO;
_tableSearchBar.searchBarStyle = UISearchBarStyleMinimal;
_tableSearchBar.placeholder = [VectorL10n searchDefaultPlaceholder];
_tableSearchBar.delegate = self;
}
#pragma mark - Lifecycle
- (void)viewDidLoad
{
[super viewDidLoad];
self.recentsTableView.backgroundColor = ThemeService.shared.theme.backgroundColor;
[self.recentsTableView registerNib:[RecentRoomTableViewCell nib] forCellReuseIdentifier:[RecentRoomTableViewCell defaultReuseIdentifier]];
[self configureSearchBar];
}
- (void)destroy
{
// Release the room data source
[self.dataSource destroy];
[super destroy];
}
#pragma mark - Views
- (void)configureSearchBar
{
self.recentsSearchBar.autocapitalizationType = UITextAutocapitalizationTypeNone;
self.recentsSearchBar.searchBarStyle = UISearchBarStyleMinimal;
self.recentsSearchBar.placeholder = [VectorL10n searchDefaultPlaceholder];
self.recentsSearchBar.tintColor = ThemeService.shared.theme.tintColor;
self.recentsSearchBar.backgroundColor = ThemeService.shared.theme.baseColor;
_tableSearchBar.tintColor = self.recentsSearchBar.tintColor;
}
#pragma mark - Override MXKRecentListViewController
- (void)refreshRecentsTable
{
[super refreshRecentsTable];
// Check conditions to display the fake search bar into the table header
if (self.recentsSearchBar.isHidden && self.recentsTableView.tableHeaderView == nil)
{
// Add the search bar by showing it by default.
self.recentsTableView.tableHeaderView = _tableSearchBar;
}
}
- (void)hideSearchBar:(BOOL)hidden
{
[super hideSearchBar:hidden];
if (!hidden)
{
// Remove the fake table header view if any
self.recentsTableView.tableHeaderView = nil;
self.recentsTableView.contentInset = UIEdgeInsetsZero;
}
}
- (void)setKeyboardHeight:(CGFloat)keyboardHeight
{
// Bypass inherited keyboard handling to fix layout when searching.
// There are no sticky headers to worry about updating.
return;
}
#pragma mark - UITableViewDelegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [RecentRoomTableViewCell cellHeight];
}
#pragma mark - MXKDataSourceDelegate
- (Class<MXKCellRendering>)cellViewClassForCellData:(MXKCellData*)cellData
{
if ([cellData isKindOfClass:[RecentCellData class]])
{
return [RecentRoomTableViewCell class];
}
return nil;
}
- (NSString *)cellReuseIdentifierForCellData:(MXKCellData*)cellData
{
if ([cellData isKindOfClass:[MXKRecentCellData class]])
{
return [RecentRoomTableViewCell defaultReuseIdentifier];
}
return nil;
}
#pragma mark - UISearchBarDelegate
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
NSArray *patterns = nil;
if (searchText.length)
{
patterns = @[searchText];
}
[self.dataSource searchWithPatterns:patterns];
}
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
if (searchBar == _tableSearchBar)
{
[self hideSearchBar:NO];
[self.recentsSearchBar becomeFirstResponder];
return NO;
}
return YES;
}
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
dispatch_async(dispatch_get_main_queue(), ^{
[self.recentsSearchBar setShowsCancelButton:YES animated:NO];
});
}
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
[self.recentsSearchBar setShowsCancelButton:NO animated:NO];
}
#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
[super scrollViewDidScroll:scrollView];
if (scrollView == self.recentsTableView)
{
if (!self.recentsSearchBar.isHidden)
{
if (!self.recentsSearchBar.text.length && (scrollView.contentOffset.y + scrollView.adjustedContentInset.top > self.recentsSearchBar.frame.size.height))
{
// Hide the search bar
[self hideSearchBar:YES];
// Refresh display
[self refreshRecentsTable];
}
// Dismiss the keyboard when scrolling to match the behaviour of the main app.
if (self.recentsSearchBar.isFirstResponder)
{
[self.recentsSearchBar resignFirstResponder];
}
}
}
}
@end

View File

@@ -0,0 +1,52 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MXKRecentListViewController">
<connections>
<outlet property="recentsSearchBar" destination="Zbr-9e-VZh" id="AvH-q6-dOM"/>
<outlet property="recentsSearchBarHeightConstraint" destination="jCU-cq-2OA" id="w76-xb-0xq"/>
<outlet property="recentsSearchBarTopConstraint" destination="aRg-Nz-enq" id="gI4-54-oEm"/>
<outlet property="recentsTableView" destination="orV-HH-88x" id="lgA-2k-pXJ"/>
<outlet property="recentsTableViewBottomConstraint" destination="m4x-32-odR" id="8JQ-c9-1Tq"/>
<outlet property="view" destination="iN0-l3-epB" id="NUQ-LI-M61"/>
</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>
<searchBar contentMode="redraw" searchBarStyle="minimal" showsCancelButton="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Zbr-9e-VZh">
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
<constraints>
<constraint firstAttribute="height" constant="44" id="jCU-cq-2OA"/>
</constraints>
<textInputTraits key="textInputTraits" returnKeyType="done"/>
<connections>
<outlet property="delegate" destination="-1" id="ejZ-kN-jKv"/>
</connections>
</searchBar>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" keyboardDismissMode="interactive" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="22" sectionFooterHeight="22" translatesAutoresizingMaskIntoConstraints="NO" id="orV-HH-88x">
<rect key="frame" x="0.0" y="44" width="375" height="623"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</tableView>
</subviews>
<constraints>
<constraint firstItem="orV-HH-88x" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="NaR-eJ-WMj"/>
<constraint firstItem="Zbr-9e-VZh" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="aRg-Nz-enq"/>
<constraint firstItem="Zbr-9e-VZh" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="fty-XB-tTr"/>
<constraint firstItem="orV-HH-88x" firstAttribute="top" secondItem="Zbr-9e-VZh" secondAttribute="bottom" id="lBa-P2-Vnx"/>
<constraint firstAttribute="bottom" secondItem="orV-HH-88x" secondAttribute="bottom" id="m4x-32-odR"/>
<constraint firstAttribute="trailing" secondItem="Zbr-9e-VZh" secondAttribute="trailing" id="rKb-TZ-sap"/>
<constraint firstAttribute="trailing" secondItem="orV-HH-88x" secondAttribute="trailing" id="yBp-63-kZi"/>
</constraints>
<point key="canvasLocation" x="130" y="89"/>
</view>
</objects>
</document>

View File

@@ -0,0 +1,40 @@
/*
Copyright 2017 Aram Sargsyan
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>
typedef NS_ENUM(NSInteger, ShareDataSourceMode)
{
DataSourceModePeople,
DataSourceModeRooms
};
@interface ShareDataSource : MXKRecentsDataSource
- (instancetype)initWithMode:(ShareDataSourceMode)dataSourceMode
fileStore:(MXFileStore *)fileStore
credentials:(MXCredentials *)credentials;
/**
Returns the cell data at the index path
@param indexPath the index of the cell
@return the MXKRecentCellData instance if it exists
*/
- (MXKRecentCellData *)cellDataAtIndexPath:(NSIndexPath *)indexPath;
@end

View File

@@ -0,0 +1,174 @@
/*
Copyright 2017 Aram Sargsyan
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 "ShareDataSource.h"
#import "RecentRoomTableViewCell.h"
@interface ShareDataSource ()
@property (nonatomic, assign, readonly) ShareDataSourceMode dataSourceMode;
@property (nonatomic, strong, readonly) MXFileStore *fileStore;
@property (nonatomic, strong, readonly) MXCredentials *credentials;
@property NSArray <MXKRecentCellData *> *recentCellDatas;
@property NSMutableArray <MXKRecentCellData *> *visibleRoomCellDatas;
@end
@implementation ShareDataSource
- (instancetype)initWithMode:(ShareDataSourceMode)dataSourceMode
fileStore:(MXFileStore *)fileStore
credentials:(MXCredentials *)credentials
{
if (self = [super init])
{
_dataSourceMode = dataSourceMode;
_fileStore = fileStore;
_credentials = credentials;
[self loadCellData];
}
return self;
}
- (void)destroy
{
[super destroy];
_recentCellDatas = nil;
_visibleRoomCellDatas = nil;
}
#pragma mark - Private
- (void)loadCellData
{
[self.fileStore asyncRoomsSummaries:^(NSArray<MXRoomSummary *> *roomsSummaries) {
NSMutableArray *cellData = [NSMutableArray array];
// Add a fake matrix session to each room summary to provide it a REST client (used to handle correctly the room avatar).
MXSession *session = [[MXSession alloc] initWithMatrixRestClient:[[MXRestClient alloc] initWithCredentials:self.credentials andOnUnrecognizedCertificateBlock:nil]];
for (MXRoomSummary *roomSummary in roomsSummaries)
{
if (!roomSummary.hiddenFromUser && ((self.dataSourceMode == DataSourceModeRooms) ^ roomSummary.isDirect))
{
[roomSummary setMatrixSession:session];
MXKRecentCellData *recentCellData = [[MXKRecentCellData alloc] initWithRoomSummary:roomSummary andRecentListDataSource:nil];
[cellData addObject:recentCellData];
}
}
// Sort rooms according to their last messages (most recent first)
NSComparator comparator = ^NSComparisonResult(MXKRecentCellData *recentCellData1, MXKRecentCellData *recentCellData2) {
return [recentCellData1.roomSummary.lastMessage compareOriginServerTs:recentCellData2.roomSummary.lastMessage];
};
[cellData sortUsingComparator:comparator];
self.recentCellDatas = cellData;
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate dataSource:self didCellChange:nil];
});
} failure:^(NSError * _Nonnull error) {
MXLogDebug(@"[ShareDataSource failed to get room summaries]");
}];
}
#pragma mark - MXKRecentsDataSource
- (MXKRecentCellData *)cellDataAtIndexPath:(NSIndexPath *)indexPath
{
if (self.visibleRoomCellDatas)
{
return self.visibleRoomCellDatas[indexPath.row];
}
return self.recentCellDatas[indexPath.row];
}
- (void)searchWithPatterns:(NSArray *)patternsList
{
if (self.visibleRoomCellDatas)
{
[self.visibleRoomCellDatas removeAllObjects];
}
else
{
self.visibleRoomCellDatas = [NSMutableArray arrayWithCapacity:self.recentCellDatas.count];
}
if (patternsList.count)
{
for (MXKRecentCellData *cellData in self.recentCellDatas)
{
for (NSString* pattern in patternsList)
{
if (cellData.roomSummary.displayname && [cellData.roomSummary.displayname rangeOfString:pattern options:NSCaseInsensitiveSearch].location != NSNotFound)
{
[self.visibleRoomCellDatas addObject:cellData];
break;
}
}
}
}
else
{
self.visibleRoomCellDatas = nil;
}
[self.delegate dataSource:self didCellChange:nil];
}
#pragma mark - UITableViewDataSource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (self.visibleRoomCellDatas)
{
return self.visibleRoomCellDatas.count;
}
return self.recentCellDatas.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
RecentRoomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[RecentRoomTableViewCell defaultReuseIdentifier]];
[cell render:[self cellDataAtIndexPath:indexPath]];
return cell;
}
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
@end

View File

@@ -0,0 +1,41 @@
/*
Copyright 2017 Aram Sargsyan
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>
typedef NS_ENUM(NSUInteger, ShareManagerResult) {
ShareManagerResultFinished,
ShareManagerResultCancelled,
ShareManagerResultFailed
};
@interface ShareManager : NSObject
@property (nonatomic, copy) void (^completionCallback)(ShareManagerResult);
- (instancetype)initWithShareExtensionContext:(NSExtensionContext *)shareExtensionContext
extensionItems:(NSArray<NSExtensionItem *> *)extensionItems;
- (UIViewController *)mainViewController;
@end
@interface NSItemProvider (ShareManager)
@property BOOL isLoaded;
@end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
/*
Copyright 2017 Aram Sargsyan
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 UIKit;
@class ShareViewController;
@class ShareDataSource;
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSUInteger, ShareViewControllerType) {
ShareViewControllerTypeSend,
ShareViewControllerTypeForward
};
typedef NS_ENUM(NSUInteger, ShareViewControllerAccountState) {
ShareViewControllerAccountStateConfigured,
ShareViewControllerAccountStateNotConfigured
};
@protocol ShareViewControllerDelegate <NSObject>
- (void)shareViewControllerDidRequestShare:(ShareViewController *)shareViewController
forRoomIdentifier:(NSString *)roomIdentifier;
- (void)shareViewControllerDidRequestDismissal:(ShareViewController *)shareViewController;
@end
@interface ShareViewController : UIViewController
@property (nonatomic, weak, nullable) id<ShareViewControllerDelegate> delegate;
- (instancetype)initWithType:(ShareViewControllerType)type
currentState:(ShareViewControllerAccountState)state;
- (void)configureWithState:(ShareViewControllerAccountState)state
roomDataSource:(nullable ShareDataSource *)roomDataSource
peopleDataSource:(nullable ShareDataSource *)peopleDataSource;
- (void)showProgressIndicator;
- (void)setProgress:(CGFloat)progress;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,204 @@
/*
Copyright 2017 Aram Sargsyan
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 "ShareViewController.h"
#import "SegmentedViewController.h"
#import "RoomsListViewController.h"
#import "FallbackViewController.h"
#import "ShareDataSource.h"
#import "ThemeService.h"
#ifdef IS_SHARE_EXTENSION
#import "RiotShareExtension-Swift.h"
#else
#import "Riot-Swift.h"
#endif
@interface ShareViewController () <MXKRecentListViewControllerDelegate>
@property (nonatomic, assign, readonly) ShareViewControllerType type;
@property (nonatomic, assign) ShareViewControllerAccountState state;
@property (nonatomic, strong) ShareDataSource *roomDataSource;
@property (nonatomic, strong) ShareDataSource *peopleDataSource;
@property (nonatomic, weak) IBOutlet UIView *masterContainerView;
@property (nonatomic, weak) IBOutlet UIButton *cancelButton;
@property (nonatomic, weak) IBOutlet UILabel *titleLabel;
@property (nonatomic, weak) IBOutlet UIButton *shareButton;
@property (nonatomic, weak) IBOutlet UIView *contentView;
@property (nonatomic, strong) SegmentedViewController *segmentedViewController;
@property (nonatomic, strong) MXKPieChartHUD *hudView;
@end
@implementation ShareViewController
- (instancetype)initWithType:(ShareViewControllerType)type
currentState:(ShareViewControllerAccountState)state
{
if (self = [super init])
{
_type = type;
_state = state;
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.masterContainerView setBackgroundColor:ThemeService.shared.theme.baseColor];
[self.masterContainerView.layer setCornerRadius:7.0];
[self.titleLabel setTextColor:ThemeService.shared.theme.textPrimaryColor];
[self.cancelButton setTintColor:ThemeService.shared.theme.tintColor];
[self.cancelButton setTitle:[VectorL10n cancel] forState:UIControlStateNormal];
[self.shareButton setTintColor:ThemeService.shared.theme.tintColor];
[self configureWithState:self.state roomDataSource:self.roomDataSource peopleDataSource:self.peopleDataSource];
}
- (void)configureWithState:(ShareViewControllerAccountState)state
roomDataSource:(ShareDataSource *)roomDataSource
peopleDataSource:(ShareDataSource *)peopleDataSource
{
self.state = state;
self.roomDataSource = roomDataSource;
self.peopleDataSource = peopleDataSource;
if (!self.isViewLoaded) {
return;
}
[self configureViews];
}
- (void)showProgressIndicator
{
if (!self.hudView)
{
self.parentViewController.view.userInteractionEnabled = NO;
self.hudView = [MXKPieChartHUD showLoadingHudOnView:self.view WithMessage:[VectorL10n sending]];
[self.hudView setProgress:0.0];
}
}
- (void)setProgress:(CGFloat)progress
{
[self.hudView setProgress:progress];
}
#pragma mark - MXKRecentListViewControllerDelegate
- (void)recentListViewController:(MXKRecentListViewController *)recentListViewController
didSelectRoom:(NSString *)roomId
inMatrixSession:(MXSession *)mxSession
{
[self.delegate shareViewControllerDidRequestShare:self forRoomIdentifier:roomId];
}
- (void)recentListViewController:(MXKRecentListViewController *)recentListViewController
didSelectSuggestedRoom:(MXSpaceChildInfo *)childInfo
{
[self.delegate shareViewControllerDidRequestShare:self forRoomIdentifier:childInfo.childRoomId];
}
#pragma mark - Private
- (void)configureViews
{
[self resetContentView];
if (self.state == ShareViewControllerAccountStateConfigured)
{
self.titleLabel.text = [VectorL10n sendTo:@""];
[self.shareButton setTitle:[VectorL10n roomEventActionForward] forState:UIControlStateNormal];
[self configureSegmentedViewController];
}
else
{
self.titleLabel.text = [AppInfo.current displayName];
[self configureFallbackViewController];
}
}
- (void)configureSegmentedViewController
{
RoomsListViewController *roomsViewController = [RoomsListViewController recentListViewController];
[roomsViewController displayList:self.roomDataSource];
[roomsViewController setDelegate:self];
RoomsListViewController *peopleViewController = [RoomsListViewController recentListViewController];
[peopleViewController setDelegate:self];
[peopleViewController displayList:self.peopleDataSource];
self.segmentedViewController = [SegmentedViewController segmentedViewController];
[self.segmentedViewController initWithTitles:@[[VectorL10n titleRooms], [VectorL10n titlePeople]]
viewControllers:@[roomsViewController, peopleViewController] defaultSelected:0];
[self addChildViewController:self.segmentedViewController];
[self.contentView vc_addSubViewMatchingParent:self.segmentedViewController.view];
[self.segmentedViewController didMoveToParentViewController:self];
}
- (void)configureFallbackViewController
{
FallbackViewController *fallbackVC = [FallbackViewController new];
[self addChildViewController:fallbackVC];
[self.contentView vc_addSubViewMatchingParent:fallbackVC.view];
[fallbackVC didMoveToParentViewController:self];
}
- (void)resetContentView
{
NSArray *subviews = self.contentView.subviews;
for (UIView *subview in subviews)
{
[subview removeFromSuperview];
}
if (self.segmentedViewController)
{
[self.segmentedViewController removeFromParentViewController];
[self.segmentedViewController destroy];
self.segmentedViewController = nil;
}
}
#pragma mark - Actions
- (IBAction)onCancelButtonTap:(UIButton *)sender
{
[self.delegate shareViewControllerDidRequestDismissal:self];
}
- (IBAction)onShareButtonTap:(UIButton *)sender
{
}
@end

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="18122" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="18093"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ShareViewController">
<connections>
<outlet property="cancelButton" destination="xhU-Rh-IgE" id="o8b-Gf-ahK"/>
<outlet property="contentView" destination="jAn-9F-DlU" id="NWV-TS-MGK"/>
<outlet property="masterContainerView" destination="oax-z3-vv0" id="KvN-B4-ZkF"/>
<outlet property="shareButton" destination="otu-Ag-Bwo" id="IeY-fj-5zI"/>
<outlet property="titleLabel" destination="BQ5-AW-rsV" id="qm6-T7-3LB"/>
<outlet property="view" destination="Bej-An-0PZ" id="sgO-5Q-y1c"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view opaque="NO" contentMode="scaleToFill" id="Bej-An-0PZ">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="oax-z3-vv0" userLabel="Master Container View">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7Ye-Ni-Nsr" userLabel="Title Container View">
<rect key="frame" x="0.0" y="0.0" width="375" height="57"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BQ5-AW-rsV" userLabel="Title Label">
<rect key="frame" x="166" y="18.5" width="43.5" height="20.5"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="17"/>
<color key="textColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="xhU-Rh-IgE">
<rect key="frame" x="16" y="12" width="53" height="33"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<state key="normal" title="Cancel"/>
<connections>
<action selector="onCancelButtonTap:" destination="-1" eventType="touchUpInside" id="47D-fR-8PQ"/>
</connections>
</button>
<button hidden="YES" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="otu-Ag-Bwo">
<rect key="frame" x="315" y="12" width="44" height="33"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<state key="normal" title="Share"/>
<connections>
<action selector="onShareButtonTap:" destination="-1" eventType="touchUpInside" id="DzX-aj-yPy"/>
</connections>
</button>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="BQ5-AW-rsV" firstAttribute="centerY" secondItem="7Ye-Ni-Nsr" secondAttribute="centerY" id="1d9-JD-CVF"/>
<constraint firstItem="xhU-Rh-IgE" firstAttribute="leading" secondItem="7Ye-Ni-Nsr" secondAttribute="leading" constant="16" id="EjM-0b-dot"/>
<constraint firstAttribute="trailing" secondItem="otu-Ag-Bwo" secondAttribute="trailing" constant="16" id="Mth-c3-3Th"/>
<constraint firstItem="xhU-Rh-IgE" firstAttribute="top" secondItem="7Ye-Ni-Nsr" secondAttribute="top" constant="12" id="T8c-d6-B7A"/>
<constraint firstItem="otu-Ag-Bwo" firstAttribute="centerY" secondItem="BQ5-AW-rsV" secondAttribute="centerY" id="YwS-RW-o1i"/>
<constraint firstItem="BQ5-AW-rsV" firstAttribute="centerX" secondItem="7Ye-Ni-Nsr" secondAttribute="centerX" id="ZDz-XD-buD"/>
<constraint firstItem="otu-Ag-Bwo" firstAttribute="top" secondItem="7Ye-Ni-Nsr" secondAttribute="top" constant="12" id="c8g-rh-ucO"/>
<constraint firstItem="xhU-Rh-IgE" firstAttribute="centerY" secondItem="BQ5-AW-rsV" secondAttribute="centerY" id="eW9-wn-0Lc"/>
<constraint firstAttribute="bottom" secondItem="otu-Ag-Bwo" secondAttribute="bottom" constant="12" id="l6n-lP-CUn"/>
<constraint firstAttribute="bottom" secondItem="xhU-Rh-IgE" secondAttribute="bottom" constant="12" id="tHm-CS-WsP"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jAn-9F-DlU">
<rect key="frame" x="0.0" y="57" width="375" height="610"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="jAn-9F-DlU" secondAttribute="trailing" id="1ce-br-3uU"/>
<constraint firstItem="jAn-9F-DlU" firstAttribute="top" secondItem="7Ye-Ni-Nsr" secondAttribute="bottom" id="1zc-qn-eFO"/>
<constraint firstItem="7Ye-Ni-Nsr" firstAttribute="leading" secondItem="oax-z3-vv0" secondAttribute="leading" id="RTO-at-ZR0"/>
<constraint firstAttribute="trailing" secondItem="7Ye-Ni-Nsr" secondAttribute="trailing" id="RtW-o3-kOS"/>
<constraint firstItem="7Ye-Ni-Nsr" firstAttribute="top" secondItem="oax-z3-vv0" secondAttribute="top" id="YIj-72-BeJ"/>
<constraint firstItem="jAn-9F-DlU" firstAttribute="leading" secondItem="oax-z3-vv0" secondAttribute="leading" id="hju-02-xMk"/>
<constraint firstAttribute="bottom" secondItem="jAn-9F-DlU" secondAttribute="bottom" id="rDT-Zr-eUB"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="oax-z3-vv0" secondAttribute="trailing" id="VUX-RZ-Jke"/>
<constraint firstItem="oax-z3-vv0" firstAttribute="leading" secondItem="Bej-An-0PZ" secondAttribute="leading" id="h8V-gU-iRt"/>
<constraint firstAttribute="bottom" secondItem="oax-z3-vv0" secondAttribute="bottom" id="qnO-IP-fp3"/>
<constraint firstItem="oax-z3-vv0" firstAttribute="top" secondItem="Bej-An-0PZ" secondAttribute="top" id="vXO-uW-nFN"/>
</constraints>
<point key="canvasLocation" x="39.5" y="89.5"/>
</view>
</objects>
</document>