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.
 
 
 
 
 
 

164 lines
6.6 KiB

/**
* Copyright (c) 2015-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
#import "RNDatePickerManager.h"
#import <React/RCTLog.h>
#import "RCTConvert.h"
#import "DatePicker.h"
@implementation RCTConvert(UIDatePicker)
RCT_ENUM_CONVERTER(UIDatePickerMode, (@{
@"time": @(UIDatePickerModeTime),
@"date": @(UIDatePickerModeDate),
@"datetime": @(UIDatePickerModeDateAndTime),
@"countdown": @(UIDatePickerModeCountDownTimer), // not supported yet
}), UIDatePickerModeTime, integerValue)
@end
@implementation RNDatePickerManager
RCT_EXPORT_MODULE()
RCT_EXPORT_METHOD(addListener : (NSString *)eventName) {
// Keep: Required for RN built in Event Emitter Calls.
}
RCT_EXPORT_METHOD(removeListeners : (NSInteger)count) {
// Keep: Required for RN built in Event Emitter Calls.
}
- (UIView *)view
{
return [DatePicker new];
}
RCT_EXPORT_VIEW_PROPERTY(date, NSDate)
RCT_EXPORT_VIEW_PROPERTY(locale, NSLocale)
RCT_EXPORT_VIEW_PROPERTY(minimumDate, NSDate)
RCT_EXPORT_VIEW_PROPERTY(maximumDate, NSDate)
RCT_EXPORT_VIEW_PROPERTY(minuteInterval, NSInteger)
RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock)
RCT_REMAP_VIEW_PROPERTY(mode, datePickerMode, UIDatePickerMode)
RCT_REMAP_VIEW_PROPERTY(timeZoneOffsetInMinutes, timeZone, NSTimeZone)
RCT_CUSTOM_VIEW_PROPERTY(textColor, NSString, DatePicker)
{
[view setTextColorProp:[RCTConvert NSString:json]];
}
RCT_EXPORT_METHOD(openPicker:(NSDictionary *) props
onConfirm:(RCTResponseSenderBlock) onConfirm
onCancel:(RCTResponseSenderBlock) onCancel)
{
dispatch_async(dispatch_get_main_queue(), ^{
bool iPad = UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad;
UIViewController *rootViewController = [UIApplication sharedApplication].delegate.window.rootViewController;
CGRect rootBounds = rootViewController.view.bounds;
NSString * title = [RCTConvert NSString:[props objectForKey:@"title"]];
title = [title isEqualToString:@""] ? nil : title;
NSString * confirmText = [RCTConvert NSString:[props objectForKey:@"confirmText"]];
NSString * cancelText = [RCTConvert NSString:[props objectForKey:@"cancelText"]];
DatePicker* picker = [[DatePicker alloc] init];
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleActionSheet];
UIView * alertView = alertController.view;
// height
int heightPx = iPad ? (title ? 300 : 260) : (title ? 370 : 340);
NSLayoutConstraint *heigth = [NSLayoutConstraint constraintWithItem:alertView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:heightPx];
[alertView addConstraint:heigth];
CGRect bounds = picker.bounds;
// picker width
int widthPx = iPad ? 320 : alertController.view.bounds.size.width - 15;
bounds.size.width = widthPx;
// top padding
bounds.origin.y += iPad ? (title ? 20: 5) : (title ? 30 : 10);
[picker setFrame: bounds];
NSDate * _Nonnull date = [RCTConvert NSDate:[props objectForKey:@"date"]];
[picker setDate:date];
NSDate * minimumDate = [RCTConvert NSDate:[props objectForKey:@"minimumDate"]];
if(minimumDate) [picker setMinimumDate:minimumDate];
NSDate * maximumDate = [RCTConvert NSDate:[props objectForKey:@"maximumDate"]];
if(maximumDate) [picker setMaximumDate:maximumDate];
NSString * textColor = [RCTConvert NSString:[props objectForKey:@"textColor"]];
if(textColor) [picker setTextColorProp:textColor];
UIDatePickerMode mode = [RCTConvert UIDatePickerMode:[props objectForKey:@"mode"]];
[picker setDatePickerMode:mode];
NSLocale * locale = [RCTConvert NSLocale:[props objectForKey:@"locale"]];
if(locale) [picker setLocale:locale];
int minuteInterval = [RCTConvert int:[props objectForKey:@"minuteInterval"]];
[picker setMinuteInterval:minuteInterval];
NSString * timeZoneProp = [props valueForKey:@"timeZoneOffsetInMinutes"];
if(timeZoneProp){
[picker setTimeZone:[RCTConvert NSTimeZone:timeZoneProp]];
}
if(@available(iOS 13, *)) {
NSString * _Nonnull theme = [RCTConvert NSString:[props objectForKey:@"theme"]];
if ([theme isEqualToString:@"light"]) {
alertController.overrideUserInterfaceStyle = UIUserInterfaceStyleLight;
} else if ([theme isEqualToString:@"dark"]) {
alertController.overrideUserInterfaceStyle = UIUserInterfaceStyleDark;
} else {
alertController.overrideUserInterfaceStyle = UIUserInterfaceStyleUnspecified;
}
}
[alertView addSubview:picker];
UIAlertAction *confirmAction = [UIAlertAction actionWithTitle:confirmText style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) {
onConfirm(@[@{ @"timestamp": @(picker.date.timeIntervalSince1970 * 1000.0) }]);
}];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:cancelText style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) {
onCancel(@[]);
}];
[alertController addAction:cancelAction];
[alertController addAction:confirmAction];
if (@available(iOS 9.0, *)) {
alertController.preferredAction = confirmAction;
}
// ipad needs to display the picker in a popover
if (iPad) {
UIPopoverPresentationController *popPresenter = [alertController popoverPresentationController];
popPresenter.sourceRect = CGRectMake(CGRectGetMidX(rootBounds), CGRectGetMidY(rootBounds),0,0);
popPresenter.sourceView = rootViewController.view;
popPresenter.presentingViewController.preferredContentSize = CGSizeMake(widthPx, heightPx);
[popPresenter setPermittedArrowDirections: (UIPopoverArrowDirection) 0];
}
// Finding the top view controller which is neccessary to be able to show the picker from within modal
UIViewController *topViewController = rootViewController;
while (topViewController.presentedViewController){
topViewController = topViewController.presentedViewController;
}
[topViewController presentViewController:alertController animated:YES completion:nil];
});
}
@end