commit a82fa5b6703fa3704e0ceb7e416ebd0d39e666c8
parent 932e525815e5c8d9b527c549986cb1db5399b912
Author: Kyle Milz <kyle@green.krwm.net>
Date: Wed, 27 Jan 2016 23:13:17 -0700
ios: get leaving/joining lists working
Diffstat:
5 files changed, 115 insertions(+), 152 deletions(-)
diff --git a/ios/shlist/DataStructures.h b/ios/shlist/DataStructures.h
@@ -11,6 +11,7 @@
@property NSNumber *num;
@property NSNumber *items_total;
@property NSArray *members_phone_nums;
+@property NSNumber *num_members;
@property bool deadline;
@property NSDate *date;
@property NSNumber *items_ready;
diff --git a/ios/shlist/MainTableViewController.h b/ios/shlist/MainTableViewController.h
@@ -9,8 +9,8 @@
- (void) lists_get_finished:(NSArray *)lists;
- (void) lists_get_other_finished:(NSArray *)other_lists;
- (void) finished_new_list_request:(SharedList *) shlist;
-- (void) finished_join_list_request:(SharedList *) shlist;
-- (void) finished_leave_list_request:(SharedList *) shlist;
+- (void) finished_join_list_request:(NSDictionary *) shlist;
+- (void) finished_leave_list_request:(NSDictionary *) shlist;
- (IBAction)unwindToList:(UIStoryboardSegue *)segue;
diff --git a/ios/shlist/MainTableViewController.m b/ios/shlist/MainTableViewController.m
@@ -243,77 +243,104 @@ clickedButtonAtIndex:(NSInteger)buttonIndex
// the response for this does all of the heavy row moving work
NSMutableDictionary *request = [[NSMutableDictionary alloc] init];
- [request setObject:list.num forKey:@"num"];
+ [request setObject:list.num forKey:@"list_num"];
[network_connection send_message:list_join contents:request];
}
-- (void) finished_join_list_request:(SharedList *) shlist
+- (void) finished_join_list_request:(NSDictionary *) shlist
{
+ NSMutableArray *lists = [_lists objectAtIndex:0];
+ NSMutableArray *other_lists = [_lists objectAtIndex:1];
+
+ // Find the list number we received a response for
SharedList *needle = nil;
- for (SharedList *temp in [_lists objectAtIndex:1]) {
- if (temp.num == shlist.num) {
+ for (SharedList *temp in other_lists) {
+ if (temp.num == shlist[@"num"]) {
needle = temp;
break;
}
}
- // if we received an update from a list id we don't know about, do nothing
+ // If we received an update from a list id we don't know about, do nothing
if (needle == nil)
return;
- // this has to be done before row moving
- [[_lists objectAtIndex:0] addObject:needle];
- [[_lists objectAtIndex:1] removeObject:needle];
-
- // [_shared_lists addObject:needle];
- // [_indirect_lists removeObject:needle];
+ // Swap between data structures first before moving rows
+ [lists addObject:needle];
+ [other_lists removeObject:needle];
- // get the original cells index path from the matched cell
+ // Get the cell index path from the matched list cell
NSIndexPath *orig_index_path = [self.tableView indexPathForCell:needle.cell];
- // compute new position and start moving row as soon as possible
+ // Compute new position and start moving row as soon as possible
// XXX: sorting
- int section_0_rows = [[_lists objectAtIndex:0] count];
- NSIndexPath *new_index_path = [NSIndexPath indexPathForRow:section_0_rows - 1 inSection:0];
-
+ int new_row_pos = [lists count] - 1;
+ NSIndexPath *new_index_path = [NSIndexPath indexPathForRow:new_row_pos inSection:0];
[self.tableView moveRowAtIndexPath:orig_index_path toIndexPath:new_index_path];
- // add > accessory indicator, fill in and show completion fraction
+ // Put any new values into data structs
+ NSData *name_data = [shlist[@"name"] dataUsingEncoding:NSISOLatin1StringEncoding];
+ needle.name = [[NSString alloc] initWithData:name_data encoding:NSUTF8StringEncoding];
+ // needle.date =
+ needle.items_ready = shlist[@"items_complete"];
+ needle.items_total = shlist[@"items_total"];
+ needle.num_members = shlist[@"num_members"];
+
+ needle.members_phone_nums = shlist[@"members"];
+ [self process_members_array:shlist[@"members"] cell:needle.cell];
+
+ // Add > accessory indicator
needle.cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
+
+ // Find fraction UILAbel, populate it and then show it
UILabel *fraction = (UILabel *)[needle.cell viewWithTag:4];
- fraction.text = [self fraction:shlist.items_ready denominator:shlist.items_total];
+ fraction.text = [self fraction:needle.items_ready denominator:needle.items_total];
fraction.hidden = NO;
}
-- (void) finished_leave_list_request:(SharedList *) shlist
+- (void) finished_leave_list_request:(NSDictionary *) response
{
+ NSMutableArray *lists = [_lists objectAtIndex:0];
+ NSMutableArray *other_lists = [_lists objectAtIndex:1];
+
SharedList *list = nil;
- for (SharedList *temp in [_lists objectAtIndex:0]) {
- if (temp.num == shlist.num) {
+ for (SharedList *temp in lists) {
+ if (temp.num == response[@"list_num"]) {
list = temp;
break;
}
}
-
if (list == nil)
return;
- // insert the new object at the beginning to match gui moving below
- [[_lists objectAtIndex:1] insertObject:list atIndex:0];
- [[_lists objectAtIndex:0] removeObject:list];
+ NSNumber *list_empty = response[@"list_empty"];
+ if ([list_empty intValue] == 1) {
+ // List was empty, delete instead of moving it
+ [lists removeObject:list];
+
+ NSIndexPath *old_path = [self.tableView indexPathForCell:list.cell];
+ [self.tableView deleteRowsAtIndexPaths:@[old_path] withRowAnimation:UITableViewRowAnimationAutomatic];
+
+ return;
+ }
+
+ // Insert the new object at the beginning to match gui moving below
+ [other_lists insertObject:list atIndex:0];
+ [lists removeObject:list];
- // perform row move, the destination is the top of "other lists"
+ // Perform row move, the destination is the top of "other lists"
NSIndexPath *old_path = [self.tableView indexPathForCell:list.cell];
NSIndexPath *new_path = [NSIndexPath indexPathForRow:0 inSection:1];
[self.tableView moveRowAtIndexPath:old_path toIndexPath:new_path];
- // remove > accessory and hide the completion fraction
+ // Remove > accessory and hide the completion fraction
list.cell.accessoryType = UITableViewCellAccessoryNone;
UILabel *fraction = (UILabel *)[list.cell viewWithTag:4];
fraction.hidden = YES;
- // reset editing state back to the default
- [self.tableView setEditing:FALSE animated:TRUE];
+ // XXX: update members array to disclude yourself (maybe send it back in response?)
+ // XXX: Maybe clear out list data that's no longer needed
+ // XXX: give some visual feedback here what's happening
}
@@ -360,19 +387,19 @@ clickedButtonAtIndex:(NSInteger)buttonIndex
}
UILabel *main_label = (UILabel *)[cell viewWithTag:1];
- UILabel *members_label = (UILabel *)[cell viewWithTag:2];
-
- // show name and members
main_label.text = shared_list.name;
- members_label.text = [self process_members_array:shared_list.members_phone_nums];
+
+ [self process_members_array:shared_list.members_phone_nums cell:cell];
// hang on to a reference, this is needed in the networking gui callbacks
shared_list.cell = cell;
return cell;
}
-- (NSString *) process_members_array:(NSArray *)phnum_array
+- (void) process_members_array:(NSArray *)phnum_array cell:(UITableViewCell *)cell
{
+ UILabel *members_label = (UILabel *)[cell viewWithTag:2];
+
if (!OSAtomicAnd32(0xffff, &_address_book->ready)) {
// not ready
NSMutableString *output = [[NSMutableString alloc] init];
@@ -384,7 +411,8 @@ clickedButtonAtIndex:(NSInteger)buttonIndex
[output appendFormat:@", %@", tmp_phone_number];
}
- return output;
+ members_label.text = output;
+ return;
}
// we can do phone number to name mappings
@@ -420,7 +448,8 @@ clickedButtonAtIndex:(NSInteger)buttonIndex
others, plural];
[members_str appendString:buf];
}
- return members_str;
+
+ members_label.text = members_str;
}
// section header titles
@@ -457,7 +486,7 @@ clickedButtonAtIndex:(NSInteger)buttonIndex
return UITableViewCellEditingStyleDelete;
}
-// this functions called when delete has been prompted and ok'd
+// This functions called when delete has been prompted and ok'd
- (void) tableView:(UITableView *)tableView
commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
@@ -466,10 +495,13 @@ clickedButtonAtIndex:(NSInteger)buttonIndex
SharedList *list = [[_lists objectAtIndex:0] objectAtIndex:[indexPath row]];
NSLog(@"info: leaving '%@' list num '%@'", list.name, list.num);
- // send leave list message, response will do all heavy lifting
+ // Send leave list message, response will do all heavy lifting
NSMutableDictionary *request = [[NSMutableDictionary alloc] init];
- [request setObject:list.num forKey:@"num"];
+ [request setObject:list.num forKey:@"list_num"];
[network_connection send_message:list_leave contents:request];
+
+ // Reset editing state back to the default
+ [self.tableView setEditing:FALSE animated:TRUE];
}
// customize deletion label text
diff --git a/ios/shlist/Network.m b/ios/shlist/Network.m
@@ -46,7 +46,7 @@
- (void) connect
{
- [self info:@"network: connect()"];
+ NSLog(@"network: connect()");
connected = 1;
CFReadStreamRef readStream;
@@ -74,7 +74,7 @@
- (void) disconnect
{
- [self info:@"network: disconnect()"];
+ NSLog(@"network: disconnect()");
connected = 0;
[inputShlistStream close];
@@ -130,7 +130,7 @@
[msg appendData:json];
[outputShlistStream write:[msg bytes] maxLength:[msg length]];
- [self info:@"register: sent request"];
+ NSLog(@"register: sent request");
// we don't have a device id so we can't do anything yet
return false;
@@ -141,8 +141,6 @@
if (!connected)
[self connect];
- NSMutableData *msg = [NSMutableData data];
-
[request setObject:device_id forKey:@"device_id"];
NSError *error = nil;
@@ -156,22 +154,23 @@
uint16_t msg_type_network = htons(send_msg_type);
uint16_t length = htons([json length]);
+ NSMutableData *msg = [NSMutableData data];
[msg appendBytes:&version length:2];
[msg appendBytes:&msg_type_network length:2];
[msg appendBytes:&length length:2];
[msg appendData:json];
- [self info:@"network: send_message: type %i, %i bytes",
- send_msg_type, [msg length]];
+ NSLog(@"network: send_message: type %i, %i bytes",
+ send_msg_type, [msg length]);
if ([outputShlistStream write:[msg bytes] maxLength:[msg length]] == -1) {
- [self warn:@"network: write error occurred, trying reconnect"];
+ NSLog(@"network: write error occurred, trying reconnect");
if (connected)
[self disconnect];
[self connect];
if ([outputShlistStream write:[msg bytes] maxLength:[msg length]] == -1) {
- [self warn:@"network: resend failed after reconnect, giving up"];
+ NSLog(@"network: resend failed after reconnect, giving up");
return false;
}
}
@@ -190,19 +189,19 @@
switch (eventCode) {
case NSStreamEventNone: {
- [self debug:@"network: NSStreamEventNone occurred"];
+ NSLog(@"network: NSStreamEventNone occurred");
break;
}
case NSStreamEventOpenCompleted: {
- [self debug:@"network: %@ opened", stream_name];
+ NSLog(@"network: %@ opened", stream_name);
break;
}
case NSStreamEventHasBytesAvailable: {
- [self debug:@"network: %@ has bytes available", stream_name];
+ NSLog(@"network: %@ has bytes available", stream_name);
if (stream == inputShlistStream) {
if (![inputShlistStream hasBytesAvailable]) {
- [self warn:@"read: input stream had no bytes available"];
+ NSLog(@"read: input stream had no bytes available");
break;
}
@@ -211,7 +210,7 @@
break;
}
case NSStreamEventHasSpaceAvailable: {
- [self debug:@"network: %@ has space available", stream_name];
+ NSLog(@"network: %@ has space available", stream_name);
break;
}
case NSStreamEventErrorOccurred: {
@@ -226,15 +225,15 @@
break;
NSError *theError = [error_stream streamError];
- [self info:@"network: %@", [NSString stringWithFormat:@"%@ error %i: %@",
- stream_name, [theError code], [theError localizedDescription]]];
+ NSLog(@"network: %@", [NSString stringWithFormat:@"%@ error %i: %@",
+ stream_name, [theError code], [theError localizedDescription]]);
[self disconnect];
break;
}
case NSStreamEventEndEncountered: {
- [self debug:@"network: %@ end encountered", stream_name];
+ NSLog(@"network: %@ end encountered", stream_name);
[self disconnect];
break;
@@ -251,7 +250,7 @@
buffer_len = [inputShlistStream read:(uint8_t *)header maxLength:6];
if (buffer_len != 6) {
- [self error:@"read: didn't return 6 bytes"];
+ NSLog(@"read: didn't return 6 bytes");
}
uint16_t version = ntohs(header[0]);
@@ -259,28 +258,25 @@
uint16_t payload_size = ntohs(header[2]);
if (version != 0) {
- [self error:@"read: invalid version %i", version];
- }
- if (msg_type > 10) {
- [self error:@"read: invalid message type %i", msg_type];
- }
- if (payload_size > 4095) {
- [self error:@"read: %i bytes payload too large", payload_size];
+ NSLog(@"read: invalid version %i", version);
+ return;
}
- if (payload_size == 0) {
- // Payload doesn't contain anything, that's ok
+ if (msg_type > 11) {
+ NSLog(@"read: invalid message type %i", msg_type);
return;
}
uint8_t *payload = malloc(payload_size);
+
+ // Accept up to 64KB of data, the maximum size of payload_size
buffer_len = [inputShlistStream read:payload maxLength:payload_size];
if (buffer_len != payload_size) {
- [self error:@"read: expected %i byte payload but got %i", payload_size, buffer_len];
+ NSLog(@"read: expected %i byte payload but got %i", payload_size, buffer_len);
return;
}
- [self info:@"read: payload is %i bytes", buffer_len];
+ NSLog(@"read: payload is %i bytes", buffer_len);
- NSData *data = [NSData dataWithBytes:payload length:payload_size];
+ NSData *data = [NSData dataWithBytesNoCopy:payload length:payload_size];
NSError *error = nil;
NSDictionary *response = [NSJSONSerialization JSONObjectWithData:data
@@ -290,13 +286,13 @@
return;
}
- NSString *status = [response objectForKey:@"status"];
+ NSString *status = response[@"status"];
if (status == nil) {
NSLog(@"read: response did not contain 'status' key");
return;
}
if ([status compare:@"err"] == 0) {
- NSLog(@"read: response error, reason = '%@'", [response valueForKey:@"reason"]);
+ NSLog(@"read: response error, reason = '%@'", response[@"reason"]);
return;
}
@@ -308,18 +304,18 @@
[self lists_get:response];
} else if (msg_type == list_join) {
[self list_join:response];
+ } else if (msg_type == list_leave) {
+ [self list_leave:response];
} else if (msg_type == lists_get_other) {
[self lists_get_other:response];
}
-
- // free((void *)payload);
}
- (void) device_add:(NSDictionary *)response
{
device_id = [response objectForKey:@"device_id"];
- [self info:@"device_add: writing new key '%@' to file", device_id];
+ NSLog(@"device_add: writing new key '%@' to file", device_id);
NSError *error = nil;
[device_id writeToFile:device_id_file atomically:YES encoding:NSUTF8StringEncoding error:&error];
@@ -343,7 +339,7 @@
if ([self check_tvc:shlist_tvc])
[shlist_tvc finished_new_list_request:shlist];
- [self info:@"list_add: successfully added new list '%@'", shlist.name];
+ NSLog(@"list_add: successfully added new list '%@'", shlist.name);
}
- (void) lists_get:(NSDictionary *)response
@@ -374,97 +370,30 @@
- (void) list_join:(NSDictionary *)response
{
- SharedList *shlist = [[SharedList alloc] init];
- shlist.num = [response objectForKey:@"num"];
-
- // XXX: these need to be sent from the server
- // shlist.items_ready = 0;
- // shlist.items_total = 99;
- // shlist.list_name = <network>;
- // shlist.members = <network>;
+ NSDictionary *list = response[@"list"];
+ NSLog(@"network: joined list %@", list[@"num"]);
if ([self check_tvc:shlist_tvc])
- [shlist_tvc finished_join_list_request:shlist];
- [self info:@"list_join: joined list %i", shlist.num];
+ [shlist_tvc finished_join_list_request:list];
}
- (void) list_leave:(NSDictionary *)response
{
- SharedList *shlist = [[SharedList alloc] init];
- shlist.num = [response objectForKey:@"num"];
-
- // XXX: these need to be sent from the server
- // shlist.list_name = <network>;
- // shlist.members = <network>;
+ NSNumber *list_num = response[@"list_num"];
+ NSLog(@"network: left list %@", list_num);
if ([self check_tvc:shlist_tvc])
- [shlist_tvc finished_leave_list_request:shlist];
- [self info:@"list_leave: left list", shlist.num];
+ [shlist_tvc finished_leave_list_request:response];
}
- (bool) check_tvc:(MainTableViewController *) tvc
{
if (tvc)
return true;
- [self warn:@"network: trying to update main_tvc before it's ready, ignoring!"];
+ NSLog(@"network: trying to update main_tvc before it's ready, ignoring!");
return false;
}
-#define LOG_LEVEL_ERROR 0
-#define LOG_LEVEL_WARN 1
-#define LOG_LEVEL_INFO 2
-#define LOG_LEVEL_DEBUG 3
-
-#define LOG_LEVEL LOG_LEVEL_INFO
-
-- (void) debug:(NSString *)fmt, ...
-{
- va_list va;
- va_start(va, fmt);
- NSString *string = [[NSString alloc] initWithFormat:fmt
- arguments:va];
- va_end(va);
- if (LOG_LEVEL < LOG_LEVEL_DEBUG)
- return;
- NSLog(@"debug: %@", string);
-}
-
-- (void) info:(NSString *)fmt, ...
-{
- va_list va;
- va_start(va, fmt);
- NSString *string = [[NSString alloc] initWithFormat:fmt
- arguments:va];
- va_end(va);
- if (LOG_LEVEL < LOG_LEVEL_INFO)
- return;
- NSLog(@"info: %@", string);
-}
-
-- (void) warn:(NSString *)fmt, ...
-{
- va_list va;
- va_start(va, fmt);
- NSString *string = [[NSString alloc] initWithFormat:fmt
- arguments:va];
- va_end(va);
- if (LOG_LEVEL < LOG_LEVEL_WARN)
- return;
- NSLog(@"warn: %@", string);
-}
-
-- (void) error:(NSString *)fmt, ...
-{
- va_list va;
- va_start(va, fmt);
- NSString *string = [[NSString alloc] initWithFormat:fmt
- arguments:va];
- va_end(va);
- if (LOG_LEVEL < LOG_LEVEL_ERROR)
- return;
- NSLog(@"error: %@", string);
-}
-
- (void) dealloc
{
[self disconnect];
diff --git a/ios/shlist/main.m b/ios/shlist/main.m
@@ -5,4 +5,4 @@ int main(int argc, char *argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
-}
+}
+\ No newline at end of file