Update App Update screen to be more iOS 6 like

Also do some small refactoring and rename the PS classes to BIT to avoid any possible namespacing problems
This commit is contained in:
Andreas Linde 2012-10-21 00:38:12 +02:00
parent 11a708d446
commit 857d02347e
14 changed files with 545 additions and 529 deletions

View File

@ -0,0 +1,41 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011-2012 Peter Steinberger.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <UIKit/UIKit.h>
@interface BITAppStoreHeader : UIView
@property (nonatomic, copy) NSString *headerLabel;
@property (nonatomic, copy) NSString *middleHeaderLabel;
@property (nonatomic, copy) NSString *subHeaderLabel;
@property (nonatomic, retain) UIImage *iconImage;
@end

161
Classes/BITAppStoreHeader.m Normal file
View File

@ -0,0 +1,161 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011-2012 Peter Steinberger.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "BITAppStoreHeader.h"
#import "BITHockeyHelper.h"
#import "HockeySDKPrivate.h"
#define BIT_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
#define kLightGrayColor BIT_RGBCOLOR(235, 235, 235)
#define kDarkGrayColor BIT_RGBCOLOR(186, 186, 186)
#define kWhiteBackgroundColor BIT_RGBCOLOR(245, 245, 245)
#define kImageHeight 72
#define kImageBorderRadius 12
#define kImageLeftMargin 14
#define kImageTopMargin 12
#define kTextRow kImageTopMargin*2 + kImageHeight
@implementation BITAppStoreHeader
#pragma mark - NSObject
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.backgroundColor = kWhiteBackgroundColor;
}
return self;
}
- (void)dealloc {
[_headerLabel release], _headerLabel = nil;
[_middleHeaderLabel release], _middleHeaderLabel = nil;
[_subHeaderLabel release], _subHeaderLabel = nil;
[_iconImage release], _iconImage = nil;;
[super dealloc];
}
#pragma mark - UIView
- (void)drawRect:(CGRect)rect {
CGRect bounds = self.bounds;
CGFloat globalWidth = self.frame.size.width;
CGContextRef context = UIGraphicsGetCurrentContext();
// draw the gradient
NSArray *colors = [NSArray arrayWithObjects:(id)kDarkGrayColor.CGColor, (id)kLightGrayColor.CGColor, nil];
CGGradientRef gradient = CGGradientCreateWithColors(CGColorGetColorSpace((CGColorRef)[colors objectAtIndex:0]), (CFArrayRef)colors, (CGFloat[2]){0, 1});
CGPoint top = CGPointMake(CGRectGetMidX(bounds), bounds.size.height - 3);
CGPoint bottom = CGPointMake(CGRectGetMidX(bounds), CGRectGetMaxY(bounds));
CGContextDrawLinearGradient(context, gradient, top, bottom, 0);
CGGradientRelease(gradient);
// draw header name
UIColor *mainTextColor = BIT_RGBCOLOR(61, 61, 61);
UIColor *secondaryTextColor = BIT_RGBCOLOR(100, 100, 100);
UIFont *mainFont = [UIFont boldSystemFontOfSize:15];
UIFont *secondaryFont = [UIFont systemFontOfSize:10];
// float myColorValues[] = {255, 255, 255, .6};
// CGColorSpaceRef myColorSpace = CGColorSpaceCreateDeviceRGB();
// CGColorRef myColor = CGColorCreate(myColorSpace, myColorValues);
// icon
[_iconImage drawAtPoint:CGPointMake(kImageLeftMargin, kImageTopMargin)];
// shadows are a beast
// NSInteger shadowOffset = 2;
// if([[UIScreen mainScreen] scale] == 2) shadowOffset = 1;
// BITHOCKEY_IF_IOS5_OR_GREATER(shadowOffset = 1;) // iOS5 changes this - again!
//
// CGContextSetShadowWithColor(context, CGSizeMake(shadowOffset, shadowOffset), 0, myColor);
[mainTextColor set];
[_headerLabel drawInRect:CGRectMake(kTextRow, kImageTopMargin, globalWidth-kTextRow, 20) withFont:mainFont lineBreakMode:UILineBreakModeTailTruncation];
// middle
[secondaryTextColor set];
[_middleHeaderLabel drawInRect:CGRectMake(kTextRow, kImageTopMargin + 17, globalWidth-kTextRow, 20) withFont:secondaryFont lineBreakMode:UILineBreakModeTailTruncation];
// CGContextSetShadowWithColor(context, CGSizeZero, 0, nil);
// sub
[secondaryTextColor set];
[_subHeaderLabel drawAtPoint:CGPointMake(kTextRow, kImageTopMargin + 29) forWidth:globalWidth-kTextRow withFont:secondaryFont lineBreakMode:UILineBreakModeTailTruncation];
// CGColorRelease(myColor);
// CGColorSpaceRelease(myColorSpace);
}
#pragma mark - Properties
- (void)setHeaderLabel:(NSString *)anHeaderLabel {
if (_headerLabel != anHeaderLabel) {
[_headerLabel release];
_headerLabel = [anHeaderLabel copy];
[self setNeedsDisplay];
}
}
- (void)setMiddleHeaderLabel:(NSString *)aMiddleHeaderLabel {
if (_middleHeaderLabel != aMiddleHeaderLabel) {
[_middleHeaderLabel release];
_middleHeaderLabel = [aMiddleHeaderLabel copy];
[self setNeedsDisplay];
}
}
- (void)setSubHeaderLabel:(NSString *)aSubHeaderLabel {
if (_subHeaderLabel != aSubHeaderLabel) {
[_subHeaderLabel release];
_subHeaderLabel = [aSubHeaderLabel copy];
[self setNeedsDisplay];
}
}
- (void)setIconImage:(UIImage *)anIconImage {
if (_iconImage != anIconImage) {
[_iconImage release];
// scale, make borders and reflection
_iconImage = bit_imageToFitSize(anIconImage, CGSizeMake(kImageHeight, kImageHeight), YES);
_iconImage = [bit_roundedCornerImage(_iconImage, kImageBorderRadius, 0.0) retain];
[self setNeedsDisplay];
}
}
@end

81
Classes/BITStoreButton.h Normal file
View File

@ -0,0 +1,81 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011-2012 Peter Steinberger.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
// defines a button action set (data container)
@interface BITStoreButtonData : NSObject {
CGPoint _customPadding;
}
+ (id)dataWithLabel:(NSString*)aLabel colors:(NSArray*)aColors enabled:(BOOL)flag;
@property (nonatomic, copy) NSString *label;
@property (nonatomic, retain) NSArray *colors;
@property (nonatomic, assign, getter=isEnabled) BOOL enabled;
@end
@class BITStoreButton;
@protocol BITStoreButtonDelegate
- (void)storeButtonFired:(BITStoreButton *)button;
@end
// Simulate the Paymeny-Button from the AppStore
// The interface is flexible, so there is now fixed order
@interface BITStoreButton : UIButton {
CAGradientLayer *_gradient;
CGPoint _customPadding;
}
- (id)initWithFrame:(CGRect)frame;
- (id)initWithPadding:(CGPoint)padding;
// action delegate
@property (nonatomic, assign) id<BITStoreButtonDelegate> buttonDelegate;
// change the button layer
@property (nonatomic, retain) BITStoreButtonData *buttonData;
- (void)setButtonData:(BITStoreButtonData *)aButtonData animated:(BOOL)animated;
// align helper
@property (nonatomic, assign) CGPoint customPadding;
- (void)alignToSuperview;
// helpers to mimic an AppStore button
+ (NSArray *)appStoreGreenColor;
+ (NSArray *)appStoreBlueColor;
+ (NSArray *)appStoreGrayColor;
@end

View File

@ -1,28 +1,35 @@
//
// Created by Peter Steinberger on 09.01.11.
// Copyright 2011-2012 Peter Steinberger. All rights reserved.
//
// This code was inspired by https://github.com/dhmspector/ZIStoreButton
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
/*
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011-2012 Peter Steinberger.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "PSStoreButton.h"
#import "BITStoreButton.h"
#define PS_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
#define PS_MIN_HEIGHT 25.0f
@ -30,12 +37,8 @@
#define PS_PADDING 12.0f
#define kDefaultButtonAnimationTime 0.25f
@implementation PSStoreButtonData
@synthesize label = label_;
@synthesize colors = colors_;
@synthesize enabled = enabled_;
@implementation BITStoreButtonData
#pragma mark - NSObject
@ -53,31 +56,26 @@
}
- (void)dealloc {
[label_ release];
[colors_ release];
[_label release], _label = nil;
[_colors release];
[super dealloc];
}
@end
@interface PSStoreButton ()
@interface BITStoreButton ()
// call when buttonData was updated
- (void)updateButtonAnimated:(BOOL)animated;
@end
@implementation PSStoreButton
@synthesize buttonData = buttonData_;
@synthesize buttonDelegate = buttonDelegate_;
@synthesize customPadding = customPadding_;
@implementation BITStoreButton
#pragma mark - private
- (void)buttonPressed:(id)sender {
[buttonDelegate_ storeButtonFired:self];
[_buttonDelegate storeButtonFired:self];
}
- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
@ -101,7 +99,7 @@
}
self.enabled = self.buttonData.isEnabled;
gradient_.colors = self.buttonData.colors;
_gradient.colors = self.buttonData.colors;
// show white or gray text, depending on the state
if (self.buttonData.isEnabled) {
@ -148,8 +146,8 @@
[self sizeToFit];
if (self.superview) {
CGRect cr = self.frame;
cr.origin.y = customPadding_.y;
cr.origin.x = self.superview.frame.size.width - cr.size.width - customPadding_.x * 2;
cr.origin.y = _customPadding.y;
cr.origin.x = self.superview.frame.size.width - cr.size.width - _customPadding.x * 2;
self.frame = cr;
}
}
@ -183,12 +181,12 @@
[self.layer addSublayer:topBorderLayer];
// main gradient layer
gradient_ = [[CAGradientLayer layer] retain];
gradient_.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:1.0], nil];//[NSNumber numberWithFloat:0.500], [NSNumber numberWithFloat:0.5001],
gradient_.frame = CGRectMake(0.75, 0.75, CGRectGetWidth(frame) - 1.5, CGRectGetHeight(frame) - 1.5);
gradient_.cornerRadius = 2.5;
gradient_.needsDisplayOnBoundsChange = YES;
[self.layer addSublayer:gradient_];
_gradient = [[CAGradientLayer layer] retain];
_gradient.locations = [NSArray arrayWithObjects:[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:1.0], nil];//[NSNumber numberWithFloat:0.500], [NSNumber numberWithFloat:0.5001],
_gradient.frame = CGRectMake(0.75, 0.75, CGRectGetWidth(frame) - 1.5, CGRectGetHeight(frame) - 1.5);
_gradient.cornerRadius = 2.5;
_gradient.needsDisplayOnBoundsChange = YES;
[self.layer addSublayer:_gradient];
[self bringSubviewToFront:self.titleLabel];
}
return self;
@ -196,14 +194,14 @@
- (id)initWithPadding:(CGPoint)padding {
if ((self = [self initWithFrame:CGRectMake(0, 0, 40, PS_MIN_HEIGHT)])) {
customPadding_ = padding;
_customPadding = padding;
}
return self;
}
- (void)dealloc {
[buttonData_ release];
[gradient_ release];
[_buttonData release];
[_gradient release];
[super dealloc];
}
@ -237,14 +235,14 @@
#pragma mark - Properties
- (void)setButtonData:(PSStoreButtonData *)aButtonData {
- (void)setButtonData:(BITStoreButtonData *)aButtonData {
[self setButtonData:aButtonData animated:NO];
}
- (void)setButtonData:(PSStoreButtonData *)aButtonData animated:(BOOL)animated {
if (buttonData_ != aButtonData) {
[buttonData_ release];
buttonData_ = [aButtonData retain];
- (void)setButtonData:(BITStoreButtonData *)aButtonData animated:(BOOL)animated {
if (_buttonData != aButtonData) {
[_buttonData release];
_buttonData = [aButtonData retain];
}
[self updateButtonAnimated:animated];

View File

@ -33,9 +33,5 @@
#import "BITHockeyBaseViewController.h"
@class PSStoreButton;
@class PSAppStoreHeader;
@interface BITUpdateViewController : BITHockeyBaseViewController
@end

View File

@ -31,9 +31,9 @@
#import <QuartzCore/QuartzCore.h>
#import "BITHockeyHelper.h"
#import "BITAppVersionMetaInfo.h"
#import "PSAppStoreHeader.h"
#import "PSWebTableViewCell.h"
#import "PSStoreButton.h"
#import "BITAppStoreHeader.h"
#import "BITWebTableViewCell.h"
#import "BITStoreButton.h"
#import "HockeySDK.h"
#import "HockeySDKPrivate.h"
@ -43,15 +43,15 @@
#define kWebCellIdentifier @"PSWebTableViewCell"
#define kAppStoreViewHeight 90
#define kAppStoreViewHeight 99
@implementation BITUpdateViewController {
BOOL _kvoRegistered;
BOOL _showAllVersions;
UIStatusBarStyle _statusBarStyle;
PSAppStoreHeader *_appStoreHeader;
PSStoreButton *_appStoreButton;
BITAppStoreHeader *_appStoreHeader;
BITStoreButton *_appStoreButton;
id _popOverController;
@ -138,11 +138,11 @@
}
- (void)changePreviousVersionButtonBackground:(id)sender {
[(UIButton *)sender setBackgroundColor:BIT_RGBCOLOR(183,183,183)];
[(UIButton *)sender setBackgroundColor:BIT_RGBCOLOR(245, 245, 245)];
}
- (void)changePreviousVersionButtonBackgroundHighlighted:(id)sender {
[(UIButton *)sender setBackgroundColor:BIT_RGBCOLOR(183,183,183)];
[(UIButton *)sender setBackgroundColor:BIT_RGBCOLOR(245, 245, 245)];
}
- (void)showHidePreviousVersionsButton {
@ -152,35 +152,47 @@
// align at the bottom if tableview is small
UIView *footerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, kMinPreviousVersionButtonHeight)];
footerView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
footerView.backgroundColor = BIT_RGBCOLOR(200, 202, 204);
footerView.backgroundColor = BIT_RGBCOLOR(245, 245, 245);
UIView *lineView1 = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 1)] autorelease];
lineView1.backgroundColor = BIT_RGBCOLOR(214, 214, 214);
lineView1.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[footerView addSubview:lineView1];
UIView *lineView2 = [[[UIView alloc] initWithFrame:CGRectMake(0, 1, self.view.frame.size.width, 1)] autorelease];
lineView2.backgroundColor = BIT_RGBCOLOR(221, 221, 221);
lineView2.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[footerView addSubview:lineView2];
UIView *lineView3 = [[[UIView alloc] initWithFrame:CGRectMake(0, 1, self.view.frame.size.width, 1)] autorelease];
lineView3.backgroundColor = BIT_RGBCOLOR(255, 255, 255);
lineView3.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[footerView addSubview:lineView3];
UIButton *footerButton = [UIButton buttonWithType:UIButtonTypeCustom];
//footerButton.layer.shadowOffset = CGSizeMake(-2, 2);
footerButton.layer.shadowColor = [[UIColor blackColor] CGColor];
footerButton.layer.shadowRadius = 2.0f;
footerButton.titleLabel.font = [UIFont boldSystemFontOfSize:14];
[footerButton setTitle:BITHockeyLocalizedString(@"UpdateShowPreviousVersions") forState:UIControlStateNormal];
[footerButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[footerButton setTitleColor:BIT_RGBCOLOR(61, 61, 61) forState:UIControlStateNormal];
[footerButton setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
[footerButton setBackgroundImage:bit_imageNamed(@"buttonHighlight.png", BITHOCKEYSDK_BUNDLE) forState:UIControlStateHighlighted];
footerButton.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin;
[footerButton addTarget:self action:@selector(showPreviousVersionAction) forControlEvents:UIControlEventTouchUpInside];
footerButton.frame = CGRectMake(0, kMinPreviousVersionButtonHeight-44, self.view.frame.size.width, 44);
footerButton.backgroundColor = BIT_RGBCOLOR(183,183,183);
footerButton.backgroundColor = BIT_RGBCOLOR(245, 245, 245);
[footerView addSubview:footerButton];
self.tableView.tableFooterView = footerView;
[self realignPreviousVersionButton];
[footerView release];
} else {
self.tableView.tableFooterView = nil;
self.tableView.backgroundColor = BIT_RGBCOLOR(200, 202, 204);
self.tableView.backgroundColor = BIT_RGBCOLOR(235, 235, 235);
}
}
- (void)configureWebCell:(PSWebTableViewCell *)cell forAppVersion:(BITAppVersionMetaInfo *)appVersion {
- (void)configureWebCell:(BITWebTableViewCell *)cell forAppVersion:(BITAppVersionMetaInfo *)appVersion {
// create web view for a version
NSString *installed = @"";
if ([appVersion.version isEqualToString:[_updateManager currentAppVersion]]) {
installed = [NSString stringWithFormat:@"<span style=\"float:%@;text-shadow:rgba(255,255,255,0.6) 1px 1px 0px;\"><b>%@</b></span>", [appVersion isEqual:_updateManager.newestAppVersion] ? @"left" : @"right", BITHockeyLocalizedString(@"UpdateInstalled")];
installed = [NSString stringWithFormat:@"<span style=\"float:%@;\"><b>%@</b></span>", [appVersion isEqual:_updateManager.newestAppVersion] ? @"left" : @"right", BITHockeyLocalizedString(@"UpdateInstalled")];
}
if ([appVersion isEqual:_updateManager.newestAppVersion]) {
@ -188,12 +200,12 @@
installed = [NSString stringWithFormat:@"<p>&nbsp;%@</p>", installed];
cell.webViewContent = [NSString stringWithFormat:@"%@%@", installed, appVersion.notes];
} else {
cell.webViewContent = [NSString stringWithFormat:@"<div style=\"min-height:200px;vertical-align:middle;text-align:center;text-shadow:rgba(255,255,255,0.6) 1px 1px 0px;\">%@</div>", BITHockeyLocalizedString(@"UpdateNoReleaseNotesAvailable")];
cell.webViewContent = [NSString stringWithFormat:@"<div style=\"min-height:200px;vertical-align:middle;text-align:center;\">%@</div>", BITHockeyLocalizedString(@"UpdateNoReleaseNotesAvailable")];
}
} else {
cell.webViewContent = [NSString stringWithFormat:@"<p><b style=\"text-shadow:rgba(255,255,255,0.6) 1px 1px 0px;\">%@</b>%@<br/><small>%@</small></p><p>%@</p>", [appVersion versionString], installed, [appVersion dateString], [appVersion notesOrEmptyString]];
cell.webViewContent = [NSString stringWithFormat:@"<p><b>%@</b>%@<br/><small>%@</small></p><p>%@</p>", [appVersion versionString], installed, [appVersion dateString], [appVersion notesOrEmptyString]];
}
cell.cellBackgroundColor = BIT_RGBCOLOR(200, 202, 204);
cell.cellBackgroundColor = BIT_RGBCOLOR(235, 235, 235);
[cell addWebView];
// hack
@ -243,28 +255,28 @@
#pragma mark - View lifecycle
- (CAGradientLayer *)backgroundLayer {
UIColor *colorOne = [UIColor colorWithWhite:0.9 alpha:1.0];
UIColor *colorTwo = [UIColor colorWithHue:0.625 saturation:0.0 brightness:0.85 alpha:1.0];
UIColor *colorThree = [UIColor colorWithHue:0.625 saturation:0.0 brightness:0.7 alpha:1.0];
UIColor *colorFour = [UIColor colorWithHue:0.625 saturation:0.0 brightness:0.4 alpha:1.0];
NSArray *colors = [NSArray arrayWithObjects:(id)colorOne.CGColor, colorTwo.CGColor, colorThree.CGColor, colorFour.CGColor, nil];
NSNumber *stopOne = [NSNumber numberWithFloat:0.0];
NSNumber *stopTwo = [NSNumber numberWithFloat:0.02];
NSNumber *stopThree = [NSNumber numberWithFloat:0.99];
NSNumber *stopFour = [NSNumber numberWithFloat:1.0];
NSArray *locations = [NSArray arrayWithObjects:stopOne, stopTwo, stopThree, stopFour, nil];
CAGradientLayer *headerLayer = [CAGradientLayer layer];
//headerLayer.frame = CGRectMake(0.0, 0.0, 320.0, 77.0);
headerLayer.colors = colors;
headerLayer.locations = locations;
return headerLayer;
}
//- (CAGradientLayer *)backgroundLayer {
// UIColor *colorOne = [UIColor colorWithWhite:0.9 alpha:1.0];
// UIColor *colorTwo = [UIColor colorWithHue:0.625 saturation:0.0 brightness:0.85 alpha:1.0];
// UIColor *colorThree = [UIColor colorWithHue:0.625 saturation:0.0 brightness:0.7 alpha:1.0];
// UIColor *colorFour = [UIColor colorWithHue:0.625 saturation:0.0 brightness:0.4 alpha:1.0];
//
// NSArray *colors = [NSArray arrayWithObjects:(id)colorOne.CGColor, colorTwo.CGColor, colorThree.CGColor, colorFour.CGColor, nil];
//
// NSNumber *stopOne = [NSNumber numberWithFloat:0.0];
// NSNumber *stopTwo = [NSNumber numberWithFloat:0.02];
// NSNumber *stopThree = [NSNumber numberWithFloat:0.99];
// NSNumber *stopFour = [NSNumber numberWithFloat:1.0];
//
// NSArray *locations = [NSArray arrayWithObjects:stopOne, stopTwo, stopThree, stopFour, nil];
//
// CAGradientLayer *headerLayer = [CAGradientLayer layer];
// //headerLayer.frame = CGRectMake(0.0, 0.0, 320.0, 77.0);
// headerLayer.colors = colors;
// headerLayer.locations = locations;
//
// return headerLayer;
//}
- (void)viewDidLoad {
[super viewDidLoad];
@ -280,7 +292,7 @@
[_updateManager addObserver:self forKeyPath:@"apps" options:0 context:nil];
_kvoRegistered = YES;
self.tableView.backgroundColor = BIT_RGBCOLOR(200, 202, 204);
self.tableView.backgroundColor = BIT_RGBCOLOR(235, 235, 235);
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
UIView *topView = [[[UIView alloc] initWithFrame:CGRectMake(0, -(600-kAppStoreViewHeight), self.view.frame.size.width, 600)] autorelease];
@ -288,7 +300,7 @@
topView.backgroundColor = BIT_RGBCOLOR(140, 141, 142);
[self.tableView addSubview:topView];
_appStoreHeader = [[PSAppStoreHeader alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, kAppStoreViewHeight)];
_appStoreHeader = [[BITAppStoreHeader alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, kAppStoreViewHeight)];
[self updateAppStoreHeader];
NSString *iconString = nil;
@ -309,17 +321,20 @@
if (icons) {
BOOL useHighResIcon = NO;
BOOL useiPadIcon = NO;
if ([UIScreen mainScreen].scale == 2.0f) useHighResIcon = YES;
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) useiPadIcon = YES;
for(NSString *icon in icons) {
iconString = icon;
UIImage *iconImage = [UIImage imageNamed:icon];
if (iconImage.size.height == 57 && !useHighResIcon) {
// found!
break;
}
if (iconImage.size.height == 114 && useHighResIcon) {
if (
(iconImage.size.height == 57 && !useHighResIcon && !useiPadIcon) ||
(iconImage.size.height == 114 && useHighResIcon && !useiPadIcon) ||
(iconImage.size.height == 72 && !useHighResIcon && useiPadIcon) ||
(iconImage.size.height == 144 && useHighResIcon && useiPadIcon)
) {
// found!
break;
}
@ -340,11 +355,11 @@
self.tableView.tableHeaderView = _appStoreHeader;
PSStoreButton *storeButton = [[[PSStoreButton alloc] initWithPadding:CGPointMake(5, 40)] autorelease];
BITStoreButton *storeButton = [[[BITStoreButton alloc] initWithPadding:CGPointMake(5, 58)] autorelease];
storeButton.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin;
storeButton.buttonDelegate = self;
[self.tableView.tableHeaderView addSubview:storeButton];
storeButton.buttonData = [PSStoreButtonData dataWithLabel:@"" colors:[PSStoreButton appStoreGrayColor] enabled:NO];
storeButton.buttonData = [BITStoreButtonData dataWithLabel:@"" colors:[BITStoreButton appStoreGrayColor] enabled:NO];
[storeButton alignToSuperview];
_appStoreButton = [storeButton retain];
self.appStoreButtonState = AppStoreButtonStateCheck;
@ -394,7 +409,7 @@
}
}
PSWebTableViewCell *cell = [[[PSWebTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kWebCellIdentifier] autorelease];
BITWebTableViewCell *cell = [[[BITWebTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kWebCellIdentifier] autorelease];
[self configureWebCell:cell forAppVersion:appVersion];
[_cells addObject:cell];
@ -421,7 +436,7 @@
}
}
PSWebTableViewCell *cell = [[[PSWebTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kWebCellIdentifier] autorelease];
BITWebTableViewCell *cell = [[[BITWebTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kWebCellIdentifier] autorelease];
[self configureWebCell:cell forAppVersion:appVersion];
[_cells addObject:cell];
}
@ -440,17 +455,17 @@
CGFloat rowHeight = 0;
if ([_cells count] > (NSUInteger)indexPath.row) {
PSWebTableViewCell *cell = [_cells objectAtIndex:indexPath.row];
BITWebTableViewCell *cell = [_cells objectAtIndex:indexPath.row];
rowHeight = cell.webViewSize.height;
}
if ([_updateManager.appVersions count] > 1 && !_showAllVersions) {
self.tableView.backgroundColor = BIT_RGBCOLOR(183, 183, 183);
self.tableView.backgroundColor = BIT_RGBCOLOR(245, 245, 245);
}
if (rowHeight == 0) {
rowHeight = indexPath.row == 0 ? 250 : 44; // fill screen on startup
self.tableView.backgroundColor = BIT_RGBCOLOR(200, 202, 204);
self.tableView.backgroundColor = BIT_RGBCOLOR(235, 235, 235);
}
return rowHeight;
@ -516,26 +531,26 @@
switch (anAppStoreButtonState) {
case AppStoreButtonStateOffline:
[_appStoreButton setButtonData:[PSStoreButtonData dataWithLabel:BITHockeyLocalizedString(@"UpdateButtonOffline") colors:[PSStoreButton appStoreGrayColor] enabled:NO] animated:animated];
[_appStoreButton setButtonData:[BITStoreButtonData dataWithLabel:BITHockeyLocalizedString(@"UpdateButtonOffline") colors:[BITStoreButton appStoreGrayColor] enabled:NO] animated:animated];
break;
case AppStoreButtonStateCheck:
[_appStoreButton setButtonData:[PSStoreButtonData dataWithLabel:BITHockeyLocalizedString(@"UpdateButtonCheck") colors:[PSStoreButton appStoreGreenColor] enabled:YES] animated:animated];
[_appStoreButton setButtonData:[BITStoreButtonData dataWithLabel:BITHockeyLocalizedString(@"UpdateButtonCheck") colors:[BITStoreButton appStoreGreenColor] enabled:YES] animated:animated];
break;
case AppStoreButtonStateSearching:
[_appStoreButton setButtonData:[PSStoreButtonData dataWithLabel:BITHockeyLocalizedString(@"UpdateButtonSearching") colors:[PSStoreButton appStoreGrayColor] enabled:NO] animated:animated];
[_appStoreButton setButtonData:[BITStoreButtonData dataWithLabel:BITHockeyLocalizedString(@"UpdateButtonSearching") colors:[BITStoreButton appStoreGrayColor] enabled:NO] animated:animated];
break;
case AppStoreButtonStateUpdate:
[_appStoreButton setButtonData:[PSStoreButtonData dataWithLabel:BITHockeyLocalizedString(@"UpdateButtonUpdate") colors:[PSStoreButton appStoreBlueColor] enabled:YES] animated:animated];
[_appStoreButton setButtonData:[BITStoreButtonData dataWithLabel:BITHockeyLocalizedString(@"UpdateButtonUpdate") colors:[BITStoreButton appStoreBlueColor] enabled:YES] animated:animated];
break;
case AppStoreButtonStateInstalling:
[_appStoreButton setButtonData:[PSStoreButtonData dataWithLabel:BITHockeyLocalizedString(@"UpdateButtonInstalling") colors:[PSStoreButton appStoreGrayColor] enabled:NO] animated:animated];
[_appStoreButton setButtonData:[BITStoreButtonData dataWithLabel:BITHockeyLocalizedString(@"UpdateButtonInstalling") colors:[BITStoreButton appStoreGrayColor] enabled:NO] animated:animated];
break;
default:
break;
}
}
- (void)storeButtonFired:(PSStoreButton *)button {
- (void)storeButtonFired:(BITStoreButton *)button {
switch (_appStoreButtonState) {
case AppStoreButtonStateCheck:
[_updateManager checkForUpdateShowFeedback:YES];

View File

@ -29,7 +29,7 @@
*/
#import <UIKit/UIKit.h>
#import "PSStoreButton.h"
#import "BITStoreButton.h"
typedef enum {
AppStoreButtonStateOffline,
@ -44,7 +44,7 @@ typedef enum {
@protocol PSStoreButtonDelegate;
@interface BITUpdateViewController() <PSStoreButtonDelegate> {
@interface BITUpdateViewController() <BITStoreButtonDelegate> {
}
@property (nonatomic, assign) BITUpdateManager *updateManager;

View File

@ -0,0 +1,44 @@
/*
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011-2012 Peter Steinberger.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface BITWebTableViewCell : UITableViewCell <UIWebViewDelegate>
@property (nonatomic, retain) UIWebView *webView;
@property (nonatomic, copy) NSString *webViewContent;
@property (nonatomic, assign) CGSize webViewSize;
@property (nonatomic, retain) UIColor *cellBackgroundColor;
- (void)addWebView;
@end

View File

@ -1,36 +1,44 @@
//
// Created by Peter Steinberger on 04.02.11.
// Copyright 2011-2012 Peter Steinberger. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
/*
* Author: Andreas Linde <mail@andreaslinde.de>
* Peter Steinberger
*
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
* Copyright (c) 2011-2012 Peter Steinberger.
* All rights reserved.
*
* Permission is hereby granted, free of charge, to any person
* obtaining a copy of this software and associated documentation
* files (the "Software"), to deal in the Software without
* restriction, including without limitation the rights to use,
* copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following
* conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
* OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*/
#import "PSWebTableViewCell.h"
#import "BITWebTableViewCell.h"
@implementation PSWebTableViewCell
@implementation BITWebTableViewCell
static NSString* PSWebTableViewCellHtmlTemplate = @"\
static NSString* BITWebTableViewCellHtmlTemplate = @"\
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\
<html xmlns=\"http://www.w3.org/1999/xhtml\">\
<head>\
<style type=\"text/css\">\
body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px;} p {margin:0;} ul {padding-left: 18px;}\
body { font: 13px 'Helvetica Neue', Helvetica; color:#626262; word-wrap:break-word; padding:8px;} p {margin:0;} ul {padding-left: 18px;}\
</style>\
<meta name=\"viewport\" content=\"user-scalable=no width=%@\" /></head>\
<body>\
@ -39,27 +47,22 @@ body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px
</html>\
";
@synthesize webView = webView_;
@synthesize webViewContent = webViewContent_;
@synthesize webViewSize = webViewSize_;
@synthesize cellBackgroundColor = cellBackgroundColor_;
#pragma mark - private
- (void)addWebView {
if(webViewContent_) {
if(_webViewContent) {
CGRect webViewRect = CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
if(!webView_) {
webView_ = [[[UIWebView alloc] initWithFrame:webViewRect] retain];
[self addSubview:webView_];
webView_.hidden = YES;
webView_.backgroundColor = self.cellBackgroundColor;
webView_.opaque = NO;
webView_.delegate = self;
webView_.autoresizingMask = UIViewAutoresizingFlexibleWidth;
if(!_webView) {
_webView = [[[UIWebView alloc] initWithFrame:webViewRect] retain];
[self addSubview:_webView];
_webView.hidden = YES;
_webView.backgroundColor = self.cellBackgroundColor;
_webView.opaque = NO;
_webView.delegate = self;
_webView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
for(UIView* subView in webView_.subviews){
for(UIView* subView in _webView.subviews){
if([subView isKindOfClass:[UIScrollView class]]){
// disable scrolling
UIScrollView *sv = (UIScrollView *)subView;
@ -76,38 +79,38 @@ body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px
}
}
else
webView_.frame = webViewRect;
_webView.frame = webViewRect;
NSString *deviceWidth = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? [NSString stringWithFormat:@"%.0f", CGRectGetWidth(self.bounds)] : @"device-width";
//HockeySDKLog(@"%@\n%@\%@", PSWebTableViewCellHtmlTemplate, deviceWidth, self.webViewContent);
NSString *contentHtml = [NSString stringWithFormat:PSWebTableViewCellHtmlTemplate, deviceWidth, self.webViewContent];
[webView_ loadHTMLString:contentHtml baseURL:nil];
NSString *contentHtml = [NSString stringWithFormat:BITWebTableViewCellHtmlTemplate, deviceWidth, self.webViewContent];
[_webView loadHTMLString:contentHtml baseURL:nil];
}
}
- (void)showWebView {
webView_.hidden = NO;
_webView.hidden = NO;
self.textLabel.text = @"";
[self setNeedsDisplay];
}
- (void)removeWebView {
if(webView_) {
webView_.delegate = nil;
[webView_ resignFirstResponder];
[webView_ removeFromSuperview];
[webView_ release];
if(_webView) {
_webView.delegate = nil;
[_webView resignFirstResponder];
[_webView removeFromSuperview];
[_webView release];
}
webView_ = nil;
_webView = nil;
[self setNeedsDisplay];
}
- (void)setWebViewContent:(NSString *)aWebViewContent {
if (webViewContent_ != aWebViewContent) {
[webViewContent_ release];
webViewContent_ = [aWebViewContent retain];
if (_webViewContent != aWebViewContent) {
[_webViewContent release];
_webViewContent = [aWebViewContent retain];
// add basic accessiblity (prevents "snarfed from ivar layout") logs
self.accessibilityLabel = aWebViewContent;
@ -126,7 +129,7 @@ body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px
- (void)dealloc {
[self removeWebView];
[webViewContent_ release];
[_webViewContent release], _webViewContent = nil;;
[super dealloc];
}
@ -163,18 +166,18 @@ body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px
- (void)webViewDidFinishLoad:(UIWebView *)webView {
if(webViewContent_)
if(_webViewContent)
[self showWebView];
CGRect frame = webView_.frame;
CGRect frame = _webView.frame;
frame.size.height = 1;
webView_.frame = frame;
CGSize fittingSize = [webView_ sizeThatFits:CGSizeZero];
_webView.frame = frame;
CGSize fittingSize = [_webView sizeThatFits:CGSizeZero];
frame.size = fittingSize;
webView_.frame = frame;
_webView.frame = frame;
// sizeThatFits is not reliable - use javascript for optimal height
NSString *output = [webView_ stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"];
NSString *output = [_webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight;"];
self.webViewSize = CGSizeMake(fittingSize.width, [output integerValue]);
}

View File

@ -1,39 +0,0 @@
//
// Created by Peter Steinberger on 09.01.11.
// Copyright (c) 2011-2012 Peter Steinberger. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <UIKit/UIKit.h>
@interface PSAppStoreHeader : UIView {
NSString *headerLabel_;
NSString *middleHeaderLabel_;
NSString *subHeaderLabel;
UIImage *iconImage_;
UIImage *reflectedImage_;
}
@property (nonatomic, copy) NSString *headerLabel;
@property (nonatomic, copy) NSString *middleHeaderLabel;
@property (nonatomic, copy) NSString *subHeaderLabel;
@property (nonatomic, retain) UIImage *iconImage;
@end

View File

@ -1,165 +0,0 @@
//
// Created by Peter Steinberger on 09.01.11.
// Copyright (c) 2011-2012 Peter Steinberger. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "PSAppStoreHeader.h"
#import "BITHockeyHelper.h"
#import "HockeySDKPrivate.h"
#define BIT_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
#define kLightGrayColor BIT_RGBCOLOR(200, 202, 204)
#define kDarkGrayColor BIT_RGBCOLOR(140, 141, 142)
#define kImageHeight 57
#define kReflectionHeight 20
#define kImageBorderRadius 10
#define kImageMargin 8
#define kTextRow kImageMargin*2 + kImageHeight
@implementation PSAppStoreHeader
@synthesize headerLabel = headerLabel_;
@synthesize middleHeaderLabel = middleHeaderLabel_;
@synthesize subHeaderLabel;
@synthesize iconImage = iconImage_;
#pragma mark - NSObject
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
self.backgroundColor = kLightGrayColor;
}
return self;
}
- (void)dealloc {
[headerLabel_ release];
[middleHeaderLabel_ release];
[subHeaderLabel release];
[iconImage_ release];
[super dealloc];
}
#pragma mark - UIView
- (void)drawRect:(CGRect)rect {
CGRect bounds = self.bounds;
CGFloat globalWidth = self.frame.size.width;
CGContextRef context = UIGraphicsGetCurrentContext();
// draw the gradient
NSArray *colors = [NSArray arrayWithObjects:(id)kDarkGrayColor.CGColor, (id)kLightGrayColor.CGColor, nil];
CGGradientRef gradient = CGGradientCreateWithColors(CGColorGetColorSpace((CGColorRef)[colors objectAtIndex:0]), (CFArrayRef)colors, (CGFloat[2]){0, 1});
CGPoint top = CGPointMake(CGRectGetMidX(bounds), bounds.origin.y);
CGPoint bottom = CGPointMake(CGRectGetMidX(bounds), CGRectGetMaxY(bounds)-kReflectionHeight);
CGContextDrawLinearGradient(context, gradient, top, bottom, 0);
CGGradientRelease(gradient);
// draw header name
UIColor *mainTextColor = BIT_RGBCOLOR(0,0,0);
UIColor *secondaryTextColor = BIT_RGBCOLOR(48,48,48);
UIFont *mainFont = [UIFont boldSystemFontOfSize:20];
UIFont *secondaryFont = [UIFont boldSystemFontOfSize:12];
UIFont *smallFont = [UIFont systemFontOfSize:12];
float myColorValues[] = {255, 255, 255, .6};
CGColorSpaceRef myColorSpace = CGColorSpaceCreateDeviceRGB();
CGColorRef myColor = CGColorCreate(myColorSpace, myColorValues);
// icon
[iconImage_ drawAtPoint:CGPointMake(kImageMargin, kImageMargin)];
[reflectedImage_ drawAtPoint:CGPointMake(kImageMargin, kImageMargin+kImageHeight)];
// shadows are a beast
NSInteger shadowOffset = 2;
if([[UIScreen mainScreen] scale] == 2) shadowOffset = 1;
BITHOCKEY_IF_IOS5_OR_GREATER(shadowOffset = 1;) // iOS5 changes this - again!
CGContextSetShadowWithColor(context, CGSizeMake(shadowOffset, shadowOffset), 0, myColor);
[mainTextColor set];
[headerLabel_ drawInRect:CGRectMake(kTextRow, kImageMargin, globalWidth-kTextRow, 20) withFont:mainFont lineBreakMode:UILineBreakModeTailTruncation];
// middle
[secondaryTextColor set];
[middleHeaderLabel_ drawInRect:CGRectMake(kTextRow, kImageMargin + 25, globalWidth-kTextRow, 20) withFont:secondaryFont lineBreakMode:UILineBreakModeTailTruncation];
CGContextSetShadowWithColor(context, CGSizeZero, 0, nil);
// sub
[secondaryTextColor set];
[subHeaderLabel drawAtPoint:CGPointMake(kTextRow, kImageMargin+kImageHeight-12) forWidth:globalWidth-kTextRow withFont:smallFont lineBreakMode:UILineBreakModeTailTruncation];
CGColorRelease(myColor);
CGColorSpaceRelease(myColorSpace);
}
#pragma mark - Properties
- (void)setHeaderLabel:(NSString *)anHeaderLabel {
if (headerLabel_ != anHeaderLabel) {
[headerLabel_ release];
headerLabel_ = [anHeaderLabel copy];
[self setNeedsDisplay];
}
}
- (void)setMiddleHeaderLabel:(NSString *)aMiddleHeaderLabel {
if (middleHeaderLabel_ != aMiddleHeaderLabel) {
[middleHeaderLabel_ release];
middleHeaderLabel_ = [aMiddleHeaderLabel copy];
[self setNeedsDisplay];
}
}
- (void)setSubHeaderLabel:(NSString *)aSubHeaderLabel {
if (subHeaderLabel != aSubHeaderLabel) {
[subHeaderLabel release];
subHeaderLabel = [aSubHeaderLabel copy];
[self setNeedsDisplay];
}
}
- (void)setIconImage:(UIImage *)anIconImage {
if (iconImage_ != anIconImage) {
[iconImage_ release];
// scale, make borders and reflection
iconImage_ = bit_imageToFitSize(anIconImage, CGSizeMake(kImageHeight, kImageHeight), YES);
iconImage_ = [bit_roundedCornerImage(iconImage_, kImageBorderRadius, 0.0) retain];
// create reflected image
[reflectedImage_ release];
reflectedImage_ = nil;
if (anIconImage) {
reflectedImage_ = [bit_reflectedImageWithHeight(iconImage_, kReflectionHeight, 0.5, 0.0) retain];
}
[self setNeedsDisplay];
}
}
@end

View File

@ -1,78 +0,0 @@
//
// Created by Peter Steinberger on 09.01.11.
// Copyright 2011-2012 Peter Steinberger. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <QuartzCore/QuartzCore.h>
#import <UIKit/UIKit.h>
// defines a button action set (data container)
@interface PSStoreButtonData : NSObject {
CGPoint customPadding_;
NSString *label_;
NSArray *colors_;
BOOL enabled_;
}
+ (id)dataWithLabel:(NSString*)aLabel colors:(NSArray*)aColors enabled:(BOOL)flag;
@property (nonatomic, copy) NSString *label;
@property (nonatomic, retain) NSArray *colors;
@property (nonatomic, assign, getter=isEnabled) BOOL enabled;
@end
@class PSStoreButton;
@protocol PSStoreButtonDelegate
- (void)storeButtonFired:(PSStoreButton *)button;
@end
// Simulate the Paymeny-Button from the AppStore
// The interface is flexible, so there is now fixed order
@interface PSStoreButton : UIButton {
PSStoreButtonData *buttonData_;
id<PSStoreButtonDelegate> buttonDelegate_;
CAGradientLayer *gradient_;
CGPoint customPadding_;
}
- (id)initWithFrame:(CGRect)frame;
- (id)initWithPadding:(CGPoint)padding;
// action delegate
@property (nonatomic, assign) id<PSStoreButtonDelegate> buttonDelegate;
// change the button layer
@property (nonatomic, retain) PSStoreButtonData *buttonData;
- (void)setButtonData:(PSStoreButtonData *)aButtonData animated:(BOOL)animated;
// align helper
@property (nonatomic, assign) CGPoint customPadding;
- (void)alignToSuperview;
// helpers to mimic an AppStore button
+ (NSArray *)appStoreGreenColor;
+ (NSArray *)appStoreBlueColor;
+ (NSArray *)appStoreGrayColor;
@end

View File

@ -1,41 +0,0 @@
//
// Created by Peter Steinberger on 04.02.11.
// Copyright 2011-2012 Peter Steinberger. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
@interface PSWebTableViewCell : UITableViewCell <UIWebViewDelegate> {
UIWebView *webView_;
NSString *webViewContent_;
CGSize webViewSize_;
UIColor *cellBackgroundColor_;
}
@property (nonatomic, retain) UIWebView *webView;
@property (nonatomic, copy) NSString *webViewContent;
@property (nonatomic, assign) CGSize webViewSize;
@property (nonatomic, retain) UIColor *cellBackgroundColor;
- (void)addWebView;
@end

View File

@ -63,12 +63,12 @@
1E49A4BB161222B900463151 /* BITHockeyBaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4A4161222B900463151 /* BITHockeyBaseViewController.m */; };
1E49A4BE161222B900463151 /* BITHockeyHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4A5161222B900463151 /* BITHockeyHelper.h */; };
1E49A4C1161222B900463151 /* BITHockeyHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4A6161222B900463151 /* BITHockeyHelper.m */; };
1E49A4C4161222B900463151 /* PSAppStoreHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4A7161222B900463151 /* PSAppStoreHeader.h */; };
1E49A4C7161222B900463151 /* PSAppStoreHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4A8161222B900463151 /* PSAppStoreHeader.m */; };
1E49A4CA161222B900463151 /* PSStoreButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4A9161222B900463151 /* PSStoreButton.h */; };
1E49A4CD161222B900463151 /* PSStoreButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4AA161222B900463151 /* PSStoreButton.m */; };
1E49A4D0161222B900463151 /* PSWebTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4AB161222B900463151 /* PSWebTableViewCell.h */; };
1E49A4D3161222B900463151 /* PSWebTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4AC161222B900463151 /* PSWebTableViewCell.m */; };
1E49A4C4161222B900463151 /* BITAppStoreHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4A7161222B900463151 /* BITAppStoreHeader.h */; };
1E49A4C7161222B900463151 /* BITAppStoreHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4A8161222B900463151 /* BITAppStoreHeader.m */; };
1E49A4CA161222B900463151 /* BITStoreButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4A9161222B900463151 /* BITStoreButton.h */; };
1E49A4CD161222B900463151 /* BITStoreButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4AA161222B900463151 /* BITStoreButton.m */; };
1E49A4D0161222B900463151 /* BITWebTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4AB161222B900463151 /* BITWebTableViewCell.h */; };
1E49A4D3161222B900463151 /* BITWebTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4AC161222B900463151 /* BITWebTableViewCell.m */; };
1E49A4D8161222D400463151 /* HockeySDKPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4D4161222D400463151 /* HockeySDKPrivate.h */; };
1E49A4DB161222D400463151 /* HockeySDKPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4D5161222D400463151 /* HockeySDKPrivate.m */; };
1E5954D315B6F24A00A03429 /* BITHockeyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB466148D7BF50015DEDC /* BITHockeyManager.m */; };
@ -151,12 +151,12 @@
1E49A4A4161222B900463151 /* BITHockeyBaseViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITHockeyBaseViewController.m; sourceTree = "<group>"; };
1E49A4A5161222B900463151 /* BITHockeyHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyHelper.h; sourceTree = "<group>"; };
1E49A4A6161222B900463151 /* BITHockeyHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITHockeyHelper.m; sourceTree = "<group>"; };
1E49A4A7161222B900463151 /* PSAppStoreHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSAppStoreHeader.h; sourceTree = "<group>"; };
1E49A4A8161222B900463151 /* PSAppStoreHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSAppStoreHeader.m; sourceTree = "<group>"; };
1E49A4A9161222B900463151 /* PSStoreButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSStoreButton.h; sourceTree = "<group>"; };
1E49A4AA161222B900463151 /* PSStoreButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSStoreButton.m; sourceTree = "<group>"; };
1E49A4AB161222B900463151 /* PSWebTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSWebTableViewCell.h; sourceTree = "<group>"; };
1E49A4AC161222B900463151 /* PSWebTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PSWebTableViewCell.m; sourceTree = "<group>"; };
1E49A4A7161222B900463151 /* BITAppStoreHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITAppStoreHeader.h; sourceTree = "<group>"; };
1E49A4A8161222B900463151 /* BITAppStoreHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITAppStoreHeader.m; sourceTree = "<group>"; };
1E49A4A9161222B900463151 /* BITStoreButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITStoreButton.h; sourceTree = "<group>"; };
1E49A4AA161222B900463151 /* BITStoreButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITStoreButton.m; sourceTree = "<group>"; };
1E49A4AB161222B900463151 /* BITWebTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITWebTableViewCell.h; sourceTree = "<group>"; };
1E49A4AC161222B900463151 /* BITWebTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITWebTableViewCell.m; sourceTree = "<group>"; };
1E49A4D4161222D400463151 /* HockeySDKPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HockeySDKPrivate.h; sourceTree = "<group>"; };
1E49A4D5161222D400463151 /* HockeySDKPrivate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HockeySDKPrivate.m; sourceTree = "<group>"; };
1E5954F215B6F24A00A03429 /* libHockeySDK.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libHockeySDK.a; sourceTree = BUILT_PRODUCTS_DIR; };
@ -274,12 +274,12 @@
1E49A4A6161222B900463151 /* BITHockeyHelper.m */,
1EACC979162F041E007578C5 /* BITAttributedLabel.h */,
1EACC97A162F041E007578C5 /* BITAttributedLabel.m */,
1E49A4A7161222B900463151 /* PSAppStoreHeader.h */,
1E49A4A8161222B900463151 /* PSAppStoreHeader.m */,
1E49A4A9161222B900463151 /* PSStoreButton.h */,
1E49A4AA161222B900463151 /* PSStoreButton.m */,
1E49A4AB161222B900463151 /* PSWebTableViewCell.h */,
1E49A4AC161222B900463151 /* PSWebTableViewCell.m */,
1E49A4A7161222B900463151 /* BITAppStoreHeader.h */,
1E49A4A8161222B900463151 /* BITAppStoreHeader.m */,
1E49A4A9161222B900463151 /* BITStoreButton.h */,
1E49A4AA161222B900463151 /* BITStoreButton.m */,
1E49A4AB161222B900463151 /* BITWebTableViewCell.h */,
1E49A4AC161222B900463151 /* BITWebTableViewCell.m */,
);
name = Helper;
sourceTree = "<group>";
@ -430,9 +430,9 @@
1E49A4B5161222B900463151 /* BITHockeyBaseManagerPrivate.h in Headers */,
1E49A4B8161222B900463151 /* BITHockeyBaseViewController.h in Headers */,
1E49A4BE161222B900463151 /* BITHockeyHelper.h in Headers */,
1E49A4C4161222B900463151 /* PSAppStoreHeader.h in Headers */,
1E49A4CA161222B900463151 /* PSStoreButton.h in Headers */,
1E49A4D0161222B900463151 /* PSWebTableViewCell.h in Headers */,
1E49A4C4161222B900463151 /* BITAppStoreHeader.h in Headers */,
1E49A4CA161222B900463151 /* BITStoreButton.h in Headers */,
1E49A4D0161222B900463151 /* BITWebTableViewCell.h in Headers */,
1E49A4D8161222D400463151 /* HockeySDKPrivate.h in Headers */,
1EC69F601615001500808FD9 /* BITHockeyManagerPrivate.h in Headers */,
1E754E5C1621FBB70070AB92 /* BITCrashManager.h in Headers */,
@ -596,9 +596,9 @@
1E49A4B2161222B900463151 /* BITHockeyBaseManager.m in Sources */,
1E49A4BB161222B900463151 /* BITHockeyBaseViewController.m in Sources */,
1E49A4C1161222B900463151 /* BITHockeyHelper.m in Sources */,
1E49A4C7161222B900463151 /* PSAppStoreHeader.m in Sources */,
1E49A4CD161222B900463151 /* PSStoreButton.m in Sources */,
1E49A4D3161222B900463151 /* PSWebTableViewCell.m in Sources */,
1E49A4C7161222B900463151 /* BITAppStoreHeader.m in Sources */,
1E49A4CD161222B900463151 /* BITStoreButton.m in Sources */,
1E49A4D3161222B900463151 /* BITWebTableViewCell.m in Sources */,
1E49A4DB161222D400463151 /* HockeySDKPrivate.m in Sources */,
1E754E5D1621FBB70070AB92 /* BITCrashManager.m in Sources */,
1E754E611621FBB70070AB92 /* BITCrashReportTextFormatter.m in Sources */,