shlist

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

commit 94668258c864cec02b1df5cf70a91add0940c226
parent 692db950ba76575d2a2cbf590669f02a80f2766e
Author: Kyle Milz <kyle@Kyles-MacBook-Pro.local>
Date:   Sun, 20 Sep 2015 12:19:08 -0600

ios: get a phone number popup dialog going

Diffstat:
Mios-ng/ContactsTableViewController.m | 8++++----
Mios-ng/shlist/MainTableViewController.m | 86++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Mios-ng/shlist/Network.h | 3++-
Mios-ng/shlist/Network.m | 145+++++++++++++++++++++++++++++++++++--------------------------------------------
4 files changed, 141 insertions(+), 101 deletions(-)

diff --git a/ios-ng/ContactsTableViewController.m b/ios-ng/ContactsTableViewController.m @@ -51,9 +51,10 @@ [_cells addObject:[letter_to_contact_map objectForKey:letter]]; } -- (void)didReceiveMemoryWarning { - [super didReceiveMemoryWarning]; - // Dispose of any resources that can be recreated. +- (void)didReceiveMemoryWarning +{ + [super didReceiveMemoryWarning]; + // Dispose of any resources that can be recreated. } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView @@ -67,7 +68,6 @@ return [[_cells objectAtIndex:section] count]; } - - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { diff --git a/ios-ng/shlist/MainTableViewController.m b/ios-ng/shlist/MainTableViewController.m @@ -7,7 +7,9 @@ #import <AddressBook/AddressBook.h> #include "libkern/OSAtomic.h" -@interface MainTableViewController () +@interface MainTableViewController () { + NSString *phone_num_file; +} @property (strong, nonatomic) Network *server; @property NSMutableDictionary *phnum_to_name_map; @@ -26,37 +28,89 @@ // display an Edit button in the navigation bar for this view controller self.navigationItem.leftBarButtonItem = self.editButtonItem; + // main lists 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"; + // store the path to the phone number file + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + phone_num_file = [documentsDirectory stringByAppendingPathComponent:@"phone_num"]; - // create one and only server instance, this gets passed around _server = [[Network alloc] init]; _server->shlist_tvc = self; - if ([_server prepare]) { - NSLog(@"info: server connection prepared"); - // 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]; + _phone_number = nil; + if ([self load_phone_number]) { + // phone number loaded, try loading device id + if ([_server load_device_id:[_phone_number dataUsingEncoding:NSASCIIStringEncoding]]) { + NSLog(@"info: network: connection ready"); + // bulk update, doesn't take a payload + [_server send_message:3 contents:nil]; + } + // else, device id request sent + } + // else, phone number entry is on screen // get instance and wait for privacy window to clear _address_book = [AddressBook shared_address_book]; _address_book.main_tvc = self; } +- (bool) load_phone_number +{ + if ([[NSFileManager defaultManager] fileExistsAtPath:phone_num_file]) { + // file exists, read what it has + // XXX: validate length of file too + _phone_number = [NSString stringWithContentsOfFile:phone_num_file]; + return true; + } + + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Important" + message:@"In order for us to calculate your mutual contacts, your phone number is needed." + delegate:self cancelButtonTitle:@"Nope" otherButtonTitles:@"Ok", nil]; + + alert.alertViewStyle = UIAlertViewStylePlainTextInput; + + // it's a phone number, so only show the number pad + UITextField * alertTextField = [alert textFieldAtIndex:0]; + alertTextField.keyboardType = UIKeyboardTypeNumberPad; + alertTextField.placeholder = @"Enter your phone number"; + + [alert show]; + return false; +} + +- (void)alertView:(UIAlertView *)alertView + clickedButtonAtIndex:(NSInteger)buttonIndex +{ + NSString *entered_phone_num = [[alertView textFieldAtIndex:0] text]; + NSLog(@"warn: main: writing phone num '%@' to disk", entered_phone_num); + NSError *error; + [entered_phone_num writeToFile:phone_num_file atomically:YES encoding:NSASCIIStringEncoding error:&error]; + + if (error) + NSLog(@"warn: main: writing phone number file: %@", error); + + if ([entered_phone_num compare:@""] == NSOrderedSame) { + NSLog(@"warn: load phone number: entered emtpy phone number"); + } + + _phone_number = entered_phone_num; + + if ([_server load_device_id:[_phone_number dataUsingEncoding:NSASCIIStringEncoding]]) { + NSLog(@"info: network: connection ready"); + // bulk update, doesn't take a payload + [_server send_message:3 contents:nil]; + } + // else, device id request sent +} + - (void) update_address_book { [_phnum_to_name_map removeAllObjects]; - // XXX: it'd be nice to resize the mutable array to num_contacts here + // XXX: it'd be nice to resize phnum_to_name_map to num_contacts here for (Contact *contact in _address_book.contacts) { NSString *disp_name; @@ -292,7 +346,7 @@ if (name) [members addObject:name]; - else if ([phone_number compare:_phone_number] == NSOrderedSame) + else if (_phone_number && ([_phone_number compare:phone_number] == NSOrderedSame)) [members addObject:@"You"]; else // didn't find it, you don't know this person diff --git a/ios-ng/shlist/Network.h b/ios-ng/shlist/Network.h @@ -1,4 +1,5 @@ #import <UIKit/UIKit.h> + #import "MainTableViewController.h" #import "ListTableViewController.h" @@ -13,7 +14,7 @@ } -- (bool) prepare; +- (bool) load_device_id:(NSData*)phone_number; - (void) send_message:(uint16_t)msg_type contents:(NSData *)data; @end \ No newline at end of file diff --git a/ios-ng/shlist/Network.m b/ios-ng/shlist/Network.m @@ -2,21 +2,21 @@ #import "DataStructures.h" @interface Network () { - NSData *msg_data; - NSString *msg_string; - uint8_t msg_buffer[1024]; - unsigned int msg_buf_position; + NSData *msg_data; + NSString *msg_string; + uint8_t msg_buffer[1024]; + unsigned int msg_buf_position; - uint8_t msg_total_bytes_tmp[2]; - unsigned short msg_total_bytes; - unsigned int msg_total_bytes_pos; + uint8_t msg_total_bytes_tmp[2]; + unsigned short msg_total_bytes; + unsigned int msg_total_bytes_pos; - uint8_t msg_type_tmp[2]; - unsigned short msg_type; - unsigned int msg_type_pos; + uint8_t msg_type_tmp[2]; + unsigned short msg_type; + unsigned int msg_type_pos; - int connected; - NSData *device_id; + NSData *device_id; + NSString *device_id_file; } @end @@ -26,7 +26,10 @@ - (id) init { if (self = [super init]) { - connected = 0; + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + device_id_file = [documentsDirectory stringByAppendingPathComponent:@"shlist_key"]; + msg_buf_position = 0; msg_total_bytes = 0; @@ -34,6 +37,7 @@ msg_type = 0; msg_type_pos = 0; + [self connect]; } return self; @@ -59,48 +63,52 @@ [inputShlistStream open]; [outputShlistStream open]; - NSLog(@"info: network: finished connecting to absentmindedproductions.ca"); + NSLog(@"info: network: bound to amp.ca"); } -- (bool) prepare +- (void) disconnect { - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; + [inputShlistStream close]; + [outputShlistStream close]; - NSString *device_id_file = [documentsDirectory stringByAppendingPathComponent:@"shlist_key"]; + [inputShlistStream removeFromRunLoop:[NSRunLoop currentRunLoop] + forMode:NSDefaultRunLoopMode]; + [outputShlistStream removeFromRunLoop:[NSRunLoop currentRunLoop] + forMode:NSDefaultRunLoopMode]; - // NSError *error = nil; - // [[NSFileManager defaultManager] removeItemAtPath:destinationPath error:&error]; + inputShlistStream = nil; // stream is ivar, so reinit it + outputShlistStream = nil; // stream is ivar, so reinit it +} - // TODO: also check the length of the file - if (![[NSFileManager defaultManager] fileExistsAtPath:device_id_file]) { - // no device id file found, send a registration message - NSMutableData *msg = [NSMutableData data]; +- (bool) load_device_id:(NSData *)phone_number; +{ + if ([[NSFileManager defaultManager] fileExistsAtPath:device_id_file]) { + // TODO: also check the length of the file + // read device id from filesystem into memory + device_id = [NSData dataWithContentsOfFile:device_id_file]; - // message type 0 - [msg appendBytes:"\x00\x00" length:2]; + return true; + } - // phone number length is 10 - uint16_t length_network = htons(10); - [msg appendBytes:&length_network length:2]; + // no device id file found, send a registration message + NSMutableData *msg = [NSMutableData data]; - // actual phone number - const char *phone_number = "4037082094"; - [msg appendBytes:phone_number length:10]; + // message type 0 + uint16_t msg_type_network = htons(0); + [msg appendBytes:&msg_type_network length:2]; - if (connected == 0) - [self connect]; - [outputShlistStream write:[msg bytes] maxLength:[msg length]]; - NSLog(@"info: sent registration message"); + // phone number length is 10 + uint16_t length_network = htons(10); + [msg appendBytes:&length_network length:2]; - // we don't have a device id so we can't do anything yet - return false; - } + // append phone number + [msg appendData:phone_number]; - // read device id from filesystem into memory - device_id = [NSData dataWithContentsOfFile:device_id_file]; + [outputShlistStream write:[msg bytes] maxLength:[msg length]]; + NSLog(@"info: sent registration message"); - return true; + // we don't have a device id so we can't do anything yet + return false; } - (void) send_message:(uint16_t)send_msg_type contents:(NSData *)payload @@ -125,12 +133,15 @@ [msg appendData:payload]; } - if (connected == 0) { - NSLog(@"info: network: not connected in send_message, reconnecting..."); + if ([outputShlistStream write:[msg bytes] maxLength:[msg length]] == -1) { + NSLog(@"warn: network: write error occurred, reconnecting"); + [self disconnect]; [self connect]; + + if ([outputShlistStream write:[msg bytes] maxLength:[msg length]] == -1) { + NSLog(@"warn: network: resend failed after reconnect, giving up"); + } } - if ([outputShlistStream write:[msg bytes] maxLength:[msg length]] == -1) - NSLog(@"warn: network: write error occurred"); } - (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode @@ -146,7 +157,6 @@ break; case NSStreamEventOpenCompleted: NSLog(@"info: network: %@ stream opened", stream_name); - connected = 1; break; case NSStreamEventHasBytesAvailable: if (stream == inputShlistStream) { @@ -163,27 +173,17 @@ NSLog(@"info: network: stream has space available"); break; case NSStreamEventErrorOccurred: + // I saw this case when trying to connect to a down server + NSLog(@"info: network: stream error occurred"); - // I saw this case when trying to connect to a down server + [self disconnect]; // fall through on purpose case NSStreamEventEndEncountered: // close both sides of the connection on end NSLog(@"ShlistServer::NSStreamEventEndEncountered"); - [inputShlistStream close]; - [outputShlistStream close]; - - [inputShlistStream removeFromRunLoop:[NSRunLoop currentRunLoop] - forMode:NSDefaultRunLoopMode]; - [outputShlistStream removeFromRunLoop:[NSRunLoop currentRunLoop] - forMode:NSDefaultRunLoopMode]; - // [inputShlistStream release]; - // [outputShlistStream release]; - - inputShlistStream = nil; // stream is ivar, so reinit it - outputShlistStream = nil; // stream is ivar, so reinit it - connected = 0; + [self disconnect]; break; default: @@ -322,11 +322,7 @@ if (msg_type == 0) { // registration response message - - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *destinationPath = [documentsDirectory stringByAppendingPathComponent:@"shlist_key"]; - if ([[NSFileManager defaultManager] fileExistsAtPath:destinationPath]) { + if ([[NSFileManager defaultManager] fileExistsAtPath:device_id_file]) { // it would be strange if we got back a registration // message type when we already have a key file NSLog(@"error: network: register: not overwriting key file with '%@'", msg_string); @@ -334,7 +330,7 @@ } NSLog(@"info: network: register: writing new key '%@' to disk", msg_string); - [msg_data writeToFile:destinationPath atomically:YES]; + [msg_data writeToFile:device_id_file atomically:YES]; // set this so we're ready to send other message types device_id = msg_data; @@ -366,6 +362,7 @@ else if (msg_type == 3) { [self handle_bulk_list_update:msg_string]; + [shlist_tvc.tableView reloadData]; } else if (msg_type == 4) { @@ -430,8 +427,6 @@ NSArray *indirect_lists = [self parse_lists:my_friends_lists]; [shlist_tvc.indirect_lists addObjectsFromArray:indirect_lists]; } - - [shlist_tvc.tableView reloadData]; } - (NSArray *) parse_lists:(NSString *)raw_lists @@ -453,7 +448,6 @@ NSLog(@"info: parse_list: '%@' has %i fields", [list_fields objectAtIndex:0], field_count); - // we've got everything we need SharedList *shared_list = [[SharedList alloc] init]; @@ -475,16 +469,7 @@ - (void) dealloc { - [inputShlistStream close]; - [outputShlistStream close]; - - [inputShlistStream removeFromRunLoop:[NSRunLoop currentRunLoop] - forMode:NSDefaultRunLoopMode]; - [outputShlistStream removeFromRunLoop:[NSRunLoop currentRunLoop] - forMode:NSDefaultRunLoopMode]; - - inputShlistStream = nil; // stream is ivar, so reinit it - outputShlistStream = nil; // stream is ivar, so reinit it + [self disconnect]; } @end