// // SinaWeiboAuthorizeView.m // sinaweibo_ios_sdk // // Created by Wade Cheng on 4/19/12. // Copyright (c) 2012 SINA. All rights reserved. // #import "SinaWeiboAuthorizeView.h" #import "SinaWeiboRequest.h" #import "SinaWeibo.h" #import "SinaWeiboConstants.h" #import static CGFloat kBorderGray[4] = {0.3, 0.3, 0.3, 0.8}; static CGFloat kBorderBlack[4] = {0.3, 0.3, 0.3, 1}; static CGFloat kTransitionDuration = 0.3; static CGFloat kPadding = 0; static CGFloat kBorderWidth = 10; @implementation SinaWeiboAuthorizeView @synthesize delegate; #pragma mark - Drawing - (void)addRoundedRectToPath:(CGContextRef)context rect:(CGRect)rect radius:(float)radius { CGContextBeginPath(context); CGContextSaveGState(context); if (radius == 0) { CGContextTranslateCTM(context, CGRectGetMinX(rect), CGRectGetMinY(rect)); CGContextAddRect(context, rect); } else { rect = CGRectOffset(CGRectInset(rect, 0.5, 0.5), 0.5, 0.5); CGContextTranslateCTM(context, CGRectGetMinX(rect)-0.5, CGRectGetMinY(rect)-0.5); CGContextScaleCTM(context, radius, radius); float fw = CGRectGetWidth(rect) / radius; float fh = CGRectGetHeight(rect) / radius; CGContextMoveToPoint(context, fw, fh/2); CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1); CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1); CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1); CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); } CGContextClosePath(context); CGContextRestoreGState(context); } - (void)drawRect:(CGRect)rect fill:(const CGFloat*)fillColors radius:(CGFloat)radius { CGContextRef context = UIGraphicsGetCurrentContext(); CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); if (fillColors) { CGContextSaveGState(context); CGContextSetFillColor(context, fillColors); if (radius) { [self addRoundedRectToPath:context rect:rect radius:radius]; CGContextFillPath(context); } else { CGContextFillRect(context, rect); } CGContextRestoreGState(context); } CGColorSpaceRelease(space); } - (void)strokeLines:(CGRect)rect stroke:(const CGFloat*)strokeColor { CGContextRef context = UIGraphicsGetCurrentContext(); CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB(); CGContextSaveGState(context); CGContextSetStrokeColorSpace(context, space); CGContextSetStrokeColor(context, strokeColor); CGContextSetLineWidth(context, 1.0); { CGPoint points[] = {{rect.origin.x+0.5, rect.origin.y-0.5}, {rect.origin.x+rect.size.width, rect.origin.y-0.5}}; CGContextStrokeLineSegments(context, points, 2); } { CGPoint points[] = {{rect.origin.x+0.5, rect.origin.y+rect.size.height-0.5}, {rect.origin.x+rect.size.width-0.5, rect.origin.y+rect.size.height-0.5}}; CGContextStrokeLineSegments(context, points, 2); } { CGPoint points[] = {{rect.origin.x+rect.size.width-0.5, rect.origin.y}, {rect.origin.x+rect.size.width-0.5, rect.origin.y+rect.size.height}}; CGContextStrokeLineSegments(context, points, 2); } { CGPoint points[] = {{rect.origin.x+0.5, rect.origin.y}, {rect.origin.x+0.5, rect.origin.y+rect.size.height}}; CGContextStrokeLineSegments(context, points, 2); } CGContextRestoreGState(context); CGColorSpaceRelease(space); } - (void)drawRect:(CGRect)rect { [self drawRect:rect fill:kBorderGray radius:0]; CGRect webRect = CGRectMake( ceil(rect.origin.x+kBorderWidth), ceil(rect.origin.y+kBorderWidth)+1, rect.size.width-kBorderWidth*2, rect.size.height-(1+kBorderWidth*2)); [self strokeLines:webRect stroke:kBorderBlack]; } #pragma mark - Memory management - (id)init { if ((self = [super init])) { self.backgroundColor = [UIColor clearColor]; self.autoresizesSubviews = YES; self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; self.contentMode = UIViewContentModeRedraw; webView = [[UIWebView alloc] init]; webView.delegate = self; webView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [self addSubview:webView]; [webView release]; UIImage* closeImage = [UIImage imageNamed:@"SinaWeibo.bundle/images/close.png"]; UIColor* color = [UIColor colorWithRed:167.0/255 green:184.0/255 blue:216.0/255 alpha:1]; closeButton = [UIButton buttonWithType:UIButtonTypeCustom]; [closeButton setImage:closeImage forState:UIControlStateNormal]; [closeButton setTitleColor:color forState:UIControlStateNormal]; [closeButton setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted]; [closeButton addTarget:self action:@selector(cancel) forControlEvents:UIControlEventTouchUpInside]; closeButton.titleLabel.font = [UIFont boldSystemFontOfSize:12]; closeButton.showsTouchWhenHighlighted = YES; closeButton.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleBottomMargin; [self addSubview:closeButton]; indicatorView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleGray]; indicatorView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; [self addSubview:indicatorView]; modalBackgroundView = [[UIView alloc] init]; } return self; } - (void)dealloc { [authParams release], authParams = nil; [appRedirectURI release], appRedirectURI = nil; [modalBackgroundView release], modalBackgroundView = nil; [super dealloc]; } - (id)initWithAuthParams:(NSDictionary *)params delegate:(id)_delegate { if ((self = [self init])) { self.delegate = _delegate; authParams = [params copy]; appRedirectURI = [[authParams objectForKey:@"redirect_uri"] retain]; } return self; } #pragma mark - View orientation - (BOOL)shouldRotateToOrientation:(UIInterfaceOrientation)orientation { if (orientation == previousOrientation) { return NO; } else { return orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown || orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight; } } - (CGAffineTransform)transformForOrientation { UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; if (orientation == UIInterfaceOrientationLandscapeLeft) { return CGAffineTransformMakeRotation(M_PI*1.5); } else if (orientation == UIInterfaceOrientationLandscapeRight) { return CGAffineTransformMakeRotation(M_PI/2); } else if (orientation == UIInterfaceOrientationPortraitUpsideDown) { return CGAffineTransformMakeRotation(-M_PI); } else { return CGAffineTransformIdentity; } } - (void)sizeToFitOrientation:(BOOL)transform { if (transform) { self.transform = CGAffineTransformIdentity; } CGRect frame = [UIScreen mainScreen].applicationFrame; CGPoint center = CGPointMake(frame.origin.x + ceil(frame.size.width/2), frame.origin.y + ceil(frame.size.height/2)); CGFloat scaleFactor = SinaWeiboIsDeviceIPad() ? 0.6f : 1.0f; CGFloat width = floor(scaleFactor * frame.size.width) - kPadding * 2; CGFloat height = floor(scaleFactor * frame.size.height) - kPadding * 2; previousOrientation = [UIApplication sharedApplication].statusBarOrientation; if (UIInterfaceOrientationIsLandscape(previousOrientation)) { self.frame = CGRectMake(kPadding, kPadding, height, width); } else { self.frame = CGRectMake(kPadding, kPadding, width, height); } self.center = center; if (transform) { self.transform = [self transformForOrientation]; } } - (void)updateWebOrientation { UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; if (UIInterfaceOrientationIsLandscape(orientation)) { [webView stringByEvaluatingJavaScriptFromString: @"document.body.setAttribute('orientation', 90);"]; } else { [webView stringByEvaluatingJavaScriptFromString: @"document.body.removeAttribute('orientation');"]; } } #pragma mark - UIDeviceOrientationDidChangeNotification Methods - (void)deviceOrientationDidChange:(id)object { UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation; if ([self shouldRotateToOrientation:orientation]) { NSTimeInterval duration = [UIApplication sharedApplication].statusBarOrientationAnimationDuration; [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:duration]; [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut]; [self sizeToFitOrientation:orientation]; [UIView commitAnimations]; } } #pragma mark - Animation - (void)bounce1AnimationStopped { [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:kTransitionDuration/2]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(bounce2AnimationStopped)]; self.transform = CGAffineTransformScale([self transformForOrientation], 0.9, 0.9); [UIView commitAnimations]; } - (void)bounce2AnimationStopped { [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:kTransitionDuration/2]; self.transform = [self transformForOrientation]; [UIView commitAnimations]; } #pragma mark Obeservers - (void)addObservers { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(deviceOrientationDidChange:) name:@"UIDeviceOrientationDidChangeNotification" object:nil]; } - (void)removeObservers { [[NSNotificationCenter defaultCenter] removeObserver:self name:@"UIDeviceOrientationDidChangeNotification" object:nil]; } #pragma mark - Activity Indicator - (void)showIndicator { [indicatorView sizeToFit]; [indicatorView startAnimating]; indicatorView.center = webView.center; } - (void)hideIndicator { [indicatorView stopAnimating]; } #pragma mark - Show / Hide - (void)load { NSString *authPagePath = [SinaWeiboRequest serializeURL:kSinaWeiboWebAuthURL params:authParams httpMethod:@"GET"]; [webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:authPagePath]]]; } - (void)showWebView { UIWindow* window = [UIApplication sharedApplication].keyWindow; if (!window) { window = [[UIApplication sharedApplication].windows objectAtIndex:0]; } modalBackgroundView.frame = window.frame; [modalBackgroundView addSubview:self]; [window addSubview:modalBackgroundView]; self.transform = CGAffineTransformScale([self transformForOrientation], 0.001, 0.001); [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:kTransitionDuration/1.5]; [UIView setAnimationDelegate:self]; [UIView setAnimationDidStopSelector:@selector(bounce1AnimationStopped)]; self.transform = CGAffineTransformScale([self transformForOrientation], 1.1, 1.1); [UIView commitAnimations]; } - (void)show { [self load]; [self sizeToFitOrientation:NO]; CGFloat innerWidth = self.frame.size.width - (kBorderWidth+1)*2; [closeButton sizeToFit]; closeButton.frame = CGRectMake(2, 2, 29, 29); webView.frame = CGRectMake(kBorderWidth+1, kBorderWidth+1, innerWidth, self.frame.size.height - (1 + kBorderWidth*2)); [self showWebView]; [self showIndicator]; [self addObservers]; } - (void)_hide { [self removeFromSuperview]; [modalBackgroundView removeFromSuperview]; } - (void)hide { [self removeObservers]; [webView stopLoading]; [self performSelectorOnMainThread:@selector(_hide) withObject:nil waitUntilDone:NO]; } - (void)cancel { [self hide]; [delegate authorizeViewDidCancel:self]; } #pragma mark - UIWebView Delegate - (void)webViewDidFinishLoad:(UIWebView *)aWebView { [self hideIndicator]; } - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error { [self hideIndicator]; } - (BOOL)webView:(UIWebView *)aWebView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSString *url = request.URL.absoluteString; NSLog(@"url = %@", url); NSString *siteRedirectURI = [NSString stringWithFormat:@"%@%@", kSinaWeiboSDKOAuth2APIDomain, appRedirectURI]; if ([url hasPrefix:appRedirectURI] || [url hasPrefix:siteRedirectURI]) { NSString *error_code = [SinaWeiboRequest getParamValueFromUrl:url paramName:@"error_code"]; if (error_code) { NSString *error = [SinaWeiboRequest getParamValueFromUrl:url paramName:@"error"]; NSString *error_uri = [SinaWeiboRequest getParamValueFromUrl:url paramName:@"error_uri"]; NSString *error_description = [SinaWeiboRequest getParamValueFromUrl:url paramName:@"error_description"]; NSDictionary *errorInfo = [NSDictionary dictionaryWithObjectsAndKeys: error, @"error", error_uri, @"error_uri", error_code, @"error_code", error_description, @"error_description", nil]; [self hide]; [delegate authorizeView:self didFailWithErrorInfo:errorInfo]; } else { NSString *code = [SinaWeiboRequest getParamValueFromUrl:url paramName:@"code"]; if (code) { [self hide]; [delegate authorizeView:self didRecieveAuthorizationCode:code]; } } return NO; } return YES; } @end