-
Notifications
You must be signed in to change notification settings - Fork 41
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add delegate for implementing custom prompting behavior #65
Conversation
…mailBugReporterPromptingDelegate` protocol. Also fixes a bug where the email dialog isn't shown when no log messages are included in the report. Previously, this could happen when the log stores are empty or the `emailAttachmentAdditionsDelegate` returns false for all log stores. The custom prompt adds another case of this bug by offering users the chance to filter out all log store.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dig the concept! A few comments.
Note that nits/supernits are not blocking 😉
/// The log stores that will be included as attachments on the email. | ||
@property (nonnull, nonatomic, copy) NSArray<ARKLogStore *> *logStores; | ||
|
||
/// Controls whether or not a screenshot should be attached to the email, when available. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be good to add what the default value is.
/// Controls whether or not a screenshot should be attached to the email, when available. | ||
@property (nonatomic) BOOL includesScreenshot; | ||
|
||
/// Controls whether or not a view hierarchy description should be attached to the email, when available. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
might be good to add what the default value is.
@class ARKEmailAttachment; | ||
|
||
|
||
@interface ARKEmailBugReportConfiguration : NSObject |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
triple-slash comment explaining what this object is?
Aardvark/ARKEmailBugReporter.h
Outdated
/// Called on the main thread when a bug is filed to signal that a bug report prompt should be presented to the user. | ||
/// The `completion` should be called with either an updated configuration to present the email dialog, or `nil` to signal that the prompt was cancelled. | ||
/// When the initial `configuration` has `includesScreenshot` or `includesViewHierarchyDescription` false, setting the field to true will have no effect. | ||
- (void)showBugReportingPromptForConfiguration:(nonnull ARKEmailBugReportConfiguration *)configuration completion:(nonnull ARKEmailBugReporterCustomPromptCompletionBlock)completion; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(not a blocker) any chance we can use the modern _Nonnull
syntax here rather than nonnull
?
|
||
@required | ||
|
||
/// Called on the main thread when a bug is filed to signal that a bug report prompt should be presented to the user. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👏 for calling out what thread this is called on
Aardvark/ARKEmailBugReporter.m
Outdated
|
||
dispatch_group_t logStoreRetrievalDispatchGroup = dispatch_group_create(); | ||
dispatch_group_enter(logStoreRetrievalDispatchGroup); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: technically there's no need for this outside enter
/leave
. As long as you're calling notify
after you've enter
ed all your async tasks, you're fine.
that said, I'm pretty sure the surrounding enter
/leave
is in the style of other code here, so, we're good either way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think theoretically it's better because we could change retrieveAllLogMessagesWithCompletionHandler
to be synchronous at some point and potentially inadvertently change behavior here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As long as notify
is called after current async work, and after you'd want it to be executed, any changes to sync/async behavior above shouldn't cause a change.
But yeah, the wrapper certainly makes things a bit more foolproof :)
Aardvark/ARKEmailBugReporter.m
Outdated
|
||
// Once all log messages have been retrieved, attach the data and show the compose window. | ||
dispatch_group_notify(logStoreRetrievalDispatchGroup, dispatch_get_main_queue(), ^{ | ||
NSMutableString *emailBody = [self _prefilledEmailBodyWithEmailBodyAdditions:emailBodyAdditions]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
supernit: const
here and... well... everywhere 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added it everywhere it seems relevant in this method.
if (appendToEmailBody) { | ||
[emailBody appendString:emailBodyForLogStore]; | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
supernit: whitespace
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch
Aardvark/ARKEmailBugReporter.m
Outdated
- (void)_createBugReportWithTitle:(NSString *)title; | ||
{ | ||
self.configuration.prefilledEmailSubject = title; | ||
self.completion(self.configuration); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we set completion
to nil
after this line to prevent accidentally calling it twice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a short-lived object, so I don't think there's any change in calling it twice. No harm in setting it to nil
though, so probably better to be safe.
Aardvark/ARKEmailBugReporter.m
Outdated
}]]; | ||
|
||
[alertController addAction:[UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { | ||
self.completion(nil); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should we set completion
to nil
after this line to prevent accidentally calling it twice?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... or consider the no-storage approach.
@@ -23,4 +23,17 @@ | |||
|
|||
@implementation ARKEmailBugReportConfiguration | |||
|
|||
- (instancetype)init; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nice 😄
@@ -53,6 +54,20 @@ | |||
@end | |||
|
|||
|
|||
typedef void (^ARKEmailBugReporterCustomPromptCompletionBlock)(ARKEmailBugReportConfiguration *_Nullable configuration); | |||
|
|||
@protocol ARKEmailBugReporterPromptingDelegate <NSObject> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The <NSObject>
specifier may be noise here. Not a strong opinion though since it's idiomatic.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like every other protocol in Aardvark does this, so just as well to match.
Aardvark/ARKEmailBugReporter.m
Outdated
if (configuration != nil) { | ||
[self _createBugReportWithConfiguration:configuration]; | ||
} else { | ||
// If the configuration is nil, the callee has signaled that we should not show a bug report. In the future, we can clean up any persisted state here as necessary. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In the absence of a specific to-do item, I'd omit the else
and put this comment before the if
.
Aardvark/ARKEmailBugReporter.m
Outdated
[self.mailComposeViewController setSubject:configuration.prefilledEmailSubject]; | ||
|
||
dispatch_group_t logStoreRetrievalDispatchGroup = dispatch_group_create(); | ||
dispatch_group_enter(logStoreRetrievalDispatchGroup); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be a little better to put this outside the canSendMail
check so the bug is fixed for both code paths.
Aardvark/ARKEmailBugReporter.m
Outdated
{ | ||
/* | ||
iOS 8 often fails to transfer the keyboard from a focused text field to a UIAlertView's text field. | ||
Transfer first responder to an invisble view when a debug screenshot is captured to make bug filing itself bug-free. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
invisible :-)
Aardvark/ARKEmailBugReporter.m
Outdated
|
||
- (void)showBugReportingPromptForConfiguration:(nonnull ARKEmailBugReportConfiguration *)configuration completion:(nonnull ARKEmailBugReporterCustomPromptCompletionBlock)completion { | ||
self.configuration = configuration; | ||
self.completion = completion; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might be a little tidier to not store these in properties on the object, but instead capture them in the completion blocks inside the method below (which could then just be inlined here).
Aardvark/ARKEmailBugReporter.m
Outdated
}]]; | ||
|
||
[alertController addAction:[UIAlertAction actionWithTitle:cancelButtonTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { | ||
self.completion(nil); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
... or consider the no-storage approach.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
{ | ||
self = [super init]; | ||
|
||
_prefilledEmailSubject = @""; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it may be worth having a quick comment here stating: "If any of the below default values change, remember to update the header file"
That may also be overkill. I leave it up to you.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like making behavioral changes like changing default values should imply needing to update the header docs, and if it doesn't then you don't have enough header docs. Maybe that's just optimistic thinking, but adding comments saying that things are documented feels backwards.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works for me!
/// Controls whether or not a view hierarchy description should be attached to the email, when available. Defaults to NO. | ||
@property (nonatomic, readonly) BOOL includesViewHierarchyDescription; | ||
|
||
/// Additional attachments to include on the email. Defaults to nil. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might be a little more convenient to make it nonnull
and default to an empty array?
- (void)removeScreenshot; | ||
|
||
/// Removes the view hierarchy description from the bug report, if one is included. | ||
- (void)removeViewHierarchyDescription; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a little confusing to use the word remove
when it's just going to flip a flag. This whole object represents a "configuration" of a bug report, not the actual contents. Might want to adjust comments to reflect that very clearly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would disable
be better than remove
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm "omit"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Works for me 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, exclude
might be better, since it matches includesScreenshot
Add delegate for implementing custom prompting behavior via the
ARKEmailBugReporterPromptingDelegate
protocol.Also fixes a bug where the email dialog isn't shown when no log messages are included in the report. Previously, this could happen when the log stores are empty or the
emailAttachmentAdditionsDelegate
returns false for all log stores. The custom prompt adds another case of this bug by offering users the chance to filter out all log store.