You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
4.6 KiB

  1. //
  2. // FLEXWebViewController.m
  3. // Flipboard
  4. //
  5. // Created by Ryan Olson on 6/10/14.
  6. // Copyright (c) 2014 Flipboard. All rights reserved.
  7. //
  8. #import "FLEXWebViewController.h"
  9. #import "FLEXUtility.h"
  10. #import <WebKit/WebKit.h>
  11. @interface FLEXWebViewController () <WKNavigationDelegate>
  12. @property (nonatomic) WKWebView *webView;
  13. @property (nonatomic) NSString *originalText;
  14. @end
  15. @implementation FLEXWebViewController
  16. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
  17. {
  18. self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  19. if (self) {
  20. WKWebViewConfiguration *configuration = [WKWebViewConfiguration new];
  21. if (@available(iOS 10.0, *)) {
  22. configuration.dataDetectorTypes = UIDataDetectorTypeLink;
  23. }
  24. self.webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:configuration];
  25. self.webView.navigationDelegate = self;
  26. }
  27. return self;
  28. }
  29. - (id)initWithText:(NSString *)text
  30. {
  31. self = [self initWithNibName:nil bundle:nil];
  32. if (self) {
  33. self.originalText = text;
  34. NSString *htmlString = [NSString stringWithFormat:@"<head><meta name='viewport' content='initial-scale=1.0'></head><body><pre>%@</pre></body>", [FLEXUtility stringByEscapingHTMLEntitiesInString:text]];
  35. [self.webView loadHTMLString:htmlString baseURL:nil];
  36. }
  37. return self;
  38. }
  39. - (id)initWithURL:(NSURL *)url
  40. {
  41. self = [self initWithNibName:nil bundle:nil];
  42. if (self) {
  43. NSURLRequest *request = [NSURLRequest requestWithURL:url];
  44. [self.webView loadRequest:request];
  45. }
  46. return self;
  47. }
  48. - (void)dealloc
  49. {
  50. // WKWebView's delegate is assigned so we need to clear it manually.
  51. if (_webView.navigationDelegate == self) {
  52. _webView.navigationDelegate = nil;
  53. }
  54. }
  55. - (void)viewDidLoad
  56. {
  57. [super viewDidLoad];
  58. [self.view addSubview:self.webView];
  59. self.webView.frame = self.view.bounds;
  60. self.webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
  61. if (self.originalText.length > 0) {
  62. self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Copy" style:UIBarButtonItemStylePlain target:self action:@selector(copyButtonTapped:)];
  63. }
  64. }
  65. - (void)copyButtonTapped:(id)sender
  66. {
  67. [UIPasteboard.generalPasteboard setString:self.originalText];
  68. }
  69. #pragma mark - WKWebView Delegate
  70. - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
  71. {
  72. WKNavigationActionPolicy policy = WKNavigationActionPolicyCancel;
  73. if (navigationAction.navigationType == WKNavigationTypeOther) {
  74. // Allow the initial load
  75. policy = WKNavigationActionPolicyAllow;
  76. } else {
  77. // For clicked links, push another web view controller onto the navigation stack so that hitting the back button works as expected.
  78. // Don't allow the current web view to handle the navigation.
  79. NSURLRequest *request = navigationAction.request;
  80. FLEXWebViewController *webVC = [[[self class] alloc] initWithURL:[request URL]];
  81. webVC.title = [[request URL] absoluteString];
  82. [self.navigationController pushViewController:webVC animated:YES];
  83. }
  84. decisionHandler(policy);
  85. }
  86. #pragma mark - Class Helpers
  87. + (BOOL)supportsPathExtension:(NSString *)extension
  88. {
  89. BOOL supported = NO;
  90. NSSet<NSString *> *supportedExtensions = [self webViewSupportedPathExtensions];
  91. if ([supportedExtensions containsObject:[extension lowercaseString]]) {
  92. supported = YES;
  93. }
  94. return supported;
  95. }
  96. + (NSSet<NSString *> *)webViewSupportedPathExtensions
  97. {
  98. static NSSet<NSString *> *pathExtensions = nil;
  99. static dispatch_once_t onceToken;
  100. dispatch_once(&onceToken, ^{
  101. // Note that this is not exhaustive, but all these extensions should work well in the web view.
  102. // See https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/CreatingContentforSafarioniPhone/CreatingContentforSafarioniPhone.html#//apple_ref/doc/uid/TP40006482-SW7
  103. pathExtensions = [NSSet<NSString *> setWithArray:@[@"jpg", @"jpeg", @"png", @"gif", @"pdf", @"svg", @"tiff", @"3gp", @"3gpp", @"3g2",
  104. @"3gp2", @"aiff", @"aif", @"aifc", @"cdda", @"amr", @"mp3", @"swa", @"mp4", @"mpeg",
  105. @"mpg", @"mp3", @"wav", @"bwf", @"m4a", @"m4b", @"m4p", @"mov", @"qt", @"mqv", @"m4v"]];
  106. });
  107. return pathExtensions;
  108. }
  109. @end