Today's Menu  Portugal
journal and plan nutrition
Y3GmailViewController.m
Go to the documentation of this file.
1 //
2 // Y3GmailViewController.m
3 // TodaysMenu
4 //
5 // Created by Don Zeek on 4/13/18.
6 // Copyright © 2018 net.dzeek.y2015.ios.portfolio. All rights reserved.
7 //
8 
9 @import GoogleSignIn;
10 
12 #import "Z5DataController.h"
17 #import "Y3GmailViewHeader.h"
18 #import "Y3GmailViewFooter.h"
21 
22 
23 @interface Y3GmailViewController ()
24 
25 @end
26 
56 /*
57  * Convenience functions
58  */
59 @implementation Y3GmailViewController {
60 
62  NSMutableArray<NSString *> *rows; // an array of randomkeys
63 
64  NSDateFormatter *msgNearDateFormatter;
65  NSDateFormatter *dspNearDateFormatter;
66 
67  UIButton *manualMailButton;
68  UIButton *addItemButton;
69 
73 
74  NSString *messageHtml;
76 
78 
79  NSDateFormatter *mDateFormatter;
80 
81  const NSString *HeaderIdentifier;
82 
83 }
84 
85 - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
86 {
87  self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
88  if (self) {
89  // Custom initialization
90  self.title = @"Messages";
91  self.tabBarItem.image = [UIImage imageNamed:@"mail19.png"];
92  nutritionJournalDataTitleKey = @"Nutrition Journal Information";
93  rows = [[NSMutableArray alloc] init];
94  _emailMessages = [[NSMutableArray alloc] init];
95  dspNearDateFormatter = [[NSDateFormatter alloc] init];
96  [dspNearDateFormatter setDateStyle:NSDateFormatterMediumStyle];
97  [dspNearDateFormatter setTimeStyle:NSDateFormatterShortStyle];
98 
99  mDateFormatter = [[NSDateFormatter alloc] init];
100  [mDateFormatter setTimeStyle:NSDateFormatterNoStyle];
101  [mDateFormatter setDateStyle:NSDateFormatterMediumStyle];
102 
103  HeaderIdentifier = @"messagesHeader";
104  }
105  return self;
106 }
107 
108 - (void)viewDidLoad {
109  [super viewDidLoad];
110  // Do any additional setup after loading the view, typically from a nib.
111  [[self view] setBackgroundColor:[UIColor colorWithHue:0.26
112  saturation:0.8
113  brightness:0.8
114  alpha:1.0]];
115  CGRect totalFrame = self.view.frame;
116 
117  UIImage *backgrdImage = [UIImage imageNamed:@"blueHydrangea.png"];
118  UIImageView *backgrd = [[UIImageView alloc] initWithImage:backgrdImage];
119  // float topSpace = navigationBarHeight + instructionPanelHeight;
120  float topSpace = 0.0; // TODO: tune page placement
121  CGRect backImageFrame = CGRectMake(0.0, topSpace, totalFrame.size.width, totalFrame.size.height - topSpace);
122  [backgrd setFrame:backImageFrame];
123  [self.view addSubview:backgrd];
124 
125  Z5LocalDataController *localData = [[Z5DataController sharedInstance] localDataController];
126  NSArray<EmailMessage *> *dbEmail = [localData retrieveAllEmailMessages];
127  NSInteger count = [dbEmail count];
128  NSLog(@"Y3GmailViewController.viewDidLoad: dbEmail count: %ld", (long)count);
129  // ==========================
130  CGRect nutritionMsgsTableFrame = CGRectMake(totalFrame.size.width * 0.54,
131  totalFrame.size.height * 0.83,
132  totalFrame.size.width * 0.42,
133  totalFrame.size.height * 0.07);
134 
135  _nutritionMsgsTable = [[Z7MessagesPanelTableView alloc] initWithFrame:nutritionMsgsTableFrame andComponents:nil inContainer:self];
136 
137 // gmailViewHeader = [[Y3GmailViewHeader alloc] initWithDelegate:self];
138 // CGRect gmailHeaderFrame = CGRectMake(0.0, 0.0, totalFrame.size.width, [gmailViewHeader heightRequirement]);
139 // [gmailViewHeader setFrame:gmailHeaderFrame];
140 // [gmailViewHeader setBackgroundColor:[UIColor colorWithHue:0.27 saturation:1.0 brightness:1.0 alpha:1.0]];
141 
142  [_nutritionMsgsTable setDataSource:self];
143  [_nutritionMsgsTable setDelegate:self];
144 
145  [_nutritionMsgsTable registerClass:[Y3GmailViewHeader class] forHeaderFooterViewReuseIdentifier:HeaderIdentifier];
146  [_nutritionMsgsTable measureForSectionHead:[Y3GmailViewHeader heightRequirement]];
147 // [_nutritionMsgsTable registerClass:[UITableViewHeaderFooterView class] forHeaderFooterViewReuseIdentifier:HeaderIdentifier];
148 
149  // TODO: modify to install head as section-head, instead of being table-head.
150  // [_nutritionMsgsTable setViewForHead:gmailViewHeader];
151 
152  gmailViewFooter = [[Y3GmailViewFooter alloc] initWithDelegate:self];
153  CGRect gmailFooterFrame = CGRectMake(0.0, 0.0, totalFrame.size.width, [gmailViewFooter heightRequirement]);
154  [gmailViewFooter setFrame:gmailFooterFrame];
155  [gmailViewFooter setBackgroundColor:[UIColor colorWithHue:0.3 saturation:1.0 brightness:1.0 alpha:1.0]];
156  [_nutritionMsgsTable setViewForTail:gmailViewFooter];
157 
158  [_emailMessages setArray:dbEmail];
159 
160  [self.view addSubview:_nutritionMsgsTable];
161 
162  [self reframeTable];
163 
164  Z5GoogleLoginController *loginControl = [[[Z5DataController sharedInstance] remoteDataController] loginController];
165  [loginControl addLoginListener:self];
166 }
167 - (void) addMailScanButton
168 {
169  CGRect totalFrame = self.view.frame;
170  CGRect manualMailButtonFrame = CGRectMake(totalFrame.size.width * 0.04,
171  totalFrame.size.height * 0.83,
172  totalFrame.size.width * 0.42,
173  totalFrame.size.height * 0.07);
174  manualMailButton = [[UIButton alloc] initWithFrame: manualMailButtonFrame];
175  [manualMailButton setTitle:@"scan msgs" forState:UIControlStateNormal];
176  [manualMailButton addTarget:self action:@selector(execMailSession) forControlEvents:UIControlEventTouchUpInside];
177  [self.view addSubview:manualMailButton];
178 }
179 -(void) viewDidAppear:(BOOL)animated
180 {
181  [[[Z5DataController sharedInstance] localDataController] saveContext];
182 
183  [gmailViewHeader appear:nutritionMessagesFrame];
184  [gmailViewFooter appear:nutritionMessagesFrame];
185 
186  NSInteger nMsgs = [_emailMessages count];
187  NSInteger nRows = [_nutritionMsgsTable numberOfRowsInSection:0];
188  if ((0 < nMsgs) && (nRows > 1)){
189  CGPoint newContentOffset = CGPointMake(0, [_nutritionMsgsTable contentSize].height - _nutritionMsgsTable.bounds.size.height);
190  [_nutritionMsgsTable setContentOffset:newContentOffset animated:YES];
191  }
192 }
193 
194 #pragma mark - Z5GoogleLoginListener
195 - (void) signedIn: (GIDGoogleUser *)user
196 {
197  NSLog(@"GmailViewController.signedIn: %@", user.profile.name);
198 
199  // [gmailViewHeader signedIn:user];
200  [gmailViewFooter signedIn:user];
201  [self placeLogoutButton];
202 
203  [self updateUI];
204 }
205 
206 - (void) signedOut:(GIDGoogleUser *)user
207 {
208  // self.service = nil;
209 }
210 
211 //- (void) logOutGoogle {
212 // NSLog(@"Y3GmailViewController.logOutGoogle");
213 //
214 // [[GIDSignIn sharedInstance] signOut];
215 //
216 // Z5GoogleLoginController *loginData = [[[Z5DataController sharedInstance] remoteDataController] loginController];
217 // [loginData revisitSignOut];
218 // if (nil!=_parentController) {
219 // [_parentController popPushController:self];
220 // }
221 //
222 // // [gmailData removeDataListener:self];
223 // [gmailViewHeader logOutGoogle];
224 //
225 // self.navigationItem.rightBarButtonItem = nil;
226 // self.navigationItem.rightBarButtonItem.enabled = NO;
227 //}
228 
229 - (void) placeLogoutButton
230 {
231  Z5GoogleLoginController *loginControl = [[[Z5DataController sharedInstance] remoteDataController] loginController];
232  UIBarButtonItem *anotherButton = [[UIBarButtonItem alloc] initWithTitle:@"Logout"
233  style:UIBarButtonItemStylePlain
234  target:loginControl
235  action:@selector(logOutGoogle)];
236  self.navigationItem.rightBarButtonItem = anotherButton;
237  self.navigationItem.rightBarButtonItem.enabled = YES;
238 }
239 
243 - (void) reframeTable
244 {
245  CGRect totalFrame = self.view.frame;
246  float messagesTableHeight = 0.0;
247  CGRect topNaviFrame = [[[self navigationController] navigationBar] frame];
248  float availableWindowTop = topNaviFrame.origin.y + topNaviFrame.size.height;
249 
250  messagesTableHeight = [_nutritionMsgsTable getViewHeightReqmt];
251  float maxHgt = totalFrame.size.height * 0.84;
252  NSLog(@"Y3GmailViewController.reframeTable: msgsTbHt: %3.2f mxHt: %3.2f", messagesTableHeight, maxHgt);
253  if (maxHgt < messagesTableHeight) {
254  messagesTableHeight = maxHgt;
255  }
256  nutritionMessagesFrame = CGRectMake(totalFrame.size.width * 0.04,
257  availableWindowTop + totalFrame.size.height * 0.02,
258  totalFrame.size.width * 0.92,
259  messagesTableHeight);
260  [_nutritionMsgsTable setFrame:nutritionMessagesFrame];
261 
262  [self.view setNeedsDisplay];
263  [[self nutritionMsgsTable] reloadData];
264  [self viewDidAppear:YES];
265 }
266 
267 
268 #pragma mark - button action
269 
272 - (void) execMailSession
273 {
274  // [manualMailButton removeFromSuperview];
275  [manualMailButton setBackgroundColor:[UIColor cyanColor]];
276  // [self.view addSubview:manualMailButton];
277 
278  Z5GmailDataController *mailControl = [[[Z5DataController sharedInstance] remoteDataController] emailController];
279 
280  mailUtility = [[M9MailServerNavigator alloc] init:self];
281  [mailControl fetchJournalHeaders:mailUtility];
282 
283  // recast after delay
284  [self performSelector:@selector(fetchMailAfterDelay) withObject:nil afterDelay:3.2];
285 }
286 
287 - (void) fetchMailAfterDelay
288 {
289  Z5LocalDataController *localData = [[Z5DataController sharedInstance] localDataController];
290  NSArray<EmailMessage *> *dbEmail = [localData retrieveAllEmailMessages];
291 
292  NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date" ascending:NO];
293  [_emailMessages setArray:[dbEmail sortedArrayUsingDescriptors:@[sortDescriptor]]];
294  [self reframeTable];
295 }
296 
297 -(void) fireAccountEntry
298 {
299  NSLog(@"NutritionRoot.fireAccountEntry -- NO-OP");
300 /*
301  Y3AccountsViewController *vc2 = [[Y3AccountsViewController alloc] init];
302  [[self navigationController] pushViewController:vc2 animated:YES];
303  */
304 }
305 
306 
307 
308 #pragma mark - Y3GmailViewProtocol
309 
310 - (void) updateUI {
311  NSLog(@"Y3GmailViewController.updateUI");
312  [_nutritionMsgsTable reloadData];
313 
314  [manualMailButton removeFromSuperview];
315 
316  Z5GoogleLoginController *loginControl = [[[Z5DataController sharedInstance] remoteDataController] loginController];
317  if ([[loginControl signedIn] boolValue]) {
318  // [self addMailScanButton];
319  }
320 }
321 
322 - (void) updateHTML:(NSString *)body
323 {
324  NSLog(@"GmailView.updateHTML: %@", body);
325  messageHtml = [[NSString alloc] initWithString:body];
326 
327  // [webView loadHTMLString:body baseURL:nil];
328  [manualMailButton setHidden:NO];
329  [addItemButton setHidden:NO];
330 
331  // [webView setHidden:NO];
332 }
337 - (void) photoAvailable: (NSDictionary *) partDetail
338 {
339  NSString *filename = [partDetail objectForKey:@"part-filename"];
340  NSString *contentID = [partDetail objectForKey:@"part-contentID"];
341 
342  NSLog(@"GmailViewControl.photoAvailable: %@ content-ID: %@", filename, contentID);
343 
344  NSString *updatePhrase;
345  NSCharacterSet *carats = [NSCharacterSet characterSetWithCharactersInString:@"<>"];
346  NSArray<NSString *> *htmlBits = [messageHtml componentsSeparatedByCharactersInSet:carats];
347  for (NSString *bits in htmlBits) {
348  NSLog(@" photoAvail: bit: %@", bits);
349  if (filename && [bits containsString:filename]) {
350  updatePhrase = [[NSString alloc] initWithString:bits];
351  } else if (contentID && [bits containsString:contentID]) {
352  updatePhrase = [[NSString alloc] initWithString:bits];
353  }
354  }
355 
356  NSString *imageHtml = [[NSString alloc] initWithFormat:@"<center><img src=\"%@\" width=\"%5.3f\"></center>", filename, 0.8 * webViewEmailWidth];
357  NSString *revisedHtml = [messageHtml stringByReplacingOccurrencesOfString:updatePhrase withString:imageHtml];
358 
359  NSLog(@"GmailViewControl.photoAvailable: revisedHtml: %@", revisedHtml);
360  // NSURL *baseURL = [NSURL fileURLWithPath:@"file:///path/to/user/"];
361  // NSString *imageDirPath = [NSHomeDirectory() stringByAppendingPathComponent:@"images/"];
362  // NSURL *baseURL = [NSURL fileURLWithPath:imageDirPath];
363  // [self.webView loadHTMLString:revisedHtml baseURL:baseURL];
364 }
365 
366 #pragma mark - Z7MessagesTableDelegate
367 - (void) messageSwiped:(NSInteger) nRow
368 {
369  NSLog(@"Y3GmailViewController.messageSwiped: removing message: %ld", (long)nRow);
370 
371  EmailMessage *eMsg = [self.emailMessages objectAtIndex:nRow];
372  NSString *swipedMesgUID = [eMsg remoteUniqueIID];
373 
374  Z5LocalDataController *localData = [[Z5DataController sharedInstance] localDataController];
375  [localData deleteEmailMessageWithFileIdentification:swipedMesgUID];
376  [mailUtility initializeBlockedList];
377 
378  // display removal
379  [self.emailMessages removeObjectAtIndex:nRow];
380 }
381 
382 - (NSMutableArray<EmailMessage *> *) retrieveEmailMessages
383 {
384  return _emailMessages;
385 }
386 
387 #pragma mark - UITextFieldDelegate
388 // from http://stackoverflow.com/questions/10077155/how-to-add-done-button-to-the-keyboard
389 - (void)textFieldDidEndEditing:(UITextField *)textField {
390  NSLog(@"GmailViewControl.textFieldDidEndEditing");
391  [textField resignFirstResponder];
392 }
393 - (BOOL)textFieldShouldReturn:(UITextField *)textField {
394  [textField resignFirstResponder];
395  return YES;
396 }
397 //- (void)textFieldDidBeginEditing:(UITextField *)textField {
398 // [textField S
399 
400 
401 #pragma mark - WKUIDelegate
402 
403 - (void)webView:(WKWebView *)webView
404 didFinishNavigation:(WKNavigation *)navigation
405 {
406  NSLog(@"GmailViewControl.didFinishNavigation: width: %3.2f", webView.scrollView.contentSize.width);
407  webViewEmailWidth = webView.scrollView.contentSize.width;
408 }
409 
410 #pragma mark - GmailHeader delegate
411 
412 - (GIDProfileData *) getLoggedInProfile
413 {
414  Z5GoogleLoginController *loginData = [[[Z5DataController sharedInstance] remoteDataController] loginController];
415 
416  return loginData.signedInUser.profile;
417 }
418 
419 #pragma mark - GmailFooter delegate
420 
421 - (void) didTapScanServer
422 {
423  NSLog(@"GmailViewControl.didTapScanServer");
424  [self execMailSession];
425 // Z5GmailDataController *eMailCntrlr = [[[Z5DataController sharedInstance] remoteDataController] emailController];
426 // [eMailCntrlr fetchJournalHeaders:self];
427 
428  // goal: determine when download of messages complete, when
429  // all the tickes are anwered. when the headers are fetched and a 'nutrition information message' is found, its
430  // message and all the parts are downloaded.
431  // TODO: within the header receipt/message request loop, keep
432  // track of tickets
433  // TODO: within the message received, remove tickets from
434  // the 'outstanding tickets' array, when empty,
435  // call 'assessMessagesToDisplay'
436 
437  // in the mean-time, cheese ball
438  [self performSelector:@selector(reframeTable) withObject:nil afterDelay:3.0];
439 }
440 
441 - (void) didTapAddItem
442 {
443 NSLog(@"GmailViewControl.didTapAddItem");
444 
445 }
446 // TableViewDataSource
447 #pragma mark - Table view data source
448 
449 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
450 {
451  return 1;
452 }
453 
459 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
460 {
461  NSInteger ret = [self assessMessagesToDisplay];
462  return ret;
463 }
464 
465 - (NSInteger) assessMessagesToDisplay
466 {
467  NSInteger ret = [_emailMessages count];
468 
469  NSLog(@"Y3GmailViewController.assessMessagesToDisplay: ret: %ld", (long)ret);
470  return ret;
471 }
472 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
473 {
474  UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"todays-menu"];
475  // NSLog(@"GmailView.cellForRow: cell: %@", cell);
476  if (cell == nil) {
477  cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"todays-menu"];
478 
479  cell.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
480 
481 
482  CGRect contentRect = [cell.contentView frame];
483  CGRect fetchPublishButton1Frame = CGRectMake(contentRect.size.width - 86.0f, 5.0, 34.0f, contentRect.size.height - 10);
484  UIButton *pushMe = [[UIButton alloc] initWithFrame:fetchPublishButton1Frame];
485  [pushMe setTitle:@"GO" forState:UIControlStateApplication];
486  [pushMe setBackgroundColor:[UIColor greenColor]];
487 
488 
489  // [cell.contentView addSubview:pushMe];
490  [cell setHidden:NO];
491 
492 
493  }
494  // CGRect contentRect = [cell.contentView frame];
495  // CGRect maskRect = cell.maskView.bounds;
496  // NSLog(@"MessagesPanel.cellForRow/B: cell Hgt: %3.2f", cell.bounds.size.height);
497 
498  NSInteger nMesgs = [_emailMessages count];
499 
500  if (nMesgs > [indexPath row]) {
501  EmailMessage *mailMsg = [_emailMessages objectAtIndex:[indexPath row]];
502  NSString *caption = [mailMsg subject];
503  NSString *shortCaption = [caption stringByReplacingOccurrencesOfString:@"(Nutrition Information Journal)" withString:@"<>"];
504  NSString *shortCaption2 = [shortCaption stringByReplacingOccurrencesOfString:@"(nutrition information journal)" withString:@"<>"];
505 
506  cell.textLabel.text = shortCaption2;
507  UIColor *labelizeColor;
508  if (mailMsg.randomkey) {
509  labelizeColor = [UIColor hazySkyBlueColor];
510  // NSLog(@"Y3GmailViewController.cellForRowAtIndexPath: DB marker");
511  } else {
512  labelizeColor = [UIColor yellowColor];
513  // NSLog(@"Y3GmailViewController.cellForRowAtIndexPath: NO DB entry");
514  }
515  NSDate *cellDate = [mailMsg date];
516  NSString *messageDate = [mDateFormatter stringFromDate:cellDate];
517 
518  // [Z5DataController labelizeCell:cell withText:caption inColor:labelizeColor andDetail:messageDate];
519  [Z5DataController labelizeCell:cell withText:caption image:[mailMsg photo] inColor:labelizeColor andDetail:messageDate];
520 
521  } else {
522  [Z5DataController labelizeCell:cell withText:@"empty" image:nil inColor:[UIColor yellowColor] andDetail:@"scan server"];
523  }
524 
525  return cell;
526 
527 }
528 
529 - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
530 {
531  float ret = [Y3GmailViewHeader heightRequirement];
532  return ret;
533 }
534 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
535 {
536  Y3GmailViewHeader *sectionHeaderView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:HeaderIdentifier];
537  CGRect sectionHeaderViewFrame = CGRectMake(0.0, 0.0, 300.0, [Y3GmailViewHeader heightRequirement]);
538  [sectionHeaderView setMsgHeaderDelegate:self];
539  [sectionHeaderView appear:sectionHeaderViewFrame];
540  return sectionHeaderView;
541 
542 }
543 
544 #pragma mark - Table view delegate
545 
550 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
551  // int row = (int)[indexPath row];
552  Y3GmailViewHeader *theHeaderView = (Y3GmailViewHeader*)[tableView headerViewForSection:indexPath.section];
553  NSLog(@"%@",theHeaderView);
554  // [theHeaderView.lblSomething setAlpha:theHeaderView.lblSomething.alpha-0.1];
555 
556  EmailMessage *focusEmailMsg = [_emailMessages objectAtIndex:[indexPath row]];
557  NSString *messageUID = [focusEmailMsg remoteUniqueIID];
558 
559  NSLog(@"GmailViewController.didSelectRow: focusEmailUID: %@", messageUID);
560  NSLog(@"GmailViewController.didSelectRow: focusEmailMsg: %@", focusEmailMsg);
561 
562  // this does init and viewDidLoad
564  [vc2 setFocusEmailMsg:focusEmailMsg];
565  // this does viewWillAppear
566  // NSLog(@"GmailViewController.didSelectRow: vc.focusEmailMsg: %@", vc2.focusEmailMsg);
567  [[self navigationController] pushViewController:vc2 animated:YES];
568 
569 }
570 
571 - (void)didReceiveMemoryWarning {
572  [super didReceiveMemoryWarning];
573  // Dispose of any resources that can be recreated.
574 }
575 
576 /*
577 #pragma mark - Navigation
578 
579 // In a storyboard-based application, you will often want to do a little preparation before navigation
580 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
581  // Get the new view controller using [segue destinationViewController].
582  // Pass the selected object to the new view controller.
583 }
584 */
585 
586 @end
UIButton * manualMailButton
GIDProfileData * profile
Definition: GIDGoogleUser.h:24
void addLoginListener:(id< Z5GoogleLoginListener > ear)
NSString * messageHtml
WKWebView * webView
void viewDidAppear:(BOOL animated)
< Y3GmailViewProtocol, Y3GmailViewProtocol, Y3GmailFooterDelegate, Z5GoogleLoginListener, Y3GmailHeaderProtocol, Z7MessagesTableDelegate, GIDSignInUIDelegate, UITableViewDataSource, UITableViewDelegate, UITextFieldDelegate, WKNavigationDelegate, WKUIDelegate > Z7MessagesPanelTableView * nutritionMsgsTable
instancetype sharedInstance()
float webViewEmailWidth
void fetchJournalHeaders:(id< Z5GmailDataListener > listener)
Boolean deleteEmailMessageWithFileIdentification:(NSString *googlefileid)
import GoogleSignIn
void appear:(CGRect frame)
NSDateFormatter * mDateFormatter
const NSString * HeaderIdentifier
NSDateFormatter * msgNearDateFormatter
CGRect nutritionMessagesFrame
Y3GmailViewHeader * gmailViewHeader
void labelizeCell:withText:image:inColor:andDetail:(UITableViewCell *targCell, [withText] NSString *txt, [image] NSData *cellImage, [inColor] UIColor *color, [andDetail] NSString *detailTxt)
Singleton interface to both core and remote data sources.
NSString * name
NSDateFormatter * dspNearDateFormatter
M9MailServerNavigator * mailUtility
NSString * nutritionJournalDataTitleKey
UIButton * addItemButton
Fetch all marked emails into the local database, and display a list.
NSMutableArray< NSString * > * rows
Y3GmailViewFooter * gmailViewFooter