You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

208 lines
5.9 KiB

//
// FLEXAlert.m
// FLEX
//
// Created by Tanner Bennett on 8/20/19.
// Copyright © 2019 Flipboard. All rights reserved.
//
#import "FLEXAlert.h"
@interface FLEXAlert ()
@property (nonatomic, readonly) UIAlertController *_controller;
@property (nonatomic, readonly) NSMutableArray<FLEXAlertAction *> *_actions;
@end
#define FLEXAlertActionMutationAssertion() \
NSAssert(!self._action, @"Cannot mutate action after retreiving underlying UIAlertAction");
@interface FLEXAlertAction ()
@property (nonatomic) UIAlertController *_controller;
@property (nonatomic) NSString *_title;
@property (nonatomic) UIAlertActionStyle _style;
@property (nonatomic) BOOL _disable;
@property (nonatomic) void(^_handler)(UIAlertAction *action);
@property (nonatomic) UIAlertAction *_action;
@end
@implementation FLEXAlert
+ (void)showAlert:(NSString *)title message:(NSString *)message from:(UIViewController *)viewController {
[self makeAlert:^(FLEXAlert *make) {
make.title(title).message(message).button(@"Dismiss").cancelStyle();
} showFrom:viewController];
}
#pragma mark Initialization
- (instancetype)initWithController:(UIAlertController *)controller {
self = [super init];
if (self) {
__controller = controller;
__actions = [NSMutableArray new];
}
return self;
}
+ (UIAlertController *)make:(FLEXAlertBuilder)block withStyle:(UIAlertControllerStyle)style {
// Create alert builder
FLEXAlert *alert = [[self alloc] initWithController:
[UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:style]
];
// Configure alert
block(alert);
// Add actions
for (FLEXAlertAction *builder in alert._actions) {
[alert._controller addAction:builder.action];
}
return alert._controller;
}
+ (void)make:(FLEXAlertBuilder)block withStyle:(UIAlertControllerStyle)style showFrom:(UIViewController *)viewController {
UIAlertController *alert = [self make:block withStyle:style];
[viewController presentViewController:alert animated:YES completion:nil];
}
+ (void)makeAlert:(FLEXAlertBuilder)block showFrom:(UIViewController *)viewController {
[self make:block withStyle:UIAlertControllerStyleAlert showFrom:viewController];
}
+ (void)makeSheet:(FLEXAlertBuilder)block showFrom:(UIViewController *)viewController {
[self make:block withStyle:UIAlertControllerStyleActionSheet showFrom:viewController];
}
+ (UIAlertController *)makeAlert:(FLEXAlertBuilder)block {
return [self make:block withStyle:UIAlertControllerStyleAlert];
}
+ (UIAlertController *)makeSheet:(FLEXAlertBuilder)block {
return [self make:block withStyle:UIAlertControllerStyleActionSheet];
}
#pragma mark Configuration
- (FLEXAlertStringProperty)title {
return ^FLEXAlert *(NSString *title) {
if (self._controller.title) {
self._controller.title = [self._controller.title stringByAppendingString:title];
} else {
self._controller.title = title;
}
return self;
};
}
- (FLEXAlertStringProperty)message {
return ^FLEXAlert *(NSString *message) {
if (self._controller.message) {
self._controller.message = [self._controller.message stringByAppendingString:message];
} else {
self._controller.message = message;
}
return self;
};
}
- (FLEXAlertAddAction)button {
return ^FLEXAlertAction *(NSString *title) {
FLEXAlertAction *action = FLEXAlertAction.new.title(title);
action._controller = self._controller;
[self._actions addObject:action];
return action;
};
}
- (FLEXAlertStringArg)textField {
return ^FLEXAlert *(NSString *placeholder) {
[self._controller addTextFieldWithConfigurationHandler:^(UITextField *textField) {
textField.placeholder = placeholder;
}];
return self;
};
}
- (FLEXAlertTextField)configuredTextField {
return ^FLEXAlert *(void(^configurationHandler)(UITextField *)) {
[self._controller addTextFieldWithConfigurationHandler:configurationHandler];
return self;
};
}
@end
@implementation FLEXAlertAction
- (FLEXAlertActionStringProperty)title {
return ^FLEXAlertAction *(NSString *title) {
FLEXAlertActionMutationAssertion();
if (self._title) {
self._title = [self._title stringByAppendingString:title];
} else {
self._title = title;
}
return self;
};
}
- (FLEXAlertActionProperty)destructiveStyle {
return ^FLEXAlertAction *() {
FLEXAlertActionMutationAssertion();
self._style = UIAlertActionStyleDestructive;
return self;
};
}
- (FLEXAlertActionProperty)cancelStyle {
return ^FLEXAlertAction *() {
FLEXAlertActionMutationAssertion();
self._style = UIAlertActionStyleCancel;
return self;
};
}
- (FLEXAlertActionBOOLProperty)enabled {
return ^FLEXAlertAction *(BOOL enabled) {
FLEXAlertActionMutationAssertion();
self._disable = !enabled;
return self;
};
}
- (FLEXAlertActionHandler)handler {
return ^FLEXAlertAction *(void(^handler)(NSArray<NSString *> *)) {
FLEXAlertActionMutationAssertion();
// Get weak reference to the alert to avoid block <--> alert retain cycle
__weak __typeof(self._controller) weakController = self._controller;
self._handler = ^(UIAlertAction *action) {
// Strongify that reference and pass the text field strings to the handler
__strong __typeof(weakController) controller = weakController;
NSArray *strings = [controller.textFields valueForKeyPath:@"text"];
handler(strings);
};
return self;
};
}
- (UIAlertAction *)action {
if (self._action) {
return self._action;
}
self._action = [UIAlertAction
actionWithTitle:self._title
style:self._style
handler:self._handler
];
self._action.enabled = !self._disable;
return self._action;
}
@end