diff --git a/Signal/src/UIView+OWS.h b/Signal/src/UIView+OWS.h index d6404cc43..c66a2e3a7 100644 --- a/Signal/src/UIView+OWS.h +++ b/Signal/src/UIView+OWS.h @@ -65,6 +65,12 @@ CGFloat ScaleFromIPhone5(CGFloat iPhone5Value); // For correct right-to-left layout behavior, use "leading" and "trailing", // not "left" and "right". // +// These methods use layoutMarginsGuide anchors, which behave differently than +// the PureLayout alternatives you indicated. Honoring layoutMargins is +// particularly important in cell layouts, where it lets us align with the +// complicated built-in behavior of table and collection view cells' default +// contents. +// // NOTE: the margin values are inverted in RTL layouts. - (BOOL)isRTL; - (NSArray *)autoPinLeadingAndTrailingToSuperview; diff --git a/Signal/src/UIView+OWS.m b/Signal/src/UIView+OWS.m index 201046a7d..206189177 100644 --- a/Signal/src/UIView+OWS.m +++ b/Signal/src/UIView+OWS.m @@ -221,11 +221,6 @@ CGFloat ScaleFromIPhone5(CGFloat iPhone5Value) == UIUserInterfaceLayoutDirectionRightToLeft); } -- (CGFloat)rtlSafeConstant:(CGFloat)value -{ - return (self.isRTL ? -value : value); -} - - (NSLayoutConstraint *)autoPinLeadingToSuperView { return [self autoPinLeadingToSuperViewWithMargin:0]; @@ -247,8 +242,7 @@ CGFloat ScaleFromIPhone5(CGFloat iPhone5Value) - (NSLayoutConstraint *)autoPinTrailingToSuperViewWithMargin:(CGFloat)margin { NSLayoutConstraint *constraint = - [self.trailingAnchor constraintEqualToAnchor:self.superview.layoutMarginsGuide.trailingAnchor - constant:[self rtlSafeConstant:margin]]; + [self.trailingAnchor constraintEqualToAnchor:self.superview.layoutMarginsGuide.trailingAnchor constant:-margin]; constraint.active = YES; return constraint; } @@ -280,8 +274,7 @@ CGFloat ScaleFromIPhone5(CGFloat iPhone5Value) { OWSAssert(view); - NSLayoutConstraint *constraint = - [self.leadingAnchor constraintEqualToAnchor:view.leadingAnchor constant:[self rtlSafeConstant:margin]]; + NSLayoutConstraint *constraint = [self.leadingAnchor constraintEqualToAnchor:view.leadingAnchor constant:margin]; constraint.active = YES; return constraint; } @@ -297,8 +290,7 @@ CGFloat ScaleFromIPhone5(CGFloat iPhone5Value) { OWSAssert(view); - NSLayoutConstraint *constraint = - [self.trailingAnchor constraintEqualToAnchor:view.trailingAnchor constant:[self rtlSafeConstant:margin]]; + NSLayoutConstraint *constraint = [self.trailingAnchor constraintEqualToAnchor:view.trailingAnchor constant:margin]; constraint.active = YES; return constraint; } diff --git a/Signal/src/ViewControllers/CallViewController.swift b/Signal/src/ViewControllers/CallViewController.swift index 4d391e15a..640fd7408 100644 --- a/Signal/src/ViewControllers/CallViewController.swift +++ b/Signal/src/ViewControllers/CallViewController.swift @@ -511,7 +511,7 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R hasConstraints = true let topMargin = CGFloat(40) - let contactHMargin = CGFloat(0) + let contactHMargin = CGFloat(5) let contactVSpacing = CGFloat(3) let ongoingHMargin = ScaleFromIPhone5To7Plus(46, 72) let incomingHMargin = ScaleFromIPhone5To7Plus(46, 72) @@ -632,9 +632,9 @@ class CallViewController: UIViewController, CallObserver, CallServiceObserver, R var constraints: [NSLayoutConstraint] = [] if localVideoView.isHidden { - let contactHMargin = CGFloat(0) - constraints.append(contactNameLabel.autoPinTrailingToSuperView()) - constraints.append(callStatusLabel.autoPinTrailingToSuperView()) + let contactHMargin = CGFloat(5) + constraints.append(contactNameLabel.autoPinTrailingToSuperView(withMargin: contactHMargin)) + constraints.append(callStatusLabel.autoPinTrailingToSuperView(withMargin: contactHMargin)) } else { let spacing = CGFloat(10) constraints.append(localVideoView.autoPinLeading(toTrailingOf: contactNameLabel, margin: spacing)) diff --git a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m index 2780ab960..6189765ce 100644 --- a/Signal/src/ViewControllers/ConversationView/MessagesViewController.m +++ b/Signal/src/ViewControllers/ConversationView/MessagesViewController.m @@ -1079,7 +1079,10 @@ typedef enum : NSUInteger { // This method gets called multiple times, so it's important we re-layout the unread badge // with respect to the new backItem. [backItem.customView addSubview:_backButtonUnreadCountView]; - // TODO: + // TODO: The back button assets are assymetrical. There are strong reasons + // to use spacing in the assets to manipulate the size and positioning of + // bar button items, but it means we'll probably need separate RTL and LTR + // flavors of these assets. [_backButtonUnreadCountView autoPinEdgeToSuperviewEdge:ALEdgeTop withInset:-6]; [_backButtonUnreadCountView autoPinLeadingToSuperViewWithMargin:1]; [_backButtonUnreadCountView autoSetDimension:ALDimensionHeight toSize:unreadCountViewDiameter]; diff --git a/Signal/src/ViewControllers/ConversationView/OWSMessagesToolbarContentView.m b/Signal/src/ViewControllers/ConversationView/OWSMessagesToolbarContentView.m index 9b59ab19c..3190717eb 100644 --- a/Signal/src/ViewControllers/ConversationView/OWSMessagesToolbarContentView.m +++ b/Signal/src/ViewControllers/ConversationView/OWSMessagesToolbarContentView.m @@ -142,6 +142,9 @@ NS_ASSUME_NONNULL_BEGIN if (self.isRecordingVoiceMemo) { // Check for "slide to cancel" gesture. CGPoint location = [sender locationInView:self]; + // For LTR/RTL, swiping in either direction will cancel. + // This is okay because there's only space on screen to perform the + // gesture in one direction. CGFloat offset = fabs(self.voiceMemoGestureStartLocation.x - location.x); // The lower this value, the easier it is to cancel by accident. // The higher this value, the harder it is to cancel. diff --git a/Signal/src/ViewControllers/InboxTableViewCell.m b/Signal/src/ViewControllers/InboxTableViewCell.m index 720ce8390..cb65791a2 100644 --- a/Signal/src/ViewControllers/InboxTableViewCell.m +++ b/Signal/src/ViewControllers/InboxTableViewCell.m @@ -69,8 +69,8 @@ const NSUInteger kavatarViewDiameter = 52; self.avatarView = [[AvatarImageView alloc] init]; [self.contentView addSubview:self.avatarView]; - [self.avatarView autoSetDimension:ALDimensionWidth toSize:52.f]; - [self.avatarView autoSetDimension:ALDimensionHeight toSize:52.f]; + [self.avatarView autoSetDimension:ALDimensionWidth toSize:self.avatarSize]; + [self.avatarView autoSetDimension:ALDimensionHeight toSize:self.avatarSize]; [self.avatarView autoPinLeadingToSuperView]; [self.avatarView autoVCenterInSuperview]; @@ -134,6 +134,11 @@ const NSUInteger kavatarViewDiameter = 52; return 72.f; } +- (CGFloat)avatarSize +{ + return 52.f; +} + - (void)initializeLayout { self.selectionStyle = UITableViewCellSelectionStyleDefault; } @@ -206,7 +211,7 @@ const NSUInteger kavatarViewDiameter = 52; self.timeLabel.attributedText = attributedDate; self.avatarView.image = nil; - self.separatorInset = UIEdgeInsetsMake(0, _avatarView.frame.size.width * 1.5f, 0, 0); + self.separatorInset = UIEdgeInsetsMake(0, self.avatarSize * 1.5f, 0, 0); if (thread.hasUnreadMessages) { [self updateCellForUnreadMessage]; diff --git a/Signal/src/ViewControllers/MessageComposeTableViewController.m b/Signal/src/ViewControllers/MessageComposeTableViewController.m index 44ec72746..78c33b0c8 100644 --- a/Signal/src/ViewControllers/MessageComposeTableViewController.m +++ b/Signal/src/ViewControllers/MessageComposeTableViewController.m @@ -76,7 +76,7 @@ NS_ASSUME_NONNULL_BEGIN [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop target:self action:@selector(dismissPressed)]; - // TODO: + // TODO: We should use separate RTL and LTR flavors of this asset. UIImage *newGroupImage = [UIImage imageNamed:@"btnGroup--white"]; OWSAssert(newGroupImage); UIBarButtonItem *newGroupButton = [[UIBarButtonItem alloc] initWithImage:newGroupImage diff --git a/Signal/src/ViewControllers/NotificationSettingsViewController.m b/Signal/src/ViewControllers/NotificationSettingsViewController.m index 3435e89a2..008689e6c 100644 --- a/Signal/src/ViewControllers/NotificationSettingsViewController.m +++ b/Signal/src/ViewControllers/NotificationSettingsViewController.m @@ -39,9 +39,8 @@ NotificationType notifType = [prefs notificationPreviewType]; NSString *detailString = [prefs nameForNotificationPreviewType:notifType]; - - [[cell textLabel] setText:NSLocalizedString(@"NOTIFICATIONS_SHOW", nil)]; - [[cell detailTextLabel] setText:detailString]; + cell.textLabel.text = NSLocalizedString(@"NOTIFICATIONS_SHOW", nil); + cell.detailTextLabel.text = detailString; [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; return cell; diff --git a/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m b/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m index 7aad681cc..8ea19b0f8 100644 --- a/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m +++ b/Signal/src/ViewControllers/OWSConversationSettingsTableViewController.m @@ -435,7 +435,7 @@ NS_ASSUME_NONNULL_BEGIN OWSTableSection *muteSection = [OWSTableSection new]; [muteSection addItem:[OWSTableItem itemWithCustomCellBlock:^{ - UITableViewCell *cell = [UITableViewCell new]; + UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:nil]; cell.preservesSuperviewLayoutMargins = YES; cell.contentView.preservesSuperviewLayoutMargins = YES; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; @@ -482,14 +482,7 @@ NS_ASSUME_NONNULL_BEGIN [dateFormatter stringFromDate:mutedUntilDate]]; } - UILabel *statusLabel = [UILabel new]; - statusLabel.textColor = [UIColor colorWithWhite:0.5f alpha:1.f]; - statusLabel.font = [UIFont ows_regularFontWithSize:17.f]; - statusLabel.text = muteStatus; - [cell.contentView addSubview:statusLabel]; - [statusLabel autoVCenterInSuperview]; - // [statusLabel autoPinLeadingToTrailingOfView:rowLabel margin:weakSelf.iconSpacing]; - [statusLabel autoPinTrailingToSuperView]; + cell.detailTextLabel.text = muteStatus; return cell; } customRowHeight:45.f @@ -567,7 +560,7 @@ NS_ASSUME_NONNULL_BEGIN - (UIView *)mainSectionHeader { UIView *mainSectionHeader = [UIView new]; - UIView *threadInfoView = [UIView new]; + UIView *threadInfoView = [UIView containerView]; [mainSectionHeader addSubview:threadInfoView]; [threadInfoView autoPinWidthToSuperviewWithMargin:16.f]; [threadInfoView autoPinHeightToSuperviewWithMargin:16.f]; diff --git a/Signal/src/ViewControllers/SignalsViewController.m b/Signal/src/ViewControllers/SignalsViewController.m index c7137bf6a..72c87b476 100644 --- a/Signal/src/ViewControllers/SignalsViewController.m +++ b/Signal/src/ViewControllers/SignalsViewController.m @@ -29,8 +29,6 @@ #import #import -#define CELL_HEIGHT 72.0f - typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; @interface SignalsViewController () @@ -590,7 +588,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - return CELL_HEIGHT; + return InboxTableViewCell.rowHeight; } #pragma mark Table Swipe to Delete diff --git a/Signal/src/views/ContactTableViewCell.m b/Signal/src/views/ContactTableViewCell.m index 6a40f8e20..ba5a7389c 100644 --- a/Signal/src/views/ContactTableViewCell.m +++ b/Signal/src/views/ContactTableViewCell.m @@ -70,8 +70,7 @@ const NSUInteger kContactTableViewCellAvatarSize = 40; [_avatarView autoSetDimension:ALDimensionWidth toSize:kContactTableViewCellAvatarSize]; [_avatarView autoSetDimension:ALDimensionHeight toSize:kContactTableViewCellAvatarSize]; - [_nameLabel autoPinEdgeToSuperviewEdge:ALEdgeTop]; - [_nameLabel autoPinEdgeToSuperviewEdge:ALEdgeBottom]; + [_nameLabel autoVCenterInSuperview]; [_nameLabel autoPinLeadingToTrailingOfView:_avatarView margin:12.f]; [_nameLabel autoPinTrailingToSuperView]; @@ -168,38 +167,9 @@ const NSUInteger kContactTableViewCellAvatarSize = 40; self.subtitle.attributedText = text; [self.subtitle sizeToFit]; [self.contentView addSubview:self.subtitle]; - - [self setNeedsLayout]; -} - -- (void)setFrame:(CGRect)frame -{ - [super setFrame:frame]; - - [self layoutSubviews]; -} - -- (void)setBounds:(CGRect)bounds -{ - [super setBounds:bounds]; - - [self layoutSubviews]; -} - -- (void)layoutSubviews -{ - [super layoutSubviews]; - - if (self.subtitle) { - OWSAssert(self.nameLabel.superview == self.contentView); - const CGFloat kSubtitleVMargin - = ((self.contentView.height - self.nameLabel.font.lineHeight) * 0.5f - self.subtitle.height) * 0.5f; - self.subtitle.frame - = CGRectMake((self.isRTL ? round(self.nameLabel.right - self.subtitle.width) : self.nameLabel.left), - round((self.contentView.height - self.subtitle.height) - kSubtitleVMargin), - self.subtitle.width, - self.subtitle.height); - } + [self.subtitle autoPinLeadingToView:self.nameLabel]; + [self.subtitle autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:self.nameLabel]; + [self.subtitle autoPinEdgeToSuperviewEdge:ALEdgeBottom]; } - (void)prepareForReuse