mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-20 00:24:43 +02:00
Merge MatrixKit develop with commit hash: b85b736313bec0592bd1cabc68035d97f5331137
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
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 <MatrixSDK/MatrixSDK.h>
|
||||
|
||||
#import "MXKView.h"
|
||||
|
||||
/**
|
||||
MXKDeviceView class may be used to display the information of a user's device.
|
||||
The displayed device may be renamed or removed.
|
||||
*/
|
||||
|
||||
@class MXKDeviceView;
|
||||
@protocol MXKDeviceViewDelegate <NSObject>
|
||||
|
||||
/**
|
||||
Tells the delegate that an alert must be presented.
|
||||
|
||||
@param deviceView the device view.
|
||||
@param alert the alert to present.
|
||||
*/
|
||||
- (void)deviceView:(MXKDeviceView*)deviceView presentAlertController:(UIAlertController*)alert;
|
||||
|
||||
@optional
|
||||
|
||||
/**
|
||||
Tells the delegate to dismiss the device view.
|
||||
|
||||
@param deviceView the device view.
|
||||
@param isUpdated tell whether the device was updated (renamed, removed...).
|
||||
*/
|
||||
- (void)dismissDeviceView:(MXKDeviceView*)deviceView didUpdate:(BOOL)isUpdated;
|
||||
|
||||
@end
|
||||
|
||||
@interface MXKDeviceView : MXKView <UIGestureRecognizerDelegate>
|
||||
|
||||
@property (weak, nonatomic) IBOutlet UIView *bgView;
|
||||
@property (weak, nonatomic) IBOutlet UIView *containerView;
|
||||
@property (weak, nonatomic) IBOutlet UITextView *textView;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *cancelButton;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *renameButton;
|
||||
@property (weak, nonatomic) IBOutlet UIButton *deleteButton;
|
||||
@property (weak, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
|
||||
|
||||
/**
|
||||
Initialize a device view to display the information of a user's device.
|
||||
|
||||
@param device a user's device.
|
||||
@param session the matrix session.
|
||||
@return the newly created instance.
|
||||
*/
|
||||
- (instancetype)initWithDevice:(MXDevice*)device andMatrixSession:(MXSession*)session;
|
||||
|
||||
/**
|
||||
The delegate.
|
||||
*/
|
||||
@property (nonatomic, weak) id<MXKDeviceViewDelegate> delegate;
|
||||
|
||||
/**
|
||||
The default text color in the text view. [UIColor blackColor] by default.
|
||||
*/
|
||||
@property (nonatomic) UIColor *defaultTextColor;
|
||||
|
||||
/**
|
||||
Action registered on 'UIControlEventTouchUpInside' event for each UIButton instance.
|
||||
*/
|
||||
- (IBAction)onButtonPressed:(id)sender;
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,481 @@
|
||||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2018 New Vector 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 "MXKDeviceView.h"
|
||||
|
||||
#import "NSBundle+MatrixKit.h"
|
||||
|
||||
#import "MXKConstants.h"
|
||||
|
||||
#import "MXKSwiftHeader.h"
|
||||
|
||||
static NSAttributedString *verticalWhitespace = nil;
|
||||
|
||||
@interface MXKDeviceView ()
|
||||
{
|
||||
/**
|
||||
The displayed device
|
||||
*/
|
||||
MXDevice *mxDevice;
|
||||
|
||||
/**
|
||||
The matrix session.
|
||||
*/
|
||||
MXSession *mxSession;
|
||||
|
||||
/**
|
||||
The current alert
|
||||
*/
|
||||
UIAlertController *currentAlert;
|
||||
|
||||
/**
|
||||
Current request in progress.
|
||||
*/
|
||||
MXHTTPOperation *mxCurrentOperation;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation MXKDeviceView
|
||||
|
||||
+ (UINib *)nib
|
||||
{
|
||||
// Check whether a nib file is available
|
||||
NSBundle *mainBundle = [NSBundle mxk_bundleForClass:self.class];
|
||||
|
||||
NSString *path = [mainBundle pathForResource:NSStringFromClass([self class]) ofType:@"nib"];
|
||||
if (path)
|
||||
{
|
||||
return [UINib nibWithNibName:NSStringFromClass([self class]) bundle:mainBundle];
|
||||
}
|
||||
return [UINib nibWithNibName:NSStringFromClass([MXKDeviceView class]) bundle:[NSBundle mxk_bundleForClass:[MXKDeviceView class]]];
|
||||
}
|
||||
|
||||
- (void)awakeFromNib
|
||||
{
|
||||
[super awakeFromNib];
|
||||
|
||||
// Add tap recognizer to discard the view on bg view tap
|
||||
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onBgViewTap:)];
|
||||
[tap setNumberOfTouchesRequired:1];
|
||||
[tap setNumberOfTapsRequired:1];
|
||||
[tap setDelegate:self];
|
||||
[self.bgView addGestureRecognizer:tap];
|
||||
|
||||
// Localize string
|
||||
[_cancelButton setTitle:[MatrixKitL10n ok] forState:UIControlStateNormal];
|
||||
[_cancelButton setTitle:[MatrixKitL10n ok] forState:UIControlStateHighlighted];
|
||||
|
||||
[_renameButton setTitle:[MatrixKitL10n rename] forState:UIControlStateNormal];
|
||||
[_renameButton setTitle:[MatrixKitL10n rename] forState:UIControlStateHighlighted];
|
||||
|
||||
[_deleteButton setTitle:[MatrixKitL10n delete] forState:UIControlStateNormal];
|
||||
[_deleteButton setTitle:[MatrixKitL10n delete] forState:UIControlStateHighlighted];
|
||||
}
|
||||
|
||||
- (void)layoutSubviews
|
||||
{
|
||||
[super layoutSubviews];
|
||||
|
||||
// Scroll to the top the text view content
|
||||
self.textView.contentOffset = CGPointZero;
|
||||
}
|
||||
|
||||
#pragma mark - Override MXKView
|
||||
|
||||
-(void)customizeViewRendering
|
||||
{
|
||||
[super customizeViewRendering];
|
||||
|
||||
_defaultTextColor = [UIColor blackColor];
|
||||
|
||||
// Add shadow on added view
|
||||
_containerView.layer.cornerRadius = 5;
|
||||
_containerView.layer.shadowOffset = CGSizeMake(0, 1);
|
||||
_containerView.layer.shadowOpacity = 0.5f;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)removeFromSuperviewDidUpdate:(BOOL)isUpdated
|
||||
{
|
||||
if (currentAlert)
|
||||
{
|
||||
[currentAlert dismissViewControllerAnimated:NO completion:nil];
|
||||
currentAlert = nil;
|
||||
}
|
||||
|
||||
if (mxCurrentOperation)
|
||||
{
|
||||
[mxCurrentOperation cancel];
|
||||
mxCurrentOperation = nil;
|
||||
}
|
||||
|
||||
if (self.delegate && [self.delegate respondsToSelector:@selector(dismissDeviceView:didUpdate:)])
|
||||
{
|
||||
[self.delegate dismissDeviceView:self didUpdate:isUpdated];
|
||||
}
|
||||
else
|
||||
{
|
||||
[self removeFromSuperview];
|
||||
}
|
||||
}
|
||||
|
||||
- (instancetype)initWithDevice:(MXDevice*)device andMatrixSession:(MXSession*)session
|
||||
{
|
||||
self = [[[self class] nib] instantiateWithOwner:nil options:nil].firstObject;
|
||||
if (self)
|
||||
{
|
||||
mxDevice = device;
|
||||
mxSession = session;
|
||||
|
||||
[self setTranslatesAutoresizingMaskIntoConstraints: NO];
|
||||
|
||||
if (mxDevice)
|
||||
{
|
||||
// Device information
|
||||
NSMutableAttributedString *deviceInformationString = [[NSMutableAttributedString alloc]
|
||||
initWithString:[MatrixKitL10n deviceDetailsTitle]
|
||||
attributes:@{NSForegroundColorAttributeName : _defaultTextColor,
|
||||
NSFontAttributeName: [UIFont boldSystemFontOfSize:15]}];
|
||||
[deviceInformationString appendAttributedString:[MXKDeviceView verticalWhitespace]];
|
||||
|
||||
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
|
||||
initWithString:[MatrixKitL10n deviceDetailsName]
|
||||
attributes:@{NSForegroundColorAttributeName : _defaultTextColor,
|
||||
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}]];
|
||||
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
|
||||
initWithString:device.displayName.length ? device.displayName : @""
|
||||
attributes:@{NSForegroundColorAttributeName : _defaultTextColor,
|
||||
NSFontAttributeName: [UIFont systemFontOfSize:14]}]];
|
||||
[deviceInformationString appendAttributedString:[MXKDeviceView verticalWhitespace]];
|
||||
|
||||
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
|
||||
initWithString:[MatrixKitL10n deviceDetailsIdentifier]
|
||||
attributes:@{NSForegroundColorAttributeName : _defaultTextColor,
|
||||
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}]];
|
||||
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
|
||||
initWithString:device.deviceId
|
||||
attributes:@{NSForegroundColorAttributeName : _defaultTextColor,
|
||||
NSFontAttributeName: [UIFont systemFontOfSize:14]}]];
|
||||
[deviceInformationString appendAttributedString:[MXKDeviceView verticalWhitespace]];
|
||||
|
||||
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
|
||||
initWithString:[MatrixKitL10n deviceDetailsLastSeen]
|
||||
attributes:@{NSForegroundColorAttributeName : _defaultTextColor,
|
||||
NSFontAttributeName: [UIFont boldSystemFontOfSize:14]}]];
|
||||
|
||||
NSDate *lastSeenDate = [NSDate dateWithTimeIntervalSince1970:device.lastSeenTs/1000];
|
||||
|
||||
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
|
||||
[dateFormatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:[[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]]];
|
||||
[dateFormatter setDateStyle:NSDateFormatterShortStyle];
|
||||
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
|
||||
[dateFormatter setFormatterBehavior:NSDateFormatterBehavior10_4];
|
||||
|
||||
NSString *lastSeen = [MatrixKitL10n deviceDetailsLastSeenFormat:device.lastSeenIp :[dateFormatter stringFromDate:lastSeenDate]];
|
||||
|
||||
[deviceInformationString appendAttributedString:[[NSMutableAttributedString alloc]
|
||||
initWithString:lastSeen
|
||||
attributes:@{NSForegroundColorAttributeName : _defaultTextColor,
|
||||
NSFontAttributeName: [UIFont systemFontOfSize:14]}]];
|
||||
[deviceInformationString appendAttributedString:[MXKDeviceView verticalWhitespace]];
|
||||
|
||||
self.textView.attributedText = deviceInformationString;
|
||||
}
|
||||
else
|
||||
{
|
||||
_textView.text = nil;
|
||||
}
|
||||
|
||||
// Hide potential activity indicator
|
||||
[_activityIndicator stopAnimating];
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
mxDevice = nil;
|
||||
mxSession = nil;
|
||||
}
|
||||
|
||||
+ (NSAttributedString *)verticalWhitespace
|
||||
{
|
||||
if (verticalWhitespace == nil)
|
||||
{
|
||||
verticalWhitespace = [[NSAttributedString alloc] initWithString:@"\n\n" attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:4]}];
|
||||
}
|
||||
return verticalWhitespace;
|
||||
}
|
||||
|
||||
#pragma mark - Actions
|
||||
|
||||
- (IBAction)onBgViewTap:(UITapGestureRecognizer*)sender
|
||||
{
|
||||
[self removeFromSuperviewDidUpdate:NO];
|
||||
}
|
||||
|
||||
- (IBAction)onButtonPressed:(id)sender
|
||||
{
|
||||
if (sender == _cancelButton)
|
||||
{
|
||||
[self removeFromSuperviewDidUpdate:NO];
|
||||
}
|
||||
else if (sender == _renameButton)
|
||||
{
|
||||
[self renameDevice];
|
||||
}
|
||||
else if (sender == _deleteButton)
|
||||
{
|
||||
[self deleteDevice];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
|
||||
- (void)renameDevice
|
||||
{
|
||||
if (!self.delegate)
|
||||
{
|
||||
// Ignore
|
||||
MXLogDebug(@"[MXKDeviceView] Rename device failed, delegate is missing");
|
||||
return;
|
||||
}
|
||||
|
||||
// Prompt the user to enter a device name.
|
||||
[currentAlert dismissViewControllerAnimated:NO completion:nil];
|
||||
__weak typeof(self) weakSelf = self;
|
||||
|
||||
currentAlert = [UIAlertController alertControllerWithTitle:[MatrixKitL10n deviceDetailsRenamePromptTitle]
|
||||
message:[MatrixKitL10n deviceDetailsRenamePromptMessage] preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[currentAlert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
|
||||
textField.secureTextEntry = NO;
|
||||
textField.placeholder = nil;
|
||||
textField.keyboardType = UIKeyboardTypeDefault;
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
textField.text = self->mxDevice.displayName;
|
||||
}
|
||||
}];
|
||||
|
||||
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentAlert = nil;
|
||||
}
|
||||
|
||||
}]];
|
||||
|
||||
[currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
NSString *text = [self->currentAlert textFields].firstObject.text;
|
||||
self->currentAlert = nil;
|
||||
|
||||
[self.activityIndicator startAnimating];
|
||||
|
||||
self->mxCurrentOperation = [self->mxSession.matrixRestClient setDeviceName:text forDeviceId:self->mxDevice.deviceId success:^{
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
|
||||
self->mxCurrentOperation = nil;
|
||||
[self.activityIndicator stopAnimating];
|
||||
|
||||
[self removeFromSuperviewDidUpdate:YES];
|
||||
}
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
|
||||
// Notify MatrixKit user
|
||||
NSString *myUserId = self->mxSession.myUser.userId;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error userInfo:myUserId ? @{kMXKErrorUserIdKey: myUserId} : nil];
|
||||
|
||||
self->mxCurrentOperation = nil;
|
||||
|
||||
MXLogDebug(@"[MXKDeviceView] Rename device (%@) failed", self->mxDevice.deviceId);
|
||||
|
||||
[self.activityIndicator stopAnimating];
|
||||
|
||||
[self removeFromSuperviewDidUpdate:NO];
|
||||
}
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
}]];
|
||||
|
||||
[self.delegate deviceView:self presentAlertController:currentAlert];
|
||||
}
|
||||
|
||||
- (void)deleteDevice
|
||||
{
|
||||
if (!self.delegate)
|
||||
{
|
||||
// Ignore
|
||||
MXLogDebug(@"[MXKDeviceView] Delete device failed, delegate is missing");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get an authentication session to prepare device deletion
|
||||
[self.activityIndicator startAnimating];
|
||||
|
||||
mxCurrentOperation = [mxSession.matrixRestClient getSessionToDeleteDeviceByDeviceId:mxDevice.deviceId success:^(MXAuthenticationSession *authSession) {
|
||||
|
||||
self->mxCurrentOperation = nil;
|
||||
|
||||
// Check whether the password based type is supported
|
||||
BOOL isPasswordBasedTypeSupported = NO;
|
||||
for (MXLoginFlow *loginFlow in authSession.flows)
|
||||
{
|
||||
if ([loginFlow.type isEqualToString:kMXLoginFlowTypePassword] || [loginFlow.stages indexOfObject:kMXLoginFlowTypePassword] != NSNotFound)
|
||||
{
|
||||
isPasswordBasedTypeSupported = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isPasswordBasedTypeSupported && authSession.session)
|
||||
{
|
||||
// Prompt for a password
|
||||
[self->currentAlert dismissViewControllerAnimated:NO completion:nil];
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
|
||||
// Prompt the user before deleting the device.
|
||||
self->currentAlert = [UIAlertController alertControllerWithTitle:[MatrixKitL10n deviceDetailsDeletePromptTitle] message:[MatrixKitL10n deviceDetailsDeletePromptMessage] preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
|
||||
[self->currentAlert addTextFieldWithConfigurationHandler:^(UITextField *textField) {
|
||||
|
||||
textField.secureTextEntry = YES;
|
||||
textField.placeholder = nil;
|
||||
textField.keyboardType = UIKeyboardTypeDefault;
|
||||
}];
|
||||
|
||||
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentAlert = nil;
|
||||
[self.activityIndicator stopAnimating];
|
||||
}
|
||||
|
||||
}]];
|
||||
|
||||
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n submit]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
UITextField *textField = [self->currentAlert textFields].firstObject;
|
||||
self->currentAlert = nil;
|
||||
|
||||
NSString *userId = self->mxSession.myUser.userId;
|
||||
NSDictionary *authParams;
|
||||
|
||||
// Sanity check
|
||||
if (userId)
|
||||
{
|
||||
authParams = @{@"session":authSession.session,
|
||||
@"user": userId,
|
||||
@"password": textField.text,
|
||||
@"type": kMXLoginFlowTypePassword};
|
||||
|
||||
}
|
||||
|
||||
self->mxCurrentOperation = [self->mxSession.matrixRestClient deleteDeviceByDeviceId:self->mxDevice.deviceId authParams:authParams success:^{
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
|
||||
self->mxCurrentOperation = nil;
|
||||
[self.activityIndicator stopAnimating];
|
||||
|
||||
[self removeFromSuperviewDidUpdate:YES];
|
||||
}
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
|
||||
// Notify MatrixKit user
|
||||
NSString *myUserId = self->mxSession.myUser.userId;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error userInfo:myUserId ? @{kMXKErrorUserIdKey: myUserId} : nil];
|
||||
|
||||
self->mxCurrentOperation = nil;
|
||||
|
||||
MXLogDebug(@"[MXKDeviceView] Delete device (%@) failed", self->mxDevice.deviceId);
|
||||
|
||||
[self.activityIndicator stopAnimating];
|
||||
|
||||
[self removeFromSuperviewDidUpdate:NO];
|
||||
}
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
}]];
|
||||
|
||||
[self.delegate deviceView:self presentAlertController:self->currentAlert];
|
||||
}
|
||||
else
|
||||
{
|
||||
MXLogDebug(@"[MXKDeviceView] Delete device (%@) failed, auth session flow type is not supported", self->mxDevice.deviceId);
|
||||
[self.activityIndicator stopAnimating];
|
||||
}
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
self->mxCurrentOperation = nil;
|
||||
|
||||
MXLogDebug(@"[MXKDeviceView] Delete device (%@) failed, unable to get auth session", self->mxDevice.deviceId);
|
||||
[self.activityIndicator stopAnimating];
|
||||
|
||||
// Notify MatrixKit user
|
||||
NSString *myUserId = self->mxSession.myUser.userId;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error userInfo:myUserId ? @{kMXKErrorUserIdKey: myUserId} : nil];
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,108 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
|
||||
<device id="retina4_7" orientation="portrait">
|
||||
<adaptation id="fullscreen"/>
|
||||
</device>
|
||||
<dependencies>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="11757"/>
|
||||
<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"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<view contentMode="scaleToFill" id="8VI-1E-fge" customClass="MXKDeviceView">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<subviews>
|
||||
<view alpha="0.5" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="D7c-Zw-n8I">
|
||||
<rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
|
||||
<color key="backgroundColor" red="0.66666666666666663" green="0.66666666666666663" blue="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</view>
|
||||
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="c3W-Ma-n01">
|
||||
<rect key="frame" x="10" y="74" width="580" height="250"/>
|
||||
<subviews>
|
||||
<textView autoresizesSubviews="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" bounces="NO" editable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="3Vk-Jx-L6Y">
|
||||
<rect key="frame" x="10" y="10" width="560" height="190"/>
|
||||
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
|
||||
<string key="text">Lorem ipsum dolor sit er elit lamet, consectetaur cillium adipisicing pecu, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum. Nam liber te conscient to factor tum poen legum odioque civiuda.</string>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||
</textView>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ump-1C-SzI">
|
||||
<rect key="frame" x="57.5" y="210" width="30" height="30"/>
|
||||
<state key="normal" title="OK">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="onButtonPressed:" destination="8VI-1E-fge" eventType="touchUpInside" id="t42-2S-MsY"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="o3Z-D3-2S3">
|
||||
<rect key="frame" x="335" y="210" width="56" height="30"/>
|
||||
<state key="normal" title="Rename">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="onButtonPressed:" destination="8VI-1E-fge" eventType="touchUpInside" id="hbe-VP-vE5"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="qkC-t0-Qd0">
|
||||
<rect key="frame" x="485" y="210" width="45" height="30"/>
|
||||
<state key="normal" title="Delete">
|
||||
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</state>
|
||||
<connections>
|
||||
<action selector="onButtonPressed:" destination="8VI-1E-fge" eventType="touchUpInside" id="ljK-ul-fY2"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="3Vk-Jx-L6Y" firstAttribute="leading" secondItem="c3W-Ma-n01" secondAttribute="leading" constant="10" id="ECh-zm-rMb"/>
|
||||
<constraint firstAttribute="trailing" secondItem="3Vk-Jx-L6Y" secondAttribute="trailing" constant="10" id="J2X-t1-Wuo"/>
|
||||
<constraint firstItem="qkC-t0-Qd0" firstAttribute="top" secondItem="3Vk-Jx-L6Y" secondAttribute="bottom" constant="10" id="QLy-iD-ead"/>
|
||||
<constraint firstAttribute="bottom" secondItem="o3Z-D3-2S3" secondAttribute="bottom" constant="10" id="RLg-NE-JtP"/>
|
||||
<constraint firstAttribute="centerX" secondItem="Ump-1C-SzI" secondAttribute="centerX" multiplier="4" id="anR-Ea-ml6"/>
|
||||
<constraint firstAttribute="bottom" secondItem="qkC-t0-Qd0" secondAttribute="bottom" constant="10" id="eJw-AZ-Okc"/>
|
||||
<constraint firstItem="3Vk-Jx-L6Y" firstAttribute="top" secondItem="c3W-Ma-n01" secondAttribute="top" constant="10" id="ej1-zq-aDf"/>
|
||||
<constraint firstAttribute="centerX" secondItem="o3Z-D3-2S3" secondAttribute="centerX" multiplier="4/5" id="h0U-I5-5dA"/>
|
||||
<constraint firstAttribute="bottom" secondItem="Ump-1C-SzI" secondAttribute="bottom" constant="10" id="kLj-CN-wSG"/>
|
||||
<constraint firstAttribute="height" priority="750" constant="250" id="rtj-ON-bkY"/>
|
||||
<constraint firstAttribute="centerX" secondItem="qkC-t0-Qd0" secondAttribute="centerX" multiplier="4/7" id="s2R-r3-jqz"/>
|
||||
</constraints>
|
||||
</view>
|
||||
<activityIndicatorView hidden="YES" opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" style="gray" translatesAutoresizingMaskIntoConstraints="NO" id="4za-i5-u2D">
|
||||
<rect key="frame" x="290" y="290" width="20" height="20"/>
|
||||
</activityIndicatorView>
|
||||
</subviews>
|
||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
<constraints>
|
||||
<constraint firstItem="D7c-Zw-n8I" firstAttribute="top" secondItem="8VI-1E-fge" secondAttribute="top" id="9Md-NO-OM3"/>
|
||||
<constraint firstAttribute="trailing" secondItem="c3W-Ma-n01" secondAttribute="trailing" constant="10" id="F6j-Ia-5EQ"/>
|
||||
<constraint firstItem="D7c-Zw-n8I" firstAttribute="leading" secondItem="8VI-1E-fge" secondAttribute="leading" id="Gzh-sa-sB4"/>
|
||||
<constraint firstItem="c3W-Ma-n01" firstAttribute="height" relation="lessThanOrEqual" secondItem="8VI-1E-fge" secondAttribute="height" constant="-20" id="OE8-Ll-IX0"/>
|
||||
<constraint firstItem="4za-i5-u2D" firstAttribute="centerX" secondItem="8VI-1E-fge" secondAttribute="centerX" id="SGT-wg-tcC"/>
|
||||
<constraint firstItem="c3W-Ma-n01" firstAttribute="top" secondItem="8VI-1E-fge" secondAttribute="top" constant="74" id="a6K-LL-lzT"/>
|
||||
<constraint firstItem="4za-i5-u2D" firstAttribute="centerY" secondItem="8VI-1E-fge" secondAttribute="centerY" id="gjb-ga-edx"/>
|
||||
<constraint firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="c3W-Ma-n01" secondAttribute="bottom" constant="10" id="oD7-T4-DuW"/>
|
||||
<constraint firstAttribute="bottom" secondItem="D7c-Zw-n8I" secondAttribute="bottom" id="qda-fo-h6c"/>
|
||||
<constraint firstItem="c3W-Ma-n01" firstAttribute="leading" secondItem="8VI-1E-fge" secondAttribute="leading" constant="10" id="ryV-yq-aqs"/>
|
||||
<constraint firstAttribute="trailing" secondItem="D7c-Zw-n8I" secondAttribute="trailing" id="wCd-aV-jjY"/>
|
||||
</constraints>
|
||||
<nil key="simulatedStatusBarMetrics"/>
|
||||
<nil key="simulatedTopBarMetrics"/>
|
||||
<nil key="simulatedBottomBarMetrics"/>
|
||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
||||
<connections>
|
||||
<outlet property="activityIndicator" destination="4za-i5-u2D" id="IH9-BZ-e26"/>
|
||||
<outlet property="bgView" destination="D7c-Zw-n8I" id="iQs-LG-SpD"/>
|
||||
<outlet property="cancelButton" destination="Ump-1C-SzI" id="U8M-nT-JiK"/>
|
||||
<outlet property="containerView" destination="c3W-Ma-n01" id="Stk-lk-Wew"/>
|
||||
<outlet property="deleteButton" destination="qkC-t0-Qd0" id="bRu-al-rte"/>
|
||||
<outlet property="renameButton" destination="o3Z-D3-2S3" id="4tr-TC-EcJ"/>
|
||||
<outlet property="textView" destination="3Vk-Jx-L6Y" id="uOw-Bq-neN"/>
|
||||
</connections>
|
||||
</view>
|
||||
</objects>
|
||||
</document>
|
||||
Reference in New Issue
Block a user