Developer Area

root/apps/iphone/my.tel/trunk/Classes/KeywordViewController.m @ 768

Revision 768, 13.8 kB (checked in by henri, 3 years ago)

Record types, location indicators and keyword names are retrieved localized from the network.

Line 
1//
2//  KeywordViewController.m
3//  My.tel
4//
5//  Created by Henri Asseily on 11/18/08.
6//  Copyright 2008 Telnic Ltd.. All rights reserved.
7//
8
9// TODO: Implement new/edit
10// TODO: Implement deletion of records (in edit table mode)
11// TODO: Implement deletion of a record in swipe mode
12
13#import "KeywordViewController.h"
14
15#define kKRowHeight 54.0
16#define kKRowLineHeightIncrease 20.0
17
18@interface KeywordViewController (PrivateMethods)
19- (void)setDidPreload:(BOOL)preload;
20@end
21
22@implementation KeywordViewController
23
24@synthesize keywordTypesNames;
25@synthesize keywordTypes;
26
27@synthesize keywordsArray;
28@synthesize uiArray;
29
30@synthesize delegate;
31
32#pragma mark -
33#pragma mark Designated initializer
34
35+ (KeywordViewController *)controllerWithDelegate:(id <TelControllerDelegate>)aDelegate preload:(BOOL)preload {
36        KeywordViewController *theC = [[[KeywordViewController alloc] initWithStyle:UITableViewStyleGrouped] autorelease];
37        theC.delegate = aDelegate;
38        theC.keywordsArray = [NSMutableArray arrayWithCapacity:20];
39        theC.uiArray = [NSMutableArray arrayWithCapacity:20];
40        if (preload) {
41                [theC getValidKeywords:TRUE];
42                [theC getKeywords];
43        }
44        [theC setDidPreload:preload];
45        theC.navigationItem.rightBarButtonItem = [theC editButtonItem];
46        return theC;   
47}
48
49- (void)setDidPreload:(BOOL)preload {
50        didPreload = preload;
51}
52
53#pragma mark ------ Standard View Controller Methods
54
55- (void)viewDidLoad {
56    [super viewDidLoad];
57        keywordTableHeight = kKRowHeight;
58        self.title = @"Keywords";
59        // Don't get the data if we preloaded
60        if (didPreload) {
61                didPreload = NO;
62        } else {
63                [self getValidKeywords:TRUE];
64                [self getKeywords];
65        }
66}
67
68- (void)viewWillAppear:(BOOL)animated {
69        [super viewWillAppear:animated];
70}
71
72- (void)dealloc {
73        [keywordTypesNames release];
74        [keywordTypes release];
75    [super dealloc];
76}
77
78#pragma mark ------ TableView Delegate and DataSource Methods
79
80- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
81    return 1;
82}
83
84- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
85        return nil;
86}
87
88- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
89    return [uiArray count];
90}
91
92
93- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
94        // Keyword entry in uiArray:
95        //  {id: 12, field: "pa", value: "my postal address",
96        //              secondaryKeywords: [ {id: 15, field: "a1",
97        //              value: "my street"} ]}
98       
99    static NSString *CellIdentifier = @"KeywordCellIdentifier";
100   
101    KeywordCell *cell = (KeywordCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
102    if (cell == nil) {
103                cell = [[[KeywordCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:CellIdentifier] autorelease];
104                cell.editingAccessoryType = UITableViewCellAccessoryNone;
105                cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
106    }
107        NSDictionary *uiItem = [[uiArray objectAtIndex:indexPath.row] retain];
108#ifdef DEBUG
109        NSLog(@"UI ITEM IS: %@", uiItem);
110#endif
111        cell.labelPrimaryType.text = [uiItem objectForKey:@"primaryLongName"];
112        if ([[uiItem objectForKey:@"secondaryString"] isEqualToString:@""]) {
113                // No secondaries, put the primary value in the larger secondary field
114                cell.labelPrimaryValue.text = @"";
115                cell.labelSecondaryText.text = [uiItem objectForKey:@"value"];
116        } else {
117                cell.labelPrimaryValue.text = [uiItem objectForKey:@"value"];
118                cell.labelSecondaryText.text = [uiItem objectForKey:@"secondaryString"];
119        }
120        [uiItem release];
121    return cell;
122}
123
124- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
125        [tableView deselectRowAtIndexPath:indexPath animated:NO];
126        KeywordEditController *editC = [KeywordEditController controllerForKeyword:[uiArray objectAtIndex:indexPath.row]
127                                                                                                                                          delegate:self];
128        editC.delegate = self;
129        [self.navigationController pushViewController:editC animated:YES];
130}
131
132- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
133   
134        if (editingStyle == UITableViewCellEditingStyleDelete) {
135                if (tableView.editing) {
136                        // delete immediately, do not cache deletion because we can't tell a single row swipe from multiple deletes
137                        [self deleteKeywords:[uiArray objectAtIndex:indexPath.row]];
138                }
139                [uiArray removeObjectAtIndex:indexPath.row];
140                [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
141        }
142}
143
144- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
145        // Disable swipe-to-delete: don't allow row edit if table not in edit mode
146        return (tableView.editing);
147}
148
149- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView
150                   editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath {
151        return UITableViewCellEditingStyleDelete;
152}
153
154- (void)setEditing:(BOOL)editing animated:(BOOL)animated {
155        [super setEditing:editing animated:animated];
156        if (editing) {
157                self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAdd
158                                                                                                                                                                                           target:self
159                                                                                                                                                                                           action:@selector(addRecord)] autorelease];
160        } else {
161                self.navigationItem.leftBarButtonItem = nil;
162        }
163}
164
165- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
166        // Primary keywords don't have an order
167    return NO;
168}
169
170- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
171        CGFloat rowSize = 30;   // title + borders
172        CGSize constrainedSize = CGSizeMake([UIScreen mainScreen].bounds.size.width - 50, 400);
173        NSDictionary *uiItem = [[uiArray objectAtIndex:indexPath.row] retain];
174        NSString *primaryValue = [uiItem objectForKey:@"value"];
175        rowSize += [primaryValue sizeWithFont:[UIFont systemFontOfSize:12]
176                                                   constrainedToSize:constrainedSize
177                                                        lineBreakMode:UILineBreakModeWordWrap].height;
178        NSString *secondaryString = [uiItem objectForKey:@"secondaryString"];
179        rowSize += [secondaryString sizeWithFont:[UIFont systemFontOfSize:12]
180                                                                          constrainedToSize:constrainedSize
181                                                                                  lineBreakMode:UILineBreakModeWordWrap].height;
182        [uiItem release];
183        return rowSize;
184}
185
186#pragma mark ------ KeywordEditDelegate Methods
187
188- (void)dataDidChangeInController:(UIViewController *)controller {
189        [self getKeywords];
190}
191
192- (NSString *)domain {
193        return ([self.delegate domain]);
194}
195
196- (NSString *)longNameForKeyword:(NSString *)shortName {
197        // Try to get the mapped keyword type. If it fails, use the incoming string
198        if (shortName == nil) return nil;
199        NSString *longName = [keywordTypesNames objectForKey:shortName];
200        if (longName) {
201                return longName;
202        } else {
203                return shortName;
204        }
205}
206
207- (NSArray *)typesForKeyword:(NSString *)shortName {
208        if (shortName == nil) {
209                // return primary keyword types
210                NSArray *primaryTypes = [keywordTypes allKeys];
211                return primaryTypes;
212        }
213        NSArray *secondaryTypes = [keywordTypes objectForKey:shortName];
214        return secondaryTypes;
215}
216
217#pragma mark ------ UI Methods and Json Delegates
218
219- (void)addRecord {
220        KeywordEditController *editC = [KeywordEditController controllerForKeyword:nil delegate:self];
221        [self.navigationController pushViewController:editC animated:YES];
222}
223
224- (NSDictionary *)selectRecordInSetUsingId:(NSString *)anId {
225        // selects the correct full record in the set from an id
226        for (NSDictionary *theRec in keywordsArray) {
227                if ([[theRec valueForKey:@"id"] integerValue] == [anId integerValue]) {
228                        return theRec;
229                }
230        }
231        return nil;
232}
233
234
235- (void)updateUITableWithJson:(NSDictionary *)parsedJson {
236#ifdef DEBUG
237        NSLog(@"%@", [parsedJson descriptionInStringsFileFormat]);
238#endif
239       
240        [self.keywordsArray removeAllObjects];
241        [self.uiArray removeAllObjects];
242        if ([[parsedJson valueForKey:@"success"] integerValue] == 1) {
243                [self.keywordsArray setArray:(NSArray *)[parsedJson valueForKey:@"keywordList"]];
244                for (NSDictionary *aRec in self.keywordsArray) {
245                        [self.uiArray addObject:[self uiItemFromJsonItem:aRec]];
246                }
247                [self.delegate dataDidChangeInController:self];
248                [self.tableView reloadData];
249        } else {
250                [self.tableView reloadData];
251                [Keyword throwJsonErrorAlert:parsedJson];
252        }
253       
254}
255
256- (NSMutableDictionary *)uiItemFromJsonItem:(NSDictionary *)jsonItem {
257        // Method that creates a dictionary to display in a cell row
258        // Sample jsonItem:
259                //      {id: 12,
260                //      field: "pa",
261                //      value: "my postal address",
262                //      secondaryKeywords: [ {id: 15, field: "a1", value: "my street"}]}
263       
264        NSMutableDictionary *uiItem;
265        if (!jsonItem) {
266                return NULL;
267        }
268        uiItem = [NSMutableDictionary dictionaryWithDictionary:jsonItem];
269       
270        // set field string
271        NSString *primaryLongName;
272        primaryLongName = [self longNameForKeyword:[jsonItem objectForKey:@"field"]];
273        [uiItem setObject:primaryLongName forKey:@"primaryLongName"];
274
275        // set value if nonexistent
276        if (![uiItem objectForKey:@"value"])
277                [uiItem setObject:@"" forKey:@"value"];
278
279        // Generate the basic display string
280        NSInteger i=0;
281        NSMutableString *theSecText = [NSMutableString stringWithCapacity:300];
282        NSDictionary *theSec;
283        for (theSec in [uiItem objectForKey:@"secondaryKeywords"]) {
284                if (i == 0) {
285                        [theSecText appendFormat:@"%@: %@", [self longNameForKeyword:[theSec objectForKey:@"field"]], [theSec objectForKey:@"value"]];
286                } else {
287                        [theSecText appendFormat:@"\n%@: %@", [self longNameForKeyword:[theSec objectForKey:@"field"]], [theSec objectForKey:@"value"]];
288                }
289                i++;
290        }
291        [uiItem setObject:theSecText forKey:@"secondaryString"];
292       
293        return uiItem;
294}
295
296- (void)fillKeywordNamesDict:(NSDictionary *)parsedJson {
297        // We'll both get the mappings and the keyword structures here
298        // Start by getting the short->long name mapping
299        if (keywordTypesNames)
300                [keywordTypesNames release];
301        if (!parsedJson) {
302                // We're loading the data statically (not from the network)
303                // Note: you must localize the resource if loading the data statically
304                keywordTypesNames = [[NSMutableDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle]
305                                                                                                                                                                pathForResource:@"KeywordTypesLongNames"
306                                                                                                                                                                ofType:@"plist"]] retain];
307        } else {
308                keywordTypesNames = [[NSMutableDictionary dictionaryWithCapacity:20] retain];
309                if ([[parsedJson valueForKey:@"success"] integerValue] == 1) {
310                        NSArray *keyTypeList = (NSArray *)[parsedJson valueForKey:@"validKeywordList"];
311                        NSDictionary *aKeyType;
312                        for (aKeyType in keyTypeList) {
313                                [keywordTypesNames setObject:(NSString *)[aKeyType objectForKey:@"displayText"]
314                                 forKey:(NSString *)[aKeyType objectForKey:@"shortForm"]];
315                        }
316                } else {
317                        [Keyword throwJsonErrorAlert:parsedJson];
318                }
319        }
320       
321        // Now grab the keyword structure, which is loaded from a local plist
322        if (keywordTypes)
323                [keywordTypes release];
324        keywordTypes = [[NSMutableDictionary dictionaryWithContentsOfFile:[[NSBundle mainBundle]
325                                                                                                                                           pathForResource:@"KeywordTypes"
326                                                                                                                                           ofType:@"plist"]] retain];
327}
328
329
330#pragma mark ------ Data management
331
332- (void)getKeywords {
333        //      inputKeyword = {
334        //              domainName: "cartman.tel",
335        //      };
336        //      successResult = {
337        //      success: true,
338        //      actionMessages: ["keywords retrieved",
339        //                                       "2nd message here"],
340        //             
341        //              keywordList = [ {id: 12, field: "pa", value: "my postal address",
342        //              secondaryKeywords: [ {id: 15, field: "a1",
343        //              value: "my street"} ]},
344        //              {id: 13, field: "fn", value: "cart",
345        //              secondaryKewords: []} ]
346        //      };
347       
348        Keyword *conn = [[[Keyword alloc] init] autorelease];
349        [conn setTheDelegate:self];
350        [conn setActionSel:@selector(updateUITableWithJson:)];
351        [conn setConnectionUrl:[conn urlFromAction:@"getkeywords"]];
352       
353        NSMutableDictionary *requestData = [[NSMutableDictionary dictionaryWithCapacity:2] retain];
354        [requestData setObject:[self.delegate domain] forKey:@"domain"];
355       
356        [conn setPayload:requestData];
357        [conn performLookup:TRUE];
358        [requestData release];
359}
360
361- (void)deleteKeywords:(NSDictionary *)aRec {
362        //      keywords = {
363        //      domain: "cartman.tel",
364        //      idList: [23, 2, 22]
365        //      };
366        //     
367        //      successResult = {
368        //      success: true,
369        //      actionMessages: ["keywords deleted"
370        //                                       "2nd message here"]
371        //      };
372       
373        if (!aRec)
374                return;
375        NSArray *idsToDelete;
376        idsToDelete = [NSMutableArray arrayWithObject:[aRec objectForKey:@"id"]];
377        if ([idsToDelete count] == 0)   // Nothing to delete
378                return;
379        [idsToDelete retain];
380        Keyword *conn = [[[Keyword alloc] init] autorelease];
381        [conn setTheDelegate:[MyTelConnect sharedInstance]];
382        [conn setActionSel:@selector(doNothing:)];
383        [conn setConnectionUrl:[conn urlFromAction:@"deletekeywords"]];
384       
385        NSMutableDictionary *requestData = [[NSMutableDictionary dictionaryWithCapacity:2] retain];
386        [requestData setObject:[self.delegate domain] forKey:@"domain"];
387        [requestData setObject:idsToDelete forKey:@"idList"];
388       
389        [conn setPayload:requestData];
390        NSDictionary *parsedJson = [conn performLookup:FALSE];
391        [requestData release];
392        [idsToDelete release];
393        if ([[parsedJson valueForKey:@"success"] integerValue] == 0) {
394                [Keyword throwJsonErrorAlert:parsedJson];
395        }
396        [self getKeywords];
397}
398
399- (void)getValidKeywords:(BOOL)fromNetwork {
400        //      successResult = {
401        //      success: true,
402        //      actionMessages: ["valid keywords retrieved",
403        //                                       "2nd message here"],
404        //              validKeywordList = [ {shortForm: "pa", displayText: "Postal address",
405        //              canHaveSecondaries: true, canBeSecondary: false},
406        //              {shortForm: "a1", displayText: "Address line 1",
407        //              canHaveSecondaries: false, canBeSecondary: true}
408        //              ]
409        //             
410        //      };
411       
412        if (fromNetwork) {
413                Keyword *conn = [[[Keyword alloc] init] autorelease];
414                [conn setTheDelegate:[MyTelConnect sharedInstance]];
415                [conn setActionSel:@selector(doNothing:)];
416                [conn setConnectionUrl:[conn urlFromAction:@"getvalidkeywords"]];
417               
418                NSMutableDictionary *requestData = [[NSMutableDictionary dictionaryWithCapacity:1] retain];
419                [requestData setObject:[self.delegate domain] forKey:@"domain"];
420               
421                [conn setPayload:requestData];
422                NSDictionary *parsedJson = [conn performLookup:FALSE];
423                [self fillKeywordNamesDict:parsedJson];
424                [requestData release];
425        } else {
426                [self fillKeywordNamesDict:nil];
427        }
428}
429
430
431@end
432
Note: See TracBrowser for help on using the browser.
Telnic
Search This Site
Partners
Neustar
ICANN
Main site | WHOIS | Sell .tel | FAQ | Archived Site | About Telnic | Contact Us