Skip to content

Commit d211d8c

Browse files
committed
Add support for AardvarkMailUI in SPM
1 parent 7c6dc2f commit d211d8c

9 files changed

+90
-52
lines changed

AardvarkMailUI.podspec

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ Pod::Spec.new do |s|
1010
s.swift_version = '5.0'
1111
s.ios.deployment_target = '14.0'
1212

13-
s.source_files = 'Sources/AardvarkMailUI/**/*.{h,m,swift}'
14-
s.private_header_files = 'Sources/AardvarkMailUI/**/*_Testing.h', 'Sources/AardvarkMailUI/PrivateCategories/*.h'
13+
s.source_files = 'Sources/AardvarkMailUI/**/*.{h,m}', 'Sources/AardvarkMailUISwift/**/*.swift'
14+
s.private_header_files = 'Sources/AardvarkMailUI/private/*.h'
1515

1616
s.dependency 'Aardvark', '~> 5.0'
1717
end

Package.swift

+19
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ let package = Package(
1616
.library(
1717
name: "AardvarkLoggingUI",
1818
targets: ["AardvarkLoggingUI"]
19+
),
20+
.library(
21+
name: "AardvarkMailUI",
22+
targets: ["AardvarkMailUI", "AardvarkMailUISwift"]
1923
),
2024
.library(
2125
name: "CoreAardvark",
@@ -47,6 +51,21 @@ let package = Package(
4751
.define("SWIFT_PACKAGE"),
4852
.headerSearchPath("private"),
4953
]
54+
),
55+
.target(
56+
name: "AardvarkMailUI",
57+
dependencies: ["Aardvark", "AardvarkSwift"],
58+
cSettings: [
59+
.define("SWIFT_PACKAGE"),
60+
.headerSearchPath("private"),
61+
]
62+
),
63+
.target(
64+
name: "AardvarkMailUISwift",
65+
dependencies: ["Aardvark", "AardvarkSwift", "AardvarkMailUI"],
66+
cSettings: [
67+
.define("SWIFT_PACKAGE"),
68+
]
5069
),
5170
.target(
5271
name: "CoreAardvark",

Sources/AardvarkMailUI/ARKEmailBugReporter.m

+47-49
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@
2424
#import "ARKEmailBugReportConfiguration.h"
2525
#import "ARKEmailBugReportConfiguration_Protected.h"
2626

27-
#import <Aardvark/Aardvark-Swift.h>
28-
2927
NSString *const ARKScreenshotFlashAnimationKey = @"ScreenshotFlashAnimation";
3028

3129

@@ -63,25 +61,25 @@ @implementation ARKEmailBugReporter
6361
- (instancetype)initWithEmailAddress:(NSString *)emailAddress logStore:(ARKLogStore *)logStore;
6462
{
6563
self = [super init];
66-
64+
6765
_prefilledEmailBody = [NSString stringWithFormat:@"Reproduction Steps:\n"
6866
@"1. \n"
6967
@"2. \n"
7068
@"3. \n"
7169
@"\n"
7270
@"System: %@", [[NSProcessInfo processInfo] operatingSystemVersionString]];
73-
71+
7472
_logFormatter = [ARKDefaultLogFormatter new];
7573
_numberOfRecentErrorLogsToIncludeInEmailBodyWhenAttachmentsAreAvailable = 3;
7674
_numberOfRecentErrorLogsToIncludeInEmailBodyWhenAttachmentsAreUnavailable = 15;
7775
_emailComposeWindowLevel = UIWindowLevelStatusBar + 3.0;
7876
_attachesViewHierarchyDescription = YES;
79-
77+
8078
_mutableLogStores = [NSMutableArray new];
81-
79+
8280
_bugReportRecipientEmailAddress = [emailAddress copy];
8381
[self addLogStores:@[logStore]];
84-
82+
8583
return self;
8684
}
8785

@@ -101,7 +99,7 @@ - (void)composeBugReportWithScreenshot:(BOOL)attachScreenshot;
10199
{
102100
ARKCheckCondition(self.bugReportRecipientEmailAddress.length > 0, , @"Attempting to compose a bug report without a recipient email address.");
103101
ARKCheckCondition(self.mutableLogStores.count > 0, , @"Attempting to compose a bug report without logs.");
104-
102+
105103
self.attachScreenshotToNextBugReport = attachScreenshot;
106104

107105
if (self.attachesViewHierarchyDescription) {
@@ -111,7 +109,7 @@ - (void)composeBugReportWithScreenshot:(BOOL)attachScreenshot;
111109
if (attachScreenshot && !self.screenFlashView) {
112110
// Take a screenshot.
113111
ARKLogScreenshot();
114-
112+
115113
// Flash the screen to simulate a screenshot being taken.
116114
UIWindow *keyWindow = [ARKEmailBugReporter _keyWindow];
117115
if (keyWindow == nil) {
@@ -122,13 +120,13 @@ - (void)composeBugReportWithScreenshot:(BOOL)attachScreenshot;
122120
self.screenFlashView.layer.opacity = 0.0f;
123121
self.screenFlashView.layer.backgroundColor = [[UIColor whiteColor] CGColor];
124122
[keyWindow addSubview:self.screenFlashView];
125-
123+
126124
CAKeyframeAnimation *screenFlash = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
127125
screenFlash.duration = 0.8;
128126
screenFlash.values = @[@0.0, @0.8, @1.0, @0.9, @0.8, @0.7, @0.6, @0.5, @0.4, @0.3, @0.2, @0.1, @0.0];
129127
screenFlash.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
130128
screenFlash.delegate = self;
131-
129+
132130
// Start the screen flash animation. Once this is done we'll fire up the bug reporter.
133131
[self.screenFlashView.layer addAnimation:screenFlash forKey:ARKScreenshotFlashAnimationKey];
134132
}
@@ -140,25 +138,25 @@ - (void)composeBugReportWithScreenshot:(BOOL)attachScreenshot;
140138
- (void)addLogStores:(NSArray *)logStores;
141139
{
142140
ARKCheckCondition(self.mailComposeViewController == nil, , @"Can not add a log store while a bug is being composed.");
143-
141+
144142
for (ARKLogStore *logStore in logStores) {
145143
ARKCheckCondition([logStore isKindOfClass:[ARKLogStore class]], , @"Can not add a log store of class %@", NSStringFromClass([logStore class]));
146144
if ([self.mutableLogStores containsObject:logStore]) {
147145
[self.mutableLogStores removeObject:logStore];
148146
}
149-
147+
150148
[self.mutableLogStores addObject:logStore];
151149
}
152150
}
153151

154152
- (void)removeLogStores:(NSArray *)logStores;
155153
{
156154
ARKCheckCondition(self.mailComposeViewController == nil, , @"Can not add a remove a controller while a bug is being composed.");
157-
155+
158156
for (ARKLogStore *logStore in logStores) {
159157
ARKCheckCondition([logStore isKindOfClass:[ARKLogStore class]], , @"Can not remove a log store of class %@", NSStringFromClass([logStore class]));
160158
}
161-
159+
162160
for (ARKLogStore *logStore in logStores) {
163161
[self.mutableLogStores removeObject:logStore];
164162
}
@@ -195,7 +193,7 @@ - (void)animationDidStop:(CAAnimation *)animation finished:(BOOL)finished;
195193
{
196194
[self.screenFlashView removeFromSuperview];
197195
self.screenFlashView = nil;
198-
196+
199197
[self _showBugReportPrompt];
200198
}
201199

@@ -222,7 +220,7 @@ - (UIWindow *)emailComposeWindow;
222220
_emailComposeWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
223221
_emailComposeWindow.windowLevel = self.emailComposeWindowLevel;
224222
}
225-
223+
226224
return _emailComposeWindow;
227225
}
228226

@@ -243,7 +241,7 @@ - (ARKEmailBugReportConfiguration *)_configurationWithCurrentSettings;
243241
{
244242
ARKEmailBugReportConfiguration *const configuration = [[ARKEmailBugReportConfiguration alloc] initWithScreenshot:self.attachScreenshotToNextBugReport
245243
viewHierarchyDescription:self.attachesViewHierarchyDescription];
246-
244+
247245
if (self.emailAttachmentAdditionsDelegate != nil) {
248246
NSMutableArray *const filteredLogStores = [NSMutableArray arrayWithCapacity:self.logStores.count];
249247
for (ARKLogStore *logStore in self.logStores) {
@@ -252,13 +250,13 @@ - (ARKEmailBugReportConfiguration *)_configurationWithCurrentSettings;
252250
}
253251
}
254252
configuration.logStores = filteredLogStores;
255-
253+
256254
configuration.additionalAttachments = [self.emailAttachmentAdditionsDelegate additionalEmailAttachmentsForEmailBugReporter:self] ?: @[];
257-
255+
258256
} else {
259257
configuration.logStores = [self.logStores copy];
260258
}
261-
259+
262260
return configuration;
263261
}
264262

@@ -267,10 +265,10 @@ - (void)_createBugReportWithConfiguration:(ARKEmailBugReportConfiguration *)conf
267265
NSMapTable *logStoresToLogMessagesMap = [NSMapTable new];
268266
NSMapTable *logStoresToLogMessagesAttachmentMap = [NSMapTable new];
269267
NSDictionary *emailBodyAdditions = [self.emailBodyAdditionsDelegate emailBodyAdditionsForEmailBugReporter:self];
270-
268+
271269
dispatch_group_t logStoreRetrievalDispatchGroup = dispatch_group_create();
272270
dispatch_group_enter(logStoreRetrievalDispatchGroup);
273-
271+
274272
NSArray<ARKLogStore *> *const logStores = configuration.logStores;
275273
for (ARKLogStore *logStore in logStores) {
276274
dispatch_group_enter(logStoreRetrievalDispatchGroup);
@@ -288,7 +286,7 @@ - (void)_createBugReportWithConfiguration:(ARKEmailBugReportConfiguration *)conf
288286
dispatch_group_leave(logStoreRetrievalDispatchGroup);
289287
}];
290288
}
291-
289+
292290
if ([MFMailComposeViewController canSendMail]) {
293291
self.mailComposeViewController = [MFMailComposeViewController new];
294292

@@ -358,19 +356,19 @@ - (void)_createBugReportWithConfiguration:(ARKEmailBugReportConfiguration *)conf
358356
} else {
359357
dispatch_group_notify(logStoreRetrievalDispatchGroup, dispatch_get_main_queue(), ^{
360358
NSMutableString *const emailBody = [self _prefilledEmailBodyWithEmailBodyAdditions:emailBodyAdditions];
361-
359+
362360
for (ARKLogStore *logStore in logStores) {
363361
NSArray *const logMessages = [logStoresToLogMessagesMap objectForKey:logStore];
364362
[emailBody appendFormat:@"%@\n", [self _recentErrorLogMessagesAsPlainText:logMessages count:self.numberOfRecentErrorLogsToIncludeInEmailBodyWhenAttachmentsAreUnavailable]];
365363
}
366-
364+
367365
NSURL *const composeEmailURL = [self _emailURLWithRecipients:@[self.bugReportRecipientEmailAddress] CC:@"" subject:configuration.prefilledEmailSubject body:emailBody];
368366
if (composeEmailURL != nil) {
369367
[[UIApplication sharedApplication] openURL:composeEmailURL options:@{} completionHandler:NULL];
370368
}
371369
});
372370
}
373-
371+
374372
dispatch_group_leave(logStoreRetrievalDispatchGroup);
375373
}
376374

@@ -379,26 +377,26 @@ - (void)_showEmailComposeWindow;
379377
self.previousKeyWindow = [ARKEmailBugReporter _keyWindow];
380378

381379
[self.mailComposeViewController beginAppearanceTransition:YES animated:YES];
382-
380+
383381
self.emailComposeWindow.rootViewController = self.mailComposeViewController;
384382
[self.emailComposeWindow makeKeyAndVisible];
385-
383+
386384
[self.mailComposeViewController endAppearanceTransition];
387385
}
388386

389387
- (void)_dismissEmailComposeWindow;
390388
{
391389
// Actually dismiss the mail compose view controller.
392390
[self.mailComposeViewController beginAppearanceTransition:NO animated:YES];
393-
391+
394392
[self.mailComposeViewController.view removeFromSuperview];
395393
self.emailComposeWindow.rootViewController = nil;
396394
// Manually hide the window so that UIKit stops retaining it
397395
self.emailComposeWindow.hidden = YES;
398396
self.emailComposeWindow = nil;
399-
397+
400398
[self.mailComposeViewController endAppearanceTransition];
401-
399+
402400
// Work around a bug introduced in iOS 9 where we don't get UIWindowDidBecomeKeyNotification when the mail compose view controller dismisses.
403401
[self.previousKeyWindow makeKeyAndVisible];
404402
self.previousKeyWindow = nil;
@@ -407,13 +405,13 @@ - (void)_dismissEmailComposeWindow;
407405
- (NSMutableString *)_prefilledEmailBodyWithEmailBodyAdditions:(nullable NSDictionary *)emailBodyAdditions;
408406
{
409407
NSMutableString *prefilledEmailBodyWithEmailBodyAdditions = [NSMutableString stringWithFormat:@"%@\n", self.prefilledEmailBody];
410-
408+
411409
if (emailBodyAdditions.count > 0) {
412410
for (NSString *emailBodyAdditionKey in emailBodyAdditions.allKeys) {
413411
[prefilledEmailBodyWithEmailBodyAdditions appendFormat:@"%@: %@\n", emailBodyAdditionKey, emailBodyAdditions[emailBodyAdditionKey]];
414412
}
415413
}
416-
414+
417415
// Add a newline to separate prefill email body and additions from what comes after.
418416
[prefilledEmailBodyWithEmailBodyAdditions appendString:@"\n"];
419417

@@ -427,13 +425,13 @@ - (NSString *)_recentErrorLogMessagesAsPlainText:(NSArray *)logMessages count:(N
427425
for (ARKLogMessage *log in [logMessages reverseObjectEnumerator]) {
428426
if(log.type == ARKLogTypeError) {
429427
[recentErrorLogs appendFormat:@"%@\n", log];
430-
428+
431429
if(++failuresFound >= errorLogsToInclude) {
432430
break;
433431
}
434432
}
435433
}
436-
434+
437435
if (recentErrorLogs.length > 0 ) {
438436
// Remove the final newline and create an immutable string.
439437
return [recentErrorLogs stringByReplacingCharactersInRange:NSMakeRange(recentErrorLogs.length - 1, 1) withString:@""];
@@ -446,33 +444,33 @@ - (NSURL *)_emailURLWithRecipients:(NSArray *)recipients CC:(NSString *)CCLine s
446444
{
447445
NSString *const defaultPrefix = @"mailto:";
448446
NSArray *const prefixes = @[@"inbox-gmail://co", @"sparrow://", @"googlegmail:///co", defaultPrefix];
449-
447+
450448
NSURL *URL = nil;
451449
for (NSString *prefix in prefixes) {
452450
URL = [self _emailURLWithPrefix:prefix recipients:recipients CC:CCLine subject:subjectLine body:bodyText shouldCheckCanOpenURL:YES];
453-
451+
454452
if (URL != nil) {
455453
break;
456454
}
457455
}
458-
456+
459457
ARKCheckCondition(URL != nil, [self _emailURLWithPrefix:defaultPrefix recipients:recipients CC:CCLine subject:subjectLine body:bodyText shouldCheckCanOpenURL:NO], @"iOS prevented us from querying for URLs with %@. Defaulting to %@", prefixes, defaultPrefix);
460-
458+
461459
return URL;
462460
}
463461

464462
- (NSURL *)_emailURLWithPrefix:(NSString *)prefix recipients:(NSArray *)recipients CC:(NSString *)CCLine subject:(NSString *)subjectLine body:(NSString *)bodyText shouldCheckCanOpenURL:(BOOL)shouldCheckCanOpenURL;
465463
{
466464
NSString *const recipientsEscapedString = [[recipients componentsJoinedByString:@","] stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet];
467-
465+
468466
NSString *const toArgument = (recipients.count > 0) ? [NSString stringWithFormat:@"to=%@&", recipientsEscapedString] : @"";
469467
NSString *const URLString = [NSString stringWithFormat:@"%@?%@cc=%@&subject=%@&body=%@",
470468
prefix,
471469
toArgument,
472470
[CCLine stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet],
473471
[subjectLine stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet],
474472
[bodyText stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]];
475-
473+
476474
NSURL *const URL = [NSURL URLWithString:URLString];
477475
if (shouldCheckCanOpenURL) {
478476
return [[UIApplication sharedApplication] canOpenURL:URL] ? URL : nil;
@@ -531,33 +529,33 @@ - (void)showBugReportingPromptForConfiguration:(nonnull ARKEmailBugReportConfigu
531529
Transfer first responder to an invisible view when a debug screenshot is captured to make bug filing itself bug-free.
532530
*/
533531
[self _stealFirstResponder];
534-
532+
535533
NSString * const title = NSLocalizedString(@"What Went Wrong?", @"Title text for alert asking user to describe a bug they just encountered");
536534
NSString * const message = NSLocalizedString(@"Please briefly summarize the issue you just encountered. You’ll be asked for more details later.", @"Subtitle text for alert asking user to describe a bug they just encountered");
537535
NSString * const composeReportButtonTitle = NSLocalizedString(@"Compose Report", @"Button title to compose bug report");
538536
NSString * const cancelButtonTitle = NSLocalizedString(@"Cancel", @"Button title to not compose a bug report");
539-
537+
540538
UIAlertController *const alertController = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert];
541-
539+
542540
[alertController addAction:[UIAlertAction actionWithTitle:composeReportButtonTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
543541
UITextField *textfield = [alertController.textFields firstObject];
544542
configuration.prefilledEmailSubject = textfield.text ?: @"";
545543
completion(configuration);
546544
}]];
547-
545+
548546
[alertController addAction:[UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
549547
completion(nil);
550548
}]];
551-
549+
552550
[alertController addTextFieldWithConfigurationHandler:^(UITextField *textField) {
553551
[self _configureAlertTextfield:textField];
554552
}];
555-
553+
556554
UIViewController *viewControllerToPresentAlertController = [ARKEmailBugReporter _keyWindow].rootViewController;
557555
while (viewControllerToPresentAlertController.presentedViewController != nil) {
558556
viewControllerToPresentAlertController = viewControllerToPresentAlertController.presentedViewController;
559557
}
560-
558+
561559
/*
562560
Disabling animations here to avoid potential crashes resulting from unexpected view state in UIKit
563561
*/

Sources/AardvarkMailUI/ARKEmailBugReporter.h Sources/AardvarkMailUI/include/ARKEmailBugReporter.h

+4
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
@import MessageUI;
1919
@import UIKit;
2020

21+
#if SWIFT_PACKAGE
22+
@import AardvarkSwift;
23+
#endif
24+
2125
@class ARKBugReportAttachment;
2226
@class ARKEmailBugReportConfiguration;
2327
@class ARKEmailBugReporter;

0 commit comments

Comments
 (0)