From c41e3c26224161b5dc77d28895bfabbd6d2b08ce Mon Sep 17 00:00:00 2001 From: Cedric van Putten Date: Wed, 5 Oct 2022 16:48:30 +0200 Subject: [PATCH 1/3] =?UTF-8?q?Upgrade=20`@react-native-community/datetime?= =?UTF-8?q?picker@6.2.0`=20=E2=9E=A1=EF=B8=8F=20`@react-native-community/d?= =?UTF-8?q?atetimepicker@6.5.0`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...nuteIntervalSnappableTimePickerDialog.java | 87 ++++++++++++------- .../RNDatePickerDialogFragment.java | 2 - .../RNDatePickerDialogModule.java | 6 +- .../RNDismissableDatePickerDialog.java | 4 + .../RNTimePickerDialogFragment.java | 7 +- .../RNTimePickerDialogModule.java | 8 +- apps/bare-expo/package.json | 2 +- apps/native-component-list/package.json | 2 +- ios/Exponent.xcodeproj/project.pbxproj | 6 ++ .../DateTimePicker/RNDateTimePicker.m | 16 +++- .../DateTimePicker/RNDateTimePickerManager.m | 50 ++++++----- .../RNDateTimePickerShadowView.h | 12 +++ .../RNDateTimePickerShadowView.m | 55 ++++++++++++ packages/expo/bundledNativeModules.json | 2 +- 14 files changed, 187 insertions(+), 72 deletions(-) create mode 100644 ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePickerShadowView.h create mode 100644 ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePickerShadowView.m diff --git a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/MinuteIntervalSnappableTimePickerDialog.java b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/MinuteIntervalSnappableTimePickerDialog.java index 8ac9ddae979e0..ca662a09581b1 100644 --- a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/MinuteIntervalSnappableTimePickerDialog.java +++ b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/MinuteIntervalSnappableTimePickerDialog.java @@ -76,7 +76,7 @@ private boolean isSpinner() { * @return returns 'real' minutes (0-59) */ private int getRealMinutes(int minutesOrSpinnerIndex) { - if (mDisplay == RNTimePickerDisplay.SPINNER) { + if (isSpinner()) { return minutesOrSpinnerIndex * mTimePickerInterval; } @@ -147,27 +147,42 @@ private void correctEnteredMinutes(final TimePicker view, final int hourOfDay, f runnable = new Runnable() { @Override public void run() { - // set valid hour & minutes - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - view.setHour(hourOfDay); - view.setMinute(correctedMinutes); - } else { - view.setCurrentHour(hourOfDay); - // we need to set minutes to 0 for this to work on older android devices - view.setCurrentMinute(0); - view.setCurrentMinute(correctedMinutes); - } - if (pickerIsInTextInputMode()) { - // move caret to the end of input - View maybeTextInput = view.findFocus(); - if (maybeTextInput instanceof EditText) { - final EditText textInput = (EditText) maybeTextInput; - textInput.setSelection(textInput.getText().length()); - } else { - Log.e("RN-datetimepicker", "could not set selection on time picker, this is a known issue on some Huawei devices"); - } - } + if (pickerIsInTextInputMode()) { + // only rewrite input when the value makes sense to be corrected + // eg. given interval 3, when user wants to enter 53 + // we don't rewrite the first number "5" to 6, because it would be confusing + // but the value will be corrected in onTimeChanged() + // however, when they enter 10, we rewrite it to 9 + boolean canRewriteTextInput = correctedMinutes > 5; + if (!canRewriteTextInput) { + return; + } + fixTime(); + moveCursorToEnd(); + } else { + fixTime(); + } } + private void fixTime() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + view.setHour(hourOfDay); + view.setMinute(correctedMinutes); + } else { + view.setCurrentHour(hourOfDay); + // we need to set minutes to 0 first for this to work on older android devices + view.setCurrentMinute(0); + view.setCurrentMinute(correctedMinutes); + } + } + private void moveCursorToEnd() { + View maybeTextInput = view.findFocus(); + if (maybeTextInput instanceof EditText) { + final EditText textInput = (EditText) maybeTextInput; + textInput.setSelection(textInput.getText().length()); + } else { + Log.e("RN-datetimepicker", "could not set selection on time picker, this is a known issue on some Huawei devices"); + } + } }; handler.postDelayed(runnable, 500); @@ -191,15 +206,17 @@ public void onTimeChanged(final TimePicker view, final int hourOfDay, final int @Override public void onClick(DialogInterface dialog, int which) { - if (mTimePicker != null && which == BUTTON_POSITIVE && timePickerHasCustomMinuteInterval()) { - final int hours = mTimePicker.getCurrentHour(); - - final int realMinutes = getRealMinutes(); - int validMinutes = isSpinner() ? realMinutes : snapRealMinutesToInterval(realMinutes); - - if (mTimeSetListener != null) { - mTimeSetListener.onTimeSet(mTimePicker, hours, validMinutes); - } + boolean needsCustomHandling = timePickerHasCustomMinuteInterval() || isSpinner(); + if (mTimePicker != null && which == BUTTON_POSITIVE && needsCustomHandling) { + mTimePicker.clearFocus(); + final int hours = mTimePicker.getCurrentHour(); + int realMinutes = getRealMinutes(); + int reportedMinutes = timePickerHasCustomMinuteInterval() + ? snapRealMinutesToInterval(realMinutes) + : realMinutes; + if (mTimeSetListener != null) { + mTimeSetListener.onTimeSet(mTimePicker, hours, reportedMinutes); + } } else { super.onClick(dialog, which); } @@ -228,15 +245,19 @@ public void updateTime(int hourOfDay, int minuteOfHour) { public void onAttachedToWindow() { super.onAttachedToWindow(); + int timePickerId = mContext.getResources().getIdentifier("timePicker", "id", "android"); + mTimePicker = this.findViewById(timePickerId); + if (timePickerHasCustomMinuteInterval()) { setupPickerDialog(); } } private void setupPickerDialog() { - int timePickerId = mContext.getResources().getIdentifier("timePicker", "id", "android"); - mTimePicker = this.findViewById(timePickerId); - + if (mTimePicker == null) { + Log.e("RN-datetimepicker", "time picker was null"); + return; + } int realMinuteBackup = mTimePicker.getCurrentMinute(); if (isSpinner()) { diff --git a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDatePickerDialogFragment.java b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDatePickerDialogFragment.java index 5063eb44c62f9..2d17afcd7f987 100644 --- a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDatePickerDialogFragment.java +++ b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDatePickerDialogFragment.java @@ -7,8 +7,6 @@ package versioned.host.exp.exponent.modules.api.components.datetimepicker; -import host.exp.expoview.R; - import android.annotation.SuppressLint; import android.app.DatePickerDialog; import android.app.DatePickerDialog.OnDateSetListener; diff --git a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDatePickerDialogModule.java b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDatePickerDialogModule.java index 3f8849b5f76a4..82bfec96adb3f 100644 --- a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDatePickerDialogModule.java +++ b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDatePickerDialogModule.java @@ -54,7 +54,7 @@ public DatePickerDialogListener(final Promise promise) { @Override public void onDateSet(DatePicker view, int year, int month, int day) { - if (!mPromiseResolved && getReactApplicationContext().hasActiveCatalystInstance()) { + if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) { WritableMap result = new WritableNativeMap(); result.putString("action", RNConstants.ACTION_DATE_SET); result.putInt("year", year); @@ -67,7 +67,7 @@ public void onDateSet(DatePicker view, int year, int month, int day) { @Override public void onDismiss(DialogInterface dialog) { - if (!mPromiseResolved && getReactApplicationContext().hasActiveCatalystInstance()) { + if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) { WritableMap result = new WritableNativeMap(); result.putString("action", RNConstants.ACTION_DISMISSED); mPromise.resolve(result); @@ -77,7 +77,7 @@ public void onDismiss(DialogInterface dialog) { @Override public void onClick(DialogInterface dialog, int which) { - if (!mPromiseResolved && getReactApplicationContext().hasActiveCatalystInstance()) { + if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) { WritableMap result = new WritableNativeMap(); result.putString("action", RNConstants.ACTION_NEUTRAL_BUTTON); mPromise.resolve(result); diff --git a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDismissableDatePickerDialog.java b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDismissableDatePickerDialog.java index 4e21a2ead5f23..37be7bc243371 100644 --- a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDismissableDatePickerDialog.java +++ b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDismissableDatePickerDialog.java @@ -106,5 +106,9 @@ private void fixSpinner(Context context, int year, int month, int dayOfMonth, RN throw new RuntimeException(e); } } + if (display == RNDatePickerDisplay.SPINNER){ + if(this.getDatePicker() != null) + this.getDatePicker().setCalendarViewShown(false); + } } } diff --git a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNTimePickerDialogFragment.java b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNTimePickerDialogFragment.java index 9526e0a7fa327..04b5acf18f683 100644 --- a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNTimePickerDialogFragment.java +++ b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNTimePickerDialogFragment.java @@ -8,8 +8,6 @@ package versioned.host.exp.exponent.modules.api.components.datetimepicker; -import host.exp.expoview.R; - import android.app.Dialog; import android.app.TimePickerDialog; import android.app.TimePickerDialog.OnTimeSetListener; @@ -17,10 +15,10 @@ import android.content.DialogInterface; import android.content.DialogInterface.OnDismissListener; import android.content.DialogInterface.OnClickListener; -import android.os.Build; import android.os.Bundle; import android.text.format.DateFormat; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.DialogFragment; @@ -37,6 +35,7 @@ public class RNTimePickerDialogFragment extends DialogFragment { @Nullable private static OnClickListener mOnNeutralButtonActionListener; + @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { final Bundle args = getArguments(); @@ -118,7 +117,7 @@ static TimePickerDialog createDialog( } @Override - public void onDismiss(DialogInterface dialog) { + public void onDismiss(@NonNull DialogInterface dialog) { super.onDismiss(dialog); if (mOnDismissListener != null) { mOnDismissListener.onDismiss(dialog); diff --git a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNTimePickerDialogModule.java b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNTimePickerDialogModule.java index 9e2f271b1450d..e26c2a218e1c8 100644 --- a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNTimePickerDialogModule.java +++ b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNTimePickerDialogModule.java @@ -19,6 +19,7 @@ import android.os.Bundle; import android.widget.TimePicker; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentManager; @@ -39,6 +40,7 @@ public RNTimePickerDialogModule(ReactApplicationContext reactContext) { super(reactContext); } + @NonNull @Override public String getName() { return FRAGMENT_TAG; @@ -54,7 +56,7 @@ public TimePickerDialogListener(Promise promise) { @Override public void onTimeSet(TimePicker view, int hour, int minute) { - if (!mPromiseResolved && getReactApplicationContext().hasActiveCatalystInstance()) { + if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) { WritableMap result = new WritableNativeMap(); result.putString("action", RNConstants.ACTION_TIME_SET); result.putInt("hour", hour); @@ -66,7 +68,7 @@ public void onTimeSet(TimePicker view, int hour, int minute) { @Override public void onDismiss(DialogInterface dialog) { - if (!mPromiseResolved && getReactApplicationContext().hasActiveCatalystInstance()) { + if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) { WritableMap result = new WritableNativeMap(); result.putString("action", RNConstants.ACTION_DISMISSED); mPromise.resolve(result); @@ -76,7 +78,7 @@ public void onDismiss(DialogInterface dialog) { @Override public void onClick(DialogInterface dialog, int which) { - if (!mPromiseResolved && getReactApplicationContext().hasActiveCatalystInstance()) { + if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) { WritableMap result = new WritableNativeMap(); result.putString("action", RNConstants.ACTION_NEUTRAL_BUTTON); mPromise.resolve(result); diff --git a/apps/bare-expo/package.json b/apps/bare-expo/package.json index a30623479ac9b..75bd4a489d943 100644 --- a/apps/bare-expo/package.json +++ b/apps/bare-expo/package.json @@ -92,7 +92,7 @@ "dependencies": { "@babel/runtime": "^7.14.0", "@react-native-async-storage/async-storage": "~1.17.3", - "@react-native-community/datetimepicker": "6.2.0", + "@react-native-community/datetimepicker": "6.5.0", "@react-native-community/netinfo": "9.3.3", "@react-native-community/slider": "4.2.3", "@react-native-community/viewpager": "5.0.11", diff --git a/apps/native-component-list/package.json b/apps/native-component-list/package.json index b14963e4b53fc..5ac5155b7934b 100644 --- a/apps/native-component-list/package.json +++ b/apps/native-component-list/package.json @@ -42,7 +42,7 @@ "dependencies": { "@expo/react-native-action-sheet": "^3.8.0", "@react-native-async-storage/async-storage": "~1.17.3", - "@react-native-community/datetimepicker": "6.2.0", + "@react-native-community/datetimepicker": "6.5.0", "@react-native-community/netinfo": "9.3.3", "@react-native-community/slider": "4.2.3", "@react-native-masked-view/masked-view": "0.2.6", diff --git a/ios/Exponent.xcodeproj/project.pbxproj b/ios/Exponent.xcodeproj/project.pbxproj index 2f46da389287f..562b772311371 100644 --- a/ios/Exponent.xcodeproj/project.pbxproj +++ b/ios/Exponent.xcodeproj/project.pbxproj @@ -583,6 +583,7 @@ FCF6D37025B34BC200808BF5 /* NotificationService.swift in Sources */ = {isa = PBXBuildFile; fileRef = FCF6D36F25B34BC200808BF5 /* NotificationService.swift */; }; FCF6D37425B34BC200808BF5 /* ExpoNotificationServiceExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = FCF6D36D25B34BC200808BF5 /* ExpoNotificationServiceExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; FE8D4A1FC2BDC25C8D4684F8 /* ExpoModulesProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C849D84FFC04012BBF6DFFD /* ExpoModulesProvider.swift */; }; + 8704B111C11841D78D77E3E7 /* RNDateTimePickerShadowView.m in Sources */ = {isa = PBXBuildFile; fileRef = 76E808C4949F497592E26673 /* RNDateTimePickerShadowView.m */; settings = {COMPILER_FLAGS = "-w"; }; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -1251,6 +1252,8 @@ FCF6D36D25B34BC200808BF5 /* ExpoNotificationServiceExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = ExpoNotificationServiceExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; FCF6D36F25B34BC200808BF5 /* NotificationService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationService.swift; sourceTree = ""; }; FCF6D37125B34BC200808BF5 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 6C7BA917106C42AEA7813785 /* RNDateTimePickerShadowView.h */ = {isa = PBXFileReference; name = "RNDateTimePickerShadowView.h"; path = "RNDateTimePickerShadowView.h"; sourceTree = ""; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; explicitFileType = undefined; includeInIndex = 0; }; + 76E808C4949F497592E26673 /* RNDateTimePickerShadowView.m */ = {isa = PBXFileReference; name = "RNDateTimePickerShadowView.m"; path = "RNDateTimePickerShadowView.m"; sourceTree = ""; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; explicitFileType = undefined; includeInIndex = 0; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -2410,6 +2413,8 @@ D47336D662754EDA8EA4BC55 /* RNDateTimePicker.m */, 12869A47946248B094FFB1C0 /* RNDateTimePickerManager.h */, D86827B3D57944D8A25F37F8 /* RNDateTimePickerManager.m */, + 6C7BA917106C42AEA7813785 /* RNDateTimePickerShadowView.h */, + 76E808C4949F497592E26673 /* RNDateTimePickerShadowView.m */, ); path = DateTimePicker; sourceTree = ""; @@ -3310,6 +3315,7 @@ C3C2D83067C44A679721209C /* RNCPickerLabel.m in Sources */, FBCC5A97F536402C98688A94 /* RNCPickerManager.m in Sources */, 142BF7101AA740B69473EA27 /* AIRMapUrlTileCachedOverlay.m in Sources */, + 8704B111C11841D78D77E3E7 /* RNDateTimePickerShadowView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePicker.m b/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePicker.m index 91151d9524399..c2a70e73b6ee4 100644 --- a/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePicker.m +++ b/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePicker.m @@ -13,6 +13,7 @@ @interface RNDateTimePicker () @property (nonatomic, copy) RCTBubblingEventBlock onChange; +@property (nonatomic, copy) RCTBubblingEventBlock onPickerDismiss; @property (nonatomic, assign) NSInteger reactMinuteInterval; @end @@ -22,8 +23,14 @@ @implementation RNDateTimePicker - (instancetype)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { - [self addTarget:self action:@selector(didChange) + #ifndef RCT_NEW_ARCH_ENABLED + // somehow, with Fabric, the callbacks are executed here as well as in RNDateTimePickerComponentView + // so do not register it with Fabric, to avoid potential problems + [self addTarget:self action:@selector(didChange) forControlEvents:UIControlEventValueChanged]; + [self addTarget:self action:@selector(onDismiss:) forControlEvents:UIControlEventEditingDidEnd]; + #endif + _reactMinuteInterval = 1; } return self; @@ -38,6 +45,13 @@ - (void)didChange } } +- (void)onDismiss:(RNDateTimePicker *)sender +{ + if (_onPickerDismiss) { + _onPickerDismiss(@{}); + } +} + - (void)setDatePickerMode:(UIDatePickerMode)datePickerMode { [super setDatePickerMode:datePickerMode]; diff --git a/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePickerManager.m b/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePickerManager.m index 8ca5217655b34..dbf3a62621426 100644 --- a/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePickerManager.m +++ b/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePickerManager.m @@ -6,6 +6,7 @@ */ #import "RNDateTimePickerManager.h" +#import "RNDateTimePickerShadowView.h" #import #import @@ -53,15 +54,35 @@ @implementation RCTConvert(UIDatePicker) @end -@implementation RNDateTimePickerManager +@implementation RNDateTimePickerManager { + RNDateTimePicker* _picker; +} RCT_EXPORT_MODULE() +- (instancetype)init { + if (self = [super init]) { + _picker = [RNDateTimePicker new]; + } + return self; +} + ++ (BOOL)requiresMainQueueSetup { + return true; +} + - (UIView *)view { return [RNDateTimePicker new]; } +- (RCTShadowView *)shadowView +{ + RNDateTimePickerShadowView* shadowView = [RNDateTimePickerShadowView new]; + shadowView.picker = _picker; + return shadowView; +} + + (NSString*) datepickerStyleToString: (UIDatePickerStyle) style API_AVAILABLE(ios(13.4)){ // RCTConvert does not handle this.? switch (style) { @@ -79,28 +100,10 @@ + (NSString*) datepickerStyleToString: (UIDatePickerStyle) style API_AVAILABLE( } } -RCT_EXPORT_METHOD(getDefaultDisplayValue:(NSDictionary *)options resolver:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) -{ - dispatch_async(dispatch_get_main_queue(), ^{ - if (@available(iOS 13.4, *)) { - UIDatePicker* view = [RNDateTimePicker new]; - - view.preferredDatePickerStyle = UIDatePickerStyleAutomatic; - UIDatePickerMode renderedMode = [RCTConvert UIDatePickerMode:options[@"mode"]]; - view.datePickerMode = renderedMode; - // NOTE afaict we do not need to measure the actual dimensions here, but if we do, just look at the original PR - - UIDatePickerStyle determinedDisplayValue = view.datePickerStyle; - - resolve(@{ - @"determinedDisplayValue": [RNDateTimePickerManager datepickerStyleToString:determinedDisplayValue], - }); - } else { - // never happens; the condition is just to avoid compiler warnings - reject(@"UNEXPECTED_CALL", @"unexpected getDefaultDisplayValue() call", nil); - } - }); -} +RCT_EXPORT_SHADOW_PROPERTY(date, NSDate) +RCT_EXPORT_SHADOW_PROPERTY(mode, UIDatePickerMode) +RCT_EXPORT_SHADOW_PROPERTY(locale, NSLocale) +RCT_EXPORT_SHADOW_PROPERTY(displayIOS, RNCUIDatePickerStyle) RCT_EXPORT_VIEW_PROPERTY(date, NSDate) RCT_EXPORT_VIEW_PROPERTY(locale, NSLocale) @@ -109,6 +112,7 @@ + (NSString*) datepickerStyleToString: (UIDatePickerStyle) style API_AVAILABLE( RCT_EXPORT_VIEW_PROPERTY(minuteInterval, NSInteger) RCT_EXPORT_VIEW_PROPERTY(enabled, BOOL) RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock) +RCT_EXPORT_VIEW_PROPERTY(onPickerDismiss, RCTBubblingEventBlock) RCT_REMAP_VIEW_PROPERTY(mode, datePickerMode, UIDatePickerMode) RCT_REMAP_VIEW_PROPERTY(timeZoneOffsetInMinutes, timeZone, NSTimeZone) diff --git a/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePickerShadowView.h b/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePickerShadowView.h new file mode 100644 index 0000000000000..04578ee8f3043 --- /dev/null +++ b/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePickerShadowView.h @@ -0,0 +1,12 @@ +#import +#import "RNDateTimePicker.h" + +@interface RNDateTimePickerShadowView : RCTShadowView + +@property (nullable, nonatomic, strong) RNDateTimePicker *picker; +@property (nonatomic) UIDatePickerMode mode; +@property (nullable, nonatomic, strong) NSDate *date; +@property (nullable, nonatomic, strong) NSLocale *locale; +@property (nonatomic, assign) UIDatePickerStyle displayIOS API_AVAILABLE(ios(13.4)); + +@end diff --git a/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePickerShadowView.m b/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePickerShadowView.m new file mode 100644 index 0000000000000..ac75a769701d4 --- /dev/null +++ b/ios/Exponent/Versioned/Core/Api/Components/DateTimePicker/RNDateTimePickerShadowView.m @@ -0,0 +1,55 @@ +#import "RNDateTimePickerShadowView.h" + +@implementation RNDateTimePickerShadowView + +- (instancetype)init +{ + if (self = [super init]) { + YGNodeSetMeasureFunc(self.yogaNode, RNDateTimePickerShadowViewMeasure); + } + return self; +} + +- (void)setDate:(NSDate *)date { + _date = date; + YGNodeMarkDirty(self.yogaNode); +} + +- (void)setLocale:(NSLocale *)locale { + _locale = locale; + YGNodeMarkDirty(self.yogaNode); +} + +- (void)setMode:(UIDatePickerMode)mode { + _mode = mode; + YGNodeMarkDirty(self.yogaNode); +} + + +- (void)setDisplayIOS:(UIDatePickerStyle)displayIOS { + _displayIOS = displayIOS; + YGNodeMarkDirty(self.yogaNode); +} + +static YGSize RNDateTimePickerShadowViewMeasure(YGNodeRef node, float width, YGMeasureMode widthMode, float height, YGMeasureMode heightMode) +{ + RNDateTimePickerShadowView *shadowPickerView = (__bridge RNDateTimePickerShadowView *)YGNodeGetContext(node); + + __block CGSize size; + dispatch_sync(dispatch_get_main_queue(), ^{ + [shadowPickerView.picker setDate:shadowPickerView.date]; + [shadowPickerView.picker setDatePickerMode:shadowPickerView.mode]; + [shadowPickerView.picker setLocale:shadowPickerView.locale]; + if (@available(iOS 14.0, *)) { + [shadowPickerView.picker setPreferredDatePickerStyle:shadowPickerView.displayIOS]; + } + size = [shadowPickerView.picker sizeThatFits:UILayoutFittingCompressedSize]; + }); + + return (YGSize){ + RCTYogaFloatFromCoreGraphicsFloat(size.width), + RCTYogaFloatFromCoreGraphicsFloat(size.height) + }; +} + +@end diff --git a/packages/expo/bundledNativeModules.json b/packages/expo/bundledNativeModules.json index e6163650e3574..c31f0e3919e0b 100644 --- a/packages/expo/bundledNativeModules.json +++ b/packages/expo/bundledNativeModules.json @@ -1,7 +1,7 @@ { "@expo/vector-icons": "^13.0.0", "@react-native-async-storage/async-storage": "~1.17.3", - "@react-native-community/datetimepicker": "6.2.0", + "@react-native-community/datetimepicker": "6.5.0", "@react-native-masked-view/masked-view": "0.2.7", "@react-native-community/netinfo": "9.3.3", "@react-native-community/slider": "4.2.3", From 86271854411ade27a8973be7f8809cb2963e03eb Mon Sep 17 00:00:00 2001 From: Cedric van Putten Date: Wed, 5 Oct 2022 18:17:34 +0200 Subject: [PATCH 2/3] Add changelog entry for rnc datetimepicker --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 870e935476ab1..354ba41a1ebc3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Package-specific changes not released in any SDK will be added here just before - Updated `@react-native-picker/picker` from `2.4.2` to `2.4.6`. ([#19390](https://github.com/expo/expo/pull/19390) by [@aleqsio](https://github.com/aleqsio)) - Updated `react-native-screens` from `3.15.0` to `3.18.0`. ([#19383](https://github.com/expo/expo/pull/19383) by [@tsapeta](https://github.com/tsapeta)) - Updated `@shopify/react-native-skia` from `0.1.136` to `0.1.153`. ([#19360](https://github.com/expo/expo/pull/19360) by [@kudo](https://github.com/kudo)) +- Updated `@react-native-community/datetimepicker` from `6.2.0` to `6.5.0`. ([#19419](https://github.com/expo/expo/pull/19419) by [@byCedric](https://github.com/byCedric)) ### 🛠 Breaking changes From df1398a7b16f6c408b5ab794b3c99f304b44760d Mon Sep 17 00:00:00 2001 From: Cedric van Putten Date: Wed, 5 Oct 2022 20:28:02 +0200 Subject: [PATCH 3/3] Add missing R imports to datetimepicker files --- .../components/datetimepicker/RNDatePickerDialogFragment.java | 2 ++ .../components/datetimepicker/RNTimePickerDialogFragment.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDatePickerDialogFragment.java b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDatePickerDialogFragment.java index 2d17afcd7f987..5063eb44c62f9 100644 --- a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDatePickerDialogFragment.java +++ b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDatePickerDialogFragment.java @@ -7,6 +7,8 @@ package versioned.host.exp.exponent.modules.api.components.datetimepicker; +import host.exp.expoview.R; + import android.annotation.SuppressLint; import android.app.DatePickerDialog; import android.app.DatePickerDialog.OnDateSetListener; diff --git a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNTimePickerDialogFragment.java b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNTimePickerDialogFragment.java index 04b5acf18f683..14b8882ece6eb 100644 --- a/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNTimePickerDialogFragment.java +++ b/android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNTimePickerDialogFragment.java @@ -8,6 +8,8 @@ package versioned.host.exp.exponent.modules.api.components.datetimepicker; +import host.exp.expoview.R; + import android.app.Dialog; import android.app.TimePickerDialog; import android.app.TimePickerDialog.OnTimeSetListener;