PageRenderTime 27ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/Three20UI/Sources/TTWebController.m

https://github.com/GetMoPix/three20
Objective C | 461 lines | 290 code | 105 blank | 66 comment | 35 complexity | f2581bd4001dae6c0757c4a4c24d56d9 MD5 | raw file
  1. //
  2. // Copyright 2009-2011 Facebook
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. #import "Three20UI/TTWebController.h"
  17. // UI
  18. #import "Three20UI/TTNavigator.h"
  19. #import "Three20UI/UIViewAdditions.h"
  20. #import "Three20UI/UIToolbarAdditions.h"
  21. // UINavigator
  22. #import "Three20UINavigator/TTGlobalNavigatorMetrics.h"
  23. #import "Three20UINavigator/TTURLMap.h"
  24. // UICommon
  25. #import "Three20UICommon/TTGlobalUICommon.h"
  26. // Style
  27. #import "Three20Style/TTGlobalStyle.h"
  28. #import "Three20Style/TTDefaultStyleSheet.h"
  29. #import "Three20Style/TTStyleSheet.h"
  30. // Network
  31. #import "Three20Network/TTGlobalNetwork.h"
  32. #import "Three20Network/TTURLCache.h"
  33. // Core
  34. #import "Three20Core/TTCorePreprocessorMacros.h"
  35. #import "Three20Core/TTGlobalCoreLocale.h"
  36. ///////////////////////////////////////////////////////////////////////////////////////////////////
  37. ///////////////////////////////////////////////////////////////////////////////////////////////////
  38. ///////////////////////////////////////////////////////////////////////////////////////////////////
  39. @implementation TTWebController
  40. @synthesize delegate = _delegate;
  41. @synthesize headerView = _headerView;
  42. ///////////////////////////////////////////////////////////////////////////////////////////////////
  43. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
  44. self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
  45. if (self) {
  46. self.hidesBottomBarWhenPushed = YES;
  47. }
  48. return self;
  49. }
  50. ///////////////////////////////////////////////////////////////////////////////////////////////////
  51. - (id)initWithNavigatorURL:(NSURL*)URL query:(NSDictionary*)query {
  52. self = [self initWithNibName:nil bundle:nil];
  53. if (self) {
  54. NSURLRequest* request = [query objectForKey:@"request"];
  55. if (nil != request) {
  56. [self openRequest:request];
  57. } else {
  58. [self openURL:URL];
  59. }
  60. }
  61. return self;
  62. }
  63. ///////////////////////////////////////////////////////////////////////////////////////////////////
  64. - (id)init {
  65. self = [self initWithNibName:nil bundle:nil];
  66. if (self) {
  67. }
  68. return self;
  69. }
  70. ///////////////////////////////////////////////////////////////////////////////////////////////////
  71. - (void)dealloc {
  72. TT_RELEASE_SAFELY(_loadingURL);
  73. TT_RELEASE_SAFELY(_headerView);
  74. TT_RELEASE_SAFELY(_actionSheet);
  75. [super dealloc];
  76. }
  77. ///////////////////////////////////////////////////////////////////////////////////////////////////
  78. ///////////////////////////////////////////////////////////////////////////////////////////////////
  79. #pragma mark -
  80. #pragma mark Private
  81. ///////////////////////////////////////////////////////////////////////////////////////////////////
  82. - (void)backAction {
  83. [_webView goBack];
  84. }
  85. ///////////////////////////////////////////////////////////////////////////////////////////////////
  86. - (void)forwardAction {
  87. [_webView goForward];
  88. }
  89. ///////////////////////////////////////////////////////////////////////////////////////////////////
  90. - (void)refreshAction {
  91. [_webView reload];
  92. }
  93. ///////////////////////////////////////////////////////////////////////////////////////////////////
  94. - (void)stopAction {
  95. [_webView stopLoading];
  96. }
  97. ///////////////////////////////////////////////////////////////////////////////////////////////////
  98. - (void)shareAction {
  99. if (nil != _actionSheet && [_actionSheet isVisible]) {
  100. //should only happen on the iPad
  101. assert(TTIsPad());
  102. [_actionSheet dismissWithClickedButtonIndex:-1 animated:YES];
  103. return;
  104. }
  105. if (nil == _actionSheet) {
  106. _actionSheet = [[UIActionSheet alloc] initWithTitle:nil
  107. delegate:self
  108. cancelButtonTitle:TTLocalizedString(@"Cancel", @"")
  109. destructiveButtonTitle:nil
  110. otherButtonTitles:TTLocalizedString(@"Open in Safari", @""),
  111. nil];
  112. if (TTIsPad()) {
  113. [_actionSheet showFromBarButtonItem:_actionButton animated:YES];
  114. } else {
  115. [_actionSheet showInView: self.view];
  116. }
  117. }
  118. }
  119. ///////////////////////////////////////////////////////////////////////////////////////////////////
  120. - (void)updateToolbarWithOrientation:(UIInterfaceOrientation)interfaceOrientation {
  121. _toolbar.height = TTToolbarHeight();
  122. _webView.height = self.view.height - _toolbar.height;
  123. _toolbar.top = self.view.height - _toolbar.height;
  124. }
  125. ///////////////////////////////////////////////////////////////////////////////////////////////////
  126. ///////////////////////////////////////////////////////////////////////////////////////////////////
  127. #pragma mark -
  128. #pragma mark UIViewController
  129. ///////////////////////////////////////////////////////////////////////////////////////////////////
  130. - (void)loadView {
  131. [super loadView];
  132. _webView = [[UIWebView alloc] initWithFrame:TTToolbarNavigationFrame()];
  133. _webView.delegate = self;
  134. _webView.autoresizingMask = UIViewAutoresizingFlexibleWidth
  135. | UIViewAutoresizingFlexibleHeight;
  136. _webView.scalesPageToFit = YES;
  137. [self.view addSubview:_webView];
  138. UIActivityIndicatorView* spinner =
  139. [[[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:
  140. UIActivityIndicatorViewStyleWhite] autorelease];
  141. [spinner startAnimating];
  142. _activityItem = [[UIBarButtonItem alloc] initWithCustomView:spinner];
  143. _backButton =
  144. [[UIBarButtonItem alloc] initWithImage:TTIMAGE(@"bundle://Three20.bundle/images/backIcon.png")
  145. style:UIBarButtonItemStylePlain
  146. target:self
  147. action:@selector(backAction)];
  148. _backButton.tag = 2;
  149. _backButton.enabled = NO;
  150. _forwardButton =
  151. [[UIBarButtonItem alloc] initWithImage:
  152. TTIMAGE(@"bundle://Three20.bundle/images/forwardIcon.png")
  153. style:UIBarButtonItemStylePlain
  154. target:self
  155. action:@selector(forwardAction)];
  156. _forwardButton.tag = 1;
  157. _forwardButton.enabled = NO;
  158. _refreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:
  159. UIBarButtonSystemItemRefresh target:self action:@selector(refreshAction)];
  160. _refreshButton.tag = 3;
  161. _stopButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:
  162. UIBarButtonSystemItemStop target:self action:@selector(stopAction)];
  163. _stopButton.tag = 3;
  164. _actionButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:
  165. UIBarButtonSystemItemAction target:self action:@selector(shareAction)];
  166. UIBarItem* space = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:
  167. UIBarButtonSystemItemFlexibleSpace target:nil action:nil] autorelease];
  168. _toolbar = [[UIToolbar alloc] initWithFrame:
  169. CGRectMake(0, self.view.height - TTToolbarHeight(),
  170. self.view.width, TTToolbarHeight())];
  171. _toolbar.autoresizingMask =
  172. UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth;
  173. _toolbar.tintColor = TTSTYLEVAR(toolbarTintColor);
  174. _toolbar.items = [NSArray arrayWithObjects:
  175. _backButton,
  176. space,
  177. _forwardButton,
  178. space,
  179. _refreshButton,
  180. space,
  181. _actionButton,
  182. nil];
  183. [self.view addSubview:_toolbar];
  184. }
  185. ///////////////////////////////////////////////////////////////////////////////////////////////////
  186. - (void)viewDidUnload {
  187. [super viewDidUnload];
  188. _delegate = nil;
  189. _webView.delegate = nil;
  190. TT_RELEASE_SAFELY(_webView);
  191. TT_RELEASE_SAFELY(_toolbar);
  192. TT_RELEASE_SAFELY(_backButton);
  193. TT_RELEASE_SAFELY(_forwardButton);
  194. TT_RELEASE_SAFELY(_refreshButton);
  195. TT_RELEASE_SAFELY(_stopButton);
  196. TT_RELEASE_SAFELY(_actionButton);
  197. TT_RELEASE_SAFELY(_activityItem);
  198. }
  199. ///////////////////////////////////////////////////////////////////////////////////////////////////
  200. - (void)viewWillAppear:(BOOL)animated {
  201. [super viewWillAppear:animated];
  202. [self updateToolbarWithOrientation:self.interfaceOrientation];
  203. }
  204. ///////////////////////////////////////////////////////////////////////////////////////////////////
  205. - (void)viewWillDisappear:(BOOL)animated {
  206. // If the browser launched the media player, it steals the key window and never gives it
  207. // back, so this is a way to try and fix that
  208. [self.view.window makeKeyWindow];
  209. [super viewWillDisappear:animated];
  210. }
  211. ///////////////////////////////////////////////////////////////////////////////////////////////////
  212. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
  213. return TTIsSupportedOrientation(interfaceOrientation);
  214. }
  215. ///////////////////////////////////////////////////////////////////////////////////////////////////
  216. - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation
  217. duration:(NSTimeInterval)duration {
  218. [super willAnimateRotationToInterfaceOrientation:toInterfaceOrientation duration:duration];
  219. [self updateToolbarWithOrientation:toInterfaceOrientation];
  220. }
  221. ///////////////////////////////////////////////////////////////////////////////////////////////////
  222. - (UIView*)rotatingFooterView {
  223. return _toolbar;
  224. }
  225. ///////////////////////////////////////////////////////////////////////////////////////////////////
  226. ///////////////////////////////////////////////////////////////////////////////////////////////////
  227. #pragma mark -
  228. #pragma mark UTViewController (TTCategory)
  229. ///////////////////////////////////////////////////////////////////////////////////////////////////
  230. - (BOOL)persistView:(NSMutableDictionary*)state {
  231. NSString* URL = self.URL.absoluteString;
  232. if (URL.length && ![URL isEqualToString:@"about:blank"]) {
  233. [state setObject:URL forKey:@"URL"];
  234. return YES;
  235. } else {
  236. return NO;
  237. }
  238. }
  239. ///////////////////////////////////////////////////////////////////////////////////////////////////
  240. - (void)restoreView:(NSDictionary*)state {
  241. NSString* URL = [state objectForKey:@"URL"];
  242. if (URL.length && ![URL isEqualToString:@"about:blank"]) {
  243. [self openURL:[NSURL URLWithString:URL]];
  244. }
  245. }
  246. ///////////////////////////////////////////////////////////////////////////////////////////////////
  247. ///////////////////////////////////////////////////////////////////////////////////////////////////
  248. #pragma mark -
  249. #pragma mark UIWebViewDelegate
  250. ///////////////////////////////////////////////////////////////////////////////////////////////////
  251. - (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request
  252. navigationType:(UIWebViewNavigationType)navigationType {
  253. if ([_delegate respondsToSelector:
  254. @selector(webController:webView:shouldStartLoadWithRequest:navigationType:)] &&
  255. ![_delegate webController:self webView:webView
  256. shouldStartLoadWithRequest:request navigationType:navigationType]) {
  257. return NO;
  258. }
  259. if ([[TTNavigator navigator].URLMap isAppURL:request.URL]) {
  260. [_loadingURL release];
  261. _loadingURL = [[NSURL URLWithString:@"about:blank"] retain];
  262. [[UIApplication sharedApplication] openURL:request.URL];
  263. return NO;
  264. }
  265. [_loadingURL release];
  266. _loadingURL = [request.URL retain];
  267. _backButton.enabled = [_webView canGoBack];
  268. _forwardButton.enabled = [_webView canGoForward];
  269. return YES;
  270. }
  271. ///////////////////////////////////////////////////////////////////////////////////////////////////
  272. - (void)webViewDidStartLoad:(UIWebView*)webView {
  273. if ([_delegate respondsToSelector:@selector(webController:webViewDidStartLoad:)]) {
  274. [_delegate webController:self webViewDidStartLoad:webView];
  275. }
  276. self.title = TTLocalizedString(@"Loading...", @"");
  277. if (!self.navigationItem.rightBarButtonItem) {
  278. [self.navigationItem setRightBarButtonItem:_activityItem animated:YES];
  279. }
  280. [_toolbar replaceItemWithTag:3 withItem:_stopButton];
  281. _backButton.enabled = [_webView canGoBack];
  282. _forwardButton.enabled = [_webView canGoForward];
  283. }
  284. ///////////////////////////////////////////////////////////////////////////////////////////////////
  285. - (void)webViewDidFinishLoad:(UIWebView*)webView {
  286. if ([_delegate respondsToSelector:@selector(webController:webViewDidFinishLoad:)]) {
  287. [_delegate webController:self webViewDidFinishLoad:webView];
  288. }
  289. TT_RELEASE_SAFELY(_loadingURL);
  290. self.title = [_webView stringByEvaluatingJavaScriptFromString:@"document.title"];
  291. if (self.navigationItem.rightBarButtonItem == _activityItem) {
  292. [self.navigationItem setRightBarButtonItem:nil animated:YES];
  293. }
  294. [_toolbar replaceItemWithTag:3 withItem:_refreshButton];
  295. _backButton.enabled = [_webView canGoBack];
  296. _forwardButton.enabled = [_webView canGoForward];
  297. }
  298. ///////////////////////////////////////////////////////////////////////////////////////////////////
  299. - (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error {
  300. if ([_delegate respondsToSelector:@selector(webController:webView:didFailLoadWithError:)]) {
  301. [_delegate webController:self webView:webView didFailLoadWithError:error];
  302. }
  303. TT_RELEASE_SAFELY(_loadingURL);
  304. [self webViewDidFinishLoad:webView];
  305. }
  306. ///////////////////////////////////////////////////////////////////////////////////////////////////
  307. ///////////////////////////////////////////////////////////////////////////////////////////////////
  308. #pragma mark -
  309. #pragma mark UIActionSheetDelegate
  310. ///////////////////////////////////////////////////////////////////////////////////////////////////
  311. - (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
  312. if (buttonIndex == 0) {
  313. [[UIApplication sharedApplication] openURL:self.URL];
  314. }
  315. }
  316. ///////////////////////////////////////////////////////////////////////////////////////////////////
  317. - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex {
  318. TT_RELEASE_SAFELY(_actionSheet);
  319. }
  320. ///////////////////////////////////////////////////////////////////////////////////////////////////
  321. - (NSURL*)URL {
  322. return _loadingURL ? _loadingURL : _webView.request.URL;
  323. }
  324. ///////////////////////////////////////////////////////////////////////////////////////////////////
  325. - (void)setHeaderView:(UIView*)headerView {
  326. if (headerView != _headerView) {
  327. BOOL addingHeader = !_headerView && headerView;
  328. BOOL removingHeader = _headerView && !headerView;
  329. [_headerView removeFromSuperview];
  330. [_headerView release];
  331. _headerView = [headerView retain];
  332. _headerView.frame = CGRectMake(0, 0, _webView.width, _headerView.height);
  333. [self view];
  334. UIView* scroller = [_webView descendantOrSelfWithClass:NSClassFromString(@"UIScroller")];
  335. UIView* docView = [scroller descendantOrSelfWithClass:NSClassFromString(@"UIWebDocumentView")];
  336. [scroller addSubview:_headerView];
  337. if (addingHeader) {
  338. docView.top += headerView.height;
  339. docView.height -= headerView.height;
  340. } else if (removingHeader) {
  341. docView.top -= headerView.height;
  342. docView.height += headerView.height;
  343. }
  344. }
  345. }
  346. ///////////////////////////////////////////////////////////////////////////////////////////////////
  347. - (void)openURL:(NSURL*)URL {
  348. NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:URL];
  349. [self openRequest:request];
  350. }
  351. ///////////////////////////////////////////////////////////////////////////////////////////////////
  352. - (void)openRequest:(NSURLRequest*)request {
  353. [self view];
  354. [_webView loadRequest:request];
  355. }
  356. @end