Designing the empty state during contact refresh.

This commit is contained in:
Christine Corbett 2015-01-30 12:11:35 -10:00 committed by Frederic Jacobs
parent af3cf25207
commit b7d65ce921
8 changed files with 177 additions and 46 deletions

View file

@ -130,7 +130,6 @@ static NSString* const kCallSegue = @"2.0_6.0_Call_Segue";
[TSPreKeyManager refreshPreKeys];
}
[MIMETypeUtil initialize];
return YES;
}

View file

@ -235,7 +235,7 @@
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="lKc-rv-FH5" userLabel="empty state view">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="uiEmptyArchive" translatesAutoresizingMaskIntoConstraints="NO" id="Off-ZL-54G">
<imageView userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="uiEmptyInbox" translatesAutoresizingMaskIntoConstraints="NO" id="Off-ZL-54G">
<rect key="frame" x="0.0" y="0.0" width="240" height="128"/>
<constraints>
<constraint firstAttribute="height" constant="140" id="QR5-Mr-y2f">
@ -5526,7 +5526,7 @@ A0 09 9A FF A8 8A 09 99</string>
<image name="signals_tab.png" width="24" height="24"/>
<image name="speaker-active" width="80" height="80"/>
<image name="speaker-inactive" width="80" height="80"/>
<image name="uiEmptyArchive" width="227" height="227"/>
<image name="uiEmptyInbox" width="227" height="227"/>
</resources>
<inferredMetricsTieBreakers>
<segue reference="DR8-fx-0PD"/>

View file

@ -43,4 +43,5 @@ typedef NS_ENUM(NSUInteger, TSImageQuality) {
-(NSString*)lastRanVersion;
-(NSString*)setAndGetCurrentVersion;
@end

View file

@ -26,7 +26,6 @@
#define NOTIFICATION_PREVIEW_TYPE_KEY @"Notification Preview Type Key"
#define IMAGE_UPLOAD_QUALITY_KEY @"Image Upload Quality Key"
#define IS_MIGRATING_FROM_1DOT0_TO_LARGER_KEY @"Migrating from 1.0 to Larger"
#define kSignalVersionKey @"SignalUpdateVersionKey"
@implementation PropertyListPreferences (PropertyUtil)
@ -110,7 +109,6 @@
} else{
return NO;
}
}
- (BOOL)loggingIsEnabled{
@ -131,6 +129,8 @@
}
}
-(NotificationType)notificationPreviewType {
NSNumber *preference = [self tryGetValueForKey:NOTIFICATION_PREVIEW_TYPE_KEY];
@ -192,8 +192,6 @@
[self setValueForKey:IS_MIGRATING_FROM_1DOT0_TO_LARGER_KEY toValue:@(enabled)];
}
-(NSString*)setAndGetCurrentVersion{
NSString *lastVersion = self.lastRanVersion;
[NSUserDefaults.standardUserDefaults setObject:[NSString stringWithFormat:@"%@", NSBundle.mainBundle.infoDictionary[@"CFBundleVersion"]] forKey:kSignalVersionKey];

View file

@ -17,4 +17,6 @@
-(void) startUntilCancelled:(TOCCancelToken*)cancelToken;
-(PhoneNumberDirectoryFilter*) getCurrentFilter;
@property BOOL isRefreshing;
@end

View file

@ -26,6 +26,7 @@
- (id)init {
if (self = [super init]) {
phoneNumberDirectoryFilter = PhoneNumberDirectoryFilter.phoneNumberDirectoryFilterDefault;
_isRefreshing = NO;
}
return self;
}
@ -70,7 +71,7 @@
- (void) updateRedPhone {
_isRefreshing = YES;
[[RPServerRequestsManager sharedInstance] performRequest:[RPAPICall fetchBloomFilter] success:^(NSURLSessionDataTask *task, id responseObject) {
PhoneNumberDirectoryFilter *directory = [PhoneNumberDirectoryFilter phoneNumberDirectoryFilterFromURLResponse:(NSHTTPURLResponse*)task.response body:responseObject];
@ -145,9 +146,12 @@
}
}];
_isRefreshing = NO;
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_DIRECTORY_WAS_UPDATED object:nil];
[self scheduleUpdate];
} failure:^(NSURLSessionDataTask *task, NSError *error) {
_isRefreshing = NO;
[[NSNotificationCenter defaultCenter] postNotificationName:NOTIFICATION_DIRECTORY_FAILED object:nil];
}];
}

View file

@ -6,10 +6,11 @@
//
//
#import "MessageComposeTableViewController.h"
#import "Environment.h"
#import "Contact.h"
#import "PhoneNumberUtil.h"
#import "MessageComposeTableViewController.h"
#import "PreferencesUtil.h"
#import "MessagesViewController.h"
#import "SignalsViewController.h"
#import "NotificationManifest.h"
@ -26,7 +27,6 @@
{
UIButton* sendTextButton;
NSString* currentSearchTerm;
NSArray* contacts;
NSArray* searchResults;
}
@ -34,6 +34,9 @@
@property (nonatomic, strong) UISearchController *searchController;
@property (nonatomic, strong) UIActivityIndicatorView *activityIndicator;
@property (nonatomic, strong) UIBarButtonItem *addGroup;
@property (nonatomic, strong) UIView *loadingBackgroundView;
@property (nonatomic, strong) UIView *emptyBackgroundView;
@end
@implementation MessageComposeTableViewController
@ -47,27 +50,144 @@
[self initializeSearch];
self.searchController.searchBar.hidden = NO;
UIView* loadingView = [[UIView alloc] initWithFrame:self.tableView.frame];
UIImageView *loadingImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"uiEmpty"]];
[loadingImageView setBackgroundColor:[UIColor whiteColor]];
[loadingImageView setContentMode:UIViewContentModeCenter];
[loadingImageView setAutoresizingMask:(UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight)];
[loadingImageView setFrame:self.tableView.frame];
[loadingView addSubview:loadingImageView];
self.tableView.backgroundView = loadingView;
self.tableView.backgroundView.opaque = YES;
self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero];
[self createLoadingAndBackgroundViews];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
-(void) viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
BOOL isRefreshing = [Environment getCurrent].phoneDirectoryManager.isRefreshing;
if([contacts count]==0) {
if([Environment getCurrent].phoneDirectoryManager.isRefreshing) {
[self showLoadingBackgroundView:YES];
}
else {
[self showEmptyBackgroundView:YES];
}
}
else if(isRefreshing) {
self.tableView.contentOffset = CGPointMake(0, -self.refreshControl.frame.size.height);
[self.refreshControl beginRefreshing];
}
}
-(UILabel*) createLabelWithFirstLine:(NSString*) firstLine andSecondLine:(NSString*)secondLine {
UILabel *label = [[UILabel alloc] init];
label.textColor = [UIColor grayColor];
label.font = [UIFont ows_regularFontWithSize:18.f];
label.textAlignment = NSTextAlignmentCenter;
label.numberOfLines = 4;
NSMutableAttributedString *fullLabelString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%@\n%@",firstLine,secondLine]];
[fullLabelString addAttribute:NSFontAttributeName value:[UIFont ows_boldFontWithSize:15.f] range:NSMakeRange(0,firstLine.length)];
[fullLabelString addAttribute:NSFontAttributeName value:[UIFont ows_regularFontWithSize:14.f] range:NSMakeRange(firstLine.length + 1, secondLine.length)];
[fullLabelString addAttribute:NSForegroundColorAttributeName value:[UIColor blackColor] range:NSMakeRange(0,firstLine.length)];
[fullLabelString addAttribute:NSForegroundColorAttributeName value:[UIColor ows_darkGrayColor] range:NSMakeRange(firstLine.length + 1, secondLine.length)];
label.attributedText = fullLabelString;
//250, 66, 140
[label setFrame:CGRectMake(self.tableView.frame.size.width/2.0f-250/2.0f, 100+140, 250, 66)];
return label;
}
-(UIButton*) createButtonWithTitle:(NSString*)title {
NSDictionary* buttonTextAttributes = @{NSFontAttributeName:[UIFont ows_regularFontWithSize:15.0f],
NSForegroundColorAttributeName:[UIColor ows_materialBlueColor]};
UIButton* button = [[UIButton alloc] initWithFrame:CGRectMake(0,0,65,24)];
NSMutableAttributedString *attributedTitle = [[NSMutableAttributedString alloc] initWithString:title];
[attributedTitle setAttributes:buttonTextAttributes range:NSMakeRange(0, [attributedTitle length])];
[button setAttributedTitle:attributedTitle forState:UIControlStateNormal];
[button.titleLabel setTextAlignment:NSTextAlignmentCenter];
return button;
}
-(void) createLoadingAndBackgroundViews {
// This will be further tweaked per design recs. It must currently be hardcoded (or we can place in separate .xib I suppose) as the controller must be a TableViewController to have access to the native pull to refresh capabilities. That means we can't do a UIView in the storyboard
_loadingBackgroundView = [[UIView alloc] initWithFrame:self.tableView.frame];
UIImageView *loadingImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"uiEmpty"]];
[loadingImageView setBackgroundColor:[UIColor whiteColor]];
[loadingImageView setContentMode:UIViewContentModeCenter];
[loadingImageView setFrame:CGRectMake(self.tableView.frame.size.width/2.0f-115.0f/2.0f, 100, 115, 110)];
loadingImageView.contentMode = UIViewContentModeCenter;
loadingImageView.contentMode = UIViewContentModeScaleAspectFit;
UIActivityIndicatorView *loadingProgressView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[loadingProgressView setFrame:CGRectMake(self.tableView.frame.size.width/2.0f-loadingProgressView.frame.size.width/2.0f, 100+110/2.0f-loadingProgressView.frame.size.height/2.0f, loadingProgressView.frame.size.width, loadingProgressView.frame.size.height)];
[loadingProgressView setHidesWhenStopped:NO];
[loadingProgressView startAnimating];
UILabel *loadingLabel = [self createLabelWithFirstLine:@"Loading your contacts." andSecondLine:@"Sit tight."];
[_loadingBackgroundView addSubview:loadingImageView];
[_loadingBackgroundView addSubview:loadingProgressView];
[_loadingBackgroundView addSubview:loadingLabel];
_emptyBackgroundView = [[UIView alloc] initWithFrame:self.tableView.frame];
UIImageView *emptyImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"uiEmptyContact"]];
[emptyImageView setBackgroundColor:[UIColor whiteColor]];
[emptyImageView setContentMode:UIViewContentModeCenter];
[emptyImageView setFrame:CGRectMake(self.tableView.frame.size.width/2.0f-115.0f/2.0f, 100, 115, 110)];
emptyImageView.contentMode = UIViewContentModeCenter;
emptyImageView.contentMode = UIViewContentModeScaleAspectFit;
UILabel *emptyLabel = [self createLabelWithFirstLine:@"None of your contacts have Signal!" andSecondLine:@"Why don't you invite someone"];
UIButton *inviteContactButton = [self createButtonWithTitle:@"Invite contact"];
[inviteContactButton addTarget:self action:@selector(sendText) forControlEvents:UIControlEventTouchUpInside];
[inviteContactButton setFrame:CGRectMake(self.tableView.frame.size.width/2.0f-inviteContactButton.frame.size.width/1.5f, self.tableView.frame.size.height - 200, 100, 66)];
[inviteContactButton.titleLabel setTextAlignment:NSTextAlignmentCenter];
[_emptyBackgroundView addSubview:emptyImageView];
[_emptyBackgroundView addSubview:emptyLabel];
[_emptyBackgroundView addSubview:inviteContactButton];
}
-(void) showLoadingBackgroundView:(BOOL)show {
if(show) {
_addGroup = self.navigationItem.rightBarButtonItem!=nil ? _addGroup : self.navigationItem.rightBarButtonItem;
self.navigationItem.rightBarButtonItem = nil;
self.searchController.searchBar.hidden = YES;
self.tableView.backgroundView = _loadingBackgroundView;
self.refreshControl = nil;
self.tableView.backgroundView.opaque = YES;
}
else {
[self initializeRefreshControl];
self.navigationItem.rightBarButtonItem = self.navigationItem.rightBarButtonItem!=nil ? self.navigationItem.rightBarButtonItem : _addGroup;
self.searchController.searchBar.hidden = NO;
self.tableView.backgroundView = nil;
}
}
-(void) showEmptyBackgroundView:(BOOL)show {
if(show) {
self.refreshControl = nil;
_addGroup = self.navigationItem.rightBarButtonItem!=nil ? _addGroup : self.navigationItem.rightBarButtonItem;
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[[UIImage imageNamed:@"btnRefresh--white"] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal] style:UIBarButtonItemStylePlain target:self action:@selector(refreshContacts)];
self.navigationItem.rightBarButtonItem.imageInsets = UIEdgeInsetsMake(8,8,8,8);
self.searchController.searchBar.hidden = YES;
self.tableView.backgroundView = _emptyBackgroundView;
self.tableView.backgroundView.opaque = YES;
}
else {
[self initializeRefreshControl];
self.refreshControl.enabled = YES;
self.navigationItem.rightBarButtonItem = self.navigationItem.rightBarButtonItem!=nil ? self.navigationItem.rightBarButtonItem : _addGroup;
self.searchController.searchBar.hidden = NO;
self.tableView.backgroundView = nil;
}
}
#pragma mark - Initializers
-(void)initializeSearch
@ -147,8 +267,9 @@
// search by contact name or number
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"(fullName contains[c] %@) OR (allPhoneNumbers contains[c] %@)", searchText, searchText];
searchResults = [contacts filteredArrayUsingPredicate:resultPredicate];
if (!searchResults.count && _searchController.searchBar.text.length == 0) searchResults = contacts;
if (!searchResults.count && _searchController.searchBar.text.length == 0) {
searchResults = contacts;
}
NSString *formattedNumber = [PhoneNumber tryParsePhoneNumberFromUserSpecifiedText:searchText].toE164;
// text to a non-signal number if we have no results and a valid phone #
@ -168,9 +289,12 @@
#pragma mark - Send Normal Text to Unknown Contact
- (void)sendText {
NSString *confirmMessage = @"Would you like to invite the following number to Signal: ";
confirmMessage = [confirmMessage stringByAppendingString:currentSearchTerm];
confirmMessage = [confirmMessage stringByAppendingString:@"?"];
NSString *confirmMessage = @"Invite a friend via insecure SMS?";
if([currentSearchTerm length]>0) {
confirmMessage = @"Would you like to invite the following number to Signal: ";
confirmMessage = [confirmMessage stringByAppendingString:currentSearchTerm];
confirmMessage = [confirmMessage stringByAppendingString:@"?"];
}
UIAlertController *alertController = [UIAlertController
alertControllerWithTitle:@"Confirm"
message:confirmMessage
@ -195,13 +319,12 @@
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.messageComposeDelegate = self;
picker.recipients = [NSArray arrayWithObject:currentSearchTerm];
picker.recipients = [currentSearchTerm length]> 0 ? [NSArray arrayWithObject:currentSearchTerm] : nil;
picker.body = @"I'm inviting you to install Signal! Here is the link: https://itunes.apple.com/us/app/signal-private-messenger/id874139669?mt=8";
[self presentViewController:picker animated:YES completion:[UIUtil modalCompletionBlock]];
} else {
// TODO: better backup for iPods (just don't support on)
UIAlertView *notPermitted=[[UIAlertView alloc] initWithTitle:@"Alert" message:@"Your device doesn't support this feature." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[notPermitted show];
}
}];
@ -210,7 +333,7 @@
[alertController addAction:okAction];
sendTextButton.hidden = YES;
self.searchController.searchBar.text = @"";
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
[self presentViewController:alertController animated:YES completion:[UIUtil modalCompletionBlock]];
}
@ -249,18 +372,7 @@
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if([contacts count] == 0) {
self.tableView.backgroundView.hidden = NO;
self.searchController.searchBar.hidden = YES;
_addGroup = self.navigationItem.rightBarButtonItem!=nil ? _addGroup : self.navigationItem.rightBarButtonItem;
self.navigationItem.rightBarButtonItem = nil;
}
else {
self.tableView.backgroundView.hidden = YES;
self.searchController.searchBar.hidden = NO;
self.navigationItem.rightBarButtonItem = self.navigationItem.rightBarButtonItem!=nil ? self.navigationItem.rightBarButtonItem : _addGroup;
}
if (self.searchController.active) {
return (NSInteger)[searchResults count];
} else {
@ -331,19 +443,34 @@
- (void)contactRefreshFailed {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:TIMEOUT message:TIMEOUT_CONTACTS_DETAIL delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", @"") otherButtonTitles:nil];
[alert show];
[self.refreshControl endRefreshing];
[self updateAfterRefreshTry];
}
- (void)contactsDidRefresh {
[self updateSearchResultsForSearchController:self.searchController];
[self.tableView reloadData];
[self updateAfterRefreshTry];
}
- (void) updateAfterRefreshTry {
[self.refreshControl endRefreshing];
[self showLoadingBackgroundView:NO];
if([contacts count]==0) {
[self showEmptyBackgroundView:YES];
}
else {
[self showEmptyBackgroundView:NO];
}
}
- (void)refreshContacts {
Environment *env = [Environment getCurrent];
PhoneNumberDirectoryFilterManager *manager = [env phoneDirectoryManager];
[manager forceUpdate];
if([contacts count]==0) {
[self showLoadingBackgroundView:YES];
}
}
#pragma mark - Navigation

View file

@ -378,7 +378,7 @@ static NSString* const kShowSignupFlowSegue = @"showSignupFlow";
- (void)checkIfEmptyView{
[_tableView setHidden:NO];
if (self.viewingThreadsIn == kInboxState && [self.threadMappings numberOfItemsInGroup:TSInboxGroup]==0) {
_emptyBoxImage.image = [UIImage imageNamed:@"uiEmptyContact"];
_emptyBoxImage.image = [UIImage imageNamed:@"uiEmptyInbox"];
[self setEmptyBoxText];
[_tableView setHidden:YES];
}