Merge branch 'develop' into voip_design_updates

This commit is contained in:
ismailgulek
2021-04-09 15:12:51 +03:00
37 changed files with 1055 additions and 282 deletions
@@ -0,0 +1,143 @@
//
// Copyright 2021 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 UIKit
@objcMembers
class RoomTypingBubbleCell: MXKTableViewCell, Themable {
// MARK: - Constants
private enum Constants {
static let maxPictureCount = 4
static let pictureSize: CGFloat = 24
static let pictureMaxMargin: CGFloat = 16
static let pictureMinMargin: CGFloat = 8
}
// MARK: - Outlets
@IBOutlet private weak var additionalUsersLabel: UILabel!
@IBOutlet private weak var additionalUsersLabelLeadingConstraint: NSLayoutConstraint!
@IBOutlet private weak var dotsView: DotsView!
@IBOutlet private weak var dotsViewLeadingConstraint: NSLayoutConstraint!
// MARK: - members
private var userPictureViews: [MXKImageView] = []
// MARK: - Lifecycle
override func awakeFromNib() {
super.awakeFromNib()
update(theme: ThemeService.shared().theme)
}
override func prepareForReuse() {
super.prepareForReuse()
for pictureView in userPictureViews {
pictureView.removeFromSuperview()
}
}
override func layoutSubviews() {
super.layoutSubviews()
dotsView.isHidden = userPictureViews.count == 0
guard userPictureViews.count > 0 else {
return
}
additionalUsersLabel?.sizeToFit()
var pictureViewsMaxX: CGFloat = 0
var xOffset: CGFloat = 0
for pictureView in userPictureViews {
pictureView.center = CGPoint(x: Constants.pictureMaxMargin + xOffset + pictureView.bounds.midX, y: self.bounds.midY)
xOffset += round(pictureView.bounds.maxX * 2 / 3)
pictureViewsMaxX = pictureView.frame.maxX
}
let leftMagin: CGFloat = pictureViewsMaxX + (userPictureViews.count == 1 ? Constants.pictureMaxMargin : Constants.pictureMinMargin)
additionalUsersLabelLeadingConstraint.constant = leftMagin
dotsViewLeadingConstraint?.constant = additionalUsersLabel.text.isEmptyOrNil == true ? leftMagin : leftMagin + 8 + additionalUsersLabel.frame.width
}
// MARK: - Overrides
override class func defaultReuseIdentifier() -> String {
return String(describing: self)
}
override class func nib() -> UINib {
return UINib(nibName: String(describing: self), bundle: nil)
}
// MARK: - Themable
func update(theme: Theme) {
additionalUsersLabel.textColor = theme.textSecondaryColor
dotsView.highlightedDotColor = theme.textTertiaryColor
dotsView.dotColor = theme.textSecondaryColor
}
// MARK: - Business methods
func updateTypingUsers(_ typingUsers: [TypingUserInfo], mediaManager: MXMediaManager) {
for pictureView in userPictureViews {
pictureView.removeFromSuperview()
}
userPictureViews = []
for user in typingUsers {
if userPictureViews.count >= Constants.maxPictureCount {
break
}
let pictureView = MXKImageView(frame: CGRect(x: 0, y: 0, width: Constants.pictureSize, height: Constants.pictureSize))
pictureView.layer.masksToBounds = true
pictureView.layer.cornerRadius = pictureView.bounds.midX
let defaultavatarImage = AvatarGenerator.generateAvatar(forMatrixItem: user.userId, withDisplayName: user.displayName)
pictureView.setImageURI(user.avatarUrl, withType: nil, andImageOrientation: .up, toFitViewSize: pictureView.bounds.size, with: MXThumbnailingMethodCrop, previewImage: defaultavatarImage, mediaManager: mediaManager)
userPictureViews.append(pictureView)
self.contentView.addSubview(pictureView)
}
switch typingUsers.count {
case 0:
additionalUsersLabel.text = nil
case 1:
additionalUsersLabel.text = firstUserNameFor(typingUsers)
default:
additionalUsersLabel.text = VectorL10n.roomMultipleTypingNotification(firstUserNameFor(typingUsers) ?? "")
}
self.setNeedsLayout()
}
private func firstUserNameFor(_ typingUsers: Array<TypingUserInfo>) -> String? {
guard let firstUser = typingUsers.first else {
return nil
}
return firstUser.displayName.isEmptyOrNil ? firstUser.userId : firstUser.displayName
}
}
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<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 clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="nQB-23-kip" customClass="RoomTypingBubbleCell" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="nQB-23-kip" id="vRo-3W-dC9">
<rect key="frame" x="0.0" y="0.0" width="414" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="+3" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="4KE-u0-T4p">
<rect key="frame" x="20" y="13" width="18.5" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<view contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Bn5-WN-DQs" customClass="DotsView" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="38" y="13" width="91" height="18"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</subviews>
<constraints>
<constraint firstItem="4KE-u0-T4p" firstAttribute="leading" secondItem="vRo-3W-dC9" secondAttribute="leading" constant="20" symbolic="YES" id="PFN-Ig-2NK"/>
<constraint firstItem="Bn5-WN-DQs" firstAttribute="leading" secondItem="vRo-3W-dC9" secondAttribute="leading" constant="38" id="hmq-dH-neQ"/>
<constraint firstItem="Bn5-WN-DQs" firstAttribute="centerY" secondItem="vRo-3W-dC9" secondAttribute="centerY" id="jup-hc-eNQ"/>
</constraints>
</tableViewCellContentView>
<constraints>
<constraint firstItem="4KE-u0-T4p" firstAttribute="centerY" secondItem="nQB-23-kip" secondAttribute="centerY" id="hBP-OB-KGd"/>
</constraints>
<connections>
<outlet property="additionalUsersLabel" destination="4KE-u0-T4p" id="SVG-Oa-aHI"/>
<outlet property="additionalUsersLabelLeadingConstraint" destination="PFN-Ig-2NK" id="4Wr-XS-XXp"/>
<outlet property="dotsView" destination="Bn5-WN-DQs" id="QqF-bu-Pbm"/>
<outlet property="dotsViewLeadingConstraint" destination="hmq-dH-neQ" id="6hM-Sc-pCc"/>
</connections>
<point key="canvasLocation" x="166.66666666666669" y="20.758928571428569"/>
</tableViewCell>
</objects>
</document>
@@ -0,0 +1,30 @@
//
// Copyright 2021 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 UIKit
@objcMembers
class RoomActionItem: NSObject {
let image: UIImage
let action: (() -> Void)
init(image: UIImage, andAction action: @escaping () -> Void) {
self.image = image
self.action = action
super.init()
}
}
@@ -0,0 +1,132 @@
//
// Copyright 2021 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 UIKit
@objcMembers
class RoomActionsBar: UIScrollView, Themable {
// MARK: - Properties
var itemSpacing: CGFloat = 20 {
didSet {
self.setNeedsLayout()
}
}
var actionItems: [RoomActionItem] = [] {
didSet {
var actionButtons: [UIButton] = []
for (index, item) in actionItems.enumerated() {
let button = UIButton(type: .custom)
button.setImage(item.image, for: .normal)
button.addTarget(self, action: #selector(buttonAction(_:)), for: .touchUpInside)
button.tintColor = ThemeService.shared().theme.tintColor
button.tag = index
actionButtons.append(button)
addSubview(button)
}
self.actionButtons = actionButtons
self.lastBounds = .zero
self.setNeedsLayout()
}
}
private var actionButtons: [UIButton] = [] {
willSet {
for button in actionButtons {
button.removeFromSuperview()
}
}
}
private var lastBounds = CGRect.zero
// MARK: - Lifecycle
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setupView()
}
override func layoutSubviews() {
super.layoutSubviews()
guard lastBounds != self.bounds else {
return
}
lastBounds = self.bounds
var currentX: CGFloat = 0
for button in actionButtons {
button.transform = CGAffineTransform.identity
button.frame = CGRect(x: currentX, y: 0, width: self.bounds.height, height: self.bounds.height)
currentX = button.frame.maxX + itemSpacing
}
self.contentSize = CGSize(width: currentX - itemSpacing, height: self.bounds.height)
}
// MARK: - Themable
func update(theme: Theme) {
for button in actionButtons {
button.tintColor = theme.tintColor
}
}
// MARK: - Business methods
func animate(showIn: Bool, completion: ((Bool) -> Void)? = nil) {
if showIn {
for button in actionButtons {
button.transform = CGAffineTransform(translationX: 0, y: self.bounds.height)
}
for (index, button) in actionButtons.enumerated() {
UIView.animate(withDuration: 0.3, delay: 0.05 * Double(index), usingSpringWithDamping: 0.45, initialSpringVelocity: 11, options: .curveEaseInOut) {
button.transform = CGAffineTransform.identity
} completion: { (finished) in
completion?(finished)
}
}
} else {
for (index, button) in actionButtons.enumerated() {
UIView.animate(withDuration: 0.25, delay: 0.05 * Double(index), options: .curveEaseInOut) {
button.transform = CGAffineTransform(translationX: 0, y: self.bounds.height)
} completion: { (finished) in
if index == self.actionButtons.count - 1 {
completion?(finished)
}
}
}
}
}
// MARK: - Private methods
@objc private func buttonAction(_ sender: UIButton) {
actionItems[sender.tag].action()
}
private func setupView() {
self.showsHorizontalScrollIndicator = false
}
}
@@ -18,6 +18,8 @@
#import "MediaPickerViewController.h"
@class RoomActionsBar;
/**
Destination of the message in the composer
*/
@@ -31,34 +33,6 @@ typedef enum : NSUInteger
@protocol RoomInputToolbarViewDelegate <MXKRoomInputToolbarViewDelegate>
/**
Tells the delegate that the user wants to display the sticker picker.
@param toolbarView the room input toolbar view.
*/
- (void)roomInputToolbarViewPresentStickerPicker:(MXKRoomInputToolbarView*)toolbarView;
/**
Tells the delegate that the user wants to send external files.
@param toolbarView the room input toolbar view
*/
- (void)roomInputToolbarViewDidTapFileUpload:(MXKRoomInputToolbarView*)toolbarView;
/**
Tells the delegate that the user wants to take photo or video with camera.
@param toolbarView the room input toolbar view
*/
- (void)roomInputToolbarViewDidTapCamera:(MXKRoomInputToolbarView*)toolbarView;
/**
Tells the delegate that the user wants to show media library.
@param toolbarView the room input toolbar view
*/
- (void)roomInputToolbarViewDidTapMediaLibrary:(MXKRoomInputToolbarView*)toolbarView;
/**
Tells the delegate that the user wants to cancel the current edition / reply.
@@ -95,6 +69,7 @@ typedef enum : NSUInteger
@property (weak, nonatomic) IBOutlet UIImageView *inputContextImageView;
@property (weak, nonatomic) IBOutlet UILabel *inputContextLabel;
@property (weak, nonatomic) IBOutlet UIButton *inputContextButton;
@property (weak, nonatomic) IBOutlet RoomActionsBar *actionsBar;
/**
Tell whether the filled data will be sent encrypted. NO by default.
@@ -111,4 +86,9 @@ typedef enum : NSUInteger
*/
@property (nonatomic) RoomInputToolbarViewSendMode sendMode;
/**
YES if action menu is opened. NO otherwise
*/
@property (nonatomic, getter=isActionMenuOpened) BOOL actionMenuOpened;
@end
@@ -27,7 +27,13 @@
#import "WidgetManager.h"
#import "IntegrationManagerViewController.h"
const double RoomInputToolbarViewContextBarHeight = 30;
const double kContextBarHeight = 24;
const NSTimeInterval kSendModeAnimationDuration = .15;
const NSTimeInterval kActionMenuAttachButtonAnimationDuration = .4;
const CGFloat kActionMenuAttachButtonSpringVelocity = 7;
const CGFloat kActionMenuAttachButtonSpringDamping = .45;
const NSTimeInterval kActionMenuContentAlphaAnimationDuration = .2;
const NSTimeInterval kActionMenuComposerHeightAnimationDuration = .3;
@interface RoomInputToolbarView()
{
@@ -120,6 +126,7 @@ const double RoomInputToolbarViewContextBarHeight = 30;
self.inputContextImageView.tintColor = ThemeService.shared.theme.textSecondaryColor;
self.inputContextLabel.textColor = ThemeService.shared.theme.textSecondaryColor;
self.inputContextButton.tintColor = ThemeService.shared.theme.textSecondaryColor;
[self.actionsBar updateWithTheme:ThemeService.shared.theme];
}
#pragma mark -
@@ -142,6 +149,7 @@ const double RoomInputToolbarViewContextBarHeight = 30;
RoomInputToolbarViewSendMode previousMode = _sendMode;
_sendMode = sendMode;
self.actionMenuOpened = NO;
[self updatePlaceholder];
[self updateToolbarButtonLabelWithPreviousMode: previousMode];
}
@@ -159,26 +167,26 @@ const double RoomInputToolbarViewContextBarHeight = 30;
self.inputContextImageView.image = [UIImage imageNamed:@"input_reply_icon"];
self.inputContextLabel.text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_message_replying_to", @"Vector", nil), self.eventSenderDisplayName];
self.inputContextViewHeightConstraint.constant = RoomInputToolbarViewContextBarHeight;
updatedHeight += RoomInputToolbarViewContextBarHeight;
self->growingTextView.maxHeight -= RoomInputToolbarViewContextBarHeight;
self.inputContextViewHeightConstraint.constant = kContextBarHeight;
updatedHeight += kContextBarHeight;
self->growingTextView.maxHeight -= kContextBarHeight;
break;
case RoomInputToolbarViewSendModeEdit:
buttonImage = [UIImage imageNamed:@"save_icon"];
self.inputContextImageView.image = [UIImage imageNamed:@"input_edit_icon"];
self.inputContextLabel.text = NSLocalizedStringFromTable(@"room_message_editing", @"Vector", nil);
self.inputContextViewHeightConstraint.constant = RoomInputToolbarViewContextBarHeight;
updatedHeight += RoomInputToolbarViewContextBarHeight;
self->growingTextView.maxHeight -= RoomInputToolbarViewContextBarHeight;
self.inputContextViewHeightConstraint.constant = kContextBarHeight;
updatedHeight += kContextBarHeight;
self->growingTextView.maxHeight -= kContextBarHeight;
break;
default:
buttonImage = [UIImage imageNamed:@"send_icon"];
if (previousMode != _sendMode)
{
updatedHeight -= RoomInputToolbarViewContextBarHeight;
self->growingTextView.maxHeight += RoomInputToolbarViewContextBarHeight;
updatedHeight -= kContextBarHeight;
self->growingTextView.maxHeight += kContextBarHeight;
}
self.inputContextViewHeightConstraint.constant = 0;
break;
@@ -199,7 +207,7 @@ const double RoomInputToolbarViewContextBarHeight = 30;
if (self.mainToolbarHeightConstraint.constant != updatedHeight)
{
[UIView animateWithDuration:.3 animations:^{
[UIView animateWithDuration:kSendModeAnimationDuration animations:^{
self.mainToolbarHeightConstraint.constant = updatedHeight;
[self layoutIfNeeded];
@@ -329,92 +337,7 @@ const double RoomInputToolbarViewContextBarHeight = 30;
{
if (button == self.attachMediaButton)
{
// Check whether media attachment is supported
if ([self.delegate respondsToSelector:@selector(roomInputToolbarView:presentViewController:)])
{
// Ask the user the kind of the call: voice or video?
actionSheet = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
__weak typeof(self) weakSelf = self;
[actionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_action_camera", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->actionSheet = nil;
[self.delegate roomInputToolbarViewDidTapCamera:self];
}
}]];
[actionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_action_send_photo_or_video", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->actionSheet = nil;
[self.delegate roomInputToolbarViewDidTapMediaLibrary:self];
}
}]];
if (BuildSettings.allowSendingStickers)
{
[actionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_action_send_sticker", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->actionSheet = nil;
[self.delegate roomInputToolbarViewPresentStickerPicker:self];
}
}]];
}
[actionSheet addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_action_send_file", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->actionSheet = nil;
[self.delegate roomInputToolbarViewDidTapFileUpload:self];
}
}]];
[actionSheet addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->actionSheet = nil;
}
}]];
[actionSheet popoverPresentationController].sourceView = self.attachMediaButton;
[actionSheet popoverPresentationController].sourceRect = self.attachMediaButton.bounds;
[self.window.rootViewController presentViewController:actionSheet animated:YES completion:nil];
}
else
{
NSLog(@"[RoomInputToolbarView] Attach media is not supported");
}
self.actionMenuOpened = !self.isActionMenuOpened;
}
[super onTouchUpInside:button];
@@ -433,6 +356,8 @@ const double RoomInputToolbarViewContextBarHeight = 30;
- (void)updateSendButtonWithMessage:(NSString *)textMessage
{
self.actionMenuOpened = NO;
if (textMessage.length)
{
self.rightInputToolbarButton.alpha = 1;
@@ -443,9 +368,61 @@ const double RoomInputToolbarViewContextBarHeight = 30;
self.rightInputToolbarButton.alpha = 0;
self.messageComposerContainerTrailingConstraint.constant = 12;
}
[self layoutIfNeeded];
}
#pragma mark - properties
- (void)setActionMenuOpened:(BOOL)actionMenuOpened
{
if (_actionMenuOpened != actionMenuOpened)
{
_actionMenuOpened = actionMenuOpened;
if (self->growingTextView.internalTextView.selectedRange.length > 0)
{
NSRange range = self->growingTextView.internalTextView.selectedRange;
range.location = range.location + range.length;
range.length = 0;
self->growingTextView.internalTextView.selectedRange = range;
}
if (_actionMenuOpened) {
self.actionsBar.hidden = NO;
[self.actionsBar animateWithShowIn:_actionMenuOpened completion:nil];
}
else
{
[self.actionsBar animateWithShowIn:_actionMenuOpened completion:^(BOOL finished) {
self.actionsBar.hidden = YES;
}];
}
[UIView animateWithDuration:kActionMenuAttachButtonAnimationDuration delay:0 usingSpringWithDamping:kActionMenuAttachButtonSpringDamping initialSpringVelocity:kActionMenuAttachButtonSpringVelocity options:UIViewAnimationOptionCurveEaseIn animations:^{
self.attachMediaButton.transform = actionMenuOpened ? CGAffineTransformMakeRotation(M_PI * 3 / 4) : CGAffineTransformIdentity;
} completion:nil];
[UIView animateWithDuration:kActionMenuContentAlphaAnimationDuration delay:_actionMenuOpened ? 0 : .1 options:UIViewAnimationOptionCurveEaseIn animations:^{
self->messageComposerContainer.alpha = actionMenuOpened ? 0 : 1;
self.rightInputToolbarButton.alpha = self->growingTextView.text.length == 0 || actionMenuOpened ? 0 : 1;
} completion:nil];
[UIView animateWithDuration:kActionMenuComposerHeightAnimationDuration animations:^{
if (actionMenuOpened)
{
self.mainToolbarHeightConstraint.constant = self.mainToolbarMinHeightConstraint.constant;
}
else
{
[self->growingTextView refreshHeight];
}
[self layoutIfNeeded];
[self.delegate roomInputToolbarView:self heightDidChanged:self.mainToolbarHeightConstraint.constant completion:nil];
}];
}
}
#pragma mark - Clipboard - Handle image/data paste from general pasteboard
- (void)paste:(id)sender
@@ -27,6 +27,14 @@
<action selector="onTouchUpInside:" destination="iN0-l3-epB" eventType="touchUpInside" id="WbU-WH-gwL"/>
</connections>
</button>
<scrollView hidden="YES" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ESv-9w-KJF" customClass="RoomActionsBar" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="60" y="8" width="540" height="38"/>
<constraints>
<constraint firstAttribute="height" constant="38" id="i6C-gL-ADZ"/>
</constraints>
<viewLayoutGuide key="contentLayoutGuide" id="F6O-76-cZl"/>
<viewLayoutGuide key="frameLayoutGuide" id="rZR-Bv-AqG"/>
</scrollView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QWp-NV-uh5" userLabel="Message Composer Container">
<rect key="frame" x="60" y="9" width="528" height="36"/>
<subviews>
@@ -37,16 +45,16 @@
<rect key="frame" x="0.0" y="0.0" width="528" height="32"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="input_edit_icon" translatesAutoresizingMaskIntoConstraints="NO" id="PZ4-0Y-TmL">
<rect key="frame" x="12" y="11" width="10.5" height="10"/>
<rect key="frame" x="8" y="16" width="10.5" height="10"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dVr-ZM-kkX">
<rect key="frame" x="26.5" y="9" width="461.5" height="14.5"/>
<rect key="frame" x="22.5" y="13.5" width="471.5" height="14.5"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="12"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="48y-kn-7b5">
<rect key="frame" x="492" y="1" width="30" height="30"/>
<rect key="frame" x="498" y="6" width="30" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="I17-S0-9fp"/>
<constraint firstAttribute="width" constant="30" id="cCe-RB-ET2"/>
@@ -59,30 +67,30 @@
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="dVr-ZM-kkX" secondAttribute="bottom" constant="4" id="58M-yd-hhK"/>
<constraint firstItem="PZ4-0Y-TmL" firstAttribute="centerY" secondItem="dVr-ZM-kkX" secondAttribute="centerY" id="Bu1-sl-qDk"/>
<constraint firstAttribute="height" constant="32" id="KNn-ng-NHK"/>
<constraint firstItem="dVr-ZM-kkX" firstAttribute="leading" secondItem="PZ4-0Y-TmL" secondAttribute="trailing" constant="4" id="RbN-mc-y2P"/>
<constraint firstItem="48y-kn-7b5" firstAttribute="centerY" secondItem="jXI-9E-Bgl" secondAttribute="centerY" id="XbN-rm-nDw"/>
<constraint firstItem="48y-kn-7b5" firstAttribute="leading" secondItem="dVr-ZM-kkX" secondAttribute="trailing" constant="4" id="bmi-rg-TNM"/>
<constraint firstItem="PZ4-0Y-TmL" firstAttribute="centerY" secondItem="jXI-9E-Bgl" secondAttribute="centerY" id="f9O-vU-41g"/>
<constraint firstItem="PZ4-0Y-TmL" firstAttribute="leading" secondItem="jXI-9E-Bgl" secondAttribute="leading" constant="12" id="mp0-tl-IIe"/>
<constraint firstAttribute="trailing" secondItem="48y-kn-7b5" secondAttribute="trailing" constant="6" id="qPb-EI-csl"/>
<constraint firstItem="dVr-ZM-kkX" firstAttribute="centerY" secondItem="jXI-9E-Bgl" secondAttribute="centerY" id="yb4-bq-XNb"/>
<constraint firstItem="PZ4-0Y-TmL" firstAttribute="leading" secondItem="jXI-9E-Bgl" secondAttribute="leading" constant="8" id="mp0-tl-IIe"/>
<constraint firstAttribute="trailing" secondItem="48y-kn-7b5" secondAttribute="trailing" id="qPb-EI-csl"/>
<constraint firstItem="48y-kn-7b5" firstAttribute="centerY" secondItem="dVr-ZM-kkX" secondAttribute="centerY" id="z5v-Vy-6tc"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wgb-ON-N29" customClass="KeyboardGrowingTextView">
<rect key="frame" x="4" y="33" width="520" height="4"/>
<rect key="frame" x="5" y="33" width="518" height="4"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
<accessibility key="accessibilityConfiguration" identifier="GrowingTextView"/>
</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="wgb-ON-N29" secondAttribute="trailing" constant="4" id="30f-rE-CKj"/>
<constraint firstAttribute="trailing" secondItem="wgb-ON-N29" secondAttribute="trailing" constant="5" id="30f-rE-CKj"/>
<constraint firstAttribute="trailing" secondItem="jXI-9E-Bgl" secondAttribute="trailing" id="3EM-Mc-ZaI"/>
<constraint firstItem="jXI-9E-Bgl" firstAttribute="top" secondItem="QWp-NV-uh5" secondAttribute="top" id="Bp8-45-jvJ"/>
<constraint firstItem="uH7-Q7-hpZ" firstAttribute="leading" secondItem="QWp-NV-uh5" secondAttribute="leading" id="Fli-kz-OcS"/>
<constraint firstItem="uH7-Q7-hpZ" firstAttribute="top" secondItem="QWp-NV-uh5" secondAttribute="top" id="Gqc-ya-F1W"/>
<constraint firstItem="wgb-ON-N29" firstAttribute="leading" secondItem="QWp-NV-uh5" secondAttribute="leading" constant="4" id="N7q-ch-iRz"/>
<constraint firstItem="wgb-ON-N29" firstAttribute="leading" secondItem="QWp-NV-uh5" secondAttribute="leading" constant="5" id="N7q-ch-iRz"/>
<constraint firstItem="wgb-ON-N29" firstAttribute="top" secondItem="jXI-9E-Bgl" secondAttribute="bottom" constant="1" id="UV2-Sh-peE"/>
<constraint firstAttribute="bottom" secondItem="uH7-Q7-hpZ" secondAttribute="bottom" id="dAX-uO-gvm"/>
<constraint firstAttribute="bottom" secondItem="wgb-ON-N29" secondAttribute="bottom" constant="-1" id="fFG-SH-Hjh"/>
@@ -105,11 +113,14 @@
<constraint firstItem="QWp-NV-uh5" firstAttribute="leading" secondItem="Hga-l8-Wua" secondAttribute="trailing" constant="12" id="M9f-je-3zO"/>
<constraint firstAttribute="bottom" secondItem="QWp-NV-uh5" secondAttribute="bottom" constant="13" id="NGr-2o-sOP"/>
<constraint firstAttribute="trailing" secondItem="G8Z-CM-tGs" secondAttribute="trailing" constant="12" id="Sua-LC-3yW"/>
<constraint firstItem="ESv-9w-KJF" firstAttribute="leading" secondItem="Hga-l8-Wua" secondAttribute="trailing" constant="12" id="TIe-py-lFJ"/>
<constraint firstItem="QWp-NV-uh5" firstAttribute="top" secondItem="a84-Vc-6ud" secondAttribute="top" constant="9" id="WyZ-3i-OHi"/>
<constraint firstAttribute="bottom" secondItem="G8Z-CM-tGs" secondAttribute="bottom" constant="12" id="Yam-dS-zwr"/>
<constraint firstAttribute="height" constant="58" id="Yjj-ua-rbe"/>
<constraint firstAttribute="bottom" secondItem="Hga-l8-Wua" secondAttribute="bottom" constant="12" id="b0G-CY-AmP"/>
<constraint firstAttribute="trailing" secondItem="QWp-NV-uh5" secondAttribute="trailing" constant="12" id="hXO-cY-Jgz"/>
<constraint firstAttribute="trailing" secondItem="ESv-9w-KJF" secondAttribute="trailing" id="jCS-Tf-vxr"/>
<constraint firstAttribute="bottom" secondItem="ESv-9w-KJF" secondAttribute="bottom" constant="12" id="v8r-ac-MKn"/>
</constraints>
</view>
</subviews>
@@ -125,6 +136,7 @@
<nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<connections>
<outlet property="actionsBar" destination="ESv-9w-KJF" id="h7H-vz-yzO"/>
<outlet property="attachMediaButton" destination="Hga-l8-Wua" id="Osr-ek-c91"/>
<outlet property="growingTextView" destination="wgb-ON-N29" id="nwF-uV-Ng9"/>
<outlet property="inputContextButton" destination="48y-kn-7b5" id="yRn-1S-96w"/>
@@ -147,7 +147,6 @@
self.pictureViewHeightConstraint.constant = 28;
self.displayNameTextField.font = [UIFont systemFontOfSize:14 weight:UIFontWeightMedium];
self.typingLabel.font = [UIFont systemFontOfSize:10];
self.dotViewCenterXConstraint.constant = 3;
self.dotViewCenterYConstraint.constant = -2;
}
else
@@ -158,7 +157,6 @@
self.pictureViewHeightConstraint.constant = 32;
self.displayNameTextField.font = [UIFont systemFontOfSize:17 weight:UIFontWeightMedium];
self.typingLabel.font = [UIFont systemFontOfSize:12];
self.dotViewCenterXConstraint.constant = 0;
self.dotViewCenterYConstraint.constant = -1;
}
}
@@ -71,7 +71,7 @@
<constraint firstItem="6uH-I3-RQg" firstAttribute="leading" secondItem="LDd-c1-ILP" secondAttribute="trailing" constant="12" id="0pG-0z-gpD"/>
<constraint firstItem="LDd-c1-ILP" firstAttribute="centerY" secondItem="BkF-x3-7fX" secondAttribute="centerY" id="33h-dC-S1U"/>
<constraint firstAttribute="bottom" secondItem="sD9-l7-azQ" secondAttribute="bottom" id="4rX-5O-LrO"/>
<constraint firstItem="yTB-Be-bLN" firstAttribute="centerX" secondItem="SUm-iW-DRR" secondAttribute="leading" id="7H4-kh-c2g"/>
<constraint firstItem="yTB-Be-bLN" firstAttribute="centerX" secondItem="SUm-iW-DRR" secondAttribute="trailing" id="7H4-kh-c2g"/>
<constraint firstItem="sD9-l7-azQ" firstAttribute="leading" secondItem="BkF-x3-7fX" secondAttribute="leading" id="AJc-Aa-sht"/>
<constraint firstItem="SUm-iW-DRR" firstAttribute="centerY" secondItem="BkF-x3-7fX" secondAttribute="centerY" id="Blv-SJ-r6v"/>
<constraint firstItem="Ky3-cy-HAx" firstAttribute="bottom" secondItem="LDd-c1-ILP" secondAttribute="bottom" id="HZy-1x-eyX"/>