1/**
2 * Copyright (c) Facebook, Inc. and its affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#import "RNDateTimePickerManager.h"
9#import "RNDateTimePickerShadowView.h"
10
11#import <React/RCTBridge.h>
12#import <React/RCTEventDispatcher.h>
13#import "RNDateTimePicker.h"
14#import <React/UIView+React.h>
15
16#ifndef __IPHONE_15_0
17@interface UIColor (Xcode12)
18+ (instancetype) tintColor;
19@end
20#endif
21
22@implementation RCTConvert(UIDatePicker)
23
24RCT_ENUM_CONVERTER(UIDatePickerMode, (@{
25  @"time": @(UIDatePickerModeTime),
26  @"date": @(UIDatePickerModeDate),
27  @"datetime": @(UIDatePickerModeDateAndTime),
28}), UIDatePickerModeTime, integerValue)
29
30
31#pragma clang diagnostic push
32#pragma clang diagnostic ignored "-Wunguarded-availability-new"
33#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
34
35typedef UIDatePickerStyle RNCUIDatePickerStyle;
36
37// using UIDatePickerStyle directly conflicts with RN implementation
38RCT_ENUM_CONVERTER(RNCUIDatePickerStyle, (@{
39    @"default": @(UIDatePickerStyleAutomatic),
40    @"compact": @(UIDatePickerStyleCompact),
41    @"spinner": @(UIDatePickerStyleWheels),
42    @"inline": @(UIDatePickerStyleInline),
43}), UIDatePickerStyleAutomatic, integerValue)
44
45
46RCT_ENUM_CONVERTER(UIUserInterfaceStyle, (@{
47    @"dark": @(UIUserInterfaceStyleDark),
48    @"light": @(UIUserInterfaceStyleLight),
49}), UIUserInterfaceStyleUnspecified, integerValue)
50
51#endif
52#pragma clang diagnostic pop
53
54
55@end
56
57@implementation RNDateTimePickerManager {
58  RNDateTimePicker* _picker;
59}
60
61RCT_EXPORT_MODULE()
62
63- (instancetype)init {
64  if (self = [super init]) {
65    _picker = [RNDateTimePicker new];
66  }
67  return self;
68}
69
70+ (BOOL)requiresMainQueueSetup {
71  return true;
72}
73
74- (UIView *)view
75{
76  return [RNDateTimePicker new];
77}
78
79- (RCTShadowView *)shadowView
80{
81  RNDateTimePickerShadowView* shadowView =  [RNDateTimePickerShadowView new];
82  shadowView.picker = _picker;
83  return shadowView;
84}
85
86+ (NSString*) datepickerStyleToString: (UIDatePickerStyle) style  API_AVAILABLE(ios(13.4)){
87    // RCTConvert does not handle this.?
88    switch (style) {
89        case UIDatePickerStyleCompact:
90            return @"compact";
91        case UIDatePickerStyleWheels:
92            return @"spinner";
93#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_14_0
94        case UIDatePickerStyleInline:
95            return @"inline";
96#endif
97        default:
98            [NSException raise:@"Unsupported style value" format:@"UIDatePickerStyle of %ld is unsupported", (long)style];
99            return @"";
100    }
101}
102
103RCT_EXPORT_SHADOW_PROPERTY(date, NSDate)
104RCT_EXPORT_SHADOW_PROPERTY(mode, UIDatePickerMode)
105RCT_EXPORT_SHADOW_PROPERTY(locale, NSLocale)
106RCT_EXPORT_SHADOW_PROPERTY(displayIOS, RNCUIDatePickerStyle)
107
108RCT_EXPORT_VIEW_PROPERTY(date, NSDate)
109RCT_EXPORT_VIEW_PROPERTY(locale, NSLocale)
110RCT_EXPORT_VIEW_PROPERTY(minimumDate, NSDate)
111RCT_EXPORT_VIEW_PROPERTY(maximumDate, NSDate)
112RCT_EXPORT_VIEW_PROPERTY(minuteInterval, NSInteger)
113RCT_EXPORT_VIEW_PROPERTY(enabled, BOOL)
114RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock)
115RCT_EXPORT_VIEW_PROPERTY(onPickerDismiss, RCTBubblingEventBlock)
116
117RCT_REMAP_VIEW_PROPERTY(mode, datePickerMode, UIDatePickerMode)
118RCT_REMAP_VIEW_PROPERTY(timeZoneOffsetInMinutes, timeZone, NSTimeZone)
119
120RCT_CUSTOM_VIEW_PROPERTY(themeVariant, UIUserInterfaceStyle, RNDateTimePicker) {
121    if (@available(iOS 13.0, *)) {
122        if (json) {
123            UIUserInterfaceStyle propValue = [RCTConvert UIUserInterfaceStyle:json];
124            view.overrideUserInterfaceStyle = propValue;
125        } else {
126            view.overrideUserInterfaceStyle = UIUserInterfaceStyleUnspecified;
127        }
128    }
129}
130
131RCT_CUSTOM_VIEW_PROPERTY(textColor, UIColor, RNDateTimePicker)
132{
133  if (@available(iOS 14.0, *)) {
134    if (view.datePickerStyle != UIDatePickerStyleWheels) {
135      // prevents #247
136      return;
137    }
138  }
139  if (json) {
140    [view setValue:[RCTConvert UIColor:json] forKey:@"textColor"];
141    [view setValue:@(NO) forKey:@"highlightsToday"];
142  } else {
143    UIColor* defaultColor;
144    if (@available(iOS 13.0, *)) {
145        defaultColor = [UIColor labelColor];
146    } else {
147        defaultColor = [UIColor blackColor];
148    }
149    [view setValue:defaultColor forKey:@"textColor"];
150    [view setValue:@(YES) forKey:@"highlightsToday"];
151  }
152}
153
154RCT_CUSTOM_VIEW_PROPERTY(accentColor, UIColor, RNDateTimePicker)
155{
156    if (json) {
157        [view setTintColor:[RCTConvert UIColor:json]];
158    } else {
159        if (@available(iOS 15.0, *)) {
160            [view setTintColor:[UIColor tintColor]];
161        } else {
162            [view setTintColor:[UIColor systemBlueColor]];
163        }
164    }
165}
166
167// TODO vonovak setting preferredDatePickerStyle invalidates minuteinterval
168RCT_CUSTOM_VIEW_PROPERTY(displayIOS, RNCUIDatePickerStyle, RNDateTimePicker)
169{
170    // officially since 13.4 (https://developer.apple.com/documentation/uikit/uidatepickerstyle?language=objc) but practically since 14
171    if (@available(iOS 14.0, *)) {
172        if (json) {
173            UIDatePickerStyle propValue = [RCTConvert RNCUIDatePickerStyle:json];
174            view.preferredDatePickerStyle = propValue;
175        } else {
176            view.preferredDatePickerStyle = UIDatePickerStyleAutomatic;
177        }
178    }
179}
180
181@end
182