shlist

share and manage lists between multiple people
Log | Files | Refs

commit 170227102196f4a0daa65e1bf12d3486d3ad65fa
parent 3cdd0ec015130c97c175e9382a91bca5cb143815
Author: Kyle Milz <kyle@Kyles-MacBook-Pro.local>
Date:   Sun, 20 Sep 2015 02:20:42 -0600

ios: move phone number resolution into cell generation

This allows me to do a non-blocking address book request, which is nice.

Diffstat:
Mios-ng/shlist/AddressBook.h | 11+++++++----
Mios-ng/shlist/AddressBook.m | 32+++++++-------------------------
Mios-ng/shlist/DataStructures.h | 2+-
Mios-ng/shlist/MainTableViewController.h | 2++
Mios-ng/shlist/MainTableViewController.m | 103++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
Mios-ng/shlist/Network.m | 79++++---------------------------------------------------------------------------
Mios-ng/shlist/NewListViewController.m | 2+-
7 files changed, 122 insertions(+), 109 deletions(-)

diff --git a/ios-ng/shlist/AddressBook.h b/ios-ng/shlist/AddressBook.h @@ -1,6 +1,11 @@ #import <Foundation/Foundation.h> -@interface AddressBook : NSObject +#import "MainTableViewController.h" + + +@interface AddressBook : NSObject { + @public volatile uint32_t ready; +} @property (strong, retain) NSMutableArray *contacts; @property unsigned long num_contacts; @@ -8,9 +13,7 @@ // returns singleton instance + (id) shared_address_book; -- (void) wait_for_ready; - -@property volatile uint32_t ready; +@property (strong, nonatomic) MainTableViewController *main_tvc; @end diff --git a/ios-ng/shlist/AddressBook.m b/ios-ng/shlist/AddressBook.m @@ -1,4 +1,5 @@ #import "AddressBook.h" + #include <AddressBook/AddressBook.h> #import <UIKit/UIKit.h> @@ -6,8 +7,6 @@ @interface AddressBook () -// - (void) get_contacts_or_fail; - @end // empty implementation @@ -32,7 +31,7 @@ if (self) { _contacts = [[NSMutableArray alloc] init]; - _ready = 0; + ready = 0; [self get_contacts_or_fail]; } return self; @@ -70,10 +69,14 @@ if (granted) { // if they gave you permission, then just carry on [self listPeopleInAddressBook:addressBook]; + if (_main_tvc) + [_main_tvc update_address_book]; + else + NSLog(@"warn: address book: address book ready before main_tvc assigned!"); // atomically set the ready flag; this completion handler // can be run on an arbitrary thread - OSAtomicIncrement32((volatile int32_t *)&_ready); + OSAtomicIncrement32((volatile int32_t *)&ready); } else { // however, if they didn't give you permission, handle it gracefully, for example... @@ -125,25 +128,4 @@ NSLog(@"info: address book: %lu contacts found", _num_contacts); } -// call this to make the address book authorization block -- (void) wait_for_ready -{ - int cumulative_ms = 0; - int sleep_for_ms = 10; - // wait for the database to become ready, no upper bound - while (!OSAtomicAnd32(0xffff, &_ready)) { - usleep(sleep_for_ms * 1000); - cumulative_ms += sleep_for_ms; - - // if we've spun for over a second reduce polling speed - if (cumulative_ms > 1 * 1000) { - NSLog(@"warn: address book: not ready for more than %i s", - cumulative_ms / 1000); - sleep_for_ms = 1 * 1000; - } - } - - NSLog(@"info: address book: ready after %i ms", cumulative_ms); -} - @end \ No newline at end of file diff --git a/ios-ng/shlist/DataStructures.h b/ios-ng/shlist/DataStructures.h @@ -9,7 +9,7 @@ @property NSString *name; @property NSData *id; -@property NSString *members; +@property NSArray *members_phone_nums; @property NSDate *date; @property int items_ready; @property int items_total; diff --git a/ios-ng/shlist/MainTableViewController.h b/ios-ng/shlist/MainTableViewController.h @@ -7,6 +7,8 @@ @property NSMutableArray *shared_lists; @property NSMutableArray *indirect_lists; +- (void) update_address_book; + - (void) finished_new_list_request:(SharedList *) shlist; - (void) finished_join_list_request:(SharedList *) shlist; - (void) finished_leave_list_request:(SharedList *) shlist; diff --git a/ios-ng/shlist/MainTableViewController.m b/ios-ng/shlist/MainTableViewController.m @@ -1,13 +1,18 @@ +#import "AddressBook.h" #import "MainTableViewController.h" #import "NewListViewController.h" #import "Network.h" #import "ListTableViewController.h" #import <AddressBook/AddressBook.h> +#include "libkern/OSAtomic.h" @interface MainTableViewController () @property (strong, nonatomic) Network *server; +@property NSMutableDictionary *phnum_to_name_map; +@property (strong, retain) AddressBook *address_book; +@property (strong, nonatomic) NSString *phone_number; @end @@ -24,6 +29,12 @@ self.shared_lists = [[NSMutableArray alloc] init]; self.indirect_lists = [[NSMutableArray alloc] init]; + // first thing we need is a phone number, can't even send registration without it + // NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + // NSString *documentsDirectory = [paths objectAtIndex:0]; + // NSString *phone_num_file = [documentsDirectory stringByAppendingPathComponent:@"phone_num"]; + _phone_number = @"4037082094"; + // create one and only server instance, this gets passed around _server = [[Network alloc] init]; _server->shlist_tvc = self; @@ -33,6 +44,41 @@ // bulk update, doesn't take a payload [_server send_message:3 contents:nil]; } + + // the capacity here assumes one phone number per person + _phnum_to_name_map = [[NSMutableDictionary alloc] init]; + + // get instance and wait for privacy window to clear + _address_book = [AddressBook shared_address_book]; + _address_book.main_tvc = self; + // [_address_book wait_for_ready]; +} + +- (void) update_address_book +{ + [_phnum_to_name_map removeAllObjects]; + // XXX: it'd be nice to resize the mutable array to num_contacts here + + for (Contact *contact in _address_book.contacts) { + NSString *disp_name; + // show first name and last initial if possible, otherwise + // just show the first name or the last name or the phone number + if (contact.first_name && contact.last_name) + disp_name = [NSString stringWithFormat:@"%@ %@", + contact.first_name, [contact.last_name substringToIndex:1]]; + else if (contact.first_name) + disp_name = contact.first_name; + else if (contact.last_name) + disp_name = contact.last_name; + else if ([contact.phone_numbers count]) + disp_name = [contact.phone_numbers objectAtIndex:0]; + else + disp_name = @"No Name"; + + // map the persons known phone number to their massaged name + for (NSString *phone_number in contact.phone_numbers) + [_phnum_to_name_map setObject:disp_name forKey:phone_number]; + } } - (void) didReceiveMemoryWarning @@ -58,7 +104,7 @@ return 0; } -// new list dialogue has been cancelled or saved +// new list dialogue has been saved - (IBAction) unwindToList:(UIStoryboardSegue *)segue { NewListViewController *source = [segue sourceViewController]; @@ -162,6 +208,7 @@ [self.tableView setEditing:FALSE animated:TRUE]; } + - (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { @@ -174,7 +221,7 @@ if ([indexPath section] == 0) { shared_list = [self.shared_lists objectAtIndex:row]; cell.textLabel.text = shared_list.name; - cell.detailTextLabel.text = shared_list.members; + cell.detailTextLabel.text = [self process_members_array:shared_list.members_phone_nums]; // fill in the completion fraction UILabel *completion_fraction; @@ -199,7 +246,7 @@ else if ([indexPath section] == 1) { shared_list = [self.indirect_lists objectAtIndex:row]; cell.textLabel.text = shared_list.name; - cell.detailTextLabel.text = shared_list.members; + cell.detailTextLabel.text = [self process_members_array:shared_list.members_phone_nums]; shared_list.cell = cell; // Modify the look of the off the shelf cell @@ -218,7 +265,57 @@ return cell; } +- (NSString *) process_members_array:(NSArray *)phnum_array +{ + if (!OSAtomicAnd32(0xffff, &_address_book->ready)) { + // not ready + NSMutableString *output = [[NSMutableString alloc] init]; + for (id phone_number in phnum_array) { + if ([phone_number compare:_phone_number] == NSOrderedSame) { + [output appendString:@"You"]; + continue; + } + + [output appendFormat:@", %@", phone_number]; + } + return output; + } + + // we can do phone number to name mappings + NSMutableArray *members = [[NSMutableArray alloc] init]; + int others = 0; + + // anything past the second field are list members + for (id phone_number in phnum_array) { + + // try to find the list member in our address book + NSString *name = _phnum_to_name_map[phone_number]; + + if (name) + [members addObject:name]; + else if ([phone_number compare:_phone_number] == NSOrderedSame) + [members addObject:@"You"]; + else + // didn't find it, you don't know this person + others++; + } + + NSMutableString *members_str = + [[members componentsJoinedByString:@", "] mutableCopy]; + + if (others) { + char *plural; + if (others == 1) + plural = "other"; + else + plural = "others"; + NSString *buf = [NSString stringWithFormat:@" + %i %s", + others, plural]; + [members_str appendString:buf]; + } + return members_str; +} // section header titles - (NSString *)tableView:(UITableView *)tableView diff --git a/ios-ng/shlist/Network.m b/ios-ng/shlist/Network.m @@ -1,6 +1,5 @@ #import "Network.h" #import "DataStructures.h" -#import "AddressBook.h" @interface Network () { NSData *msg_data; @@ -19,11 +18,7 @@ int connected; } -@property (strong, retain) NSMutableData *data; -@property (strong, retain) AddressBook *address_book; -@property NSMutableDictionary *phnum_to_name_map; - -@property (strong, nonatomic) NSString *phone_number; +// @property (strong, retain) NSMutableData *data; @property (strong, nonatomic) NSData *device_id; @end @@ -41,37 +36,6 @@ msg_type = 0; msg_type_pos = 0; - - // [self connect]; - - // get instance and wait for privacy window to clear - _address_book = [AddressBook shared_address_book]; - [_address_book wait_for_ready]; - - // the capacity here assumes one phone number per person - _phnum_to_name_map = [NSMutableDictionary - dictionaryWithCapacity:_address_book.num_contacts]; - - for (Contact *contact in _address_book.contacts) { - NSString *disp_name; - // show first name and last initial if possible, otherwise - // just show the first name or the last name or the phone number - if (contact.first_name && contact.last_name) - disp_name = [NSString stringWithFormat:@"%@ %@", - contact.first_name, [contact.last_name substringToIndex:1]]; - else if (contact.first_name) - disp_name = contact.first_name; - else if (contact.last_name) - disp_name = contact.last_name; - else if ([contact.phone_numbers count]) - disp_name = [contact.phone_numbers objectAtIndex:0]; - else - disp_name = @"No Name"; - - // map the persons known phone number to their massaged name - for (NSString *phone_number in contact.phone_numbers) - [_phnum_to_name_map setObject:disp_name forKey:phone_number]; - } } return self; @@ -105,8 +69,6 @@ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; - // NSString *phone_num_file = [documentsDirectory stringByAppendingPathComponent:@"phone_num"]; - _phone_number = @"4037082094"; NSString *device_id_file = [documentsDirectory stringByAppendingPathComponent:@"shlist_key"]; // NSError *error = nil; @@ -381,7 +343,7 @@ if (msg_type == 1) { NSArray *fields = [msg_string componentsSeparatedByString:@"\0"]; - if ([fields count] != 2) { + if ([fields count] != 3) { NSLog(@"warn: network: new list response has invalid number of fields %i", [fields count]); return; @@ -390,7 +352,7 @@ SharedList *shlist = [[SharedList alloc] init]; shlist.id = [[fields objectAtIndex:0] dataUsingEncoding:NSUTF8StringEncoding]; shlist.name = [fields objectAtIndex:1]; - shlist.members = @"You"; + shlist.members_phone_nums = [NSArray arrayWithObjects:[fields objectAtIndex:2], nil]; shlist.items_ready = 0; shlist.items_total = 0; @@ -487,46 +449,13 @@ NSLog(@"info: parse_list: '%@' has %i fields", [list_fields objectAtIndex:0], field_count); - NSMutableArray *members = [[NSMutableArray alloc] init]; - int others = 0; - - // anything past the second field are list members - NSArray *phone_numbers = [list_fields subarrayWithRange:NSMakeRange(2, field_count - 2)]; - for (id phone_number in phone_numbers) { - - // try to find the list member in our address book - NSString *name = _phnum_to_name_map[phone_number]; - - if (name) - [members addObject:name]; - else if ([phone_number compare:_phone_number]) - [members addObject:@"You"]; - else - // didn't find it, you don't know this person - others++; - } - - NSMutableString *members_str = - [[members componentsJoinedByString:@", "] mutableCopy]; - - if (others) { - char *plural; - if (others == 1) - plural = "other"; - else - plural = "others"; - - NSString *buf = [NSString stringWithFormat:@" + %i %s", - others, plural]; - [members_str appendString:buf]; - } // we've got everything we need SharedList *shared_list = [[SharedList alloc] init]; shared_list.name = [list_fields objectAtIndex:0]; shared_list.id = [[list_fields objectAtIndex:1] dataUsingEncoding:NSUTF8StringEncoding]; - shared_list.members = members_str; + shared_list.members_phone_nums = [list_fields subarrayWithRange:NSMakeRange(2, field_count - 2)]; // we don't currently get this information back // XXX: lists your not in will not return this information diff --git a/ios-ng/shlist/NewListViewController.m b/ios-ng/shlist/NewListViewController.m @@ -35,7 +35,7 @@ self.shared_list = [[SharedList alloc] init]; self.shared_list.name = self.textField.text; // self.shared_list.list_date = self.datePicker.date; - self.shared_list.members = @"You"; + // self.shared_list.members = @"You"; NSLog(@"NewListViewController::prepareForSegue(): %@", self.textField.text); }