Skip to content

Commit 097c899

Browse files
authored
[ios][android] Update @react-native-community/datetimepicker to 7.6.1 (expo#25482)
1 parent 1404a35 commit 097c899

File tree

18 files changed

+242
-256
lines changed

18 files changed

+242
-256
lines changed

android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/Common.java

+78-15
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,15 @@
1818
import androidx.fragment.app.FragmentManager;
1919

2020
import com.facebook.react.bridge.Promise;
21+
import com.facebook.react.bridge.ReadableMap;
22+
import com.facebook.react.util.RNLog;
2123

24+
import java.util.Arrays;
25+
import java.util.Calendar;
26+
import java.util.HashSet;
2227
import java.util.Locale;
28+
import java.util.SimpleTimeZone;
29+
import java.util.TimeZone;
2330

2431
public class Common {
2532

@@ -63,21 +70,18 @@ public static int getDefaultDialogButtonTextColor(@NonNull Context activity) {
6370

6471
@NonNull
6572
public static DialogInterface.OnShowListener setButtonTextColor(@NonNull final Context activityContext, final AlertDialog dialog, final Bundle args, final boolean needsColorOverride) {
66-
return new DialogInterface.OnShowListener() {
67-
@Override
68-
public void onShow(DialogInterface dialogInterface) {
69-
// change text color only if custom color is set or if spinner mode is set
70-
// because spinner suffers from https://github.com/react-native-datetimepicker/datetimepicker/issues/543
71-
72-
Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
73-
Button negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
74-
Button neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
75-
76-
int textColorPrimary = getDefaultDialogButtonTextColor(activityContext);
77-
setTextColor(positiveButton, POSITIVE, args, needsColorOverride, textColorPrimary);
78-
setTextColor(negativeButton, NEGATIVE, args, needsColorOverride, textColorPrimary);
79-
setTextColor(neutralButton, NEUTRAL, args, needsColorOverride, textColorPrimary);
80-
}
73+
return dialogInterface -> {
74+
// change text color only if custom color is set or if spinner mode is set
75+
// because spinner suffers from https://github.com/react-native-datetimepicker/datetimepicker/issues/543
76+
77+
Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
78+
Button negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
79+
Button neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);
80+
81+
int textColorPrimary = getDefaultDialogButtonTextColor(activityContext);
82+
setTextColor(positiveButton, POSITIVE, args, needsColorOverride, textColorPrimary);
83+
setTextColor(negativeButton, NEGATIVE, args, needsColorOverride, textColorPrimary);
84+
setTextColor(neutralButton, NEUTRAL, args, needsColorOverride, textColorPrimary);
8185
};
8286
}
8387

@@ -139,4 +143,63 @@ private static void setButtonLabel(Bundle buttonConfig, AlertDialog dialog, int
139143
}
140144
dialog.setButton(whichButton, buttonConfig.getString(LABEL), listener);
141145
}
146+
147+
public static TimeZone getTimeZone(Bundle args) {
148+
if (args != null && args.containsKey(RNConstants.ARG_TZOFFSET_MINS)) {
149+
return new SimpleTimeZone((int)args.getLong(RNConstants.ARG_TZOFFSET_MINS) * 60 * 1000, "GMT");
150+
}
151+
152+
if (args != null && args.containsKey(RNConstants.ARG_TZ_NAME)) {
153+
String timeZoneName = args.getString(RNConstants.ARG_TZ_NAME);
154+
if ("GMT".equals(timeZoneName)) {
155+
return TimeZone.getTimeZone("GMT");
156+
} else if (!"GMT".equals(TimeZone.getTimeZone(timeZoneName).getID())) {
157+
return TimeZone.getTimeZone(timeZoneName);
158+
}
159+
RNLog.w(null, "'" + timeZoneName + "' does not exist in TimeZone.getAvailableIDs(). Falling back to TimeZone.getDefault()=" + TimeZone.getDefault().getID());
160+
}
161+
162+
return TimeZone.getDefault();
163+
}
164+
165+
public static long maxDateWithTimeZone(Bundle args) {
166+
if (!args.containsKey(RNConstants.ARG_MAXDATE)) {
167+
return Long.MAX_VALUE;
168+
}
169+
170+
Calendar maxDate = Calendar.getInstance(getTimeZone(args));
171+
maxDate.setTimeInMillis(args.getLong(RNConstants.ARG_MAXDATE));
172+
maxDate.set(Calendar.HOUR_OF_DAY, 23);
173+
maxDate.set(Calendar.MINUTE, 59);
174+
maxDate.set(Calendar.SECOND, 59);
175+
maxDate.set(Calendar.MILLISECOND, 999);
176+
return maxDate.getTimeInMillis();
177+
}
178+
179+
public static long minDateWithTimeZone(Bundle args) {
180+
if (!args.containsKey(RNConstants.ARG_MINDATE)) {
181+
return 0;
182+
}
183+
184+
Calendar minDate = Calendar.getInstance(getTimeZone(args));
185+
minDate.setTimeInMillis(args.getLong(RNConstants.ARG_MINDATE));
186+
minDate.set(Calendar.HOUR_OF_DAY, 0);
187+
minDate.set(Calendar.MINUTE, 0);
188+
minDate.set(Calendar.SECOND, 0);
189+
minDate.set(Calendar.MILLISECOND, 0);
190+
return minDate.getTimeInMillis();
191+
}
192+
193+
public static Bundle createFragmentArguments(ReadableMap options) {
194+
final Bundle args = new Bundle();
195+
196+
if (options.hasKey(RNConstants.ARG_VALUE) && !options.isNull(RNConstants.ARG_VALUE)) {
197+
args.putLong(RNConstants.ARG_VALUE, (long) options.getDouble(RNConstants.ARG_VALUE));
198+
}
199+
if (options.hasKey(RNConstants.ARG_TZ_NAME) && !options.isNull(RNConstants.ARG_TZ_NAME)) {
200+
args.putString(RNConstants.ARG_TZ_NAME, options.getString(RNConstants.ARG_TZ_NAME));
201+
}
202+
203+
return args;
204+
}
142205
}

android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/DatePickerModule.java

+34-48
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,6 @@
2222
import com.facebook.react.module.annotations.ReactModule;
2323

2424
import static versioned.host.exp.exponent.modules.api.components.datetimepicker.Common.dismissDialog;
25-
import static versioned.host.exp.exponent.modules.api.components.datetimepicker.KeepDateInRangeListener.isDateAfterMaxDate;
26-
import static versioned.host.exp.exponent.modules.api.components.datetimepicker.KeepDateInRangeListener.isDateBeforeMinDate;
2725

2826
import java.util.Calendar;
2927

@@ -35,14 +33,15 @@
3533
public class DatePickerModule extends NativeModuleDatePickerSpec {
3634

3735
@VisibleForTesting
38-
public static final String NAME = "RNDatePicker";
36+
public static final String NAME = "RNCDatePicker";
3937

4038
public DatePickerModule(ReactApplicationContext reactContext) {
4139
super(reactContext);
4240
}
4341

42+
@NonNull
4443
@Override
45-
public @NonNull String getName() {
44+
public String getName() {
4645
return NAME;
4746
}
4847

@@ -60,31 +59,15 @@ public DatePickerDialogListener(final Promise promise, Bundle arguments) {
6059
@Override
6160
public void onDateSet(DatePicker view, int year, int month, int day) {
6261
if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) {
62+
final RNDate date = new RNDate(mArgs);
63+
Calendar calendar = Calendar.getInstance(Common.getTimeZone(mArgs));
64+
calendar.set(year, month, day, date.hour(), date.minute(), 0);
65+
calendar.set(Calendar.MILLISECOND, 0);
66+
6367
WritableMap result = new WritableNativeMap();
6468
result.putString("action", RNConstants.ACTION_DATE_SET);
65-
result.putInt("year", year);
66-
result.putInt("month", month);
67-
result.putInt("day", day);
68-
69-
// https://issuetracker.google.com/issues/169602180
70-
// TODO revisit day, month, year with timezoneoffset fixes
71-
if (isDateAfterMaxDate(mArgs, year, month, day)) {
72-
Calendar maxDate = Calendar.getInstance();
73-
maxDate.setTimeInMillis(mArgs.getLong(RNConstants.ARG_MAXDATE));
74-
75-
result.putInt("year", maxDate.get(Calendar.YEAR));
76-
result.putInt("month", maxDate.get(Calendar.MONTH) );
77-
result.putInt("day", maxDate.get(Calendar.DAY_OF_MONTH));
78-
}
79-
80-
if (isDateBeforeMinDate(mArgs, year, month, day)) {
81-
Calendar minDate = Calendar.getInstance();
82-
minDate.setTimeInMillis(mArgs.getLong(RNConstants.ARG_MINDATE));
83-
84-
result.putInt("year", minDate.get(Calendar.YEAR));
85-
result.putInt("month", minDate.get(Calendar.MONTH) );
86-
result.putInt("day", minDate.get(Calendar.DAY_OF_MONTH));
87-
}
69+
result.putDouble("timestamp", calendar.getTimeInMillis());
70+
result.putDouble("utcOffset", calendar.getTimeZone().getOffset(calendar.getTimeInMillis()) / 1000 / 60);
8871

8972
mPromise.resolve(result);
9073
mPromiseResolved = true;
@@ -135,6 +118,9 @@ public void dismiss(Promise promise) {
135118
* <li>
136119
* {@code display} To set the date picker display to 'calendar/spinner/default'
137120
* </li>
121+
* <li>
122+
* {@code testID} testID for testing with e.g. detox.
123+
* </li>
138124
* </ul>
139125
*
140126
* @param promise This will be invoked with parameters action, year,
@@ -154,35 +140,32 @@ public void open(final ReadableMap options, final Promise promise) {
154140

155141
final FragmentManager fragmentManager = activity.getSupportFragmentManager();
156142

157-
UiThreadUtil.runOnUiThread(new Runnable() {
158-
@Override
159-
public void run() {
160-
RNDatePickerDialogFragment oldFragment =
161-
(RNDatePickerDialogFragment) fragmentManager.findFragmentByTag(NAME);
143+
UiThreadUtil.runOnUiThread(() -> {
144+
RNDatePickerDialogFragment oldFragment =
145+
(RNDatePickerDialogFragment) fragmentManager.findFragmentByTag(NAME);
162146

163-
if (oldFragment != null) {
164-
oldFragment.update(createFragmentArguments(options));
165-
return;
166-
}
147+
Bundle arguments = createFragmentArguments(options);
167148

168-
RNDatePickerDialogFragment fragment = new RNDatePickerDialogFragment();
149+
if (oldFragment != null) {
150+
oldFragment.update(arguments);
151+
return;
152+
}
169153

170-
fragment.setArguments(createFragmentArguments(options));
154+
RNDatePickerDialogFragment fragment = new RNDatePickerDialogFragment();
171155

172-
final DatePickerDialogListener listener = new DatePickerDialogListener(promise, createFragmentArguments(options));
173-
fragment.setOnDismissListener(listener);
174-
fragment.setOnDateSetListener(listener);
175-
fragment.setOnNeutralButtonActionListener(listener);
176-
fragment.show(fragmentManager, NAME);
177-
}
156+
fragment.setArguments(arguments);
157+
158+
final DatePickerDialogListener listener = new DatePickerDialogListener(promise, arguments);
159+
fragment.setOnDismissListener(listener);
160+
fragment.setOnDateSetListener(listener);
161+
fragment.setOnNeutralButtonActionListener(listener);
162+
fragment.show(fragmentManager, NAME);
178163
});
179164
}
180165

181166
private Bundle createFragmentArguments(ReadableMap options) {
182-
final Bundle args = new Bundle();
183-
if (options.hasKey(RNConstants.ARG_VALUE) && !options.isNull(RNConstants.ARG_VALUE)) {
184-
args.putLong(RNConstants.ARG_VALUE, (long) options.getDouble(RNConstants.ARG_VALUE));
185-
}
167+
final Bundle args = Common.createFragmentArguments(options);
168+
186169
if (options.hasKey(RNConstants.ARG_MINDATE) && !options.isNull(RNConstants.ARG_MINDATE)) {
187170
args.putLong(RNConstants.ARG_MINDATE, (long) options.getDouble(RNConstants.ARG_MINDATE));
188171
}
@@ -198,6 +181,9 @@ private Bundle createFragmentArguments(ReadableMap options) {
198181
if (options.hasKey(RNConstants.ARG_TZOFFSET_MINS) && !options.isNull(RNConstants.ARG_TZOFFSET_MINS)) {
199182
args.putLong(RNConstants.ARG_TZOFFSET_MINS, (long) options.getDouble(RNConstants.ARG_TZOFFSET_MINS));
200183
}
184+
if (options.hasKey(RNConstants.ARG_TESTID) && !options.isNull(RNConstants.ARG_TESTID)) {
185+
args.putString(RNConstants.ARG_TESTID, options.getString(RNConstants.ARG_TESTID));
186+
}
201187
return args;
202188
}
203189
}

android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/KeepDateInRangeListener.java

-65
This file was deleted.

android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNConstants.java

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ public final class RNConstants {
1212
public static final String ARG_DISPLAY = "display";
1313
public static final String ARG_DIALOG_BUTTONS = "dialogButtons";
1414
public static final String ARG_TZOFFSET_MINS = "timeZoneOffsetInMinutes";
15+
public static final String ARG_TZ_NAME = "timeZoneName";
16+
public static final String ARG_TESTID = "testID";
1517
public static final String ACTION_DATE_SET = "dateSetAction";
1618
public static final String ACTION_TIME_SET = "timeSetAction";
1719
public static final String ACTION_DISMISSED = "dismissedAction";

android/expoview/src/main/java/versioned/host/exp/exponent/modules/api/components/datetimepicker/RNDate.java

+2-10
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,11 @@ public RNDate(Bundle args) {
1111
now = Calendar.getInstance();
1212

1313
if (args != null && args.containsKey(RNConstants.ARG_VALUE)) {
14-
set(args.getLong(RNConstants.ARG_VALUE));
14+
now.setTimeInMillis((args.getLong(RNConstants.ARG_VALUE)));
1515
}
1616

17-
if (args != null && args.containsKey(RNConstants.ARG_TZOFFSET_MINS)) {
18-
now.setTimeZone(TimeZone.getTimeZone("GMT"));
19-
Long timeZoneOffsetInMinutesFallback = args.getLong(RNConstants.ARG_TZOFFSET_MINS);
20-
Integer timeZoneOffsetInMinutes = args.getInt(RNConstants.ARG_TZOFFSET_MINS, timeZoneOffsetInMinutesFallback.intValue());
21-
now.add(Calendar.MILLISECOND, timeZoneOffsetInMinutes * 60000);
22-
}
23-
}
2417

25-
public void set(long value) {
26-
now.setTimeInMillis(value);
18+
now.setTimeZone(Common.getTimeZone(args));
2719
}
2820

2921
public int year() { return now.get(Calendar.YEAR); }

0 commit comments

Comments
 (0)