Merge branch 'gil/SP1_space_creation' into gil/5231_SP3-1_Update_room_settings_for_Spaces

# Conflicts:
#	Podfile.lock
This commit is contained in:
Gil Eluard
2022-02-21 17:57:58 +01:00
687 changed files with 8777 additions and 3697 deletions
@@ -120,7 +120,7 @@ sendObjectMessage({ \
MXLogDebug(@"[MXKAuthenticationFallbackWebView] URL has js: prefix");
// Listen only to scheme of the JS-WKWebView bridge
NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByRemovingPercentEncoding];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
@@ -102,7 +102,7 @@ var onloadCallback = function() { \
if ([urlString hasPrefix:@"js:"])
{
// Listen only to scheme of the JS-WKWebView bridge
NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding];
NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByRemovingPercentEncoding];
NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding];
NSError *error;
@@ -417,7 +417,7 @@ static NSAttributedString *verticalWhitespace = nil;
[_mxSession.crypto setDeviceVerification:MXDeviceVerified forDevice:_mxDeviceInfo.deviceId ofUser:_mxDeviceInfo.userId success:^{
// Refresh data
_mxDeviceInfo = [self.mxSession.crypto eventDeviceInfo:self.mxEvent];
self->_mxDeviceInfo = [self.mxSession.crypto eventDeviceInfo:self.mxEvent];
if (self->_delegate)
{
[self->_delegate encryptionInfoView:self didDeviceInfoVerifiedChange:self.mxDeviceInfo];
@@ -473,7 +473,7 @@ static NSAttributedString *verticalWhitespace = nil;
[_mxSession.crypto setDeviceVerification:verificationStatus forDevice:_mxDeviceInfo.deviceId ofUser:_mxDeviceInfo.userId success:^{
// Refresh data
_mxDeviceInfo = [self.mxSession.crypto eventDeviceInfo:self.mxEvent];
self->_mxDeviceInfo = [self.mxSession.crypto eventDeviceInfo:self.mxEvent];
if (self->_delegate)
{
@@ -75,11 +75,9 @@
- (MXKCellData*)renderedCellData;
/**
Reset the cell.
Stop processes no more needed when cell is not visible.
The cell is no more displayed. This is time to release resources and removing listeners.
In case of UITableViewCell or UIContentViewCell object, the cell must reset in a state
that it can be reusable.
The cell is no more displayed but still recycled. This is time to stop animation.
*/
- (void)didEndDisplay;
@@ -1,99 +0,0 @@
/*
Copyright 2015 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 <MatrixSDK/MatrixSDK.h>
#import "MXKView.h"
typedef NS_ENUM(NSInteger, ReadReceiptsAlignment)
{
/**
The latest receipt is displayed on left
*/
ReadReceiptAlignmentLeft = 0,
/**
The latest receipt is displayed on right
*/
ReadReceiptAlignmentRight = 1,
};
/**
`MXKReceiptSendersContainer` is a view dedicated to display receipt senders by using their avatars.
This container handles automatically the number of visible avatars. A label is added when avatars are not all visible (see 'moreLabel' property).
*/
@interface MXKReceiptSendersContainer : MXKView
/**
The maximum number of avatars displayed in the container. 3 by default.
*/
@property (nonatomic) NSInteger maxDisplayedAvatars;
/**
The space between avatars. 2.0 points by default.
*/
@property (nonatomic) CGFloat avatarMargin;
/**
The label added beside avatars when avatars are not all visible.
*/
@property (nonatomic) UILabel* moreLabel;
/**
The more label text color (If set to nil `moreLabel.textColor` use `UIColor.blackColor` as default color).
*/
@property (nonatomic) UIColor* moreLabelTextColor;
/*
The read receipt objects for details required in the details view
*/
@property (nonatomic) NSArray <MXReceiptData *> *readReceipts;
/*
The array of the room members that will be displayed in the container
*/
@property (nonatomic, readonly) NSArray <MXRoomMember *> *roomMembers;
/*
The placeholders of the room members that will be shown if the users don't have avatars
*/
@property (nonatomic, readonly) NSArray <UIImage *> *placeholders;
/**
Initializes an `MXKReceiptSendersContainer` object with a frame and a media manager.
This is the designated initializer.
@param frame the container frame. Note that avatar will be displayed in full height in this container.
@param mediaManager the media manager used to download the matrix user's avatar.
@return The newly-initialized MXKReceiptSendersContainer instance
*/
- (instancetype)initWithFrame:(CGRect)frame andMediaManager:(MXMediaManager*)mediaManager;
/**
Refresh the container content by using the provided room members.
@param roomMembers list of room members sorted from the latest receipt to the oldest receipt.
@param placeHolders list of placeholders, one by room member. Used when url is nil, or during avatar download.
@param alignment (see ReadReceiptsAlignment).
*/
- (void)refreshReceiptSenders:(NSArray<MXRoomMember*>*)roomMembers withPlaceHolders:(NSArray<UIImage*>*)placeHolders andAlignment:(ReadReceiptsAlignment)alignment;
@end
@@ -1,174 +0,0 @@
/*
Copyright 2015 OpenMarket 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 "MXKReceiptSendersContainer.h"
#import "MXKImageView.h"
static UIColor* kMoreLabelDefaultcolor;
@interface MXKReceiptSendersContainer ()
@property (nonatomic, readwrite) NSArray <MXRoomMember *> *roomMembers;
@property (nonatomic, readwrite) NSArray <UIImage *> *placeholders;
@property (nonatomic) MXMediaManager *mediaManager;
@end
@implementation MXKReceiptSendersContainer
+ (void)initialize
{
if (self == [MXKReceiptSendersContainer class])
{
kMoreLabelDefaultcolor = [UIColor blackColor];
}
}
- (instancetype)initWithFrame:(CGRect)frame andMediaManager:(MXMediaManager*)mediaManager
{
self = [super initWithFrame:frame];
if (self)
{
_mediaManager = mediaManager;
_maxDisplayedAvatars = 3;
_avatarMargin = 2.0;
_moreLabel = nil;
_moreLabelTextColor = kMoreLabelDefaultcolor;
}
return self;
}
- (void)refreshReceiptSenders:(NSArray<MXRoomMember*>*)roomMembers withPlaceHolders:(NSArray<UIImage*>*)placeHolders andAlignment:(ReadReceiptsAlignment)alignment
{
// Store the room members and placeholders for showing in the details view controller
self.roomMembers = roomMembers;
self.placeholders = placeHolders;
// Remove all previous content
for (UIView* view in self.subviews)
{
[view removeFromSuperview];
}
if (_moreLabel)
{
[_moreLabel removeFromSuperview];
_moreLabel = nil;
}
CGRect globalFrame = self.frame;
CGFloat side = globalFrame.size.height;
CGFloat defaultMoreLabelWidth = side < 20 ? 20 : side;
unsigned long count;
unsigned long maxDisplayableItems = (int)((globalFrame.size.width - defaultMoreLabelWidth - _avatarMargin) / (side + _avatarMargin));
maxDisplayableItems = MIN(maxDisplayableItems, _maxDisplayedAvatars);
count = MIN(roomMembers.count, maxDisplayableItems);
int index;
CGFloat xOff = 0;
if (alignment == ReadReceiptAlignmentRight)
{
xOff = globalFrame.size.width - (side + _avatarMargin);
}
for (index = 0; index < count; index++)
{
MXRoomMember *roomMember = [roomMembers objectAtIndex:index];
UIImage *preview = index < placeHolders.count ? placeHolders[index] : nil;
MXKImageView *imageView = [[MXKImageView alloc] initWithFrame:CGRectMake(xOff, 0, side, side)];
imageView.defaultBackgroundColor = [UIColor clearColor];
imageView.autoresizingMask = UIViewAutoresizingNone;
if (alignment == ReadReceiptAlignmentRight)
{
xOff -= side + _avatarMargin;
}
else
{
xOff += side + _avatarMargin;
}
[self addSubview:imageView];
imageView.enableInMemoryCache = YES;
[imageView setImageURI:roomMember.avatarUrl
withType:nil
andImageOrientation:UIImageOrientationUp
toFitViewSize:CGSizeMake(side, side)
withMethod:MXThumbnailingMethodCrop
previewImage:preview
mediaManager:_mediaManager];
[imageView.layer setCornerRadius:imageView.frame.size.width / 2];
imageView.clipsToBounds = YES;
}
// Check whether there are more than expected read receipts
if (roomMembers.count > maxDisplayableItems)
{
// Add a more indicator
// In case of right alignment, adjust the current position by considering the default label width
if (alignment == ReadReceiptAlignmentRight && side < defaultMoreLabelWidth)
{
xOff -= (defaultMoreLabelWidth - side);
}
_moreLabel = [[UILabel alloc] initWithFrame:CGRectMake(xOff, 0, defaultMoreLabelWidth, side)];
_moreLabel.text = [NSString stringWithFormat:(alignment == ReadReceiptAlignmentRight) ? @"%tu+" : @"+%tu", roomMembers.count - maxDisplayableItems];
_moreLabel.font = [UIFont systemFontOfSize:11];
_moreLabel.adjustsFontSizeToFitWidth = YES;
_moreLabel.minimumScaleFactor = 0.6;
// In case of right alignment, adjust the horizontal position according to the actual label width
if (alignment == ReadReceiptAlignmentRight)
{
[_moreLabel sizeToFit];
CGRect frame = _moreLabel.frame;
if (frame.size.width < defaultMoreLabelWidth)
{
frame.origin.x += (defaultMoreLabelWidth - frame.size.width);
_moreLabel.frame = frame;
}
}
_moreLabel.textColor = self.moreLabelTextColor ?: kMoreLabelDefaultcolor;
[self addSubview:_moreLabel];
}
}
- (void)dealloc
{
NSArray* subviews = self.subviews;
for (UIView* view in subviews)
{
[view removeFromSuperview];
}
if (_moreLabel)
{
[_moreLabel removeFromSuperview];
_moreLabel = nil;
}
}
@end
@@ -1,33 +0,0 @@
/*
Copyright 2015 OpenMarket Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#import "MXKRoomInputToolbarView.h"
#import <HPGrowingTextView/HPGrowingTextView.h>
/**
`MXKRoomInputToolbarViewWithHPGrowingText` is a MXKRoomInputToolbarView-inherited class in which message
composer is based on `HPGrowingTextView`.
Toolbar buttons are not overridden by this class. We keep the default implementation.
*/
@interface MXKRoomInputToolbarViewWithHPGrowingText : MXKRoomInputToolbarView <HPGrowingTextViewDelegate>
{
@protected
HPGrowingTextView *growingTextView;
}
@end
@@ -1,187 +0,0 @@
/*
Copyright 2015 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 "MXKRoomInputToolbarViewWithHPGrowingText.h"
@interface MXKRoomInputToolbarViewWithHPGrowingText()
{
// HPGrowingTextView triggers growingTextViewDidChange event when it recomposes itself
// Save the last edited text to prevent unexpected typing events
NSString* lastEditedText;
}
/**
Message composer defined in `messageComposerContainer`.
*/
@property (nonatomic) IBOutlet HPGrowingTextView *growingTextView;
@end
@implementation MXKRoomInputToolbarViewWithHPGrowingText
@synthesize growingTextView;
+ (UINib *)nib
{
return [UINib nibWithNibName:NSStringFromClass([MXKRoomInputToolbarViewWithHPGrowingText class])
bundle:[NSBundle bundleForClass:[MXKRoomInputToolbarViewWithHPGrowingText class]]];
}
- (void)awakeFromNib
{
[super awakeFromNib];
// Handle message composer based on HPGrowingTextView use
growingTextView.delegate = self;
[growingTextView setTranslatesAutoresizingMaskIntoConstraints: NO];
// Add an accessory view to the text view in order to retrieve keyboard view.
inputAccessoryView = [[UIView alloc] initWithFrame:CGRectZero];
growingTextView.internalTextView.inputAccessoryView = self.inputAccessoryView;
// on IOS 8, the growing textview animation could trigger weird UI animations
// indeed, the messages tableView can be refreshed while its height is updated (e.g. when setting a message)
growingTextView.animateHeightChange = NO;
lastEditedText = nil;
}
- (void)dealloc
{
[self destroy];
}
-(void)customizeViewRendering
{
[super customizeViewRendering];
// set text input font
growingTextView.font = [UIFont systemFontOfSize:14];
// draw a rounded border around the textView
growingTextView.layer.cornerRadius = 5;
growingTextView.layer.borderWidth = 1;
growingTextView.layer.borderColor = [UIColor lightGrayColor].CGColor;
growingTextView.clipsToBounds = YES;
growingTextView.backgroundColor = [UIColor whiteColor];
}
- (void)destroy
{
if (growingTextView)
{
growingTextView.delegate = nil;
growingTextView = nil;
}
[super destroy];
}
- (void)setMaxHeight:(CGFloat)maxHeight
{
growingTextView.maxHeight = maxHeight - (self.messageComposerContainerTopConstraint.constant + self.messageComposerContainerBottomConstraint.constant);
[growingTextView refreshHeight];
super.maxHeight = maxHeight;
}
- (NSString*)textMessage
{
return growingTextView.text;
}
- (void)setTextMessage:(NSString *)textMessage
{
growingTextView.text = textMessage;
self.rightInputToolbarButton.enabled = textMessage.length;
}
- (void)pasteText:(NSString *)text
{
self.textMessage = [growingTextView.text stringByReplacingCharactersInRange:growingTextView.selectedRange withString:text];
}
- (void)setPlaceholder:(NSString *)inPlaceholder
{
[super setPlaceholder:inPlaceholder];
growingTextView.placeholder = inPlaceholder;
}
- (BOOL)becomeFirstResponder
{
return [growingTextView becomeFirstResponder];
}
- (void)dismissKeyboard
{
[growingTextView resignFirstResponder];
}
#pragma mark - HPGrowingTextView delegate
- (void)growingTextViewDidEndEditing:(HPGrowingTextView *)sender
{
if ([self.delegate respondsToSelector:@selector(roomInputToolbarView:isTyping:)])
{
[self.delegate roomInputToolbarView:self isTyping:NO];
}
}
- (void)growingTextViewDidChange:(HPGrowingTextView *)sender
{
NSString *msg = growingTextView.text;
// HPGrowingTextView triggers growingTextViewDidChange event when it recomposes itself.
// Save the last edited text to prevent unexpected typing events
if (![lastEditedText isEqualToString:msg])
{
lastEditedText = msg;
if (msg.length)
{
if ([self.delegate respondsToSelector:@selector(roomInputToolbarView:isTyping:)])
{
[self.delegate roomInputToolbarView:self isTyping:YES];
}
self.rightInputToolbarButton.enabled = YES;
}
else
{
if ([self.delegate respondsToSelector:@selector(roomInputToolbarView:isTyping:)])
{
[self.delegate roomInputToolbarView:self isTyping:NO];
}
self.rightInputToolbarButton.enabled = NO;
}
}
}
- (void)growingTextView:(HPGrowingTextView *)growingTextView willChangeHeight:(float)height
{
// Update growing text's superview (toolbar view)
CGFloat updatedHeight = height + (self.messageComposerContainerTopConstraint.constant + self.messageComposerContainerBottomConstraint.constant);
if ([self.delegate respondsToSelector:@selector(roomInputToolbarView:heightDidChanged:completion:)])
{
[self.delegate roomInputToolbarView:self heightDidChanged:updatedHeight completion:nil];
}
}
- (BOOL)growingTextView:(HPGrowingTextView *)growingTextView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
{
return self.isEditable;
}
@end
@@ -1,85 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="11762" systemVersion="16C67" 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="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="iN0-l3-epB" customClass="MXKRoomInputToolbarViewWithHPGrowingText">
<rect key="frame" x="0.0" y="0.0" width="600" height="41"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="contactAdd" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Hga-l8-Wua" userLabel="left Button">
<rect key="frame" x="8" y="0.0" width="35" height="41"/>
<constraints>
<constraint firstAttribute="width" relation="greaterThanOrEqual" constant="35" id="ptO-BQ-NhS"/>
</constraints>
<state key="normal">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="onTouchUpInside:" destination="iN0-l3-epB" eventType="touchUpInside" id="jVG-We-DmS"/>
</connections>
</button>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Owf-M8-qJi" userLabel="right Button">
<rect key="frame" x="552" y="0.0" width="44" height="41"/>
<constraints>
<constraint firstAttribute="width" constant="44" id="9FZ-CI-diT"/>
</constraints>
<state key="normal" title="Send">
<color key="titleShadowColor" red="0.5" green="0.5" blue="0.5" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</state>
<connections>
<action selector="onTouchUpInside:" destination="iN0-l3-epB" eventType="touchUpInside" id="jed-Mz-rxe"/>
</connections>
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QWp-NV-uh5" userLabel="Message Composer Container">
<rect key="frame" x="51" y="4" width="497" height="33"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pkf-YH-tco" customClass="HPGrowingTextView">
<rect key="frame" x="0.0" y="0.0" width="497" height="33"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</view>
</subviews>
<color key="backgroundColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.95686274510000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="pkf-YH-tco" secondAttribute="bottom" id="L3A-Oo-Ml2"/>
<constraint firstItem="pkf-YH-tco" firstAttribute="top" secondItem="QWp-NV-uh5" secondAttribute="top" id="VPn-k0-0vc"/>
<constraint firstItem="pkf-YH-tco" firstAttribute="leading" secondItem="QWp-NV-uh5" secondAttribute="leading" id="mXj-f3-DcT"/>
<constraint firstAttribute="trailing" secondItem="pkf-YH-tco" secondAttribute="trailing" id="n4K-Do-gHr"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" red="0.89720267057418823" green="0.89720267057418823" blue="0.89720267057418823" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="Owf-M8-qJi" secondAttribute="trailing" constant="4" id="2M8-Gu-0f6"/>
<constraint firstItem="QWp-NV-uh5" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" constant="4" id="570-8j-VYY"/>
<constraint firstAttribute="bottom" secondItem="QWp-NV-uh5" secondAttribute="bottom" constant="4" id="9Ya-0H-03W"/>
<constraint firstItem="Hga-l8-Wua" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="8" id="Bc8-T7-wmA"/>
<constraint firstItem="Hga-l8-Wua" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="Cvk-xZ-ODy"/>
<constraint firstItem="Owf-M8-qJi" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="SV8-U3-8dd"/>
<constraint firstAttribute="bottom" secondItem="Hga-l8-Wua" secondAttribute="bottom" id="Slr-2H-laO"/>
<constraint firstItem="Owf-M8-qJi" firstAttribute="leading" secondItem="QWp-NV-uh5" secondAttribute="trailing" constant="4" id="UEd-gb-jgR"/>
<constraint firstItem="QWp-NV-uh5" firstAttribute="leading" secondItem="Hga-l8-Wua" secondAttribute="trailing" constant="8" id="cCr-Am-M7d"/>
<constraint firstAttribute="bottom" secondItem="Owf-M8-qJi" secondAttribute="bottom" id="ycc-x9-PAv"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<nil key="simulatedTopBarMetrics"/>
<nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="growingTextView" destination="pkf-YH-tco" id="VeP-WI-6Xh"/>
<outlet property="leftInputToolbarButton" destination="Hga-l8-Wua" id="zbm-3b-hoY"/>
<outlet property="messageComposerContainer" destination="QWp-NV-uh5" id="7EX-Un-ZIe"/>
<outlet property="messageComposerContainerBottomConstraint" destination="9Ya-0H-03W" id="226-iu-6tU"/>
<outlet property="messageComposerContainerTopConstraint" destination="570-8j-VYY" id="VKv-Qh-PCs"/>
<outlet property="rightInputToolbarButton" destination="Owf-M8-qJi" id="seO-ly-Bgg"/>
</connections>
</view>
</objects>
</document>