From ca08b982c3c2f905c75608c7319fd0189586d9ef Mon Sep 17 00:00:00 2001 From: Andreas Linde Date: Tue, 16 Oct 2012 01:50:21 +0200 Subject: [PATCH] Add a UIActivity subclass and the option to invoke compose view from anywhere modally --- Classes/BITFeedbackActivity.h | 18 +++++ Classes/BITFeedbackActivity.m | 79 +++++++++++++++++++ Classes/BITFeedbackComposeViewController.h | 6 ++ Classes/BITFeedbackComposeViewController.m | 73 ++++++++++++++--- ...BITFeedbackComposeViewControllerDelegate.h | 31 ++++++++ Classes/BITFeedbackManager.h | 18 ++++- Classes/BITFeedbackManager.m | 14 ++++ Classes/BITHockeyBaseManager.m | 8 +- Classes/BITHockeyBaseManagerPrivate.h | 2 +- Classes/BITHockeyBaseViewController.m | 12 +-- Classes/HockeySDK.h | 2 + Support/HockeySDK.xcodeproj/project.pbxproj | 14 +++- 12 files changed, 247 insertions(+), 30 deletions(-) create mode 100644 Classes/BITFeedbackActivity.h create mode 100644 Classes/BITFeedbackActivity.m create mode 100644 Classes/BITFeedbackComposeViewControllerDelegate.h diff --git a/Classes/BITFeedbackActivity.h b/Classes/BITFeedbackActivity.h new file mode 100644 index 0000000000..fa2289a75d --- /dev/null +++ b/Classes/BITFeedbackActivity.h @@ -0,0 +1,18 @@ +// +// BITFeedbackActivity.h +// HockeySDK +// +// Created by Andreas Linde on 15.10.12. +// +// + +#import + +#import "BITFeedbackComposeViewControllerDelegate.h" + +@interface BITFeedbackActivity : UIActivity + +@property (nonatomic, retain) UIImage *shareImage; +@property (nonatomic, retain) NSString *shareString; + +@end diff --git a/Classes/BITFeedbackActivity.m b/Classes/BITFeedbackActivity.m new file mode 100644 index 0000000000..9529aa6d14 --- /dev/null +++ b/Classes/BITFeedbackActivity.m @@ -0,0 +1,79 @@ +// +// BITFeedbackActivity.m +// HockeySDK +// +// Created by Andreas Linde on 15.10.12. +// +// + +#import "BITFeedbackActivity.h" + +#import "HockeySDKPrivate.h" +#import "HockeySDK.h" +#import "BITFeedbackManagerPrivate.h" + +@implementation BITFeedbackActivity + +- (NSString *)activityType { + return @"UIActivityTypePostToHockeySDKFeedback"; +} + +- (NSString *)activityTitle { + return @"Feedback"; +} + +- (UIImage *)activityImage { + return [UIImage imageNamed:@"instagram.png"]; +} + + +- (BOOL)canPerformWithActivityItems:(NSArray *)activityItems { + if ([BITHockeyManager sharedHockeyManager].disableFeedbackManager) return NO; + + // we can present the user data screen on top of the compose screen + // so for now only allow this if all required user data is available + BITFeedbackManager *feedbackManager = [BITHockeyManager sharedHockeyManager].feedbackManager; + if ([feedbackManager askManualUserDataAvailable] && + ([feedbackManager requireManualUserDataMissing]) + ) + return NO; + + for (UIActivityItemProvider *item in activityItems) { + if ([item isKindOfClass:[UIImage class]]) { + return YES; + } else if ([item isKindOfClass:[NSString class]]) { + return YES; + } else if ([item isKindOfClass:[NSString class]]) { + return YES; + } + } + return NO; +} + +- (void)prepareWithActivityItems:(NSArray *)activityItems { + for (id item in activityItems) { + if ([item isKindOfClass:[UIImage class]]) { + self.shareImage = item; + } else if ([item isKindOfClass:[NSString class]]) { + self.shareString = [(self.shareString ? self.shareString : @"") stringByAppendingFormat:@"%@%@",(self.shareString ? @" " : @""),item]; + } else if ([item isKindOfClass:[NSURL class]]) { + self.shareString = [(self.shareString ? self.shareString : @"") stringByAppendingFormat:@"%@%@",(self.shareString ? @" " : @""),[(NSURL *)item absoluteString]]; + } else { + BITHockeyLog(@"Unknown item type %@", item); + } + } +} + +- (UIViewController *)activityViewController { + // TODO: return compose controller with activity content added + BITFeedbackComposeViewController *composeViewController = [[BITHockeyManager sharedHockeyManager].feedbackManager feedbackComposeViewControllerWithDelegate:self]; + composeViewController.modalPresentationStyle = UIModalPresentationFormSheet; + return composeViewController; +} + +-(void)feedbackComposeViewControllerDidFinish:(BITFeedbackComposeViewController *)composeViewController { + [self activityDidFinish:YES]; +} + + +@end diff --git a/Classes/BITFeedbackComposeViewController.h b/Classes/BITFeedbackComposeViewController.h index 217db38baf..b59b623739 100644 --- a/Classes/BITFeedbackComposeViewController.h +++ b/Classes/BITFeedbackComposeViewController.h @@ -29,8 +29,14 @@ #import +#import "BITFeedbackComposeViewControllerDelegate.h" + + @interface BITFeedbackComposeViewController : UIViewController +@property (nonatomic, assign) id delegate; + - (id)init; +- (id)initWithDelegate:(id)delegate; @end \ No newline at end of file diff --git a/Classes/BITFeedbackComposeViewController.m b/Classes/BITFeedbackComposeViewController.m index 33c91f301e..0513d46998 100644 --- a/Classes/BITFeedbackComposeViewController.m +++ b/Classes/BITFeedbackComposeViewController.m @@ -57,33 +57,70 @@ if (self) { self.title = BITHockeyLocalizedString(@"HockeyFeedbackComposeTitle"); blockUserDataScreen = NO; + _delegate = nil; _manager = [BITHockeyManager sharedHockeyManager].feedbackManager; } return self; } + +- (id)initWithDelegate:(id)delegate { + self = [self init]; + if (self) { + _delegate = delegate; + } + return self; +} + + +#pragma mark - View lifecycle + - (void)viewDidLoad { [super viewDidLoad]; self.view.backgroundColor = [UIColor whiteColor]; + CGFloat yPos = 0; - // Do any additional setup after loading the view. - self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel - target:self - action:@selector(dismissAction:)] autorelease]; - - self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeSend") - style:UIBarButtonItemStyleDone - target:self - action:@selector(sendAction:)] autorelease]; + // when being used inside an activity, we don't have a navigation controller embedded + if (!self.navigationController) { + UINavigationBar *navigationBar = [[[UINavigationBar alloc] initWithFrame:CGRectMake(self.view.bounds.origin.x, self.view.bounds.origin.y, self.view.bounds.size.width, 44)] autorelease]; + navigationBar.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleBottomMargin; + [self.view addSubview:navigationBar]; + [navigationBar sizeToFit]; + yPos = navigationBar.frame.size.height; + + UIBarButtonItem *cancelItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel + target:self + action:@selector(dismissAction:)] autorelease]; + + UIBarButtonItem *saveItem = [[[UIBarButtonItem alloc] initWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeSend") + style:UIBarButtonItemStyleDone + target:self + action:@selector(sendAction:)] autorelease]; + + UINavigationItem *navigationItem = [[[UINavigationItem alloc] initWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeTitle")] autorelease]; + navigationItem.leftBarButtonItem = cancelItem; + navigationItem.rightBarButtonItem = saveItem; + [navigationBar pushNavigationItem:navigationItem animated:NO]; + } else { + // Do any additional setup after loading the view. + self.navigationItem.leftBarButtonItem = [[[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel + target:self + action:@selector(dismissAction:)] autorelease]; + + self.navigationItem.rightBarButtonItem = [[[UIBarButtonItem alloc] initWithTitle:BITHockeyLocalizedString(@"HockeyFeedbackComposeSend") + style:UIBarButtonItemStyleDone + target:self + action:@selector(sendAction:)] autorelease]; + } // message input textfield CGRect frame = CGRectZero; if (UI_USER_INTERFACE_IDIOM() != UIUserInterfaceIdiomPad) { - frame = CGRectMake(0, 0, self.view.bounds.size.width, 200); + frame = CGRectMake(0, yPos, self.view.bounds.size.width, 200-yPos); } else { - frame = CGRectMake(0, 0, self.view.bounds.size.width, self.view.bounds.size.height); + frame = CGRectMake(0, yPos, self.view.bounds.size.width, self.view.bounds.size.height-yPos); } self.textView = [[[UITextView alloc] initWithFrame:frame] autorelease]; self.textView.font = [UIFont systemFontOfSize:17]; @@ -100,6 +137,8 @@ [super viewWillAppear:animated]; self.navigationItem.rightBarButtonItem.enabled = NO; + + [[UIApplication sharedApplication] setStatusBarStyle:(self.navigationController.navigationBar.barStyle == UIBarStyleDefault) ? UIStatusBarStyleDefault : UIStatusBarStyleBlackOpaque]; } - (void)viewDidAppear:(BOOL)animated { @@ -129,6 +168,14 @@ #pragma mark - Private methods +- (void)dismiss { + if (self.delegate && [self.delegate respondsToSelector:@selector(feedbackComposeViewControllerDidFinish:)]) { + [self.delegate feedbackComposeViewControllerDidFinish:self]; + } else { + [self dismissModalViewControllerAnimated:YES]; + } +} + - (void)setUserDataAction { BITFeedbackUserDataViewController *userController = [[[BITFeedbackUserDataViewController alloc] initWithStyle:UITableViewStyleGrouped] autorelease]; userController.delegate = self; @@ -139,7 +186,7 @@ } - (void)dismissAction:(id)sender { - [self dismissModalViewControllerAnimated:YES]; + [self dismiss]; } - (void)sendAction:(id)sender { @@ -150,7 +197,7 @@ [self.manager submitMessageWithText:text]; - [self dismissModalViewControllerAnimated:YES]; + [self dismiss]; } diff --git a/Classes/BITFeedbackComposeViewControllerDelegate.h b/Classes/BITFeedbackComposeViewControllerDelegate.h new file mode 100644 index 0000000000..eebf8118ca --- /dev/null +++ b/Classes/BITFeedbackComposeViewControllerDelegate.h @@ -0,0 +1,31 @@ +// +// BITFeedbackComposeViewControllerDelegate.h +// HockeySDK +// +// Created by Andreas Linde on 15.10.12. +// +// + +#import + +@class BITFeedbackComposeViewController; + +@protocol BITFeedbackComposeViewControllerDelegate + +@optional + +///----------------------------------------------------------------------------- +/// @name View Controller Management +///----------------------------------------------------------------------------- + +/** + Invoked once the compose screen is finished via send or cancel + + If this is implemented, it's the responsibility of this method to dismiss the presented + `BITFeedbackComposeViewController` + + @param composeViewController The `BITFeedbackComposeViewController` instance invoking this delegate + */ +- (void)feedbackComposeViewControllerDidFinish:(BITFeedbackComposeViewController *)composeViewController; + +@end diff --git a/Classes/BITFeedbackManager.h b/Classes/BITFeedbackManager.h index c571cce8f1..64a73b09f9 100644 --- a/Classes/BITFeedbackManager.h +++ b/Classes/BITFeedbackManager.h @@ -72,9 +72,25 @@ typedef enum { Create an feedback list view @param modal Return a view ready for modal presentation with integrated navigation bar - @return BITFeedbackListViewController The update user interface view controller, + @return `BITFeedbackListViewController` The feedback list view controller, e.g. to push it onto a navigation stack. */ - (BITFeedbackListViewController *)feedbackListViewController:(BOOL)modal; + +/** + Present the modal feedback compose message user interface. + */ +- (void)showFeedbackComposeView; + + +/** + Create an feedback compose view + + @param modal Return a view ready for modal presentation with integrated navigation bar + @return `BITFeedbackComposeViewController` The compose feedback view controller, + e.g. to push it onto a navigation stack. + */ +- (BITFeedbackComposeViewController *)feedbackComposeViewControllerWithDelegate:(id)delegate; + @end diff --git a/Classes/BITFeedbackManager.m b/Classes/BITFeedbackManager.m index 355b0b692d..854ac8f1cd 100644 --- a/Classes/BITFeedbackManager.m +++ b/Classes/BITFeedbackManager.m @@ -177,6 +177,20 @@ } +- (BITFeedbackComposeViewController *)feedbackComposeViewControllerWithDelegate:(id)delegate { + return [[[BITFeedbackComposeViewController alloc] initWithDelegate:delegate] autorelease]; +} + +- (void)showFeedbackComposeView { + if (_currentFeedbackComposeViewController) { + BITHockeyLog(@"INFO: update view already visible, aborting"); + return; + } + + [self showView:[self feedbackComposeViewControllerWithDelegate:nil]]; +} + + #pragma mark - Manager Control - (void)startManager { diff --git a/Classes/BITHockeyBaseManager.m b/Classes/BITHockeyBaseManager.m index a1345f313b..e723099333 100644 --- a/Classes/BITHockeyBaseManager.m +++ b/Classes/BITHockeyBaseManager.m @@ -137,7 +137,7 @@ return visibleWindow; } -- (void)showView:(BITHockeyBaseViewController *)viewController { +- (void)showView:(UIViewController *)viewController { UIViewController *parentViewController = nil; if ([[BITHockeyManager sharedHockeyManager].delegate respondsToSelector:@selector(viewControllerForHockeyManager:componentManager:)]) { @@ -179,14 +179,16 @@ _navController.modalPresentationStyle = UIModalPresentationFormSheet; } - viewController.modalAnimated = YES; + if ([viewController isKindOfClass:[BITHockeyBaseViewController class]]) + [(BITHockeyBaseViewController *)viewController setModalAnimated:YES]; [parentViewController presentModalViewController:_navController animated:YES]; } else { // if not, we add a subview to the window. A bit hacky but should work in most circumstances. // Also, we don't get a nice animation for free, but hey, this is for beta not production users ;) BITHockeyLog(@"INFO: No rootViewController found, using UIWindow-approach: %@", visibleWindow); - viewController.modalAnimated = NO; + if ([viewController isKindOfClass:[BITHockeyBaseViewController class]]) + [(BITHockeyBaseViewController *)viewController setModalAnimated:NO]; [visibleWindow addSubview:_navController.view]; } } diff --git a/Classes/BITHockeyBaseManagerPrivate.h b/Classes/BITHockeyBaseManagerPrivate.h index c5028524f8..e58a3e1f0b 100644 --- a/Classes/BITHockeyBaseManagerPrivate.h +++ b/Classes/BITHockeyBaseManagerPrivate.h @@ -26,7 +26,7 @@ - (NSString *)executableUUID; - (UIWindow *)findVisibleWindow; -- (void)showView:(BITHockeyBaseViewController *)viewController; +- (void)showView:(UIViewController *)viewController; - (NSData *)appendPostValue:(NSString *)value forKey:(NSString *)key; diff --git a/Classes/BITHockeyBaseViewController.m b/Classes/BITHockeyBaseViewController.m index 98e80ccf38..b07411c8ef 100644 --- a/Classes/BITHockeyBaseViewController.m +++ b/Classes/BITHockeyBaseViewController.m @@ -50,17 +50,7 @@ - (void)onDismissModal:(id)sender { if (self.modal) { - // Note that as of 5.0, parentViewController will no longer return the presenting view controller - SEL presentingViewControllerSelector = NSSelectorFromString(@"presentingViewController"); - UIViewController *presentingViewController = nil; - if ([self respondsToSelector:presentingViewControllerSelector]) { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-performSelector-leaks" - presentingViewController = [self performSelector:presentingViewControllerSelector]; -#pragma clang diagnostic pop - } else { - presentingViewController = [self parentViewController]; - } + UIViewController *presentingViewController = [self presentingViewController]; // If there is no presenting view controller just remove view if (presentingViewController && self.modalAnimated) { diff --git a/Classes/HockeySDK.h b/Classes/HockeySDK.h index a377574bf5..a47d61f1dc 100644 --- a/Classes/HockeySDK.h +++ b/Classes/HockeySDK.h @@ -41,7 +41,9 @@ #import "BITUpdateViewController.h" #import "BITFeedbackManager.h" +#import "BITFeedbackActivity.h" #import "BITFeedbackComposeViewController.h" +#import "BITFeedbackComposeViewControllerDelegate.h" #import "BITFeedbackListViewController.h" diff --git a/Support/HockeySDK.xcodeproj/project.pbxproj b/Support/HockeySDK.xcodeproj/project.pbxproj index d28dc30fe7..8d63f2615d 100644 --- a/Support/HockeySDK.xcodeproj/project.pbxproj +++ b/Support/HockeySDK.xcodeproj/project.pbxproj @@ -34,7 +34,7 @@ /* Begin PBXBuildFile section */ 1E27EF2515BB5033000AE995 /* HockeySDK.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1E59555F15B6F80E00A03429 /* HockeySDK.strings */; }; - 1E49A43C1612223B00463151 /* BITFeedbackComposeViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A42D1612223B00463151 /* BITFeedbackComposeViewController.h */; }; + 1E49A43C1612223B00463151 /* BITFeedbackComposeViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A42D1612223B00463151 /* BITFeedbackComposeViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; 1E49A43F1612223B00463151 /* BITFeedbackComposeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A42E1612223B00463151 /* BITFeedbackComposeViewController.m */; }; 1E49A4421612223B00463151 /* BITFeedbackListViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A42F1612223B00463151 /* BITFeedbackListViewCell.h */; }; 1E49A4451612223B00463151 /* BITFeedbackListViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4301612223B00463151 /* BITFeedbackListViewCell.m */; }; @@ -93,6 +93,9 @@ 1E754E601621FBB70070AB92 /* BITCrashReportTextFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E754E5A1621FBB70070AB92 /* BITCrashReportTextFormatter.h */; }; 1E754E611621FBB70070AB92 /* BITCrashReportTextFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E754E5B1621FBB70070AB92 /* BITCrashReportTextFormatter.m */; }; 1EC69F601615001500808FD9 /* BITHockeyManagerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EC69F5D1615001500808FD9 /* BITHockeyManagerPrivate.h */; }; + 1EF95CA6162CB037000AE3AD /* BITFeedbackActivity.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF95CA4162CB036000AE3AD /* BITFeedbackActivity.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 1EF95CA7162CB037000AE3AD /* BITFeedbackActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */; }; + 1EF95CAA162CB314000AE3AD /* BITFeedbackComposeViewControllerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF95CA9162CB313000AE3AD /* BITFeedbackComposeViewControllerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -187,6 +190,9 @@ 1E754E5B1621FBB70070AB92 /* BITCrashReportTextFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITCrashReportTextFormatter.m; sourceTree = ""; }; 1EC69F5D1615001500808FD9 /* BITHockeyManagerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyManagerPrivate.h; sourceTree = ""; }; 1EDA60CF15C2C1450032D10B /* HockeySDK-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HockeySDK-Info.plist"; sourceTree = ""; }; + 1EF95CA4162CB036000AE3AD /* BITFeedbackActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackActivity.h; sourceTree = ""; }; + 1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackActivity.m; sourceTree = ""; }; + 1EF95CA9162CB313000AE3AD /* BITFeedbackComposeViewControllerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackComposeViewControllerDelegate.h; sourceTree = ""; }; E400561D148D79B500EB22B9 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; E41EB465148D7BF50015DEDC /* BITHockeyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyManager.h; sourceTree = ""; }; E41EB466148D7BF50015DEDC /* BITHockeyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITHockeyManager.m; sourceTree = ""; }; @@ -267,12 +273,15 @@ 1E49A4371612223B00463151 /* BITFeedbackMessage.m */, 1E49A42D1612223B00463151 /* BITFeedbackComposeViewController.h */, 1E49A42E1612223B00463151 /* BITFeedbackComposeViewController.m */, + 1EF95CA9162CB313000AE3AD /* BITFeedbackComposeViewControllerDelegate.h */, 1E49A4381612223B00463151 /* BITFeedbackUserDataViewController.h */, 1E49A4391612223B00463151 /* BITFeedbackUserDataViewController.m */, 1E49A42F1612223B00463151 /* BITFeedbackListViewCell.h */, 1E49A4301612223B00463151 /* BITFeedbackListViewCell.m */, 1E49A4311612223B00463151 /* BITFeedbackListViewController.h */, 1E49A4321612223B00463151 /* BITFeedbackListViewController.m */, + 1EF95CA4162CB036000AE3AD /* BITFeedbackActivity.h */, + 1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */, 1E49A4331612223B00463151 /* BITFeedbackManager.h */, 1E49A4341612223B00463151 /* BITFeedbackManager.m */, 1E49A4351612223B00463151 /* BITFeedbackManagerPrivate.h */, @@ -390,6 +399,8 @@ 1E49A4481612223B00463151 /* BITFeedbackListViewController.h in Headers */, 1E49A47F1612226D00463151 /* BITUpdateViewController.h in Headers */, 1E49A43C1612223B00463151 /* BITFeedbackComposeViewController.h in Headers */, + 1EF95CAA162CB314000AE3AD /* BITFeedbackComposeViewControllerDelegate.h in Headers */, + 1EF95CA6162CB037000AE3AD /* BITFeedbackActivity.h in Headers */, 1E49A4421612223B00463151 /* BITFeedbackListViewCell.h in Headers */, 1E49A4541612223B00463151 /* BITFeedbackManagerPrivate.h in Headers */, 1E49A4571612223B00463151 /* BITFeedbackMessage.h in Headers */, @@ -568,6 +579,7 @@ 1E49A4DB161222D400463151 /* HockeySDKPrivate.m in Sources */, 1E754E5D1621FBB70070AB92 /* BITCrashManager.m in Sources */, 1E754E611621FBB70070AB92 /* BITCrashReportTextFormatter.m in Sources */, + 1EF95CA7162CB037000AE3AD /* BITFeedbackActivity.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };