Today's Menu  Portugal
journal and plan nutrition
Y3WebView.m
Go to the documentation of this file.
1 //
2 // Y3WebView.m
3 // TodaysMenu
4 //
5 // Created by Don Zeek on 5/17/18.
6 // Copyright © 2018 net.dzeek.y2015.ios.portfolio. All rights reserved.
7 //
27 #import "Y3WebView.h"
28 #import "U4WebControlsView.h"
30 #import <JavaScriptCore/JavaScriptCore.h>
32 
33 
34 @interface WKWebView () <WKScriptMessageHandler>
35 @end
36 
37 @implementation Y3WebViewResponder {NSString *selectedText;
38  id<Y3WebViewDelegate> y3rDelegate;
39 }
40 
41 - (instancetype)initWithFrame:(CGRect)frame
42  configuration:(WKWebViewConfiguration *)configuration
43  andControllerDelegate:(id<Y3WebViewDelegate>)delegate
44 {
45  self = [super initWithFrame:frame configuration:configuration];
46  if (self) {
48 
49  if (configuration.showConsole) {
50  WKUserContentController *userCC = configuration.userContentController;
51  [userCC addScriptMessageHandler:self name:@"log"];
52 
53  [userCC addScriptMessageHandler:self name:@"logging"];
54  [userCC addScriptMessageHandler:self name:@"newSelectionDetected"] ;
55 
56  [self showConsole];
57  }
58  }
59  return self;
60 }
61 
62 - (BOOL) becomeFirstResponder
63 {
64  NSLog(@"Y3WebView.becomeFirstResponder");
65  [y3rDelegate becomeResponder:YES];
66  BOOL ret = [super becomeFirstResponder];
67  return ret;
68 }
69 - (BOOL) resignFirstResponder
70 {
71  NSLog(@"Y3WebView.resignFirstResponder");
72  [y3rDelegate becomeResponder:NO];
73  BOOL ret = [super resignFirstResponder];
74  return ret;
75 }
76 - (void)copy:(id)sender {
77  NSLog(@"Y3WebView.copyClicked: start:sender class: %@", NSStringFromClass([sender class]));
78 
80 }
81 
82 - (void (^)(id, NSError *error)) provideQueryCopyBlock:(MenuItemSegment) itemSegment
83 {
84  void (^queryCopyBlock)(id, NSError *error) = ^void(id jsReturn, NSError *error)
85  {
86  if (nil == error) {
87 
88  // [self->y3rDelegate jsReturn:jsReturn];
89  switch (itemSegment) {
90  case ReturnBasic:
91  [self->y3rDelegate jsReturnIndication:jsReturn];
92  NSLog(@"Y3WebView.provideQueryCopyBlock: ReturnBasic: %@", jsReturn);
93  break;
94  case ReturnTitle:
95  [self->y3rDelegate jsTitleReturn:jsReturn];
96  NSLog(@"Y3WebView.provideQueryCopyBlock: ReturnTitle: %@", jsReturn);
97  break;
98  case ReturnIngredients:
99  [self->y3rDelegate jsIngredientsReturn:jsReturn];
100  NSLog(@"Y3WebView.provideQueryCopyBlock: ReturnIngredients: %@", jsReturn);
101  break;
102  case ReturnInstructions:
103  [self->y3rDelegate jsInstructionReturn:jsReturn];
104  NSLog(@"Y3WebView.provideQueryCopyBlock: ReturnInstructions: %@", jsReturn);
105  break;
106  default:
107  NSLog(@"Y3WebView.provideQueryCopyBlock: default?: ret: %@", jsReturn);
108  break;
109  }
110  [self->y3rDelegate setControlbarColor:[UIColor greenColor]];
111  } else {
112  NSLog(@"Y3WebView.provideQueryCopyBlock: completion: ERROR: %@", error);
113  [self->y3rDelegate setControlbarColor:[UIColor redColor]];
114  }
115  };
116  return queryCopyBlock;
117 }
118 
119 - (void) exerciseJavascriptBasic: (NSString *)js
120 {
121  void (^queryCopyBlock)(id, NSError *error) = [self provideQueryCopyBlock:ReturnBasic];
122  [self evaluateJavaScript:js completionHandler:queryCopyBlock];
123 }
124 - (void) exerciseJavascriptSendSelection
125 {
126  NSBundle *mb = [NSBundle mainBundle];
127  NSString *jsPathStr = [mb pathForResource:@"detectSelection"
128  ofType:@"js"];
129  NSString* content = [NSString stringWithContentsOfFile:jsPathStr
130  encoding:NSUTF8StringEncoding
131  error:NULL];
132 
133  [self exerciseJavascriptBasic:content];
134 }
135 - (void) exerciseJavascriptScanForRecipe
136 {
137  NSBundle *mb = [NSBundle mainBundle];
138  NSString *jsPathStr = [mb pathForResource:@"scanForRecipe"
139  ofType:@"js"
140  inDirectory:@"webviewJS"];
141  NSString* content = [NSString stringWithContentsOfFile:jsPathStr
142  encoding:NSUTF8StringEncoding
143  error:NULL];
144  NSLog(@"Y3WebView.exerciseJavascriptScanForRecipe: content: %@", content);
145  void (^queryTitleCopyBlock)(id, NSError *error) = [self provideQueryCopyBlock:ReturnTitle];
146  [self evaluateJavaScript:content completionHandler:queryTitleCopyBlock];
147 
148 /*
149  void (^queryIngredientsCopyBlock)(id, NSError *error) = [self provideQueryCopyBlock:ReturnIngredients];
150  [self evaluateJavaScript:content completionHandler:queryIngredientsCopyBlock];
151 
152  void (^queryInstructionCopyBlock)(id, NSError *error) = [self provideQueryCopyBlock:ReturnInstructions];
153  [self evaluateJavaScript:content completionHandler:queryInstructionCopyBlock];
154  */
155 }
156 - (void) exerciseJavascriptScanForTitle
157 {
158  NSBundle *mb = [NSBundle mainBundle];
159  NSString *jsPathStr = [mb pathForResource:@"scanForTitle"
160  ofType:@"js"
161  inDirectory:@"webviewJS"];
162  NSString* content = [NSString stringWithContentsOfFile:jsPathStr
163  encoding:NSUTF8StringEncoding
164  error:NULL];
165  NSLog(@"Y3WebView.exerciseJavascriptScanForTitle: content: %@", content);
166  void (^queryTitleCopyBlock)(id, NSError *error) = [self provideQueryCopyBlock:ReturnTitle];
167  [self evaluateJavaScript:content completionHandler:queryTitleCopyBlock];
168 }
169 
170 - (void) exerciseJavascriptScanForIngredients
171 {
172  NSBundle *mb = [NSBundle mainBundle];
173  NSError *error;
174  NSString *jsPathStr = [mb pathForResource:@"scanForIngredients"
175  ofType:@"js"
176  inDirectory:@"webviewJS"];
177  NSString* content = [NSString stringWithContentsOfFile:jsPathStr
178  encoding:NSUTF8StringEncoding
179  error:&error];
180  if (nil == error) {
181  NSLog(@"Y3WebView.exerciseJavascriptScanForIngredients: content: %@", content);
182  void (^queryIngredientsCopyBlock)(id, NSError *error) = [self provideQueryCopyBlock:ReturnIngredients];
183  [self evaluateJavaScript:content completionHandler:queryIngredientsCopyBlock];
184  } else {
185  NSLog(@"Y3WebView.exerciseJavascriptScanForIngredients: error: %@", error);
186  }
187 }
188 - (void) exerciseJavascriptScanForInstruction
189 {
190  NSBundle *mb = [NSBundle mainBundle];
191  NSString *jsPathStr = [mb pathForResource:@"scanForInstruction"
192  ofType:@"js"
193  inDirectory:@"webviewJS"];
194  NSString* content = [NSString stringWithContentsOfFile:jsPathStr
195  encoding:NSUTF8StringEncoding
196  error:NULL];
197  void (^queryInstructionCopyBlock)(id, NSError *error) = [self provideQueryCopyBlock:ReturnInstructions];
198  [self evaluateJavaScript:content completionHandler:queryInstructionCopyBlock];
199 }
200 
201 - (void)showConsole {
202  //rewrite the method of console.log
203  NSString *jsCode = @"console.log = (function(oriLogFunc){\
204  return function(str)\
205  {\
206  window.webkit.messageHandlers.log.postMessage(str);\
207  oriLogFunc.call(console,str);\
208  }\
209  })(console.log);";
210  //injected the method when H5 starts to create the DOM tree
211  [self.configuration.userContentController addUserScript:[[WKUserScript alloc] initWithSource:jsCode injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES]];
212 }
213 - (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
214  NSLog(@"OK> %@",message.body);
215 }
216 
217 
218 @end
219 @implementation Y3WebView {
220  id<Y3WebViewDelegate> y3Delegate;
221  NSURL *fileURL;
222 }
226 - (instancetype) initWithFrame:(CGRect)frame andDelegate:(id<Y3WebViewDelegate>)delegate
227 {
228  self = [super initWithFrame:frame];
229  if (self) {
230  CGRect totalFrame = self.frame;
231 
232  CGRect controlsViewFrame = CGRectMake(10, 0, totalFrame.size.width - 20, 68.0);
233  _webControls = [[U4WebControlsView alloc] initWithFrame:controlsViewFrame andDelegate:self];
234  [_webControls appear:controlsViewFrame];
235  [_webControls setBackgroundColor:[UIColor lightGrayColor]];
236 
237  float controlsHeight = 70.0;
238  CGRect webViewFrame = CGRectMake(totalFrame.size.width * 0.01,
239  controlsHeight,
240  totalFrame.size.width * 0.98,
241  totalFrame.size.height - controlsHeight);
242 
243  WKPreferences *prefers = [[WKPreferences alloc] init];
244  [prefers setJavaScriptEnabled:YES];
245  [prefers setJavaScriptCanOpenWindowsAutomatically:YES];
246 
247 
248 //let contentController = WKUserContentController()
249 //let scriptSource = "document.body.style.backgroundColor = `red`;"
250 //let script = WKUserScript(source: scriptSource, injectionTime: .atDocumentEnd, forMainFrameOnly: true)
251 //contentController.addUserScript(script)
252 //
253 //let config = WKWebViewConfiguration()
254 //config.userContentController = contentController
255 //
256 //let webView = WKWebView(frame: .zero, configuration: config)
257 
258  // create message handlers named "logging" and "newSelectionDetected"
259  WKUserContentController *ucc = [[WKUserContentController alloc] init];
260 // [ucc addScriptMessageHandler:delegate name:@"logging"];
261 // [ucc addScriptMessageHandler:delegate name:@"newSelectionDetected"] ;
262 
263  // assign usercontentcontroller to configuration
264  WKWebViewConfiguration *configur = [[WKWebViewConfiguration alloc] init];
265  [configur setPreferences:prefers];
266  [configur setUserContentController:ucc];
267  configur.showConsole = YES;
268 
269  _webView = [[Y3WebViewResponder alloc] initWithFrame:webViewFrame configuration:configur andControllerDelegate:delegate];
270 
271  y3Delegate = delegate;
272  _webView.navigationDelegate = delegate;
273  _webView.UIDelegate = delegate;
274 
275 
276 // Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<Y3WebViewResponder 0x7f98bd002e00> valueForUndefinedKey:]: this class is not key value coding-compliant for the key documentView.'
277 // JSContext *ctx = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
278 // ctx[@"console"][@"log"] = ^(JSValue * msg) {
279 // NSLog(@"JavaScript %@ log message: %@", [JSContext currentContext], msg);
280 // };
281 
282 
283 
284  // UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
285  // [webView addGestureRecognizer:tapRecognizer];
286 
287  [self addSubview:_webControls];
288  [self addSubview:_webView];
289  }
290  return self;
291 }
292 - (void) updateWebControls
293 {
294  [_webControls update:_webView];
295 }
296 
297 - (void) captureClicked:(id)sender
298 {
299  NSLog(@"captureClicked");
300 }
301 
302 - (void) handleTapGesture:(UIGestureRecognizer *)gesture
303 {
304  NSLog(@"Y3WebView.handleTapGesture: tap recognized");
305 
306  CGPoint tapLocation = [gesture locationInView:_webView];
307 
308  CGRect targetRect = CGRectMake(tapLocation.x, tapLocation.y, 0.0f, 0.0f);
309  [[UIMenuController sharedMenuController] setTargetRect:targetRect inView:_webView];
310 
311  UIMenuItem *menuItem = [[UIMenuItem alloc] initWithTitle:@"Capture" action:@selector(captureClicked:)];
312  [[UIMenuController sharedMenuController] setMenuItems:@[menuItem]];
313 
314  [[UIMenuController sharedMenuController] setMenuVisible:YES animated:YES];
315 }
316 
317 - (void) becomeResponder: (BOOL)flag {
318 
319  [_webControls focusAvailable:flag];
320 }
321 - (void) reformForKeyboard
322 {
323  NSLog(@"Y3WebView.reformForKeyboard: NO-OP");
324 //
325 // CGRect totalFrame = self.frame;
326 // CGFloat height;
327 // if (flag) {
328 // height = totalFrame.size.height * 0.38;
329 // } else {
330 // height = totalFrame.size.height * 0.88;
331 // }
332 //
333 // CGRect webViewFrame = CGRectMake(totalFrame.size.width * 0.01,
334 // totalFrame.size.height * 0.10,
335 // totalFrame.size.width * 0.98,
336 // height);
337 //
338 // [_webView setFrame:webViewFrame];
339 // [self setNeedsDisplay];
340 }
341 - (void) goBack
342 {
343  NSLog(@"Y3WebView.goBack");
344  [_webView goBack];
345 }
346 - (void) goForward
347 {
348  NSLog(@"Y3WebView.goForward");
349  [_webView goForward];
350 }
351 - (void) stirJavascript
352 {
353  NSLog(@"Y3WebView.stirJavascript");
354  [_webView exerciseJavascriptSendSelection];
355  }
356 - (void) loadRequest: (NSURLRequest *)requestURL
357 {
358  NSLog(@"Y3WebView.loadRequest");
359  [_webView loadRequest:requestURL];
360 }
361 - (void) goEditCopy
362 {
363  NSLog(@"Y3WebView.goEditCopy");
364  [y3Delegate fireSnippetScreen];
365 }
366 #pragma - mark
367 #pragma called from didFinishNavigation
368 - (void) scanPageForTitle
369 {
370  NSLog(@"Y3WebView.scanPageForTitle");
371  [_webView exerciseJavascriptScanForTitle];
372 }
373 - (void) scanPageForIngredients
374 {
375  NSLog(@"Y3WebView.scanPageForIngredients");
376  [_webView exerciseJavascriptScanForIngredients];
377 }
378 - (void) scanPageForInstruction
379 {
380  NSLog(@"Y3WebView.scanPageForInstruction");
381  [_webView exerciseJavascriptScanForInstruction];
382 }
383 #pragma mark - WKUIDelegate
384 
385 - (void)webView:(WKWebView *)webViewHere didFinishNavigation:(WKNavigation *)navigation
386 {
387  NSLog(@"Y3WebView.didFinishNavigation");
388  assert(NO);
389  [_webControls update: webViewHere];
390 }
391 
392 - (void)webView:(WKWebView *)webView
393 didCommitNavigation:(WKNavigation *)navigation
394 {
395  NSLog(@"Y3WebView.didCommitNavigation: active URL: %@", webView.URL.description);
396 }
397 
398 - (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(null_unspecified WKNavigation *)navigation
399 {
400  NSLog(@"Y3WebView.didStartProvisionalNavigation: active URL: %@", webView.URL.description);
401 }
402 
403 - (void)webView:(WKWebView *)webView
404  decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse
405  decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
406 
407  NSHTTPURLResponse *response = (NSHTTPURLResponse *)navigationResponse.response;
408  NSArray *cookies =[NSHTTPCookie cookiesWithResponseHeaderFields:[response allHeaderFields] forURL:response.URL];
409  for (NSHTTPCookie *cookie in cookies) {
410  [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie];
411  }
412 
413  decisionHandler(WKNavigationResponsePolicyAllow);
414  NSLog(@"Y3WebView.decidePolicyForNavigationResponse: ALLOW");
415 }
416 
417 
418 //Download manager
419 - (void)webView:(WKWebView *)webView
420  decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction
421  decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
422 
423  NSURLRequest *request = navigationAction.request;
424  fileURL = request.URL;
425 
426  // HCDownloadViewController *dlvc = [[HCDownloadViewController alloc] init];
427  // UINavigationController *vc = [[UINavigationController alloc] initWithRootViewController:dlvc];
428  // vc.transitioningDelegate = self;
429  // dlvc.delegate = self;
430 
431  NSLog(@"Y3WebView.decidePolicyForNavigationAction: ~~~~~~~~~~~~~~~~~~~~~~");
432  [self logNavigationAction:navigationAction];
433  if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {
434 
435  }
436 
437  if (decisionHandler) {
438  decisionHandler(WKNavigationActionPolicyAllow);
439  }
440 }
441 
442 - (void) logNavigationAction: (WKNavigationAction *)navigationAction
443 {
444  NSLog(@" request: %@", navigationAction.request);
445  NSLog(@" source frame: %@", navigationAction.sourceFrame);
446  NSLog(@" target frame: %@", navigationAction.targetFrame);
447  if (navigationAction.navigationType == WKNavigationTypeLinkActivated) {
448  NSLog(@" WKNavigationTypeLinkActivated");
449  }
450  if (navigationAction.navigationType == WKNavigationTypeFormSubmitted) {
451  NSLog(@" WKNavigationTypeFormSubmitted");
452  }
453  if (navigationAction.navigationType == WKNavigationTypeBackForward) {
454  NSLog(@" WKNavigationTypeBackForward");
455  }
456  if (navigationAction.navigationType == WKNavigationTypeReload) {
457  NSLog(@" WKNavigationTypeReload");
458  }
459  if (navigationAction.navigationType == WKNavigationTypeFormResubmitted) {
460  NSLog(@" WKNavigationTypeFormResubmitted");
461  }
462  if (navigationAction.navigationType == WKNavigationTypeOther) {
463  NSLog(@" WKNavigationTypeOther");
464  }
465 }
466 
467 /*
468 // Only override drawRect: if you perform custom drawing.
469 // An empty implementation adversely affects performance during animation.
470 - (void)drawRect:(CGRect)rect {
471  // Drawing code
472 }
473 */
474 
475 @end
WKWebView * webView
void exerciseJavascriptSendSelection()
Definition: Y3WebView.m:124
NSURL * fileURL
Definition: Y3WebView.m:219
MenuItem * menuItem
id< Y3WebViewDelegate > y3rDelegate
Definition: Y3WebView.m:37
id< U7ParamEditControlDelegate > delegate
void logNavigationAction:(WKNavigationAction *navigationAction)
Definition: Y3WebView.m:442
void exerciseJavascriptBasic:(NSString *js)
Definition: Y3WebView.m:119