Composer update - UI enhancements

- Composer height =58px - Frame = 42px
- Replace current scroll to bottom implementation with a scroll to Bottom FAB on both themes
- The text inside the composer frame should be centered
- The padding between the "reveal plus" button, composer frame and Left + Right sides should be at equal distance on default mode
- Verify that the "Send a message..." String matches with the colour indicated on Figma.
- The padding between each component (buttons and composer frame) should be at equal distance on default mode. E.g : It should be at 12px for each gap.
- The input text jumps down when users start typing. It should be centered at all times.
- Remove the Scroll bar in the text frame.
- DARK THEME
This commit is contained in:
Gil Eluard
2021-03-20 21:31:17 +01:00
parent 889bad2daa
commit f79eccdbb9
25 changed files with 167 additions and 115 deletions
+6
View File
@@ -27,6 +27,8 @@
#import "UIViewController+RiotSearch.h"
@class BadgeLabel;
/**
Notification string used to indicate call tile tapped in a room. Notification object will be the `RoomBubbleCellData` object.
*/
@@ -47,6 +49,8 @@ extern NSNotificationName const RoomCallTileTappedNotification;
@property (weak, nonatomic) IBOutlet UIButton *resetReadMarkerButton;
@property (weak, nonatomic) IBOutlet UIView *jumpToLastUnreadBannerSeparatorView;
@property (weak, nonatomic) IBOutlet UIVisualEffectView *inputBackgroundView;
@property (weak, nonatomic) IBOutlet UIButton *scrollToBottomButton;
@property (weak, nonatomic) IBOutlet BadgeLabel *scrollToBottomBadgeLabel;
/**
Preview data for a room invitation received by email, or a link to a room.
@@ -73,5 +77,7 @@ extern NSNotificationName const RoomCallTileTappedNotification;
*/
- (IBAction)onButtonPressed:(id)sender;
- (IBAction)scrollToBottomAction:(id)sender;
@end
+46 -17
View File
@@ -227,6 +227,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
@property (nonatomic, strong) RoomInfoCoordinatorBridgePresenter *roomInfoCoordinatorBridgePresenter;
@property (nonatomic, strong) CustomSizedPresentationController *customSizedPresentationController;
@property (nonatomic, getter=isActivitiesViewExpanded) BOOL activitiesViewExpanded;
@property (nonatomic, getter=isScrollToBottomHidden) BOOL scrollToBottomHidden;
@end
@@ -291,7 +292,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
formattedBodyParser = [FormattedBodyParser new];
_showMissedDiscussionsBadge = YES;
_scrollToBottomHidden = YES;
// Listen to the event sent state changes
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(eventDidChangeSentState:) name:kMXEventDidChangeSentStateNotification object:nil];
@@ -409,15 +410,6 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
}];
[self userInterfaceThemeDidChange];
if ([ThemeService.shared.themeId isEqualToString:@"light"])
{
self.inputBackgroundView.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
}
else if ([ThemeService.shared.themeId isEqualToString:@"dark"] || [ThemeService.shared.themeId isEqualToString:@"black"])
{
self.inputBackgroundView.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
}
}
- (void)userInterfaceThemeDidChange
@@ -468,6 +460,27 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
[self.bubblesTableView reloadData];
}
self.scrollToBottomButton.layer.shadowColor = [UIColor blackColor].CGColor;
self.scrollToBottomButton.layer.shadowOpacity = 0.2;
self.scrollToBottomButton.layer.shadowRadius = 6;
self.scrollToBottomButton.layer.shadowOffset = CGSizeMake(0, 4);
if ([ThemeService.shared.themeId isEqualToString:@"light"])
{
self.inputBackgroundView.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
[self.scrollToBottomButton setImage:[UIImage imageNamed:@"scrolldown"] forState:UIControlStateNormal];
}
else if ([ThemeService.shared.themeId isEqualToString:@"dark"] || [ThemeService.shared.themeId isEqualToString:@"black"])
{
self.inputBackgroundView.effect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
[self.scrollToBottomButton setImage:[UIImage imageNamed:@"scrolldown_dark"] forState:UIControlStateNormal];
}
else if (@available(iOS 12.0, *) && ThemeService.shared.theme.userInterfaceStyle == UIUserInterfaceStyleDark) {
[self.scrollToBottomButton setImage:[UIImage imageNamed:@"scrolldown_dark"] forState:UIControlStateNormal];
}
self.scrollToBottomBadgeLabel.badgeColor = ThemeService.shared.theme.tintColor;
[self setNeedsStatusBarAppearanceUpdate];
}
@@ -1276,7 +1289,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
[super destroy];
}
#pragma mark -
#pragma mark - Properties
-(void)setActivitiesViewExpanded:(BOOL)activitiesViewExpanded
{
@@ -1294,6 +1307,19 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
missedDiscussionsBadgeLabel.hidden = !showMissedDiscussionsBadge;
}
- (void)setScrollToBottomHidden:(BOOL)scrollToBottomHidden
{
if (_scrollToBottomHidden != scrollToBottomHidden)
{
_scrollToBottomHidden = scrollToBottomHidden;
}
[UIView animateWithDuration:.2 animations:^{
self.scrollToBottomBadgeLabel.alpha = (scrollToBottomHidden || !self.scrollToBottomBadgeLabel.text) ? 0 : 1;
self.scrollToBottomButton.alpha = scrollToBottomHidden ? 0 : 1;
}];
}
#pragma mark - Internals
- (void)forceLayoutRefresh
@@ -3647,6 +3673,11 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
[widgetPicker showInViewController:self];
}
- (void)scrollToBottomAction:(id)sender
{
[self goBackToLive];
}
- (IBAction)onButtonPressed:(id)sender
{
if (sender == self.jumpToLastUnreadButton)
@@ -4360,15 +4391,12 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
// Retrieve the unread messages count
NSUInteger unreadCount = self.roomDataSource.room.summary.localUnreadEventCount;
self.activitiesViewExpanded = YES;
[roomActivitiesView displayScrollToBottomIcon:unreadCount onIconTapGesture:^{
[self goBackToLive];
}];
self.scrollToBottomBadgeLabel.text = unreadCount ? [NSString stringWithFormat:@"%lu", unreadCount] : nil;
self.scrollToBottomHidden = NO;
}
else if (serverNotices.usageLimit && serverNotices.usageLimit.isServerNoticeUsageLimit)
{
self.scrollToBottomHidden = YES;
self.activitiesViewExpanded = YES;
[roomActivitiesView showResourceUsageLimitNotice:serverNotices.usageLimit onAdminContactTapped:^(NSURL *adminContactURL) {
[[UIApplication sharedApplication] vc_open:adminContactURL completionHandler:^(BOOL success) {
@@ -4381,6 +4409,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo
}
else
{
self.scrollToBottomHidden = YES;
self.activitiesViewExpanded = NO;
[self refreshTypingNotification];
}
+25
View File
@@ -29,6 +29,8 @@
<outlet property="roomInputToolbarContainer" destination="nLd-BP-JAE" id="1dp-P1-0js"/>
<outlet property="roomInputToolbarContainerBottomConstraint" destination="omU-sm-3bK" id="qaT-Ej-BdE"/>
<outlet property="roomInputToolbarContainerHeightConstraint" destination="5eD-Fm-RDb" id="6ny-5w-1UA"/>
<outlet property="scrollToBottomBadgeLabel" destination="QHs-rM-UU8" id="wk7-PQ-9Jm"/>
<outlet property="scrollToBottomButton" destination="Ih9-EU-BOU" id="Wwg-gS-Sfp"/>
<outlet property="view" destination="iN0-l3-epB" id="ieV-u7-rXU"/>
</connections>
</placeholder>
@@ -130,6 +132,19 @@
<constraint firstItem="ISb-UT-u0O" firstAttribute="centerY" secondItem="Vlz-UJ-Jz8" secondAttribute="centerY" id="w7t-WC-VjP"/>
</constraints>
</view>
<button opaque="NO" alpha="0.0" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Ih9-EU-BOU" userLabel="scroll Button">
<rect key="frame" x="327" y="570" width="32" height="32"/>
<state key="normal" image="scrolldown"/>
<connections>
<action selector="scrollToBottomAction:" destination="-1" eventType="touchUpInside" id="TOf-aY-J6a"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" alpha="0.0" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="0" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QHs-rM-UU8" userLabel="scroll badge" customClass="BadgeLabel" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="334" y="562.5" width="18" height="15.5"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="11"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<view clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XX4-n6-hCm" userLabel="Activities Container">
<rect key="frame" x="0.0" y="626" width="375" height="0.0"/>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
@@ -158,12 +173,16 @@
<constraint firstAttribute="bottom" secondItem="BGD-sd-SQR" secondAttribute="bottom" constant="41" id="1SD-y2-oTg"/>
<constraint firstItem="S6r-bo-jxw" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="5eM-eJ-khq"/>
<constraint firstItem="lPR-zi-UZr" firstAttribute="trailing" secondItem="QpJ-1u-4ii" secondAttribute="trailing" id="6no-fN-liL"/>
<constraint firstItem="QpJ-1u-4ii" firstAttribute="trailing" secondItem="Ih9-EU-BOU" secondAttribute="trailing" constant="16" id="6rq-lR-0sB"/>
<constraint firstItem="54r-18-K1g" firstAttribute="top" secondItem="iN0-l3-epB" secondAttribute="top" id="7Ft-EV-Br0"/>
<constraint firstItem="gt1-EO-UVY" firstAttribute="leading" secondItem="QpJ-1u-4ii" secondAttribute="leading" id="8Ff-Ot-h3F"/>
<constraint firstItem="S6r-bo-jxw" firstAttribute="leading" secondItem="QpJ-1u-4ii" secondAttribute="leading" id="Bcq-e4-B0D"/>
<constraint firstItem="BGD-sd-SQR" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" id="ECb-mP-EOG"/>
<constraint firstAttribute="trailing" secondItem="BGD-sd-SQR" secondAttribute="trailing" id="EGD-cX-OGq"/>
<constraint firstItem="XX4-n6-hCm" firstAttribute="top" secondItem="Ih9-EU-BOU" secondAttribute="bottom" constant="24" id="GUp-ZU-6h3"/>
<constraint firstItem="lPR-zi-UZr" firstAttribute="bottom" secondItem="iN0-l3-epB" secondAttribute="bottom" id="HJy-rU-H5H"/>
<constraint firstItem="QHs-rM-UU8" firstAttribute="centerX" secondItem="Ih9-EU-BOU" secondAttribute="centerX" id="K8X-wJ-hkh"/>
<constraint firstItem="QHs-rM-UU8" firstAttribute="centerY" secondItem="Ih9-EU-BOU" secondAttribute="top" id="KL4-OU-cP6"/>
<constraint firstItem="gt1-EO-UVY" firstAttribute="trailing" secondItem="QpJ-1u-4ii" secondAttribute="trailing" id="L9A-P5-xeT"/>
<constraint firstItem="XX4-n6-hCm" firstAttribute="leading" secondItem="QpJ-1u-4ii" secondAttribute="leading" id="Os4-cU-eQb"/>
<constraint firstItem="XX4-n6-hCm" firstAttribute="bottom" secondItem="nLd-BP-JAE" secondAttribute="top" id="QO8-nF-xys"/>
@@ -184,8 +203,14 @@
<point key="canvasLocation" x="136.80000000000001" y="152.47376311844079"/>
</view>
</objects>
<designables>
<designable name="QHs-rM-UU8">
<size key="intrinsicContentSize" width="17.5" height="15.5"/>
</designable>
</designables>
<resources>
<image name="cancel" width="20" height="20"/>
<image name="scrolldown" width="32" height="32"/>
<image name="scrollup" width="30" height="30"/>
</resources>
</document>
@@ -73,16 +73,6 @@
*/
- (void)displayOngoingConferenceCall:(void (^)(BOOL video))ongoingConferenceCallPressed onClosePressed:(void (^)(void))ongoingConferenceCallClosePressed;
/**
Display a "scroll to bottom" icon.
Replace the current notification if any.
@param newMessagesCount the count of the unread messages.
@param onIconTapGesture block called when user taps on notification icon.
*/
- (void)displayScrollToBottomIcon:(NSUInteger)newMessagesCount onIconTapGesture:(void (^)(void))onIconTapGesture;
/**
Notify that the a room is obsolete and a replacement room is available.
@@ -268,62 +268,6 @@
[self checkHeight:YES];
}
- (void)displayScrollToBottomIcon:(NSUInteger)newMessagesCount onIconTapGesture:(void (^)(void))onIconTapGesture
{
if (newMessagesCount)
{
[self reset];
self.iconImageView.image = [UIImage imageNamed:@"scrolldown"];
self.iconImageView.tintColor = ThemeService.shared.theme.noticeColor;
NSString *notification;
if (newMessagesCount > 1)
{
notification = NSLocalizedStringFromTable(@"room_new_messages_notification", @"Vector", nil);
}
else
{
notification = NSLocalizedStringFromTable(@"room_new_message_notification", @"Vector", nil);
}
self.messageLabel.text = [NSString stringWithFormat:notification, newMessagesCount];
self.messageLabel.textColor = ThemeService.shared.theme.warningColor;
self.messageLabel.hidden = NO;
}
else
{
self.unsentMessagesContentView.hidden = YES;
// We keep the current message if any
[self resetIcon];
self.messageLabel.text = nil;
self.iconImageView.image = [UIImage imageNamed:@"scrolldown"];
self.iconImageView.tintColor = ThemeService.shared.theme.textPrimaryColor;
}
self.iconImageView.hidden = NO;
// Make VoiceOver consider it as a button
self.iconImageView.accessibilityLabel = NSLocalizedStringFromTable(@"room_accessiblity_scroll_to_bottom", @"Vector", nil);
self.iconImageView.isAccessibilityElement = YES;
self.iconImageView.accessibilityTraits = UIAccessibilityTraitButton;
if (onIconTapGesture)
{
objc_setAssociatedObject(self.iconImageView, "onIconTapGesture", [onIconTapGesture copy], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
// Listen to icon tap
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onIconTap:)];
[tapGesture setNumberOfTouchesRequired:1];
[tapGesture setNumberOfTapsRequired:1];
[tapGesture setDelegate:self];
[self.iconImageView addGestureRecognizer:tapGesture];
self.iconImageView.userInteractionEnabled = YES;
}
[self checkHeight:YES];
}
- (void)displayRoomReplacementWithRoomLinkTappedHandler:(void (^)(void))onRoomReplacementLinkTapped
{
[self reset];
@@ -85,7 +85,7 @@
growingTextView.font = [UIFont systemFontOfSize:15];
growingTextView.textColor = ThemeService.shared.theme.textPrimaryColor;
growingTextView.tintColor = ThemeService.shared.theme.tintColor;
growingTextView.placeholderColor = ThemeService.shared.theme.textTertiaryColor;
growingTextView.internalTextView.showsVerticalScrollIndicator = NO;
growingTextView.internalTextView.keyboardAppearance = ThemeService.shared.theme.keyboardAppearance;
@@ -100,6 +100,19 @@
UIImage *image = [UIImage imageNamed:@"input_text_background"];
image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(9, 15, 10, 16)];
self.inputTextBackgroundView.image = image;
self.inputTextBackgroundView.tintColor = ThemeService.shared.theme.roomInputTextBorder;
if ([ThemeService.shared.themeId isEqualToString:@"light"])
{
[self.attachMediaButton setImage:[UIImage imageNamed:@"upload_icon"] forState:UIControlStateNormal];
}
else if ([ThemeService.shared.themeId isEqualToString:@"dark"] || [ThemeService.shared.themeId isEqualToString:@"black"])
{
[self.attachMediaButton setImage:[UIImage imageNamed:@"upload_icon_dark"] forState:UIControlStateNormal];
}
else if (@available(iOS 12.0, *) && ThemeService.shared.theme.userInterfaceStyle == UIUserInterfaceStyleDark) {
[self.attachMediaButton setImage:[UIImage imageNamed:@"upload_icon_dark"] forState:UIControlStateNormal];
}
}
#pragma mark -
@@ -187,21 +200,15 @@
if (self.rightInputToolbarButton.isEnabled && !self.rightInputToolbarButton.alpha)
{
[UIView animateWithDuration:.4 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:8 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.rightInputToolbarButton.alpha = 1;
self.messageComposerContainerTrailingConstraint.constant = self.frame.size.width - self.rightInputToolbarButton.frame.origin.x + 12;
[self layoutIfNeeded];
} completion:^(BOOL finished) {
}];
self.rightInputToolbarButton.alpha = 1;
self.messageComposerContainerTrailingConstraint.constant = self.frame.size.width - self.rightInputToolbarButton.frame.origin.x + 12;
[self layoutIfNeeded];
}
else if (!self.rightInputToolbarButton.isEnabled && self.rightInputToolbarButton.alpha)
{
[UIView animateWithDuration:.4 delay:0 usingSpringWithDamping:0.7 initialSpringVelocity:8 options:UIViewAnimationOptionCurveEaseIn animations:^{
self.rightInputToolbarButton.alpha = 0;
self.messageComposerContainerTrailingConstraint.constant = 12;
[self layoutIfNeeded];
} completion:^(BOOL finished) {
}];
self.rightInputToolbarButton.alpha = 0;
self.messageComposerContainerTrailingConstraint.constant = 12;
[self layoutIfNeeded];
}
}
@@ -14,13 +14,13 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="a84-Vc-6ud" userLabel="MainToolBar View">
<rect key="frame" x="0.0" y="0.0" width="600" height="60"/>
<rect key="frame" x="0.0" y="2" width="600" height="58"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Hga-l8-Wua" userLabel="attach Button">
<rect key="frame" x="12" y="12" width="46" height="36"/>
<rect key="frame" x="12" y="10" width="36" height="36"/>
<accessibility key="accessibilityConfiguration" identifier="AttachButton"/>
<constraints>
<constraint firstAttribute="width" constant="46" id="O2T-T8-EjV"/>
<constraint firstAttribute="width" constant="36" id="O2T-T8-EjV"/>
</constraints>
<state key="normal" image="upload_icon"/>
<connections>
@@ -28,13 +28,13 @@
</connections>
</button>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="QWp-NV-uh5" userLabel="Message Composer Container">
<rect key="frame" x="70" y="10" width="518" height="40"/>
<rect key="frame" x="60" y="9" width="528" height="36"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="input_text_background" translatesAutoresizingMaskIntoConstraints="NO" id="uH7-Q7-hpZ">
<rect key="frame" x="0.0" y="0.0" width="518" height="42"/>
<rect key="frame" x="0.0" y="0.0" width="528" height="38"/>
</imageView>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="wgb-ON-N29" customClass="KeyboardGrowingTextView">
<rect key="frame" x="4" y="1" width="510" height="40"/>
<rect key="frame" x="4" y="1" width="520" height="36"/>
<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>
@@ -52,7 +52,7 @@
</constraints>
</view>
<button opaque="NO" alpha="0.0" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="G8Z-CM-tGs" userLabel="send Button">
<rect key="frame" x="552" y="12" width="36" height="36"/>
<rect key="frame" x="552" y="10" width="36" height="36"/>
<accessibility key="accessibilityConfiguration" identifier="SendButton"/>
<state key="normal" image="send_icon"/>
<connections>
@@ -61,15 +61,15 @@
</button>
</subviews>
<constraints>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="60" id="1FO-iu-urG"/>
<constraint firstAttribute="height" relation="greaterThanOrEqual" constant="58" id="1FO-iu-urG"/>
<constraint firstItem="Hga-l8-Wua" firstAttribute="leading" secondItem="a84-Vc-6ud" secondAttribute="leading" constant="12" id="31r-fn-347"/>
<constraint firstItem="G8Z-CM-tGs" firstAttribute="centerY" secondItem="a84-Vc-6ud" secondAttribute="centerY" id="Fsw-LO-vgm"/>
<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="10" id="NGr-2o-sOP"/>
<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="QWp-NV-uh5" firstAttribute="top" secondItem="a84-Vc-6ud" secondAttribute="top" constant="10" id="WyZ-3i-OHi"/>
<constraint firstItem="Hga-l8-Wua" firstAttribute="centerY" secondItem="a84-Vc-6ud" secondAttribute="centerY" id="YND-k2-HMH"/>
<constraint firstAttribute="height" constant="60" id="Yjj-ua-rbe"/>
<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"/>
</constraints>
</view>