shlist

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

commit 442a5b7a139feb72db7d8f5b511e3d0eae1df1ff
parent 7dfdbf09145a8c6d761ae60ac722fdbd7915b173
Author: Kyle Milz <kyle@Kyles-MacBook-Pro.local>
Date:   Thu,  9 Jul 2015 21:37:14 -0600

ios: get some more stuff working

+ loading of lists from the server works
+ lists are split on the main screen by your involvement
+ list items are split between personal and shared
+ probably some other stuff

Diffstat:
Mios-ng/ContactsViewController.m | 11++++++-----
Mios-ng/shlist/AppDelegate.m | 15++++++++-------
Mios-ng/shlist/Base.lproj/Main.storyboard | 50++++++++++++++++++++++++++++++--------------------
Mios-ng/shlist/ListDetailTableViewController.m | 38++++++++++++++++++++++++--------------
Mios-ng/shlist/NewListViewController.m | 6+++---
Mios-ng/shlist/SharedList.h | 1+
Mios-ng/shlist/SharedListsTableViewController.h | 5++++-
Mios-ng/shlist/SharedListsTableViewController.m | 203+++++++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------
Mios-ng/shlist/ShlistServer.h | 13+++++++++----
Mios-ng/shlist/ShlistServer.m | 207+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
10 files changed, 386 insertions(+), 163 deletions(-)

diff --git a/ios-ng/ContactsViewController.m b/ios-ng/ContactsViewController.m @@ -6,7 +6,7 @@ @implementation ContactsViewController -- (void)viewDidLoad { +- (void) viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. @@ -19,12 +19,12 @@ [self.view addSubview:picker.view]; } -- (void)didReceiveMemoryWarning { +- (void) didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } -- (BOOL)peoplePickerNavigationController: +- (BOOL) peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person { @@ -35,7 +35,7 @@ return NO; } -- (BOOL)peoplePickerNavigationController: +- (BOOL) peoplePickerNavigationController: (ABPeoplePickerNavigationController *)peoplePicker shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property @@ -54,4 +54,4 @@ } */ -@end +@end +\ No newline at end of file diff --git a/ios-ng/shlist/AppDelegate.m b/ios-ng/shlist/AppDelegate.m @@ -7,13 +7,13 @@ @implementation AppDelegate -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +- (BOOL) application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // customization after application launch return YES; } -- (void)applicationWillResignActive:(UIApplication *)application +- (void) applicationWillResignActive:(UIApplication *)application { // Sent when the application is about to move from active to inactive // state. This can occur for certain types of temporary interruptions @@ -26,7 +26,7 @@ // game. } -- (void)applicationDidEnterBackground:(UIApplication *)application +- (void) applicationDidEnterBackground:(UIApplication *)application { // Use this method to release shared resources, save user data, // invalidate timers, and store enough application state information to @@ -36,24 +36,24 @@ // called instead of applicationWillTerminate: when the user quits. } -- (void)applicationWillEnterForeground:(UIApplication *)application +- (void) applicationWillEnterForeground:(UIApplication *)application { // Called as part of the transition from the background to the inactive // state; here you can undo many of the changes made on entering the // background. } -- (void)applicationDidBecomeActive:(UIApplication *)application +- (void) applicationDidBecomeActive:(UIApplication *)application { // Restart any tasks that were paused (or not yet started) while the // application was inactive. If the application was previously in the // background, optionally refresh the user interface. } -- (void)applicationWillTerminate:(UIApplication *)application +- (void) applicationWillTerminate:(UIApplication *)application { // Called when the application is about to terminate. Save data if // appropriate. See also applicationDidEnterBackground:. } -@end +@end +\ No newline at end of file diff --git a/ios-ng/shlist/Base.lproj/Main.storyboard b/ios-ng/shlist/Base.lproj/Main.storyboard @@ -78,6 +78,26 @@ <segue destination="pMK-tA-j4s" kind="show" id="ORk-KR-Twe"/> </connections> </tableViewCell> + <tableViewCell contentMode="scaleToFill" selectionStyle="blue" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="IndirectListPrototypeCell" textLabel="WuW-Sd-sxB" detailTextLabel="rf3-DG-Fgi" style="IBUITableViewCellStyleSubtitle" id="kbj-EX-eeF"> + <autoresizingMask key="autoresizingMask"/> + <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="kbj-EX-eeF" id="fgg-hw-Da6"> + <autoresizingMask key="autoresizingMask"/> + <subviews> + <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Title" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="WuW-Sd-sxB"> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <fontDescription key="fontDescription" type="system" pointSize="16"/> + <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> + <nil key="highlightedColor"/> + </label> + <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Subtitle" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="rf3-DG-Fgi"> + <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/> + <fontDescription key="fontDescription" type="system" pointSize="11"/> + <color key="textColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/> + <nil key="highlightedColor"/> + </label> + </subviews> + </tableViewCellContentView> + </tableViewCell> </prototypes> <sections/> <connections> @@ -114,7 +134,7 @@ <subviews> <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="new list name" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="gPO-fo-XXP"> <rect key="frame" x="16" y="72" width="568" height="30"/> - <fontDescription key="fontDescription" type="system" pointSize="14"/> + <fontDescription key="fontDescription" type="system" pointSize="16"/> <textInputTraits key="textInputTraits" returnKeyType="done"/> <connections> <action selector="textField" destination="BYZ-38-t0r" eventType="editingDidEnd" id="x6t-Ub-mbI"/> @@ -173,9 +193,10 @@ <rect key="frame" x="0.0" y="0.0" width="600" height="600"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <subviews> - <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" misplaced="YES" text="This is something we do on our free time. If you respect that, please donate." translatesAutoresizingMaskIntoConstraints="NO" id="3Tn-bI-uKk"> - <rect key="frame" x="16" y="134" width="568" height="37"/> + <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" selectable="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vqD-fu-CUL"> + <rect key="frame" x="16" y="57" width="568" height="316"/> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> + <string key="text">This project is a humble attempt to help people be more organized. It's main purpose is to make group events easy to plan and execute. It's founders hope you find it as useful as they do.

This is something we do on our free time. If you respect that, please donate.</string> <fontDescription key="fontDescription" type="system" pointSize="14"/> <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/> </textView> @@ -185,26 +206,15 @@ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/> <nil key="highlightedColor"/> </label> - <textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" misplaced="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vqD-fu-CUL"> - <rect key="frame" x="16" y="49" width="568" height="77"/> - <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> - <string key="text">This project is a humble attempt to help people be more organized. It's main purpose is to make group events easy to plan and execute. It's founders hope you find it as useful as they do.</string> - <fontDescription key="fontDescription" type="system" pointSize="14"/> - <textInputTraits key="textInputTraits" autocapitalizationType="sentences"/> - </textView> </subviews> <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/> <constraints> - <constraint firstItem="vqD-fu-CUL" firstAttribute="trailing" secondItem="BEH-Qp-ix3" secondAttribute="trailingMargin" id="0kQ-sN-zkj"/> - <constraint firstItem="hjG-BQ-XBF" firstAttribute="leading" secondItem="BEH-Qp-ix3" secondAttribute="leadingMargin" id="64i-ls-ddW"/> - <constraint firstItem="3Tn-bI-uKk" firstAttribute="trailing" secondItem="BEH-Qp-ix3" secondAttribute="trailingMargin" id="AlZ-Vo-99h"/> - <constraint firstItem="vqD-fu-CUL" firstAttribute="leading" secondItem="BEH-Qp-ix3" secondAttribute="leadingMargin" id="Bxp-G1-gOp"/> - <constraint firstItem="3Tn-bI-uKk" firstAttribute="top" secondItem="vqD-fu-CUL" secondAttribute="bottom" constant="8" id="GR0-aa-vSO"/> - <constraint firstItem="3Tn-bI-uKk" firstAttribute="leading" secondItem="BEH-Qp-ix3" secondAttribute="leadingMargin" id="e5J-II-Cyn"/> - <constraint firstAttribute="trailingMargin" secondItem="hjG-BQ-XBF" secondAttribute="trailing" constant="496" id="mgk-JE-jzk"/> - <constraint firstItem="vqD-fu-CUL" firstAttribute="top" secondItem="hjG-BQ-XBF" secondAttribute="bottom" constant="8" id="rnu-FP-hp6"/> - <constraint firstItem="hjG-BQ-XBF" firstAttribute="top" secondItem="3hJ-K1-i1o" secondAttribute="bottom" constant="8" id="vgR-2B-gRS"/> - <constraint firstItem="9zw-4a-J6h" firstAttribute="top" secondItem="3Tn-bI-uKk" secondAttribute="bottom" constant="8" symbolic="YES" id="w2y-Cf-BBd"/> + <constraint firstItem="9zw-4a-J6h" firstAttribute="top" secondItem="vqD-fu-CUL" secondAttribute="bottom" constant="178" id="9Cp-IX-R3d"/> + <constraint firstItem="vqD-fu-CUL" firstAttribute="leading" secondItem="hjG-BQ-XBF" secondAttribute="leading" id="XeA-5Y-GFI"/> + <constraint firstItem="vqD-fu-CUL" firstAttribute="top" secondItem="hjG-BQ-XBF" secondAttribute="bottom" constant="8" symbolic="YES" id="ZQH-f4-CgD"/> + <constraint firstItem="hjG-BQ-XBF" firstAttribute="leading" secondItem="BEH-Qp-ix3" secondAttribute="leadingMargin" id="dS7-kL-9Vc"/> + <constraint firstItem="hjG-BQ-XBF" firstAttribute="top" secondItem="3hJ-K1-i1o" secondAttribute="bottom" constant="8" symbolic="YES" id="nss-ZG-IMi"/> + <constraint firstItem="vqD-fu-CUL" firstAttribute="trailing" secondItem="BEH-Qp-ix3" secondAttribute="trailingMargin" id="rlU-s2-Y9s"/> </constraints> </view> <tabBarItem key="tabBarItem" title="About Us" id="djS-DN-skn" userLabel="About Us"/> diff --git a/ios-ng/shlist/ListDetailTableViewController.m b/ios-ng/shlist/ListDetailTableViewController.m @@ -9,9 +9,9 @@ @implementation ListDetailTableViewController -- (void)load_initial_data +- (void) load_initial_data { - NSLog(@"ListDetailTableViewController::load_initial_data()"); + // NSLog(@"ListDetailTableViewController::load_initial_data()"); ListItem *item1 = [[ListItem alloc] init]; item1.name = @"Axe"; @@ -29,7 +29,7 @@ [self.list_items addObject:item3]; } -- (void)viewDidLoad +- (void) viewDidLoad { [super viewDidLoad]; @@ -45,7 +45,7 @@ [self load_initial_data]; } -- (void)didReceiveMemoryWarning +- (void) didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. @@ -53,21 +53,32 @@ #pragma mark - Table view data source -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { - return 1; + return 2; } -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.list_items count]; } -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section +{ + if (section == 0) { + return @"shared items"; + } + else if (section == 1) { + return @"personal items"; + } + return @""; +} + +- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ListDetailPrototypeCell" forIndexPath:indexPath]; - NSLog(@"ListDetailTableViewController::cellForRowAtIndexPath()"); + // NSLog(@"ListDetailTableViewController::cellForRowAtIndexPath()"); ListItem *item = [self.list_items objectAtIndex:indexPath.row]; cell.textLabel.text = item.name; @@ -76,15 +87,13 @@ return cell; } -/* // Override to support conditional editing of the table view. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the specified item to be editable. return YES; } -*/ -/* + // Override to support editing the table view. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { @@ -94,7 +103,7 @@ // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view } } -*/ + /* // Override to support rearranging the table view. @@ -120,4 +129,4 @@ } */ -@end +@end +\ No newline at end of file diff --git a/ios-ng/shlist/NewListViewController.m b/ios-ng/shlist/NewListViewController.m @@ -11,12 +11,12 @@ @implementation NewListViewController -- (void)viewDidLoad { +- (void) viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. } -- (void)didReceiveMemoryWarning { +- (void) didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @@ -24,7 +24,7 @@ #pragma mark - Navigation // preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender +- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. diff --git a/ios-ng/shlist/SharedList.h b/ios-ng/shlist/SharedList.h @@ -7,6 +7,7 @@ // UILabel *names; @property NSString *list_name; +@property NSString *list_id; @property NSString *list_members; @property NSDate *list_date; diff --git a/ios-ng/shlist/SharedListsTableViewController.h b/ios-ng/shlist/SharedListsTableViewController.h @@ -3,7 +3,9 @@ @interface SharedListsTableViewController : UITableViewController @property NSMutableArray *shared_lists; +@property NSMutableArray *indirect_lists; + - (IBAction)unwindToList:(UIStoryboardSegue *)segue; -@end +@end +\ No newline at end of file diff --git a/ios-ng/shlist/SharedListsTableViewController.m b/ios-ng/shlist/SharedListsTableViewController.m @@ -6,6 +6,7 @@ @interface SharedListsTableViewController () @property (strong, nonatomic) ShlistServer *server; +@property (strong, nonatomic) NSData *device_id; @end @@ -19,31 +20,50 @@ // initialize connection _server = [[ShlistServer alloc] init]; - - bool initialized = false; - if (!initialized) { - // new client - [_server writeToServer:"\x00\x00\x00\x0a" "4037082094" :15]; - // [server readFromServer]; + _server->shlist_tvc = self; + + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + NSString *destinationPath = [documentsDirectory stringByAppendingPathComponent:@"shlist_key"]; + + if (![[NSFileManager defaultManager] fileExistsAtPath:destinationPath]) { + // do a fake registration + NSData *msg_register = [NSData dataWithBytes:"\x00\x00\x00\x0a" "4037082094" length:15]; + [_server writeToServer:msg_register]; + NSLog(@"Sent registration"); } - NSLog(@"SharedListsTableViewController::load_initial_data()"); + // send bulk shared list update + NSMutableData *msg = [NSMutableData data]; + [msg appendBytes:"\x00\x03" length:2]; + + // read device id from filesystem into memory + _device_id = [NSData dataWithContentsOfFile:destinationPath]; + + // write length of device id as uint16 + uint16_t dev_id_len_network = htons([_device_id length]); + [msg appendBytes:&dev_id_len_network length:2]; + + // append device id itself + [msg appendData:_device_id]; + + // NSLog(@"SharedListsTableViewController::load_initial_data() device id lenth = %i", device_id_length); // NSString *num = [[NSUserDefaults standardUserDefaults] stringForKey:@"SBFormattedPhoneNumber"]; // NSLog(@"%@\n", num); // ShlistServer *server = [[ShlistServer alloc] init]; - // [server writeToServer:"\x00\x00\xff\0x00"]; + [_server writeToServer:msg]; SharedList *list1 = [[SharedList alloc] init]; list1.list_name = @"Camping"; - list1.list_members = @"David, Kyle, Greg"; - [self.shared_lists addObject:list1]; + list1.list_members = @"David, Greg"; + [self.indirect_lists addObject:list1]; SharedList *list2 = [[SharedList alloc] init]; list2.list_name = @"Wedding"; - list2.list_members = @"Kyle, Stephanie"; - [self.shared_lists addObject:list2]; + list2.list_members = @"Stephanie, Beatrice"; + [self.indirect_lists addObject:list2]; } - (IBAction) unwindToList:(UIStoryboardSegue *)segue @@ -51,26 +71,49 @@ NewListViewController *source = [segue sourceViewController]; SharedList *list = source.shared_list; - if (list != nil) { - [self.shared_lists addObject:list]; - [self.tableView reloadData]; + if (list == nil) { + return; } + [self.shared_lists addObject:list]; + [self.tableView reloadData]; + + // send new list message + NSMutableData *msg = [NSMutableData data]; + [msg appendBytes:"\x00\x01" length:2]; + + // length = device id + list name + null separator + uint16_t length_network_endian = htons([_device_id length] + [list.list_name length] + 1); + [msg appendBytes:&length_network_endian length:2]; + + // append device id + [msg appendData:_device_id]; + + // append null separator + [msg appendBytes:"\0" length:1]; + + // append new list name + [msg appendData:[list.list_name dataUsingEncoding:NSUTF8StringEncoding]]; + + [_server writeToServer:msg]; + NSLog(@"unwindToList(): done"); } - (void)viewDidLoad { [super viewDidLoad]; - + // Uncomment the following line to preserve selection between // presentations. // self.clearsSelectionOnViewWillAppear = NO; - + // display an Edit button in the navigation bar for this view controller self.navigationItem.leftBarButtonItem = self.editButtonItem; - + self.shared_lists = [[NSMutableArray alloc] init]; + self.indirect_lists = [[NSMutableArray alloc] init]; + [self load_initial_data]; } @@ -82,79 +125,127 @@ #pragma mark - Table view data source -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView +- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView { - return 1; + return 2; } -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section +- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [self.shared_lists count]; + if (section == 0) { + return [self.shared_lists count]; + } + else if (section == 1) { + return 2; + } + + return 0; } -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath +- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell; - cell = [tableView dequeueReusableCellWithIdentifier:@"SharedListPrototypeCell" forIndexPath:indexPath]; - // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SharedListPrototypeCell"]; - - if (cell == nil) { - cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"SharedListPrototypeCell"]; - cell.selectionStyle = UITableViewCellSelectionStyleNone; - } - NSLog(@"SharedListsTableViewController::cellForRowAtIndexPath()"); + // NSLog(@"SharedListsTableViewController::cellForRowAtIndexPath()"); + + NSInteger section_number = [indexPath section]; + if (section_number == 0) { + cell = [tableView dequeueReusableCellWithIdentifier:@"SharedListPrototypeCell" forIndexPath:indexPath]; + // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SharedListPrototypeCell"]; + + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"SharedListPrototypeCell"]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + } - // configure the cell - SharedList *shared_list = [self.shared_lists objectAtIndex:indexPath.row]; - cell.textLabel.text = shared_list.list_name; - cell.detailTextLabel.text = shared_list.list_members; + SharedList *shared_list = [self.shared_lists objectAtIndex:indexPath.row]; + cell.textLabel.text = shared_list.list_name; + cell.detailTextLabel.text = shared_list.list_members; + } + else if (section_number == 1) { + cell = [tableView dequeueReusableCellWithIdentifier:@"IndirectListPrototypeCell" forIndexPath:indexPath]; + // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SharedListPrototypeCell"]; + + if (cell == nil) { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"IndirectListPrototypeCell"]; + cell.selectionStyle = UITableViewCellSelectionStyleNone; + } + + SharedList *shared_list = [self.indirect_lists objectAtIndex:indexPath.row]; + cell.textLabel.text = shared_list.list_name; + cell.detailTextLabel.text = shared_list.list_members; + } return cell; } -/* +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section +{ + if (section == 0) { + if ([self.shared_lists count] == 0) { + return @"you're not in any lists"; + } + else if ([self.shared_lists count] == 1) { + return @"list you are in"; + } + return @"lists you are in"; + } + else if (section == 1) { + if ([self.indirect_lists count] == 0) { + return @"your friends don't have any lists"; + } + else if ([self.indirect_lists count] == 1) { + return @"list your friends are in"; + } + return @"lists your friends are in"; + } + return @""; +} + // Override to support conditional editing of the table view. -- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { - // Return NO if you do not want the specified item to be editable. - return YES; +- (BOOL) tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath +{ + if ([indexPath section] == 0) { + // editable + return YES; + } + + return NO; } -*/ -/* // Override to support editing the table view. -- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { - if (editingStyle == UITableViewCellEditingStyleDelete) { - // Delete the row from the data source - [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; - } else if (editingStyle == UITableViewCellEditingStyleInsert) { - // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view - } +- (void) tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (editingStyle == UITableViewCellEditingStyleDelete) { + // Delete the row from the data source + [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade]; + // [self.shared_lists removeObjectAtIndex:[indexPath row]]; + } else if (editingStyle == UITableViewCellEditingStyleInsert) { + NSLog(@"editing style insert"); + // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view + } } -*/ /* // Override to support rearranging the table view. -- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { +- (void) tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath { } */ /* // Override to support conditional rearranging of the table view. -- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { +- (BOOL) tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { // Return NO if you do not want the item to be re-orderable. return YES; } */ -/* -#pragma mark - Navigation - // In a storyboard-based application, you will often want to do a little preparation before navigation -- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { +- (void) prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { // Get the new view controller using [segue destinationViewController]. // Pass the selected object to the new view controller. + + NSLog(@"preparing for segue"); } -*/ @end diff --git a/ios-ng/shlist/ShlistServer.h b/ios-ng/shlist/ShlistServer.h @@ -1,11 +1,16 @@ #import <UIKit/UIKit.h> +#import "SharedListsTableViewController.h" @interface ShlistServer : NSObject <NSStreamDelegate> { - NSInputStream *inputShlistStream; - NSOutputStream *outputShlistStream; - int *bytesRead; + NSInputStream *inputShlistStream; + NSOutputStream *outputShlistStream; + int *bytesRead; + + @public + SharedListsTableViewController *shlist_tvc; } -- (void) writeToServer:(const char *)data :(size_t)length; + +- (void) writeToServer:(NSData *)data; @end \ No newline at end of file diff --git a/ios-ng/shlist/ShlistServer.m b/ios-ng/shlist/ShlistServer.m @@ -1,4 +1,5 @@ #import "ShlistServer.h" +#import "SharedList.h" @interface ShlistServer () @@ -11,82 +12,162 @@ - (id) init { if (self = [super init]) { - CFReadStreamRef readStream; - CFWriteStreamRef writeStream; - - CFStringRef host_name = CFSTR("absentmindedproductions.ca"); - - CFStreamCreatePairWithSocketToHost(NULL, host_name, 5437, &readStream, &writeStream); - inputShlistStream = (__bridge NSInputStream *)readStream; - outputShlistStream = (__bridge NSOutputStream *)writeStream; - - [inputShlistStream setDelegate:self]; - [outputShlistStream setDelegate:self]; - - [inputShlistStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - [outputShlistStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - - [inputShlistStream open]; - [outputShlistStream open]; + /* + CFReadStreamRef readStream; + CFWriteStreamRef writeStream; + + CFStringRef host_name = CFSTR("absentmindedproductions.ca"); + + CFStreamCreatePairWithSocketToHost(NULL, host_name, 5437, &readStream, &writeStream); + inputShlistStream = (__bridge NSInputStream *)readStream; + outputShlistStream = (__bridge NSOutputStream *)writeStream; + + [inputShlistStream setDelegate:self]; + [outputShlistStream setDelegate:self]; + + [inputShlistStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + [outputShlistStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + + [inputShlistStream open]; + [outputShlistStream open]; + */ } return self; } -- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode +- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode { switch (eventCode) { case NSStreamEventNone: break; case NSStreamEventOpenCompleted: - NSLog(@"Stream Opened"); - break; + if (stream == inputShlistStream) { + NSLog(@"info: input stream opened"); + } + else if (stream == outputShlistStream) { + NSLog(@"info: output stream opened"); + } + break; case NSStreamEventHasBytesAvailable: - - if (aStream == inputShlistStream) { + if (stream == inputShlistStream) { + /* + if (![inputShlistStream hasBytesAvailable]) { + break; + } + */ + NSInteger len; uint16_t msg_metadata[2]; len = [inputShlistStream read:(uint8_t *)&msg_metadata maxLength:4]; - if (len != 4) { - NSLog(@"warn: msg metadata was %li bytes, expected 4 bytes", + NSLog(@"warn: read: msg metadata was %li bytes, expected 4", (long)len); break; } - if (msg_metadata[0] > 4) { - NSLog(@"warn: out of range msg type %i", msg_metadata[0]); + + uint16_t msg_type = ntohs(msg_metadata[0]); + uint16_t msg_length = ntohs(msg_metadata[1]); + if (msg_type > 4) { + NSLog(@"warn: read: out of range msg type %i", msg_type); break; } - NSLog(@"info: received message type %i", msg_metadata[0]); + NSLog(@"info: read: received message type %i", msg_type); - if (msg_metadata[1] > 1024) { - NSLog(@"warn: message too large: %i bytes", msg_metadata[1]); + if (msg_length > 1024) { + NSLog(@"warn: read: message too large: %i bytes", msg_length); break; } - NSLog(@"info: message size is %i bytes", msg_metadata[1]); - - uint8_t *buffer = malloc(msg_metadata[1]); + NSLog(@"info: read: message size is %i bytes", msg_length); + + uint8_t *buffer = malloc(msg_length); if (buffer == nil) { - NSLog(@"warn: couldn't allocate receiving buffer size %i", - msg_metadata[1]); + NSLog(@"warn: read: couldn't allocate receiving buffer size %i", + msg_length); break; } - - len = [inputShlistStream read:buffer maxLength:msg_metadata[1]]; - if (len != msg_metadata[1]) { - NSLog(@"warn: main message read byte mismatch: %li vs %i", - (long)len, msg_metadata[1]); + + len = [inputShlistStream read:buffer maxLength:msg_length]; + if (len != msg_length) { + NSLog(@"warn: read: main message read byte mismatch: %li vs %i", + (long)len, msg_length); break; } NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding]; + NSData *data = [[NSData alloc] initWithBytes:buffer length:msg_length]; if (output == nil) { - NSLog(@"warn: couldn't allocate output string"); + NSLog(@"warn: read: couldn't allocate output string"); break; } - NSLog(@"info: message is %@", output); + NSLog(@"info: read: message is %@", output); + + if (msg_type == 0) { + // write key to file + NSLog(@"info: read: writing new keyfile to disk"); + + NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); + NSString *documentsDirectory = [paths objectAtIndex:0]; + + NSString *destinationPath = [documentsDirectory stringByAppendingPathComponent:@"shlist_key"]; + // if (![[NSFileManager defaultManager] fileExistsAtPath:destinationPath]) { + [data writeToFile:destinationPath atomically:YES]; + // } + } + + if (msg_type == 3) { + NSLog(@"info: read: processing bulk list update message"); + + // split over double \0 + NSArray *list_types = [output componentsSeparatedByString:@"\0\0"]; + if ([list_types count] != 2) { + NSLog(@"warn: more than one \\0\\0 found in response"); + break; + } + + // split over \0 + NSString *direct_list_str = [list_types objectAtIndex:0]; + NSString *indirect_list_str = [list_types objectAtIndex:1]; + + if ([direct_list_str length] != 0) { + NSArray *direct_lists = [direct_list_str componentsSeparatedByString:@"\0"]; + [shlist_tvc.shared_lists removeAllObjects]; + + for (id str in direct_lists) { + // NSLog(@"info: got raw direct list %@", str); + + NSArray *broken_down_list = [str componentsSeparatedByString:@":"]; + + + SharedList *shared_list = [[SharedList alloc] init]; + shared_list.list_name = [broken_down_list objectAtIndex:0]; + shared_list.list_id = [broken_down_list objectAtIndex:1]; + shared_list.list_members = [broken_down_list objectAtIndex:2]; + + NSLog(@"info: network: got list '%@'", shared_list.list_name); + [shlist_tvc.shared_lists addObject:shared_list]; + + // [direct_shared_lists addObject:shared_list]; + } + + } + if ([indirect_list_str length] != 0) { + NSArray *indirect_lists = [indirect_list_str componentsSeparatedByString:@"\0"]; + } + [shlist_tvc.tableView reloadData]; + + /* + dispatch_async(dispatch_get_main_queue(), ^{ + shlist_tvc.shared_lists = direct_shared_lists; + [shlist_tvc.tableView reloadData]; + }); + */ + // [shlist_tvc update_shared_lists:direct_shared_lists :indirect_shared_lists]; + + // NSLog(@"info: %i direct lists, %i indirect lists"); + } } break; case NSStreamEventHasSpaceAvailable: @@ -94,6 +175,7 @@ break; case NSStreamEventErrorOccurred: NSLog(@"ShlistServer::NSStreamEventErrorOccurred"); + // I saw this case when trying to connect to a down server break; case NSStreamEventEndEncountered: { @@ -114,23 +196,23 @@ break; } default: - break; - } + break; + } } - (void) dealloc { - [inputShlistStream close]; - [outputShlistStream close]; - - [inputShlistStream removeFromRunLoop:[NSRunLoop currentRunLoop] + [inputShlistStream close]; + [outputShlistStream close]; + + [inputShlistStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; - [outputShlistStream removeFromRunLoop:[NSRunLoop currentRunLoop] + [outputShlistStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + - - inputShlistStream = nil; // stream is ivar, so reinit it - outputShlistStream = nil; // stream is ivar, so reinit it + inputShlistStream = nil; // stream is ivar, so reinit it + outputShlistStream = nil; // stream is ivar, so reinit it } - (void) _readData @@ -142,13 +224,32 @@ NSLog(@"_writeData"); } -- (void) writeToServer:(const char *)bytes :(size_t)length +- (void) writeToServer:(NSData *)data { + CFReadStreamRef readStream; + CFWriteStreamRef writeStream; + + CFStringRef host_name = CFSTR("absentmindedproductions.ca"); + + CFStreamCreatePairWithSocketToHost(NULL, host_name, 5437, &readStream, &writeStream); + inputShlistStream = (__bridge NSInputStream *)readStream; + outputShlistStream = (__bridge NSOutputStream *)writeStream; + + [inputShlistStream setDelegate:self]; + [outputShlistStream setDelegate:self]; + + [inputShlistStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + [outputShlistStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + + [inputShlistStream open]; + [outputShlistStream open]; + // const char bytes[] = "\x00\x00\xff\0x00"; //string literals have implicit trailing '\0' // size_t length = (sizeof bytes) - 1; - NSData *data = [NSData dataWithBytes:bytes length:length]; + // NSData *data = [NSData dataWithBytes:bytes length:length]; + NSLog(@"writeToServer()"); [outputShlistStream write:[data bytes] maxLength:[data length]]; }