Refactoring
- Change Prefixes to BIT - Make one shared instance and change the functionalities to modules - One bundle for resources - Targets for framework and static libs - Other cleanup
53
Classes/BITAppVersionMetaInfo.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Author: Peter Steinberger
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* Copyright (c) 2011 Andreas Linde, 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>
|
||||
|
||||
@interface BITAppVersionMetaInfo : NSObject {
|
||||
}
|
||||
@property (nonatomic, copy) NSString *name;
|
||||
@property (nonatomic, copy) NSString *version;
|
||||
@property (nonatomic, copy) NSString *shortVersion;
|
||||
@property (nonatomic, copy) NSString *notes;
|
||||
@property (nonatomic, copy) NSDate *date;
|
||||
@property (nonatomic, copy) NSNumber *size;
|
||||
@property (nonatomic, copy) NSNumber *mandatory;
|
||||
|
||||
- (NSString *)nameAndVersionString;
|
||||
- (NSString *)versionString;
|
||||
- (NSString *)dateString;
|
||||
- (NSString *)sizeInMB;
|
||||
- (NSString *)notesOrEmptyString;
|
||||
- (void)setDateWithTimestamp:(NSTimeInterval)timestamp;
|
||||
- (BOOL)isValid;
|
||||
- (BOOL)isEqualToAppVersionMetaInfo:(BITAppVersionMetaInfo *)anAppVersionMetaInfo;
|
||||
|
||||
+ (BITAppVersionMetaInfo *)appVersionMetaInfoFromDict:(NSDictionary *)dict;
|
||||
|
||||
@end
|
186
Classes/BITAppVersionMetaInfo.m
Normal file
@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Author: Peter Steinberger
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* Copyright (c) 2011 Andreas Linde, 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 "BITAppVersionMetaInfo.h"
|
||||
#import "HockeySDKPrivate.h"
|
||||
|
||||
|
||||
@implementation BITAppVersionMetaInfo
|
||||
|
||||
@synthesize name = _name;
|
||||
@synthesize version = _version;
|
||||
@synthesize shortVersion = _shortVersion;
|
||||
@synthesize notes = _notes;
|
||||
@synthesize date = _date;
|
||||
@synthesize size = _size;
|
||||
@synthesize mandatory = _mandatory;
|
||||
|
||||
|
||||
#pragma mark - Static
|
||||
|
||||
+ (BITAppVersionMetaInfo *)appVersionMetaInfoFromDict:(NSDictionary *)dict {
|
||||
BITAppVersionMetaInfo *appVersionMetaInfo = [[[[self class] alloc] init] autorelease];
|
||||
|
||||
if ([dict isKindOfClass:[NSDictionary class]]) {
|
||||
appVersionMetaInfo.name = [dict objectForKey:@"title"];
|
||||
appVersionMetaInfo.version = [dict objectForKey:@"version"];
|
||||
appVersionMetaInfo.shortVersion = [dict objectForKey:@"shortversion"];
|
||||
[appVersionMetaInfo setDateWithTimestamp:[[dict objectForKey:@"timestamp"] doubleValue]];
|
||||
appVersionMetaInfo.size = [dict objectForKey:@"appsize"];
|
||||
appVersionMetaInfo.notes = [dict objectForKey:@"notes"];
|
||||
appVersionMetaInfo.mandatory = [dict objectForKey:@"mandatory"];
|
||||
}
|
||||
|
||||
return appVersionMetaInfo;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - NSObject
|
||||
|
||||
- (void)dealloc {
|
||||
[_name release];
|
||||
[_version release];
|
||||
[_shortVersion release];
|
||||
[_notes release];
|
||||
[_date release];
|
||||
[_size release];
|
||||
[_mandatory release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other {
|
||||
if (other == self)
|
||||
return YES;
|
||||
if (!other || ![other isKindOfClass:[self class]])
|
||||
return NO;
|
||||
return [self isEqualToAppVersionMetaInfo:other];
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToAppVersionMetaInfo:(BITAppVersionMetaInfo *)anAppVersionMetaInfo {
|
||||
if (self == anAppVersionMetaInfo)
|
||||
return YES;
|
||||
if (self.name != anAppVersionMetaInfo.name && ![self.name isEqualToString:anAppVersionMetaInfo.name])
|
||||
return NO;
|
||||
if (self.version != anAppVersionMetaInfo.version && ![self.version isEqualToString:anAppVersionMetaInfo.version])
|
||||
return NO;
|
||||
if (self.shortVersion != anAppVersionMetaInfo.shortVersion && ![self.shortVersion isEqualToString:anAppVersionMetaInfo.shortVersion])
|
||||
return NO;
|
||||
if (self.notes != anAppVersionMetaInfo.notes && ![self.notes isEqualToString:anAppVersionMetaInfo.notes])
|
||||
return NO;
|
||||
if (self.date != anAppVersionMetaInfo.date && ![self.date isEqualToDate:anAppVersionMetaInfo.date])
|
||||
return NO;
|
||||
if (self.size != anAppVersionMetaInfo.size && ![self.size isEqualToNumber:anAppVersionMetaInfo.size])
|
||||
return NO;
|
||||
if (self.mandatory != anAppVersionMetaInfo.mandatory && ![self.mandatory isEqualToNumber:anAppVersionMetaInfo.mandatory])
|
||||
return NO;
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - NSCoder
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)encoder {
|
||||
[encoder encodeObject:self.name forKey:@"name"];
|
||||
[encoder encodeObject:self.version forKey:@"version"];
|
||||
[encoder encodeObject:self.shortVersion forKey:@"shortVersion"];
|
||||
[encoder encodeObject:self.notes forKey:@"notes"];
|
||||
[encoder encodeObject:self.date forKey:@"date"];
|
||||
[encoder encodeObject:self.size forKey:@"size"];
|
||||
[encoder encodeObject:self.mandatory forKey:@"mandatory"];
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)decoder {
|
||||
if ((self = [super init])) {
|
||||
self.name = [decoder decodeObjectForKey:@"name"];
|
||||
self.version = [decoder decodeObjectForKey:@"version"];
|
||||
self.shortVersion = [decoder decodeObjectForKey:@"shortVersion"];
|
||||
self.notes = [decoder decodeObjectForKey:@"notes"];
|
||||
self.date = [decoder decodeObjectForKey:@"date"];
|
||||
self.size = [decoder decodeObjectForKey:@"size"];
|
||||
self.mandatory = [decoder decodeObjectForKey:@"mandatory"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (NSString *)nameAndVersionString {
|
||||
NSString *appNameAndVersion = [NSString stringWithFormat:@"%@ %@", self.name, [self versionString]];
|
||||
return appNameAndVersion;
|
||||
}
|
||||
|
||||
- (NSString *)versionString {
|
||||
NSString *shortString = ([self.shortVersion respondsToSelector:@selector(length)] && [self.shortVersion length]) ? [NSString stringWithFormat:@"%@", self.shortVersion] : @"";
|
||||
NSString *versionString = [shortString length] ? [NSString stringWithFormat:@" (%@)", self.version] : self.version;
|
||||
return [NSString stringWithFormat:@"%@ %@%@", BITHockeySDKLocalizedString(@"UpdateVersion"), shortString, versionString];
|
||||
}
|
||||
|
||||
- (NSString *)dateString {
|
||||
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
|
||||
[formatter setDateStyle:NSDateFormatterMediumStyle];
|
||||
|
||||
return [formatter stringFromDate:self.date];
|
||||
}
|
||||
|
||||
- (NSString *)sizeInMB {
|
||||
if ([_size isKindOfClass: [NSNumber class]] && [_size doubleValue] > 0) {
|
||||
double appSizeInMB = [_size doubleValue]/(1024*1024);
|
||||
NSString *appSizeString = [NSString stringWithFormat:@"%.1f MB", appSizeInMB];
|
||||
return appSizeString;
|
||||
}
|
||||
|
||||
return @"0 MB";
|
||||
}
|
||||
|
||||
- (void)setDateWithTimestamp:(NSTimeInterval)timestamp {
|
||||
if (timestamp) {
|
||||
NSDate *appDate = [NSDate dateWithTimeIntervalSince1970:timestamp];
|
||||
self.date = appDate;
|
||||
} else {
|
||||
self.date = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)notesOrEmptyString {
|
||||
if (self.notes) {
|
||||
return self.notes;
|
||||
}else {
|
||||
return [NSString string];
|
||||
}
|
||||
}
|
||||
|
||||
// a valid app needs at least following properties: name, version, date
|
||||
- (BOOL)isValid {
|
||||
BOOL valid = [self.name length] && [self.version length] && self.date;
|
||||
return valid;
|
||||
}
|
||||
|
||||
@end
|
116
Classes/BITCrashManager.h
Normal file
@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
* Kent Sutherland
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* Copyright (c) 2011 Andreas Linde & Kent Sutherland.
|
||||
* 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>
|
||||
|
||||
|
||||
typedef enum BITCrashAlertType {
|
||||
BITCrashAlertTypeSend = 0,
|
||||
BITCrashAlertTypeFeedback = 1,
|
||||
} BITCrashAlertType;
|
||||
|
||||
typedef enum BITCrashStatus {
|
||||
BITCrashStatusQueued = -80,
|
||||
BITCrashStatusUnknown = 0,
|
||||
BITCrashStatusAssigned = 1,
|
||||
BITCrashStatusSubmitted = 2,
|
||||
BITCrashStatusAvailable = 3,
|
||||
} BITCrashStatus;
|
||||
|
||||
|
||||
@protocol BITCrashManagerDelegate;
|
||||
|
||||
@interface BITCrashManager : NSObject {
|
||||
id <BITCrashManagerDelegate> _delegate;
|
||||
|
||||
NSString *_appIdentifier;
|
||||
|
||||
NSString *_feedbackRequestID;
|
||||
float _feedbackDelayInterval;
|
||||
|
||||
NSMutableString *_contentOfProperty;
|
||||
BITCrashStatus _serverResult;
|
||||
|
||||
int _analyzerStarted;
|
||||
NSString *_crashesDir;
|
||||
NSFileManager *_fileManager;
|
||||
|
||||
BOOL _crashIdenticalCurrentVersion;
|
||||
BOOL _crashReportActivated;
|
||||
|
||||
NSMutableArray *_crashFiles;
|
||||
|
||||
NSMutableData *_responseData;
|
||||
NSInteger _statusCode;
|
||||
|
||||
NSURLConnection *_urlConnection;
|
||||
|
||||
NSData *_crashData;
|
||||
|
||||
BOOL _sendingInProgress;
|
||||
}
|
||||
|
||||
// delegate is optional
|
||||
@property (nonatomic, assign) id <BITCrashManagerDelegate> delegate;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// settings
|
||||
|
||||
/** Define the users name or userid that should be send along each crash report
|
||||
*/
|
||||
@property (nonatomic, copy) NSString *userName;
|
||||
|
||||
/** Define the users email address that should be send along each crash report
|
||||
*/
|
||||
@property (nonatomic, copy) NSString *userEmail;
|
||||
|
||||
// if YES, the user will get the option to choose "Always" for sending crash reports. This will cause the dialog not to show the alert description text landscape mode! (default)
|
||||
// if NO, the dialog will not show a "Always" button
|
||||
@property (nonatomic, assign, getter=isShowingAlwaysButton) BOOL showAlwaysButton;
|
||||
|
||||
// if YES, the user will be presented with a status of the crash, if known
|
||||
// if NO, the user will not see any feedback information (default)
|
||||
@property (nonatomic, assign, getter=isFeedbackActivated) BOOL feedbackActivated;
|
||||
|
||||
// if YES, the crash report will be submitted without asking the user
|
||||
// if NO, the user will be asked if the crash report can be submitted (default)
|
||||
@property (nonatomic, assign, getter=isAutoSubmitCrashReport) BOOL autoSubmitCrashReport;
|
||||
|
||||
// will return YES if the last session crashed, to e.g. make sure a "rate my app" alert will not show up
|
||||
@property (nonatomic, readonly) BOOL didCrashInLastSession;
|
||||
|
||||
// will return the timeinterval from startup to the crash in seconds, default is -1
|
||||
@property (nonatomic, readonly) NSTimeInterval timeintervalCrashInLastSessionOccured;
|
||||
|
||||
- (id)initWithAppIdentifier:(NSString *)appIdentifier;
|
||||
|
||||
- (void)startManager;
|
||||
|
||||
@end
|
@ -2,6 +2,7 @@
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
* Kent Sutherland
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* Copyright (c) 2011 Andreas Linde & Kent Sutherland.
|
||||
* All rights reserved.
|
||||
*
|
||||
@ -30,120 +31,60 @@
|
||||
#import <CrashReporter/CrashReporter.h>
|
||||
#import <SystemConfiguration/SystemConfiguration.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "BWGlobal.h"
|
||||
#import "BWQuincyManager.h"
|
||||
#import "CNSCrashReportTextFormatter.h"
|
||||
#import "HockeySDK.h"
|
||||
#import "HockeySDKPrivate.h"
|
||||
|
||||
#import "BITCrashReportTextFormatter.h"
|
||||
|
||||
#include <sys/sysctl.h>
|
||||
#include <inttypes.h> //needed for PRIx64 macro
|
||||
|
||||
// hockey api error domain
|
||||
typedef enum {
|
||||
QuincyErrorUnknown,
|
||||
QuincyAPIAppVersionRejected,
|
||||
QuincyAPIReceivedEmptyResponse,
|
||||
QuincyAPIErrorWithStatusCode
|
||||
} HockeyErrorReason;
|
||||
static NSString *kQuincyErrorDomain = @"QuincyErrorDomain";
|
||||
|
||||
NSBundle *quincyBundle(void) {
|
||||
static NSBundle* bundle = nil;
|
||||
if (!bundle) {
|
||||
NSString* path = [[[NSBundle mainBundle] resourcePath]
|
||||
stringByAppendingPathComponent:kQuincyBundleName];
|
||||
bundle = [[NSBundle bundleWithPath:path] retain];
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
if ([BWQuincyManager sharedQuincyManager].languageStyle == nil)
|
||||
return NSLocalizedStringFromTableInBundle(stringToken, @"Quincy", quincyBundle(), @"");
|
||||
else {
|
||||
NSString *alternate = [NSString stringWithFormat:@"Quincy%@", [BWQuincyManager sharedQuincyManager].languageStyle];
|
||||
return NSLocalizedStringFromTableInBundle(stringToken, alternate, quincyBundle(), @"");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@interface BWQuincyManager ()
|
||||
// flags if the crashlog analyzer is started. since this may theoretically crash we need to track it
|
||||
#define kBITCrashAnalyzerStarted @"HockeySDKCrashAnalyzerStarted"
|
||||
|
||||
- (void)startManager;
|
||||
// stores the set of crashreports that have been approved but aren't sent yet
|
||||
#define kBITCrashApprovedReports @"HockeySDKCrashApprovedReports"
|
||||
|
||||
- (void)showCrashStatusMessage;
|
||||
// stores the user name entered in the UI
|
||||
#define kBITCrashUserName @"HockeySDKCrashUserName"
|
||||
|
||||
- (void)handleCrashReport;
|
||||
- (void)_cleanCrashReports;
|
||||
// stores the user email address entered in the UI
|
||||
#define kBITCrashUserEmail @"HockeySDKCrashUserEmail"
|
||||
|
||||
- (void)_checkForFeedbackStatus;
|
||||
|
||||
- (void)_performSendingCrashReports;
|
||||
- (void)_sendCrashReports;
|
||||
|
||||
- (void)_postXML:(NSString*)xml toURL:(NSURL*)url;
|
||||
- (NSString *)_getDevicePlatform;
|
||||
|
||||
- (BOOL)hasNonApprovedCrashReports;
|
||||
- (BOOL)hasPendingCrashReport;
|
||||
@interface BITCrashManager ()
|
||||
|
||||
@property (nonatomic, retain) NSFileManager *fileManager;
|
||||
|
||||
@end
|
||||
|
||||
@implementation BWQuincyManager
|
||||
@implementation BITCrashManager
|
||||
|
||||
@synthesize delegate = _delegate;
|
||||
@synthesize submissionURL = _submissionURL;
|
||||
@synthesize showAlwaysButton = _showAlwaysButton;
|
||||
@synthesize feedbackActivated = _feedbackActivated;
|
||||
@synthesize autoSubmitCrashReport = _autoSubmitCrashReport;
|
||||
@synthesize languageStyle = _languageStyle;
|
||||
@synthesize didCrashInLastSession = _didCrashInLastSession;
|
||||
@synthesize timeintervalCrashInLastSessionOccured = _timeintervalCrashInLastSessionOccured;
|
||||
@synthesize loggingEnabled = _loggingEnabled;
|
||||
|
||||
@synthesize appIdentifier = _appIdentifier;
|
||||
|
||||
@synthesize fileManager = _fileManager;
|
||||
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 40000
|
||||
+(BWQuincyManager *)sharedQuincyManager {
|
||||
static BWQuincyManager *sharedInstance = nil;
|
||||
static dispatch_once_t pred;
|
||||
|
||||
dispatch_once(&pred, ^{
|
||||
sharedInstance = [BWQuincyManager alloc];
|
||||
sharedInstance = [sharedInstance init];
|
||||
});
|
||||
|
||||
return sharedInstance;
|
||||
}
|
||||
#else
|
||||
+ (BWQuincyManager *)sharedQuincyManager {
|
||||
static BWQuincyManager *quincyManager = nil;
|
||||
|
||||
if (quincyManager == nil) {
|
||||
quincyManager = [[BWQuincyManager alloc] init];
|
||||
}
|
||||
|
||||
return quincyManager;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (id) init {
|
||||
- (id)initWithAppIdentifier:(NSString *)appIdentifier {
|
||||
if ((self = [super init])) {
|
||||
_serverResult = CrashReportStatusUnknown;
|
||||
BITHockeySDKLog(@"Initializing CrashReporter");
|
||||
|
||||
_appIdentifier = appIdentifier;
|
||||
|
||||
_delegate = nil;
|
||||
_serverResult = BITCrashStatusUnknown;
|
||||
_crashIdenticalCurrentVersion = YES;
|
||||
_crashData = nil;
|
||||
_urlConnection = nil;
|
||||
_submissionURL = nil;
|
||||
_responseData = nil;
|
||||
_appIdentifier = nil;
|
||||
_sendingInProgress = NO;
|
||||
_languageStyle = nil;
|
||||
_didCrashInLastSession = NO;
|
||||
_timeintervalCrashInLastSessionOccured = -1;
|
||||
_loggingEnabled = NO;
|
||||
_fileManager = [[NSFileManager alloc] init];
|
||||
|
||||
self.delegate = nil;
|
||||
@ -151,20 +92,20 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
self.showAlwaysButton = NO;
|
||||
self.autoSubmitCrashReport = NO;
|
||||
|
||||
NSString *testValue = [[NSUserDefaults standardUserDefaults] stringForKey:kQuincyKitAnalyzerStarted];
|
||||
NSString *testValue = [[NSUserDefaults standardUserDefaults] stringForKey:kBITCrashAnalyzerStarted];
|
||||
if (testValue) {
|
||||
_analyzerStarted = [[NSUserDefaults standardUserDefaults] integerForKey:kQuincyKitAnalyzerStarted];
|
||||
_analyzerStarted = [[NSUserDefaults standardUserDefaults] integerForKey:kBITCrashAnalyzerStarted];
|
||||
} else {
|
||||
_analyzerStarted = 0;
|
||||
}
|
||||
|
||||
testValue = nil;
|
||||
testValue = [[NSUserDefaults standardUserDefaults] stringForKey:kQuincyKitActivated];
|
||||
testValue = [[NSUserDefaults standardUserDefaults] stringForKey:kBITCrashActivated];
|
||||
if (testValue) {
|
||||
_crashReportActivated = [[NSUserDefaults standardUserDefaults] boolForKey:kQuincyKitActivated];
|
||||
_crashReportActivated = [[NSUserDefaults standardUserDefaults] boolForKey:kBITCrashActivated];
|
||||
} else {
|
||||
_crashReportActivated = YES;
|
||||
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:YES] forKey:kQuincyKitActivated];
|
||||
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithBool:YES] forKey:kBITCrashActivated];
|
||||
}
|
||||
|
||||
if (_crashReportActivated) {
|
||||
@ -192,10 +133,10 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
if (![crashReporter enableCrashReporterAndReturnError: &error])
|
||||
NSLog(@"WARNING: Could not enable crash reporter: %@", error);
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startManager) name:BWQuincyNetworkBecomeReachable object:nil];
|
||||
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(startManager) name:BITHockeyNetworkDidBecomeReachableNotification object:nil];
|
||||
}
|
||||
|
||||
if (!quincyBundle()) {
|
||||
if (!BITHockeySDKBundle()) {
|
||||
NSLog(@"WARNING: Quincy.bundle is missing, will send reports automatically!");
|
||||
}
|
||||
}
|
||||
@ -205,12 +146,7 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
|
||||
- (void) dealloc {
|
||||
self.delegate = nil;
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:BWQuincyNetworkBecomeReachable object:nil];
|
||||
|
||||
[_languageStyle release];
|
||||
|
||||
[_submissionURL release];
|
||||
_submissionURL = nil;
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self name:BITHockeyNetworkDidBecomeReachableNotification object:nil];
|
||||
|
||||
[_appIdentifier release];
|
||||
_appIdentifier = nil;
|
||||
@ -231,35 +167,13 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark setter
|
||||
- (void)setSubmissionURL:(NSString *)anSubmissionURL {
|
||||
if (_submissionURL != anSubmissionURL) {
|
||||
[_submissionURL release];
|
||||
_submissionURL = [anSubmissionURL copy];
|
||||
}
|
||||
|
||||
[self performSelector:@selector(startManager) withObject:nil afterDelay:1.0f];
|
||||
}
|
||||
|
||||
- (void)setAppIdentifier:(NSString *)anAppIdentifier {
|
||||
if (_appIdentifier != anAppIdentifier) {
|
||||
[_appIdentifier release];
|
||||
_appIdentifier = [anAppIdentifier copy];
|
||||
}
|
||||
|
||||
[self setSubmissionURL:@"https://sdk.hockeyapp.net/"];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark private methods
|
||||
#pragma mark - private methods
|
||||
|
||||
- (BOOL)autoSendCrashReports {
|
||||
BOOL result = NO;
|
||||
|
||||
if (!self.autoSubmitCrashReport) {
|
||||
if (self.isShowingAlwaysButton && [[NSUserDefaults standardUserDefaults] boolForKey: kAutomaticallySendCrashReports]) {
|
||||
if (self.isShowingAlwaysButton && [[NSUserDefaults standardUserDefaults] boolForKey: kBITCrashAutomaticallySendReports]) {
|
||||
result = YES;
|
||||
}
|
||||
} else {
|
||||
@ -273,38 +187,84 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
- (void)startManager {
|
||||
if (!_sendingInProgress && [self hasPendingCrashReport]) {
|
||||
_sendingInProgress = YES;
|
||||
if (!quincyBundle()) {
|
||||
NSLog(@"WARNING: Quincy.bundle is missing, sending reports automatically!");
|
||||
[self _sendCrashReports];
|
||||
if (!BITHockeySDKBundle()) {
|
||||
NSLog(@"WARNING: HockeySDKResource.bundle is missing, sending reports automatically!");
|
||||
[self sendCrashReports];
|
||||
} else if (![self autoSendCrashReports] && [self hasNonApprovedCrashReports]) {
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(willShowSubmitCrashReportAlert)]) {
|
||||
[self.delegate willShowSubmitCrashReportAlert];
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReporterWillShowSubmitCrashReportAlert:)]) {
|
||||
[self.delegate crashReporterWillShowSubmitCrashReportAlert:self];
|
||||
}
|
||||
|
||||
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
|
||||
|
||||
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:BWQuincyLocalize(@"CrashDataFoundTitle"), appName]
|
||||
message:[NSString stringWithFormat:BWQuincyLocalize(@"CrashDataFoundDescription"), appName]
|
||||
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:[NSString stringWithFormat:BITHockeySDKLocalizedString(@"CrashDataFoundTitle"), appName]
|
||||
message:[NSString stringWithFormat:BITHockeySDKLocalizedString(@"CrashDataFoundDescription"), appName]
|
||||
delegate:self
|
||||
cancelButtonTitle:BWQuincyLocalize(@"CrashDontSendReport")
|
||||
otherButtonTitles:BWQuincyLocalize(@"CrashSendReport"), nil];
|
||||
cancelButtonTitle:BITHockeySDKLocalizedString(@"CrashDontSendReport")
|
||||
otherButtonTitles:BITHockeySDKLocalizedString(@"CrashSendReport"), nil];
|
||||
|
||||
if ([self isShowingAlwaysButton]) {
|
||||
[alertView addButtonWithTitle:BWQuincyLocalize(@"CrashSendReportAlways")];
|
||||
[alertView addButtonWithTitle:BITHockeySDKLocalizedString(@"CrashSendReportAlways")];
|
||||
}
|
||||
|
||||
[alertView setTag: QuincyKitAlertTypeSend];
|
||||
[alertView setTag: BITCrashAlertTypeSend];
|
||||
[alertView show];
|
||||
[alertView release];
|
||||
} else {
|
||||
[self _sendCrashReports];
|
||||
[self sendCrashReports];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - PLCrashReporter
|
||||
|
||||
//
|
||||
// Called to handle a pending crash report.
|
||||
//
|
||||
- (void) handleCrashReport {
|
||||
PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter];
|
||||
NSError *error = NULL;
|
||||
|
||||
// check if the next call ran successfully the last time
|
||||
if (_analyzerStarted == 0) {
|
||||
// mark the start of the routine
|
||||
_analyzerStarted = 1;
|
||||
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:_analyzerStarted] forKey:kBITCrashAnalyzerStarted];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
// Try loading the crash report
|
||||
_crashData = [[NSData alloc] initWithData:[crashReporter loadPendingCrashReportDataAndReturnError: &error]];
|
||||
|
||||
NSString *cacheFilename = [NSString stringWithFormat: @"%.0f", [NSDate timeIntervalSinceReferenceDate]];
|
||||
|
||||
if (_crashData == nil) {
|
||||
NSLog(@"Could not load crash report: %@", error);
|
||||
} else {
|
||||
[_crashData writeToFile:[_crashesDir stringByAppendingPathComponent: cacheFilename] atomically:YES];
|
||||
|
||||
// get the startup timestamp from the crash report, and the file timestamp to calculate the timeinterval when the crash happened after startup
|
||||
PLCrashReport *report = [[[PLCrashReport alloc] initWithData:_crashData error:&error] autorelease];
|
||||
|
||||
if (report.systemInfo.timestamp && report.applicationInfo.applicationStartupTimestamp) {
|
||||
_timeintervalCrashInLastSessionOccured = [report.systemInfo.timestamp timeIntervalSinceDate:report.applicationInfo.applicationStartupTimestamp];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Purge the report
|
||||
// mark the end of the routine
|
||||
_analyzerStarted = 0;
|
||||
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:_analyzerStarted] forKey:kBITCrashAnalyzerStarted];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
[crashReporter purgePendingCrashReport];
|
||||
return;
|
||||
}
|
||||
|
||||
- (BOOL)hasNonApprovedCrashReports {
|
||||
NSDictionary *approvedCrashReports = [[NSUserDefaults standardUserDefaults] dictionaryForKey: kApprovedCrashReports];
|
||||
NSDictionary *approvedCrashReports = [[NSUserDefaults standardUserDefaults] dictionaryForKey: kBITCrashApprovedReports];
|
||||
|
||||
if (!approvedCrashReports || [approvedCrashReports count] == 0) return YES;
|
||||
|
||||
@ -334,7 +294,7 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
}
|
||||
|
||||
if ([_crashFiles count] > 0) {
|
||||
BWQuincyLog(@"Pending crash reports found.");
|
||||
BITHockeySDKLog(@"Pending crash reports found.");
|
||||
return YES;
|
||||
} else
|
||||
return NO;
|
||||
@ -346,31 +306,31 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
- (void) showCrashStatusMessage {
|
||||
UIAlertView *alertView = nil;
|
||||
|
||||
if (_serverResult >= CrashReportStatusAssigned &&
|
||||
if (_serverResult >= BITCrashStatusAssigned &&
|
||||
_crashIdenticalCurrentVersion &&
|
||||
quincyBundle()) {
|
||||
BITHockeySDKBundle()) {
|
||||
// show some feedback to the user about the crash status
|
||||
NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
|
||||
switch (_serverResult) {
|
||||
case CrashReportStatusAssigned:
|
||||
alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseTitle"), appName ]
|
||||
message: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseNextRelease"), appName]
|
||||
case BITCrashStatusAssigned:
|
||||
alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BITHockeySDKLocalizedString(@"CrashResponseTitle"), appName ]
|
||||
message: [NSString stringWithFormat:BITHockeySDKLocalizedString(@"CrashResponseNextRelease"), appName]
|
||||
delegate: self
|
||||
cancelButtonTitle: BWQuincyLocalize(@"CrashResponseTitleOK")
|
||||
cancelButtonTitle: BITHockeySDKLocalizedString(@"HockeyOK")
|
||||
otherButtonTitles: nil];
|
||||
break;
|
||||
case CrashReportStatusSubmitted:
|
||||
alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseTitle"), appName ]
|
||||
message: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseWaitingApple"), appName]
|
||||
case BITCrashStatusSubmitted:
|
||||
alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BITHockeySDKLocalizedString(@"CrashResponseTitle"), appName ]
|
||||
message: [NSString stringWithFormat:BITHockeySDKLocalizedString(@"CrashResponseWaitingApple"), appName]
|
||||
delegate: self
|
||||
cancelButtonTitle: BWQuincyLocalize(@"CrashResponseTitleOK")
|
||||
cancelButtonTitle: BITHockeySDKLocalizedString(@"HockeyOK")
|
||||
otherButtonTitles: nil];
|
||||
break;
|
||||
case CrashReportStatusAvailable:
|
||||
alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseTitle"), appName ]
|
||||
message: [NSString stringWithFormat:BWQuincyLocalize(@"CrashResponseAvailable"), appName]
|
||||
case BITCrashStatusAvailable:
|
||||
alertView = [[UIAlertView alloc] initWithTitle: [NSString stringWithFormat:BITHockeySDKLocalizedString(@"CrashResponseTitle"), appName ]
|
||||
message: [NSString stringWithFormat:BITHockeySDKLocalizedString(@"CrashResponseAvailable"), appName]
|
||||
delegate: self
|
||||
cancelButtonTitle: BWQuincyLocalize(@"CrashResponseTitleOK")
|
||||
cancelButtonTitle: BITHockeySDKLocalizedString(@"HockeyOK")
|
||||
otherButtonTitles: nil];
|
||||
break;
|
||||
default:
|
||||
@ -379,7 +339,7 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
}
|
||||
|
||||
if (alertView) {
|
||||
[alertView setTag: QuincyKitAlertTypeFeedback];
|
||||
[alertView setTag: BITCrashAlertTypeFeedback];
|
||||
[alertView show];
|
||||
[alertView release];
|
||||
}
|
||||
@ -391,89 +351,47 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
#pragma mark UIAlertView Delegate
|
||||
|
||||
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex {
|
||||
if ([alertView tag] == QuincyKitAlertTypeSend) {
|
||||
if ([alertView tag] == BITCrashAlertTypeSend) {
|
||||
switch (buttonIndex) {
|
||||
case 0:
|
||||
_sendingInProgress = NO;
|
||||
[self _cleanCrashReports];
|
||||
[self cleanCrashReports];
|
||||
break;
|
||||
case 1:
|
||||
[self _sendCrashReports];
|
||||
[self sendCrashReports];
|
||||
break;
|
||||
case 2: {
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kAutomaticallySendCrashReports];
|
||||
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:kBITCrashAutomaticallySendReports];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(userDidChooseSendAlways)]) {
|
||||
[self.delegate userDidChooseSendAlways];
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReporterWillSendCrashReportsAlways:)]) {
|
||||
[self.delegate crashReporterWillSendCrashReportsAlways:self];
|
||||
}
|
||||
|
||||
[self _sendCrashReports];
|
||||
[self sendCrashReports];
|
||||
break;
|
||||
}
|
||||
default:
|
||||
_sendingInProgress = NO;
|
||||
[self _cleanCrashReports];
|
||||
[self cleanCrashReports];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark NSXMLParser Delegate
|
||||
|
||||
#pragma mark NSXMLParser
|
||||
|
||||
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
|
||||
if (qName) {
|
||||
elementName = qName;
|
||||
}
|
||||
|
||||
if ([elementName isEqualToString:@"result"]) {
|
||||
_contentOfProperty = [NSMutableString string];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
|
||||
if (qName) {
|
||||
elementName = qName;
|
||||
}
|
||||
|
||||
// open source implementation
|
||||
if ([elementName isEqualToString: @"result"]) {
|
||||
if ([_contentOfProperty intValue] > _serverResult) {
|
||||
_serverResult = (CrashReportStatus)[_contentOfProperty intValue];
|
||||
} else {
|
||||
CrashReportStatus errorcode = (CrashReportStatus)[_contentOfProperty intValue];
|
||||
NSLog(@"CrashReporter ended in error code: %i", errorcode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
|
||||
if (_contentOfProperty) {
|
||||
// If the current element is one whose content we care about, append 'string'
|
||||
// to the property that holds the content of the current element.
|
||||
if (string != nil) {
|
||||
[_contentOfProperty appendString:string];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Private
|
||||
#pragma mark - Private
|
||||
|
||||
|
||||
- (NSString *) extractAppUUIDs:(PLCrashReport *)report {
|
||||
NSMutableString *uuidString = [NSMutableString string];
|
||||
NSArray *uuidArray = [CNSCrashReportTextFormatter arrayOfAppUUIDsForCrashReport:report];
|
||||
NSArray *uuidArray = [BITCrashReportTextFormatter arrayOfAppUUIDsForCrashReport:report];
|
||||
|
||||
for (NSDictionary *element in uuidArray) {
|
||||
if ([element objectForKey:kCNSBinaryImageKeyUUID] && [element objectForKey:kCNSBinaryImageKeyArch] && [element objectForKey:kCNSBinaryImageKeyUUID]) {
|
||||
if ([element objectForKey:kBITBinaryImageKeyUUID] && [element objectForKey:kBITBinaryImageKeyArch] && [element objectForKey:kBITBinaryImageKeyUUID]) {
|
||||
[uuidString appendFormat:@"<uuid type=\"%@\" arch=\"%@\">%@</uuid>",
|
||||
[element objectForKey:kCNSBinaryImageKeyType],
|
||||
[element objectForKey:kCNSBinaryImageKeyArch],
|
||||
[element objectForKey:kCNSBinaryImageKeyUUID]
|
||||
[element objectForKey:kBITBinaryImageKeyType],
|
||||
[element objectForKey:kBITBinaryImageKeyArch],
|
||||
[element objectForKey:kBITBinaryImageKeyUUID]
|
||||
];
|
||||
}
|
||||
}
|
||||
@ -482,7 +400,7 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)_getDevicePlatform {
|
||||
- (NSString *)getDevicePlatform {
|
||||
size_t size = 0;
|
||||
sysctlbyname("hw.machine", NULL, &size, NULL, 0);
|
||||
char *answer = (char*)malloc(size);
|
||||
@ -493,25 +411,17 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
}
|
||||
|
||||
|
||||
- (void)_performSendingCrashReports {
|
||||
NSMutableDictionary *approvedCrashReports = [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults] dictionaryForKey: kApprovedCrashReports]];
|
||||
- (void)performSendingCrashReports {
|
||||
NSMutableDictionary *approvedCrashReports = [NSMutableDictionary dictionaryWithDictionary:[[NSUserDefaults standardUserDefaults] dictionaryForKey: kBITCrashApprovedReports]];
|
||||
|
||||
NSError *error = NULL;
|
||||
|
||||
NSString *userid = @"";
|
||||
NSString *contact = @"";
|
||||
NSString *description = @"";
|
||||
NSString *username = _userName ?: @"";
|
||||
NSString *email = _userEmail ?: @"";
|
||||
NSString *applicationLog = @"";
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReportUserID)]) {
|
||||
userid = [self.delegate crashReportUserID] ?: @"";
|
||||
}
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReportContact)]) {
|
||||
contact = [self.delegate crashReportContact] ?: @"";
|
||||
}
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReportDescription)]) {
|
||||
description = [self.delegate crashReportDescription] ?: @"";
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(applicationLogForCrashReporter:)]) {
|
||||
applicationLog = [self.delegate applicationLogForCrashReporter:self] ?: @"";
|
||||
}
|
||||
|
||||
NSMutableString *crashes = nil;
|
||||
@ -526,11 +436,13 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
|
||||
if (report == nil) {
|
||||
NSLog(@"Could not parse crash report");
|
||||
// we cannot do anything with this report, so delete it
|
||||
[self.fileManager removeItemAtPath:filename error:&error];
|
||||
continue;
|
||||
}
|
||||
|
||||
NSString *crashUUID = report.reportInfo.reportGUID ?: @"";
|
||||
NSString *crashLogString = [CNSCrashReportTextFormatter stringValueForCrashReport:report withTextFormat:PLCrashReportTextFormatiOS];
|
||||
NSString *crashLogString = [BITCrashReportTextFormatter stringValueForCrashReport:report];
|
||||
|
||||
if ([report.applicationInfo.applicationVersion compare:[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]] == NSOrderedSame) {
|
||||
_crashIdenticalCurrentVersion = YES;
|
||||
@ -545,14 +457,14 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
[self extractAppUUIDs:report],
|
||||
report.applicationInfo.applicationIdentifier,
|
||||
report.systemInfo.operatingSystemVersion,
|
||||
[self _getDevicePlatform],
|
||||
[self getDevicePlatform],
|
||||
[[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"],
|
||||
report.applicationInfo.applicationVersion,
|
||||
crashUUID,
|
||||
[crashLogString stringByReplacingOccurrencesOfString:@"]]>" withString:@"]]" @"]]><![CDATA[" @">" options:NSLiteralSearch range:NSMakeRange(0,crashLogString.length)],
|
||||
userid,
|
||||
contact,
|
||||
[description stringByReplacingOccurrencesOfString:@"]]>" withString:@"]]" @"]]><![CDATA[" @">" options:NSLiteralSearch range:NSMakeRange(0,description.length)]];
|
||||
username,
|
||||
email,
|
||||
[applicationLog stringByReplacingOccurrencesOfString:@"]]>" withString:@"]]" @"]]><![CDATA[" @">" options:NSLiteralSearch range:NSMakeRange(0,applicationLog.length)]];
|
||||
|
||||
|
||||
// store this crash report as user approved, so if it fails it will retry automatically
|
||||
@ -563,18 +475,18 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
}
|
||||
}
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setObject:approvedCrashReports forKey:kApprovedCrashReports];
|
||||
[[NSUserDefaults standardUserDefaults] setObject:approvedCrashReports forKey:kBITCrashApprovedReports];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
if (crashes != nil) {
|
||||
BWQuincyLog(@"Sending crash reports:\n%@", crashes);
|
||||
[self _postXML:[NSString stringWithFormat:@"<crashes>%@</crashes>", crashes]
|
||||
toURL:[NSURL URLWithString:self.submissionURL]];
|
||||
BITHockeySDKLog(@"Sending crash reports:\n%@", crashes);
|
||||
[self postXML:[NSString stringWithFormat:@"<crashes>%@</crashes>", crashes]
|
||||
toURL:[NSURL URLWithString:BITHOCKEYSDK_URL]];
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_cleanCrashReports {
|
||||
- (void)cleanCrashReports {
|
||||
NSError *error = NULL;
|
||||
|
||||
for (NSUInteger i=0; i < [_crashFiles count]; i++) {
|
||||
@ -582,22 +494,22 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
}
|
||||
[_crashFiles removeAllObjects];
|
||||
|
||||
[[NSUserDefaults standardUserDefaults] setObject:nil forKey:kApprovedCrashReports];
|
||||
[[NSUserDefaults standardUserDefaults] setObject:nil forKey:kBITCrashApprovedReports];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
}
|
||||
|
||||
- (void)_sendCrashReports {
|
||||
- (void)sendCrashReports {
|
||||
// send it to the next runloop
|
||||
[self performSelector:@selector(_performSendingCrashReports) withObject:nil afterDelay:0.0f];
|
||||
[self performSelector:@selector(performSendingCrashReports) withObject:nil afterDelay:0.0f];
|
||||
}
|
||||
|
||||
- (void)_checkForFeedbackStatus {
|
||||
- (void)checkForFeedbackStatus {
|
||||
NSMutableURLRequest *request = nil;
|
||||
|
||||
request = [NSMutableURLRequest requestWithURL:
|
||||
[NSURL URLWithString:[NSString stringWithFormat:@"%@api/2/apps/%@/crashes/%@",
|
||||
self.submissionURL,
|
||||
[self.appIdentifier stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
|
||||
BITHOCKEYSDK_URL,
|
||||
[_appIdentifier stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
|
||||
_feedbackRequestID
|
||||
]
|
||||
]];
|
||||
@ -608,45 +520,41 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
[request setTimeoutInterval: 15];
|
||||
[request setHTTPMethod:@"GET"];
|
||||
|
||||
_serverResult = CrashReportStatusUnknown;
|
||||
_serverResult = BITCrashStatusUnknown;
|
||||
_statusCode = 200;
|
||||
|
||||
// Release when done in the delegate method
|
||||
_responseData = [[NSMutableData alloc] init];
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionOpened)]) {
|
||||
[self.delegate connectionOpened];
|
||||
}
|
||||
|
||||
_urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
|
||||
|
||||
BWQuincyLog(@"Requesting feedback status.");
|
||||
if (!_urlConnection) {
|
||||
BITHockeySDKLog(@"Requesting feedback status could not start!");
|
||||
} else {
|
||||
BITHockeySDKLog(@"Requesting feedback status.");
|
||||
}
|
||||
}
|
||||
|
||||
- (void)_postXML:(NSString*)xml toURL:(NSURL*)url {
|
||||
- (void)postXML:(NSString*)xml toURL:(NSURL*)url {
|
||||
NSMutableURLRequest *request = nil;
|
||||
NSString *boundary = @"----FOO";
|
||||
|
||||
if (self.appIdentifier) {
|
||||
NSString *feedbackEnabled = @"&feedbackEnabled=no";
|
||||
|
||||
if ([self isFeedbackActivated]) {
|
||||
feedbackEnabled = @"&feedbackEnabled=yes";
|
||||
}
|
||||
|
||||
request = [NSMutableURLRequest requestWithURL:
|
||||
[NSURL URLWithString:[NSString stringWithFormat:@"%@api/2/apps/%@/crashes?sdk=%@&sdk_version=%@%@",
|
||||
self.submissionURL,
|
||||
[self.appIdentifier stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
|
||||
SDK_NAME,
|
||||
SDK_VERSION,
|
||||
feedbackEnabled
|
||||
]
|
||||
]];
|
||||
} else {
|
||||
request = [NSMutableURLRequest requestWithURL:url];
|
||||
NSString *feedbackEnabled = @"&feedbackEnabled=no";
|
||||
|
||||
if ([self isFeedbackActivated]) {
|
||||
feedbackEnabled = @"&feedbackEnabled=yes";
|
||||
}
|
||||
|
||||
request = [NSMutableURLRequest requestWithURL:
|
||||
[NSURL URLWithString:[NSString stringWithFormat:@"%@api/2/apps/%@/crashes?sdk=%@&sdk_version=%@%@",
|
||||
BITHOCKEYSDK_URL,
|
||||
[_appIdentifier stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding],
|
||||
BITHOCKEYSDK_NAME,
|
||||
BITHOCKEYSDK_VERSION,
|
||||
feedbackEnabled
|
||||
]
|
||||
]];
|
||||
|
||||
[request setCachePolicy: NSURLRequestReloadIgnoringLocalCacheData];
|
||||
[request setValue:@"Quincy/iOS" forHTTPHeaderField:@"User-Agent"];
|
||||
[request setValue:@"gzip" forHTTPHeaderField:@"Accept-Encoding"];
|
||||
@ -657,18 +565,14 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
|
||||
NSMutableData *postBody = [NSMutableData data];
|
||||
[postBody appendData:[[NSString stringWithFormat:@"--%@\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
if (self.appIdentifier) {
|
||||
[postBody appendData:[@"Content-Disposition: form-data; name=\"xml\"; filename=\"crash.xml\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[postBody appendData:[[NSString stringWithFormat:@"Content-Type: text/xml\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
} else {
|
||||
[postBody appendData:[@"Content-Disposition: form-data; name=\"xmlstring\"\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
}
|
||||
[postBody appendData:[@"Content-Disposition: form-data; name=\"xml\"; filename=\"crash.xml\"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[postBody appendData:[[NSString stringWithFormat:@"Content-Type: text/xml\r\n\r\n"] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[postBody appendData:[xml dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
[postBody appendData:[[NSString stringWithFormat:@"\r\n--%@--\r\n", boundary] dataUsingEncoding:NSUTF8StringEncoding]];
|
||||
|
||||
[request setHTTPBody:postBody];
|
||||
|
||||
_serverResult = CrashReportStatusUnknown;
|
||||
_serverResult = BITCrashStatusUnknown;
|
||||
_statusCode = 200;
|
||||
|
||||
//Release when done in the delegate method
|
||||
@ -677,22 +581,18 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
_urlConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
|
||||
|
||||
if (!_urlConnection) {
|
||||
BWQuincyLog(@"Sending crash reports could not start!");
|
||||
BITHockeySDKLog(@"Sending crash reports could not start!");
|
||||
_sendingInProgress = NO;
|
||||
} else {
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionOpened)]) {
|
||||
[self.delegate connectionOpened];
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReporterWillSendCrashReport:)]) {
|
||||
[self.delegate crashReporterWillSendCrashReport:self];
|
||||
}
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(sendingCrashReportsDidStart)]) {
|
||||
[self.delegate sendingCrashReportsDidStart];
|
||||
}
|
||||
|
||||
BWQuincyLog(@"Sending crash reports started.");
|
||||
BITHockeySDKLog(@"Sending crash reports started.");
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark NSURLConnection Delegate
|
||||
#pragma mark - NSURLConnection Delegate
|
||||
|
||||
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
|
||||
if ([response isKindOfClass:[NSHTTPURLResponse class]]) {
|
||||
@ -705,15 +605,11 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
}
|
||||
|
||||
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionClosed)]) {
|
||||
[self.delegate connectionClosed];
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReporter:didFailWithError:)]) {
|
||||
[self.delegate crashReporter:self didFailWithError:error];
|
||||
}
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(sendingCrashReportsDidFailWithError:)]) {
|
||||
[self.delegate sendingCrashReportsDidFailWithError:error];
|
||||
}
|
||||
|
||||
BWQuincyLog(@"ERROR: %@", [error localizedDescription]);
|
||||
BITHockeySDKLog(@"ERROR: %@", [error localizedDescription]);
|
||||
|
||||
_sendingInProgress = NO;
|
||||
|
||||
@ -727,85 +623,68 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
NSError *error = nil;
|
||||
|
||||
if (_statusCode >= 200 && _statusCode < 400 && _responseData != nil && [_responseData length] > 0) {
|
||||
[self _cleanCrashReports];
|
||||
[self cleanCrashReports];
|
||||
|
||||
_feedbackRequestID = nil;
|
||||
if (self.appIdentifier) {
|
||||
// HockeyApp uses PList XML format
|
||||
NSMutableDictionary *response = [NSPropertyListSerialization propertyListFromData:_responseData
|
||||
mutabilityOption:NSPropertyListMutableContainersAndLeaves
|
||||
format:nil
|
||||
errorDescription:NULL];
|
||||
BWQuincyLog(@"Received API response: %@", response);
|
||||
|
||||
_serverResult = (CrashReportStatus)[[response objectForKey:@"status"] intValue];
|
||||
if ([response objectForKey:@"id"]) {
|
||||
_feedbackRequestID = [[NSString alloc] initWithString:[response objectForKey:@"id"]];
|
||||
_feedbackDelayInterval = [[response objectForKey:@"delay"] floatValue];
|
||||
if (_feedbackDelayInterval > 0)
|
||||
_feedbackDelayInterval *= 0.01;
|
||||
}
|
||||
} else {
|
||||
BWQuincyLog(@"Received API response: %@", [[[NSString alloc] initWithBytes:[_responseData bytes] length:[_responseData length] encoding: NSUTF8StringEncoding] autorelease]);
|
||||
|
||||
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:_responseData];
|
||||
// Set self as the delegate of the parser so that it will receive the parser delegate methods callbacks.
|
||||
[parser setDelegate:self];
|
||||
// Depending on the XML document you're parsing, you may want to enable these features of NSXMLParser.
|
||||
[parser setShouldProcessNamespaces:NO];
|
||||
[parser setShouldReportNamespacePrefixes:NO];
|
||||
[parser setShouldResolveExternalEntities:NO];
|
||||
|
||||
[parser parse];
|
||||
|
||||
[parser release];
|
||||
// HockeyApp uses PList XML format
|
||||
NSMutableDictionary *response = [NSPropertyListSerialization propertyListFromData:_responseData
|
||||
mutabilityOption:NSPropertyListMutableContainersAndLeaves
|
||||
format:nil
|
||||
errorDescription:NULL];
|
||||
BITHockeySDKLog(@"Received API response: %@", response);
|
||||
|
||||
_serverResult = (BITCrashStatus)[[response objectForKey:@"status"] intValue];
|
||||
if ([response objectForKey:@"id"]) {
|
||||
_feedbackRequestID = [[NSString alloc] initWithString:[response objectForKey:@"id"]];
|
||||
_feedbackDelayInterval = [[response objectForKey:@"delay"] floatValue];
|
||||
if (_feedbackDelayInterval > 0)
|
||||
_feedbackDelayInterval *= 0.01;
|
||||
}
|
||||
|
||||
if ([self isFeedbackActivated]) {
|
||||
// only proceed if the server did not report any problem
|
||||
if ((self.appIdentifier) && (_serverResult == CrashReportStatusQueued)) {
|
||||
if (_serverResult == BITCrashStatusQueued) {
|
||||
// the report is still in the queue
|
||||
if (_feedbackRequestID) {
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(_checkForFeedbackStatus) object:nil];
|
||||
[self performSelector:@selector(_checkForFeedbackStatus) withObject:nil afterDelay:_feedbackDelayInterval];
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(checkForFeedbackStatus) object:nil];
|
||||
[self performSelector:@selector(checkForFeedbackStatus) withObject:nil afterDelay:_feedbackDelayInterval];
|
||||
}
|
||||
} else {
|
||||
[self showCrashStatusMessage];
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(sendingCrashReportsDidFinish)]) {
|
||||
[self.delegate sendingCrashReportsDidFinish];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReporterDidFinishSendingCrashReport:)]) {
|
||||
[self.delegate crashReporterDidFinishSendingCrashReport:self];
|
||||
}
|
||||
}
|
||||
} else if (_statusCode == 400 && self.appIdentifier) {
|
||||
[self _cleanCrashReports];
|
||||
} else if (_statusCode == 400) {
|
||||
[self cleanCrashReports];
|
||||
|
||||
error = [NSError errorWithDomain:kQuincyErrorDomain
|
||||
code:QuincyAPIAppVersionRejected
|
||||
error = [NSError errorWithDomain:kBITCrashErrorDomain
|
||||
code:BITCrashAPIAppVersionRejected
|
||||
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"The server rejected receiving crash reports for this app version!", NSLocalizedDescriptionKey, nil]];
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(sendingCrashReportsDidFailWithError:)]) {
|
||||
[self.delegate sendingCrashReportsDidFailWithError:error];
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReporter:didFailWithError:)]) {
|
||||
[self.delegate crashReporter:self didFailWithError:error];
|
||||
}
|
||||
|
||||
BWQuincyLog(@"ERROR: %@", [error localizedDescription]);
|
||||
BITHockeySDKLog(@"ERROR: %@", [error localizedDescription]);
|
||||
} else {
|
||||
if (_responseData == nil || [_responseData length] == 0) {
|
||||
error = [NSError errorWithDomain:kQuincyErrorDomain
|
||||
code:QuincyAPIReceivedEmptyResponse
|
||||
error = [NSError errorWithDomain:kBITCrashErrorDomain
|
||||
code:BITCrashAPIReceivedEmptyResponse
|
||||
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"Sending failed with an empty response!", NSLocalizedDescriptionKey, nil]];
|
||||
} else {
|
||||
error = [NSError errorWithDomain:kQuincyErrorDomain
|
||||
code:QuincyAPIErrorWithStatusCode
|
||||
error = [NSError errorWithDomain:kBITCrashErrorDomain
|
||||
code:BITCrashAPIErrorWithStatusCode
|
||||
userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:@"Sending failed with status code: %i", _statusCode], NSLocalizedDescriptionKey, nil]];
|
||||
}
|
||||
|
||||
BWQuincyLog(@"ERROR: %@", [error localizedDescription]);
|
||||
}
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(connectionClosed)]) {
|
||||
[self.delegate connectionClosed];
|
||||
|
||||
if (self.delegate != nil && [self.delegate respondsToSelector:@selector(crashReporter:didFailWithError:)]) {
|
||||
[self.delegate crashReporter:self didFailWithError:error];
|
||||
}
|
||||
|
||||
BITHockeySDKLog(@"ERROR: %@", [error localizedDescription]);
|
||||
}
|
||||
|
||||
_sendingInProgress = NO;
|
||||
@ -816,50 +695,5 @@ NSString *BWQuincyLocalize(NSString *stringToken) {
|
||||
_urlConnection = nil;
|
||||
}
|
||||
|
||||
#pragma mark PLCrashReporter
|
||||
|
||||
//
|
||||
// Called to handle a pending crash report.
|
||||
//
|
||||
- (void) handleCrashReport {
|
||||
PLCrashReporter *crashReporter = [PLCrashReporter sharedReporter];
|
||||
NSError *error = NULL;
|
||||
|
||||
// check if the next call ran successfully the last time
|
||||
if (_analyzerStarted == 0) {
|
||||
// mark the start of the routine
|
||||
_analyzerStarted = 1;
|
||||
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:_analyzerStarted] forKey:kQuincyKitAnalyzerStarted];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
// Try loading the crash report
|
||||
_crashData = [[NSData alloc] initWithData:[crashReporter loadPendingCrashReportDataAndReturnError: &error]];
|
||||
|
||||
NSString *cacheFilename = [NSString stringWithFormat: @"%.0f", [NSDate timeIntervalSinceReferenceDate]];
|
||||
|
||||
if (_crashData == nil) {
|
||||
NSLog(@"Could not load crash report: %@", error);
|
||||
} else {
|
||||
[_crashData writeToFile:[_crashesDir stringByAppendingPathComponent: cacheFilename] atomically:YES];
|
||||
|
||||
// get the startup timestamp from the crash report, and the file timestamp to calculate the timeinterval when the crash happened after startup
|
||||
PLCrashReport *report = [[[PLCrashReport alloc] initWithData:_crashData error:&error] autorelease];
|
||||
|
||||
if (report.systemInfo.timestamp && report.applicationInfo.applicationStartupTimestamp) {
|
||||
_timeintervalCrashInLastSessionOccured = [report.systemInfo.timestamp timeIntervalSinceDate:report.applicationInfo.applicationStartupTimestamp];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Purge the report
|
||||
// mark the end of the routine
|
||||
_analyzerStarted = 0;
|
||||
[[NSUserDefaults standardUserDefaults] setValue:[NSNumber numberWithInt:_analyzerStarted] forKey:kQuincyKitAnalyzerStarted];
|
||||
[[NSUserDefaults standardUserDefaults] synchronize];
|
||||
|
||||
[crashReporter purgePendingCrashReport];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@end
|
60
Classes/BITCrashManagerDelegate.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* 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>
|
||||
|
||||
@protocol BITCrashManagerDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
/** Return any log string based data the crash report being processed should contain
|
||||
*/
|
||||
-(NSString *)applicationLogForCrashReporter:(BITCrashManager *)crashReporter;
|
||||
|
||||
/** Invoked before the user is asked to send a crash report, so you can do additional actions.
|
||||
E.g. to make sure not to ask the user for an app rating :)
|
||||
*/
|
||||
-(void)crashReporterWillShowSubmitCrashReportAlert:(BITCrashManager *)crashReporter;
|
||||
|
||||
/** Invoked after the user did choose to send crashes always in the alert
|
||||
*/
|
||||
-(void)crashReporterWillSendCrashReportsAlways:(BITCrashManager *)crashReporter;
|
||||
|
||||
/** Invoked right before sending crash reports will start
|
||||
*/
|
||||
- (void)crashReporterWillSendCrashReport:(BITCrashManager *)crashReporter;
|
||||
|
||||
/** Invoked after sending crash reports failed
|
||||
*/
|
||||
- (void)crashReporter:(BITCrashManager *)crashReporter didFailWithError:(NSError *)error;
|
||||
|
||||
/** Invoked after sending crash reports succeeded
|
||||
*/
|
||||
- (void)crashReporterDidFinishSendingCrashReport:(BITCrashManager *)crashReporter;
|
||||
|
||||
@end
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* Copyright (c) 2008-2012 Plausible Labs Cooperative, Inc.
|
||||
* Copyright (c) 2010 MOSO Corporation, Pty Ltd.
|
||||
* Copyright (c) 2012 Codenauts UG (haftungsbeschränkt)
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
@ -34,38 +34,20 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "CrashReporter/PLCrashReportFormatter.h"
|
||||
|
||||
/**
|
||||
* Supported text output formats.
|
||||
*
|
||||
* @ingroup enums
|
||||
*/
|
||||
typedef enum {
|
||||
/** An iOS-compatible crash log text format. Compatible with the crash logs generated by the device and available
|
||||
* through iTunes Connect. */
|
||||
CNSCrashReportTextFormatiOS = 0
|
||||
} CNSCrashReportTextFormat;
|
||||
|
||||
#import <CrashReporter/PLCrashReport.h>
|
||||
|
||||
// Dictionary keys for array elements returned by arrayOfAppUUIDsForCrashReport:
|
||||
#define kCNSBinaryImageKeyUUID @"uuid"
|
||||
#define kCNSBinaryImageKeyArch @"arch"
|
||||
#define kCNSBinaryImageKeyType @"type"
|
||||
#ifndef kBITBinaryImageKeyUUID
|
||||
#define kBITBinaryImageKeyUUID @"uuid"
|
||||
#define kBITBinaryImageKeyArch @"arch"
|
||||
#define kBITBinaryImageKeyType @"type"
|
||||
#endif
|
||||
|
||||
|
||||
@interface CNSCrashReportTextFormatter : NSObject <PLCrashReportFormatter> {
|
||||
@private
|
||||
/** Text output format. */
|
||||
CNSCrashReportTextFormat _textFormat;
|
||||
|
||||
/** Encoding to use for string output. */
|
||||
NSStringEncoding _stringEncoding;
|
||||
@interface BITCrashReportTextFormatter : NSObject {
|
||||
}
|
||||
|
||||
+ (NSString *) stringValueForCrashReport: (PLCrashReport *) report withTextFormat: (CNSCrashReportTextFormat) textFormat;
|
||||
+ (NSArray *) arrayOfAppUUIDsForCrashReport: (PLCrashReport *) report;
|
||||
|
||||
- (id) initWithTextFormat: (CNSCrashReportTextFormat) textFormat stringEncoding: (NSStringEncoding) stringEncoding;
|
||||
+ (NSString *)stringValueForCrashReport:(PLCrashReport *)report;
|
||||
+ (NSArray *)arrayOfAppUUIDsForCrashReport:(PLCrashReport *)report;
|
||||
|
||||
@end
|
@ -6,7 +6,7 @@
|
||||
*
|
||||
* Copyright (c) 2008-2012 Plausible Labs Cooperative, Inc.
|
||||
* Copyright (c) 2010 MOSO Corporation, Pty Ltd.
|
||||
* Copyright (c) 2012 Codenauts UG (haftungsbeschränkt)
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person
|
||||
@ -31,22 +31,22 @@
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#import "CrashReporter/CrashReporter.h"
|
||||
#import <CrashReporter/CrashReporter.h>
|
||||
|
||||
#import "CNSCrashReportTextFormatter.h"
|
||||
#import "BITCrashReportTextFormatter.h"
|
||||
|
||||
@interface CNSCrashReportTextFormatter (PrivateAPI)
|
||||
@interface BITCrashReportTextFormatter (PrivateAPI)
|
||||
NSInteger binaryImageSort(id binary1, id binary2, void *context);
|
||||
+ (NSString *) formatStackFrame: (PLCrashReportStackFrameInfo *) frameInfo
|
||||
frameIndex: (NSUInteger) frameIndex
|
||||
report: (PLCrashReport *) report;
|
||||
+ (NSString *)formatStackFrame:(PLCrashReportStackFrameInfo *)frameInfo
|
||||
frameIndex:(NSUInteger)frameIndex
|
||||
report:(PLCrashReport *)report;
|
||||
@end
|
||||
|
||||
|
||||
/**
|
||||
* Formats PLCrashReport data as human-readable text.
|
||||
*/
|
||||
@implementation CNSCrashReportTextFormatter
|
||||
@implementation BITCrashReportTextFormatter
|
||||
|
||||
|
||||
/**
|
||||
@ -58,7 +58,7 @@ NSInteger binaryImageSort(id binary1, id binary2, void *context);
|
||||
*
|
||||
* @return Returns the formatted result on success, or nil if an error occurs.
|
||||
*/
|
||||
+ (NSString *) stringValueForCrashReport: (PLCrashReport *) report withTextFormat: (CNSCrashReportTextFormat) textFormat {
|
||||
+ (NSString *)stringValueForCrashReport:(PLCrashReport *)report {
|
||||
NSMutableString* text = [NSMutableString string];
|
||||
boolean_t lp64 = true; // quiesce GCC uninitialized value warning
|
||||
|
||||
@ -435,7 +435,7 @@ NSInteger binaryImageSort(id binary1, id binary2, void *context);
|
||||
*
|
||||
* @return Returns the formatted result on success, or nil if an error occurs.
|
||||
*/
|
||||
+ (NSArray *) arrayOfAppUUIDsForCrashReport: (PLCrashReport *) report {
|
||||
+ (NSArray *)arrayOfAppUUIDsForCrashReport:(PLCrashReport *)report {
|
||||
NSMutableArray* appUUIDs = [NSMutableArray array];
|
||||
|
||||
/* Images. The iPhone crash report format sorts these in ascending order, by the base address */
|
||||
@ -498,40 +498,18 @@ NSInteger binaryImageSort(id binary1, id binary2, void *context);
|
||||
}
|
||||
|
||||
if ([imagePath isEqual: report.processInfo.processPath] || [imagePath hasPrefix:appBundleContentsPath]) {
|
||||
[appUUIDs addObject:[NSDictionary dictionaryWithObjectsAndKeys:uuid, kCNSBinaryImageKeyUUID, archName, kCNSBinaryImageKeyArch, imageType, kCNSBinaryImageKeyType, nil]];
|
||||
[appUUIDs addObject:[NSDictionary dictionaryWithObjectsAndKeys:uuid, kBITBinaryImageKeyUUID, archName, kBITBinaryImageKeyArch, imageType, kBITBinaryImageKeyType, nil]];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return appUUIDs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize with the request string encoding and output format.
|
||||
*
|
||||
* @param textFormat Format to use for the generated text crash report.
|
||||
* @param stringEncoding Encoding to use when writing to the output stream.
|
||||
*/
|
||||
- (id) initWithTextFormat: (CNSCrashReportTextFormat) textFormat stringEncoding: (NSStringEncoding) stringEncoding {
|
||||
if ((self = [super init]) == nil)
|
||||
return nil;
|
||||
|
||||
_textFormat = textFormat;
|
||||
_stringEncoding = stringEncoding;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
// from PLCrashReportFormatter protocol
|
||||
- (NSData *) formatReport: (PLCrashReport *) report error: (NSError **) outError {
|
||||
NSString *text = [PLCrashReportTextFormatter stringValueForCrashReport: report withTextFormat: _textFormat];
|
||||
return [text dataUsingEncoding: _stringEncoding allowLossyConversion: YES];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation CNSCrashReportTextFormatter (PrivateAPI)
|
||||
@implementation BITCrashReportTextFormatter (PrivateAPI)
|
||||
|
||||
|
||||
/**
|
||||
@ -543,9 +521,9 @@ NSInteger binaryImageSort(id binary1, id binary2, void *context);
|
||||
*
|
||||
* @return Returns a formatted frame line.
|
||||
*/
|
||||
+ (NSString *) formatStackFrame: (PLCrashReportStackFrameInfo *) frameInfo
|
||||
frameIndex: (NSUInteger) frameIndex
|
||||
report: (PLCrashReport *) report
|
||||
+ (NSString *)formatStackFrame: (PLCrashReportStackFrameInfo *) frameInfo
|
||||
frameIndex: (NSUInteger) frameIndex
|
||||
report: (PLCrashReport *) report
|
||||
{
|
||||
/* Base image address containing instrumention pointer, offset of the IP from that base
|
||||
* address, and the associated image name */
|
81
Classes/BITHockeyManager.h
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
* Kent Sutherland
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* 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 "BITUpdateManager.h"
|
||||
|
||||
|
||||
@protocol BITHockeyManagerDelegate;
|
||||
|
||||
@class BITCrashManager;
|
||||
|
||||
@interface BITHockeyManager : NSObject {
|
||||
@private
|
||||
id<BITHockeyManagerDelegate> delegate;
|
||||
NSString *_appIdentifier;
|
||||
|
||||
BOOL _validAppIdentifier;
|
||||
|
||||
BOOL _startManagerIsInvoked;
|
||||
}
|
||||
|
||||
#pragma mark - Public Properties
|
||||
|
||||
@property (nonatomic, retain) BITCrashManager *crashManager;
|
||||
|
||||
@property (nonatomic, retain) BITUpdateManager *updateManager;
|
||||
|
||||
|
||||
// if YES the app is installed from the app store
|
||||
// if NO the app is installed via ad-hoc or enterprise distribution
|
||||
@property (nonatomic, readonly) BOOL isAppStoreEnvironment;
|
||||
|
||||
// Enable debug logging; ONLY ENABLE THIS FOR DEBUGGING!
|
||||
//
|
||||
// Default: NO
|
||||
@property (nonatomic, assign, getter=isLoggingEnabled) BOOL loggingEnabled;
|
||||
|
||||
|
||||
#pragma mark - Public Methods
|
||||
|
||||
// Returns the shared manager object
|
||||
+ (BITHockeyManager *)sharedHockeyManager;
|
||||
|
||||
// Configure HockeyApp with a single app identifier and delegate; use this
|
||||
// only for debug or beta versions of your app!
|
||||
- (void)configureWithIdentifier:(NSString *)appIdentifier delegate:(id<BITHockeyManagerDelegate>)delegate;
|
||||
|
||||
// Configure HockeyApp with different app identifiers for beta and live versions
|
||||
// of the app; the update alert will only be shown for the beta identifier
|
||||
- (void)configureWithBetaIdentifier:(NSString *)betaIdentifier liveIdentifier:(NSString *)liveIdentifier delegate:(id<BITHockeyManagerDelegate>)delegate;
|
||||
|
||||
// Initialize all submodules and start them
|
||||
- (void)startManager;
|
||||
|
||||
|
||||
@end
|
296
Classes/BITHockeyManager.m
Normal file
@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
* Kent Sutherland
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* 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 "HockeySDK.h"
|
||||
#import "HockeySDKPrivate.h"
|
||||
#import "BITUpdateManager.h"
|
||||
|
||||
|
||||
@interface BITHockeyManager ()
|
||||
|
||||
- (BOOL)shouldUseLiveIdenfitier;
|
||||
|
||||
- (void)configureJMC;
|
||||
|
||||
@end
|
||||
|
||||
@implementation BITHockeyManager
|
||||
|
||||
@synthesize crashManager = _crashManager;
|
||||
@synthesize updateManager = _updateManager;
|
||||
|
||||
@synthesize isAppStoreEnvironment = _isAppStoreEnvironment;
|
||||
|
||||
|
||||
#pragma mark - Public Class Methods
|
||||
|
||||
+ (BITHockeyManager *)sharedHockeyManager {
|
||||
static BITHockeyManager *sharedInstance = nil;
|
||||
static dispatch_once_t pred;
|
||||
|
||||
dispatch_once(&pred, ^{
|
||||
sharedInstance = [BITHockeyManager alloc];
|
||||
sharedInstance = [sharedInstance init];
|
||||
});
|
||||
|
||||
return sharedInstance;
|
||||
}
|
||||
|
||||
- (id) init {
|
||||
if ((self = [super init])) {
|
||||
_isAppStoreEnvironment = NO;
|
||||
_startManagerIsInvoked = NO;
|
||||
|
||||
[self performSelector:@selector(validateStartManagerIsInvoked) withObject:nil afterDelay:0.0f];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[_appIdentifier release], _appIdentifier = nil;
|
||||
|
||||
[_crashManager release], _crashManager = nil;
|
||||
[_updateManager release], _updateManager = nil;
|
||||
|
||||
delegate = nil;
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Public Instance Methods (Configuration)
|
||||
|
||||
- (void)configureWithIdentifier:(NSString *)newAppIdentifier delegate:(id)newDelegate {
|
||||
delegate = newDelegate;
|
||||
[_appIdentifier release];
|
||||
_appIdentifier = [newAppIdentifier copy];
|
||||
|
||||
[self initializeModules];
|
||||
}
|
||||
|
||||
- (void)configureWithBetaIdentifier:(NSString *)betaIdentifier liveIdentifier:(NSString *)liveIdentifier delegate:(id)newDelegate {
|
||||
delegate = newDelegate;
|
||||
[_appIdentifier release];
|
||||
|
||||
if ([self shouldUseLiveIdenfitier]) {
|
||||
_appIdentifier = [liveIdentifier copy];
|
||||
}
|
||||
else {
|
||||
_appIdentifier = [betaIdentifier copy];
|
||||
}
|
||||
|
||||
[self initializeModules];
|
||||
}
|
||||
|
||||
|
||||
- (void)startManager {
|
||||
BITHockeySDKLog(@"Starting HockeyManager");
|
||||
_startManagerIsInvoked = YES;
|
||||
|
||||
// start CrashManager
|
||||
BITHockeySDKLog(@"Start crashManager");
|
||||
[_crashManager performSelector:@selector(startManager) withObject:nil afterDelay:1.0f];
|
||||
|
||||
// Setup UpdateManager
|
||||
BITHockeySDKLog(@"Start UpdateManager");
|
||||
[_updateManager performSelector:@selector(startManager) withObject:nil afterDelay:0.0f];
|
||||
}
|
||||
|
||||
|
||||
- (void)validateStartManagerIsInvoked {
|
||||
if (_validAppIdentifier && !_isAppStoreEnvironment) {
|
||||
if (!_startManagerIsInvoked) {
|
||||
NSLog(@"ERROR: You did not call [[BITHockeyManager sharedHockeyManager] startManager] to startup the HockeySDK! Please do so after setting up all properties. The SDK is NOT running.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Private Instance Methods
|
||||
|
||||
- (BOOL)shouldUseLiveIdenfitier {
|
||||
BOOL delegateResult = NO;
|
||||
if ([delegate respondsToSelector:@selector(shouldUseLiveIdenfitier)]) {
|
||||
delegateResult = [(NSObject <BITHockeyManagerDelegate>*)delegate shouldUseLiveIdenfitier];
|
||||
}
|
||||
|
||||
return (delegateResult) || (_isAppStoreEnvironment);
|
||||
}
|
||||
|
||||
- (void)initializeModules {
|
||||
NSCharacterSet *hexSet = [NSCharacterSet characterSetWithCharactersInString:@"0123456789abcdef"];
|
||||
NSCharacterSet *inStringSet = [NSCharacterSet characterSetWithCharactersInString:_appIdentifier];
|
||||
_validAppIdentifier = ([_appIdentifier length] == 32) && ([hexSet isSupersetOfSet:inStringSet]);
|
||||
|
||||
// check if we are really not in an app store environment
|
||||
if ([[NSBundle mainBundle] pathForResource:@"embedded" ofType:@"mobileprovision"]) {
|
||||
_isAppStoreEnvironment = NO;
|
||||
} else {
|
||||
_isAppStoreEnvironment = YES;
|
||||
}
|
||||
|
||||
#if TARGET_IPHONE_SIMULATOR
|
||||
_isAppStoreEnvironment = NO;
|
||||
#endif
|
||||
|
||||
_startManagerIsInvoked = NO;
|
||||
|
||||
if (_validAppIdentifier) {
|
||||
BITHockeySDKLog(@"Setup CrashManager");
|
||||
self.crashManager = [[[BITCrashManager alloc] initWithAppIdentifier:_appIdentifier] autorelease];
|
||||
|
||||
BITHockeySDKLog(@"Setup UpdateManager");
|
||||
self.updateManager = [[[BITUpdateManager alloc] initWithAppIdentifier:_appIdentifier isAppStoreEnvironemt:_isAppStoreEnvironment] autorelease];
|
||||
|
||||
// Only if JMC is part of the project
|
||||
if ([[self class] isJMCPresent]) {
|
||||
BITHockeySDKLog(@"Setup JMC");
|
||||
[_updateManager setCheckForTracker:YES];
|
||||
[_updateManager addObserver:self forKeyPath:@"trackerConfig" options:0 context:nil];
|
||||
[[self class] disableJMCCrashReporter];
|
||||
[self performSelector:@selector(configureJMC) withObject:nil afterDelay:0];
|
||||
}
|
||||
|
||||
} else {
|
||||
NSLog(@"ERROR: The app identifier is invalid! Please use the HockeyApp app identifier you find on the apps website on HockeyApp! The SDK is disabled!");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - JMC
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
+ (id)jmcInstance {
|
||||
id jmcClass = NSClassFromString(@"JMC");
|
||||
if ((jmcClass) && ([jmcClass respondsToSelector:@selector(sharedInstance)])) {
|
||||
return [jmcClass performSelector:@selector(sharedInstance)];
|
||||
}
|
||||
#ifdef JMC_LEGACY
|
||||
else if ((jmcClass) && ([jmcClass respondsToSelector:@selector(instance)])) {
|
||||
return [jmcClass performSelector:@selector(instance)]; // legacy pre (JMC 1.0.11) support
|
||||
}
|
||||
#endif
|
||||
|
||||
return nil;
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
+ (BOOL)isJMCActive {
|
||||
id jmcInstance = [self jmcInstance];
|
||||
return (jmcInstance) && ([jmcInstance performSelector:@selector(url)]);
|
||||
}
|
||||
|
||||
+ (BOOL)isJMCPresent {
|
||||
return [self jmcInstance] != nil;
|
||||
}
|
||||
|
||||
#pragma mark - Private Class Methods
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
+ (void)disableJMCCrashReporter {
|
||||
id jmcInstance = [self jmcInstance];
|
||||
id jmcOptions = [jmcInstance performSelector:@selector(options)];
|
||||
SEL crashReporterSelector = @selector(setCrashReportingEnabled:);
|
||||
|
||||
BOOL value = NO;
|
||||
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[jmcOptions methodSignatureForSelector:crashReporterSelector]];
|
||||
invocation.target = jmcOptions;
|
||||
invocation.selector = crashReporterSelector;
|
||||
[invocation setArgument:&value atIndex:2];
|
||||
[invocation invoke];
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
+ (BOOL)checkJMCConfiguration:(NSDictionary *)configuration {
|
||||
return (([configuration isKindOfClass:[NSDictionary class]]) &&
|
||||
([[configuration valueForKey:@"enabled"] boolValue]) &&
|
||||
([[configuration valueForKey:@"url"] length] > 0) &&
|
||||
([[configuration valueForKey:@"key"] length] > 0) &&
|
||||
([[configuration valueForKey:@"project"] length] > 0));
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
+ (void)applyJMCConfiguration:(NSDictionary *)configuration {
|
||||
id jmcInstance = [self jmcInstance];
|
||||
SEL configureSelector = @selector(configureJiraConnect:projectKey:apiKey:);
|
||||
|
||||
NSString *url = [configuration valueForKey:@"url"];
|
||||
NSString *project = [configuration valueForKey:@"project"];
|
||||
NSString *key = [configuration valueForKey:@"key"];
|
||||
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[jmcInstance methodSignatureForSelector:configureSelector]];
|
||||
invocation.target = jmcInstance;
|
||||
invocation.selector = configureSelector;
|
||||
[invocation setArgument:&url atIndex:2];
|
||||
[invocation setArgument:&project atIndex:3];
|
||||
[invocation setArgument:&key atIndex:4];
|
||||
[invocation invoke];
|
||||
|
||||
if ([jmcInstance respondsToSelector:@selector(ping)]) {
|
||||
[jmcInstance performSelector:@selector(ping)];
|
||||
}
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
- (void)configureJMC {
|
||||
// Return if JMC is already configured
|
||||
if ([[self class] isJMCActive]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Configure JMC from user defaults
|
||||
NSDictionary *configurations = [[NSUserDefaults standardUserDefaults] valueForKey:@"BITTrackerConfigurations"];
|
||||
NSDictionary *configuration = [configurations valueForKey:_appIdentifier];
|
||||
if ([[self class] checkJMCConfiguration:configuration]) {
|
||||
[[self class] applyJMCConfiguration:configuration];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
||||
if (([object trackerConfig]) && ([[object trackerConfig] isKindOfClass:[NSDictionary class]])) {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSMutableDictionary *trackerConfig = [[defaults valueForKey:@"BITTrackerConfigurations"] mutableCopy];
|
||||
if (!trackerConfig) {
|
||||
trackerConfig = [[NSMutableDictionary dictionaryWithCapacity:1] retain];
|
||||
}
|
||||
|
||||
[trackerConfig setValue:[object trackerConfig] forKey:_appIdentifier];
|
||||
[defaults setValue:trackerConfig forKey:@"BITTrackerConfigurations"];
|
||||
[trackerConfig release];
|
||||
|
||||
[defaults synchronize];
|
||||
[self configureJMC];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
41
Classes/BITHockeyManagerDelegate.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* 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>
|
||||
|
||||
@protocol BITHockeyManagerDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
// Invoked when the manager is configured
|
||||
//
|
||||
// Implement to force the usage of the live identifier, e.g. for enterprise apps
|
||||
// which are distributed inside your company
|
||||
- (BOOL)shouldUseLiveIdenfitier;
|
||||
|
||||
@end
|
194
Classes/BITUpdateManager.h
Normal file
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
* Peter Steinberger
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* Copyright (c) 2011 Andreas Linde.
|
||||
* 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>
|
||||
|
||||
|
||||
typedef enum {
|
||||
BITUpdateComparisonResultDifferent,
|
||||
BITUpdateComparisonResultGreater
|
||||
} BITUpdateComparisonResult;
|
||||
|
||||
typedef enum {
|
||||
BITUpdateAuthorizationDenied,
|
||||
BITUpdateAuthorizationAllowed,
|
||||
BITUpdateAuthorizationPending
|
||||
} BITUpdateAuthorizationState;
|
||||
|
||||
typedef enum {
|
||||
BITUpdateCheckStartup = 0,
|
||||
BITUpdateCheckDaily = 1,
|
||||
BITUpdateCheckManually = 2
|
||||
} BITUpdateSetting;
|
||||
|
||||
@protocol BITUpdateManagerDelegate;
|
||||
|
||||
@class BITAppVersionMetaInfo;
|
||||
@class BITUpdateViewController;
|
||||
|
||||
@interface BITUpdateManager : NSObject <UIAlertViewDelegate> {
|
||||
NSString *_appIdentifier;
|
||||
NSString *_currentAppVersion;
|
||||
|
||||
UINavigationController *_navController;
|
||||
BITUpdateViewController *_currentHockeyViewController;
|
||||
|
||||
BOOL _dataFound;
|
||||
BOOL _showFeedback;
|
||||
BOOL _updateURLOffline;
|
||||
BOOL _updateAlertShowing;
|
||||
BOOL _lastCheckFailed;
|
||||
|
||||
BOOL _isAppStoreEnvironment;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setting Properties
|
||||
|
||||
// delegate is optional
|
||||
@property (nonatomic, assign) id <BITUpdateManagerDelegate> delegate;
|
||||
|
||||
// hockey secret is required if authentication is used
|
||||
@property (nonatomic, retain) NSString *authenticationSecret;
|
||||
|
||||
// if YES, the current user data is send: device type, iOS version, app version, UDID (default)
|
||||
// if NO, no such data is send to the server
|
||||
@property (nonatomic, assign, getter=shouldSendUserData) BOOL sendUserData;
|
||||
|
||||
// if YES, the the users usage time of the app to the service, only in 1 minute granularity! (default)
|
||||
// if NO, no such data is send to the server
|
||||
@property (nonatomic, assign, getter=shouldSendUsageTime) BOOL sendUsageTime;
|
||||
|
||||
// if YES, the user agrees to send the usage data, user can change it if the developer shows the settings (default)
|
||||
// if NO, the user overwrites the developer setting and no such data is sent
|
||||
@property (nonatomic, assign, getter=isAllowUserToDisableSendData) BOOL allowUserToDisableSendData;
|
||||
|
||||
// if YES, the user allowed to send user data (default)
|
||||
// if NO, the user denied to send user data
|
||||
@property (nonatomic, assign, getter=doesUserAllowsSendUserData) BOOL userAllowsSendUserData;
|
||||
|
||||
// if YES, the user allowed to send usage data (default)
|
||||
// if NO, the user denied to send usage data
|
||||
@property (nonatomic, assign, getter=doesUserAllowsSendUsageTime) BOOL userAllowsSendUsageTime;
|
||||
|
||||
// if YES, the new version alert will be displayed always if the current version is outdated (default)
|
||||
// if NO, the alert will be displayed only once for each new update
|
||||
@property (nonatomic, assign) BOOL alwaysShowUpdateReminder;
|
||||
|
||||
// if YES, the user can change the HockeyUpdateSetting value (default)
|
||||
// if NO, the user can not change it, and the default or developer defined value will be used
|
||||
@property (nonatomic, assign, getter=shouldShowUserSettings) BOOL showUserSettings;
|
||||
|
||||
// set bar style of navigation controller
|
||||
@property (nonatomic, assign) UIBarStyle barStyle;
|
||||
|
||||
// set modal presentation style of update view
|
||||
@property (nonatomic, assign) UIModalPresentationStyle modalPresentationStyle;
|
||||
|
||||
// if YES, then an update check will be performed after the application becomes active (default)
|
||||
// if NO, then the update check will not happen unless invoked explicitly
|
||||
@property (nonatomic, assign, getter=isCheckForUpdateOnLaunch) BOOL checkForUpdateOnLaunch;
|
||||
|
||||
// if YES, the alert notifying about an new update also shows a button to install the update directly
|
||||
// if NO, the alert notifying about an new update only shows ignore and show update button
|
||||
@property (nonatomic, assign, getter=isShowingDirectInstallOption) BOOL showDirectInstallOption;
|
||||
|
||||
// if YES, each app version needs to be authorized by the server to run on this device
|
||||
// if NO, each app version does not need to be authorized (default)
|
||||
@property (nonatomic, assign, getter=isRequireAuthorization) BOOL requireAuthorization;
|
||||
|
||||
// HockeyComparisonResultDifferent: alerts if the version on the server is different (default)
|
||||
// HockeyComparisonResultGreater: alerts if the version on the server is greater
|
||||
@property (nonatomic, assign) BITUpdateComparisonResult compareVersionType;
|
||||
|
||||
// see HockeyUpdateSetting-enum. Will be saved in user defaults.
|
||||
// default value: HockeyUpdateCheckStartup
|
||||
@property (nonatomic, assign) BITUpdateSetting updateSetting;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private Properties
|
||||
|
||||
// if YES, the API will return an existing JMC config
|
||||
// if NO, the API will return only version information
|
||||
@property (nonatomic, assign) BOOL checkForTracker;
|
||||
|
||||
// Contains the tracker config if received from server
|
||||
@property (nonatomic, retain, readonly) NSDictionary *trackerConfig;
|
||||
|
||||
|
||||
- (id)initWithAppIdentifier:(NSString *)appIdentifier isAppStoreEnvironemt:(BOOL)isAppStoreEnvironment;
|
||||
|
||||
- (void)startManager;
|
||||
|
||||
// is an update available?
|
||||
- (BOOL)isUpdateAvailable;
|
||||
|
||||
// are we currently checking for updates?
|
||||
- (BOOL)isCheckInProgress;
|
||||
|
||||
// open update info view
|
||||
- (void)showUpdateView;
|
||||
|
||||
// manually start an update check
|
||||
- (void)checkForUpdate;
|
||||
|
||||
// checks for update, informs the user (error, no update found, etc)
|
||||
- (void)checkForUpdateShowFeedback:(BOOL)feedback;
|
||||
|
||||
// initiates app-download call. displays an system UIAlertView
|
||||
- (BOOL)initiateAppDownload;
|
||||
|
||||
// checks wether this app version is authorized
|
||||
- (BOOL)appVersionIsAuthorized;
|
||||
|
||||
// start checking for an authorization key
|
||||
- (void)checkForAuthorization;
|
||||
|
||||
// convenience methode to create hockey view controller
|
||||
- (BITUpdateViewController *)hockeyViewController:(BOOL)modal;
|
||||
|
||||
// get/set current active hockey view controller
|
||||
@property (nonatomic, retain) BITUpdateViewController *currentHockeyViewController;
|
||||
|
||||
// convenience method to get current running version string
|
||||
- (NSString *)currentAppVersion;
|
||||
|
||||
// get newest app version
|
||||
- (BITAppVersionMetaInfo *)newestAppVersion;
|
||||
|
||||
// get array of all available versions
|
||||
- (NSArray *)appVersions;
|
||||
|
||||
// check if there is any newer version mandatory
|
||||
- (BOOL)hasNewerMandatoryVersion;
|
||||
|
||||
@end
|
51
Classes/BITUpdateManagerDelegate.h
Normal file
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* 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>
|
||||
|
||||
@protocol BITUpdateManagerDelegate <NSObject>
|
||||
|
||||
/*
|
||||
Return the device UDID which is required for beta testing, should return nil for app store configuration!
|
||||
Example implementation if your configuration for the App Store is called "AppStore":
|
||||
|
||||
#ifndef (CONFIGURATION_AppStore)
|
||||
if ([[UIDevice currentDevice] respondsToSelector:@selector(uniqueIdentifier)])
|
||||
return [[UIDevice currentDevice] performSelector:@selector(uniqueIdentifier)];
|
||||
#endif
|
||||
return nil;
|
||||
|
||||
*/
|
||||
- (NSString *)customDeviceIdentifierForUpdateManager:(BITUpdateManager *)updateManager;
|
||||
|
||||
@optional
|
||||
|
||||
// optional parent view controller for the update screen when invoked via the alert view, default is the root UIWindow instance
|
||||
- (UIViewController *)viewControllerForUpdateManager:(BITUpdateManager *)updateManager;
|
||||
|
||||
@end
|
42
Classes/BITUpdateSettingsViewController.h
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* Copyright (c) 2011 Andreas Linde.
|
||||
* 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>
|
||||
|
||||
@class BITUpdateManager;
|
||||
|
||||
@interface BITUpdateSettingsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
|
||||
}
|
||||
|
||||
@property (nonatomic, retain) BITUpdateManager *updateManager;
|
||||
|
||||
- (id)init:(BITUpdateManager *)newUpdateManager;
|
||||
- (id)init;
|
||||
|
||||
@end
|
@ -1,32 +1,54 @@
|
||||
//
|
||||
// BWHockeySettingsViewController.m
|
||||
// HockeyDemo
|
||||
//
|
||||
// Created by Andreas Linde on 3/8/11.
|
||||
// Copyright 2011 Andreas Linde. All rights reserved.
|
||||
//
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* Copyright (c) 2011 Andreas Linde.
|
||||
* 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 "BITUpdateSettingsViewController.h"
|
||||
|
||||
#import "HockeySDK.h"
|
||||
#import "HockeySDKPrivate.h"
|
||||
|
||||
#import "BWHockeySettingsViewController.h"
|
||||
#import "BWHockeyManager.h"
|
||||
#import "BWGlobal.h"
|
||||
|
||||
#define BW_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
|
||||
|
||||
@implementation BWHockeySettingsViewController
|
||||
@implementation BITUpdateSettingsViewController
|
||||
|
||||
@synthesize hockeyManager = hockeyManager_;
|
||||
@synthesize updateManager = _updateManager;
|
||||
|
||||
- (void)dismissSettings {
|
||||
[self.navigationController dismissModalViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Initialization
|
||||
#pragma mark - Initialization
|
||||
|
||||
- (id)init:(BWHockeyManager *)newHockeyManager {
|
||||
- (id)init:(BITUpdateManager *)newUpdateManager {
|
||||
if ((self = [super init])) {
|
||||
self.hockeyManager = newHockeyManager;
|
||||
self.title = BWHockeyLocalize(@"HockeySettingsTitle");
|
||||
self.updateManager = newUpdateManager;
|
||||
self.title = BITHockeySDKLocalizedString(@"UpdateSettingsTitle");
|
||||
|
||||
CGRect frame = self.view.frame;
|
||||
frame.origin = CGPointZero;
|
||||
@ -34,22 +56,13 @@
|
||||
UITableView *tableView_ = [[[UITableView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - 260, self.view.frame.size.width, 260) style:UITableViewStyleGrouped] autorelease];
|
||||
tableView_.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleWidth;
|
||||
|
||||
BW_IF_3_2_OR_GREATER(
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
|
||||
self.view.backgroundColor = BW_RGBCOLOR(200, 202, 204);
|
||||
tableView_.backgroundColor = BW_RGBCOLOR(200, 202, 204);
|
||||
} else {
|
||||
tableView_.frame = frame;
|
||||
tableView_.autoresizingMask = tableView_.autoresizingMask | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
|
||||
}
|
||||
)
|
||||
BW_IF_PRE_3_2(
|
||||
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
|
||||
target:self
|
||||
action:@selector(dismissSettings)] autorelease];
|
||||
tableView_.frame = frame;
|
||||
tableView_.autoresizingMask = tableView_.autoresizingMask | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
|
||||
)
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) {
|
||||
self.view.backgroundColor = BW_RGBCOLOR(200, 202, 204);
|
||||
tableView_.backgroundColor = BW_RGBCOLOR(200, 202, 204);
|
||||
} else {
|
||||
tableView_.frame = frame;
|
||||
tableView_.autoresizingMask = tableView_.autoresizingMask | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin;
|
||||
}
|
||||
|
||||
tableView_.delegate = self;
|
||||
tableView_.dataSource = self;
|
||||
@ -62,18 +75,18 @@
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
return [self init:[BWHockeyManager sharedHockeyManager]];
|
||||
return [self init:[BITHockeyManager sharedHockeyManager].updateManager];
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Table view data source
|
||||
|
||||
#pragma mark - Table view data source
|
||||
|
||||
- (int)numberOfSections {
|
||||
int numberOfSections = 1;
|
||||
|
||||
if ([self.hockeyManager isAllowUserToDisableSendData]) {
|
||||
if ([self.hockeyManager shouldSendUserData]) numberOfSections++;
|
||||
if ([self.hockeyManager shouldSendUsageTime]) numberOfSections++;
|
||||
if ([_updateManager isAllowUserToDisableSendData]) {
|
||||
if ([_updateManager shouldSendUserData]) numberOfSections++;
|
||||
if ([_updateManager shouldSendUsageTime]) numberOfSections++;
|
||||
}
|
||||
|
||||
return numberOfSections;
|
||||
@ -82,7 +95,7 @@
|
||||
|
||||
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
|
||||
if (section == [self numberOfSections] - 1) {
|
||||
return BWHockeyLocalize(@"HockeySectionCheckTitle");
|
||||
return BITHockeySDKLocalizedString(@"UpdateSectionCheckTitle");
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
@ -106,10 +119,10 @@
|
||||
footer.textColor = [UIColor grayColor];
|
||||
footer.font = [UIFont systemFontOfSize:13];
|
||||
|
||||
if (section == 0 && [self.hockeyManager isAllowUserToDisableSendData] && [self.hockeyManager shouldSendUserData]) {
|
||||
footer.text = BWHockeyLocalize(@"HockeySettingsUserDataDescription");
|
||||
} else if ([self.hockeyManager isAllowUserToDisableSendData] && section < [self numberOfSections]) {
|
||||
footer.text = BWHockeyLocalize(@"HockeySettingsUsageDataDescription");
|
||||
if (section == 0 && [_updateManager isAllowUserToDisableSendData] && [_updateManager shouldSendUserData]) {
|
||||
footer.text = BITHockeySDKLocalizedString(@"UpdateSettingsUserDataDescription");
|
||||
} else if ([_updateManager isAllowUserToDisableSendData] && section < [self numberOfSections]) {
|
||||
footer.text = BITHockeySDKLocalizedString(@"UpdateSettingsUsageDataDescription");
|
||||
}
|
||||
|
||||
UIView* view = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 285, footer.frame.size.height + 6 + 11)] autorelease];
|
||||
@ -147,11 +160,11 @@
|
||||
|
||||
|
||||
- (void)sendUserData:(UISwitch *)switcher {
|
||||
[self.hockeyManager setUserAllowsSendUserData:switcher.on];
|
||||
[_updateManager setUserAllowsSendUserData:switcher.on];
|
||||
}
|
||||
|
||||
- (void)sendUsageData:(UISwitch *)switcher {
|
||||
[self.hockeyManager setUserAllowsSendUsageTime:switcher.on];
|
||||
[_updateManager setUserAllowsSendUsageTime:switcher.on];
|
||||
}
|
||||
|
||||
|
||||
@ -185,42 +198,42 @@
|
||||
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
|
||||
|
||||
// update check selection
|
||||
HockeyUpdateSetting hockeyAutoUpdateSetting = [[BWHockeyManager sharedHockeyManager] updateSetting];
|
||||
BITUpdateSetting hockeyAutoUpdateSetting = [_updateManager updateSetting];
|
||||
if (indexPath.row == 0) {
|
||||
// on startup
|
||||
cell.textLabel.text = BWHockeyLocalize(@"HockeySectionCheckStartup");
|
||||
if (hockeyAutoUpdateSetting == HockeyUpdateCheckStartup) {
|
||||
cell.textLabel.text = BITHockeySDKLocalizedString(@"UpdateSectionCheckStartup");
|
||||
if (hockeyAutoUpdateSetting == BITUpdateCheckStartup) {
|
||||
cell.accessoryType = UITableViewCellAccessoryCheckmark;
|
||||
}
|
||||
} else if (indexPath.row == 1) {
|
||||
// daily
|
||||
cell.textLabel.text = BWHockeyLocalize(@"HockeySectionCheckDaily");
|
||||
if (hockeyAutoUpdateSetting == HockeyUpdateCheckDaily) {
|
||||
cell.textLabel.text = BITHockeySDKLocalizedString(@"UpdateSectionCheckDaily");
|
||||
if (hockeyAutoUpdateSetting == BITUpdateCheckDaily) {
|
||||
cell.accessoryType = UITableViewCellAccessoryCheckmark;
|
||||
}
|
||||
} else {
|
||||
// manually
|
||||
cell.textLabel.text = BWHockeyLocalize(@"HockeySectionCheckManually");
|
||||
if (hockeyAutoUpdateSetting == HockeyUpdateCheckManually) {
|
||||
cell.textLabel.text = BITHockeySDKLocalizedString(@"UpdateSectionCheckManually");
|
||||
if (hockeyAutoUpdateSetting == BITUpdateCheckManually) {
|
||||
cell.accessoryType = UITableViewCellAccessoryCheckmark;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
UISwitch *toggleSwitch = [[[UISwitch alloc] initWithFrame:CGRectZero] autorelease];
|
||||
|
||||
if (indexPath.section == 0 && [self.hockeyManager shouldSendUserData] && [self.hockeyManager isAllowUserToDisableSendData]) {
|
||||
if (indexPath.section == 0 && [_updateManager shouldSendUserData] && [_updateManager isAllowUserToDisableSendData]) {
|
||||
// send user data
|
||||
cell.textLabel.text = BWHockeyLocalize(@"HockeySettingsUserData");
|
||||
cell.textLabel.text = BITHockeySDKLocalizedString(@"UpdateSettingsUserData");
|
||||
[toggleSwitch addTarget:self action:@selector(sendUserData:)
|
||||
forControlEvents:UIControlEventValueChanged];
|
||||
[toggleSwitch setOn:[self.hockeyManager doesUserAllowsSendUserData]];
|
||||
[toggleSwitch setOn:[_updateManager doesUserAllowsSendUserData]];
|
||||
|
||||
} else if ([self.hockeyManager shouldSendUsageTime] && [self.hockeyManager isAllowUserToDisableSendData]) {
|
||||
} else if ([_updateManager shouldSendUsageTime] && [_updateManager isAllowUserToDisableSendData]) {
|
||||
// send usage time
|
||||
cell.textLabel.text = BWHockeyLocalize(@"HockeySettingsUsageData");
|
||||
cell.textLabel.text = BITHockeySDKLocalizedString(@"UpdateSettingsUsageData");
|
||||
[toggleSwitch addTarget:self action:@selector(sendUsageData:)
|
||||
forControlEvents:UIControlEventValueChanged];
|
||||
[toggleSwitch setOn:[self.hockeyManager doesUserAllowsSendUsageTime]];
|
||||
[toggleSwitch setOn:[_updateManager doesUserAllowsSendUsageTime]];
|
||||
}
|
||||
|
||||
cell.accessoryView = toggleSwitch;
|
||||
@ -231,8 +244,7 @@
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Table view delegate
|
||||
#pragma mark - Table view delegate
|
||||
|
||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
[tableView deselectRowAtIndexPath:indexPath animated:YES];
|
||||
@ -240,43 +252,29 @@
|
||||
// update check interval selection
|
||||
if (indexPath.row == 0) {
|
||||
// on startup
|
||||
[BWHockeyManager sharedHockeyManager].updateSetting = HockeyUpdateCheckStartup;
|
||||
_updateManager.updateSetting = BITUpdateCheckStartup;
|
||||
} else if (indexPath.row == 1) {
|
||||
// daily
|
||||
[BWHockeyManager sharedHockeyManager].updateSetting = HockeyUpdateCheckDaily;
|
||||
_updateManager.updateSetting = BITUpdateCheckDaily;
|
||||
} else {
|
||||
// manually
|
||||
[BWHockeyManager sharedHockeyManager].updateSetting = HockeyUpdateCheckManually;
|
||||
_updateManager.updateSetting = BITUpdateCheckManually;
|
||||
}
|
||||
|
||||
[tableView reloadData];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Memory management
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
// Releases the view if it doesn't have a superview.
|
||||
[super didReceiveMemoryWarning];
|
||||
|
||||
// Relinquish ownership any cached data, images, etc. that aren't in use.
|
||||
}
|
||||
|
||||
- (void)viewDidUnload {
|
||||
// Relinquish ownership of anything that can be recreated in viewDidLoad or on demand.
|
||||
// For example: self.myOutlet = nil;
|
||||
}
|
||||
|
||||
#pragma mark - Memory management
|
||||
|
||||
- (void)dealloc {
|
||||
[_updateManager release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark Rotation
|
||||
#pragma mark - Rotation
|
||||
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
||||
BOOL shouldAutorotate;
|
66
Classes/BITUpdateViewController.h
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
* Peter Steinberger
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* Copyright (c) 2011 Andreas Linde, 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>
|
||||
|
||||
@class PSStoreButton;
|
||||
@class PSAppStoreHeader;
|
||||
@class BITUpdateManager;
|
||||
|
||||
typedef enum {
|
||||
AppStoreButtonStateOffline,
|
||||
AppStoreButtonStateCheck,
|
||||
AppStoreButtonStateSearching,
|
||||
AppStoreButtonStateUpdate,
|
||||
AppStoreButtonStateInstalling
|
||||
} AppStoreButtonState;
|
||||
|
||||
@interface BITUpdateViewController : UITableViewController {
|
||||
BOOL _kvoRegistered;
|
||||
BOOL _showAllVersions;
|
||||
UIStatusBarStyle _statusBarStyle;
|
||||
PSAppStoreHeader *_appStoreHeader;
|
||||
PSStoreButton *_appStoreButton;
|
||||
|
||||
id _popOverController;
|
||||
|
||||
NSMutableArray *_cells;
|
||||
|
||||
BOOL _isAppStoreEnvironment;
|
||||
}
|
||||
|
||||
@property (nonatomic, retain) BITUpdateManager *updateManager;
|
||||
@property (nonatomic, readwrite) BOOL modal;
|
||||
@property (nonatomic, readwrite) BOOL modalAnimated;
|
||||
|
||||
- (id)init:(BITUpdateManager *)newUpdateManager modal:(BOOL)newModal;
|
||||
- (id)init;
|
||||
|
||||
@end
|
@ -1,42 +1,51 @@
|
||||
//
|
||||
// BWHockeyViewController.m
|
||||
//
|
||||
// Created by Andreas Linde on 8/17/10.
|
||||
// Copyright 2010-2011 Andreas Linde, 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 Andreas Linde, 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 "NSString+HockeyAdditions.h"
|
||||
#import "BWHockeyViewController.h"
|
||||
#import "BWHockeyManager.h"
|
||||
#import "BWGlobal.h"
|
||||
#import "UIImage+HockeyAdditions.h"
|
||||
#import "NSString+BITHockeyAdditions.h"
|
||||
#import "BITAppVersionMetaInfo.h"
|
||||
#import "UIImage+BITHockeyAdditions.h"
|
||||
#import "PSAppStoreHeader.h"
|
||||
#import "PSWebTableViewCell.h"
|
||||
#import "BWHockeySettingsViewController.h"
|
||||
#import "BITUpdateSettingsViewController.h"
|
||||
#import "PSStoreButton.h"
|
||||
|
||||
#define BW_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
|
||||
#import "HockeySDK.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 kWebCellIdentifier @"PSWebTableViewCell"
|
||||
#define kAppStoreViewHeight 90
|
||||
|
||||
@interface BWHockeyViewController ()
|
||||
@interface BITUpdateViewController()<PSStoreButtonDelegate>
|
||||
// updates the whole view
|
||||
- (void)showPreviousVersionAction;
|
||||
- (void)redrawTableView;
|
||||
@ -45,89 +54,78 @@
|
||||
@end
|
||||
|
||||
|
||||
@implementation BWHockeyViewController
|
||||
@implementation BITUpdateViewController
|
||||
|
||||
@synthesize appStoreButtonState = appStoreButtonState_;
|
||||
@synthesize hockeyManager = hockeyManager_;
|
||||
@synthesize modal = modal_;
|
||||
@synthesize modalAnimated = modalAnimated_;
|
||||
@synthesize modal = _modal;
|
||||
@synthesize modalAnimated = _modalAnimated;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark private
|
||||
|
||||
- (void)restoreStoreButtonStateAnimated_:(BOOL)animated {
|
||||
if ([self.hockeyManager isAppStoreEnvironment]) {
|
||||
#pragma mark - Private
|
||||
|
||||
- (void)restoreStoreButtonStateAnimated:(BOOL)animated {
|
||||
if (_isAppStoreEnvironment) {
|
||||
[self setAppStoreButtonState:AppStoreButtonStateOffline animated:animated];
|
||||
} else if ([self.hockeyManager isUpdateAvailable]) {
|
||||
} else if ([_updateManager isUpdateAvailable]) {
|
||||
[self setAppStoreButtonState:AppStoreButtonStateUpdate animated:animated];
|
||||
} else {
|
||||
[self setAppStoreButtonState:AppStoreButtonStateCheck animated:animated];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)updateAppStoreHeader_ {
|
||||
BWApp *app = self.hockeyManager.app;
|
||||
appStoreHeader_.headerLabel = app.name;
|
||||
appStoreHeader_.middleHeaderLabel = [app versionString];
|
||||
- (void)updateAppStoreHeader {
|
||||
BITAppVersionMetaInfo *appVersion = _updateManager.newestAppVersion;
|
||||
_appStoreHeader.headerLabel = appVersion.name;
|
||||
_appStoreHeader.middleHeaderLabel = [appVersion versionString];
|
||||
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
|
||||
[formatter setDateStyle:NSDateFormatterMediumStyle];
|
||||
NSMutableString *subHeaderString = [NSMutableString string];
|
||||
if (app.date) {
|
||||
[subHeaderString appendString:[formatter stringFromDate:app.date]];
|
||||
if (appVersion.date) {
|
||||
[subHeaderString appendString:[formatter stringFromDate:appVersion.date]];
|
||||
}
|
||||
if (app.size) {
|
||||
if (appVersion.size) {
|
||||
if ([subHeaderString length]) {
|
||||
[subHeaderString appendString:@" - "];
|
||||
}
|
||||
[subHeaderString appendString:app.sizeInMB];
|
||||
[subHeaderString appendString:appVersion.sizeInMB];
|
||||
}
|
||||
appStoreHeader_.subHeaderLabel = subHeaderString;
|
||||
_appStoreHeader.subHeaderLabel = subHeaderString;
|
||||
}
|
||||
|
||||
- (void)appDidBecomeActive_ {
|
||||
if (self.appStoreButtonState == AppStoreButtonStateInstalling) {
|
||||
[self setAppStoreButtonState:AppStoreButtonStateUpdate animated:YES];
|
||||
} else if (![self.hockeyManager isCheckInProgress]) {
|
||||
[self restoreStoreButtonStateAnimated_:YES];
|
||||
} else if (![_updateManager isCheckInProgress]) {
|
||||
[self restoreStoreButtonStateAnimated:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)openSettings:(id)sender {
|
||||
BWHockeySettingsViewController *settings = [[[BWHockeySettingsViewController alloc] init] autorelease];
|
||||
BITUpdateSettingsViewController *settings = [[[BITUpdateSettingsViewController alloc] init] autorelease];
|
||||
|
||||
Class popoverControllerClass = NSClassFromString(@"UIPopoverController");
|
||||
if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad && popoverControllerClass) {
|
||||
if (popOverController_ == nil) {
|
||||
popOverController_ = [[popoverControllerClass alloc] initWithContentViewController:settings];
|
||||
if (_popOverController == nil) {
|
||||
_popOverController = [[popoverControllerClass alloc] initWithContentViewController:settings];
|
||||
}
|
||||
if ([popOverController_ contentViewController].view.window) {
|
||||
[popOverController_ dismissPopoverAnimated:YES];
|
||||
if ([_popOverController contentViewController].view.window) {
|
||||
[_popOverController dismissPopoverAnimated:YES];
|
||||
}else {
|
||||
[popOverController_ setPopoverContentSize: CGSizeMake(320, 440)];
|
||||
[popOverController_ presentPopoverFromBarButtonItem:self.navigationItem.rightBarButtonItem
|
||||
[_popOverController setPopoverContentSize: CGSizeMake(320, 440)];
|
||||
[_popOverController presentPopoverFromBarButtonItem:self.navigationItem.rightBarButtonItem
|
||||
permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES];
|
||||
}
|
||||
} else {
|
||||
|
||||
BW_IF_3_2_OR_GREATER(
|
||||
settings.modalTransitionStyle = UIModalTransitionStylePartialCurl;
|
||||
[self presentModalViewController:settings animated:YES];
|
||||
)
|
||||
BW_IF_PRE_3_2(
|
||||
UINavigationController *navController = [[[UINavigationController alloc] initWithRootViewController:settings] autorelease];
|
||||
navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
|
||||
[self presentModalViewController:navController animated:YES];
|
||||
)
|
||||
settings.modalTransitionStyle = UIModalTransitionStylePartialCurl;
|
||||
[self presentModalViewController:settings animated:YES];
|
||||
}
|
||||
}
|
||||
|
||||
- (UIImage *)addGlossToImage_:(UIImage *)image {
|
||||
BW_IF_IOS4_OR_GREATER(UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0);)
|
||||
BW_IF_PRE_IOS4(UIGraphicsBeginImageContext(image.size);)
|
||||
- (UIImage *)addGlossToImage:(UIImage *)image {
|
||||
UIGraphicsBeginImageContextWithOptions(image.size, NO, 0.0);
|
||||
|
||||
[image drawAtPoint:CGPointZero];
|
||||
UIImage *iconGradient = [UIImage bw_imageNamed:@"IconGradient.png" bundle:kHockeyBundleName];
|
||||
UIImage *iconGradient = [UIImage bit_imageNamed:@"IconGradient.png" bundle:BITHOCKEYSDK_BUNDLE];
|
||||
[iconGradient drawInRect:CGRectMake(0, 0, image.size.width, image.size.height) blendMode:kCGBlendModeNormal alpha:0.5];
|
||||
|
||||
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
|
||||
@ -161,64 +159,62 @@
|
||||
}
|
||||
|
||||
- (void)changePreviousVersionButtonBackground:(id)sender {
|
||||
[(UIButton *)sender setBackgroundColor:BW_RGBCOLOR(183,183,183)];
|
||||
[(UIButton *)sender setBackgroundColor:BIT_RGBCOLOR(183,183,183)];
|
||||
}
|
||||
|
||||
- (void)changePreviousVersionButtonBackgroundHighlighted:(id)sender {
|
||||
[(UIButton *)sender setBackgroundColor:BW_RGBCOLOR(183,183,183)];
|
||||
[(UIButton *)sender setBackgroundColor:BIT_RGBCOLOR(183,183,183)];
|
||||
}
|
||||
|
||||
- (void)showHidePreviousVersionsButton {
|
||||
BOOL multipleVersionButtonNeeded = [self.hockeyManager.apps count] > 1 && !showAllVersions_;
|
||||
BOOL multipleVersionButtonNeeded = [_updateManager.appVersions count] > 1 && !_showAllVersions;
|
||||
|
||||
if(multipleVersionButtonNeeded) {
|
||||
// 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 = BW_RGBCOLOR(200, 202, 204);
|
||||
footerView.backgroundColor = BIT_RGBCOLOR(200, 202, 204);
|
||||
UIButton *footerButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
BW_IF_IOS4_OR_GREATER(
|
||||
//footerButton.layer.shadowOffset = CGSizeMake(-2, 2);
|
||||
footerButton.layer.shadowColor = [[UIColor blackColor] CGColor];
|
||||
footerButton.layer.shadowRadius = 2.0f;
|
||||
)
|
||||
//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:BWHockeyLocalize(@"HockeyShowPreviousVersions") forState:UIControlStateNormal];
|
||||
[footerButton setTitle:BITHockeySDKLocalizedString(@"UpdateShowPreviousVersions") forState:UIControlStateNormal];
|
||||
[footerButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
|
||||
[footerButton setTitleColor:[UIColor whiteColor] forState:UIControlStateHighlighted];
|
||||
[footerButton setBackgroundImage:[UIImage bw_imageNamed:@"buttonHighlight.png" bundle:kHockeyBundleName] forState:UIControlStateHighlighted];
|
||||
[footerButton setBackgroundImage:[UIImage bit_imageNamed:@"buttonHighlight.png" bundle: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 = BW_RGBCOLOR(183,183,183);
|
||||
footerButton.backgroundColor = BIT_RGBCOLOR(183,183,183);
|
||||
[footerView addSubview:footerButton];
|
||||
self.tableView.tableFooterView = footerView;
|
||||
[self realignPreviousVersionButton];
|
||||
[footerView release];
|
||||
} else {
|
||||
self.tableView.tableFooterView = nil;
|
||||
self.tableView.backgroundColor = BW_RGBCOLOR(200, 202, 204);
|
||||
self.tableView.backgroundColor = BIT_RGBCOLOR(200, 202, 204);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)configureWebCell:(PSWebTableViewCell *)cell forApp_:(BWApp *)app {
|
||||
- (void)configureWebCell:(PSWebTableViewCell *)cell forAppVersion:(BITAppVersionMetaInfo *)appVersion {
|
||||
// create web view for a version
|
||||
NSString *installed = @"";
|
||||
if ([app.version isEqualToString:[self.hockeyManager currentAppVersion]]) {
|
||||
installed = [NSString stringWithFormat:@"<span style=\"float:%@;text-shadow:rgba(255,255,255,0.6) 1px 1px 0px;\"><b>%@</b></span>", [app isEqual:self.hockeyManager.app] ? @"left" : @"right", BWHockeyLocalize(@"HockeyInstalled")];
|
||||
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", BITHockeySDKLocalizedString(@"UpdateInstalled")];
|
||||
}
|
||||
|
||||
if ([app isEqual:self.hockeyManager.app]) {
|
||||
if ([app.notes length] > 0) {
|
||||
if ([appVersion isEqual:_updateManager.newestAppVersion]) {
|
||||
if ([appVersion.notes length] > 0) {
|
||||
installed = [NSString stringWithFormat:@"<p> %@</p>", installed];
|
||||
cell.webViewContent = [NSString stringWithFormat:@"%@%@", installed, app.notes];
|
||||
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>", BWHockeyLocalize(@"HockeyNoReleaseNotesAvailable")];
|
||||
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>", BITHockeySDKLocalizedString(@"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>", [app versionString], installed, [app dateString], [app notesOrEmptyString]];
|
||||
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.cellBackgroundColor = BW_RGBCOLOR(200, 202, 204);
|
||||
cell.cellBackgroundColor = BIT_RGBCOLOR(200, 202, 204);
|
||||
|
||||
[cell addWebView];
|
||||
// hack
|
||||
@ -227,47 +223,46 @@
|
||||
[cell addObserver:self forKeyPath:@"webViewSize" options:0 context:nil];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark NSObject
|
||||
|
||||
- (id)init:(BWHockeyManager *)newHockeyManager modal:(BOOL)newModal {
|
||||
#pragma mark - Init
|
||||
|
||||
- (id)init:(BITUpdateManager *)newUpdateManager modal:(BOOL)newModal {
|
||||
if ((self = [super initWithStyle:UITableViewStylePlain])) {
|
||||
self.hockeyManager = newHockeyManager;
|
||||
self.updateManager = newUpdateManager;
|
||||
self.modal = newModal;
|
||||
self.modalAnimated = YES;
|
||||
self.title = BWHockeyLocalize(@"HockeyUpdateScreenTitle");
|
||||
self.title = BITHockeySDKLocalizedString(@"UpdateScreenTitle");
|
||||
|
||||
if ([self.hockeyManager shouldShowUserSettings]) {
|
||||
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithImage:[UIImage bw_imageNamed:@"gear.png" bundle:kHockeyBundleName]
|
||||
_isAppStoreEnvironment = [BITHockeyManager sharedHockeyManager].isAppStoreEnvironment;
|
||||
|
||||
if ([_updateManager shouldShowUserSettings]) {
|
||||
self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithImage:[UIImage bit_imageNamed:@"gear.png" bundle:BITHOCKEYSDK_BUNDLE]
|
||||
style:UIBarButtonItemStyleBordered
|
||||
target:self
|
||||
action:@selector(openSettings:)] autorelease];
|
||||
}
|
||||
|
||||
cells_ = [[NSMutableArray alloc] initWithCapacity:5];
|
||||
popOverController_ = nil;
|
||||
_cells = [[NSMutableArray alloc] initWithCapacity:5];
|
||||
_popOverController = nil;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id)init {
|
||||
return [self init:[BWHockeyManager sharedHockeyManager] modal:NO];
|
||||
return [self init:[BITHockeyManager sharedHockeyManager].updateManager modal:NO];
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[self viewDidUnload];
|
||||
for (UITableViewCell *cell in cells_) {
|
||||
for (UITableViewCell *cell in _cells) {
|
||||
[cell removeObserver:self forKeyPath:@"webViewSize"];
|
||||
}
|
||||
[cells_ release];
|
||||
[_cells release];
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark View lifecycle
|
||||
#pragma mark - View lifecycle
|
||||
|
||||
- (void)onAction:(id)sender {
|
||||
if (self.modal) {
|
||||
@ -293,7 +288,7 @@
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
|
||||
[[UIApplication sharedApplication] setStatusBarStyle:statusBarStyle_];
|
||||
[[UIApplication sharedApplication] setStatusBarStyle:_statusBarStyle];
|
||||
}
|
||||
|
||||
- (CAGradientLayer *)backgroundLayer {
|
||||
@ -327,22 +322,22 @@
|
||||
[dnc addObserver:self selector:@selector(appDidBecomeActive_) name:UIApplicationDidBecomeActiveNotification object:nil];
|
||||
|
||||
// hook into manager with kvo!
|
||||
[self.hockeyManager addObserver:self forKeyPath:@"checkInProgress" options:0 context:nil];
|
||||
[self.hockeyManager addObserver:self forKeyPath:@"isUpdateURLOffline" options:0 context:nil];
|
||||
[self.hockeyManager addObserver:self forKeyPath:@"updateAvailable" options:0 context:nil];
|
||||
[self.hockeyManager addObserver:self forKeyPath:@"apps" options:0 context:nil];
|
||||
kvoRegistered_ = YES;
|
||||
[_updateManager addObserver:self forKeyPath:@"checkInProgress" options:0 context:nil];
|
||||
[_updateManager addObserver:self forKeyPath:@"isUpdateURLOffline" options:0 context:nil];
|
||||
[_updateManager addObserver:self forKeyPath:@"updateAvailable" options:0 context:nil];
|
||||
[_updateManager addObserver:self forKeyPath:@"apps" options:0 context:nil];
|
||||
_kvoRegistered = YES;
|
||||
|
||||
self.tableView.backgroundColor = BW_RGBCOLOR(200, 202, 204);
|
||||
self.tableView.backgroundColor = BIT_RGBCOLOR(200, 202, 204);
|
||||
self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;
|
||||
|
||||
UIView *topView = [[[UIView alloc] initWithFrame:CGRectMake(0, -(600-kAppStoreViewHeight), self.view.frame.size.width, 600)] autorelease];
|
||||
topView.autoresizingMask = UIViewAutoresizingFlexibleWidth;
|
||||
topView.backgroundColor = BW_RGBCOLOR(140, 141, 142);
|
||||
topView.backgroundColor = BIT_RGBCOLOR(140, 141, 142);
|
||||
[self.tableView addSubview:topView];
|
||||
|
||||
appStoreHeader_ = [[PSAppStoreHeader alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, kAppStoreViewHeight)];
|
||||
[self updateAppStoreHeader_];
|
||||
_appStoreHeader = [[PSAppStoreHeader alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, kAppStoreViewHeight)];
|
||||
[self updateAppStoreHeader];
|
||||
|
||||
NSString *iconString = nil;
|
||||
NSArray *icons = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleIconFiles"];
|
||||
@ -362,7 +357,7 @@
|
||||
|
||||
if (icons) {
|
||||
BOOL useHighResIcon = NO;
|
||||
BW_IF_IOS4_OR_GREATER(if ([UIScreen mainScreen].scale == 2.0f) useHighResIcon = YES;)
|
||||
if ([UIScreen mainScreen].scale == 2.0f) useHighResIcon = YES;
|
||||
|
||||
for(NSString *icon in icons) {
|
||||
iconString = icon;
|
||||
@ -386,12 +381,12 @@
|
||||
}
|
||||
|
||||
if (addGloss) {
|
||||
appStoreHeader_.iconImage = [self addGlossToImage_:[UIImage imageNamed:iconString]];
|
||||
_appStoreHeader.iconImage = [self addGlossToImage:[UIImage imageNamed:iconString]];
|
||||
} else {
|
||||
appStoreHeader_.iconImage = [UIImage imageNamed:iconString];
|
||||
_appStoreHeader.iconImage = [UIImage imageNamed:iconString];
|
||||
}
|
||||
|
||||
self.tableView.tableHeaderView = appStoreHeader_;
|
||||
self.tableView.tableHeaderView = _appStoreHeader;
|
||||
|
||||
if (self.modal) {
|
||||
self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone
|
||||
@ -406,47 +401,47 @@
|
||||
storeButton.buttonData = [PSStoreButtonData dataWithLabel:@"" colors:[PSStoreButton appStoreGrayColor] enabled:NO];
|
||||
self.appStoreButtonState = AppStoreButtonStateCheck;
|
||||
[storeButton alignToSuperview];
|
||||
appStoreButton_ = [storeButton retain];
|
||||
_appStoreButton = [storeButton retain];
|
||||
}
|
||||
|
||||
- (void)viewWillAppear:(BOOL)animated {
|
||||
if ([self.hockeyManager isAppStoreEnvironment])
|
||||
if (_isAppStoreEnvironment)
|
||||
self.appStoreButtonState = AppStoreButtonStateOffline;
|
||||
self.hockeyManager.currentHockeyViewController = self;
|
||||
_updateManager.currentHockeyViewController = self;
|
||||
[super viewWillAppear:animated];
|
||||
statusBarStyle_ = [[UIApplication sharedApplication] statusBarStyle];
|
||||
_statusBarStyle = [[UIApplication sharedApplication] statusBarStyle];
|
||||
[[UIApplication sharedApplication] setStatusBarStyle:(self.navigationController.navigationBar.barStyle == UIBarStyleDefault) ? UIStatusBarStyleDefault : UIStatusBarStyleBlackOpaque];
|
||||
[self redrawTableView];
|
||||
}
|
||||
|
||||
- (void)viewWillDisappear:(BOOL)animated {
|
||||
self.hockeyManager.currentHockeyViewController = nil;
|
||||
_updateManager.currentHockeyViewController = nil;
|
||||
//if the popover is still visible, dismiss it
|
||||
[popOverController_ dismissPopoverAnimated:YES];
|
||||
[_popOverController dismissPopoverAnimated:YES];
|
||||
[super viewWillDisappear:animated];
|
||||
[[UIApplication sharedApplication] setStatusBarStyle:statusBarStyle_];
|
||||
[[UIApplication sharedApplication] setStatusBarStyle:_statusBarStyle];
|
||||
}
|
||||
|
||||
- (void)redrawTableView {
|
||||
[self restoreStoreButtonStateAnimated_:NO];
|
||||
[self updateAppStoreHeader_];
|
||||
[self restoreStoreButtonStateAnimated:NO];
|
||||
[self updateAppStoreHeader];
|
||||
|
||||
// clean up and remove any pending overservers
|
||||
for (UITableViewCell *cell in cells_) {
|
||||
for (UITableViewCell *cell in _cells) {
|
||||
[cell removeObserver:self forKeyPath:@"webViewSize"];
|
||||
}
|
||||
[cells_ removeAllObjects];
|
||||
[_cells removeAllObjects];
|
||||
|
||||
int i = 0;
|
||||
BOOL breakAfterThisApp = NO;
|
||||
for (BWApp *app in self.hockeyManager.apps) {
|
||||
BOOL breakAfterThisAppVersion = NO;
|
||||
for (BITAppVersionMetaInfo *appVersion in _updateManager.appVersions) {
|
||||
i++;
|
||||
|
||||
// only show the newer version of the app by default, if we don't show all versions
|
||||
if (!showAllVersions_) {
|
||||
if ([app.version isEqualToString:[self.hockeyManager currentAppVersion]]) {
|
||||
if (!_showAllVersions) {
|
||||
if ([appVersion.version isEqualToString:[_updateManager currentAppVersion]]) {
|
||||
if (i == 1) {
|
||||
breakAfterThisApp = YES;
|
||||
breakAfterThisAppVersion = YES;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
@ -454,10 +449,10 @@
|
||||
}
|
||||
|
||||
PSWebTableViewCell *cell = [[[PSWebTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kWebCellIdentifier] autorelease];
|
||||
[self configureWebCell:cell forApp_:app];
|
||||
[cells_ addObject:cell];
|
||||
[self configureWebCell:cell forAppVersion:appVersion];
|
||||
[_cells addObject:cell];
|
||||
|
||||
if (breakAfterThisApp) break;
|
||||
if (breakAfterThisAppVersion) break;
|
||||
}
|
||||
|
||||
[self.tableView reloadData];
|
||||
@ -465,14 +460,14 @@
|
||||
}
|
||||
|
||||
- (void)showPreviousVersionAction {
|
||||
showAllVersions_ = YES;
|
||||
_showAllVersions = YES;
|
||||
BOOL showAllPending = NO;
|
||||
|
||||
for (BWApp *app in self.hockeyManager.apps) {
|
||||
for (BITAppVersionMetaInfo *appVersion in _updateManager.appVersions) {
|
||||
if (!showAllPending) {
|
||||
if ([app.version isEqualToString:[self.hockeyManager currentAppVersion]]) {
|
||||
if ([appVersion.version isEqualToString:[_updateManager currentAppVersion]]) {
|
||||
showAllPending = YES;
|
||||
if (app == self.hockeyManager.app) {
|
||||
if (appVersion == _updateManager.newestAppVersion) {
|
||||
continue; // skip this version already if it the latest version is the installed one
|
||||
}
|
||||
} else {
|
||||
@ -481,33 +476,32 @@
|
||||
}
|
||||
|
||||
PSWebTableViewCell *cell = [[[PSWebTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:kWebCellIdentifier] autorelease];
|
||||
[self configureWebCell:cell forApp_:app];
|
||||
[cells_ addObject:cell];
|
||||
[self configureWebCell:cell forAppVersion:appVersion];
|
||||
[_cells addObject:cell];
|
||||
}
|
||||
[self.tableView reloadData];
|
||||
[self showHidePreviousVersionsButton];
|
||||
}
|
||||
|
||||
- (void)viewDidUnload {
|
||||
[appStoreHeader_ release]; appStoreHeader_ = nil;
|
||||
[popOverController_ release], popOverController_ = nil;
|
||||
[_appStoreHeader release]; _appStoreHeader = nil;
|
||||
[_popOverController release], _popOverController = nil;
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
|
||||
// test if KVO's are registered. if class is destroyed before it was shown(viewDidLoad) no KVOs are registered.
|
||||
if (kvoRegistered_) {
|
||||
[self.hockeyManager removeObserver:self forKeyPath:@"checkInProgress"];
|
||||
[self.hockeyManager removeObserver:self forKeyPath:@"isUpdateURLOffline"];
|
||||
[self.hockeyManager removeObserver:self forKeyPath:@"updateAvailable"];
|
||||
[self.hockeyManager removeObserver:self forKeyPath:@"apps"];
|
||||
kvoRegistered_ = NO;
|
||||
if (_kvoRegistered) {
|
||||
[_updateManager removeObserver:self forKeyPath:@"checkInProgress"];
|
||||
[_updateManager removeObserver:self forKeyPath:@"isUpdateURLOffline"];
|
||||
[_updateManager removeObserver:self forKeyPath:@"updateAvailable"];
|
||||
[_updateManager removeObserver:self forKeyPath:@"apps"];
|
||||
_kvoRegistered = NO;
|
||||
}
|
||||
|
||||
[super viewDidUnload];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark Table view data source
|
||||
|
||||
#pragma mark - Table view data source
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
|
||||
return 1;
|
||||
@ -516,31 +510,30 @@
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
CGFloat rowHeight = 0;
|
||||
|
||||
if ([cells_ count] > (NSUInteger)indexPath.row) {
|
||||
PSWebTableViewCell *cell = [cells_ objectAtIndex:indexPath.row];
|
||||
if ([_cells count] > (NSUInteger)indexPath.row) {
|
||||
PSWebTableViewCell *cell = [_cells objectAtIndex:indexPath.row];
|
||||
rowHeight = cell.webViewSize.height;
|
||||
}
|
||||
|
||||
if ([self.hockeyManager.apps count] > 1 && !showAllVersions_) {
|
||||
self.tableView.backgroundColor = BW_RGBCOLOR(183, 183, 183);
|
||||
if ([_updateManager.appVersions count] > 1 && !_showAllVersions) {
|
||||
self.tableView.backgroundColor = BIT_RGBCOLOR(183, 183, 183);
|
||||
}
|
||||
|
||||
if (rowHeight == 0) {
|
||||
rowHeight = indexPath.row == 0 ? 250 : 44; // fill screen on startup
|
||||
self.tableView.backgroundColor = BW_RGBCOLOR(200, 202, 204);
|
||||
self.tableView.backgroundColor = BIT_RGBCOLOR(200, 202, 204);
|
||||
}
|
||||
|
||||
return rowHeight;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
NSInteger cellCount = [cells_ count];
|
||||
NSInteger cellCount = [_cells count];
|
||||
return cellCount;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark KVO
|
||||
|
||||
#pragma mark - KVO
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
||||
// only make changes if we are visible
|
||||
@ -549,15 +542,15 @@
|
||||
[self.tableView reloadData];
|
||||
[self realignPreviousVersionButton];
|
||||
} else if ([keyPath isEqualToString:@"checkInProgress"]) {
|
||||
if (self.hockeyManager.isCheckInProgress) {
|
||||
if (_updateManager.isCheckInProgress) {
|
||||
[self setAppStoreButtonState:AppStoreButtonStateSearching animated:YES];
|
||||
}else {
|
||||
[self restoreStoreButtonStateAnimated_:YES];
|
||||
[self restoreStoreButtonStateAnimated:YES];
|
||||
}
|
||||
} else if ([keyPath isEqualToString:@"isUpdateURLOffline"]) {
|
||||
[self restoreStoreButtonStateAnimated_:YES];
|
||||
[self restoreStoreButtonStateAnimated:YES];
|
||||
} else if ([keyPath isEqualToString:@"updateAvailable"]) {
|
||||
[self restoreStoreButtonStateAnimated_:YES];
|
||||
[self restoreStoreButtonStateAnimated:YES];
|
||||
} else if ([keyPath isEqualToString:@"apps"]) {
|
||||
[self redrawTableView];
|
||||
}
|
||||
@ -566,18 +559,16 @@
|
||||
|
||||
// Customize the appearance of table view cells.
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
if ([cells_ count] > (NSUInteger)indexPath.row) {
|
||||
return [cells_ objectAtIndex:indexPath.row];
|
||||
if ([_cells count] > (NSUInteger)indexPath.row) {
|
||||
return [_cells objectAtIndex:indexPath.row];
|
||||
} else {
|
||||
BWHockeyLog(@"Warning: cells_ and indexPath do not match? forgot calling redrawTableView?");
|
||||
BITHockeySDKLog(@"Warning: cells_ and indexPath do not match? forgot calling redrawTableView?");
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark Rotation
|
||||
#pragma mark - Rotation
|
||||
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
|
||||
BOOL shouldAutorotate;
|
||||
@ -595,12 +586,11 @@
|
||||
|
||||
- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration {
|
||||
// update all cells
|
||||
[cells_ makeObjectsPerformSelector:@selector(addWebView)];
|
||||
[_cells makeObjectsPerformSelector:@selector(addWebView)];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark PSAppStoreHeaderDelegate
|
||||
|
||||
#pragma mark - PSAppStoreHeaderDelegate
|
||||
|
||||
- (void)setAppStoreButtonState:(AppStoreButtonState)anAppStoreButtonState {
|
||||
[self setAppStoreButtonState:anAppStoreButtonState animated:NO];
|
||||
@ -611,19 +601,19 @@
|
||||
|
||||
switch (anAppStoreButtonState) {
|
||||
case AppStoreButtonStateOffline:
|
||||
[appStoreButton_ setButtonData:[PSStoreButtonData dataWithLabel:BWHockeyLocalize(@"HockeyButtonOffline") colors:[PSStoreButton appStoreGrayColor] enabled:NO] animated:animated];
|
||||
[_appStoreButton setButtonData:[PSStoreButtonData dataWithLabel:BITHockeySDKLocalizedString(@"UpdateButtonOffline") colors:[PSStoreButton appStoreGrayColor] enabled:NO] animated:animated];
|
||||
break;
|
||||
case AppStoreButtonStateCheck:
|
||||
[appStoreButton_ setButtonData:[PSStoreButtonData dataWithLabel:BWHockeyLocalize(@"HockeyButtonCheck") colors:[PSStoreButton appStoreGreenColor] enabled:YES] animated:animated];
|
||||
[_appStoreButton setButtonData:[PSStoreButtonData dataWithLabel:BITHockeySDKLocalizedString(@"UpdateButtonCheck") colors:[PSStoreButton appStoreGreenColor] enabled:YES] animated:animated];
|
||||
break;
|
||||
case AppStoreButtonStateSearching:
|
||||
[appStoreButton_ setButtonData:[PSStoreButtonData dataWithLabel:BWHockeyLocalize(@"HockeyButtonSearching") colors:[PSStoreButton appStoreGrayColor] enabled:NO] animated:animated];
|
||||
[_appStoreButton setButtonData:[PSStoreButtonData dataWithLabel:BITHockeySDKLocalizedString(@"UpdateButtonSearching") colors:[PSStoreButton appStoreGrayColor] enabled:NO] animated:animated];
|
||||
break;
|
||||
case AppStoreButtonStateUpdate:
|
||||
[appStoreButton_ setButtonData:[PSStoreButtonData dataWithLabel:BWHockeyLocalize(@"HockeyButtonUpdate") colors:[PSStoreButton appStoreBlueColor] enabled:YES] animated:animated];
|
||||
[_appStoreButton setButtonData:[PSStoreButtonData dataWithLabel:BITHockeySDKLocalizedString(@"UpdateButtonUpdate") colors:[PSStoreButton appStoreBlueColor] enabled:YES] animated:animated];
|
||||
break;
|
||||
case AppStoreButtonStateInstalling:
|
||||
[appStoreButton_ setButtonData:[PSStoreButtonData dataWithLabel:BWHockeyLocalize(@"HockeyButtonInstalling") colors:[PSStoreButton appStoreGrayColor] enabled:NO] animated:animated];
|
||||
[_appStoreButton setButtonData:[PSStoreButtonData dataWithLabel:BITHockeySDKLocalizedString(@"UpdateButtonInstalling") colors:[PSStoreButton appStoreGrayColor] enabled:NO] animated:animated];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -633,10 +623,10 @@
|
||||
- (void)storeButtonFired:(PSStoreButton *)button {
|
||||
switch (appStoreButtonState_) {
|
||||
case AppStoreButtonStateCheck:
|
||||
[self.hockeyManager checkForUpdateShowFeedback:YES];
|
||||
[_updateManager checkForUpdateShowFeedback:YES];
|
||||
break;
|
||||
case AppStoreButtonStateUpdate:
|
||||
if ([self.hockeyManager initiateAppDownload]) {
|
||||
if ([_updateManager initiateAppDownload]) {
|
||||
[self setAppStoreButtonState:AppStoreButtonStateInstalling animated:YES];
|
||||
};
|
||||
break;
|
@ -1,56 +0,0 @@
|
||||
//
|
||||
// BWApp.h
|
||||
// HockeyDemo
|
||||
//
|
||||
// Created by Peter Steinberger on 04.02.11.
|
||||
// Copyright 2011 Buzzworks. 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>
|
||||
|
||||
@interface BWApp : NSObject {
|
||||
NSString *name_;
|
||||
NSString *version_;
|
||||
NSString *shortVersion_;
|
||||
NSString *notes_;
|
||||
NSDate *date_;
|
||||
NSNumber *size_;
|
||||
NSNumber *mandatory_;
|
||||
}
|
||||
@property (nonatomic, copy) NSString *name;
|
||||
@property (nonatomic, copy) NSString *version;
|
||||
@property (nonatomic, copy) NSString *shortVersion;
|
||||
@property (nonatomic, copy) NSString *notes;
|
||||
@property (nonatomic, copy) NSDate *date;
|
||||
@property (nonatomic, copy) NSNumber *size;
|
||||
@property (nonatomic, copy) NSNumber *mandatory;
|
||||
|
||||
- (NSString *)nameAndVersionString;
|
||||
- (NSString *)versionString;
|
||||
- (NSString *)dateString;
|
||||
- (NSString *)sizeInMB;
|
||||
- (NSString *)notesOrEmptyString;
|
||||
- (void)setDateWithTimestamp:(NSTimeInterval)timestamp;
|
||||
- (BOOL)isValid;
|
||||
- (BOOL)isEqualToBWApp:(BWApp *)anApp;
|
||||
|
||||
+ (BWApp *)appFromDict:(NSDictionary *)dict;
|
||||
|
||||
@end
|
186
Classes/BWApp.m
@ -1,186 +0,0 @@
|
||||
//
|
||||
// BWApp.m
|
||||
// HockeyDemo
|
||||
//
|
||||
// Created by Peter Steinberger on 04.02.11.
|
||||
// Copyright 2011 Buzzworks. 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 "BWApp.h"
|
||||
#import "BWGlobal.h"
|
||||
|
||||
@implementation BWApp
|
||||
|
||||
@synthesize name = name_;
|
||||
@synthesize version = version_;
|
||||
@synthesize shortVersion = shortVersion_;
|
||||
@synthesize notes = notes_;
|
||||
@synthesize date = date_;
|
||||
@synthesize size = size_;
|
||||
@synthesize mandatory = mandatory_;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark static
|
||||
|
||||
+ (BWApp *)appFromDict:(NSDictionary *)dict {
|
||||
BWApp *app = [[[[self class] alloc] init] autorelease];
|
||||
|
||||
// NSParameterAssert([dict isKindOfClass:[NSDictionary class]]);
|
||||
if ([dict isKindOfClass:[NSDictionary class]]) {
|
||||
app.name = [dict objectForKey:@"title"];
|
||||
app.version = [dict objectForKey:@"version"];
|
||||
app.shortVersion = [dict objectForKey:@"shortversion"];
|
||||
[app setDateWithTimestamp:[[dict objectForKey:@"timestamp"] doubleValue]];
|
||||
app.size = [dict objectForKey:@"appsize"];
|
||||
app.notes = [dict objectForKey:@"notes"];
|
||||
app.mandatory = [dict objectForKey:@"mandatory"];
|
||||
}
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark NSObject
|
||||
|
||||
- (void)dealloc {
|
||||
[name_ release];
|
||||
[version_ release];
|
||||
[shortVersion_ release];
|
||||
[notes_ release];
|
||||
[date_ release];
|
||||
[size_ release];
|
||||
[mandatory_ release];
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)other {
|
||||
if (other == self)
|
||||
return YES;
|
||||
if (!other || ![other isKindOfClass:[self class]])
|
||||
return NO;
|
||||
return [self isEqualToBWApp:other];
|
||||
}
|
||||
|
||||
- (BOOL)isEqualToBWApp:(BWApp *)anApp {
|
||||
if (self == anApp)
|
||||
return YES;
|
||||
if (self.name != anApp.name && ![self.name isEqualToString:anApp.name])
|
||||
return NO;
|
||||
if (self.version != anApp.version && ![self.version isEqualToString:anApp.version])
|
||||
return NO;
|
||||
if (self.shortVersion != anApp.shortVersion && ![self.shortVersion isEqualToString:anApp.shortVersion])
|
||||
return NO;
|
||||
if (self.notes != anApp.notes && ![self.notes isEqualToString:anApp.notes])
|
||||
return NO;
|
||||
if (self.date != anApp.date && ![self.date isEqualToDate:anApp.date])
|
||||
return NO;
|
||||
if (self.size != anApp.size && ![self.size isEqualToNumber:anApp.size])
|
||||
return NO;
|
||||
if (self.mandatory != anApp.mandatory && ![self.mandatory isEqualToNumber:anApp.mandatory])
|
||||
return NO;
|
||||
return YES;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark NSCoder
|
||||
|
||||
- (void)encodeWithCoder:(NSCoder *)encoder {
|
||||
[encoder encodeObject:self.name forKey:@"name"];
|
||||
[encoder encodeObject:self.version forKey:@"version"];
|
||||
[encoder encodeObject:self.shortVersion forKey:@"shortVersion"];
|
||||
[encoder encodeObject:self.notes forKey:@"notes"];
|
||||
[encoder encodeObject:self.date forKey:@"date"];
|
||||
[encoder encodeObject:self.size forKey:@"size"];
|
||||
[encoder encodeObject:self.mandatory forKey:@"mandatory"];
|
||||
}
|
||||
|
||||
- (id)initWithCoder:(NSCoder *)decoder {
|
||||
if ((self = [super init])) {
|
||||
self.name = [decoder decodeObjectForKey:@"name"];
|
||||
self.version = [decoder decodeObjectForKey:@"version"];
|
||||
self.shortVersion = [decoder decodeObjectForKey:@"shortVersion"];
|
||||
self.notes = [decoder decodeObjectForKey:@"notes"];
|
||||
self.date = [decoder decodeObjectForKey:@"date"];
|
||||
self.size = [decoder decodeObjectForKey:@"size"];
|
||||
self.mandatory = [decoder decodeObjectForKey:@"mandatory"];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark Properties
|
||||
|
||||
- (NSString *)nameAndVersionString {
|
||||
NSString *appNameAndVersion = [NSString stringWithFormat:@"%@ %@", self.name, [self versionString]];
|
||||
return appNameAndVersion;
|
||||
}
|
||||
|
||||
- (NSString *)versionString {
|
||||
NSString *shortString = ([self.shortVersion respondsToSelector:@selector(length)] && [self.shortVersion length]) ? [NSString stringWithFormat:@"%@", self.shortVersion] : @"";
|
||||
NSString *versionString = [shortString length] ? [NSString stringWithFormat:@" (%@)", self.version] : self.version;
|
||||
return [NSString stringWithFormat:@"%@ %@%@", BWHockeyLocalize(@"HockeyVersion"), shortString, versionString];
|
||||
}
|
||||
|
||||
- (NSString *)dateString {
|
||||
NSDateFormatter *formatter = [[[NSDateFormatter alloc] init] autorelease];
|
||||
[formatter setDateStyle:NSDateFormatterMediumStyle];
|
||||
|
||||
return [formatter stringFromDate:self.date];
|
||||
}
|
||||
|
||||
- (NSString *)sizeInMB {
|
||||
if ([size_ isKindOfClass: [NSNumber class]] && [size_ doubleValue] > 0) {
|
||||
double appSizeInMB = [size_ doubleValue]/(1024*1024);
|
||||
NSString *appSizeString = [NSString stringWithFormat:@"%.1f MB", appSizeInMB];
|
||||
return appSizeString;
|
||||
}
|
||||
|
||||
return @"0 MB";
|
||||
}
|
||||
|
||||
- (void)setDateWithTimestamp:(NSTimeInterval)timestamp {
|
||||
if (timestamp) {
|
||||
NSDate *appDate = [NSDate dateWithTimeIntervalSince1970:timestamp];
|
||||
self.date = appDate;
|
||||
} else {
|
||||
self.date = nil;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSString *)notesOrEmptyString {
|
||||
if (self.notes) {
|
||||
return self.notes;
|
||||
}else {
|
||||
return [NSString string];
|
||||
}
|
||||
}
|
||||
|
||||
// a valid app needs at least following properties: name, version, date
|
||||
- (BOOL)isValid {
|
||||
BOOL valid = [self.name length] && [self.version length] && self.date;
|
||||
return valid;
|
||||
}
|
||||
|
||||
@end
|
@ -1,127 +0,0 @@
|
||||
//
|
||||
// BWGlobal.h
|
||||
//
|
||||
// Created by Andreas Linde on 08/17/10.
|
||||
// Copyright 2010-2011 Andreas Linde, 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 "BWHockeyManager.h"
|
||||
#import "BWApp.h"
|
||||
|
||||
#define SDK_NAME @"HockeySDK"
|
||||
#define SDK_VERSION @"2.2.6"
|
||||
|
||||
#ifndef HOCKEY_BLOCK_UDID
|
||||
#define HOCKEY_BLOCK_UDID 1
|
||||
#endif
|
||||
|
||||
// uncomment this line to enable NSLog-debugging output
|
||||
//#define kHockeyDebugEnabled
|
||||
|
||||
#define kArrayOfLastHockeyCheck @"ArrayOfLastHockeyCheck"
|
||||
#define kDateOfLastHockeyCheck @"DateOfLastHockeyCheck"
|
||||
#define kDateOfVersionInstallation @"DateOfVersionInstallation"
|
||||
#define kUsageTimeOfCurrentVersion @"UsageTimeOfCurrentVersion"
|
||||
#define kUsageTimeForVersionString @"kUsageTimeForVersionString"
|
||||
#define kHockeyAutoUpdateSetting @"HockeyAutoUpdateSetting"
|
||||
#define kHockeyAllowUserSetting @"HockeyAllowUserSetting"
|
||||
#define kHockeyAllowUsageSetting @"HockeyAllowUsageSetting"
|
||||
#define kHockeyAutoUpdateSetting @"HockeyAutoUpdateSetting"
|
||||
#define kHockeyAuthorizedVersion @"HockeyAuthorizedVersion"
|
||||
#define kHockeyAuthorizedToken @"HockeyAuthorizedToken"
|
||||
|
||||
#define kHockeyBundleName @"Hockey.bundle"
|
||||
|
||||
// Notification message which HockeyManager is listening to, to retry requesting updated from the server
|
||||
#define BWHockeyNetworkBecomeReachable @"NetworkDidBecomeReachable"
|
||||
|
||||
#define BWHockeyLog(fmt, ...) do { if([BWHockeyManager sharedHockeyManager].isLoggingEnabled) { NSLog((@"[HockeyLib] %s/%d " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); }} while(0)
|
||||
|
||||
NSBundle *hockeyBundle(void);
|
||||
NSString *BWmd5(NSString *str);
|
||||
NSString *BWHockeyLocalize(NSString *stringToken);
|
||||
|
||||
// compatibility helper
|
||||
#ifdef HOCKEYLIB_STATIC_LIBRARY
|
||||
// If HockeyLib is built as a static library and linked into the project
|
||||
// we can't use this project's deployment target to statically decide if
|
||||
// native JSON is available
|
||||
#define BW_NATIVE_JSON_AVAILABLE 0
|
||||
#else
|
||||
#define BW_NATIVE_JSON_AVAILABLE __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
|
||||
#endif
|
||||
|
||||
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_3_2
|
||||
#define kCFCoreFoundationVersionNumber_iPhoneOS_3_2 478.61
|
||||
#endif
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 32000
|
||||
#define BW_IF_3_2_OR_GREATER(...) \
|
||||
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_3_2) \
|
||||
{ \
|
||||
__VA_ARGS__ \
|
||||
}
|
||||
#else
|
||||
#define BW_IF_3_2_OR_GREATER(...)
|
||||
#endif
|
||||
#define BW_IF_PRE_3_2(...) \
|
||||
if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_3_2) \
|
||||
{ \
|
||||
__VA_ARGS__ \
|
||||
}
|
||||
|
||||
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_4_0
|
||||
#define kCFCoreFoundationVersionNumber_iPhoneOS_4_0 550.32
|
||||
#endif
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
|
||||
#define BW_IF_IOS4_OR_GREATER(...) \
|
||||
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_4_0) \
|
||||
{ \
|
||||
__VA_ARGS__ \
|
||||
}
|
||||
#else
|
||||
#define BW_IF_IOS4_OR_GREATER(...)
|
||||
#endif
|
||||
|
||||
#define BW_IF_PRE_IOS4(...) \
|
||||
if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_4_0) \
|
||||
{ \
|
||||
__VA_ARGS__ \
|
||||
}
|
||||
|
||||
|
||||
|
||||
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_5_0
|
||||
#define kCFCoreFoundationVersionNumber_iPhoneOS_5_0 674.0
|
||||
#endif
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 50000
|
||||
#define BW_IF_IOS5_OR_GREATER(...) \
|
||||
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_5_0) \
|
||||
{ \
|
||||
__VA_ARGS__ \
|
||||
}
|
||||
#else
|
||||
#define BW_IF_IOS5_OR_GREATER(...)
|
||||
#endif
|
||||
|
||||
#define BW_IF_PRE_IOS5(...) \
|
||||
if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_5_0) \
|
||||
{ \
|
||||
__VA_ARGS__ \
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
//
|
||||
// BWGlobal.h
|
||||
//
|
||||
// Created by Andreas Linde on 08/17/10.
|
||||
// Copyright 2010-2011 Andreas Linde, 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 "BWGlobal.h"
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
|
||||
NSBundle *hockeyBundle(void) {
|
||||
static NSBundle* bundle = nil;
|
||||
if (!bundle) {
|
||||
NSString* path = [[[NSBundle mainBundle] resourcePath]
|
||||
stringByAppendingPathComponent:kHockeyBundleName];
|
||||
bundle = [[NSBundle bundleWithPath:path] retain];
|
||||
}
|
||||
return bundle;
|
||||
}
|
||||
|
||||
NSString *BWmd5(NSString *str) {
|
||||
const char *cStr = [str UTF8String];
|
||||
unsigned char result[CC_MD5_DIGEST_LENGTH];
|
||||
CC_MD5( cStr, strlen(cStr), result );
|
||||
return [NSString
|
||||
stringWithFormat: @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
result[0], result[1],
|
||||
result[2], result[3],
|
||||
result[4], result[5],
|
||||
result[6], result[7],
|
||||
result[8], result[9],
|
||||
result[10], result[11],
|
||||
result[12], result[13],
|
||||
result[14], result[15]
|
||||
];
|
||||
}
|
||||
|
||||
NSString *BWHockeyLocalize(NSString *stringToken) {
|
||||
if (hockeyBundle()) {
|
||||
return NSLocalizedStringFromTableInBundle(stringToken, @"Hockey", hockeyBundle(), @"");
|
||||
} else {
|
||||
return stringToken;
|
||||
}
|
||||
}
|
@ -1,266 +0,0 @@
|
||||
//
|
||||
// BWHockeyManager.h
|
||||
//
|
||||
// Created by Andreas Linde on 8/17/10.
|
||||
// Copyright 2010-2011 Andreas Linde. 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>
|
||||
#import "BWHockeyViewController.h"
|
||||
#import "BWGlobal.h"
|
||||
|
||||
|
||||
typedef enum {
|
||||
HockeyComparisonResultDifferent,
|
||||
HockeyComparisonResultGreater
|
||||
} HockeyComparisonResult;
|
||||
|
||||
typedef enum {
|
||||
HockeyAuthorizationDenied,
|
||||
HockeyAuthorizationAllowed,
|
||||
HockeyAuthorizationPending
|
||||
} HockeyAuthorizationState;
|
||||
|
||||
typedef enum {
|
||||
HockeyUpdateCheckStartup = 0,
|
||||
HockeyUpdateCheckDaily = 1,
|
||||
HockeyUpdateCheckManually = 2
|
||||
} HockeyUpdateSetting;
|
||||
|
||||
@protocol BWHockeyManagerDelegate;
|
||||
|
||||
@class BWApp;
|
||||
|
||||
@interface BWHockeyManager : NSObject <UIAlertViewDelegate> {
|
||||
id <BWHockeyManagerDelegate> delegate_;
|
||||
NSArray *apps_;
|
||||
|
||||
NSString *updateURL_;
|
||||
NSString *appIdentifier_;
|
||||
NSString *currentAppVersion_;
|
||||
|
||||
UINavigationController *navController_;
|
||||
BWHockeyViewController *currentHockeyViewController_;
|
||||
UIView *authorizeView_;
|
||||
|
||||
NSMutableData *receivedData_;
|
||||
|
||||
BOOL loggingEnabled_;
|
||||
BOOL checkInProgress_;
|
||||
BOOL dataFound;
|
||||
BOOL updateAvailable_;
|
||||
BOOL showFeedback_;
|
||||
BOOL updateURLOffline_;
|
||||
BOOL updateAlertShowing_;
|
||||
BOOL lastCheckFailed_;
|
||||
|
||||
BOOL isAppStoreEnvironment_;
|
||||
|
||||
NSURLConnection *urlConnection_;
|
||||
NSDate *lastCheck_;
|
||||
NSDate *usageStartTimestamp_;
|
||||
|
||||
BOOL sendUserData_;
|
||||
BOOL sendUsageTime_;
|
||||
BOOL allowUserToDisableSendData_;
|
||||
BOOL userAllowsSendUserData_;
|
||||
BOOL userAllowsSendUsageTime_;
|
||||
BOOL showUpdateReminder_;
|
||||
BOOL checkForUpdateOnLaunch_;
|
||||
HockeyComparisonResult compareVersionType_;
|
||||
HockeyUpdateSetting updateSetting_;
|
||||
BOOL showUserSettings_;
|
||||
BOOL showDirectInstallOption_;
|
||||
|
||||
BOOL requireAuthorization_;
|
||||
NSString *authenticationSecret_;
|
||||
|
||||
BOOL checkForTracker_;
|
||||
NSDictionary *trackerConfig_;
|
||||
|
||||
UIBarStyle barStyle_;
|
||||
UIModalPresentationStyle modalPresentationStyle_;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// this is a singleton
|
||||
+ (BWHockeyManager *)sharedHockeyManager;
|
||||
|
||||
// update url needs to be set
|
||||
@property (nonatomic, retain) NSString *updateURL;
|
||||
|
||||
// private app identifier (optional)
|
||||
@property (nonatomic, retain) NSString *appIdentifier;
|
||||
|
||||
// delegate is optional
|
||||
@property (nonatomic, assign) id <BWHockeyManagerDelegate> delegate;
|
||||
|
||||
// hockey secret is required if authentication is used
|
||||
@property (nonatomic, retain) NSString *authenticationSecret;
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Setting Properties
|
||||
|
||||
// if YES, states will be logged using NSLog. Only enable this for debugging!
|
||||
// if NO, nothing will be logged. (default)
|
||||
@property (nonatomic, assign, getter=isLoggingEnabled) BOOL loggingEnabled;
|
||||
|
||||
// if YES, the current user data is send: device type, iOS version, app version, UDID (default)
|
||||
// if NO, no such data is send to the server
|
||||
@property (nonatomic, assign, getter=shouldSendUserData) BOOL sendUserData;
|
||||
|
||||
// if YES, the the users usage time of the app to the service, only in 1 minute granularity! (default)
|
||||
// if NO, no such data is send to the server
|
||||
@property (nonatomic, assign, getter=shouldSendUsageTime) BOOL sendUsageTime;
|
||||
|
||||
// if YES, the user agrees to send the usage data, user can change it if the developer shows the settings (default)
|
||||
// if NO, the user overwrites the developer setting and no such data is sent
|
||||
@property (nonatomic, assign, getter=isAllowUserToDisableSendData) BOOL allowUserToDisableSendData;
|
||||
|
||||
// if YES, the user allowed to send user data (default)
|
||||
// if NO, the user denied to send user data
|
||||
@property (nonatomic, assign, getter=doesUserAllowsSendUserData) BOOL userAllowsSendUserData;
|
||||
|
||||
// if YES, the user allowed to send usage data (default)
|
||||
// if NO, the user denied to send usage data
|
||||
@property (nonatomic, assign, getter=doesUserAllowsSendUsageTime) BOOL userAllowsSendUsageTime;
|
||||
|
||||
// if YES, the new version alert will be displayed always if the current version is outdated (default)
|
||||
// if NO, the alert will be displayed only once for each new update
|
||||
@property (nonatomic, assign) BOOL alwaysShowUpdateReminder;
|
||||
|
||||
// if YES, the user can change the HockeyUpdateSetting value (default)
|
||||
// if NO, the user can not change it, and the default or developer defined value will be used
|
||||
@property (nonatomic, assign, getter=shouldShowUserSettings) BOOL showUserSettings;
|
||||
|
||||
// set bar style of navigation controller
|
||||
@property (nonatomic, assign) UIBarStyle barStyle;
|
||||
|
||||
// set modal presentation style of update view
|
||||
@property (nonatomic, assign) UIModalPresentationStyle modalPresentationStyle;
|
||||
|
||||
// if YES, then an update check will be performed after the application becomes active (default)
|
||||
// if NO, then the update check will not happen unless invoked explicitly
|
||||
@property (nonatomic, assign, getter=isCheckForUpdateOnLaunch) BOOL checkForUpdateOnLaunch;
|
||||
|
||||
// if YES, the alert notifying about an new update also shows a button to install the update directly
|
||||
// if NO, the alert notifying about an new update only shows ignore and show update button
|
||||
@property (nonatomic, assign, getter=isShowingDirectInstallOption) BOOL showDirectInstallOption;
|
||||
|
||||
// if YES, each app version needs to be authorized by the server to run on this device
|
||||
// if NO, each app version does not need to be authorized (default)
|
||||
@property (nonatomic, assign, getter=isRequireAuthorization) BOOL requireAuthorization;
|
||||
|
||||
// HockeyComparisonResultDifferent: alerts if the version on the server is different (default)
|
||||
// HockeyComparisonResultGreater: alerts if the version on the server is greater
|
||||
@property (nonatomic, assign) HockeyComparisonResult compareVersionType;
|
||||
|
||||
// see HockeyUpdateSetting-enum. Will be saved in user defaults.
|
||||
// default value: HockeyUpdateCheckStartup
|
||||
@property (nonatomic, assign) HockeyUpdateSetting updateSetting;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Private Properties
|
||||
|
||||
// if YES, the API will return an existing JMC config
|
||||
// if NO, the API will return only version information
|
||||
@property (nonatomic, assign) BOOL checkForTracker;
|
||||
|
||||
// Contains the tracker config if received from server
|
||||
@property (nonatomic, retain, readonly) NSDictionary *trackerConfig;
|
||||
|
||||
// if YES the app is installed from the app store
|
||||
// if NO the app is installed via ad-hoc or enterprise distribution
|
||||
@property (nonatomic, readonly) BOOL isAppStoreEnvironment;
|
||||
|
||||
// is an update available?
|
||||
- (BOOL)isUpdateAvailable;
|
||||
|
||||
// are we currently checking for updates?
|
||||
- (BOOL)isCheckInProgress;
|
||||
|
||||
// open update info view
|
||||
- (void)showUpdateView;
|
||||
|
||||
// manually start an update check
|
||||
- (void)checkForUpdate;
|
||||
|
||||
// checks for update, informs the user (error, no update found, etc)
|
||||
- (void)checkForUpdateShowFeedback:(BOOL)feedback;
|
||||
|
||||
// initiates app-download call. displays an system UIAlertView
|
||||
- (BOOL)initiateAppDownload;
|
||||
|
||||
// checks wether this app version is authorized
|
||||
- (BOOL)appVersionIsAuthorized;
|
||||
|
||||
// start checking for an authorization key
|
||||
- (void)checkForAuthorization;
|
||||
|
||||
// convenience methode to create hockey view controller
|
||||
- (BWHockeyViewController *)hockeyViewController:(BOOL)modal;
|
||||
|
||||
// get/set current active hockey view controller
|
||||
@property (nonatomic, retain) BWHockeyViewController *currentHockeyViewController;
|
||||
|
||||
// convenience method to get current running version string
|
||||
- (NSString *)currentAppVersion;
|
||||
|
||||
// get newest app or array of all available versions
|
||||
- (BWApp *)app;
|
||||
|
||||
- (NSArray *)apps;
|
||||
|
||||
// check if there is any newer version mandatory
|
||||
- (BOOL)hasNewerMandatoryVersion;
|
||||
|
||||
@end
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@protocol BWHockeyManagerDelegate <NSObject>
|
||||
|
||||
/*
|
||||
Return the device UDID which is required for beta testing, should return nil for app store configuration!
|
||||
Example implementation if your configuration for the App Store is called "AppStore":
|
||||
|
||||
#ifndef (CONFIGURATION_AppStore)
|
||||
if ([[UIDevice currentDevice] respondsToSelector:@selector(uniqueIdentifier)])
|
||||
return [[UIDevice currentDevice] performSelector:@selector(uniqueIdentifier)];
|
||||
#endif
|
||||
return nil;
|
||||
|
||||
*/
|
||||
- (NSString *)customDeviceIdentifier;
|
||||
|
||||
@optional
|
||||
|
||||
// Invoked when the internet connection is started, to let the app enable the activity indicator
|
||||
- (void)connectionOpened;
|
||||
|
||||
// Invoked when the internet connection is closed, to let the app disable the activity indicator
|
||||
- (void)connectionClosed;
|
||||
|
||||
// optional parent view controller for the update screen when invoked via the alert view, default is the root UIWindow instance
|
||||
- (UIViewController *)viewControllerForHockeyController:(BWHockeyManager *)hockeyController;
|
||||
|
||||
@end
|
@ -1,22 +0,0 @@
|
||||
//
|
||||
// BWHockeySettingsViewController.h
|
||||
// HockeyDemo
|
||||
//
|
||||
// Created by Andreas Linde on 3/8/11.
|
||||
// Copyright 2011 Andreas Linde. All rights reserved.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class BWHockeyManager;
|
||||
|
||||
@interface BWHockeySettingsViewController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
|
||||
BWHockeyManager *hockeyManager_;
|
||||
}
|
||||
|
||||
@property (nonatomic, retain) BWHockeyManager *hockeyManager;
|
||||
|
||||
- (id)init:(BWHockeyManager *)newHockeyManager;
|
||||
- (id)init;
|
||||
|
||||
@end
|
@ -1,68 +0,0 @@
|
||||
//
|
||||
// BWHockeyViewController.h
|
||||
//
|
||||
// Created by Andreas Linde on 8/17/10.
|
||||
// Copyright 2010-2011 Andreas Linde. 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>
|
||||
#import "PSStoreButton.h"
|
||||
|
||||
@class PSAppStoreHeader;
|
||||
|
||||
typedef enum {
|
||||
AppStoreButtonStateOffline,
|
||||
AppStoreButtonStateCheck,
|
||||
AppStoreButtonStateSearching,
|
||||
AppStoreButtonStateUpdate,
|
||||
AppStoreButtonStateInstalling
|
||||
} AppStoreButtonState;
|
||||
|
||||
|
||||
@class BWHockeyManager;
|
||||
|
||||
@interface BWHockeyViewController : UITableViewController <PSStoreButtonDelegate> {
|
||||
BWHockeyManager *hockeyManager_;
|
||||
|
||||
NSDictionary *cellLayout;
|
||||
|
||||
BOOL modal_;
|
||||
BOOL modalAnimated_;
|
||||
BOOL kvoRegistered_;
|
||||
BOOL showAllVersions_;
|
||||
UIStatusBarStyle statusBarStyle_;
|
||||
PSAppStoreHeader *appStoreHeader_;
|
||||
PSStoreButton *appStoreButton_;
|
||||
|
||||
id popOverController_;
|
||||
|
||||
AppStoreButtonState appStoreButtonState_;
|
||||
|
||||
NSMutableArray *cells_;
|
||||
}
|
||||
|
||||
@property (nonatomic, retain) BWHockeyManager *hockeyManager;
|
||||
@property (nonatomic, readwrite) BOOL modal;
|
||||
@property (nonatomic, readwrite) BOOL modalAnimated;
|
||||
|
||||
- (id)init:(BWHockeyManager *)newHockeyManager modal:(BOOL)newModal;
|
||||
- (id)init;
|
||||
|
||||
@end
|
@ -1,201 +0,0 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
* Kent Sutherland
|
||||
*
|
||||
* Copyright (c) 2011 Andreas Linde & Kent Sutherland.
|
||||
* 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 "BWQuincyManagerDelegate.h"
|
||||
|
||||
#define BWQuincyLog(fmt, ...) do { if([BWQuincyManager sharedQuincyManager].isLoggingEnabled) { NSLog((@"[QuincyLib] %s/%d " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); }} while(0)
|
||||
|
||||
#define kQuincyBundleName @"Quincy.bundle"
|
||||
|
||||
NSBundle *quincyBundle(void);
|
||||
NSString *BWQuincyLocalize(NSString *stringToken);
|
||||
|
||||
//#define BWQuincyLocalize(StringToken) NSLocalizedStringFromTableInBundle(StringToken, @"Quincy", quincyBundle(), @"")
|
||||
|
||||
// flags if the crashlog analyzer is started. since this may theoretically crash we need to track it
|
||||
#define kQuincyKitAnalyzerStarted @"QuincyKitAnalyzerStarted"
|
||||
|
||||
// flags if the QuincyKit is activated at all
|
||||
#define kQuincyKitActivated @"QuincyKitActivated"
|
||||
|
||||
// flags if the crashreporter should automatically send crashes without asking the user again
|
||||
#define kAutomaticallySendCrashReports @"AutomaticallySendCrashReports"
|
||||
|
||||
// stores the set of crashreports that have been approved but aren't sent yet
|
||||
#define kApprovedCrashReports @"ApprovedCrashReports"
|
||||
|
||||
// Notification message which QuincyManager is listening to, to retry sending pending crash reports to the server
|
||||
#define BWQuincyNetworkBecomeReachable @"NetworkDidBecomeReachable"
|
||||
|
||||
typedef enum QuincyKitAlertType {
|
||||
QuincyKitAlertTypeSend = 0,
|
||||
QuincyKitAlertTypeFeedback = 1,
|
||||
} CrashAlertType;
|
||||
|
||||
typedef enum CrashReportStatus {
|
||||
// The status of the crash is queued, need to check later (HockeyApp)
|
||||
CrashReportStatusQueued = -80,
|
||||
|
||||
// This app version is set to discontinued, no new crash reports accepted by the server
|
||||
CrashReportStatusFailureVersionDiscontinued = -30,
|
||||
|
||||
// XML: Sender version string contains not allowed characters, only alphanumberical including space and . are allowed
|
||||
CrashReportStatusFailureXMLSenderVersionNotAllowed = -21,
|
||||
|
||||
// XML: Version string contains not allowed characters, only alphanumberical including space and . are allowed
|
||||
CrashReportStatusFailureXMLVersionNotAllowed = -20,
|
||||
|
||||
// SQL for adding a symoblicate todo entry in the database failed
|
||||
CrashReportStatusFailureSQLAddSymbolicateTodo = -18,
|
||||
|
||||
// SQL for adding crash log in the database failed
|
||||
CrashReportStatusFailureSQLAddCrashlog = -17,
|
||||
|
||||
// SQL for adding a new version in the database failed
|
||||
CrashReportStatusFailureSQLAddVersion = -16,
|
||||
|
||||
// SQL for checking if the version is already added in the database failed
|
||||
CrashReportStatusFailureSQLCheckVersionExists = -15,
|
||||
|
||||
// SQL for creating a new pattern for this bug and set amount of occurrances to 1 in the database failed
|
||||
CrashReportStatusFailureSQLAddPattern = -14,
|
||||
|
||||
// SQL for checking the status of the bugfix version in the database failed
|
||||
CrashReportStatusFailureSQLCheckBugfixStatus = -13,
|
||||
|
||||
// SQL for updating the occurances of this pattern in the database failed
|
||||
CrashReportStatusFailureSQLUpdatePatternOccurances = -12,
|
||||
|
||||
// SQL for getting all the known bug patterns for the current app version in the database failed
|
||||
CrashReportStatusFailureSQLFindKnownPatterns = -11,
|
||||
|
||||
// SQL for finding the bundle identifier in the database failed
|
||||
CrashReportStatusFailureSQLSearchAppName = -10,
|
||||
|
||||
// the post request didn't contain valid data
|
||||
CrashReportStatusFailureInvalidPostData = -3,
|
||||
|
||||
// incoming data may not be added, because e.g. bundle identifier wasn't found
|
||||
CrashReportStatusFailureInvalidIncomingData = -2,
|
||||
|
||||
// database cannot be accessed, check hostname, username, password and database name settings in config.php
|
||||
CrashReportStatusFailureDatabaseNotAvailable = -1,
|
||||
|
||||
CrashReportStatusUnknown = 0,
|
||||
|
||||
CrashReportStatusAssigned = 1,
|
||||
|
||||
CrashReportStatusSubmitted = 2,
|
||||
|
||||
CrashReportStatusAvailable = 3,
|
||||
} CrashReportStatus;
|
||||
|
||||
@interface BWQuincyManager : NSObject <NSXMLParserDelegate> {
|
||||
NSString *_submissionURL;
|
||||
|
||||
id <BWQuincyManagerDelegate> _delegate;
|
||||
|
||||
BOOL _loggingEnabled;
|
||||
BOOL _showAlwaysButton;
|
||||
BOOL _feedbackActivated;
|
||||
BOOL _autoSubmitCrashReport;
|
||||
|
||||
BOOL _didCrashInLastSession;
|
||||
NSTimeInterval _timeintervalCrashInLastSessionOccured;
|
||||
|
||||
NSString *_appIdentifier;
|
||||
|
||||
NSString *_feedbackRequestID;
|
||||
float _feedbackDelayInterval;
|
||||
|
||||
NSMutableString *_contentOfProperty;
|
||||
CrashReportStatus _serverResult;
|
||||
|
||||
int _analyzerStarted;
|
||||
NSString *_crashesDir;
|
||||
NSFileManager *_fileManager;
|
||||
|
||||
BOOL _crashIdenticalCurrentVersion;
|
||||
BOOL _crashReportActivated;
|
||||
|
||||
NSMutableArray *_crashFiles;
|
||||
|
||||
NSMutableData *_responseData;
|
||||
NSInteger _statusCode;
|
||||
|
||||
NSURLConnection *_urlConnection;
|
||||
|
||||
NSData *_crashData;
|
||||
|
||||
NSString *_languageStyle;
|
||||
BOOL _sendingInProgress;
|
||||
}
|
||||
|
||||
+ (BWQuincyManager *)sharedQuincyManager;
|
||||
|
||||
// submission URL defines where to send the crash reports to (required)
|
||||
@property (nonatomic, retain) NSString *submissionURL;
|
||||
|
||||
// delegate is optional
|
||||
@property (nonatomic, assign) id <BWQuincyManagerDelegate> delegate;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// settings
|
||||
|
||||
// if YES, states will be logged using NSLog. Only enable this for debugging!
|
||||
// if NO, nothing will be logged. (default)
|
||||
@property (nonatomic, assign, getter=isLoggingEnabled) BOOL loggingEnabled;
|
||||
|
||||
// nil, using the default localization files (Default)
|
||||
// set to another string which will be appended to the Quincy localization file name, "Alternate" is another provided text set
|
||||
@property (nonatomic, retain) NSString *languageStyle;
|
||||
|
||||
// if YES, the user will get the option to choose "Always" for sending crash reports. This will cause the dialog not to show the alert description text landscape mode! (default)
|
||||
// if NO, the dialog will not show a "Always" button
|
||||
@property (nonatomic, assign, getter=isShowingAlwaysButton) BOOL showAlwaysButton;
|
||||
|
||||
// if YES, the user will be presented with a status of the crash, if known
|
||||
// if NO, the user will not see any feedback information (default)
|
||||
@property (nonatomic, assign, getter=isFeedbackActivated) BOOL feedbackActivated;
|
||||
|
||||
// if YES, the crash report will be submitted without asking the user
|
||||
// if NO, the user will be asked if the crash report can be submitted (default)
|
||||
@property (nonatomic, assign, getter=isAutoSubmitCrashReport) BOOL autoSubmitCrashReport;
|
||||
|
||||
// will return YES if the last session crashed, to e.g. make sure a "rate my app" alert will not show up
|
||||
@property (nonatomic, readonly) BOOL didCrashInLastSession;
|
||||
|
||||
// will return the timeinterval from startup to the crash in seconds, default is -1
|
||||
@property (nonatomic, readonly) NSTimeInterval timeintervalCrashInLastSessionOccured;
|
||||
|
||||
// If you want to use HockeyApp instead of your own server, this is required
|
||||
@property (nonatomic, retain) NSString *appIdentifier;
|
||||
|
||||
@end
|
@ -1,46 +0,0 @@
|
||||
//
|
||||
// CNSCrashReportManagerDelegate.h
|
||||
// HockeySDK
|
||||
//
|
||||
// Created by Andreas Linde on 29.03.12.
|
||||
// Copyright (c) 2012 __MyCompanyName__. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
// This protocol is used to send the image updates
|
||||
@protocol BWQuincyManagerDelegate <NSObject>
|
||||
|
||||
@optional
|
||||
|
||||
// Return the userid the crashreport should contain, empty by default
|
||||
-(NSString *) crashReportUserID;
|
||||
|
||||
// Return the contact value (e.g. email) the crashreport should contain, empty by default
|
||||
-(NSString *) crashReportContact;
|
||||
|
||||
// Return the description the crashreport should contain, empty by default. The string will automatically be wrapped into <[DATA[ ]]>, so make sure you don't do that in your string.
|
||||
-(NSString *) crashReportDescription;
|
||||
|
||||
// Invoked when the internet connection is started, to let the app enable the activity indicator
|
||||
-(void) connectionOpened;
|
||||
|
||||
// Invoked when the internet connection is closed, to let the app disable the activity indicator
|
||||
-(void) connectionClosed;
|
||||
|
||||
// Invoked before the user is asked to send a crash report, so you can do additional actions. E.g. to make sure not to ask the user for an app rating :)
|
||||
-(void) willShowSubmitCrashReportAlert;
|
||||
|
||||
// Invoked after the user did choose to send crashes always in the alert
|
||||
-(void) userDidChooseSendAlways;
|
||||
|
||||
// Invoked right before sending crash reports to the server succeeded
|
||||
-(void) sendingCrashReportsDidStart;
|
||||
|
||||
// Invoked after sending crash reports to the server failed
|
||||
-(void) sendingCrashReportsDidFailWithError:(NSError *)error;
|
||||
|
||||
// Invoked after sending crash reports to the server succeeded
|
||||
-(void) sendingCrashReportsDidFinish;
|
||||
|
||||
@end
|
@ -1,25 +0,0 @@
|
||||
//
|
||||
// CNSFixCategoryBug.h
|
||||
// HockeySDK
|
||||
//
|
||||
// Created by Andreas Linde on 12/7/11.
|
||||
// Copyright (c) 2011 Andreas Linde. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef HockeySDK_CNSFixCategoryBug_h
|
||||
#define HockeySDK_CNSFixCategoryBug_h
|
||||
|
||||
/**
|
||||
Add this macro before each category implementation, so we don't have to use
|
||||
-all_load or -force_load to load object files from static libraries that only contain
|
||||
categories and no classes.
|
||||
See http://developer.apple.com/library/mac/#qa/qa2006/qa1490.html for more info.
|
||||
|
||||
Shamelessly borrowed from Three20
|
||||
*/
|
||||
|
||||
#define CNS_FIX_CATEGORY_BUG(name) @interface CNS_FIX_CATEGORY_BUG##name @end \
|
||||
@implementation CNS_FIX_CATEGORY_BUG##name @end
|
||||
|
||||
|
||||
#endif
|
@ -1,261 +0,0 @@
|
||||
// Copyright 2011 Codenauts UG (haftungsbeschränkt). All rights reserved.
|
||||
// See LICENSE.txt for author information.
|
||||
//
|
||||
// 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 "BWHockeyManager.h"
|
||||
|
||||
#pragma mark - Delegate
|
||||
|
||||
@protocol CNSHockeyManagerDelegate <NSObject>
|
||||
|
||||
/*
|
||||
Return the device UDID which is required for beta testing, should return nil for app store configuration!
|
||||
Example implementation if your configuration for the App Store is called "AppStore":
|
||||
|
||||
#ifndef (CONFIGURATION_AppStore)
|
||||
if ([[UIDevice currentDevice] respondsToSelector:@selector(uniqueIdentifier)])
|
||||
return [[UIDevice currentDevice] performSelector:@selector(uniqueIdentifier)];
|
||||
#endif
|
||||
return nil;
|
||||
|
||||
*/
|
||||
- (NSString *)customDeviceIdentifier;
|
||||
|
||||
@optional
|
||||
|
||||
// Invoked when the manager is configured
|
||||
//
|
||||
// Implement to force the usage of the live identifier, e.g. for enterprise apps
|
||||
// which are distributed inside your company
|
||||
- (BOOL)shouldUseLiveIdenfitier;
|
||||
|
||||
// Invoked when the internet connection is started
|
||||
//
|
||||
// Implement to let the delegate enable the activity indicator
|
||||
- (void)connectionOpened;
|
||||
|
||||
// Invoked when the internet connection is closed
|
||||
//
|
||||
// Implement to let the delegate disable the activity indicator
|
||||
- (void)connectionClosed;
|
||||
|
||||
// Invoked via the alert view to define the presenting view controller
|
||||
//
|
||||
// Default is the root view controller of the main window instance
|
||||
- (UIViewController *)viewControllerForHockeyController:(BWHockeyManager *)hockeyController;
|
||||
|
||||
// Invoked before a crash report will be sent
|
||||
//
|
||||
// Return a userid or similar which the crashreport should contain
|
||||
//
|
||||
// Maximum length: 255 chars
|
||||
//
|
||||
// Default: empty
|
||||
- (NSString *)crashReportUserID;
|
||||
|
||||
// Invoked before a crash report will be sent
|
||||
//
|
||||
// Return contact data, e.g. an email address, for the crash report
|
||||
// Maximum length: 255 chars
|
||||
//
|
||||
// Default: empty
|
||||
-(NSString *)crashReportContact;
|
||||
|
||||
// Invoked before a crash report will be sent
|
||||
//
|
||||
// Return a the description for the crashreport should contain; the string
|
||||
// will automatically be wrapped into <[DATA[ ]]>, so make sure you don't do
|
||||
// that in your string.
|
||||
//
|
||||
// Default: empty
|
||||
-(NSString *)crashReportDescription;
|
||||
|
||||
// Invoked before the user is asked to send a crash report
|
||||
//
|
||||
// Implement to do additional actions, e.g. to make sure to not to ask the
|
||||
// user for an app rating :)
|
||||
- (void)willShowSubmitCrashReportAlert;
|
||||
|
||||
// Invoked after the user did choose to send crashes always in the alert
|
||||
-(void) userDidChooseSendAlways;
|
||||
|
||||
@end
|
||||
|
||||
@interface CNSHockeyManager : NSObject {
|
||||
@private
|
||||
id<CNSHockeyManagerDelegate> delegate;
|
||||
NSString *appIdentifier;
|
||||
}
|
||||
|
||||
#pragma mark - Public Properties
|
||||
|
||||
// Custom language style; set to a string which will be appended to
|
||||
// to the localization file name; the Hockey SDK includes an alternative
|
||||
// file, to use this, set to @"Alternate"
|
||||
//
|
||||
// Default: nil
|
||||
@property (nonatomic, retain) NSString *languageStyle;
|
||||
|
||||
// Enable debug logging; ONLY ENABLE THIS FOR DEBUGGING!
|
||||
//
|
||||
// Default: NO
|
||||
@property (nonatomic, assign, getter=isLoggingEnabled) BOOL loggingEnabled;
|
||||
|
||||
// Show button "Always" in crash alert; this will cause the dialog not to
|
||||
// show the alert description text landscape mode! (default)
|
||||
//
|
||||
// Default: NO
|
||||
@property (nonatomic, assign, getter=isShowingAlwaysButton) BOOL showAlwaysButton;
|
||||
|
||||
// Show feedback from server with status of the crash; if you set a crash
|
||||
// to resolved on HockeyApp and assign a fixed version, this version will
|
||||
// be reported to the user
|
||||
//
|
||||
// Default: NO
|
||||
@property (nonatomic, assign, getter=isFeedbackActivated) BOOL feedbackActivated;
|
||||
|
||||
// Submit crash report without asking the user
|
||||
//
|
||||
// Default: NO
|
||||
@property (nonatomic, assign, getter=isAutoSubmitCrashReport) BOOL autoSubmitCrashReport;
|
||||
|
||||
// Send user data to HockeyApp when checking for a new version; works only
|
||||
// for beta apps and should not be activated for live apps. User data includes
|
||||
// the device type, OS version, app version and device UDID.
|
||||
//
|
||||
// Default: YES
|
||||
@property (nonatomic, assign, getter=shouldSendUserData) BOOL sendUserData;
|
||||
|
||||
// Send usage time to HockeyApp when checking for a new version; works only
|
||||
// for beta apps and should not be activated for live apps.
|
||||
//
|
||||
// Default: YES
|
||||
@property (nonatomic, assign, getter=shouldSendUsageTime) BOOL sendUsageTime;
|
||||
|
||||
// Enable to allow the user to change the settings from the update view
|
||||
//
|
||||
// Default: YES
|
||||
@property (nonatomic, assign, getter=shouldShowUserSettings) BOOL showUserSettings;
|
||||
|
||||
// Set bar style of navigation controller
|
||||
//
|
||||
// Default: UIBarStyleDefault
|
||||
@property (nonatomic, assign) UIBarStyle barStyle;
|
||||
|
||||
// Set modal presentation style of update view
|
||||
//
|
||||
// Default: UIModalPresentationStyleFormSheet
|
||||
@property (nonatomic, assign) UIModalPresentationStyle modalPresentationStyle;
|
||||
|
||||
// Allow the user to disable the sending of user data; this settings should
|
||||
// only be set if showUserSettings is enabled.
|
||||
//
|
||||
// Default: YES
|
||||
@property (nonatomic, assign, getter=isUserAllowedToDisableSendData) BOOL allowUserToDisableSendData;
|
||||
|
||||
// Enable to show the new version alert every time the app becomes active and
|
||||
// the current version is outdated
|
||||
//
|
||||
// Default: YES
|
||||
@property (nonatomic, assign) BOOL alwaysShowUpdateReminder;
|
||||
|
||||
// Enable to check for a new version every time the app becomes active; if
|
||||
// disabled you need to trigger the update mechanism manually
|
||||
//
|
||||
// Default: YES
|
||||
@property (nonatomic, assign, getter=shouldCheckForUpdateOnLaunch) BOOL checkForUpdateOnLaunch;
|
||||
|
||||
// Show a button "Install" in the update alert to let the user directly start
|
||||
// the update; note that the user will not see the release notes.
|
||||
//
|
||||
// Default: NO
|
||||
@property (nonatomic, assign, getter=isShowingDirectInstallOption) BOOL showDirectInstallOption;
|
||||
|
||||
// Enable to check on the server that the app is authorized to run on this
|
||||
// device; the check is based on the UDID and the authentication secret which
|
||||
// is shown on the app page on HockeyApp
|
||||
//
|
||||
// Default: NO
|
||||
@property (nonatomic, assign, getter=shouldRequireAuthorization) BOOL requireAuthorization;
|
||||
|
||||
// Set to the authentication secret which is shown on the app page on HockeyApp;
|
||||
// must be set if requireAuthorization is enabled; leave empty otherwise
|
||||
//
|
||||
// Default: nil
|
||||
@property (nonatomic, retain) NSString *authenticationSecret;
|
||||
|
||||
// Define how the client determines if a new version is available.
|
||||
//
|
||||
// Values:
|
||||
// HockeyComparisonResultDifferent - the version on the server is different
|
||||
// HockeyComparisonResultGreate - the version on the server is greater
|
||||
//
|
||||
// Default: HockeyComparisonResultGreater
|
||||
@property (nonatomic, assign) HockeyComparisonResult compareVersionType;
|
||||
|
||||
// if YES the app is installed from the app store
|
||||
// if NO the app is installed via ad-hoc or enterprise distribution
|
||||
@property (nonatomic, readonly) BOOL isAppStoreEnvironment;
|
||||
|
||||
#pragma mark - Public Methods
|
||||
|
||||
// Returns the shared manager object
|
||||
+ (CNSHockeyManager *)sharedHockeyManager;
|
||||
|
||||
// Configure HockeyApp with a single app identifier and delegate; use this
|
||||
// only for debug or beta versions of your app!
|
||||
- (void)configureWithIdentifier:(NSString *)appIdentifier delegate:(id<CNSHockeyManagerDelegate>)delegate;
|
||||
|
||||
// Configure HockeyApp with different app identifiers for beta and live versions
|
||||
// of the app; the update alert will only be shown for the beta identifier
|
||||
- (void)configureWithBetaIdentifier:(NSString *)betaIdentifier liveIdentifier:(NSString *)liveIdentifier delegate:(id<CNSHockeyManagerDelegate>)delegate;
|
||||
|
||||
// Returns true if the app crashes in the last session
|
||||
- (BOOL)didCrashInLastSession;
|
||||
|
||||
// Returns true if an update is available
|
||||
- (BOOL)isUpdateAvailable;
|
||||
|
||||
// Returns true if update check is running
|
||||
- (BOOL)isCheckInProgress;
|
||||
|
||||
// Show update info view
|
||||
- (void)showUpdateView;
|
||||
|
||||
// Manually start an update check
|
||||
- (void)checkForUpdate;
|
||||
|
||||
// Checks for update and informs the user if an update was found or an
|
||||
// error occurred
|
||||
- (void)checkForUpdateShowFeedback:(BOOL)feedback;
|
||||
|
||||
// Initiates app-download call; this displays an alert view of the OS
|
||||
- (BOOL)initiateAppDownload;
|
||||
|
||||
// Returns true if this app version was authorized with the server
|
||||
- (BOOL)appVersionIsAuthorized;
|
||||
|
||||
// Manually check if the device is authorized to run this version
|
||||
- (void)checkForAuthorization;
|
||||
|
||||
// Return a new instance of BWHockeyViewController
|
||||
- (BWHockeyViewController *)hockeyViewController:(BOOL)modal;
|
||||
|
||||
@end
|
@ -1,427 +0,0 @@
|
||||
// Copyright 2011 Codenauts UG (haftungsbeschränkt). All rights reserved.
|
||||
// See LICENSE.txt for author information.
|
||||
//
|
||||
// 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 "CNSHockeyManager.h"
|
||||
#import "BWQuincyManager.h"
|
||||
#import "BWHockeyManager.h"
|
||||
|
||||
@interface CNSHockeyManager ()
|
||||
|
||||
- (BOOL)shouldUseLiveIdenfitier;
|
||||
|
||||
- (void)configureJMC;
|
||||
- (void)configureHockeyManager;
|
||||
- (void)configureQuincyManager;
|
||||
|
||||
@end
|
||||
|
||||
@implementation CNSHockeyManager
|
||||
|
||||
#pragma mark - Public Class Methods
|
||||
|
||||
#if __IPHONE_OS_VERSION_MIN_REQUIRED >= 40000
|
||||
+ (CNSHockeyManager *)sharedHockeyManager {
|
||||
static CNSHockeyManager *sharedInstance = nil;
|
||||
static dispatch_once_t pred;
|
||||
|
||||
dispatch_once(&pred, ^{
|
||||
sharedInstance = [CNSHockeyManager alloc];
|
||||
sharedInstance = [sharedInstance init];
|
||||
});
|
||||
|
||||
return sharedInstance;
|
||||
}
|
||||
#else
|
||||
+ (CNSHockeyManager *)sharedHockeyManager {
|
||||
static CNSHockeyManager *hockeyManager = nil;
|
||||
|
||||
if (hockeyManager == nil) {
|
||||
hockeyManager = [[CNSHockeyManager alloc] init];
|
||||
}
|
||||
|
||||
return hockeyManager;
|
||||
}
|
||||
#endif
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
+ (id)jmcInstance {
|
||||
id jmcClass = NSClassFromString(@"JMC");
|
||||
if ((jmcClass) && ([jmcClass respondsToSelector:@selector(sharedInstance)])) {
|
||||
return [jmcClass performSelector:@selector(sharedInstance)];
|
||||
}
|
||||
#ifdef JMC_LEGACY
|
||||
else if ((jmcClass) && ([jmcClass respondsToSelector:@selector(instance)])) {
|
||||
return [jmcClass performSelector:@selector(instance)]; // legacy pre (JMC 1.0.11) support
|
||||
}
|
||||
#endif
|
||||
|
||||
return nil;
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
+ (BOOL)isJMCActive {
|
||||
id jmcInstance = [self jmcInstance];
|
||||
return (jmcInstance) && ([jmcInstance performSelector:@selector(url)]);
|
||||
}
|
||||
|
||||
+ (BOOL)isJMCPresent {
|
||||
return [self jmcInstance] != nil;
|
||||
}
|
||||
|
||||
#pragma mark - Private Class Methods
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
+ (void)disableJMCCrashReporter {
|
||||
id jmcInstance = [self jmcInstance];
|
||||
id jmcOptions = [jmcInstance performSelector:@selector(options)];
|
||||
SEL crashReporterSelector = @selector(setCrashReportingEnabled:);
|
||||
|
||||
BOOL value = NO;
|
||||
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[jmcOptions methodSignatureForSelector:crashReporterSelector]];
|
||||
invocation.target = jmcOptions;
|
||||
invocation.selector = crashReporterSelector;
|
||||
[invocation setArgument:&value atIndex:2];
|
||||
[invocation invoke];
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
+ (BOOL)checkJMCConfiguration:(NSDictionary *)configuration {
|
||||
return (([configuration isKindOfClass:[NSDictionary class]]) &&
|
||||
([[configuration valueForKey:@"enabled"] boolValue]) &&
|
||||
([[configuration valueForKey:@"url"] length] > 0) &&
|
||||
([[configuration valueForKey:@"key"] length] > 0) &&
|
||||
([[configuration valueForKey:@"project"] length] > 0));
|
||||
}
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wundeclared-selector"
|
||||
+ (void)applyJMCConfiguration:(NSDictionary *)configuration {
|
||||
id jmcInstance = [self jmcInstance];
|
||||
SEL configureSelector = @selector(configureJiraConnect:projectKey:apiKey:);
|
||||
|
||||
NSString *url = [configuration valueForKey:@"url"];
|
||||
NSString *project = [configuration valueForKey:@"project"];
|
||||
NSString *key = [configuration valueForKey:@"key"];
|
||||
|
||||
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[jmcInstance methodSignatureForSelector:configureSelector]];
|
||||
invocation.target = jmcInstance;
|
||||
invocation.selector = configureSelector;
|
||||
[invocation setArgument:&url atIndex:2];
|
||||
[invocation setArgument:&project atIndex:3];
|
||||
[invocation setArgument:&key atIndex:4];
|
||||
[invocation invoke];
|
||||
|
||||
if ([jmcInstance respondsToSelector:@selector(ping)]) {
|
||||
[jmcInstance performSelector:@selector(ping)];
|
||||
}
|
||||
}
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#pragma mark - Public Instance Methods (Configuration)
|
||||
|
||||
- (void)configureWithIdentifier:(NSString *)newAppIdentifier delegate:(id)newDelegate {
|
||||
delegate = newDelegate;
|
||||
[appIdentifier release];
|
||||
appIdentifier = [newAppIdentifier copy];
|
||||
|
||||
[self configureQuincyManager];
|
||||
[self configureHockeyManager];
|
||||
}
|
||||
|
||||
- (void)configureWithBetaIdentifier:(NSString *)betaIdentifier liveIdentifier:(NSString *)liveIdentifier delegate:(id)newDelegate {
|
||||
delegate = newDelegate;
|
||||
[appIdentifier release];
|
||||
|
||||
if ([self shouldUseLiveIdenfitier]) {
|
||||
appIdentifier = [liveIdentifier copy];
|
||||
}
|
||||
else {
|
||||
appIdentifier = [betaIdentifier copy];
|
||||
}
|
||||
|
||||
if (appIdentifier) {
|
||||
[self configureQuincyManager];
|
||||
[self configureHockeyManager];
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)isLoggingEnabled {
|
||||
return [[BWHockeyManager sharedHockeyManager] isLoggingEnabled];
|
||||
return [[BWQuincyManager sharedQuincyManager] isLoggingEnabled];
|
||||
}
|
||||
|
||||
- (void)setLoggingEnabled:(BOOL)loggingEnabled {
|
||||
return [[BWHockeyManager sharedHockeyManager] setLoggingEnabled:loggingEnabled];
|
||||
return [[BWQuincyManager sharedQuincyManager] setLoggingEnabled:loggingEnabled];
|
||||
}
|
||||
|
||||
#pragma mark - Public Instance Methods (Crash Reporting)
|
||||
|
||||
- (NSString *)languageStyle {
|
||||
return [[BWQuincyManager sharedQuincyManager] languageStyle];
|
||||
}
|
||||
|
||||
- (void)setLanguageStyle:(NSString *)languageStyle {
|
||||
[[BWQuincyManager sharedQuincyManager] setLanguageStyle:languageStyle];
|
||||
}
|
||||
|
||||
- (BOOL)isShowingAlwaysButton {
|
||||
return [[BWQuincyManager sharedQuincyManager] isShowingAlwaysButton];
|
||||
}
|
||||
|
||||
- (void)setShowAlwaysButton:(BOOL)showAlwaysButton {
|
||||
[[BWQuincyManager sharedQuincyManager] setShowAlwaysButton:showAlwaysButton];
|
||||
}
|
||||
|
||||
- (BOOL)isFeedbackActivated {
|
||||
return [[BWQuincyManager sharedQuincyManager] isFeedbackActivated];
|
||||
}
|
||||
|
||||
- (void)setFeedbackActivated:(BOOL)setFeedbackActivated {
|
||||
[[BWQuincyManager sharedQuincyManager] setFeedbackActivated:setFeedbackActivated];
|
||||
}
|
||||
|
||||
- (BOOL)isAutoSubmitCrashReport {
|
||||
return [[BWQuincyManager sharedQuincyManager] isAutoSubmitCrashReport];
|
||||
}
|
||||
|
||||
- (void)setAutoSubmitCrashReport:(BOOL)autoSubmitCrashReport {
|
||||
[[BWQuincyManager sharedQuincyManager] setAutoSubmitCrashReport:autoSubmitCrashReport];
|
||||
}
|
||||
|
||||
- (BOOL)didCrashInLastSession {
|
||||
return [[BWQuincyManager sharedQuincyManager] didCrashInLastSession];
|
||||
}
|
||||
|
||||
#pragma mark - Public Instance Methods (Distribution)
|
||||
|
||||
- (BOOL)shouldSendUserData {
|
||||
return [[BWHockeyManager sharedHockeyManager] shouldSendUserData];
|
||||
}
|
||||
|
||||
- (void)setSendUserData:(BOOL)sendUserData {
|
||||
[[BWHockeyManager sharedHockeyManager] setSendUserData:sendUserData];
|
||||
}
|
||||
|
||||
- (BOOL)shouldSendUsageTime {
|
||||
return [[BWHockeyManager sharedHockeyManager] shouldSendUsageTime];
|
||||
}
|
||||
|
||||
- (void)setSendUsageTime:(BOOL)sendUsageTime {
|
||||
[[BWHockeyManager sharedHockeyManager] setSendUsageTime:sendUsageTime];
|
||||
}
|
||||
|
||||
- (BOOL)shouldShowUserSettings {
|
||||
return [[BWHockeyManager sharedHockeyManager] shouldShowUserSettings];
|
||||
}
|
||||
|
||||
- (void)setShowUserSettings:(BOOL)showUserSettings {
|
||||
[[BWHockeyManager sharedHockeyManager] setShowUserSettings:showUserSettings];
|
||||
}
|
||||
|
||||
- (UIBarStyle)barStyle {
|
||||
return [[BWHockeyManager sharedHockeyManager] barStyle];
|
||||
}
|
||||
|
||||
- (void)setBarStyle:(UIBarStyle)barStyle {
|
||||
[[BWHockeyManager sharedHockeyManager] setBarStyle:barStyle];
|
||||
}
|
||||
|
||||
- (UIModalPresentationStyle)modalPresentationStyle {
|
||||
return [[BWHockeyManager sharedHockeyManager] modalPresentationStyle];
|
||||
}
|
||||
|
||||
- (void)setModalPresentationStyle:(UIModalPresentationStyle)modalPresentationStyle {
|
||||
[[BWHockeyManager sharedHockeyManager] setModalPresentationStyle:modalPresentationStyle];
|
||||
}
|
||||
|
||||
- (BOOL)isUserAllowedToDisableSendData {
|
||||
return [[BWHockeyManager sharedHockeyManager] isAllowUserToDisableSendData];
|
||||
}
|
||||
|
||||
- (void)setAllowUserToDisableSendData:(BOOL)allowUserToDisableSendData {
|
||||
[[BWHockeyManager sharedHockeyManager] setAllowUserToDisableSendData:allowUserToDisableSendData];
|
||||
}
|
||||
|
||||
- (BOOL)alwaysShowUpdateReminder {
|
||||
return [[BWHockeyManager sharedHockeyManager] alwaysShowUpdateReminder];
|
||||
}
|
||||
|
||||
- (void)setAlwaysShowUpdateReminder:(BOOL)alwaysShowUpdateReminder {
|
||||
[[BWHockeyManager sharedHockeyManager] setAlwaysShowUpdateReminder:alwaysShowUpdateReminder];
|
||||
}
|
||||
|
||||
- (BOOL)shouldCheckForUpdateOnLaunch {
|
||||
return [[BWHockeyManager sharedHockeyManager] isCheckForUpdateOnLaunch];
|
||||
}
|
||||
|
||||
- (void)setCheckForUpdateOnLaunch:(BOOL)checkForUpdateOnLaunch {
|
||||
[[BWHockeyManager sharedHockeyManager] setCheckForUpdateOnLaunch:checkForUpdateOnLaunch];
|
||||
}
|
||||
|
||||
- (BOOL)isShowingDirectInstallOption {
|
||||
return [[BWHockeyManager sharedHockeyManager] isShowingDirectInstallOption];
|
||||
}
|
||||
|
||||
- (void)setShowDirectInstallOption:(BOOL)showDirectInstallOption {
|
||||
[[BWHockeyManager sharedHockeyManager] setShowDirectInstallOption:showDirectInstallOption];
|
||||
}
|
||||
|
||||
- (BOOL)shouldRequireAuthorization {
|
||||
return [[BWHockeyManager sharedHockeyManager] isRequireAuthorization];
|
||||
}
|
||||
|
||||
- (void)setRequireAuthorization:(BOOL)requireAuthorization {
|
||||
[[BWHockeyManager sharedHockeyManager] setRequireAuthorization:requireAuthorization];
|
||||
}
|
||||
|
||||
- (NSString *)authenticationSecret {
|
||||
return [[BWHockeyManager sharedHockeyManager] authenticationSecret];
|
||||
}
|
||||
|
||||
- (void)setAuthenticationSecret:(NSString *)authenticationSecret {
|
||||
[[BWHockeyManager sharedHockeyManager] setAuthenticationSecret:authenticationSecret];
|
||||
}
|
||||
|
||||
- (HockeyComparisonResult)compareVersionType {
|
||||
return [[BWHockeyManager sharedHockeyManager] compareVersionType];
|
||||
}
|
||||
|
||||
- (void)setCompareVersionType:(HockeyComparisonResult)compareVersionType {
|
||||
[[BWHockeyManager sharedHockeyManager] setCompareVersionType:compareVersionType];
|
||||
}
|
||||
|
||||
- (BOOL)isAppStoreEnvironment {
|
||||
return [[BWHockeyManager sharedHockeyManager] isAppStoreEnvironment];
|
||||
}
|
||||
|
||||
- (BOOL)isUpdateAvailable {
|
||||
return [[BWHockeyManager sharedHockeyManager] isUpdateAvailable];
|
||||
}
|
||||
|
||||
- (BOOL)isCheckInProgress {
|
||||
return [[BWHockeyManager sharedHockeyManager] isCheckInProgress];
|
||||
}
|
||||
|
||||
- (void)showUpdateView {
|
||||
[[BWHockeyManager sharedHockeyManager] showUpdateView];
|
||||
}
|
||||
|
||||
- (void)checkForUpdate {
|
||||
[[BWHockeyManager sharedHockeyManager] checkForUpdate];
|
||||
}
|
||||
|
||||
- (void)checkForUpdateShowFeedback:(BOOL)feedback {
|
||||
[[BWHockeyManager sharedHockeyManager] checkForUpdateShowFeedback:feedback];
|
||||
}
|
||||
|
||||
- (BOOL)initiateAppDownload {
|
||||
return [[BWHockeyManager sharedHockeyManager] initiateAppDownload];
|
||||
}
|
||||
|
||||
- (BOOL)appVersionIsAuthorized {
|
||||
return [[BWHockeyManager sharedHockeyManager] appVersionIsAuthorized];
|
||||
}
|
||||
|
||||
- (void)checkForAuthorization {
|
||||
[[BWHockeyManager sharedHockeyManager] checkForAuthorization];
|
||||
}
|
||||
|
||||
- (BWHockeyViewController *)hockeyViewController:(BOOL)modal {
|
||||
return [[BWHockeyManager sharedHockeyManager] hockeyViewController:modal];
|
||||
}
|
||||
|
||||
#pragma mark - Private Instance Methods
|
||||
|
||||
- (BOOL)shouldUseLiveIdenfitier {
|
||||
BOOL delegateResult = NO;
|
||||
if ([delegate respondsToSelector:@selector(shouldUseLiveIdenfitier)]) {
|
||||
delegateResult = [(NSObject <CNSHockeyManagerDelegate>*)delegate shouldUseLiveIdenfitier];
|
||||
}
|
||||
|
||||
return (delegateResult) || ([[BWHockeyManager sharedHockeyManager] isAppStoreEnvironment]);
|
||||
}
|
||||
|
||||
- (void)configureQuincyManager {
|
||||
[[BWQuincyManager sharedQuincyManager] setAppIdentifier:appIdentifier];
|
||||
[[BWQuincyManager sharedQuincyManager] setDelegate:(id)delegate];
|
||||
}
|
||||
|
||||
- (void)configureHockeyManager {
|
||||
[[BWHockeyManager sharedHockeyManager] setAppIdentifier:appIdentifier];
|
||||
[[BWHockeyManager sharedHockeyManager] setCheckForTracker:YES];
|
||||
[[BWHockeyManager sharedHockeyManager] setDelegate:(id)delegate];
|
||||
|
||||
// Only if JMC is part of the project
|
||||
if ([[self class] isJMCPresent]) {
|
||||
[[BWHockeyManager sharedHockeyManager] addObserver:self forKeyPath:@"trackerConfig" options:0 context:nil];
|
||||
[[self class] disableJMCCrashReporter];
|
||||
[self performSelector:@selector(configureJMC) withObject:nil afterDelay:0];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)configureJMC {
|
||||
// Return if JMC is already configured
|
||||
if ([[self class] isJMCActive]) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Return if app id is nil
|
||||
if (!appIdentifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Configure JMC from user defaults
|
||||
NSDictionary *configurations = [[NSUserDefaults standardUserDefaults] valueForKey:@"CNSTrackerConfigurations"];
|
||||
NSDictionary *configuration = [configurations valueForKey:appIdentifier];
|
||||
if ([[self class] checkJMCConfiguration:configuration]) {
|
||||
[[self class] applyJMCConfiguration:configuration];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
|
||||
if (([object trackerConfig]) && ([[object trackerConfig] isKindOfClass:[NSDictionary class]])) {
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
NSMutableDictionary *trackerConfig = [[defaults valueForKey:@"CNSTrackerConfigurations"] mutableCopy];
|
||||
if (!trackerConfig) {
|
||||
trackerConfig = [[NSMutableDictionary dictionaryWithCapacity:1] retain];
|
||||
}
|
||||
|
||||
[trackerConfig setValue:[object trackerConfig] forKey:appIdentifier];
|
||||
[defaults setValue:trackerConfig forKey:@"CNSTrackerConfigurations"];
|
||||
[trackerConfig release];
|
||||
|
||||
[defaults synchronize];
|
||||
[self configureJMC];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
[appIdentifier release], appIdentifier = nil;
|
||||
delegate = nil;
|
||||
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
@end
|
82
Classes/HockeySDK.h
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* Copyright (c) 2011 Andreas Linde.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef HockeySDK_h
|
||||
#define HockeySDK_h
|
||||
|
||||
#import "BITHockeyManager.h"
|
||||
#import "BITHockeyManagerDelegate.h"
|
||||
|
||||
#import "BITCrashManager.h"
|
||||
#import "BITCrashManagerDelegate.h"
|
||||
|
||||
#import "BITUpdateManager.h"
|
||||
#import "BITUpdateManagerDelegate.h"
|
||||
#import "BITUpdateViewController.h"
|
||||
#import "BITUpdateSettingsViewController.h"
|
||||
|
||||
// Notification message which HockeyManager is listening to, to retry requesting updated from the server
|
||||
#define BITHockeyNetworkDidBecomeReachableNotification @"BITHockeyNetworkDidBecomeReachable"
|
||||
|
||||
|
||||
// Crash Reporting
|
||||
|
||||
// flags if the crashreporter is activated at all
|
||||
// set this as bool in user defaults e.g. in the settings, if you want to let the user be able to deactivate it
|
||||
#define kBITCrashActivated @"BITCrashActivated"
|
||||
|
||||
// flags if the crashreporter should automatically send crashes without asking the user again
|
||||
// set this as bool in user defaults e.g. in the settings, if you want to let the user be able to set this on or off
|
||||
#define kBITCrashAutomaticallySendReports @"BITCrashAutomaticallySendReports"
|
||||
|
||||
// hockey api error domain
|
||||
typedef enum {
|
||||
BITCrashErrorUnknown,
|
||||
BITCrashAPIAppVersionRejected,
|
||||
BITCrashAPIReceivedEmptyResponse,
|
||||
BITCrashAPIErrorWithStatusCode
|
||||
} BITCrashErrorReason;
|
||||
static NSString *kBITCrashErrorDomain = @"BITCrashReporterErrorDomain";
|
||||
|
||||
|
||||
// Update App Versions
|
||||
|
||||
// hockey api error domain
|
||||
typedef enum {
|
||||
BITUpdateErrorUnknown,
|
||||
BITUpdateAPIServerReturnedInvalidStatus,
|
||||
BITUpdateAPIServerReturnedInvalidData,
|
||||
BITUpdateAPIServerReturnedEmptyResponse,
|
||||
BITUpdateAPIClientAuthorizationMissingSecret,
|
||||
BITUpdateAPIClientCannotCreateConnection
|
||||
} BITUpdateErrorReason;
|
||||
static NSString *kBITUpdateErrorDomain = @"BITUpdaterErrorDomain";
|
||||
|
||||
|
||||
#endif
|
94
Classes/HockeySDKPrivate.h
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
* Kent Sutherland
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* Copyright (c) 2011 Andreas Linde & Kent Sutherland.
|
||||
* 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>
|
||||
|
||||
#ifndef HockeySDK_HockeySDKPrivate_h
|
||||
#define HockeySDK_HockeySDKPrivate_h
|
||||
|
||||
#define BITHOCKEYSDK_NAME @"HockeySDK"
|
||||
#define BITHOCKEYSDK_VERSION @"2.3.0-dev"
|
||||
|
||||
#define kBITUpdateArrayOfLastCheck @"BITUpdateArrayOfLastCheck"
|
||||
#define kBITUpdateDateOfLastCheck @"BITUpdateDateOfLastCheck"
|
||||
#define kBITUpdateDateOfVersionInstallation @"BITUpdateDateOfVersionInstallation"
|
||||
#define kBITUpdateUsageTimeOfCurrentVersion @"BITUpdateUsageTimeOfCurrentVersion"
|
||||
#define kBITUpdateUsageTimeForVersionString @"BITUpdateUsageTimeForVersionString"
|
||||
#define kBITUpdateAutoUpdateSetting @"BITUpdateAutoUpdateSetting"
|
||||
#define kBITUpdateAllowUserSetting @"BITUpdateAllowUserSetting"
|
||||
#define kBITUpdateAllowUsageSetting @"BITUpdateAllowUsageSetting"
|
||||
#define kBITUpdateAutoUpdateSetting @"BITUpdateAutoUpdateSetting"
|
||||
#define kBITUpdateAuthorizedVersion @"BITUpdateAuthorizedVersion"
|
||||
#define kBITUpdateAuthorizedToken @"BITUpdateAuthorizedToken"
|
||||
|
||||
#define BITHOCKEYSDK_BUNDLE @"HockeySDKResources"
|
||||
#define BITHOCKEYSDK_URL @"https://sdk.hockeyapp.net/"
|
||||
|
||||
#define BITHockeySDKLog(fmt, ...) do { if([BITHockeyManager sharedHockeyManager].isLoggingEnabled) { NSLog((@"[HockeySDK] %s/%d " fmt), __PRETTY_FUNCTION__, __LINE__, ##__VA_ARGS__); }} while(0)
|
||||
|
||||
NSBundle *BITHockeySDKBundle(void);
|
||||
NSString *BITHockeySDKLocalizedString(NSString *stringToken);
|
||||
NSString *BITHockeySDKMD5(NSString *str);
|
||||
|
||||
|
||||
// compatibility helper
|
||||
#ifdef BITHOCKEYSDK_STATIC_LIBRARY
|
||||
// If HockeySDK is built as a static library and linked into the project
|
||||
// we can't use this project's deployment target to statically decide if
|
||||
// native JSON is available
|
||||
#define BITHOCKEYSDK_NATIVE_JSON_AVAILABLE 0
|
||||
#else
|
||||
#define BITHOCKEYSDK_NATIVE_JSON_AVAILABLE __IPHONE_OS_VERSION_MIN_REQUIRED >= 50000
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_5_0
|
||||
#define kCFCoreFoundationVersionNumber_iPhoneOS_5_0 674.0
|
||||
#endif
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 50000
|
||||
#define BITHOCKEYSDK_IF_IOS5_OR_GREATER(...) \
|
||||
if (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_5_0) \
|
||||
{ \
|
||||
__VA_ARGS__ \
|
||||
}
|
||||
#else
|
||||
#define BITHOCKEYSDK_IF_IOS5_OR_GREATER(...)
|
||||
#endif
|
||||
|
||||
#define BITHOCKEYSDK_IF_PRE_IOS5(...) \
|
||||
if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_5_0) \
|
||||
{ \
|
||||
__VA_ARGS__ \
|
||||
}
|
||||
|
||||
|
||||
#endif
|
69
Classes/HockeySDKPrivate.m
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Author: Andreas Linde <mail@andreaslinde.de>
|
||||
*
|
||||
* Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
* Copyright (c) 2011 Andreas Linde.
|
||||
* 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 "HockeySDKPrivate.h"
|
||||
#include <CommonCrypto/CommonDigest.h>
|
||||
|
||||
|
||||
// Load the framework bundle.
|
||||
NSBundle *BITHockeySDKBundle(void) {
|
||||
static NSBundle *bundle = nil;
|
||||
static dispatch_once_t predicate;
|
||||
dispatch_once(&predicate, ^{
|
||||
NSString* mainBundlePath = [[NSBundle mainBundle] resourcePath];
|
||||
NSString* frameworkBundlePath = [mainBundlePath stringByAppendingPathComponent:BITHOCKEYSDK_BUNDLE];
|
||||
bundle = [[NSBundle bundleWithPath:frameworkBundlePath] retain];
|
||||
});
|
||||
return bundle;
|
||||
}
|
||||
|
||||
NSString *BITHockeySDKLocalizedString(NSString *stringToken) {
|
||||
if (BITHockeySDKBundle()) {
|
||||
return NSLocalizedStringFromTableInBundle(stringToken, @"HockeySDK", BITHockeySDKBundle(), @"");
|
||||
} else {
|
||||
return stringToken;
|
||||
}
|
||||
}
|
||||
|
||||
NSString *BITHockeySDKMD5(NSString *str) {
|
||||
const char *cStr = [str UTF8String];
|
||||
unsigned char result[CC_MD5_DIGEST_LENGTH];
|
||||
CC_MD5( cStr, strlen(cStr), result );
|
||||
return [NSString
|
||||
stringWithFormat: @"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
|
||||
result[0], result[1],
|
||||
result[2], result[3],
|
||||
result[4], result[5],
|
||||
result[6], result[7],
|
||||
result[8], result[9],
|
||||
result[10], result[11],
|
||||
result[12], result[13],
|
||||
result[14], result[15]
|
||||
];
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
//
|
||||
// NSString+HockeyAdditions.h
|
||||
//
|
||||
// Created by Jon Crosby on 10/19/07.
|
||||
// Copyright 2007 Kaboomerang LLC. All rights reserved.
|
||||
// Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
@ -25,11 +24,11 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NSString (HockeyAdditions)
|
||||
@interface NSString (BITHockeyAdditions)
|
||||
|
||||
- (NSString *)bw_URLEncodedString;
|
||||
- (NSString *)bw_URLDecodedString;
|
||||
- (NSString *)bit_URLEncodedString;
|
||||
- (NSString *)bit_URLDecodedString;
|
||||
|
||||
- (NSComparisonResult)versionCompare:(NSString *)other;
|
||||
- (NSComparisonResult)bit_versionCompare:(NSString *)other;
|
||||
|
||||
@end
|
@ -1,8 +1,7 @@
|
||||
//
|
||||
// NSString+HockeyAdditions.m
|
||||
//
|
||||
// Created by Jon Crosby on 10/19/07.
|
||||
// Copyright 2007 Kaboomerang LLC. All rights reserved.
|
||||
// Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
@ -23,16 +22,11 @@
|
||||
// THE SOFTWARE.
|
||||
|
||||
|
||||
#import "NSString+HockeyAdditions.h"
|
||||
#import "NSString+BITHockeyAdditions.h"
|
||||
|
||||
#ifdef HOCKEYLIB_STATIC_LIBRARY
|
||||
#import "CNSFixCategoryBug.h"
|
||||
CNS_FIX_CATEGORY_BUG(NSString_HockeyAdditions)
|
||||
#endif
|
||||
@implementation NSString (BITHockeyAdditions)
|
||||
|
||||
@implementation NSString (HockeyAdditions)
|
||||
|
||||
- (NSString *)bw_URLEncodedString {
|
||||
- (NSString *)bit_URLEncodedString {
|
||||
NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
|
||||
(CFStringRef)self,
|
||||
NULL,
|
||||
@ -42,7 +36,7 @@ CNS_FIX_CATEGORY_BUG(NSString_HockeyAdditions)
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSString*)bw_URLDecodedString {
|
||||
- (NSString*)bit_URLDecodedString {
|
||||
NSString *result = (NSString *)CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault,
|
||||
(CFStringRef)self,
|
||||
CFSTR(""),
|
||||
@ -51,7 +45,7 @@ CNS_FIX_CATEGORY_BUG(NSString_HockeyAdditions)
|
||||
return result;
|
||||
}
|
||||
|
||||
- (NSComparisonResult)versionCompare:(NSString *)other {
|
||||
- (NSComparisonResult)bit_versionCompare:(NSString *)other {
|
||||
// Extract plain version number from self
|
||||
NSString *plainSelf = self;
|
||||
NSRange letterRange = [plainSelf rangeOfCharacterFromSet: [NSCharacterSet letterCharacterSet]];
|
@ -1,9 +1,6 @@
|
||||
//
|
||||
// PSAppStoreHeader.h
|
||||
// HockeyDemo
|
||||
//
|
||||
// Created by Peter Steinberger on 09.01.11.
|
||||
// Copyright 2011 Peter Steinberger. All rights reserved.
|
||||
// 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
|
||||
|
@ -1,9 +1,6 @@
|
||||
//
|
||||
// PSAppStoreHeader.m
|
||||
// HockeyDemo
|
||||
//
|
||||
// Created by Peter Steinberger on 09.01.11.
|
||||
// Copyright 2011 Peter Steinberger. All rights reserved.
|
||||
// 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
|
||||
@ -24,13 +21,14 @@
|
||||
// THE SOFTWARE.
|
||||
|
||||
#import "PSAppStoreHeader.h"
|
||||
#import "UIImage+HockeyAdditions.h"
|
||||
#import "BWGlobal.h"
|
||||
#import "UIImage+BITHockeyAdditions.h"
|
||||
#import "HockeySDKPrivate.h"
|
||||
|
||||
#define BW_RGBCOLOR(r,g,b) [UIColor colorWithRed:(r)/255.0 green:(g)/255.0 blue:(b)/255.0 alpha:1]
|
||||
|
||||
#define kLightGrayColor BW_RGBCOLOR(200, 202, 204)
|
||||
#define kDarkGrayColor BW_RGBCOLOR(140, 141, 142)
|
||||
#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
|
||||
@ -45,9 +43,8 @@
|
||||
@synthesize subHeaderLabel;
|
||||
@synthesize iconImage = iconImage_;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark NSObject
|
||||
|
||||
#pragma mark - NSObject
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame {
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
@ -67,9 +64,7 @@
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark UIView
|
||||
#pragma mark - UIView
|
||||
|
||||
- (void)drawRect:(CGRect)rect {
|
||||
CGRect bounds = self.bounds;
|
||||
@ -85,8 +80,8 @@
|
||||
CGGradientRelease(gradient);
|
||||
|
||||
// draw header name
|
||||
UIColor *mainTextColor = BW_RGBCOLOR(0,0,0);
|
||||
UIColor *secondaryTextColor = BW_RGBCOLOR(48,48,48);
|
||||
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];
|
||||
@ -101,12 +96,10 @@
|
||||
|
||||
// shadows are a beast
|
||||
NSInteger shadowOffset = 2;
|
||||
BW_IF_IOS4_OR_GREATER(if([[UIScreen mainScreen] scale] == 2) shadowOffset = 1;)
|
||||
BW_IF_IOS5_OR_GREATER(shadowOffset = 1;) // iOS5 changes this - again!
|
||||
|
||||
BW_IF_3_2_OR_GREATER(CGContextSetShadowWithColor(context, CGSizeMake(shadowOffset, shadowOffset), 0, myColor);)
|
||||
BW_IF_PRE_3_2(shadowOffset=1;CGContextSetShadowWithColor(context, CGSizeMake(shadowOffset, -shadowOffset), 0, myColor);)
|
||||
if([[UIScreen mainScreen] scale] == 2) shadowOffset = 1;
|
||||
BITHOCKEYSDK_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];
|
||||
@ -124,9 +117,8 @@
|
||||
CGColorSpaceRelease(myColorSpace);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark Properties
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (void)setHeaderLabel:(NSString *)anHeaderLabel {
|
||||
if (headerLabel_ != anHeaderLabel) {
|
||||
@ -157,14 +149,14 @@
|
||||
[iconImage_ release];
|
||||
|
||||
// scale, make borders and reflection
|
||||
iconImage_ = [anIconImage bw_imageToFitSize:CGSizeMake(kImageHeight, kImageHeight) honorScaleFactor:YES];
|
||||
iconImage_ = [[iconImage_ bw_roundedCornerImage:kImageBorderRadius borderSize:0.0] retain];
|
||||
iconImage_ = [anIconImage bit_imageToFitSize:CGSizeMake(kImageHeight, kImageHeight) honorScaleFactor:YES];
|
||||
iconImage_ = [[iconImage_ bit_roundedCornerImage:kImageBorderRadius borderSize:0.0] retain];
|
||||
|
||||
// create reflected image
|
||||
[reflectedImage_ release];
|
||||
reflectedImage_ = nil;
|
||||
if (anIconImage) {
|
||||
reflectedImage_ = [[iconImage_ bw_reflectedImageWithHeight:kReflectionHeight fromAlpha:0.5 toAlpha:0.0] retain];
|
||||
reflectedImage_ = [[iconImage_ bit_reflectedImageWithHeight:kReflectionHeight fromAlpha:0.5 toAlpha:0.0] retain];
|
||||
}
|
||||
[self setNeedsDisplay];
|
||||
}
|
||||
|
@ -1,9 +1,6 @@
|
||||
//
|
||||
// PSStoreButton.h
|
||||
// HockeyDemo
|
||||
//
|
||||
// Created by Peter Steinberger on 09.01.11.
|
||||
// Copyright 2011 Peter Steinberger. All rights reserved.
|
||||
// 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
|
||||
|
@ -1,9 +1,6 @@
|
||||
//
|
||||
// PSStoreButton.m
|
||||
// HockeyDemo
|
||||
//
|
||||
// Created by Peter Steinberger on 09.01.11.
|
||||
// Copyright 2011 Peter Steinberger. All rights reserved.
|
||||
// Copyright 2011-2012 Peter Steinberger. All rights reserved.
|
||||
//
|
||||
// This code was inspired by https://github.com/dhmspector/ZIStoreButton
|
||||
//
|
||||
@ -39,9 +36,8 @@
|
||||
@synthesize colors = colors_;
|
||||
@synthesize enabled = enabled_;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark NSObject
|
||||
|
||||
#pragma mark - NSObject
|
||||
|
||||
- (id)initWithLabel:(NSString*)aLabel colors:(NSArray*)aColors enabled:(BOOL)flag {
|
||||
if ((self = [super init])) {
|
||||
@ -77,9 +73,8 @@
|
||||
@synthesize buttonDelegate = buttonDelegate_;
|
||||
@synthesize customPadding = customPadding_;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark private
|
||||
|
||||
#pragma mark - private
|
||||
|
||||
- (void)buttonPressed:(id)sender {
|
||||
[buttonDelegate_ storeButtonFired:self];
|
||||
@ -159,9 +154,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark NSObject
|
||||
|
||||
#pragma mark - NSObject
|
||||
|
||||
- (id)initWithFrame:(CGRect)frame {
|
||||
if ((self = [super initWithFrame:frame])) {
|
||||
@ -214,9 +208,8 @@
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark UIView
|
||||
|
||||
#pragma mark - UIView
|
||||
|
||||
- (CGSize)sizeThatFits:(CGSize)size {
|
||||
CGSize constr = (CGSize){.height = self.frame.size.height, .width = PS_MAX_WIDTH};
|
||||
@ -241,9 +234,8 @@
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark Properties
|
||||
|
||||
#pragma mark - Properties
|
||||
|
||||
- (void)setButtonData:(PSStoreButtonData *)aButtonData {
|
||||
[self setButtonData:aButtonData animated:NO];
|
||||
@ -258,9 +250,8 @@
|
||||
[self updateButtonAnimated:animated];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark Static
|
||||
|
||||
#pragma mark - Static
|
||||
|
||||
+ (NSArray *)appStoreGreenColor {
|
||||
return [NSArray arrayWithObjects:(id)
|
||||
|
@ -1,9 +1,6 @@
|
||||
//
|
||||
// PSWebTableViewCell.h
|
||||
// HockeyDemo
|
||||
//
|
||||
// Created by Peter Steinberger on 04.02.11.
|
||||
// Copyright 2011 Peter Steinberger. All rights reserved.
|
||||
// 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
|
||||
|
@ -1,9 +1,6 @@
|
||||
//
|
||||
// PSWebTableViewCell.m
|
||||
// HockeyDemo
|
||||
//
|
||||
// Created by Peter Steinberger on 04.02.11.
|
||||
// Copyright 2011 Peter Steinberger. All rights reserved.
|
||||
// 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
|
||||
@ -24,7 +21,7 @@
|
||||
// THE SOFTWARE.
|
||||
|
||||
#import "PSWebTableViewCell.h"
|
||||
#import "BWGlobal.h"
|
||||
|
||||
|
||||
@implementation PSWebTableViewCell
|
||||
|
||||
@ -47,9 +44,8 @@ body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px
|
||||
@synthesize webViewSize = webViewSize_;
|
||||
@synthesize cellBackgroundColor = cellBackgroundColor_;
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark private
|
||||
|
||||
#pragma mark - private
|
||||
|
||||
- (void)addWebView {
|
||||
if(webViewContent_) {
|
||||
@ -83,7 +79,7 @@ body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px
|
||||
webView_.frame = webViewRect;
|
||||
|
||||
NSString *deviceWidth = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ? [NSString stringWithFormat:@"%.0f", CGRectGetWidth(self.bounds)] : @"device-width";
|
||||
//BWHockeyLog(@"%@\n%@\%@", PSWebTableViewCellHtmlTemplate, deviceWidth, self.webViewContent);
|
||||
//HockeySDKLog(@"%@\n%@\%@", PSWebTableViewCellHtmlTemplate, deviceWidth, self.webViewContent);
|
||||
NSString *contentHtml = [NSString stringWithFormat:PSWebTableViewCellHtmlTemplate, deviceWidth, self.webViewContent];
|
||||
[webView_ loadHTMLString:contentHtml baseURL:nil];
|
||||
}
|
||||
@ -118,9 +114,8 @@ body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark NSObject
|
||||
|
||||
#pragma mark - NSObject
|
||||
|
||||
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
|
||||
if((self = [super initWithStyle:style reuseIdentifier:reuseIdentifier])) {
|
||||
@ -135,9 +130,8 @@ body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px
|
||||
[super dealloc];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark UIView
|
||||
|
||||
#pragma mark - UIView
|
||||
|
||||
- (void)setFrame:(CGRect)aFrame {
|
||||
BOOL needChange = !CGRectEqualToRect(aFrame, self.frame);
|
||||
@ -148,9 +142,8 @@ body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark UITableViewCell
|
||||
|
||||
#pragma mark - UITableViewCell
|
||||
|
||||
- (void)prepareForReuse {
|
||||
[self removeWebView];
|
||||
@ -158,9 +151,8 @@ body { font: 13px 'Helvetica Neue', Helvetica; word-wrap:break-word; padding:8px
|
||||
[super prepareForReuse];
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
#pragma mark -
|
||||
#pragma mark UIWebView
|
||||
|
||||
#pragma mark - UIWebView
|
||||
|
||||
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
|
||||
if(navigationType == UIWebViewNavigationTypeOther)
|
||||
|
@ -1,9 +1,10 @@
|
||||
//
|
||||
// UIImage+HockeyAdditions.h
|
||||
// HockeyDemo
|
||||
// UIImage+BITHockeySDKAdditions.h
|
||||
//
|
||||
// Created by Peter Steinberger on 10.01.11.
|
||||
// Copyright 2011 Peter Steinberger. All rights reserved.
|
||||
// Copyright (c) 2011-2012 Peter Steinberger.
|
||||
// Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
// 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
|
||||
@ -25,14 +26,14 @@
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@interface UIImage (HockeyAdditions)
|
||||
@interface UIImage (BITHockeySDKAdditions)
|
||||
|
||||
- (UIImage *)bw_roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize;
|
||||
- (UIImage *)bw_imageToFitSize:(CGSize)fitSize honorScaleFactor:(BOOL)honorScaleFactor;
|
||||
- (UIImage *)bw_reflectedImageWithHeight:(NSUInteger)height fromAlpha:(float)fromAlpha toAlpha:(float)toAlpha;
|
||||
- (UIImage *)bit_roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize;
|
||||
- (UIImage *)bit_imageToFitSize:(CGSize)fitSize honorScaleFactor:(BOOL)honorScaleFactor;
|
||||
- (UIImage *)bit_reflectedImageWithHeight:(NSUInteger)height fromAlpha:(float)fromAlpha toAlpha:(float)toAlpha;
|
||||
|
||||
- (id)bw_initWithContentsOfResolutionIndependentFile:(NSString *)path NS_RETURNS_RETAINED;
|
||||
+ (UIImage*)bw_imageWithContentsOfResolutionIndependentFile:(NSString *)path;
|
||||
+ (UIImage *)bw_imageNamed:(NSString *)imageName bundle:(NSString *)bundleName;
|
||||
- (id)bit_initWithContentsOfResolutionIndependentFile:(NSString *)path NS_RETURNS_RETAINED;
|
||||
+ (UIImage *)bit_imageWithContentsOfResolutionIndependentFile:(NSString *)path;
|
||||
+ (UIImage *)bit_imageNamed:(NSString *)imageName bundle:(NSString *)bundleName;
|
||||
|
||||
@end
|
@ -1,9 +1,10 @@
|
||||
//
|
||||
// UIImage+HockeyAdditions.m
|
||||
// HockeyDemo
|
||||
// UIImage+BITHockeySDKAdditions.m
|
||||
//
|
||||
// Created by Peter Steinberger on 10.01.11.
|
||||
// Copyright 2011 Peter Steinberger. All rights reserved.
|
||||
// Copyright (c) 2011-2012 Peter Steinberger.
|
||||
// Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
// 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
|
||||
@ -23,20 +24,14 @@
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
#import "UIImage+HockeyAdditions.h"
|
||||
#import "BWGlobal.h"
|
||||
|
||||
#ifdef HOCKEYLIB_STATIC_LIBRARY
|
||||
#import "CNSFixCategoryBug.h"
|
||||
CNS_FIX_CATEGORY_BUG(UIImage_HockeyAdditionsPrivate)
|
||||
#endif
|
||||
#import "UIImage+BITHockeyAdditions.h"
|
||||
|
||||
// Private helper methods
|
||||
@interface UIImage (HockeyAdditionsPrivate)
|
||||
- (void)addRoundedRectToPath:(CGRect)rect context:(CGContextRef)context ovalWidth:(CGFloat)ovalWidth ovalHeight:(CGFloat)ovalHeight;
|
||||
@interface UIImage (BITHockeyAdditionsPrivate)
|
||||
- (void)bit_addRoundedRectToPath:(CGRect)rect context:(CGContextRef)context ovalWidth:(CGFloat)ovalWidth ovalHeight:(CGFloat)ovalHeight;
|
||||
@end
|
||||
|
||||
@implementation UIImage (HockeyAdditions)
|
||||
@implementation UIImage (BITHockeyAdditions)
|
||||
|
||||
CGContextRef MyOpenBitmapContext(int pixelsWide, int pixelsHigh);
|
||||
CGImageRef CreateGradientImage(int pixelsWide, int pixelsHigh, float fromAlpha, float toAlpha);
|
||||
@ -84,32 +79,29 @@ CGImageRef CreateGradientImage(int pixelsWide, int pixelsHigh, float fromAlpha,
|
||||
// Creates a copy of this image with rounded corners
|
||||
// If borderSize is non-zero, a transparent border of the given size will also be added
|
||||
// Original author: Björn Sållarp. Used with permission. See: http://blog.sallarp.com/iphone-uiimage-round-corners/
|
||||
- (UIImage *)bw_roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize {
|
||||
- (UIImage *)bit_roundedCornerImage:(NSInteger)cornerSize borderSize:(NSInteger)borderSize {
|
||||
// If the image does not have an alpha layer, add one
|
||||
|
||||
UIImage *roundedImage = nil;
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
|
||||
BW_IF_IOS4_OR_GREATER(
|
||||
UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0); // 0.0 for scale means "correct scale for device's main screen".
|
||||
CGImageRef sourceImg = CGImageCreateWithImageInRect([self CGImage], CGRectMake(0, 0, self.size.width * self.scale, self.size.height * self.scale)); // cropping happens here.
|
||||
|
||||
// Create a clipping path with rounded corners
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextBeginPath(context);
|
||||
[self addRoundedRectToPath:CGRectMake(borderSize, borderSize, self.size.width - borderSize * 2, self.size.height - borderSize * 2)
|
||||
context:context
|
||||
ovalWidth:cornerSize
|
||||
ovalHeight:cornerSize];
|
||||
CGContextClosePath(context);
|
||||
CGContextClip(context);
|
||||
|
||||
roundedImage = [UIImage imageWithCGImage:sourceImg scale:0.0 orientation:self.imageOrientation]; // create cropped UIImage.
|
||||
[roundedImage drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)]; // the actual scaling happens here, and orientation is taken care of automatically.
|
||||
CGImageRelease(sourceImg);
|
||||
roundedImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
)
|
||||
#endif
|
||||
UIGraphicsBeginImageContextWithOptions(self.size, NO, 0.0); // 0.0 for scale means "correct scale for device's main screen".
|
||||
CGImageRef sourceImg = CGImageCreateWithImageInRect([self CGImage], CGRectMake(0, 0, self.size.width * self.scale, self.size.height * self.scale)); // cropping happens here.
|
||||
|
||||
// Create a clipping path with rounded corners
|
||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
||||
CGContextBeginPath(context);
|
||||
[self addRoundedRectToPath:CGRectMake(borderSize, borderSize, self.size.width - borderSize * 2, self.size.height - borderSize * 2)
|
||||
context:context
|
||||
ovalWidth:cornerSize
|
||||
ovalHeight:cornerSize];
|
||||
CGContextClosePath(context);
|
||||
CGContextClip(context);
|
||||
|
||||
roundedImage = [UIImage imageWithCGImage:sourceImg scale:0.0 orientation:self.imageOrientation]; // create cropped UIImage.
|
||||
[roundedImage drawInRect:CGRectMake(0, 0, self.size.width, self.size.height)]; // the actual scaling happens here, and orientation is taken care of automatically.
|
||||
CGImageRelease(sourceImg);
|
||||
roundedImage = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
if (!roundedImage) {
|
||||
// Try older method.
|
||||
UIImage *image = [self imageWithAlpha];
|
||||
@ -146,8 +138,7 @@ CGImageRef CreateGradientImage(int pixelsWide, int pixelsHigh, float fromAlpha,
|
||||
return roundedImage;
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
#pragma mark Private helper methods
|
||||
#pragma mark - Private helper methods
|
||||
|
||||
// Adds a rectangular path to the given context and rounds its corners by the given extents
|
||||
// Original author: Björn Sållarp. Used with permission. See: http://blog.sallarp.com/iphone-uiimage-round-corners/
|
||||
@ -170,16 +161,14 @@ CGImageRef CreateGradientImage(int pixelsWide, int pixelsHigh, float fromAlpha,
|
||||
CGContextRestoreGState(context);
|
||||
}
|
||||
|
||||
- (UIImage *)bw_imageToFitSize:(CGSize)fitSize honorScaleFactor:(BOOL)honorScaleFactor
|
||||
- (UIImage *)bit_imageToFitSize:(CGSize)fitSize honorScaleFactor:(BOOL)honorScaleFactor
|
||||
{
|
||||
float imageScaleFactor = 1.0;
|
||||
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
|
||||
if (honorScaleFactor) {
|
||||
if ([self respondsToSelector:@selector(scale)]) {
|
||||
imageScaleFactor = [self scale];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
float sourceWidth = [self size].width * imageScaleFactor;
|
||||
float sourceHeight = [self size].height * imageScaleFactor;
|
||||
@ -214,16 +203,13 @@ CGImageRef CreateGradientImage(int pixelsWide, int pixelsHigh, float fromAlpha,
|
||||
|
||||
// Create appropriately modified image.
|
||||
UIImage *image = nil;
|
||||
BW_IF_IOS4_OR_GREATER
|
||||
(
|
||||
UIGraphicsBeginImageContextWithOptions(destRect.size, NO, honorScaleFactor ? 0.0 : 1.0); // 0.0 for scale means "correct scale for device's main screen".
|
||||
CGImageRef sourceImg = CGImageCreateWithImageInRect([self CGImage], sourceRect); // cropping happens here.
|
||||
image = [UIImage imageWithCGImage:sourceImg scale:0.0 orientation:self.imageOrientation]; // create cropped UIImage.
|
||||
[image drawInRect:destRect]; // the actual scaling happens here, and orientation is taken care of automatically.
|
||||
CGImageRelease(sourceImg);
|
||||
image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
)
|
||||
UIGraphicsBeginImageContextWithOptions(destRect.size, NO, honorScaleFactor ? 0.0 : 1.0); // 0.0 for scale means "correct scale for device's main screen".
|
||||
CGImageRef sourceImg = CGImageCreateWithImageInRect([self CGImage], sourceRect); // cropping happens here.
|
||||
image = [UIImage imageWithCGImage:sourceImg scale:0.0 orientation:self.imageOrientation]; // create cropped UIImage.
|
||||
[image drawInRect:destRect]; // the actual scaling happens here, and orientation is taken care of automatically.
|
||||
CGImageRelease(sourceImg);
|
||||
image = UIGraphicsGetImageFromCurrentImageContext();
|
||||
UIGraphicsEndImageContext();
|
||||
|
||||
if (!image) {
|
||||
// Try older method.
|
||||
@ -292,7 +278,7 @@ CGContextRef MyOpenBitmapContext(int pixelsWide, int pixelsHigh) {
|
||||
return UIGraphicsGetCurrentContext();
|
||||
}
|
||||
|
||||
- (UIImage *)bw_reflectedImageWithHeight:(NSUInteger)height fromAlpha:(float)fromAlpha toAlpha:(float)toAlpha {
|
||||
- (UIImage *)bit_reflectedImageWithHeight:(NSUInteger)height fromAlpha:(float)fromAlpha toAlpha:(float)toAlpha {
|
||||
if(height == 0)
|
||||
return nil;
|
||||
|
||||
@ -319,7 +305,7 @@ CGContextRef MyOpenBitmapContext(int pixelsWide, int pixelsHigh) {
|
||||
return theImage;
|
||||
}
|
||||
|
||||
- (id)bw_initWithContentsOfResolutionIndependentFile:(NSString *)path {
|
||||
- (id)bit_initWithContentsOfResolutionIndependentFile:(NSString *)path {
|
||||
if ([UIScreen instancesRespondToSelector:@selector(scale)] && (int)[[UIScreen mainScreen] scale] == 2.0) {
|
||||
NSString *path2x = [[path stringByDeletingLastPathComponent]
|
||||
stringByAppendingPathComponent:[NSString stringWithFormat:@"%@@2x.%@",
|
||||
@ -334,19 +320,19 @@ CGContextRef MyOpenBitmapContext(int pixelsWide, int pixelsHigh) {
|
||||
return [self initWithContentsOfFile:path];
|
||||
}
|
||||
|
||||
+ (UIImage*)bw_imageWithContentsOfResolutionIndependentFile:(NSString *)path {
|
||||
+ (UIImage*)bit_imageWithContentsOfResolutionIndependentFile:(NSString *)path {
|
||||
#ifndef __clang_analyzer__
|
||||
// clang alayzer in 4.2b3 thinks here's a leak, which is not the case.
|
||||
return [[[UIImage alloc] bw_initWithContentsOfResolutionIndependentFile:path] autorelease];
|
||||
return [[[UIImage alloc] bit_initWithContentsOfResolutionIndependentFile:path] autorelease];
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
+ (UIImage *)bw_imageNamed:(NSString *)imageName bundle:(NSString *)bundleName {
|
||||
+ (UIImage *)bit_imageNamed:(NSString *)imageName bundle:(NSString *)bundleName {
|
||||
NSString *resourcePath = [[NSBundle mainBundle] resourcePath];
|
||||
NSString *bundlePath = [resourcePath stringByAppendingPathComponent:bundleName];
|
||||
NSString *imagePath = [bundlePath stringByAppendingPathComponent:imageName];
|
||||
return [UIImage bw_imageWithContentsOfResolutionIndependentFile:imagePath];
|
||||
return [UIImage bit_imageWithContentsOfResolutionIndependentFile:imagePath];
|
||||
}
|
||||
|
||||
@end
|
@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |s|
|
||||
s.name = 'HockeySDK'
|
||||
s.version = '2.2.6'
|
||||
s.version = '2.3.0'
|
||||
s.license = 'MIT'
|
||||
s.platform = :ios
|
||||
s.summary = 'Distribute beta apps and collect crash reports with HockeyApp.'
|
||||
s.homepage = 'http://hockeyapp.net/'
|
||||
s.author = { 'Andreas Linde' => 'mail@andreaslinde.de', 'Thomas Dohmke' => "thomas@dohmke.de" }
|
||||
s.source = { :git => 'https://github.com/codenauts/HockeySDK-iOS', :tag => '2.2.3' }
|
||||
s.source = { :git => 'https://github.com/bitstadium/HockeySDK-iOS', :tag => '2.3.0' }
|
||||
|
||||
s.description = 'HockeyApp is a server to distribute beta apps and collect crash reports. ' \
|
||||
'It improves the testing process dramatically and can be used for both beta ' \
|
||||
@ -17,7 +17,7 @@ Pod::Spec.new do |s|
|
||||
'yourself when the network becomse reachable.'
|
||||
|
||||
s.source_files = 'Classes'
|
||||
s.resources = 'Resources/Hockey.bundle', 'Resources/Quincy.bundle'
|
||||
s.resources = 'Resources/HockeySDKResources.bundle'
|
||||
s.frameworks = 'QuartzCore', 'SystemConfiguration', 'CrashReporter'
|
||||
s.xcconfig = { 'FRAMEWORK_SEARCH_PATHS' => '"$(BUILT_PRODUCTS_DIR)/Pods/Frameworks"' }
|
||||
|
||||
|
15
LICENSE.txt
@ -1,20 +1,10 @@
|
||||
## Authors
|
||||
|
||||
Andreas Linde <andy@buzzworks.de>
|
||||
Stanley Rost <soryu2@gmail.com>
|
||||
Fabian Kreiser <fabian@fabian-kreiser.com>
|
||||
Tobias Höhmann
|
||||
FutureTap
|
||||
Kent Sutherland
|
||||
Peter Steinberger <me@petersteinberger.com>
|
||||
Thomas Dohmke <thomas@dohmke.de>
|
||||
|
||||
## Licenses
|
||||
|
||||
The Hockey SDK is provided under the following license:
|
||||
|
||||
The MIT License
|
||||
Copyright (c) 2011-2012 Codenauts UG (haftungsbeschränkt). All rights reserved.
|
||||
Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation
|
||||
@ -41,6 +31,7 @@ Except as noted below, PLCrashReporter
|
||||
is provided under the following license:
|
||||
|
||||
Copyright (c) 2008 - 2012 Plausible Labs Cooperative, Inc.
|
||||
Copyright (c) 2012 HockeyApp, Bit Stadium GmbH.
|
||||
All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
Hockey.strings
|
||||
Hockey
|
||||
|
||||
Created by Andreas Linde on 11/15/10.
|
||||
Copyright 2010 buzzworks.de. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
/* Alert view */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Ja";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "Nein";
|
||||
|
||||
/* Update available */
|
||||
"HockeyUpdateAvailable" = "Aktualisierung verfügbar";
|
||||
|
||||
/* Would you like to check out the new update? You can do this later on at any time in the In-App settings. */
|
||||
"HockeyUpdateAlertText" = "Möchten Sie sich weitere Informationen zu der Aktualisierung ansehen?";
|
||||
|
||||
|
||||
/* Update details screen */
|
||||
|
||||
/* Update Details */
|
||||
"HockeyUpdateScreenTitle" = "Aktualisierung";
|
||||
|
||||
|
||||
/* Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"HockeySettingsTitle" = "Einstellungen";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"HockeySettingsUserData" = "Daten senden";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"HockeySettingsUserDataDescription" = "Daten senden liefert dem Entwickler die folgenden Daten: Programmversion, Sprache, Gerätetyp und iOS Version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"HockeySettingsUsageData" = "Testzeit senden";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"HockeySettingsUsageDataDescription" = "Testzeit senden informiert den Entwickler über die Summe der Testzeit, in einer Genauigkeit von 1 Minute.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"HockeySectionCheckTitle" = "Nach Aktualisierung Prüfen";
|
||||
|
||||
/* On Startup */
|
||||
"HockeySectionCheckStartup" = "Beim Start";
|
||||
|
||||
/* Daily */
|
||||
"HockeySectionCheckDaily" = "Täglich";
|
||||
|
||||
/* Manually */
|
||||
"HockeySectionCheckManually" = "Manuell";
|
||||
|
||||
|
||||
"HockeyVersion" = "Version";
|
||||
"HockeyShowPreviousVersions" = "Zeige frühere Versionen...";
|
||||
"HockeyNoUpdateNeededTitle" = "Kein Update Verfügbar";
|
||||
"HockeyNoUpdateNeededMessage" = "%@ ist bereits die aktuellste Version.";
|
||||
"HockeyUpdateAlertTextWithAppVersion" = "%@ ist verfügbar.";
|
||||
"HockeyUpdateAlertMandatoryTextWithAppVersion" = "%@ ist verfügbar und muss installiert werden!";
|
||||
"HockeyIgnore" = "Ignorieren";
|
||||
"HockeyShowUpdate" = "Anzeigen";
|
||||
"HockeyInstallUpdate" = "Installieren";
|
||||
"HockeyError" = "Fehler";
|
||||
"HockeyOK" = "OK";
|
||||
"HockeyWarning" = "Warnung";
|
||||
"HockeyNoReleaseNotesAvailable" = "Keine Release Notes verfügbar.";
|
||||
|
||||
"HockeyAuthorizationProgress" = "Autorisierung...";
|
||||
"HockeyAuthorizationOffline" = "Internet Verbindung wird benötigt!";
|
||||
"HockeyAuthorizationDenied" = "Autorisierung verweigert. Bitte kontaktieren Sie den Entwickler.";
|
||||
|
||||
"HockeyiOS3Message" = "In-App download benötigt iOS 4 oder höher. Sie können die Applikation manuell updaten, indem sie das IPA von %@ laden und es via iTunes syncen.";
|
||||
"HockeySimulatorMessage" = "Hockey funktioniert nicht im Simulator.";
|
||||
|
||||
"HockeyButtonCheck" = "PRÜFE";
|
||||
"HockeyButtonSearching" = "PRÜFEN";
|
||||
"HockeyButtonUpdate" = "UPDATE";
|
||||
"HockeyButtonInstalling" = "INSTALLIEREN";
|
||||
"HockeyButtonOffline" = "OFFLINE";
|
||||
"HockeyInstalled" = "INSTALLIERT";
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
Hockey.strings
|
||||
Hockey
|
||||
|
||||
Created by Andreas Linde on 11/15/10.
|
||||
Copyright 2010 buzzworks.de. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
/* Alert view */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Yes";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "No";
|
||||
|
||||
/* Update available */
|
||||
"HockeyUpdateAvailable" = "Update available";
|
||||
|
||||
/* Would you like to check out the new update? You can do this later on at any time in the In-App settings. */
|
||||
"HockeyUpdateAlertText" = "Would you like to check out the new update?";
|
||||
|
||||
|
||||
/* Update details screen */
|
||||
|
||||
/* Update Details */
|
||||
"HockeyUpdateScreenTitle" = "Update";
|
||||
|
||||
|
||||
/* Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"HockeySettingsTitle" = "Settings";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"HockeySettingsUserData" = "Send User Data";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"HockeySettingsUserDataDescription" = "Send User Data will send the following data to the developer: app version, language, device type and iOS version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"HockeySettingsUsageData" = "Send Usage Data";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"HockeySettingsUsageDataDescription" = "Send Usage Data will send the amount of test time to the developer, in a granularity of 1 minute.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"HockeySectionCheckTitle" = "Check For Update";
|
||||
|
||||
/* On Startup */
|
||||
"HockeySectionCheckStartup" = "On Startup";
|
||||
|
||||
/* Daily */
|
||||
"HockeySectionCheckDaily" = "Daily";
|
||||
|
||||
/* Manually */
|
||||
"HockeySectionCheckManually" = "Manually";
|
||||
|
||||
|
||||
"HockeyVersion" = "Version";
|
||||
"HockeyShowPreviousVersions" = "Show previous versions...";
|
||||
"HockeyNoUpdateNeededTitle" = "No Update Available";
|
||||
"HockeyNoUpdateNeededMessage" = "%@ is already the latest version.";
|
||||
"HockeyUpdateAlertTextWithAppVersion" = "%@ is available.";
|
||||
"HockeyUpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
"HockeyIgnore" = "Ignore";
|
||||
"HockeyShowUpdate" = "Show";
|
||||
"HockeyInstallUpdate" = "Install";
|
||||
"HockeyError" = "Error";
|
||||
"HockeyOK" = "OK";
|
||||
"HockeyWarning" = "Warning";
|
||||
"HockeyNoReleaseNotesAvailable" = "No release notes available.";
|
||||
|
||||
"HockeyAuthorizationProgress" = "Authorizing...";
|
||||
"HockeyAuthorizationOffline" = "Internet connection required!";
|
||||
"HockeyAuthorizationDenied" = "Authorizing denied. Please contact the developer.";
|
||||
|
||||
"HockeyiOS3Message" = "In-App download requires iOS 4 or higher. You can update this application via downloading the IPA from %@ and syncing it with iTunes.";
|
||||
"HockeySimulatorMessage" = "Hockey Update does not work in the Simulator.\nThe itms-services:// url scheme is implemented but nonfunctional.";
|
||||
|
||||
"HockeyButtonCheck" = "CHECK";
|
||||
"HockeyButtonSearching" = "CHECKING";
|
||||
"HockeyButtonUpdate" = "UPDATE";
|
||||
"HockeyButtonInstalling" = "INSTALLING";
|
||||
"HockeyButtonOffline" = "OFFLINE";
|
||||
"HockeyInstalled" = "INSTALLED";
|
@ -1,87 +0,0 @@
|
||||
/*
|
||||
Hockey.strings
|
||||
Hockey
|
||||
|
||||
Created by Andreas Linde on 11/15/10.
|
||||
Copyright 2010 buzzworks.de. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
/* Alert view */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Si";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "No";
|
||||
|
||||
/* Update available */
|
||||
"HockeyUpdateAvailable" = "Aggiornamento disponibile";
|
||||
|
||||
/* Would you like to check out the new update? You can do this later on at any time in the In-App settings. */
|
||||
"HockeyUpdateAlertText" = "Vuoi scaricare il nuovo aggiornamento ?";
|
||||
|
||||
|
||||
/* Update details screen */
|
||||
|
||||
/* Update Details */
|
||||
"HockeyUpdateScreenTitle" = "Aggiorna";
|
||||
|
||||
|
||||
/* Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"HockeySettingsTitle" = "Impostazioni";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"HockeySettingsUserData" = "Invia dati di sistema";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"HockeySettingsUserDataDescription" = "Invia le seguenti informazioni allo sviluppatore: versione app, lingua, tipo dispositivo e versione iOS.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"HockeySettingsUsageData" = "Invia dati di utilizzo";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"HockeySettingsUsageDataDescription" = "Invia il tempo di utilizzo allo svilupatore, con un dettaglio di 1 minuto.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"HockeySectionCheckTitle" = "Controlla gli aggiornamenti";
|
||||
|
||||
/* On Startup */
|
||||
"HockeySectionCheckStartup" = "All'avvio";
|
||||
|
||||
/* Daily */
|
||||
"HockeySectionCheckDaily" = "Ogni giorno";
|
||||
|
||||
/* Manually */
|
||||
"HockeySectionCheckManually" = "Manualmente";
|
||||
|
||||
|
||||
"HockeyVersion" = "Versione";
|
||||
"HockeyShowPreviousVersions" = "Mostra le versioni precedenti...";
|
||||
"HockeyNoUpdateNeededTitle" = "Nessun aggiornamento disponibile";
|
||||
"HockeyNoUpdateNeededMessage" = "%@ <20> aggiornata all'ultima versione.";
|
||||
"HockeyUpdateAlertTextWithAppVersion" = "%@ <20> disponibile.";
|
||||
"HockeyUpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
"HockeyIgnore" = "Ignora";
|
||||
"HockeyShowUpdate" = "Mostra";
|
||||
"HockeyInstallUpdate" = "Installa";
|
||||
"HockeyError" = "Errore";
|
||||
"HockeyOK" = "OK";
|
||||
"HockeyWarning" = "Avviso";
|
||||
"HockeyNoReleaseNotesAvailable" = "Non sono disponibili note di rilascio.";
|
||||
|
||||
"HockeyAuthorizationProgress" = "Attendo autorizzazione...";
|
||||
"HockeyAuthorizationOffline" = "E' richiesta la connessione internet!";
|
||||
"HockeyAuthorizationDenied" = "Autorizzazione negata, contattare lo sviluppatore.";
|
||||
|
||||
"HockeyiOS3Message" = "L'aggioranento dall'applicazione <20> possibile con iOS 4 o superiore. Puoi aggiornare questa applicazione scaricandola da %@.";
|
||||
"HockeySimulatorMessage" = "Hockey Update does not work in the Simulator.\nThe itms-services:// url scheme is implemented but nonfunctional.";
|
||||
|
||||
"HockeyButtonCheck" = "CONTROLLA";
|
||||
"HockeyButtonSearching" = "CONTROLLO";
|
||||
"HockeyButtonUpdate" = "AGGIORNA";
|
||||
"HockeyButtonInstalling" = "INSTALLO";
|
||||
"HockeyButtonOffline" = "OFFLINE";
|
||||
"HockeyInstalled" = "INSTALLATA";
|
@ -1,88 +0,0 @@
|
||||
/*
|
||||
Hockey.strings
|
||||
Hockey
|
||||
|
||||
Created by Andreas Linde on 11/15/10.
|
||||
Copyright 2010 buzzworks.de. All rights reserved.
|
||||
Swedish translation by Joakim Ramer.
|
||||
*/
|
||||
|
||||
|
||||
/* Alert view */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Ja";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "Nej";
|
||||
|
||||
/* Update available */
|
||||
"HockeyUpdateAvailable" = "Uppdatering tillgänglig";
|
||||
|
||||
/* Would you like to check out the new update? You can do this later on at any time in the In-App settings. */
|
||||
"HockeyUpdateAlertText" = "Vill du hämta den nya uppdateringen?";
|
||||
|
||||
|
||||
/* Update details screen */
|
||||
|
||||
/* Update Details */
|
||||
"HockeyUpdateScreenTitle" = "Uppdatera";
|
||||
|
||||
|
||||
/* Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"HockeySettingsTitle" = "Inställningar";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"HockeySettingsUserData" = "Skicka användardata";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"HockeySettingsUserDataDescription" = "Skicka användardata skickar följande till utvecklaren: app version, språk, enhetstyp och iOS version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"HockeySettingsUsageData" = "Skicka användn.data";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"HockeySettingsUsageDataDescription" = "Skicka användningsdata skickar information om hur länge appen testats (i antal minuter), till utvecklaren.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"HockeySectionCheckTitle" = "Leta efter uppdateringar";
|
||||
|
||||
/* On Startup */
|
||||
"HockeySectionCheckStartup" = "Vid uppstart";
|
||||
|
||||
/* Daily */
|
||||
"HockeySectionCheckDaily" = "Dagligen";
|
||||
|
||||
/* Manually */
|
||||
"HockeySectionCheckManually" = "Manuellt";
|
||||
|
||||
|
||||
"HockeyVersion" = "Version";
|
||||
"HockeyShowPreviousVersions" = "Se tidigare versioner...";
|
||||
"HockeyNoUpdateNeededTitle" = "Ingen uppdatering tillgänglig";
|
||||
"HockeyNoUpdateNeededMessage" = "%@ är den senaste versionen.";
|
||||
"HockeyUpdateAlertTextWithAppVersion" = "%@ finns.";
|
||||
"HockeyUpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
"HockeyIgnore" = "Ignorera";
|
||||
"HockeyShowUpdate" = "Visa";
|
||||
"HockeyInstallUpdate" = "Installera";
|
||||
"HockeyError" = "Error";
|
||||
"HockeyOK" = "OK";
|
||||
"HockeyWarning" = "Varning";
|
||||
"HockeyNoReleaseNotesAvailable" = "Inga releasenoteringar tillgängliga.";
|
||||
|
||||
"HockeyAuthorizationProgress" = "Auktoriserar...";
|
||||
"HockeyAuthorizationOffline" = "Internetuppkoppling krävs!";
|
||||
"HockeyAuthorizationDenied" = "Auktoriseringen nekades. Kontakta utvecklaren.";
|
||||
|
||||
"HockeyiOS3Message" = "In-App nedladdning kräver iOS 4 eller högre. Du kan uppdatera applikationen genoma att ladda ner IPA-filen från %@ och synka in den i iTunes.";
|
||||
"HockeySimulatorMessage" = "Hockey Update fungerar inte i Simulatorn.\nitms-services:// url schemat är implementerat men fungerar ej.";
|
||||
|
||||
"HockeyButtonCheck" = "FRÅGA";
|
||||
"HockeyButtonSearching" = "FRÅGAR";
|
||||
"HockeyButtonUpdate" = "UPPDATERA";
|
||||
"HockeyButtonInstalling" = "INSTALLERAR";
|
||||
"HockeyButtonOffline" = "OFFLINE";
|
||||
"HockeyInstalled" = "INSTALLERAD";
|
Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 4.3 KiB After Width: | Height: | Size: 4.3 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
Before Width: | Height: | Size: 4.7 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1021 B After Width: | Height: | Size: 1021 B |
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
144
Resources/de.lproj/HockeySDK.strings
Executable file
@ -0,0 +1,144 @@
|
||||
/* General */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Ja";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "Nein";
|
||||
|
||||
/* For dialogs ok buttons */
|
||||
"HockeyOK" = "OK";
|
||||
|
||||
|
||||
/* Crash */
|
||||
|
||||
|
||||
/* Crash dialog */
|
||||
|
||||
/* Title showing in the alert box when crash report data has been found */
|
||||
"CrashDataFoundTitle" = "%@ unerwartet beendet";
|
||||
|
||||
/* Description explaining that crash data has been found and ask the user if the data might be uplaoded to the developers server */
|
||||
"CrashDataFoundDescription" = "Möchten Sie einen anonymen Absturzbericht senden, damit wir das Problem beheben können?";
|
||||
|
||||
/* Alert box button if the users wants to send crash data always automatically */
|
||||
"CrashSendReportAlways" = "Immer senden";
|
||||
|
||||
/* Alert box button to send the crash report once */
|
||||
"CrashSendReport" = "Bericht senden";
|
||||
|
||||
/* Alert box button to decline sending the report */
|
||||
"CrashDontSendReport" = "Nicht senden";
|
||||
|
||||
/* Text showing in a processing box that the crash data is being uploaded to the server */
|
||||
"CrashReportSending" = "Senden…";
|
||||
|
||||
|
||||
/* Crash status dialog */
|
||||
|
||||
/* Title for the alertview giving feedback about the crash */
|
||||
"CrashResponseTitle" = "Zuvor auf %@";
|
||||
|
||||
/* Full text telling the bug is fixed and will be available in the next release */
|
||||
"CrashResponseNextRelease" = "%@ wurde unerwartet beendet. Die gute Nachricht? Die Absturzursache wurde gefunden und wird für eine zukünftige Aktualisierung behoben. Bleiben Sie dran.";
|
||||
|
||||
/* Full text telling the bug is fixed and the new release is waiting at Apple */
|
||||
"CrashResponseWaitingApple" = "%@ wurde unerwartet beendet. Die gute Nachricht? Wir haben den Fehler bereits behoben und eine Aktualisierung an Apple gesendet. Gedulden Sie sich noch etwas, während sie geprüft wird.";
|
||||
|
||||
/* Full text telling the bug is fixed and an update is available in the AppStore */
|
||||
"CrashResponseAvailable" = "%@ wurde unerwartet beendet. Die gute Nachricht? Wir haben den Fehler bereits behoben! Aktualisieren Sie auf die neueste Version.";
|
||||
|
||||
|
||||
/* Update */
|
||||
|
||||
|
||||
/* Update Alert view */
|
||||
|
||||
/* Update available */
|
||||
"UpdateAvailable" = "Aktualisierung verfügbar";
|
||||
|
||||
"UpdateAlertTextWithAppVersion" = "%@ ist verfügbar.";
|
||||
|
||||
"UpdateAlertMandatoryTextWithAppVersion" = "%@ ist verfügbar und muss installiert werden!";
|
||||
|
||||
"UpdateIgnore" = "Ignorieren";
|
||||
|
||||
"UpdateShow" = "Anzeigen";
|
||||
|
||||
"UpdateInstall" = "Installieren";
|
||||
|
||||
|
||||
/* Update Details */
|
||||
|
||||
"UpdateScreenTitle" = "Aktualisierung";
|
||||
|
||||
"UpdateButtonCheck" = "PRÜFE";
|
||||
|
||||
"UpdateButtonSearching" = "PRÜFEN";
|
||||
|
||||
"UpdateButtonUpdate" = "UPDATE";
|
||||
|
||||
"UpdateButtonInstalling" = "INSTALLIEREN";
|
||||
|
||||
"UpdateButtonOffline" = "OFFLINE";
|
||||
|
||||
"UpdateInstalled" = "INSTALLIERT";
|
||||
|
||||
"UpdateVersion" = "Version";
|
||||
|
||||
"UpdateShowPreviousVersions" = "Zeige frühere Versionen...";
|
||||
|
||||
"UpdateNoUpdateAvailableTitle" = "Kein Update Verfügbar";
|
||||
|
||||
"UpdateNoUpdateAvailableMessage" = "%@ ist bereits die aktuellste Version.";
|
||||
|
||||
"UpdateError" = "Fehler";
|
||||
|
||||
"UpdateWarning" = "Warnung";
|
||||
|
||||
"UpdateNoReleaseNotesAvailable" = "Keine Release Notes verfügbar.";
|
||||
|
||||
|
||||
/* Update Authorization */
|
||||
|
||||
"UpdateAuthorizationProgress" = "Autorisierung...";
|
||||
|
||||
"UpdateAuthorizationOffline" = "Internet Verbindung wird benötigt!";
|
||||
|
||||
"UpdateAuthorizationDenied" = "Autorisierung verweigert. Bitte kontaktieren Sie den Entwickler.";
|
||||
|
||||
|
||||
/* Update Simulator Warning */
|
||||
|
||||
"UpdateSimulatorMessage" = "Hockey funktioniert nicht im Simulator.";
|
||||
|
||||
|
||||
/* Update Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"UpdateSettingsTitle" = "Einstellungen";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"UpdateSettingsUserData" = "Daten senden";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"UpdateSettingsUserDataDescription" = "Daten senden liefert dem Entwickler die folgenden Daten: Programmversion, Sprache, Gerätetyp und iOS Version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"UpdateSettingsUsageData" = "Testzeit senden";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"UpdateSettingsUsageDataDescription" = "Testzeit senden informiert den Entwickler über die Summe der Testzeit, in einer Genauigkeit von 1 Minute.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"UpdateSectionCheckTitle" = "Nach Aktualisierung Prüfen";
|
||||
|
||||
/* On Startup */
|
||||
"UpdateSectionCheckStartup" = "Beim Start";
|
||||
|
||||
/* Daily */
|
||||
"UpdateSectionCheckDaily" = "Täglich";
|
||||
|
||||
/* Manually */
|
||||
"UpdateSectionCheckManually" = "Manuell";
|
||||
|
143
Resources/en.lproj/HockeySDK.strings
Executable file
@ -0,0 +1,143 @@
|
||||
/* General */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Yes";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "No";
|
||||
|
||||
/* For dialogs ok buttons */
|
||||
"HockeyOK" = "OK";
|
||||
|
||||
|
||||
/* Crash */
|
||||
|
||||
|
||||
/* Crash dialog */
|
||||
|
||||
/* Title showing in the alert box when crash report data has been found */
|
||||
"CrashDataFoundTitle" = "%@ Unexpectedly Quit";
|
||||
|
||||
/* Description explaining that crash data has been found and ask the user if the data might be uploaded to the developers server */
|
||||
"CrashDataFoundDescription" = "Would you like to send an anonymous report so we can fix the problem?";
|
||||
|
||||
/* Alert box button if the users wants to send crash data always automatically */
|
||||
"CrashSendReportAlways" = "Always Send";
|
||||
|
||||
/* Alert box button to send the crash report once */
|
||||
"CrashSendReport" = "Send Report";
|
||||
|
||||
/* Alert box button to decline sending the report */
|
||||
"CrashDontSendReport" = "Don't Send";
|
||||
|
||||
/* Text showing in a processing box that the crash data is being uploaded to the server */
|
||||
"CrashReportSending" = "Sending…";
|
||||
|
||||
|
||||
/* Crash status dialog */
|
||||
|
||||
/* Title for the alertview giving feedback about the crash */
|
||||
"CrashResponseTitle" = "Previously on %@";
|
||||
|
||||
/* Full text telling the bug is fixed and will be available in the next release */
|
||||
"CrashResponseNextRelease" = "The bug has been fixed for a future update. Stay tuned.";
|
||||
|
||||
/* Full text telling the bug is fixed and the new release is waiting at Apple */
|
||||
"CrashResponseWaitingApple" = "The bug has been fixed, and we submitted an update to Apple. Hang tight while it’s in review!";
|
||||
|
||||
/* Full text telling the bug is fixed and an update is available in the AppStore */
|
||||
"CrashResponseAvailable" = "The bug has been fixed. Update to the latest version in the App Store.";
|
||||
|
||||
|
||||
/* Update */
|
||||
|
||||
|
||||
/* Update Alert view */
|
||||
|
||||
/* Update available */
|
||||
"UpdateAvailable" = "Update available";
|
||||
|
||||
"UpdateAlertTextWithAppVersion" = "%@ is available.";
|
||||
|
||||
"UpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
|
||||
"UpdateIgnore" = "Ignore";
|
||||
|
||||
"UpdateShow" = "Show";
|
||||
|
||||
"UpdateInstall" = "Install";
|
||||
|
||||
|
||||
/* Update Details */
|
||||
|
||||
"UpdateScreenTitle" = "Update";
|
||||
|
||||
"UpdateButtonCheck" = "CHECK";
|
||||
|
||||
"UpdateButtonSearching" = "CHECKING";
|
||||
|
||||
"UpdateButtonUpdate" = "UPDATE";
|
||||
|
||||
"UpdateButtonInstalling" = "INSTALLING";
|
||||
|
||||
"UpdateButtonOffline" = "OFFLINE";
|
||||
|
||||
"UpdateInstalled" = "INSTALLED";
|
||||
|
||||
"UpdateVersion" = "Version";
|
||||
|
||||
"UpdateShowPreviousVersions" = "Show previous versions...";
|
||||
|
||||
"UpdateNoUpdateAvailableTitle" = "No Update Available";
|
||||
|
||||
"UpdateNoUpdateAvailableMessage" = "%@ is already the latest version.";
|
||||
|
||||
"UpdateError" = "Error";
|
||||
|
||||
"UpdateWarning" = "Warning";
|
||||
|
||||
"UpdateNoReleaseNotesAvailable" = "No release notes available.";
|
||||
|
||||
|
||||
/* Update Authorization */
|
||||
|
||||
"UpdateAuthorizationProgress" = "Authorizing...";
|
||||
|
||||
"UpdateAuthorizationOffline" = "Internet connection required!";
|
||||
|
||||
"UpdateAuthorizationDenied" = "Authorizing denied. Please contact the developer.";
|
||||
|
||||
|
||||
/* Update Simulator Warning */
|
||||
|
||||
"UpdateSimulatorMessage" = "Hockey Update does not work in the Simulator.\nThe itms-services:// url scheme is implemented but nonfunctional.";
|
||||
|
||||
|
||||
/* Update Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"UpdateSettingsTitle" = "Settings";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"UpdateSettingsUserData" = "Send User Data";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"UpdateSettingsUserDataDescription" = "Send User Data will send the following data to the developer: app version, language, device type and iOS version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"UpdateSettingsUsageData" = "Send Usage Data";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"UpdateSettingsUsageDataDescription" = "Send Usage Data will send the amount of test time to the developer, in a granularity of 1 minute.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"UpdateSectionCheckTitle" = "Check For Update";
|
||||
|
||||
/* On Startup */
|
||||
"UpdateSectionCheckStartup" = "On Startup";
|
||||
|
||||
/* Daily */
|
||||
"UpdateSectionCheckDaily" = "Daily";
|
||||
|
||||
/* Manually */
|
||||
"UpdateSectionCheckManually" = "Manually";
|
143
Resources/es.lproj/HockeySDK.strings
Executable file
@ -0,0 +1,143 @@
|
||||
/* General */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Yes";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "No";
|
||||
|
||||
/* For dialogs ok buttons */
|
||||
"HockeyOK" = "OK";
|
||||
|
||||
|
||||
/* Crash */
|
||||
|
||||
|
||||
/* Crash dialog */
|
||||
|
||||
/* Title showing in the alert box when crash report data has been found */
|
||||
"CrashDataFoundTitle" = "Conflicto de datos detectado";
|
||||
|
||||
/* Description explaining that crash data has been found and ask the user if the data might be uploaded to the developers server */
|
||||
"CrashDataFoundDescription" = "La aplicación fallo previamente. ¿Le gustaría proporcionar de manera anonima información relacionado con el fallo al programador para que este pueda solucionar el problema?";
|
||||
|
||||
/* Alert box button if the users wants to send crash data always automatically */
|
||||
"CrashSendReportAlways" = "Siempre";
|
||||
|
||||
/* Alert box button to send the crash report once */
|
||||
"CrashSendReport" = "Sí";
|
||||
|
||||
/* Alert box button to decline sending the report */
|
||||
"CrashDontSendReport" = "No";
|
||||
|
||||
/* Text showing in a processing box that the crash data is being uploaded to the server */
|
||||
"CrashReportSending" = "Enviando…";
|
||||
|
||||
|
||||
/* Crash status dialog */
|
||||
|
||||
/* Title for the alertview giving feedback about the crash */
|
||||
"CrashResponseTitle" = "Estado de la falla";
|
||||
|
||||
/* Full text telling the bug is fixed and will be available in the next release */
|
||||
"CrashResponseNextRelease" = "El error que causo la falla ha sido solucionado y la corrección estará disponible en la siguiente versión de %@";
|
||||
|
||||
/* Full text telling the bug is fixed and the new release is waiting at Apple */
|
||||
"CrashResponseWaitingApple" = "El error que causo la falla ha sido solucionado, la nueva versión de %@ esta en espera de la aprobación de Apple";
|
||||
|
||||
/* Full text telling the bug is fixed and an update is available in the AppStore */
|
||||
"CrashResponseAvailable" = "El error que causo la falla ha sido solucionado, una nueva versión de %@ esta disponible. ¡Por favor actaulice!";
|
||||
|
||||
|
||||
/* Update */
|
||||
|
||||
|
||||
/* Update Alert view */
|
||||
|
||||
/* Update available */
|
||||
"UpdateAvailable" = "Update available";
|
||||
|
||||
"UpdateAlertTextWithAppVersion" = "%@ is available.";
|
||||
|
||||
"UpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
|
||||
"UpdateIgnore" = "Ignore";
|
||||
|
||||
"UpdateShow" = "Show";
|
||||
|
||||
"UpdateInstall" = "Install";
|
||||
|
||||
|
||||
/* Update Details */
|
||||
|
||||
"UpdateScreenTitle" = "Update";
|
||||
|
||||
"UpdateButtonCheck" = "CHECK";
|
||||
|
||||
"UpdateButtonSearching" = "CHECKING";
|
||||
|
||||
"UpdateButtonUpdate" = "UPDATE";
|
||||
|
||||
"UpdateButtonInstalling" = "INSTALLING";
|
||||
|
||||
"UpdateButtonOffline" = "OFFLINE";
|
||||
|
||||
"UpdateInstalled" = "INSTALLED";
|
||||
|
||||
"UpdateVersion" = "Version";
|
||||
|
||||
"UpdateShowPreviousVersions" = "Show previous versions...";
|
||||
|
||||
"UpdateNoUpdateAvailableTitle" = "No Update Available";
|
||||
|
||||
"UpdateNoUpdateAvailableMessage" = "%@ is already the latest version.";
|
||||
|
||||
"UpdateError" = "Error";
|
||||
|
||||
"UpdateWarning" = "Warning";
|
||||
|
||||
"UpdateNoReleaseNotesAvailable" = "No release notes available.";
|
||||
|
||||
|
||||
/* Update Authorization */
|
||||
|
||||
"UpdateAuthorizationProgress" = "Authorizing...";
|
||||
|
||||
"UpdateAuthorizationOffline" = "Internet connection required!";
|
||||
|
||||
"UpdateAuthorizationDenied" = "Authorizing denied. Please contact the developer.";
|
||||
|
||||
|
||||
/* Update Simulator Warning */
|
||||
|
||||
"UpdateSimulatorMessage" = "Hockey Update does not work in the Simulator.\nThe itms-services:// url scheme is implemented but nonfunctional.";
|
||||
|
||||
|
||||
/* Update Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"UpdateSettingsTitle" = "Settings";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"UpdateSettingsUserData" = "Send User Data";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"UpdateSettingsUserDataDescription" = "Send User Data will send the following data to the developer: app version, language, device type and iOS version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"UpdateSettingsUsageData" = "Send Usage Data";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"UpdateSettingsUsageDataDescription" = "Send Usage Data will send the amount of test time to the developer, in a granularity of 1 minute.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"UpdateSectionCheckTitle" = "Check For Update";
|
||||
|
||||
/* On Startup */
|
||||
"UpdateSectionCheckStartup" = "On Startup";
|
||||
|
||||
/* Daily */
|
||||
"UpdateSectionCheckDaily" = "Daily";
|
||||
|
||||
/* Manually */
|
||||
"UpdateSectionCheckManually" = "Manually";
|
143
Resources/fr.lproj/HockeySDK.strings
Executable file
@ -0,0 +1,143 @@
|
||||
/* General */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Oui";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "Non";
|
||||
|
||||
/* For dialogs ok buttons */
|
||||
"HockeyOK" = "OK";
|
||||
|
||||
|
||||
/* Crash */
|
||||
|
||||
|
||||
/* Crash dialog */
|
||||
|
||||
/* Title showing in the alert box when crash report data has been found */
|
||||
"CrashDataFoundTitle" = "Rapport de plantage";
|
||||
|
||||
/* Description explaining that crash data has been found and ask the user if the data might be uploaded to the developers server */
|
||||
"CrashDataFoundDescription" = "%@ s’est fermé de façon inattendue. Souhaitez-vous envoyer un rapport d’incident anonyme pour nous aider à corriger le problème ?";
|
||||
|
||||
/* Alert box button if the users wants to send crash data always automatically */
|
||||
"CrashSendReportAlways" = "Toujours";
|
||||
|
||||
/* Alert box button to send the crash report once */
|
||||
"CrashSendReport" = "Oui";
|
||||
|
||||
/* Alert box button to decline sending the report */
|
||||
"CrashDontSendReport" = "Non";
|
||||
|
||||
/* Text showing in a processing box that the crash data is being uploaded to the server */
|
||||
"CrashReportSending" = "Envoyer…";
|
||||
|
||||
|
||||
/* Crash status dialog */
|
||||
|
||||
/* Title for the alertview giving feedback about the crash */
|
||||
"CrashResponseTitle" = "Précédemment dans %@";
|
||||
|
||||
/* Full text telling the bug is fixed and will be available in the next release */
|
||||
"CrashResponseNextRelease" = "%@ s’est fermé de façon inattendue. La bonne nouvelle ? La cause du problème a été détectée et une solution a été trouvée pour les versions ultérieures. Restez à l’écoute.";
|
||||
|
||||
/* Full text telling the bug is fixed and the new release is waiting at Apple */
|
||||
"CrashResponseWaitingApple" = "%@ s’est fermé de façon inattendue. La bonne nouvelle ? Nous avons déjà corrigé le problème et soumis une mise à jour à Apple. Veuillez patienter durant l’examen de cette mise à jour !";
|
||||
|
||||
/* Full text telling the bug is fixed and an update is available in the AppStore */
|
||||
"CrashResponseAvailable" = "%@ s’est fermé de façon inattendue. La bonne nouvelle ? Nous avons déjà réglé le problème ! Veuillez installer la mise à jour la plus récente.";
|
||||
|
||||
|
||||
/* Update */
|
||||
|
||||
|
||||
/* Update Alert view */
|
||||
|
||||
/* Update available */
|
||||
"UpdateAvailable" = "Update available";
|
||||
|
||||
"UpdateAlertTextWithAppVersion" = "%@ is available.";
|
||||
|
||||
"UpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
|
||||
"UpdateIgnore" = "Ignore";
|
||||
|
||||
"UpdateShow" = "Show";
|
||||
|
||||
"UpdateInstall" = "Install";
|
||||
|
||||
|
||||
/* Update Details */
|
||||
|
||||
"UpdateScreenTitle" = "Update";
|
||||
|
||||
"UpdateButtonCheck" = "CHECK";
|
||||
|
||||
"UpdateButtonSearching" = "CHECKING";
|
||||
|
||||
"UpdateButtonUpdate" = "UPDATE";
|
||||
|
||||
"UpdateButtonInstalling" = "INSTALLING";
|
||||
|
||||
"UpdateButtonOffline" = "OFFLINE";
|
||||
|
||||
"UpdateInstalled" = "INSTALLED";
|
||||
|
||||
"UpdateVersion" = "Version";
|
||||
|
||||
"UpdateShowPreviousVersions" = "Show previous versions...";
|
||||
|
||||
"UpdateNoUpdateAvailableTitle" = "No Update Available";
|
||||
|
||||
"UpdateNoUpdateAvailableMessage" = "%@ is already the latest version.";
|
||||
|
||||
"UpdateError" = "Error";
|
||||
|
||||
"UpdateWarning" = "Warning";
|
||||
|
||||
"UpdateNoReleaseNotesAvailable" = "No release notes available.";
|
||||
|
||||
|
||||
/* Update Authorization */
|
||||
|
||||
"UpdateAuthorizationProgress" = "Authorizing...";
|
||||
|
||||
"UpdateAuthorizationOffline" = "Internet connection required!";
|
||||
|
||||
"UpdateAuthorizationDenied" = "Authorizing denied. Please contact the developer.";
|
||||
|
||||
|
||||
/* Update Simulator Warning */
|
||||
|
||||
"UpdateSimulatorMessage" = "Hockey Update does not work in the Simulator.\nThe itms-services:// url scheme is implemented but nonfunctional.";
|
||||
|
||||
|
||||
/* Update Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"UpdateSettingsTitle" = "Settings";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"UpdateSettingsUserData" = "Send User Data";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"UpdateSettingsUserDataDescription" = "Send User Data will send the following data to the developer: app version, language, device type and iOS version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"UpdateSettingsUsageData" = "Send Usage Data";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"UpdateSettingsUsageDataDescription" = "Send Usage Data will send the amount of test time to the developer, in a granularity of 1 minute.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"UpdateSectionCheckTitle" = "Check For Update";
|
||||
|
||||
/* On Startup */
|
||||
"UpdateSectionCheckStartup" = "On Startup";
|
||||
|
||||
/* Daily */
|
||||
"UpdateSectionCheckDaily" = "Daily";
|
||||
|
||||
/* Manually */
|
||||
"UpdateSectionCheckManually" = "Manually";
|
Before Width: | Height: | Size: 521 B After Width: | Height: | Size: 521 B |
Before Width: | Height: | Size: 911 B After Width: | Height: | Size: 911 B |
143
Resources/it.lproj/HockeySDK.strings
Executable file
@ -0,0 +1,143 @@
|
||||
/* General */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Si";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "No";
|
||||
|
||||
/* For dialogs ok buttons */
|
||||
"HockeyOK" = "OK";
|
||||
|
||||
|
||||
/* Crash */
|
||||
|
||||
|
||||
/* Crash dialog */
|
||||
|
||||
/* Title showing in the alert box when crash report data has been found */
|
||||
"CrashDataFoundTitle" = "Dati del crash trovati";
|
||||
|
||||
/* Description explaining that crash data has been found and ask the user if the data might be uplaoded to the developers server */
|
||||
"CrashDataFoundDescription" = "L'applicazione precedentemente ha avuto un crash. Vuoi inviare allo sviluppatore i dati anonimi del crash in modo che possa provare a sistemare il problema?";
|
||||
|
||||
/* Alert box button if the users wants to send crash data always automatically */
|
||||
"CrashSendReportAlways" = "Sempre";
|
||||
|
||||
/* Alert box button to send the crash report once */
|
||||
"CrashSendReport" = "Si";
|
||||
|
||||
/* Alert box button to decline sending the report */
|
||||
"CrashDontSendReport" = "No";
|
||||
|
||||
/* Text showing in a processing box that the crash data is being uploaded to the server */
|
||||
"CrashReportSending" = "Invio…";
|
||||
|
||||
|
||||
/* Crash status dialog */
|
||||
|
||||
/* Title for the alertview giving feedback about the crash */
|
||||
"CrashResponseTitle" = "Stato del bug";
|
||||
|
||||
/* Full text telling the bug is fixed and will be available in the next release */
|
||||
"CrashResponseNextRelease" = "Il bug che ha causato il tuo problema è già stato risolto e sarà incluso nella prossima versione di %@.";
|
||||
|
||||
/* Full text telling the bug is fixed and the new release is waiting at Apple */
|
||||
"CrashResponseWaitingApple" = "Il bug che ha causato il tuo problema è già stato risolto e la nuova versione di %@ è in attesa di approvazione da parte della Apple.";
|
||||
|
||||
/* Full text telling the bug is fixed and an update is available in the AppStore */
|
||||
"CrashResponseAvailable" = "Il bug che ha causato il tuo problema è già stato risolto e la nuova versione di %@ è disponibile. Ti preghiamo di effettuare un aggiornamento!";
|
||||
|
||||
|
||||
/* Update */
|
||||
|
||||
|
||||
/* Update Alert view */
|
||||
|
||||
/* Update available */
|
||||
"UpdateAvailable" = "Aggiornamento disponibile";
|
||||
|
||||
"UpdateAlertTextWithAppVersion" = "%@ è disponibile.";
|
||||
|
||||
"UpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
|
||||
"UpdateIgnore" = "Ignora";
|
||||
|
||||
"UpdateShow" = "Mostra";
|
||||
|
||||
"UpdateInstall" = "Installa";
|
||||
|
||||
|
||||
/* Update Details */
|
||||
|
||||
"UpdateScreenTitle" = "Aggiorna";
|
||||
|
||||
"UpdateButtonCheck" = "CONTROLLA";
|
||||
|
||||
"UpdateButtonSearching" = "CONTROLLO";
|
||||
|
||||
"UpdateButtonUpdate" = "AGGIORNA";
|
||||
|
||||
"UpdateButtonInstalling" = "INSTALLO";
|
||||
|
||||
"UpdateButtonOffline" = "OFFLINE";
|
||||
|
||||
"UpdateInstalled" = "INSTALLATA";
|
||||
|
||||
"UpdateVersion" = "Versione";
|
||||
|
||||
"UpdateShowPreviousVersions" = "Mostra le versioni precedenti...";
|
||||
|
||||
"UpdateNoUpdateAvailableTitle" = "Nessun aggiornamento disponibile";
|
||||
|
||||
"UpdateNoUpdateAvailableMessage" = "%@ è aggiornata all'ultima versione.";
|
||||
|
||||
"UpdateError" = "Errore";
|
||||
|
||||
"UpdateWarning" = "Avviso";
|
||||
|
||||
"UpdateNoReleaseNotesAvailable" = "Non sono disponibili note di rilascio.";
|
||||
|
||||
|
||||
/* Update Authorization */
|
||||
|
||||
"UpdateAuthorizationProgress" = "Attendo autorizzazione...";
|
||||
|
||||
"UpdateAuthorizationOffline" = "E' richiesta la connessione internet!";
|
||||
|
||||
"UpdateAuthorizationDenied" = "Autorizzazione negata, contattare lo sviluppatore.";
|
||||
|
||||
|
||||
/* Update Simulator Warning */
|
||||
|
||||
"UpdateSimulatorMessage" = "Hockey Update does not work in the Simulator.\nThe itms-services:// url scheme is implemented but nonfunctional.";
|
||||
|
||||
|
||||
/* Update Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"UpdateSettingsTitle" = "Impostazioni";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"UpdateSettingsUserData" = "Invia dati di sistema";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"UpdateSettingsUserDataDescription" = "Invia le seguenti informazioni allo sviluppatore: versione app, lingua, tipo dispositivo e versione iOS.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"UpdateSettingsUsageData" = "Invia dati di utilizzo";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"UpdateSettingsUsageDataDescription" = "Invia il tempo di utilizzo allo svilupatore, con un dettaglio di 1 minuto.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"UpdateSectionCheckTitle" = "Controlla gli aggiornamenti";
|
||||
|
||||
/* On Startup */
|
||||
"UpdateSectionCheckStartup" = "All'avvio";
|
||||
|
||||
/* Daily */
|
||||
"UpdateSectionCheckDaily" = "Ogni giorno";
|
||||
|
||||
/* Manually */
|
||||
"UpdateSectionCheckManually" = "Manualmente";
|
143
Resources/ja.lproj/HockeySDK.strings
Executable file
@ -0,0 +1,143 @@
|
||||
/* General */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Yes";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "No";
|
||||
|
||||
/* For dialogs ok buttons */
|
||||
"HockeyOK" = "保存";
|
||||
|
||||
|
||||
/* Crash */
|
||||
|
||||
|
||||
/* Crash dialog */
|
||||
|
||||
/* Title showing in the alert box when crash report data has been found */
|
||||
"CrashDataFoundTitle" = "クラッシュ時のデータを検知";
|
||||
|
||||
/* Description explaining that crash data has been found and ask the user if the data might be uplaoded to the developers server */
|
||||
"CrashDataFoundDescription" = "%@ は不正に終了しました。問題の修正のため、匿名でクラッシュレポートを送信しますか?";
|
||||
|
||||
/* Alert box button if the users wants to send crash data always automatically */
|
||||
"CrashSendReportAlways" = "いつも";
|
||||
|
||||
/* Alert box button to send the crash report once */
|
||||
"CrashSendReport" = "はい";
|
||||
|
||||
/* Alert box button to decline sending the report */
|
||||
"CrashDontSendReport" = "いいえ";
|
||||
|
||||
/* Text showing in a processing box that the crash data is being uploaded to the server */
|
||||
"CrashReportSending" = "送信中…";
|
||||
|
||||
|
||||
/* Crash status dialog */
|
||||
|
||||
/* Title for the alertview giving feedback about the crash */
|
||||
"CrashResponseTitle" = "%@、前回までは";
|
||||
|
||||
/* Full text telling the bug is fixed and will be available in the next release */
|
||||
"CrashResponseNextRelease" = "%@ は不正に終了しました。幸い、クラッシュの原因は既に特定され、将来のバージョンで修正されます。今しばらくお待ちください。";
|
||||
|
||||
/* Full text telling the bug is fixed and the new release is waiting at Apple */
|
||||
"CrashResponseWaitingApple" = "%@ は不正に終了しました。幸い、クラッシュの原因を既に修正したアップデートを Apple に提出しました。公開まで今しばらくお待ちください!";
|
||||
|
||||
/* Full text telling the bug is fixed and an update is available in the AppStore */
|
||||
"CrashResponseAvailable" = "%@ は不正に終了しました。幸い、クラッシュの原因を既に修正したアップデートが配布されています!最新版にアップデートしてください。";
|
||||
|
||||
|
||||
/* Update */
|
||||
|
||||
|
||||
/* Update Alert view */
|
||||
|
||||
/* Update available */
|
||||
"UpdateAvailable" = "Update available";
|
||||
|
||||
"UpdateAlertTextWithAppVersion" = "%@ is available.";
|
||||
|
||||
"UpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
|
||||
"UpdateIgnore" = "Ignore";
|
||||
|
||||
"UpdateShow" = "Show";
|
||||
|
||||
"UpdateInstall" = "Install";
|
||||
|
||||
|
||||
/* Update Details */
|
||||
|
||||
"UpdateScreenTitle" = "Update";
|
||||
|
||||
"UpdateButtonCheck" = "CHECK";
|
||||
|
||||
"UpdateButtonSearching" = "CHECKING";
|
||||
|
||||
"UpdateButtonUpdate" = "UPDATE";
|
||||
|
||||
"UpdateButtonInstalling" = "INSTALLING";
|
||||
|
||||
"UpdateButtonOffline" = "OFFLINE";
|
||||
|
||||
"UpdateInstalled" = "INSTALLED";
|
||||
|
||||
"UpdateVersion" = "Version";
|
||||
|
||||
"UpdateShowPreviousVersions" = "Show previous versions...";
|
||||
|
||||
"UpdateNoUpdateAvailableTitle" = "No Update Available";
|
||||
|
||||
"UpdateNoUpdateAvailableMessage" = "%@ is already the latest version.";
|
||||
|
||||
"UpdateError" = "Error";
|
||||
|
||||
"UpdateWarning" = "Warning";
|
||||
|
||||
"UpdateNoReleaseNotesAvailable" = "No release notes available.";
|
||||
|
||||
|
||||
/* Update Authorization */
|
||||
|
||||
"UpdateAuthorizationProgress" = "Authorizing...";
|
||||
|
||||
"UpdateAuthorizationOffline" = "Internet connection required!";
|
||||
|
||||
"UpdateAuthorizationDenied" = "Authorizing denied. Please contact the developer.";
|
||||
|
||||
|
||||
/* Update Simulator Warning */
|
||||
|
||||
"UpdateSimulatorMessage" = "Hockey Update does not work in the Simulator.\nThe itms-services:// url scheme is implemented but nonfunctional.";
|
||||
|
||||
|
||||
/* Update Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"UpdateSettingsTitle" = "Settings";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"UpdateSettingsUserData" = "Send User Data";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"UpdateSettingsUserDataDescription" = "Send User Data will send the following data to the developer: app version, language, device type and iOS version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"UpdateSettingsUsageData" = "Send Usage Data";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"UpdateSettingsUsageDataDescription" = "Send Usage Data will send the amount of test time to the developer, in a granularity of 1 minute.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"UpdateSectionCheckTitle" = "Check For Update";
|
||||
|
||||
/* On Startup */
|
||||
"UpdateSectionCheckStartup" = "On Startup";
|
||||
|
||||
/* Daily */
|
||||
"UpdateSectionCheckDaily" = "Daily";
|
||||
|
||||
/* Manually */
|
||||
"UpdateSectionCheckManually" = "Manually";
|
143
Resources/nl.lproj/HockeySDK.strings
Executable file
@ -0,0 +1,143 @@
|
||||
/* General */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Ja";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "Nee";
|
||||
|
||||
/* For dialogs ok buttons */
|
||||
"HockeyOK" = "OK";
|
||||
|
||||
|
||||
/* Crash */
|
||||
|
||||
|
||||
/* Crash dialog */
|
||||
|
||||
/* Title showing in the alert box when crash report data has been found */
|
||||
"CrashDataFoundTitle" = "Crashdata gevonden";
|
||||
|
||||
/* Description explaining that crash data has been found and ask the user if the data might be uplaoded to the developers server */
|
||||
"CrashDataFoundDescription" = "De applicatie is gecrasht. Wilt u de ontwikkelaars anonieme data sturen zodat zij kunnen proberen de problemen op te lossen?";
|
||||
|
||||
/* Alert box button if the users wants to send crash data always automatically */
|
||||
"CrashSendReportAlways" = "Altijd";
|
||||
|
||||
/* Alert box button to send the crash report once */
|
||||
"CrashSendReport" = "Ja";
|
||||
|
||||
/* Alert box button to decline sending the report */
|
||||
"CrashDontSendReport" = "Nee";
|
||||
|
||||
/* Text showing in a processing box that the crash data is being uploaded to the server */
|
||||
"CrashReportSending" = "Zenden…";
|
||||
|
||||
|
||||
/* Crash status dialog */
|
||||
|
||||
/* Title for the alertview giving feedback about the crash */
|
||||
"CrashResponseTitle" = "Bugstatus";
|
||||
|
||||
/* Full text telling the bug is fixed and will be available in the next release */
|
||||
"CrashResponseNextRelease" = "De bug die uw probleem heeft veroorzaakt is reeds opgelost en de oplossing zal in een volgende versie van %@ worden toegevoegd.";
|
||||
|
||||
/* Full text telling the bug is fixed and the new release is waiting at Apple */
|
||||
"CrashResponseWaitingApple" = "De bug die uw probleem heeft veroorzaakt is reeds opgelost en een nieuwe versie %@ wacht op goedkeuring door Apple.";
|
||||
|
||||
/* Full text telling the bug is fixed and an update is available in the AppStore */
|
||||
"CrashResponseAvailable" = "De bug die uw probleem heeft veroorzaakt is reeds opgelost en een nieuwe versie van %@ is beschikbaar. Update a.u.b.!";
|
||||
|
||||
|
||||
/* Update */
|
||||
|
||||
|
||||
/* Update Alert view */
|
||||
|
||||
/* Update available */
|
||||
"UpdateAvailable" = "Update available";
|
||||
|
||||
"UpdateAlertTextWithAppVersion" = "%@ is available.";
|
||||
|
||||
"UpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
|
||||
"UpdateIgnore" = "Ignore";
|
||||
|
||||
"UpdateShow" = "Show";
|
||||
|
||||
"UpdateInstall" = "Install";
|
||||
|
||||
|
||||
/* Update Details */
|
||||
|
||||
"UpdateScreenTitle" = "Update";
|
||||
|
||||
"UpdateButtonCheck" = "CHECK";
|
||||
|
||||
"UpdateButtonSearching" = "CHECKING";
|
||||
|
||||
"UpdateButtonUpdate" = "UPDATE";
|
||||
|
||||
"UpdateButtonInstalling" = "INSTALLING";
|
||||
|
||||
"UpdateButtonOffline" = "OFFLINE";
|
||||
|
||||
"UpdateInstalled" = "INSTALLED";
|
||||
|
||||
"UpdateVersion" = "Version";
|
||||
|
||||
"UpdateShowPreviousVersions" = "Show previous versions...";
|
||||
|
||||
"UpdateNoUpdateAvailableTitle" = "No Update Available";
|
||||
|
||||
"UpdateNoUpdateAvailableMessage" = "%@ is already the latest version.";
|
||||
|
||||
"UpdateError" = "Error";
|
||||
|
||||
"UpdateWarning" = "Warning";
|
||||
|
||||
"UpdateNoReleaseNotesAvailable" = "No release notes available.";
|
||||
|
||||
|
||||
/* Update Authorization */
|
||||
|
||||
"UpdateAuthorizationProgress" = "Authorizing...";
|
||||
|
||||
"UpdateAuthorizationOffline" = "Internet connection required!";
|
||||
|
||||
"UpdateAuthorizationDenied" = "Authorizing denied. Please contact the developer.";
|
||||
|
||||
|
||||
/* Update Simulator Warning */
|
||||
|
||||
"UpdateSimulatorMessage" = "Hockey Update does not work in the Simulator.\nThe itms-services:// url scheme is implemented but nonfunctional.";
|
||||
|
||||
|
||||
/* Update Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"UpdateSettingsTitle" = "Settings";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"UpdateSettingsUserData" = "Send User Data";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"UpdateSettingsUserDataDescription" = "Send User Data will send the following data to the developer: app version, language, device type and iOS version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"UpdateSettingsUsageData" = "Send Usage Data";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"UpdateSettingsUsageDataDescription" = "Send Usage Data will send the amount of test time to the developer, in a granularity of 1 minute.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"UpdateSectionCheckTitle" = "Check For Update";
|
||||
|
||||
/* On Startup */
|
||||
"UpdateSectionCheckStartup" = "On Startup";
|
||||
|
||||
/* Daily */
|
||||
"UpdateSectionCheckDaily" = "Daily";
|
||||
|
||||
/* Manually */
|
||||
"UpdateSectionCheckManually" = "Manually";
|
143
Resources/pt-PT.lproj/HockeySDK.strings
Executable file
@ -0,0 +1,143 @@
|
||||
/* General */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Sim";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "Não";
|
||||
|
||||
/* For dialogs ok buttons */
|
||||
"HockeyOK" = "OK";
|
||||
|
||||
|
||||
/* Crash */
|
||||
|
||||
|
||||
/* Crash dialog */
|
||||
|
||||
/* Title showing in the alert box when crash report data has been found */
|
||||
"CrashDataFoundTitle" = "Informação de falha encontrada";
|
||||
|
||||
/* Description explaining that crash data has been found and ask the user if the data might be uplaoded to the developers server */
|
||||
"CrashDataFoundDescription" = "A aplicação falhou anteriormente. Gostaria de enviar informação anónima ao programador acerca da falha de forma a poderem resolver o problema?";
|
||||
|
||||
/* Alert box button if the users wants to send crash data always automatically */
|
||||
"CrashSendReportAlways" = "Sempre";
|
||||
|
||||
/* Alert box button to send the crash report once */
|
||||
"CrashSendReport" = "Sim";
|
||||
|
||||
/* Alert box button to decline sending the report */
|
||||
"CrashDontSendReport" = "Não";
|
||||
|
||||
/* Text showing in a processing box that the crash data is being uploaded to the server */
|
||||
"CrashReportSending" = "Enviando…";
|
||||
|
||||
|
||||
/* Crash status dialog */
|
||||
|
||||
/* Title for the alertview giving feedback about the crash */
|
||||
"CrashResponseTitle" = "Estado do bug";
|
||||
|
||||
/* Full text telling the bug is fixed and will be available in the next release */
|
||||
"CrashResponseNextRelease" = "O bug que causou o problema já se encontra resolvido e a solução será incluída na próxima versão do %@.";
|
||||
|
||||
/* Full text telling the bug is fixed and the new release is waiting at Apple */
|
||||
"CrashResponseWaitingApple" = "O bug que causou o problema já se encontra resolvido e a nova versão do %@ está aguardando aprovação da Apple.";
|
||||
|
||||
/* Full text telling the bug is fixed and an update is available in the AppStore */
|
||||
"CrashResponseAvailable" = "O bug que causou o problema já se encontra resolvido e a nova versão do %@ está disponível. Por favor actualize!";
|
||||
|
||||
|
||||
/* Update */
|
||||
|
||||
|
||||
/* Update Alert view */
|
||||
|
||||
/* Update available */
|
||||
"UpdateAvailable" = "Update available";
|
||||
|
||||
"UpdateAlertTextWithAppVersion" = "%@ is available.";
|
||||
|
||||
"UpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
|
||||
"UpdateIgnore" = "Ignore";
|
||||
|
||||
"UpdateShow" = "Show";
|
||||
|
||||
"UpdateInstall" = "Install";
|
||||
|
||||
|
||||
/* Update Details */
|
||||
|
||||
"UpdateScreenTitle" = "Update";
|
||||
|
||||
"UpdateButtonCheck" = "CHECK";
|
||||
|
||||
"UpdateButtonSearching" = "CHECKING";
|
||||
|
||||
"UpdateButtonUpdate" = "UPDATE";
|
||||
|
||||
"UpdateButtonInstalling" = "INSTALLING";
|
||||
|
||||
"UpdateButtonOffline" = "OFFLINE";
|
||||
|
||||
"UpdateInstalled" = "INSTALLED";
|
||||
|
||||
"UpdateVersion" = "Version";
|
||||
|
||||
"UpdateShowPreviousVersions" = "Show previous versions...";
|
||||
|
||||
"UpdateNoUpdateAvailableTitle" = "No Update Available";
|
||||
|
||||
"UpdateNoUpdateAvailableMessage" = "%@ is already the latest version.";
|
||||
|
||||
"UpdateError" = "Error";
|
||||
|
||||
"UpdateWarning" = "Warning";
|
||||
|
||||
"UpdateNoReleaseNotesAvailable" = "No release notes available.";
|
||||
|
||||
|
||||
/* Update Authorization */
|
||||
|
||||
"UpdateAuthorizationProgress" = "Authorizing...";
|
||||
|
||||
"UpdateAuthorizationOffline" = "Internet connection required!";
|
||||
|
||||
"UpdateAuthorizationDenied" = "Authorizing denied. Please contact the developer.";
|
||||
|
||||
|
||||
/* Update Simulator Warning */
|
||||
|
||||
"UpdateSimulatorMessage" = "Hockey Update does not work in the Simulator.\nThe itms-services:// url scheme is implemented but nonfunctional.";
|
||||
|
||||
|
||||
/* Update Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"UpdateSettingsTitle" = "Settings";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"UpdateSettingsUserData" = "Send User Data";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"UpdateSettingsUserDataDescription" = "Send User Data will send the following data to the developer: app version, language, device type and iOS version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"UpdateSettingsUsageData" = "Send Usage Data";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"UpdateSettingsUsageDataDescription" = "Send Usage Data will send the amount of test time to the developer, in a granularity of 1 minute.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"UpdateSectionCheckTitle" = "Check For Update";
|
||||
|
||||
/* On Startup */
|
||||
"UpdateSectionCheckStartup" = "On Startup";
|
||||
|
||||
/* Daily */
|
||||
"UpdateSectionCheckDaily" = "Daily";
|
||||
|
||||
/* Manually */
|
||||
"UpdateSectionCheckManually" = "Manually";
|
143
Resources/pt.lproj/HockeySDK.strings
Executable file
@ -0,0 +1,143 @@
|
||||
/* General */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Sim";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "Não";
|
||||
|
||||
/* For dialogs ok buttons */
|
||||
"HockeyOK" = "OK";
|
||||
|
||||
|
||||
/* Crash */
|
||||
|
||||
|
||||
/* Crash dialog */
|
||||
|
||||
/* Title showing in the alert box when crash report data has been found */
|
||||
"CrashDataFoundTitle" = "Dados de falha encontrados";
|
||||
|
||||
/* Description explaining that crash data has been found and ask the user if the data might be uplaoded to the developers server */
|
||||
"CrashDataFoundDescription" = "O aplicativo falhou anteriormente. Você gostaria de enviar ao desenvolvedor os dados sobre a falha do sistema, para que ele resolva o problema?";
|
||||
|
||||
/* Alert box button if the users wants to send crash data always automatically */
|
||||
"CrashSendReportAlways" = "Sempre";
|
||||
|
||||
/* Alert box button to send the crash report once */
|
||||
"CrashSendReport" = "Sim";
|
||||
|
||||
/* Alert box button to decline sending the report */
|
||||
"CrashDontSendReport" = "Não";
|
||||
|
||||
/* Text showing in a processing box that the crash data is being uploaded to the server */
|
||||
"CrashReportSending" = "Enviando…";
|
||||
|
||||
|
||||
/* Crash status dialog */
|
||||
|
||||
/* Title for the alertview giving feedback about the crash */
|
||||
"CrashResponseTitle" = "Status do bug";
|
||||
|
||||
/* Full text telling the bug is fixed and will be available in the next release */
|
||||
"CrashResponseNextRelease" = "O bug que causou o problema já está resolvido e a solução será incluída na próxima versão do %@.";
|
||||
|
||||
/* Full text telling the bug is fixed and the new release is waiting at Apple */
|
||||
"CrashResponseWaitingApple" = "O bug que causou o problema já está resolvido e uma nova versão do %@ está aguardando aprovação da Apple.";
|
||||
|
||||
/* Full text telling the bug is fixed and an update is available in the AppStore */
|
||||
"CrashResponseAvailable" = "O bug que causou o problema já está resolvido e uma nova versão do %@ está disponível. Por favor, atualize!";
|
||||
|
||||
|
||||
/* Update */
|
||||
|
||||
|
||||
/* Update Alert view */
|
||||
|
||||
/* Update available */
|
||||
"UpdateAvailable" = "Update available";
|
||||
|
||||
"UpdateAlertTextWithAppVersion" = "%@ is available.";
|
||||
|
||||
"UpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
|
||||
"UpdateIgnore" = "Ignore";
|
||||
|
||||
"UpdateShow" = "Show";
|
||||
|
||||
"UpdateInstall" = "Install";
|
||||
|
||||
|
||||
/* Update Details */
|
||||
|
||||
"UpdateScreenTitle" = "Update";
|
||||
|
||||
"UpdateButtonCheck" = "CHECK";
|
||||
|
||||
"UpdateButtonSearching" = "CHECKING";
|
||||
|
||||
"UpdateButtonUpdate" = "UPDATE";
|
||||
|
||||
"UpdateButtonInstalling" = "INSTALLING";
|
||||
|
||||
"UpdateButtonOffline" = "OFFLINE";
|
||||
|
||||
"UpdateInstalled" = "INSTALLED";
|
||||
|
||||
"UpdateVersion" = "Version";
|
||||
|
||||
"UpdateShowPreviousVersions" = "Show previous versions...";
|
||||
|
||||
"UpdateNoUpdateAvailableTitle" = "No Update Available";
|
||||
|
||||
"UpdateNoUpdateAvailableMessage" = "%@ is already the latest version.";
|
||||
|
||||
"UpdateError" = "Error";
|
||||
|
||||
"UpdateWarning" = "Warning";
|
||||
|
||||
"UpdateNoReleaseNotesAvailable" = "No release notes available.";
|
||||
|
||||
|
||||
/* Update Authorization */
|
||||
|
||||
"UpdateAuthorizationProgress" = "Authorizing...";
|
||||
|
||||
"UpdateAuthorizationOffline" = "Internet connection required!";
|
||||
|
||||
"UpdateAuthorizationDenied" = "Authorizing denied. Please contact the developer.";
|
||||
|
||||
|
||||
/* Update Simulator Warning */
|
||||
|
||||
"UpdateSimulatorMessage" = "Hockey Update does not work in the Simulator.\nThe itms-services:// url scheme is implemented but nonfunctional.";
|
||||
|
||||
|
||||
/* Update Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"UpdateSettingsTitle" = "Settings";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"UpdateSettingsUserData" = "Send User Data";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"UpdateSettingsUserDataDescription" = "Send User Data will send the following data to the developer: app version, language, device type and iOS version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"UpdateSettingsUsageData" = "Send Usage Data";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"UpdateSettingsUsageDataDescription" = "Send Usage Data will send the amount of test time to the developer, in a granularity of 1 minute.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"UpdateSectionCheckTitle" = "Check For Update";
|
||||
|
||||
/* On Startup */
|
||||
"UpdateSectionCheckStartup" = "On Startup";
|
||||
|
||||
/* Daily */
|
||||
"UpdateSectionCheckDaily" = "Daily";
|
||||
|
||||
/* Manually */
|
||||
"UpdateSectionCheckManually" = "Manually";
|
140
Resources/ru.lproj/HockeySDK.strings
Executable file
@ -0,0 +1,140 @@
|
||||
/* General */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Да";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "Нет";
|
||||
|
||||
/* For dialogs ok buttons */
|
||||
"HockeyOK" = "OK";
|
||||
|
||||
|
||||
/* Crash */
|
||||
|
||||
|
||||
/* Crash dialog */
|
||||
|
||||
/* Title showing in the alert box when crash report data has been found */
|
||||
"CrashDataFoundTitle" = "Обнаружена проблема";
|
||||
|
||||
/* Description explaining that crash data has been found and ask the user if the data might be uplaoded to the developers server */
|
||||
"CrashDataFoundDescription" = "%@ программа неожиданно завершена. Хотите ли Вы отправить нам анонимное сообщение о неполадках, чтобы мы могли устранить проблему?";
|
||||
|
||||
/* Alert box button if the users wants to send crash data always automatically */
|
||||
"Always" = "Всегда";
|
||||
|
||||
/* Alert box button to send the crash report once */
|
||||
"Send Report" = "Да";
|
||||
|
||||
/* Alert box button to decline sending the report */
|
||||
"Don't Send" = "Нет";
|
||||
|
||||
/* Text showing in a processing box that the crash data is being uploaded to the server */
|
||||
"Sending" = "Отправить";
|
||||
|
||||
/* Title for the alertview giving feedback about the crash */
|
||||
"CrashResponseTitle" = "Обнаружена проблема %@";
|
||||
|
||||
/* Full text telling the bug is fixed and will be available in the next release */
|
||||
"CrashResponseNextRelease" = "%@ неожиданно завершен. Причина неполадки будет найдена и исправлена в следующем обновлении. Оставайтесь с нами.";
|
||||
|
||||
/* Full text telling the bug is fixed and the new release is waiting at Apple */
|
||||
"CrashResponseWaitingApple" = "%@ неожиданно завершен. Мы исправили ошибку и отправили обновление в Apple.";
|
||||
|
||||
/* Full text telling the bug is fixed and an update is available in the AppStore */
|
||||
"CrashResponseAvailable" = "%@ неожиданно завершен. Ошибка исправлена! Обновите программу в App Store.";
|
||||
|
||||
|
||||
/* Update */
|
||||
|
||||
|
||||
/* Update Alert view */
|
||||
|
||||
/* Update available */
|
||||
"UpdateAvailable" = "Update available";
|
||||
|
||||
"UpdateAlertTextWithAppVersion" = "%@ is available.";
|
||||
|
||||
"UpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
|
||||
"UpdateIgnore" = "Ignore";
|
||||
|
||||
"UpdateShow" = "Show";
|
||||
|
||||
"UpdateInstall" = "Install";
|
||||
|
||||
|
||||
/* Update Details */
|
||||
|
||||
"UpdateScreenTitle" = "Update";
|
||||
|
||||
"UpdateButtonCheck" = "CHECK";
|
||||
|
||||
"UpdateButtonSearching" = "CHECKING";
|
||||
|
||||
"UpdateButtonUpdate" = "UPDATE";
|
||||
|
||||
"UpdateButtonInstalling" = "INSTALLING";
|
||||
|
||||
"UpdateButtonOffline" = "OFFLINE";
|
||||
|
||||
"UpdateInstalled" = "INSTALLED";
|
||||
|
||||
"UpdateVersion" = "Version";
|
||||
|
||||
"UpdateShowPreviousVersions" = "Show previous versions...";
|
||||
|
||||
"UpdateNoUpdateAvailableTitle" = "No Update Available";
|
||||
|
||||
"UpdateNoUpdateAvailableMessage" = "%@ is already the latest version.";
|
||||
|
||||
"UpdateError" = "Error";
|
||||
|
||||
"UpdateWarning" = "Warning";
|
||||
|
||||
"UpdateNoReleaseNotesAvailable" = "No release notes available.";
|
||||
|
||||
|
||||
/* Update Authorization */
|
||||
|
||||
"UpdateAuthorizationProgress" = "Authorizing...";
|
||||
|
||||
"UpdateAuthorizationOffline" = "Internet connection required!";
|
||||
|
||||
"UpdateAuthorizationDenied" = "Authorizing denied. Please contact the developer.";
|
||||
|
||||
|
||||
/* Update Simulator Warning */
|
||||
|
||||
"UpdateSimulatorMessage" = "Hockey Update does not work in the Simulator.\nThe itms-services:// url scheme is implemented but nonfunctional.";
|
||||
|
||||
|
||||
/* Update Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"UpdateSettingsTitle" = "Settings";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"UpdateSettingsUserData" = "Send User Data";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"UpdateSettingsUserDataDescription" = "Send User Data will send the following data to the developer: app version, language, device type and iOS version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"UpdateSettingsUsageData" = "Send Usage Data";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"UpdateSettingsUsageDataDescription" = "Send Usage Data will send the amount of test time to the developer, in a granularity of 1 minute.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"UpdateSectionCheckTitle" = "Check For Update";
|
||||
|
||||
/* On Startup */
|
||||
"UpdateSectionCheckStartup" = "On Startup";
|
||||
|
||||
/* Daily */
|
||||
"UpdateSectionCheckDaily" = "Daily";
|
||||
|
||||
/* Manually */
|
||||
"UpdateSectionCheckManually" = "Manually";
|
144
Resources/sv.lproj/HockeySDK.strings
Executable file
@ -0,0 +1,144 @@
|
||||
/* General */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Ja";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "Nej";
|
||||
|
||||
/* For dialogs ok buttons */
|
||||
"HockeyOK" = "OK";
|
||||
|
||||
|
||||
/* Crash */
|
||||
|
||||
|
||||
/* Crash dialog */
|
||||
|
||||
/* Title showing in the alert box when crash report data has been found */
|
||||
"CrashDataFoundTitle" = "%@ kraschade";
|
||||
|
||||
/* Description explaining that crash data has been found and ask the user if the data might be uploaded to the developers server */
|
||||
"CrashDataFoundDescription" = "Vill du skicka en anonym kraschrapport så att vi kan lösa felet?";
|
||||
|
||||
/* Alert box button if the users wants to send crash data always automatically */
|
||||
"CrashSendReportAlways" = "Skicka alltid";
|
||||
|
||||
/* Alert box button to send the crash report once */
|
||||
"CrashSendReport" = "Skicka rapport";
|
||||
|
||||
/* Alert box button to decline sending the report */
|
||||
"CrashDontSendReport" = "Skicka inte";
|
||||
|
||||
/* Text showing in a processing box that the crash data is being uploaded to the server */
|
||||
"CrashReportSending" = "Skickar…";
|
||||
|
||||
|
||||
/* Crash status dialog */
|
||||
|
||||
/* Title for the alertview giving feedback about the crash */
|
||||
"CrashResponseTitle" = "Tidigare %@ krasch";
|
||||
|
||||
/* Full text telling the bug is fixed and will be available in the next release */
|
||||
"CrashResponseNextRelease" = "Buggen har lösts och är borttagen i nästa release som kommer snart.";
|
||||
|
||||
/* Full text telling the bug is fixed and the new release is waiting at Apple */
|
||||
"CrashResponseWaitingApple" = "Buggen har lösts, en ny version har skickats till Apple. Håll i dig medans de testar!";
|
||||
|
||||
/* Full text telling the bug is fixed and an update is available in the AppStore */
|
||||
"CrashResponseAvailable" = "Buggen har lösts. Updatera till senaste versionen i App Store.";
|
||||
|
||||
|
||||
/* Update */
|
||||
|
||||
|
||||
/* Update Alert view */
|
||||
|
||||
/* Update available */
|
||||
"UpdateAvailable" = "Uppdatering tillgänglig";
|
||||
|
||||
"UpdateAlertTextWithAppVersion" = "%@ finns.";
|
||||
|
||||
"UpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
|
||||
"UpdateIgnore" = "Ignorera";
|
||||
|
||||
"UpdateShow" = "Visa";
|
||||
|
||||
"UpdateInstall" = "Installera";
|
||||
|
||||
|
||||
/* Update Details */
|
||||
|
||||
"UpdateScreenTitle" = "Uppdatera";
|
||||
|
||||
"UpdateButtonCheck" = "FRÅGA";
|
||||
|
||||
"UpdateButtonSearching" = "FRÅGAR";
|
||||
|
||||
"UpdateButtonUpdate" = "UPPDATERA";
|
||||
|
||||
"UpdateButtonInstalling" = "INSTALLERAR";
|
||||
|
||||
"UpdateButtonOffline" = "OFFLINE";
|
||||
|
||||
"UpdateInstalled" = "INSTALLERAD";
|
||||
|
||||
"UpdateVersion" = "Version";
|
||||
|
||||
"UpdateShowPreviousVersions" = "Se tidigare versioner...";
|
||||
|
||||
"UpdateNoUpdateAvailableTitle" = "Ingen uppdatering tillgänglig";
|
||||
|
||||
"UpdateNoUpdateAvailableMessage" = "%@ är den senaste versionen.";
|
||||
|
||||
"UpdateError" = "Error";
|
||||
|
||||
"UpdateWarning" = "Varning";
|
||||
|
||||
"UpdateNoReleaseNotesAvailable" = "Inga releasenoteringar tillgängliga.";
|
||||
|
||||
|
||||
/* Update Authorization */
|
||||
|
||||
"UpdateAuthorizationProgress" = "Auktoriserar...";
|
||||
|
||||
"UpdateAuthorizationOffline" = "Internetuppkoppling krävs!";
|
||||
|
||||
"UpdateAuthorizationDenied" = "Auktoriseringen nekades. Kontakta utvecklaren.";
|
||||
|
||||
|
||||
/* Update Simulator Warning */
|
||||
|
||||
"UpdateSimulatorMessage" = "Hockey Update fungerar inte i Simulatorn.\nitms-services:// url schemat är implementerat men fungerar ej.";
|
||||
|
||||
|
||||
/* Update Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"UpdateSettingsTitle" = "Inställningar";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"UpdateSettingsUserData" = "Skicka användardata";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"UpdateSettingsUserDataDescription" = "Skicka användardata skickar följande till utvecklaren: app version, språk, enhetstyp och iOS version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"UpdateSettingsUsageData" = "Skicka användn.data";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"UpdateSettingsUsageDataDescription" = "Skicka användningsdata skickar information om hur länge appen testats (i antal minuter), till utvecklaren.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"UpdateSectionCheckTitle" = "Leta efter uppdateringar";
|
||||
|
||||
/* On Startup */
|
||||
"UpdateSectionCheckStartup" = "Vid uppstart";
|
||||
|
||||
/* Daily */
|
||||
"UpdateSectionCheckDaily" = "Dagligen";
|
||||
|
||||
/* Manually */
|
||||
"UpdateSectionCheckManually" = "Manuellt";
|
||||
|
142
Resources/tr.lproj/HockeySDK.strings
Normal file
@ -0,0 +1,142 @@
|
||||
/* General */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Evet";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "Yok";
|
||||
|
||||
/* For dialogs ok buttons */
|
||||
"HockeyOK" = "Tamam";
|
||||
|
||||
|
||||
/* Crash */
|
||||
|
||||
|
||||
/* Crash dialog */
|
||||
|
||||
/* Title showing in the alert box when crash report data has been found */
|
||||
"CrashDataFoundTitle" = "Hata raporu bulundu";
|
||||
|
||||
/* Description explaining that crash data has been found and ask the user if the data might be uplaoded to the developers server */
|
||||
"CrashDataFoundDescription" = "%@ beklenmeyen bir şekilde kapanmış. Bu hatayı gidermemizi kolaylaştırmak için anonim bir hata raporu göndermek ister misiniz?";
|
||||
|
||||
/* Alert box button if the users wants to send crash data always automatically */
|
||||
"CrashSendReportAlways" = "Her seferinde gönder!";
|
||||
|
||||
/* Alert box button to send the crash report once */
|
||||
"CrashSendReport" = "Gönder!";
|
||||
|
||||
/* Alert box button to decline sending the report */
|
||||
"CrashDontSendReport" = "Hayır";
|
||||
|
||||
/* Text showing in a processing box that the crash data is being uploaded to the server */
|
||||
"CrashReportSending" = "Gönderiliyor…";
|
||||
|
||||
|
||||
/* Crash status dialog */
|
||||
|
||||
/* Title for the alertview giving feedback about the crash */
|
||||
"CrashResponseTitle" = "Hata raporu bulundu";
|
||||
|
||||
/* Full text telling the bug is fixed and will be available in the next release */
|
||||
"CrashResponseNextRelease" = "%@ beklenmeyen bir şekilde kapanmış. Sorunun sebebi bulundu ve en kısa zamanda bir güncelleme ile giderilecek.";
|
||||
/* Full text telling the bug is fixed and the new release is waiting at Apple */
|
||||
"CrashResponseWaitingApple" = "%@ beklenmeyen bir şekilde kapanmış. Hata giderildi ve yeni sunum Apple'a gönderildi. Birkaç gün içerisinde iTunes'tan indirebilirsiniz.";
|
||||
|
||||
/* Full text telling the bug is fixed and an update is available in the AppStore */
|
||||
"CrashResponseAvailable" = "%@ beklenmeyen bir şekilde kapanmış. Bu hatayı gideren yeni sunumu iTunes'tan indirebilirsiniz.";
|
||||
|
||||
|
||||
/* Update */
|
||||
|
||||
|
||||
/* Update Alert view */
|
||||
|
||||
/* Update available */
|
||||
"UpdateAvailable" = "Update available";
|
||||
|
||||
"UpdateAlertTextWithAppVersion" = "%@ is available.";
|
||||
|
||||
"UpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
|
||||
"UpdateIgnore" = "Ignore";
|
||||
|
||||
"UpdateShow" = "Show";
|
||||
|
||||
"UpdateInstall" = "Install";
|
||||
|
||||
|
||||
/* Update Details */
|
||||
|
||||
"UpdateScreenTitle" = "Update";
|
||||
|
||||
"UpdateButtonCheck" = "CHECK";
|
||||
|
||||
"UpdateButtonSearching" = "CHECKING";
|
||||
|
||||
"UpdateButtonUpdate" = "UPDATE";
|
||||
|
||||
"UpdateButtonInstalling" = "INSTALLING";
|
||||
|
||||
"UpdateButtonOffline" = "OFFLINE";
|
||||
|
||||
"UpdateInstalled" = "INSTALLED";
|
||||
|
||||
"UpdateVersion" = "Version";
|
||||
|
||||
"UpdateShowPreviousVersions" = "Show previous versions...";
|
||||
|
||||
"UpdateNoUpdateAvailableTitle" = "No Update Available";
|
||||
|
||||
"UpdateNoUpdateAvailableMessage" = "%@ is already the latest version.";
|
||||
|
||||
"UpdateError" = "Error";
|
||||
|
||||
"UpdateWarning" = "Warning";
|
||||
|
||||
"UpdateNoReleaseNotesAvailable" = "No release notes available.";
|
||||
|
||||
|
||||
/* Update Authorization */
|
||||
|
||||
"UpdateAuthorizationProgress" = "Authorizing...";
|
||||
|
||||
"UpdateAuthorizationOffline" = "Internet connection required!";
|
||||
|
||||
"UpdateAuthorizationDenied" = "Authorizing denied. Please contact the developer.";
|
||||
|
||||
|
||||
/* Update Simulator Warning */
|
||||
|
||||
"UpdateSimulatorMessage" = "Hockey Update does not work in the Simulator.\nThe itms-services:// url scheme is implemented but nonfunctional.";
|
||||
|
||||
|
||||
/* Update Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"UpdateSettingsTitle" = "Settings";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"UpdateSettingsUserData" = "Send User Data";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"UpdateSettingsUserDataDescription" = "Send User Data will send the following data to the developer: app version, language, device type and iOS version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"UpdateSettingsUsageData" = "Send Usage Data";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"UpdateSettingsUsageDataDescription" = "Send Usage Data will send the amount of test time to the developer, in a granularity of 1 minute.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"UpdateSectionCheckTitle" = "Check For Update";
|
||||
|
||||
/* On Startup */
|
||||
"UpdateSectionCheckStartup" = "On Startup";
|
||||
|
||||
/* Daily */
|
||||
"UpdateSectionCheckDaily" = "Daily";
|
||||
|
||||
/* Manually */
|
||||
"UpdateSectionCheckManually" = "Manually";
|
143
Resources/zh_CN.lproj/HockeySDK.strings
Normal file
@ -0,0 +1,143 @@
|
||||
/* General */
|
||||
|
||||
/* For dialogs yes buttons */
|
||||
"HockeyYes" = "Yes";
|
||||
|
||||
/* For dialogs no buttons */
|
||||
"HockeyNo" = "No";
|
||||
|
||||
/* For dialogs ok buttons */
|
||||
"HockeyOK" = "确定";
|
||||
|
||||
|
||||
/* Crash */
|
||||
|
||||
|
||||
/* Crash dialog */
|
||||
|
||||
/* Title showing in the alert box when crash report data has been found */
|
||||
"CrashDataFoundTitle" = "发现崩溃数据";
|
||||
|
||||
/* Description explaining that crash data has been found and ask the user if the data might be uplaoded to the developers server */
|
||||
"CrashDataFoundDescription" = "%@ 不正常退出。您能否匿名提供崩溃记录以帮助我们解决问题?";
|
||||
|
||||
/* Alert box button if the users wants to send crash data always automatically */
|
||||
"CrashSendReportAlways" = "总是";
|
||||
|
||||
/* Alert box button to send the crash report once */
|
||||
"CrashSendReport" = "是";
|
||||
|
||||
/* Alert box button to decline sending the report */
|
||||
"CrashDontSendReport" = "否";
|
||||
|
||||
/* Text showing in a processing box that the crash data is being uploaded to the server */
|
||||
"CrashReportSending" = "发送中…";
|
||||
|
||||
|
||||
/* Crash status dialog */
|
||||
|
||||
/* Title for the alertview giving feedback about the crash */
|
||||
"CrashResponseTitle" = "之前在 %@";
|
||||
|
||||
/* Full text telling the bug is fixed and will be available in the next release */
|
||||
"CrashResponseNextRelease" = "%@ 不正常退出。好消息?造成崩溃的原因已被发现,并将在后续版本中修正。请耐心等待。";
|
||||
|
||||
/* Full text telling the bug is fixed and the new release is waiting at Apple */
|
||||
"CrashResponseWaitingApple" = "%@ 不正常。好消息?我们已经解决了这个问题,并已将新版本提交到苹果审核。请在审核期间耐心等待。";
|
||||
|
||||
/* Full text telling the bug is fixed and an update is available in the AppStore */
|
||||
"CrashResponseAvailable" = "%@ 不正常退出。好消息?我们已经解决了这个问题。请更新到最新版本。";
|
||||
|
||||
|
||||
/* Update */
|
||||
|
||||
|
||||
/* Update Alert view */
|
||||
|
||||
/* Update available */
|
||||
"UpdateAvailable" = "Update available";
|
||||
|
||||
"UpdateAlertTextWithAppVersion" = "%@ is available.";
|
||||
|
||||
"UpdateAlertMandatoryTextWithAppVersion" = "%@ is available and is a mandatory update!";
|
||||
|
||||
"UpdateIgnore" = "Ignore";
|
||||
|
||||
"UpdateShow" = "Show";
|
||||
|
||||
"UpdateInstall" = "Install";
|
||||
|
||||
|
||||
/* Update Details */
|
||||
|
||||
"UpdateScreenTitle" = "Update";
|
||||
|
||||
"UpdateButtonCheck" = "CHECK";
|
||||
|
||||
"UpdateButtonSearching" = "CHECKING";
|
||||
|
||||
"UpdateButtonUpdate" = "UPDATE";
|
||||
|
||||
"UpdateButtonInstalling" = "INSTALLING";
|
||||
|
||||
"UpdateButtonOffline" = "OFFLINE";
|
||||
|
||||
"UpdateInstalled" = "INSTALLED";
|
||||
|
||||
"UpdateVersion" = "Version";
|
||||
|
||||
"UpdateShowPreviousVersions" = "Show previous versions...";
|
||||
|
||||
"UpdateNoUpdateAvailableTitle" = "No Update Available";
|
||||
|
||||
"UpdateNoUpdateAvailableMessage" = "%@ is already the latest version.";
|
||||
|
||||
"UpdateError" = "Error";
|
||||
|
||||
"UpdateWarning" = "Warning";
|
||||
|
||||
"UpdateNoReleaseNotesAvailable" = "No release notes available.";
|
||||
|
||||
|
||||
/* Update Authorization */
|
||||
|
||||
"UpdateAuthorizationProgress" = "Authorizing...";
|
||||
|
||||
"UpdateAuthorizationOffline" = "Internet connection required!";
|
||||
|
||||
"UpdateAuthorizationDenied" = "Authorizing denied. Please contact the developer.";
|
||||
|
||||
|
||||
/* Update Simulator Warning */
|
||||
|
||||
"UpdateSimulatorMessage" = "Hockey Update does not work in the Simulator.\nThe itms-services:// url scheme is implemented but nonfunctional.";
|
||||
|
||||
|
||||
/* Update Settings */
|
||||
|
||||
/* Screen title for settings view */
|
||||
"UpdateSettingsTitle" = "Settings";
|
||||
|
||||
/* Text asking the user to send user data (on/off switch) */
|
||||
"UpdateSettingsUserData" = "Send User Data";
|
||||
|
||||
/* Description text for turning on/off sending user data */
|
||||
"UpdateSettingsUserDataDescription" = "Send User Data will send the following data to the developer: app version, language, device type and iOS version.";
|
||||
|
||||
/* Text asking the user to send usage data (on/off switch) */
|
||||
"UpdateSettingsUsageData" = "Send Usage Data";
|
||||
|
||||
/* Description text for turning on/off sending usage data */
|
||||
"UpdateSettingsUsageDataDescription" = "Send Usage Data will send the amount of test time to the developer, in a granularity of 1 minute.";
|
||||
|
||||
/* Title for defining when update checks may be made */
|
||||
"UpdateSectionCheckTitle" = "Check For Update";
|
||||
|
||||
/* On Startup */
|
||||
"UpdateSectionCheckStartup" = "On Startup";
|
||||
|
||||
/* Daily */
|
||||
"UpdateSectionCheckDaily" = "Daily";
|
||||
|
||||
/* Manually */
|
||||
"UpdateSectionCheckManually" = "Manually";
|