Merge branch 'charlesmchen/archivedConversations'
This commit is contained in:
commit
2c1e633914
21
Podfile.lock
21
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
|
||||
|
|
|
@ -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;
|
||||
|
|
23
Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/Contents.json
vendored
Normal file
23
Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/Contents.json
vendored
Normal file
|
@ -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"
|
||||
}
|
||||
}
|
BIN
Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/DisclosureIndicatorRTL@1x.png
vendored
Normal file
BIN
Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/DisclosureIndicatorRTL@1x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/DisclosureIndicatorRTL@2x.png
vendored
Normal file
BIN
Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/DisclosureIndicatorRTL@2x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/DisclosureIndicatorRTL@3x.png
vendored
Normal file
BIN
Signal/Images.xcassets/system_disclosure_indicator_rtl.imageset/DisclosureIndicatorRTL@3x.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
|
@ -2,7 +2,6 @@
|
|||
// Copyright (c) 2018 Open Whisper Systems. All rights reserved.
|
||||
//
|
||||
|
||||
#import "HomeViewController.h"
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
extern NSString *const AppDelegateStoryboardMain;
|
||||
|
|
|
@ -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"
|
||||
|
@ -707,14 +708,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];
|
||||
}
|
||||
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
keyboardOnViewAppearing:(BOOL)keyboardOnViewAppearing
|
||||
callOnViewAppearing:(BOOL)callOnViewAppearing;
|
||||
|
||||
- (void)updateInboxCountLabel;
|
||||
|
||||
- (void)showNewConversationView;
|
||||
|
||||
- (void)presentTopLevelModalViewController:(UIViewController *)viewController
|
||||
|
|
|
@ -32,7 +32,12 @@
|
|||
#import <YapDatabase/YapDatabaseViewChange.h>
|
||||
#import <YapDatabase/YapDatabaseViewConnection.h>
|
||||
|
||||
typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
|
||||
typedef NS_ENUM(NSInteger, HomeViewMode) {
|
||||
HomeViewMode_Archive,
|
||||
HomeViewMode_Inbox,
|
||||
};
|
||||
|
||||
NSString *const kArchivedConversationsReuseIdentifier = @"kArchivedConversationsReuseIdentifier";
|
||||
|
||||
@interface HomeViewController () <UITableViewDelegate, UITableViewDataSource, UIViewControllerPreviewingDelegate>
|
||||
|
||||
|
@ -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<NSString *> *blockedPhoneNumberSet;
|
||||
@property (nonatomic, readonly) NSCache<NSString *, ThreadViewModel *> *threadViewModelCache;
|
||||
|
@ -82,6 +85,8 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
|
|||
return self;
|
||||
}
|
||||
|
||||
_homeViewMode = HomeViewMode_Inbox;
|
||||
|
||||
[self commonInit];
|
||||
|
||||
return self;
|
||||
|
@ -177,30 +182,21 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
|
|||
// 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.");
|
||||
__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];
|
||||
|
@ -213,6 +209,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 +234,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) {
|
||||
|
@ -259,25 +256,28 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
|
|||
// 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];
|
||||
|
||||
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
|
||||
= 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;
|
||||
}
|
||||
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)) {
|
||||
|
@ -296,6 +296,9 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
|
|||
|
||||
- (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.
|
||||
|
@ -327,7 +330,15 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
|
|||
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
|
||||
|
@ -367,6 +378,10 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
|
|||
|
||||
- (void)showNewConversationView
|
||||
{
|
||||
OWSAssertIsOnMainThread();
|
||||
|
||||
DDLogInfo(@"%@ %s", self.logTag, __PRETTY_FUNCTION__);
|
||||
|
||||
NewContactThreadViewController *viewController = [NewContactThreadViewController new];
|
||||
|
||||
[self.contactsManager requestSystemContactsOnceWithCompletion:^(NSError *_Nullable error) {
|
||||
|
@ -384,15 +399,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 +414,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 +503,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 +604,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 +642,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 +667,47 @@ 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];
|
||||
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;
|
||||
[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 +745,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 +757,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 +835,6 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
|
|||
[thread removeWithTransaction:transaction];
|
||||
}];
|
||||
|
||||
_inboxCount -= (self.viewingThreadsIn == kArchiveState) ? 1 : 0;
|
||||
[self checkIfEmptyView];
|
||||
}
|
||||
|
||||
|
@ -769,31 +842,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
|
||||
{
|
||||
NSUInteger numberOfItems = [OWSMessageUtils.sharedManager unreadMessagesCount];
|
||||
NSString *unreadString = NSLocalizedString(@"WHISPER_NAV_BAR_TITLE", nil);
|
||||
|
||||
if (numberOfItems > 0) {
|
||||
unreadString = [unreadString stringByAppendingFormat:@" (%@)", [OWSFormat formatInt:(int)numberOfItems]];
|
||||
}
|
||||
|
||||
[_segmentedControl setTitle:unreadString forSegmentAtIndex:0];
|
||||
[_segmentedControl sizeToFit];
|
||||
[_segmentedControl.superview setNeedsLayout];
|
||||
[_segmentedControl reloadInputViews];
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
if ([self isIndexPathForArchivedConversations:indexPath]) {
|
||||
[self showArchivedConversations];
|
||||
return;
|
||||
}
|
||||
|
||||
TSThread *thread = [self threadForIndexPath:indexPath];
|
||||
[self presentThread:thread keyboardOnViewAppearing:NO callOnViewAppearing:NO];
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
|
@ -898,30 +966,29 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
|
|||
|
||||
- (void)showInboxGrouping
|
||||
{
|
||||
self.viewingThreadsIn = kInboxState;
|
||||
OWSAssert(self.homeViewMode == HomeViewMode_Archive);
|
||||
|
||||
[self.navigationController popToRootViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
- (void)showArchiveGrouping
|
||||
- (void)showArchivedConversations
|
||||
{
|
||||
self.viewingThreadsIn = kArchiveState;
|
||||
}
|
||||
OWSAssert(self.homeViewMode == HomeViewMode_Inbox);
|
||||
|
||||
- (void)setViewingThreadsIn:(CellState)viewingThreadsIn
|
||||
{
|
||||
BOOL didChange = _viewingThreadsIn != viewingThreadsIn;
|
||||
_viewingThreadsIn = viewingThreadsIn;
|
||||
self.segmentedControl.selectedSegmentIndex = (viewingThreadsIn == kInboxState ? 0 : 1);
|
||||
if (didChange || !self.threadMappings) {
|
||||
[self updateMappings];
|
||||
} else {
|
||||
[self checkIfEmptyView];
|
||||
[self updateReminderViews];
|
||||
}
|
||||
// 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
|
||||
{
|
||||
return self.viewingThreadsIn == kInboxState ? TSInboxGroup : TSArchiveGroup;
|
||||
switch (self.homeViewMode) {
|
||||
case HomeViewMode_Inbox:
|
||||
return TSInboxGroup;
|
||||
case HomeViewMode_Archive:
|
||||
return TSArchiveGroup;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateMappings
|
||||
|
@ -986,8 +1053,10 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
|
|||
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];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1011,7 +1080,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 +1115,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: {
|
||||
|
@ -1076,21 +1142,31 @@ typedef NS_ENUM(NSInteger, CellState) { kArchiveState, kInboxState };
|
|||
|
||||
- (void)checkIfEmptyView
|
||||
{
|
||||
[_tableView setHidden:NO];
|
||||
[_emptyBoxLabel setHidden:NO];
|
||||
if (self.viewingThreadsIn == kInboxState && [self.threadMappings numberOfItemsInGroup:TSInboxGroup] == 0) {
|
||||
[self setEmptyBoxText];
|
||||
// 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 updateEmptyBoxText];
|
||||
[_tableView setHidden:YES];
|
||||
} else if (self.viewingThreadsIn == kArchiveState &&
|
||||
[self.threadMappings numberOfItemsInGroup:TSArchiveGroup] == 0) {
|
||||
[self setEmptyBoxText];
|
||||
[_emptyBoxLabel setHidden:NO];
|
||||
} else if (self.homeViewMode == HomeViewMode_Archive && archiveCount == 0) {
|
||||
[self updateEmptyBoxText];
|
||||
[_tableView setHidden:YES];
|
||||
[_emptyBoxLabel setHidden:NO];
|
||||
} else {
|
||||
[_emptyBoxLabel setHidden:YES];
|
||||
[_tableView setHidden:NO];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setEmptyBoxText
|
||||
- (void)updateEmptyBoxText
|
||||
{
|
||||
_emptyBoxLabel.textColor = [UIColor grayColor];
|
||||
_emptyBoxLabel.font = [UIFont ows_regularFontWithSize:18.f];
|
||||
|
@ -1100,7 +1176,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", @"");
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
//
|
||||
|
||||
#import "ShowGroupMembersViewController.h"
|
||||
#import "HomeViewController.h"
|
||||
#import "Signal-Swift.h"
|
||||
#import "SignalApp.h"
|
||||
#import "ViewControllerUtils.h"
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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
|
||||
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
|
||||
|
||||
super.init(coder: coder)
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -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,18 @@
|
|||
/* 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'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…";
|
||||
|
||||
|
@ -888,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.";
|
||||
|
@ -2110,9 +2116,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.";
|
||||
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
//
|
||||
|
||||
#import "ViewControllerUtils.h"
|
||||
#import "HomeViewController.h"
|
||||
#import "NSString+OWS.h"
|
||||
#import "PhoneNumber.h"
|
||||
#import <AVFoundation/AVFoundation.h>
|
||||
|
|
Loading…
Reference in New Issue