From af2539f47332993cb303761f2f7268ae6076fcf5 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 23 Apr 2018 12:33:23 -0400 Subject: [PATCH 1/6] Rework archived conversations mode of home view. --- Signal/src/AppDelegate.m | 8 - .../HomeView/HomeViewController.h | 2 - .../HomeView/HomeViewController.m | 187 ++++++++++++------ Signal/src/network/PushManager.m | 1 - .../translations/en.lproj/Localizable.strings | 12 +- 5 files changed, 130 insertions(+), 80 deletions(-) diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 2f669220c..42e746506 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -707,14 +707,6 @@ static NSString *const kURLHostVerifyPrefix = @"verify"; DDLogWarn(@"%@ applicationWillResignActive.", self.logTag); - __block OWSBackgroundTask *backgroundTask = [OWSBackgroundTask backgroundTaskWithLabelStr:__PRETTY_FUNCTION__]; - [AppReadiness runNowOrWhenAppIsReady:^{ - if ([TSAccountManager isRegistered]) { - [SignalApp.sharedApp.homeViewController updateInboxCountLabel]; - } - backgroundTask = nil; - }]; - [DDLog flushLog]; } diff --git a/Signal/src/ViewControllers/HomeView/HomeViewController.h b/Signal/src/ViewControllers/HomeView/HomeViewController.h index 26f1858c3..632419ab0 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewController.h +++ b/Signal/src/ViewControllers/HomeView/HomeViewController.h @@ -13,8 +13,6 @@ keyboardOnViewAppearing:(BOOL)keyboardOnViewAppearing callOnViewAppearing:(BOOL)callOnViewAppearing; -- (void)updateInboxCountLabel; - - (void)showNewConversationView; - (void)presentTopLevelModalViewController:(UIViewController *)viewController diff --git a/Signal/src/ViewControllers/HomeView/HomeViewController.m b/Signal/src/ViewControllers/HomeView/HomeViewController.m index 1d507f74c..f2fb6e4b3 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewController.m +++ b/Signal/src/ViewControllers/HomeView/HomeViewController.m @@ -32,7 +32,12 @@ #import #import -typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; +typedef NS_ENUM(NSInteger, HomeViewMode) { + HomeViewMode_Archive, + HomeViewMode_Inbox, +}; + +NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversationsReuseIdentifier"; @interface HomeViewController () @@ -42,9 +47,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; @property (nonatomic) YapDatabaseConnection *editingDbConnection; @property (nonatomic) YapDatabaseConnection *uiDatabaseConnection; @property (nonatomic) YapDatabaseViewMappings *threadMappings; -@property (nonatomic) CellState viewingThreadsIn; -@property (nonatomic) long inboxCount; -@property (nonatomic) UISegmentedControl *segmentedControl; +@property (nonatomic) HomeViewMode homeViewMode; @property (nonatomic) id previewingContext; @property (nonatomic) NSSet *blockedPhoneNumberSet; @property (nonatomic, readonly) NSCache *threadViewModelCache; @@ -82,6 +85,8 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; return self; } + _homeViewMode = HomeViewMode_Inbox; + [self commonInit]; return self; @@ -213,6 +218,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; self.tableView.dataSource = self; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; [self.tableView registerClass:[HomeViewCell class] forCellReuseIdentifier:HomeViewCell.cellReuseIdentifier]; + [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:kArchivedConversationsReuseIdentifier]; [self.view addSubview:self.tableView]; [self.tableView autoPinWidthToSuperview]; [self.tableView autoPinEdgeToSuperviewEdge:ALEdgeBottom]; @@ -237,7 +243,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; - (void)updateReminderViews { - BOOL shouldHideArchiveReminderView = self.viewingThreadsIn != kArchiveState; + BOOL shouldHideArchiveReminderView = self.homeViewMode != HomeViewMode_Archive; BOOL shouldHideMissingContactsPermissionView = !self.shouldShowMissingContactsPermissionView; if (self.hideArchiveReminderViewConstraint.active == shouldHideArchiveReminderView && self.hideMissingContactsPermissionViewConstraint.active == shouldHideMissingContactsPermissionView) { @@ -265,18 +271,10 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; // after mappings have been set up in `showInboxGrouping` [self tableViewSetUp]; - self.segmentedControl = [[UISegmentedControl alloc] initWithItems:@[ - NSLocalizedString(@"WHISPER_NAV_BAR_TITLE", nil), - NSLocalizedString(@"ARCHIVE_NAV_BAR_TITLE", nil) - ]]; - - [self.segmentedControl addTarget:self - action:@selector(swappedSegmentedControl) - forControlEvents:UIControlEventValueChanged]; - UINavigationItem *navigationItem = self.navigationItem; - navigationItem.titleView = self.segmentedControl; - [self.segmentedControl setSelectedSegmentIndex:0]; - navigationItem.leftBarButtonItem.accessibilityLabel + // TODO: Should our app name be translated? Probably not. + self.title = NSLocalizedString(@"HOME_VIEW_TITLE", @"Title for the home view."); + + self.navigationItem.leftBarButtonItem.accessibilityLabel = NSLocalizedString(@"SETTINGS_BUTTON_ACCESSIBILITY", @"Accessibility hint for the settings button"); if ([self.traitCollection respondsToSelector:@selector(forceTouchCapability)] @@ -384,15 +382,6 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; }]; } -- (void)swappedSegmentedControl -{ - if (self.segmentedControl.selectedSegmentIndex == 0) { - [self showInboxGrouping]; - } else { - [self showArchiveGrouping]; - } -} - - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; @@ -408,8 +397,6 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; }]; } - [self updateInboxCountLabel]; - self.isViewVisible = YES; // When returning to home view, try to ensure that the "last" thread is still @@ -499,7 +486,6 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; [self reloadTableViewData]; [self checkIfEmptyView]; - [self updateInboxCountLabel]; // If the user hasn't already granted contact access // we don't want to request until they receive a message. @@ -601,7 +587,24 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return (NSInteger)[self.threadMappings numberOfItemsInSection:(NSUInteger)section]; + NSInteger result = (NSInteger)[self.threadMappings numberOfItemsInSection:(NSUInteger)section]; + if (self.homeViewMode == HomeViewMode_Inbox) { + // Add the "archived conversations" row. + result++; + } + return result; +} + +- (BOOL)isIndexPathForArchivedConversations:(NSIndexPath *)indexPath +{ + if (self.homeViewMode != HomeViewMode_Inbox) { + return NO; + } + if (indexPath.section != 0) { + return NO; + } + NSInteger cellCount = (NSInteger)[self.threadMappings numberOfItemsInSection:(NSUInteger)0]; + return indexPath.row == cellCount; } - (ThreadViewModel *)threadViewModelForIndexPath:(NSIndexPath *)indexPath @@ -622,6 +625,15 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([self isIndexPathForArchivedConversations:indexPath]) { + return [self cellForArchivedConversationsRow:tableView]; + } else { + return [self tableView:tableView cellForConversationAtIndexPath:indexPath]; + } +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForConversationAtIndexPath:(NSIndexPath *)indexPath { HomeViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:HomeViewCell.cellReuseIdentifier]; OWSAssert(cell); @@ -638,6 +650,53 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; return cell; } +- (UITableViewCell *)cellForArchivedConversationsRow:(UITableView *)tableView +{ + UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:kArchivedConversationsReuseIdentifier]; + OWSAssert(cell); + + for (UIView *subview in cell.contentView.subviews) { + [subview removeFromSuperview]; + } + + cell.backgroundColor = [UIColor whiteColor]; + + UIImage *disclosureImage = [UIImage imageNamed:(cell.isRTL ? @"NavBarBack" : @"NavBarBackRTL")]; + OWSAssert(disclosureImage); + UIImageView *disclosureImageView = [UIImageView new]; + disclosureImageView.image = [disclosureImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + // TODO: + disclosureImageView.tintColor = [UIColor colorWithRGBHex:0xd1d1d6]; + [disclosureImageView setContentHuggingHigh]; + [disclosureImageView setCompressionResistanceHigh]; + + UILabel *label = [UILabel new]; + label.text = NSLocalizedString(@"HOME_VIEW_ARCHIVED_CONVERSATIONS", @"Label for 'archived conversations' button."); + label.textAlignment = NSTextAlignmentCenter; + label.font = [UIFont ows_dynamicTypeBodyFont]; + label.textColor = [UIColor blackColor]; + + UIStackView *stackView = [UIStackView new]; + stackView.axis = UILayoutConstraintAxisHorizontal; + stackView.spacing = 5; + if (cell.isRTL) { + [stackView addArrangedSubview:disclosureImageView]; + [stackView addArrangedSubview:label]; + } else { + [stackView addArrangedSubview:label]; + [stackView addArrangedSubview:disclosureImageView]; + } + [cell.contentView addSubview:stackView]; + [stackView autoCenterInSuperview]; + // Constrain to cell margins. + [stackView autoPinEdgeToSuperviewMargin:ALEdgeTop relation:NSLayoutRelationGreaterThanOrEqual]; + [stackView autoPinEdgeToSuperviewMargin:ALEdgeBottom relation:NSLayoutRelationGreaterThanOrEqual]; + [stackView autoPinEdgeToSuperviewMargin:ALEdgeLeading relation:NSLayoutRelationGreaterThanOrEqual]; + [stackView autoPinEdgeToSuperviewMargin:ALEdgeTrailing relation:NSLayoutRelationGreaterThanOrEqual]; + + return cell; +} + - (TSThread *)threadForIndexPath:(NSIndexPath *)indexPath { __block TSThread *thread = nil; @@ -675,6 +734,10 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; - (NSArray *)tableView:(UITableView *)tableView editActionsForRowAtIndexPath:(NSIndexPath *)indexPath { + if ([self isIndexPathForArchivedConversations:indexPath]) { + return @[]; + } + UITableViewRowAction *deleteAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleDefault title:NSLocalizedString(@"TXT_DELETE_TITLE", nil) @@ -683,7 +746,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; }]; UITableViewRowAction *archiveAction; - if (self.viewingThreadsIn == kInboxState) { + if (self.homeViewMode == HomeViewMode_Inbox) { archiveAction = [UITableViewRowAction rowActionWithStyle:UITableViewRowActionStyleNormal title:NSLocalizedString(@"ARCHIVE_ACTION", @@ -761,7 +824,6 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; [thread removeWithTransaction:transaction]; }]; - _inboxCount -= (self.viewingThreadsIn == kArchiveState) ? 1 : 0; [self checkIfEmptyView]; } @@ -769,31 +831,26 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; { TSThread *thread = [self threadForIndexPath:indexPath]; - BOOL viewingThreadsIn = self.viewingThreadsIn; [self.editingDbConnection readWriteWithBlock:^(YapDatabaseReadWriteTransaction *transaction) { - viewingThreadsIn == kInboxState ? [thread archiveThreadWithTransaction:transaction] - : [thread unarchiveThreadWithTransaction:transaction]; + switch (self.homeViewMode) { + case HomeViewMode_Inbox: + [thread archiveThreadWithTransaction:transaction]; + break; + case HomeViewMode_Archive: + [thread unarchiveThreadWithTransaction:transaction]; + break; + } }]; [self checkIfEmptyView]; } -- (void)updateInboxCountLabel +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - NSUInteger numberOfItems = [OWSMessageUtils.sharedManager unreadMessagesCount]; - NSString *unreadString = NSLocalizedString(@"WHISPER_NAV_BAR_TITLE", nil); - - if (numberOfItems > 0) { - unreadString = [unreadString stringByAppendingFormat:@" (%@)", [OWSFormat formatInt:(int)numberOfItems]]; + if ([self isIndexPathForArchivedConversations:indexPath]) { + [self showArchiveGrouping]; + return; } - [_segmentedControl setTitle:unreadString forSegmentAtIndex:0]; - [_segmentedControl sizeToFit]; - [_segmentedControl.superview setNeedsLayout]; - [_segmentedControl reloadInputViews]; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ TSThread *thread = [self threadForIndexPath:indexPath]; [self presentThread:thread keyboardOnViewAppearing:NO callOnViewAppearing:NO]; [tableView deselectRowAtIndexPath:indexPath animated:YES]; @@ -896,22 +953,24 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; return _threadMappings; } +// TODO: Rework. - (void)showInboxGrouping { - self.viewingThreadsIn = kInboxState; + self.homeViewMode = HomeViewMode_Inbox; } +// TODO: Rework. - (void)showArchiveGrouping { - self.viewingThreadsIn = kArchiveState; + self.homeViewMode = HomeViewMode_Archive; } -- (void)setViewingThreadsIn:(CellState)viewingThreadsIn +// TODO: Rework. +- (void)setHomeViewMode:(HomeViewMode)homeViewMode { - BOOL didChange = _viewingThreadsIn != viewingThreadsIn; - _viewingThreadsIn = viewingThreadsIn; - self.segmentedControl.selectedSegmentIndex = (viewingThreadsIn == kInboxState ? 0 : 1); - if (didChange || !self.threadMappings) { + BOOL didChange = _homeViewMode != homeViewMode; + _homeViewMode = homeViewMode; + if (didChange || !_threadMappings) { [self updateMappings]; } else { [self checkIfEmptyView]; @@ -921,7 +980,12 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; - (NSString *)currentGrouping { - return self.viewingThreadsIn == kInboxState ? TSInboxGroup : TSArchiveGroup; + switch (self.homeViewMode) { + case HomeViewMode_Inbox: + return TSInboxGroup; + case HomeViewMode_Archive: + return TSArchiveGroup; + } } - (void)updateMappings @@ -1011,7 +1075,6 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; // We want this regardless of if we're currently viewing the archive. // So we run it before the early return - [self updateInboxCountLabel]; [self checkIfEmptyView]; if ([sectionChanges count] == 0 && [rowChanges count] == 0) { @@ -1047,13 +1110,11 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; case YapDatabaseViewChangeDelete: { [self.tableView deleteRowsAtIndexPaths:@[ rowChange.indexPath ] withRowAnimation:UITableViewRowAnimationAutomatic]; - _inboxCount += (self.viewingThreadsIn == kArchiveState) ? 1 : 0; break; } case YapDatabaseViewChangeInsert: { [self.tableView insertRowsAtIndexPaths:@[ rowChange.newIndexPath ] withRowAnimation:UITableViewRowAnimationAutomatic]; - _inboxCount -= (self.viewingThreadsIn == kArchiveState) ? 1 : 0; break; } case YapDatabaseViewChangeMove: { @@ -1078,10 +1139,10 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; { [_tableView setHidden:NO]; [_emptyBoxLabel setHidden:NO]; - if (self.viewingThreadsIn == kInboxState && [self.threadMappings numberOfItemsInGroup:TSInboxGroup] == 0) { + if (self.homeViewMode == HomeViewMode_Inbox && [self.threadMappings numberOfItemsInGroup:TSInboxGroup] == 0) { [self setEmptyBoxText]; [_tableView setHidden:YES]; - } else if (self.viewingThreadsIn == kArchiveState && + } else if (self.homeViewMode == HomeViewMode_Archive && [self.threadMappings numberOfItemsInGroup:TSArchiveGroup] == 0) { [self setEmptyBoxText]; [_tableView setHidden:YES]; @@ -1100,7 +1161,7 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState }; NSString *firstLine = @""; NSString *secondLine = @""; - if (self.viewingThreadsIn == kInboxState) { + if (self.homeViewMode == HomeViewMode_Inbox) { if ([Environment.preferences getHasSentAMessage]) { firstLine = NSLocalizedString(@"EMPTY_INBOX_FIRST_TITLE", @""); secondLine = NSLocalizedString(@"EMPTY_INBOX_FIRST_TEXT", @""); diff --git a/Signal/src/network/PushManager.m b/Signal/src/network/PushManager.m index 21e778bb6..0e950bbed 100644 --- a/Signal/src/network/PushManager.m +++ b/Signal/src/network/PushManager.m @@ -288,7 +288,6 @@ NSString *const Signal_Message_MarkAsRead_Identifier = @"Signal_Message_MarkAsRe [thread markAllAsReadWithTransaction:transaction]; } completionBlock:^{ - [SignalApp.sharedApp.homeViewController updateInboxCountLabel]; [self cancelNotificationsWithThreadId:threadId]; completionHandler(); diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 9fb15f040..ace80f060 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -76,9 +76,6 @@ /* Pressing this button moves a thread from the inbox to the archive */ "ARCHIVE_ACTION" = "Archive"; -/* No comment provided by engineer. */ -"ARCHIVE_NAV_BAR_TITLE" = "Archive"; - /* No comment provided by engineer. */ "ATTACHMENT" = "Attachment"; @@ -869,9 +866,15 @@ /* No comment provided by engineer. */ "GROUP_YOU_LEFT" = "You have left the group."; +/* Label for 'archived conversations' button. */ +"HOME_VIEW_ARCHIVED_CONVERSATIONS" = "Archived Conversations"; + /* A label for conversations with blocked users. */ "HOME_VIEW_BLOCKED_CONTACT_CONVERSATION" = "Blocked"; +/* Title for the home view. */ +"HOME_VIEW_TITLE" = "Signal"; + /* Call setup status label */ "IN_CALL_CONNECTING" = "Connecting…"; @@ -2110,9 +2113,6 @@ /* Activity indicator title, shown upon returning to the device manager, until you complete the provisioning process on desktop */ "WAITING_TO_COMPLETE_DEVICE_LINK_TEXT" = "Complete setup on Signal Desktop."; -/* No comment provided by engineer. */ -"WHISPER_NAV_BAR_TITLE" = "Inbox"; - /* Info Message when you disable disappearing messages */ "YOU_DISABLED_DISAPPEARING_MESSAGES_CONFIGURATION" = "You disabled disappearing messages."; From 9c7e9b795a3f608ec4c598f40d24c91709727b5b Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 23 Apr 2018 12:42:58 -0400 Subject: [PATCH 2/6] Rework archived conversations mode of home view. --- .../HomeView/HomeViewController.m | 64 ++++++++++--------- .../translations/en.lproj/Localizable.strings | 7 +- 2 files changed, 39 insertions(+), 32 deletions(-) diff --git a/Signal/src/ViewControllers/HomeView/HomeViewController.m b/Signal/src/ViewControllers/HomeView/HomeViewController.m index f2fb6e4b3..36a6b5534 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewController.m +++ b/Signal/src/ViewControllers/HomeView/HomeViewController.m @@ -182,11 +182,6 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations // TODO: Remove this. [SignalApp.sharedApp setHomeViewController:self]; - self.navigationItem.rightBarButtonItem = - [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose - target:self - action:@selector(showNewConversationView)]; - ReminderView *archiveReminderView = [ReminderView new]; archiveReminderView.text = NSLocalizedString( @"INBOX_VIEW_ARCHIVE_MODE_REMINDER", @"Label reminding the user that they are in archive mode."); @@ -265,17 +260,23 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations // Create the database connection. [self uiDatabaseConnection]; - [self showInboxGrouping]; + [self updateMappings]; + [self checkIfEmptyView]; + [self updateReminderViews]; // because this uses the table data source, `tableViewSetup` must happen // after mappings have been set up in `showInboxGrouping` [self tableViewSetUp]; - // TODO: Should our app name be translated? Probably not. - self.title = NSLocalizedString(@"HOME_VIEW_TITLE", @"Title for the home view."); - - self.navigationItem.leftBarButtonItem.accessibilityLabel - = NSLocalizedString(@"SETTINGS_BUTTON_ACCESSIBILITY", @"Accessibility hint for the settings button"); + switch (self.homeViewMode) { + case HomeViewMode_Inbox: + // TODO: Should our app name be translated? Probably not. + self.title = NSLocalizedString(@"HOME_VIEW_TITLE_INBOX", @"Title for the home view's default mode."); + break; + case HomeViewMode_Archive: + self.title = NSLocalizedString(@"HOME_VIEW_TITLE_ARCHIVE", @"Title for the home view's 'archive' mode."); + break; + } if ([self.traitCollection respondsToSelector:@selector(forceTouchCapability)] && (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)) { @@ -294,6 +295,9 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations - (void)updateBarButtonItems { + if (self.homeViewMode != HomeViewMode_Inbox) { + return; + } const CGFloat kBarButtonSize = 44; // We use UIButtons with [UIBarButtonItem initWithCustomView:...] instead of // UIBarButtonItem in order to ensure that these buttons are spaced tightly. @@ -325,7 +329,15 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations 0, round(image.size.width + imageEdgeInsets.left + imageEdgeInsets.right), round(image.size.height + imageEdgeInsets.top + imageEdgeInsets.bottom)); - self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:button]; + UIBarButtonItem *settingsButton = [[UIBarButtonItem alloc] initWithCustomView:button]; + settingsButton.accessibilityLabel + = NSLocalizedString(@"SETTINGS_BUTTON_ACCESSIBILITY", @"Accessibility hint for the settings button"); + self.navigationItem.leftBarButtonItem = settingsButton; + + self.navigationItem.rightBarButtonItem = + [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCompose + target:self + action:@selector(showNewConversationView)]; } - (void)settingsButtonPressed:(id)sender @@ -847,7 +859,7 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if ([self isIndexPathForArchivedConversations:indexPath]) { - [self showArchiveGrouping]; + [self showArchivedConversations]; return; } @@ -953,29 +965,21 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations return _threadMappings; } -// TODO: Rework. - (void)showInboxGrouping { - self.homeViewMode = HomeViewMode_Inbox; -} + OWSAssert(self.homeViewMode == HomeViewMode_Archive); -// TODO: Rework. -- (void)showArchiveGrouping -{ - self.homeViewMode = HomeViewMode_Archive; + [self.navigationController popToRootViewControllerAnimated:YES]; } -// TODO: Rework. -- (void)setHomeViewMode:(HomeViewMode)homeViewMode +- (void)showArchivedConversations { - BOOL didChange = _homeViewMode != homeViewMode; - _homeViewMode = homeViewMode; - if (didChange || !_threadMappings) { - [self updateMappings]; - } else { - [self checkIfEmptyView]; - [self updateReminderViews]; - } + OWSAssert(self.homeViewMode == HomeViewMode_Inbox); + + // Push a separate instance of this view using "archive" mode. + HomeViewController *homeView = [HomeViewController new]; + homeView.homeViewMode = HomeViewMode_Archive; + [self.navigationController pushViewController:homeView animated:YES]; } - (NSString *)currentGrouping diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index ace80f060..539d40f16 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -872,8 +872,11 @@ /* A label for conversations with blocked users. */ "HOME_VIEW_BLOCKED_CONTACT_CONVERSATION" = "Blocked"; -/* Title for the home view. */ -"HOME_VIEW_TITLE" = "Signal"; +/* Title for the home view's 'archive' mode. */ +"HOME_VIEW_TITLE_ARCHIVE" = "Archive"; + +/* Title for the home view's default mode. */ +"HOME_VIEW_TITLE_INBOX" = "Signal"; /* Call setup status label */ "IN_CALL_CONNECTING" = "Connecting…"; From fe9a61117cc035be895892f4d987b8559b0ed14b Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 23 Apr 2018 13:49:11 -0400 Subject: [PATCH 3/6] Rework archived conversations mode of home view. --- .../Contents.json | 23 +++++++ .../DisclosureIndicatorRTL@1x.png | Bin 0 -> 1417 bytes .../DisclosureIndicatorRTL@2x.png | Bin 0 -> 1702 bytes .../DisclosureIndicatorRTL@3x.png | Bin 0 -> 1981 bytes .../HomeView/HomeViewController.m | 46 ++++++++----- .../NewContactThreadViewController.m | 12 ++-- Signal/src/views/ReminderView.swift | 63 +++++++++++++----- .../translations/en.lproj/Localizable.strings | 2 +- 8 files changed, 103 insertions(+), 43 deletions(-) create mode 100644 Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/Contents.json create mode 100644 Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/DisclosureIndicatorRTL@1x.png create mode 100644 Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/DisclosureIndicatorRTL@2x.png create mode 100644 Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/DisclosureIndicatorRTL@3x.png diff --git a/Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/Contents.json b/Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/Contents.json new file mode 100644 index 000000000..433f40bea --- /dev/null +++ b/Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "DisclosureIndicatorRTL@1x.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "DisclosureIndicatorRTL@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "DisclosureIndicatorRTL@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/DisclosureIndicatorRTL@1x.png b/Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/DisclosureIndicatorRTL@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..5ce140e4bff056e18e2b7ddc77d2d9524a3ba864 GIT binary patch literal 1417 zcmeAS@N?(olHy`uVBq!ia0vp^LO?9a!3HF~Pw#sVq*&4&eH|GXHuiJ>Nn{1`ISV`@ ziy0UcEkKyjb(&!UP>o7vNJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8Erc zlUHn2VXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1A zfjnEKjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf| zi<65o3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp&g7)QU_T z+CVZmwWTD(eN|9elmqrtO0s@xPHJvyUP&=fpCMN3fME;Qh~mhK!~%$A;6Q}<%?9Lh ztDw~4{G3uy5QOGsme?8DfIWmRj0h2kF6aE*f}+&oVxTrVQ>YeXF?9722y5(&49%cA zkVVmT_!ngYy_yJen4KY1J+c_O`bexcAd4dD00q8PKxRd1PJ~M)Fi64vFto7I$0~uY z(K$aSzbLpMF*z0FGO!jTA#~MXYa$WW7{Tz_eiHo1c=IR_T&hl4@sUU}&LhV4`be9Aao}Wnf}uYH6d7rUuCcAQ|VP z)WnkfqLBRj96PXMb3t4MV?A?-PGotgRvUd#K0?Y@kW32}1?E~iE}%|W31G+du0|>c zSSbAVba4!^5L`ONo9mE)i0f6c!Y4^qg%8&K$zQCuK*^%OlTT)ckm)>gj+Q^S zF0fCx$-B3+H*@3l>`1Sbva`0xeD4?B;27i|@?*JF%z>>c5~1b_@60}&;+XKQf$d$& z5yl9v%n;Z6{R;2I8f1eWtIkhJoa1y$`_!G|t}+cfC%D~x@tNaM9^(zg@;wW!B?~0Z zP53iMe$u3`jc$xb@|i_mbeHVSJofKp2lo`^O7CAT^1r%&2)md2@B4f| e*Yku)NtgZkyE9MOCf4VI3P(>@KbLh*2~7YPIMAj5 literal 0 HcmV?d00001 diff --git a/Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/DisclosureIndicatorRTL@2x.png b/Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/DisclosureIndicatorRTL@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..a6abf47c383d7bf52f952055156047febfef1c6d GIT binary patch literal 1702 zcmeAS@N?(olHy`uVBq!ia0vp^DnP8o!3HF6bNze)q*&4&eH|GXHuiJ>Nn{1`ISV`@ ziy0UcEkKyjb(&!UP>o7vNJL45ua8x7ey(0(N`6wRUPW#JP&EUCO@$SZnVVXYs8Erc zlUHn2VXFjIVFhG^g!Ppaz)DK8ZIvQ?0~DO|i&7O#^-S~(l1A zfjnEKjFOT9D}DX)@^Za$W4-*MbbUihOG|wNBYh(yU7!lx;>x^|#0uTKVr7USFmqf| zi<65o3raHc^AtelCMM;Vme?vOfh>Xph&xL%(-1c06+^uR^q@XSM&D4+Kp&g7)QU_T z+CVZmwWTD(eN|9elmqrtO0s@xPHJvyUP&=fpCMN3fME;Qh~mhK!~%$A;6Q}<%?9Lh ztDw~4{G3uy5QOGsme?8DfIWmRj0h2kF6aE*f}+&oVxTrVQ>YeXF?9722y5(&49%cA zkVVmT_!ngYy_yJen4KY1J+c_O`bexcAd4dD00q8PKxRd1PJ~M)Fi64vFa|mcs|316 z=lq=fqTqtW-m&{c!2i9}dq0t{k=HAoUj8dH+3ic6ESQj<%N;tLpS;MDJw zn68f`Y@?4=wGA*WSo!9sWTsWRB$lMw85tN_=o*;l8X1Qe8e18dSeY8w=%cAYasf!j zxhOTUB)=#mKR?F~?2B9wSHW1%9HJ9h9;($wAC!-f@)ac0f<=M3){YCP6IKG)aq+EQ z+RVVfB;o1e7!tv`cZRq3VF!`c+VHhe@;`38&@Xv-u64gd!1SxXSVU{OyEL?JtlfWP ze*nwYI(DfON_!<|K8dqXIkVUJ`I(t1R=)oJ2QTJrXFni%L!;uwfByCk#S08w`Wrs| z59E5q_*3BqD3++lH?XB#H(^Y*kuc6y`vw&%%sLJ1HlUwe{JIzd|RXjpj~2eZP0| zOh+^JSqHjuCpml0zqEdWZo{7I_wKHo&>Ogj&AVJfvBAe)_Ezzlf^w}V$G0{ng)diA zxbpE3S7%Y}?~-pAHc+4r?xyZ$@ zRQRiJ-d$IZSxc0&x?k&iI3oo1K-RHKp^5>XQ2>tmIipR1RclAn~SSCLx)RL#I(Q(*;U=BAb;Dpcg= zfKjI1nLzvjMr> zDk!x$Kc^HF1fhAEC3Z$OU=N`SBSHkC%Q-){peVJt7^uz86siST3|)N$!WugxLo=uj zWKnb-{zaKUuO@;VW@iXhk1U3+J`$@9$f8I(K!I-+kXezM6XB8x3{r?cOlmznNg!!VNwz93P0C75Ez_eiHo1c=IR_T&hl4@sUU}&LhV4`be9Aao}WncnCHu`94kX!(gaV|V%a5c3he59l+9t zS>MyeF(iZa?yR@nzJVg`&(8@=nz$^(ZbHkHL+tWP0wztWKX89p3!7nOy(HUb)>i%{ zAN2$$PWPDn@m$P#t?hZ2|CC(2yL_+s?l9xc?{1abp11sd&bEC1-K(J$CbQ38K63St z#Mf=^88b3^Pk*(mUYLG3ZAt2tZ^cUl{A_atcV1F6{&~IlYstw!IuS9mbBvDOS2s>x zy4Cr?F%coHQj4Xxw@f)1`rPT>f^T9QSG|&XHO(^X^YmFFh2e9>Cd!}nfAxZ+g#V+% zfz@Afj;^^5L3(LQ|^-;ZF%^_LzlO>_7cbFur6?5BnCb(%IBJ)PG5m16*j-bxvhKif zmOWnW)1x?ky1VLsdbm`K*-r04=r23|mO6i3)(?{xiU0f%q|NYO=RxSLb+4S~ubj$I z7x+a^~Z)6p+%EbCs^b8Da5;*X~d)w46d%kPjanOjiuZfV)_#rtA3 z)AMG3ern zL)Cgw-@JIsB=>ZOaN&8Yt0&)npAooDB;fsb!^zeGeK#&jUU=H_UHXe7NOgy<;vR0x z_EUn^R?6EtKIrY`wThae?Yd_E2fb-(Zy8Rcb>FBtw0lpjigbdP@)4_@iiIXi)3@zB zaaQ%7(7Zw&kZ8{{f%Ud&SLS)VoSCb)pzQt6rNQs+-_UQJ@>Z!`9m*Yk+m6=YM z9`?kpUmpD|-SN$j_$PU3$5w8aO=@n@{j;V2#_Tz(<(PWdI;PF3U2uHw)#%Vwq3vh% e7JZxjX+L9m-qMRFUu??elF{r5}E)F^Y?`S literal 0 HcmV?d00001 diff --git a/Signal/src/ViewControllers/HomeView/HomeViewController.m b/Signal/src/ViewControllers/HomeView/HomeViewController.m index 36a6b5534..cc3a951ed 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewController.m +++ b/Signal/src/ViewControllers/HomeView/HomeViewController.m @@ -182,25 +182,21 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations // TODO: Remove this. [SignalApp.sharedApp setHomeViewController:self]; - ReminderView *archiveReminderView = [ReminderView new]; - archiveReminderView.text = NSLocalizedString( - @"INBOX_VIEW_ARCHIVE_MODE_REMINDER", @"Label reminding the user that they are in archive mode."); - __weak HomeViewController *weakSelf = self; - archiveReminderView.tapAction = ^{ - [weakSelf showInboxGrouping]; - }; + ReminderView *archiveReminderView = + [ReminderView explanationWithText:NSLocalizedString(@"INBOX_VIEW_ARCHIVE_MODE_REMINDER", + @"Label reminding the user that they are in archive mode.")]; [self.view addSubview:archiveReminderView]; [archiveReminderView autoPinWidthToSuperview]; [archiveReminderView autoPinToTopLayoutGuideOfViewController:self withInset:0]; self.hideArchiveReminderViewConstraint = [archiveReminderView autoSetDimension:ALDimensionHeight toSize:0]; self.hideArchiveReminderViewConstraint.priority = UILayoutPriorityRequired; - ReminderView *missingContactsPermissionView = [ReminderView new]; - missingContactsPermissionView.text = NSLocalizedString(@"INBOX_VIEW_MISSING_CONTACTS_PERMISSION", - @"Multi-line label explaining how to show names instead of phone numbers in your inbox"); - missingContactsPermissionView.tapAction = ^{ - [[UIApplication sharedApplication] openSystemSettings]; - }; + ReminderView *missingContactsPermissionView = [ReminderView + nagWithText:NSLocalizedString(@"INBOX_VIEW_MISSING_CONTACTS_PERMISSION", + @"Multi-line label explaining how to show names instead of phone numbers in your inbox") + tapAction:^{ + [[UIApplication sharedApplication] openSystemSettings]; + }]; [self.view addSubview:missingContactsPermissionView]; [missingContactsPermissionView autoPinWidthToSuperview]; [missingContactsPermissionView autoPinEdge:ALEdgeTop toEdge:ALEdgeBottom ofView:archiveReminderView]; @@ -1056,6 +1052,10 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { [self.self.threadMappings updateWithTransaction:transaction]; }]; + [self checkIfEmptyView]; + self.threadMappings = [[YapDatabaseViewMappings alloc] initWithGroups:@[ self.currentGrouping ] + view:TSThreadDatabaseViewExtensionName]; + return; } @@ -1141,17 +1141,27 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations - (void)checkIfEmptyView { - [_tableView setHidden:NO]; - [_emptyBoxLabel setHidden:NO]; - if (self.homeViewMode == HomeViewMode_Inbox && [self.threadMappings numberOfItemsInGroup:TSInboxGroup] == 0) { + // We need to consult the db view, not the mapping since the mapping only knows about + // the current group. + __block NSUInteger inboxCount; + __block NSUInteger archiveCount; + [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { + YapDatabaseViewTransaction *viewTransaction = [transaction ext:TSThreadDatabaseViewExtensionName]; + inboxCount = [viewTransaction numberOfItemsInGroup:TSInboxGroup]; + archiveCount = [viewTransaction numberOfItemsInGroup:TSArchiveGroup]; + }]; + + if (self.homeViewMode == HomeViewMode_Inbox && inboxCount == 0 && archiveCount == 0) { [self setEmptyBoxText]; [_tableView setHidden:YES]; - } else if (self.homeViewMode == HomeViewMode_Archive && - [self.threadMappings numberOfItemsInGroup:TSArchiveGroup] == 0) { + [_emptyBoxLabel setHidden:NO]; + } else if (self.homeViewMode == HomeViewMode_Archive && archiveCount == 0) { [self setEmptyBoxText]; [_tableView setHidden:YES]; + [_emptyBoxLabel setHidden:NO]; } else { [_emptyBoxLabel setHidden:YES]; + [_tableView setHidden:NO]; } } diff --git a/Signal/src/ViewControllers/NewContactThreadViewController.m b/Signal/src/ViewControllers/NewContactThreadViewController.m index f955ddd7a..8ff55a48b 100644 --- a/Signal/src/ViewControllers/NewContactThreadViewController.m +++ b/Signal/src/ViewControllers/NewContactThreadViewController.m @@ -82,12 +82,12 @@ NS_ASSUME_NONNULL_BEGIN _nonContactAccountSet = [NSMutableSet set]; _collation = [UILocalizedIndexedCollation currentCollation]; - ReminderView *contactsPermissionReminderView = [[ReminderView alloc] - initWithText:NSLocalizedString(@"COMPOSE_SCREEN_MISSING_CONTACTS_PERMISSION", - @"Multi-line label explaining why compose-screen contact picker is empty.") - tapAction:^{ - [[UIApplication sharedApplication] openSystemSettings]; - }]; + ReminderView *contactsPermissionReminderView = + [ReminderView nagWithText:NSLocalizedString(@"COMPOSE_SCREEN_MISSING_CONTACTS_PERMISSION", + @"Multi-line label explaining why compose-screen contact picker is empty.") + tapAction:^{ + [[UIApplication sharedApplication] openSystemSettings]; + }]; [self.view addSubview:contactsPermissionReminderView]; [contactsPermissionReminderView autoPinWidthToSuperview]; [contactsPermissionReminderView autoPinEdgeToSuperviewMargin:ALEdgeTop]; diff --git a/Signal/src/views/ReminderView.swift b/Signal/src/views/ReminderView.swift index 098cd498e..4f515ee46 100644 --- a/Signal/src/views/ReminderView.swift +++ b/Signal/src/views/ReminderView.swift @@ -1,5 +1,5 @@ // -// Copyright (c) 2017 Open Whisper Systems. All rights reserved. +// Copyright (c) 2018 Open Whisper Systems. All rights reserved. // import Foundation @@ -9,7 +9,7 @@ class ReminderView: UIView { let TAG = "[ReminderView]" let label = UILabel() - let defaultTapAction = { + static let defaultTapAction = { Logger.debug("[ReminderView] tapped.") } @@ -25,30 +25,51 @@ class ReminderView: UIView { } } - required init?(coder: NSCoder) { - self.tapAction = defaultTapAction - - super.init(coder: coder) + enum ReminderViewMode { + // Nags are urgent interactive prompts, bidding for the user's attention. + case nag + // Explanations are not interactive or urgent. + case explanation + } + let mode: ReminderViewMode - setupSubviews() + @available(*, unavailable, message:"use other constructor instead.") + required init?(coder aDecoder: NSCoder) { + fatalError("\(#function) is unimplemented.") } + @available(*, unavailable, message:"use other constructor instead.") override init(frame: CGRect) { - self.tapAction = defaultTapAction + fatalError("\(#function) is unimplemented.") + } - super.init(frame: frame) + private init(mode: ReminderViewMode, + text: String, tapAction: @escaping () -> Void) { + self.mode = mode + self.tapAction = tapAction + + super.init(frame: .zero) + + self.text = text setupSubviews() } - convenience init(text: String, tapAction: @escaping () -> Void) { - self.init(frame: .zero) - self.text = text - self.tapAction = tapAction + @objc public class func nag(text: String, tapAction: @escaping () -> Void) -> ReminderView { + return ReminderView(mode: .nag, text: text, tapAction: tapAction) + } + + @objc public class func explanation(text: String) -> ReminderView { + return ReminderView(mode: .explanation, text: text, tapAction: ReminderView.defaultTapAction) } func setupSubviews() { - self.backgroundColor = UIColor.ows_reminderYellow + switch (mode) { + case .nag: + self.backgroundColor = UIColor.ows_reminderYellow + case .explanation: + self.backgroundColor = UIColor(rgbHex: 0xf5f5f5) + } self.clipsToBounds = true let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(gestureRecognizer:))) @@ -66,19 +87,25 @@ class ReminderView: UIView { label.numberOfLines = 0 label.lineBreakMode = .byWordWrapping label.autoPinEdge(toSuperviewEdge: .top) - label.autoPinEdge(toSuperviewEdge: .left) + label.autoPinLeadingToSuperviewMargin() label.autoPinEdge(toSuperviewEdge: .bottom) label.textColor = UIColor.black.withAlphaComponent(0.9) + guard mode == .nag else { + label.autoPinTrailingToSuperviewMargin() + return + } + // Icon - let iconImage = #imageLiteral(resourceName: "system_disclosure_indicator").withRenderingMode(.alwaysTemplate) + let iconName = (self.isRTL() ? "system_disclosure_indicator_rtl" : "system_disclosure_indicator") + let iconImage = UIImage(named: iconName)?.withRenderingMode(.alwaysTemplate) let iconView = UIImageView(image: iconImage) iconView.contentMode = .scaleAspectFit iconView.tintColor = UIColor.black.withAlphaComponent(0.6) container.addSubview(iconView) - iconView.autoPinEdge(toSuperviewEdge: .right) - iconView.autoPinEdge(.left, to: .right, of: label, withOffset: 28) + iconView.autoPinLeading(toTrailingEdgeOf: label, offset: 28) + iconView.autoPinTrailingToSuperviewMargin() iconView.autoVCenterInSuperview() iconView.autoSetDimension(.width, toSize: 13) } diff --git a/Signal/translations/en.lproj/Localizable.strings b/Signal/translations/en.lproj/Localizable.strings index 539d40f16..0008b922b 100644 --- a/Signal/translations/en.lproj/Localizable.strings +++ b/Signal/translations/en.lproj/Localizable.strings @@ -894,7 +894,7 @@ "IN_CALL_TERMINATED" = "Call Ended."; /* Label reminding the user that they are in archive mode. */ -"INBOX_VIEW_ARCHIVE_MODE_REMINDER" = "You are viewing your archived messages. Tap to return to your Inbox."; +"INBOX_VIEW_ARCHIVE_MODE_REMINDER" = "These conversations are archived. They will appear in the inbox if new messages are received."; /* Multi-line label explaining how to show names instead of phone numbers in your inbox */ "INBOX_VIEW_MISSING_CONTACTS_PERMISSION" = "To see the names of your contacts, update your system settings to allow contact access."; From 21ab670fc92c456f209342378de2b6bad052b07c Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 23 Apr 2018 14:13:55 -0400 Subject: [PATCH 4/6] Clean up ahead of PR. --- Signal/src/ViewControllers/HomeView/HomeViewController.m | 8 +++++--- .../ThreadSettings/ShowGroupMembersViewController.m | 1 - Signal/src/environment/SignalApp.m | 3 +++ SignalMessaging/contacts/ViewControllerUtils.m | 1 - 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Signal/src/ViewControllers/HomeView/HomeViewController.m b/Signal/src/ViewControllers/HomeView/HomeViewController.m index cc3a951ed..3ea1f50cb 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewController.m +++ b/Signal/src/ViewControllers/HomeView/HomeViewController.m @@ -373,6 +373,10 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations - (void)showNewConversationView { + OWSAssertIsOnMainThread(); + + DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__); + NewContactThreadViewController *viewController = [NewContactThreadViewController new]; [self.contactsManager requestSystemContactsOnceWithCompletion:^(NSError *_Nullable error) { @@ -1050,11 +1054,9 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations if (![[self.uiDatabaseConnection ext:TSThreadDatabaseViewExtensionName] hasChangesForGroup:self.currentGrouping inNotifications:notifications]) { [self.uiDatabaseConnection readWithBlock:^(YapDatabaseReadTransaction *transaction) { - [self.self.threadMappings updateWithTransaction:transaction]; + [self.threadMappings updateWithTransaction:transaction]; }]; [self checkIfEmptyView]; - self.threadMappings = [[YapDatabaseViewMappings alloc] initWithGroups:@[ self.currentGrouping ] - view:TSThreadDatabaseViewExtensionName]; return; } diff --git a/Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.m b/Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.m index 66c8addec..975834a9c 100644 --- a/Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.m +++ b/Signal/src/ViewControllers/ThreadSettings/ShowGroupMembersViewController.m @@ -3,7 +3,6 @@ // #import "ShowGroupMembersViewController.h" -#import "HomeViewController.h" #import "Signal-Swift.h" #import "SignalApp.h" #import "ViewControllerUtils.h" diff --git a/Signal/src/environment/SignalApp.m b/Signal/src/environment/SignalApp.m index 739151820..9fed45388 100644 --- a/Signal/src/environment/SignalApp.m +++ b/Signal/src/environment/SignalApp.m @@ -211,9 +211,12 @@ keyboardOnViewAppearing:(BOOL)keyboardOnViewAppearing callOnViewAppearing:(BOOL)callOnViewAppearing { + OWSAssertIsOnMainThread(); // At most one. OWSAssert(!keyboardOnViewAppearing || !callOnViewAppearing); + DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__); + if (!thread) { OWSFail(@"%@ Can't present nil thread.", self.logTag); return; diff --git a/SignalMessaging/contacts/ViewControllerUtils.m b/SignalMessaging/contacts/ViewControllerUtils.m index c4bc0b66c..eb9406cea 100644 --- a/SignalMessaging/contacts/ViewControllerUtils.m +++ b/SignalMessaging/contacts/ViewControllerUtils.m @@ -3,7 +3,6 @@ // #import "ViewControllerUtils.h" -#import "HomeViewController.h" #import "NSString+OWS.h" #import "PhoneNumber.h" #import From e252447cfea94e3909727a2b2d13f2efd509ea62 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Mon, 23 Apr 2018 14:14:38 -0400 Subject: [PATCH 5/6] Clean up ahead of PR. --- Signal/src/AppDelegate.h | 1 - Signal/src/AppDelegate.m | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Signal/src/AppDelegate.h b/Signal/src/AppDelegate.h index cc90a26bd..3c563548a 100644 --- a/Signal/src/AppDelegate.h +++ b/Signal/src/AppDelegate.h @@ -2,7 +2,6 @@ // Copyright (c) 2018 Open Whisper Systems. All rights reserved. // -#import "HomeViewController.h" #import extern NSString *const AppDelegateStoryboardMain; diff --git a/Signal/src/AppDelegate.m b/Signal/src/AppDelegate.m index 42e746506..c6125a59c 100644 --- a/Signal/src/AppDelegate.m +++ b/Signal/src/AppDelegate.m @@ -6,6 +6,7 @@ #import "AppStoreRating.h" #import "AppUpdateNag.h" #import "CodeVerificationViewController.h" +#import "HomeViewController.h" #import "DebugLogger.h" #import "MainAppContext.h" #import "NotificationsManager.h" From 1395a6c37b40a0b0132444de5f2c796f1624f806 Mon Sep 17 00:00:00 2001 From: Matthew Chen Date: Tue, 24 Apr 2018 11:42:04 -0400 Subject: [PATCH 6/6] Respond to CR. --- Podfile.lock | 21 +++- Signal.xcodeproj/project.pbxproj | 99 +------------------ .../HomeView/HomeViewController.m | 21 ++-- 3 files changed, 30 insertions(+), 111 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index 683c22158..9911e27b3 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -144,6 +144,23 @@ DEPENDENCIES: - YapDatabase/SQLCipher (from `https://github.com/signalapp/YapDatabase.git`, branch `release/unencryptedHeaders`) - YYImage +SPEC REPOS: + https://github.com/CocoaPods/Specs.git: + - AFNetworking + - ATAppUpdater + - CocoaLumberjack + - JSQSystemSoundPlayer + - libPhoneNumber-iOS + - Mantle + - ProtocolBuffers + - PureLayout + - Reachability + - SAMKeychain + - SSZipArchive + - TwistedOakCollapsingFutures + - UnionFind + - YYImage + EXTERNAL SOURCES: AxolotlKit: :git: https://github.com/signalapp/SignalProtocolKit.git @@ -159,7 +176,7 @@ EXTERNAL SOURCES: :branch: mkirk/share-compatible :git: https://github.com/signalapp/JSQMessagesViewController.git SignalServiceKit: - :path: . + :path: "." SocketRocket: :git: https://github.com/facebook/SocketRocket.git SQLCipher: @@ -222,4 +239,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 6a1bafb7c5bedfa4e577580ff12e487cc7111f38 -COCOAPODS: 1.4.0 +COCOAPODS: 1.5.0 diff --git a/Signal.xcodeproj/project.pbxproj b/Signal.xcodeproj/project.pbxproj index c8baf2705..85ee16cc0 100644 --- a/Signal.xcodeproj/project.pbxproj +++ b/Signal.xcodeproj/project.pbxproj @@ -2412,7 +2412,6 @@ 453518641FC635DD00210559 /* Sources */, 453518651FC635DD00210559 /* Frameworks */, 453518661FC635DD00210559 /* Resources */, - 7B85A55670DC3D49AFBF7359 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -2433,7 +2432,6 @@ 4535188E1FC63DBF00210559 /* Frameworks */, 4535188F1FC63DBF00210559 /* Headers */, 453518901FC63DBF00210559 /* Resources */, - 6C612B7B27FC78638EB7B113 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -2454,7 +2452,6 @@ D221A086169C9E5E00537ABF /* Frameworks */, D221A087169C9E5E00537ABF /* Resources */, 59C9DBA462715B5C999FFB02 /* [CP] Embed Pods Frameworks */, - 3465F381B1856CC06933B3A8 /* [CP] Copy Pods Resources */, 451DE9EE1DC1546A00810E42 /* [Carthage] Copy Frameworks */, 453518771FC635DD00210559 /* Embed App Extensions */, 4535189F1FC63DBF00210559 /* Embed Frameworks */, @@ -2479,7 +2476,6 @@ D221A0A6169C9E5F00537ABF /* Frameworks */, D221A0A7169C9E5F00537ABF /* Resources */, B4E9B04E862FB64FC9A8F79B /* [CP] Embed Pods Frameworks */, - F76686434770E2BBEBD9665A /* [CP] Copy Pods Resources */, 451DE9FB1DC18D4500810E42 /* [Carthage] Copy Frameworks */, ); buildRules = ( @@ -2780,39 +2776,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 3465F381B1856CC06933B3A8 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${SRCROOT}/Pods/Target Support Files/Pods-Signal/Pods-Signal-resources.sh", - "${PODS_ROOT}/JSQMessagesViewController/JSQMessagesViewController/Assets/JSQMessagesAssets.bundle", - "${PODS_ROOT}/JSQMessagesViewController/JSQMessagesViewController/Controllers/JSQMessagesViewController.xib", - "${PODS_ROOT}/JSQMessagesViewController/JSQMessagesViewController/Views/JSQMessagesCollectionViewCellIncoming.xib", - "${PODS_ROOT}/JSQMessagesViewController/JSQMessagesViewController/Views/JSQMessagesCollectionViewCellOutgoing.xib", - "${PODS_ROOT}/JSQMessagesViewController/JSQMessagesViewController/Views/JSQMessagesLoadEarlierHeaderView.xib", - "${PODS_ROOT}/JSQMessagesViewController/JSQMessagesViewController/Views/JSQMessagesToolbarContentView.xib", - "${PODS_ROOT}/JSQMessagesViewController/JSQMessagesViewController/Views/JSQMessagesTypingIndicatorFooterView.xib", - "${PODS_ROOT}/SAMKeychain/Support/SAMKeychain.bundle", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/textsecure.cer", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GIAG2.crt", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GSR2.crt", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GSR4.crt", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GTSR1.crt", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GTSR2.crt", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GTSR3.crt", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GTSR4.crt", - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-Signal/Pods-Signal-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; 451DE9EE1DC1546A00810E42 /* [Carthage] Copy Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -2941,47 +2904,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - 6C612B7B27FC78638EB7B113 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SignalMessaging/Pods-SignalMessaging-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; - 7B85A55670DC3D49AFBF7359 /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - "${SRCROOT}/Pods/Target Support Files/Pods-SignalShareExtension/Pods-SignalShareExtension-resources.sh", - "${PODS_ROOT}/SAMKeychain/Support/SAMKeychain.bundle", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/textsecure.cer", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GIAG2.crt", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GSR2.crt", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GSR4.crt", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GTSR1.crt", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GTSR2.crt", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GTSR3.crt", - "${PODS_ROOT}/../SignalServiceKit/src/Security/PinningCertificate/GTSR4.crt", - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}", - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SignalShareExtension/Pods-SignalShareExtension-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; B4E9B04E862FB64FC9A8F79B /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -3058,21 +2980,6 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; - F76686434770E2BBEBD9665A /* [CP] Copy Pods Resources */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "[CP] Copy Pods Resources"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-SignalTests/Pods-SignalTests-resources.sh\"\n"; - showEnvVarsInLog = 0; - }; /* End PBXShellScriptBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -3512,11 +3419,7 @@ "DEBUG=1", "$(inherited)", ); - "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = ( - "DEBUG=1", - "$(inherited)", - "SSK_BUILDING_FOR_TESTS=1", - ); + "GCC_PREPROCESSOR_DEFINITIONS[arch=*]" = "DEBUG=1 $(inherited) SSK_BUILDING_FOR_TESTS=1"; GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES; GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; diff --git a/Signal/src/ViewControllers/HomeView/HomeViewController.m b/Signal/src/ViewControllers/HomeView/HomeViewController.m index 3ea1f50cb..9c80b54be 100644 --- a/Signal/src/ViewControllers/HomeView/HomeViewController.m +++ b/Signal/src/ViewControllers/HomeView/HomeViewController.m @@ -273,6 +273,11 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations self.title = NSLocalizedString(@"HOME_VIEW_TITLE_ARCHIVE", @"Title for the home view's 'archive' mode."); break; } + self.navigationItem.backBarButtonItem = + [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"BACK_BUTTON", @"button text for back button") + style:UIBarButtonItemStylePlain + target:nil + action:nil]; if ([self.traitCollection respondsToSelector:@selector(forceTouchCapability)] && (self.traitCollection.forceTouchCapability == UIForceTouchCapabilityAvailable)) { @@ -677,7 +682,6 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations OWSAssert(disclosureImage); UIImageView *disclosureImageView = [UIImageView new]; disclosureImageView.image = [disclosureImage imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - // TODO: disclosureImageView.tintColor = [UIColor colorWithRGBHex:0xd1d1d6]; [disclosureImageView setContentHuggingHigh]; [disclosureImageView setCompressionResistanceHigh]; @@ -691,13 +695,8 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations UIStackView *stackView = [UIStackView new]; stackView.axis = UILayoutConstraintAxisHorizontal; stackView.spacing = 5; - if (cell.isRTL) { - [stackView addArrangedSubview:disclosureImageView]; - [stackView addArrangedSubview:label]; - } else { - [stackView addArrangedSubview:label]; - [stackView addArrangedSubview:disclosureImageView]; - } + [stackView addArrangedSubview:label]; + [stackView addArrangedSubview:disclosureImageView]; [cell.contentView addSubview:stackView]; [stackView autoCenterInSuperview]; // Constrain to cell margins. @@ -1154,11 +1153,11 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations }]; if (self.homeViewMode == HomeViewMode_Inbox && inboxCount == 0 && archiveCount == 0) { - [self setEmptyBoxText]; + [self updateEmptyBoxText]; [_tableView setHidden:YES]; [_emptyBoxLabel setHidden:NO]; } else if (self.homeViewMode == HomeViewMode_Archive && archiveCount == 0) { - [self setEmptyBoxText]; + [self updateEmptyBoxText]; [_tableView setHidden:YES]; [_emptyBoxLabel setHidden:NO]; } else { @@ -1167,7 +1166,7 @@ NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversations } } -- (void)setEmptyBoxText +- (void)updateEmptyBoxText { _emptyBoxLabel.textColor = [UIColor grayColor]; _emptyBoxLabel.font = [UIFont ows_regularFontWithSize:18.f];