Skip to content

Commit

Permalink
feat: add timeZoneName props
Browse files Browse the repository at this point in the history
  • Loading branch information
wood1986 committed Mar 27, 2023
1 parent f265c43 commit 5a9d512
Show file tree
Hide file tree
Showing 28 changed files with 2,234 additions and 4,221 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -59,3 +59,5 @@ buck-out/

# CocoaPods
example/ios/Pods/

.xcode.env
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,15 @@
import androidx.fragment.app.FragmentManager;

import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.util.RNLog;

import java.util.Arrays;
import java.util.Calendar;
import java.util.HashSet;
import java.util.Locale;
import java.util.SimpleTimeZone;
import java.util.TimeZone;

public class Common {

Expand All @@ -28,6 +35,7 @@ public class Common {
public static final String NEGATIVE = "negative";
public static final String LABEL = "label";
public static final String TEXT_COLOR = "textColor";
private static final HashSet TIMEZONE_IDS = new HashSet<>(Arrays.asList(TimeZone.getAvailableIDs()));

public static void dismissDialog(FragmentActivity activity, String fragmentTag, Promise promise) {
if (activity == null) {
Expand Down Expand Up @@ -63,21 +71,18 @@ public static int getDefaultDialogButtonTextColor(@NonNull Context activity) {

@NonNull
public static DialogInterface.OnShowListener setButtonTextColor(@NonNull final Context activityContext, final AlertDialog dialog, final Bundle args, final boolean needsColorOverride) {
return new DialogInterface.OnShowListener() {
@Override
public void onShow(DialogInterface dialogInterface) {
// change text color only if custom color is set or if spinner mode is set
// because spinner suffers from https://github.com/react-native-datetimepicker/datetimepicker/issues/543

Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
Button negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
Button neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);

int textColorPrimary = getDefaultDialogButtonTextColor(activityContext);
setTextColor(positiveButton, POSITIVE, args, needsColorOverride, textColorPrimary);
setTextColor(negativeButton, NEGATIVE, args, needsColorOverride, textColorPrimary);
setTextColor(neutralButton, NEUTRAL, args, needsColorOverride, textColorPrimary);
}
return dialogInterface -> {
// change text color only if custom color is set or if spinner mode is set
// because spinner suffers from https://github.com/react-native-datetimepicker/datetimepicker/issues/543

Button positiveButton = dialog.getButton(AlertDialog.BUTTON_POSITIVE);
Button negativeButton = dialog.getButton(AlertDialog.BUTTON_NEGATIVE);
Button neutralButton = dialog.getButton(AlertDialog.BUTTON_NEUTRAL);

int textColorPrimary = getDefaultDialogButtonTextColor(activityContext);
setTextColor(positiveButton, POSITIVE, args, needsColorOverride, textColorPrimary);
setTextColor(negativeButton, NEGATIVE, args, needsColorOverride, textColorPrimary);
setTextColor(neutralButton, NEUTRAL, args, needsColorOverride, textColorPrimary);
};
}

Expand Down Expand Up @@ -139,4 +144,65 @@ private static void setButtonLabel(Bundle buttonConfig, AlertDialog dialog, int
}
dialog.setButton(whichButton, buttonConfig.getString(LABEL), listener);
}

public static TimeZone getTimeZone(Bundle args) {
if (args != null && args.containsKey(RNConstants.ARG_TZOFFSET_MINS)) {
return new SimpleTimeZone(args.getInt(RNConstants.ARG_TZOFFSET_MINS) * 60 * 1000, "GMT");
}

if (args != null && args.containsKey(RNConstants.ARG_TZ_NAME)) {
String timeZoneName = args.getString(RNConstants.ARG_TZ_NAME);
if (TIMEZONE_IDS.contains(timeZoneName)) {
return TimeZone.getTimeZone(timeZoneName);
}
RNLog.w(null, "'" + timeZoneName + "' does not exist in TimeZone.getAvailableIDs() fallback to TimeZone.getDefault()=" + TimeZone.getDefault().getID());
}

return TimeZone.getDefault();
}

public static long clamp(final long value, final long min, final long max) {
return Math.min(Math.max(value, min), max);
}

public static long maxDateWithTimeZone(Bundle args) {
if (!args.containsKey(RNConstants.ARG_MAXDATE)) {
return Long.MAX_VALUE;
}

Calendar maxDate = Calendar.getInstance(getTimeZone(args));
maxDate.setTimeInMillis(args.getLong(RNConstants.ARG_MAXDATE));
maxDate.set(Calendar.HOUR_OF_DAY, 23);
maxDate.set(Calendar.MINUTE, 59);
maxDate.set(Calendar.SECOND, 59);
maxDate.set(Calendar.MILLISECOND, 999);
return maxDate.getTimeInMillis();
}

public static long minDateWithTimeZone(Bundle args) {
if (!args.containsKey(RNConstants.ARG_MINDATE)) {
return 0;
}

Calendar minDate = Calendar.getInstance(getTimeZone(args));
minDate.setTimeInMillis(args.getLong(RNConstants.ARG_MINDATE));
minDate.set(Calendar.HOUR_OF_DAY, 0);
minDate.set(Calendar.MINUTE, 0);
minDate.set(Calendar.SECOND, 0);
minDate.set(Calendar.MILLISECOND, 0);
return minDate.getTimeInMillis();
}

public static Bundle createFragmentArguments(ReadableMap options) {
final Bundle args = new Bundle();

if (options.hasKey(RNConstants.ARG_VALUE) && !options.isNull(RNConstants.ARG_VALUE)) {
args.putLong(RNConstants.ARG_VALUE, (long) options.getDouble(RNConstants.ARG_VALUE));
}
if (options.hasKey(RNConstants.ARG_TZ_NAME) && !options.isNull(RNConstants.ARG_TZ_NAME)) {
args.putString(RNConstants.ARG_TZ_NAME, options.getString(RNConstants.ARG_TZ_NAME));
}

return args;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
import com.facebook.react.module.annotations.ReactModule;

import static com.reactcommunity.rndatetimepicker.Common.dismissDialog;
import static com.reactcommunity.rndatetimepicker.KeepDateInRangeListener.isDateAfterMaxDate;
import static com.reactcommunity.rndatetimepicker.KeepDateInRangeListener.isDateBeforeMinDate;

import java.util.Calendar;

Expand All @@ -41,8 +39,9 @@ public DatePickerModule(ReactApplicationContext reactContext) {
super(reactContext);
}

@NonNull
@Override
public @NonNull String getName() {
public String getName() {
return NAME;
}

Expand All @@ -60,31 +59,15 @@ public DatePickerDialogListener(final Promise promise, Bundle arguments) {
@Override
public void onDateSet(DatePicker view, int year, int month, int day) {
if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) {
final RNDate date = new RNDate(mArgs);
Calendar calendar = Calendar.getInstance(Common.getTimeZone(mArgs));
calendar.set(year, month, day, date.hour(), date.minute(), 0);
calendar.set(Calendar.MILLISECOND, 0);

WritableMap result = new WritableNativeMap();
result.putString("action", RNConstants.ACTION_DATE_SET);
result.putInt("year", year);
result.putInt("month", month);
result.putInt("day", day);

// https://issuetracker.google.com/issues/169602180
// TODO revisit day, month, year with timezoneoffset fixes
if (isDateAfterMaxDate(mArgs, year, month, day)) {
Calendar maxDate = Calendar.getInstance();
maxDate.setTimeInMillis(mArgs.getLong(RNConstants.ARG_MAXDATE));

result.putInt("year", maxDate.get(Calendar.YEAR));
result.putInt("month", maxDate.get(Calendar.MONTH) );
result.putInt("day", maxDate.get(Calendar.DAY_OF_MONTH));
}

if (isDateBeforeMinDate(mArgs, year, month, day)) {
Calendar minDate = Calendar.getInstance();
minDate.setTimeInMillis(mArgs.getLong(RNConstants.ARG_MINDATE));

result.putInt("year", minDate.get(Calendar.YEAR));
result.putInt("month", minDate.get(Calendar.MONTH) );
result.putInt("day", minDate.get(Calendar.DAY_OF_MONTH));
}
result.putDouble("timestamp", calendar.getTimeInMillis());
result.putDouble("utcOffset", calendar.getTimeZone().getRawOffset() / 1000 / 60);

mPromise.resolve(result);
mPromiseResolved = true;
Expand Down Expand Up @@ -154,35 +137,32 @@ public void open(final ReadableMap options, final Promise promise) {

final FragmentManager fragmentManager = activity.getSupportFragmentManager();

UiThreadUtil.runOnUiThread(new Runnable() {
@Override
public void run() {
RNDatePickerDialogFragment oldFragment =
(RNDatePickerDialogFragment) fragmentManager.findFragmentByTag(NAME);
UiThreadUtil.runOnUiThread(() -> {
RNDatePickerDialogFragment oldFragment =
(RNDatePickerDialogFragment) fragmentManager.findFragmentByTag(NAME);

Bundle arguments = createFragmentArguments(options);

if (oldFragment != null) {
oldFragment.update(createFragmentArguments(options));
return;
}
if (oldFragment != null) {
oldFragment.update(arguments);
return;
}

RNDatePickerDialogFragment fragment = new RNDatePickerDialogFragment();
RNDatePickerDialogFragment fragment = new RNDatePickerDialogFragment();

fragment.setArguments(createFragmentArguments(options));
fragment.setArguments(arguments);

final DatePickerDialogListener listener = new DatePickerDialogListener(promise, createFragmentArguments(options));
fragment.setOnDismissListener(listener);
fragment.setOnDateSetListener(listener);
fragment.setOnNeutralButtonActionListener(listener);
fragment.show(fragmentManager, NAME);
}
final DatePickerDialogListener listener = new DatePickerDialogListener(promise, arguments);
fragment.setOnDismissListener(listener);
fragment.setOnDateSetListener(listener);
fragment.setOnNeutralButtonActionListener(listener);
fragment.show(fragmentManager, NAME);
});
}

private Bundle createFragmentArguments(ReadableMap options) {
final Bundle args = new Bundle();
if (options.hasKey(RNConstants.ARG_VALUE) && !options.isNull(RNConstants.ARG_VALUE)) {
args.putLong(RNConstants.ARG_VALUE, (long) options.getDouble(RNConstants.ARG_VALUE));
}
final Bundle args = Common.createFragmentArguments(options);

if (options.hasKey(RNConstants.ARG_MINDATE) && !options.isNull(RNConstants.ARG_MINDATE)) {
args.putLong(RNConstants.ARG_MINDATE, (long) options.getDouble(RNConstants.ARG_MINDATE));
}
Expand All @@ -195,9 +175,7 @@ private Bundle createFragmentArguments(ReadableMap options) {
if (options.hasKey(RNConstants.ARG_DIALOG_BUTTONS) && !options.isNull(RNConstants.ARG_DIALOG_BUTTONS)) {
args.putBundle(RNConstants.ARG_DIALOG_BUTTONS, Arguments.toBundle(options.getMap(RNConstants.ARG_DIALOG_BUTTONS)));
}
if (options.hasKey(RNConstants.ARG_TZOFFSET_MINS) && !options.isNull(RNConstants.ARG_TZOFFSET_MINS)) {
args.putLong(RNConstants.ARG_TZOFFSET_MINS, (long) options.getDouble(RNConstants.ARG_TZOFFSET_MINS));
}

return args;
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public final class RNConstants {
public static final String ARG_DISPLAY = "display";
public static final String ARG_DIALOG_BUTTONS = "dialogButtons";
public static final String ARG_TZOFFSET_MINS = "timeZoneOffsetInMinutes";
public static final String ARG_TZ_NAME = "timeZoneName";
public static final String ACTION_DATE_SET = "dateSetAction";
public static final String ACTION_TIME_SET = "timeSetAction";
public static final String ACTION_DISMISSED = "dismissedAction";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,11 @@ public RNDate(Bundle args) {
now = Calendar.getInstance();

if (args != null && args.containsKey(RNConstants.ARG_VALUE)) {
set(args.getLong(RNConstants.ARG_VALUE));
now.setTimeInMillis((args.getLong(RNConstants.ARG_VALUE)));
}

if (args != null && args.containsKey(RNConstants.ARG_TZOFFSET_MINS)) {
now.setTimeZone(TimeZone.getTimeZone("GMT"));
Long timeZoneOffsetInMinutesFallback = args.getLong(RNConstants.ARG_TZOFFSET_MINS);
Integer timeZoneOffsetInMinutes = args.getInt(RNConstants.ARG_TZOFFSET_MINS, timeZoneOffsetInMinutesFallback.intValue());
now.add(Calendar.MILLISECOND, timeZoneOffsetInMinutes * 60000);
}
}

public void set(long value) {
now.setTimeInMillis(value);
now.setTimeZone(Common.getTimeZone(args));
}

public int year() { return now.get(Calendar.YEAR); }
Expand Down
Loading

0 comments on commit 5a9d512

Please sign in to comment.