mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Remove DatePickerAndroid from react-native-github
Summary: Changelog: [JavaScript][Removed] - Remove DatePickerAndroid from React Native Reviewed By: lunaleaps, yungsters Differential Revision: D30281952 fbshipit-source-id: 5cd0ad2ad741afeef3e6f8a39635c6baf4b79b38
This commit is contained in:
committed by
Facebook GitHub Bot
parent
25c5d194ad
commit
7a770526c6
@@ -1,27 +0,0 @@
|
||||
load("//tools/build_defs/oss:rn_defs.bzl", "react_native_dep", "react_native_root_target", "react_native_target", "rn_android_library")
|
||||
|
||||
rn_android_library(
|
||||
name = "datepicker",
|
||||
srcs = glob(["**/*.java"]),
|
||||
autoglob = False,
|
||||
is_androidx = True,
|
||||
labels = ["supermodule:xplat/default/public.react_native.infra"],
|
||||
provided_deps = [
|
||||
react_native_dep("third-party/android/androidx:annotation"),
|
||||
react_native_dep("third-party/android/androidx:core"),
|
||||
react_native_dep("third-party/android/androidx:fragment"),
|
||||
react_native_dep("third-party/android/androidx:legacy-support-core-ui"),
|
||||
react_native_dep("third-party/android/androidx:legacy-support-core-utils"),
|
||||
],
|
||||
visibility = [
|
||||
"PUBLIC",
|
||||
],
|
||||
deps = [
|
||||
react_native_dep("third-party/java/infer-annotations:infer-annotations"),
|
||||
react_native_dep("third-party/java/jsr-305:jsr-305"),
|
||||
react_native_target("java/com/facebook/react/bridge:bridge"),
|
||||
react_native_target("java/com/facebook/react/common:common"),
|
||||
react_native_target("java/com/facebook/react/module/annotations:annotations"),
|
||||
],
|
||||
exported_deps = [react_native_root_target(":FBReactNativeSpec")],
|
||||
)
|
||||
-137
@@ -1,137 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.modules.datepicker;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.app.DatePickerDialog;
|
||||
import android.app.DatePickerDialog.OnDateSetListener;
|
||||
import android.app.Dialog;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnDismissListener;
|
||||
import android.graphics.drawable.ColorDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.widget.DatePicker;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
|
||||
@SuppressLint("ValidFragment")
|
||||
public class DatePickerDialogFragment extends DialogFragment {
|
||||
|
||||
/** Minimum date supported by {@link DatePicker}, 01 Jan 1900 */
|
||||
private static final long DEFAULT_MIN_DATE = -2208988800001l;
|
||||
|
||||
@Nullable private OnDateSetListener mOnDateSetListener;
|
||||
@Nullable private OnDismissListener mOnDismissListener;
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle savedInstanceState) {
|
||||
Bundle args = getArguments();
|
||||
return createDialog(args, getActivity(), mOnDateSetListener);
|
||||
}
|
||||
|
||||
/*package*/ static Dialog createDialog(
|
||||
Bundle args, Context activityContext, @Nullable OnDateSetListener onDateSetListener) {
|
||||
final Calendar c = Calendar.getInstance();
|
||||
if (args != null && args.containsKey(DatePickerDialogModule.ARG_DATE)) {
|
||||
c.setTimeInMillis(args.getLong(DatePickerDialogModule.ARG_DATE));
|
||||
}
|
||||
final int year = c.get(Calendar.YEAR);
|
||||
final int month = c.get(Calendar.MONTH);
|
||||
final int day = c.get(Calendar.DAY_OF_MONTH);
|
||||
|
||||
DatePickerMode mode = DatePickerMode.DEFAULT;
|
||||
if (args != null && args.getString(DatePickerDialogModule.ARG_MODE, null) != null) {
|
||||
mode =
|
||||
DatePickerMode.valueOf(
|
||||
args.getString(DatePickerDialogModule.ARG_MODE).toUpperCase(Locale.US));
|
||||
}
|
||||
|
||||
DatePickerDialog dialog = null;
|
||||
|
||||
switch (mode) {
|
||||
case CALENDAR:
|
||||
dialog =
|
||||
new DismissableDatePickerDialog(
|
||||
activityContext,
|
||||
activityContext
|
||||
.getResources()
|
||||
.getIdentifier(
|
||||
"CalendarDatePickerDialog", "style", activityContext.getPackageName()),
|
||||
onDateSetListener,
|
||||
year,
|
||||
month,
|
||||
day);
|
||||
break;
|
||||
case SPINNER:
|
||||
dialog =
|
||||
new DismissableDatePickerDialog(
|
||||
activityContext,
|
||||
android.R.style.Theme_Holo_Light_Dialog,
|
||||
onDateSetListener,
|
||||
year,
|
||||
month,
|
||||
day);
|
||||
dialog
|
||||
.getWindow()
|
||||
.setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
|
||||
break;
|
||||
case DEFAULT:
|
||||
dialog =
|
||||
new DismissableDatePickerDialog(activityContext, onDateSetListener, year, month, day);
|
||||
break;
|
||||
}
|
||||
|
||||
final DatePicker datePicker = dialog.getDatePicker();
|
||||
|
||||
if (args != null && args.containsKey(DatePickerDialogModule.ARG_MINDATE)) {
|
||||
// Set minDate to the beginning of the day. We need this because of clowniness in datepicker
|
||||
// that causes it to throw an exception if minDate is greater than the internal timestamp
|
||||
// that it generates from the y/m/d passed in the constructor.
|
||||
c.setTimeInMillis(args.getLong(DatePickerDialogModule.ARG_MINDATE));
|
||||
c.set(Calendar.HOUR_OF_DAY, 0);
|
||||
c.set(Calendar.MINUTE, 0);
|
||||
c.set(Calendar.SECOND, 0);
|
||||
c.set(Calendar.MILLISECOND, 0);
|
||||
datePicker.setMinDate(c.getTimeInMillis());
|
||||
} else {
|
||||
// This is to work around a bug in DatePickerDialog where it doesn't display a title showing
|
||||
// the date under certain conditions.
|
||||
datePicker.setMinDate(DEFAULT_MIN_DATE);
|
||||
}
|
||||
if (args != null && args.containsKey(DatePickerDialogModule.ARG_MAXDATE)) {
|
||||
// Set maxDate to the end of the day, same reason as for minDate.
|
||||
c.setTimeInMillis(args.getLong(DatePickerDialogModule.ARG_MAXDATE));
|
||||
c.set(Calendar.HOUR_OF_DAY, 23);
|
||||
c.set(Calendar.MINUTE, 59);
|
||||
c.set(Calendar.SECOND, 59);
|
||||
c.set(Calendar.MILLISECOND, 999);
|
||||
datePicker.setMaxDate(c.getTimeInMillis());
|
||||
}
|
||||
|
||||
return dialog;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
super.onDismiss(dialog);
|
||||
if (mOnDismissListener != null) {
|
||||
mOnDismissListener.onDismiss(dialog);
|
||||
}
|
||||
}
|
||||
|
||||
/*package*/ void setOnDateSetListener(@Nullable OnDateSetListener onDateSetListener) {
|
||||
mOnDateSetListener = onDateSetListener;
|
||||
}
|
||||
|
||||
/*package*/ void setOnDismissListener(@Nullable OnDismissListener onDismissListener) {
|
||||
mOnDismissListener = onDismissListener;
|
||||
}
|
||||
}
|
||||
-153
@@ -1,153 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.modules.datepicker;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.DatePickerDialog.OnDateSetListener;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnDismissListener;
|
||||
import android.os.Bundle;
|
||||
import android.widget.DatePicker;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.fragment.app.DialogFragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
import com.facebook.fbreact.specs.NativeDatePickerAndroidSpec;
|
||||
import com.facebook.react.bridge.*;
|
||||
import com.facebook.react.common.annotations.VisibleForTesting;
|
||||
import com.facebook.react.module.annotations.ReactModule;
|
||||
|
||||
/**
|
||||
* {@link NativeModule} that allows JS to show a native date picker dialog and get called back when
|
||||
* the user selects a date.
|
||||
*/
|
||||
@ReactModule(name = DatePickerDialogModule.FRAGMENT_TAG)
|
||||
public class DatePickerDialogModule extends NativeDatePickerAndroidSpec {
|
||||
|
||||
@VisibleForTesting public static final String FRAGMENT_TAG = "DatePickerAndroid";
|
||||
|
||||
private static final String ERROR_NO_ACTIVITY = "E_NO_ACTIVITY";
|
||||
|
||||
/* package */ static final String ARG_DATE = "date";
|
||||
/* package */ static final String ARG_MINDATE = "minDate";
|
||||
/* package */ static final String ARG_MAXDATE = "maxDate";
|
||||
/* package */ static final String ARG_MODE = "mode";
|
||||
|
||||
/* package */ static final String ACTION_DATE_SET = "dateSetAction";
|
||||
/* package */ static final String ACTION_DISMISSED = "dismissedAction";
|
||||
|
||||
public DatePickerDialogModule(ReactApplicationContext reactContext) {
|
||||
super(reactContext);
|
||||
}
|
||||
|
||||
public @NonNull String getName() {
|
||||
return DatePickerDialogModule.FRAGMENT_TAG;
|
||||
}
|
||||
|
||||
private class DatePickerDialogListener implements OnDateSetListener, OnDismissListener {
|
||||
|
||||
private final Promise mPromise;
|
||||
private boolean mPromiseResolved = false;
|
||||
|
||||
public DatePickerDialogListener(final Promise promise) {
|
||||
mPromise = promise;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDateSet(DatePicker view, int year, int month, int day) {
|
||||
if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) {
|
||||
WritableMap result = new WritableNativeMap();
|
||||
result.putString("action", ACTION_DATE_SET);
|
||||
result.putInt("year", year);
|
||||
result.putInt("month", month);
|
||||
result.putInt("day", day);
|
||||
mPromise.resolve(result);
|
||||
mPromiseResolved = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDismiss(DialogInterface dialog) {
|
||||
if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) {
|
||||
WritableMap result = new WritableNativeMap();
|
||||
result.putString("action", ACTION_DISMISSED);
|
||||
mPromise.resolve(result);
|
||||
mPromiseResolved = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a date picker dialog.
|
||||
*
|
||||
* @param options a map containing options. Available keys are:
|
||||
* <ul>
|
||||
* <li>{@code date} (timestamp in milliseconds) the date to show by default
|
||||
* <li>{@code minDate} (timestamp in milliseconds) the minimum date the user should be
|
||||
* allowed to select
|
||||
* <li>{@code maxDate} (timestamp in milliseconds) the maximum date the user should be
|
||||
* allowed to select
|
||||
* <li>{@code mode} To set the date picker mode to 'calendar/spinner/default'
|
||||
* </ul>
|
||||
*
|
||||
* @param promise This will be invoked with parameters action, year, month (0-11), day, where
|
||||
* action is {@code dateSetAction} or {@code dismissedAction}, depending on what the user did.
|
||||
* If the action is dismiss, year, month and date are undefined.
|
||||
*/
|
||||
@Override
|
||||
public void open(@Nullable final ReadableMap options, final Promise promise) {
|
||||
Activity raw_activity = getCurrentActivity();
|
||||
if (raw_activity == null || !(raw_activity instanceof FragmentActivity)) {
|
||||
promise.reject(
|
||||
ERROR_NO_ACTIVITY,
|
||||
"Tried to open a DatePicker dialog while not attached to a FragmentActivity");
|
||||
return;
|
||||
}
|
||||
|
||||
FragmentActivity activity = (FragmentActivity) raw_activity;
|
||||
|
||||
final FragmentManager fragmentManager = activity.getSupportFragmentManager();
|
||||
DialogFragment oldFragment = (DialogFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG);
|
||||
if (oldFragment != null) {
|
||||
oldFragment.dismiss();
|
||||
}
|
||||
activity.runOnUiThread(
|
||||
new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
DatePickerDialogFragment fragment = new DatePickerDialogFragment();
|
||||
if (options != null) {
|
||||
final Bundle args = createFragmentArguments(options);
|
||||
fragment.setArguments(args);
|
||||
}
|
||||
final DatePickerDialogListener listener = new DatePickerDialogListener(promise);
|
||||
fragment.setOnDismissListener(listener);
|
||||
fragment.setOnDateSetListener(listener);
|
||||
fragment.show(fragmentManager, FRAGMENT_TAG);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private Bundle createFragmentArguments(ReadableMap options) {
|
||||
final Bundle args = new Bundle();
|
||||
if (options.hasKey(ARG_DATE) && !options.isNull(ARG_DATE)) {
|
||||
args.putLong(ARG_DATE, (long) options.getDouble(ARG_DATE));
|
||||
}
|
||||
if (options.hasKey(ARG_MINDATE) && !options.isNull(ARG_MINDATE)) {
|
||||
args.putLong(ARG_MINDATE, (long) options.getDouble(ARG_MINDATE));
|
||||
}
|
||||
if (options.hasKey(ARG_MAXDATE) && !options.isNull(ARG_MAXDATE)) {
|
||||
args.putLong(ARG_MAXDATE, (long) options.getDouble(ARG_MAXDATE));
|
||||
}
|
||||
if (options.hasKey(ARG_MODE) && !options.isNull(ARG_MODE)) {
|
||||
args.putString(ARG_MODE, options.getString(ARG_MODE));
|
||||
}
|
||||
return args;
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.modules.datepicker;
|
||||
|
||||
/** Date picker modes */
|
||||
public enum DatePickerMode {
|
||||
CALENDAR,
|
||||
SPINNER,
|
||||
DEFAULT
|
||||
}
|
||||
-117
@@ -1,117 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.react.modules.datepicker;
|
||||
|
||||
import android.app.DatePickerDialog;
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.DatePicker;
|
||||
import androidx.annotation.Nullable;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class DismissableDatePickerDialog extends DatePickerDialog {
|
||||
|
||||
public DismissableDatePickerDialog(
|
||||
Context context,
|
||||
@Nullable DatePickerDialog.OnDateSetListener callback,
|
||||
int year,
|
||||
int monthOfYear,
|
||||
int dayOfMonth) {
|
||||
super(context, callback, year, monthOfYear, dayOfMonth);
|
||||
fixSpinner(context, year, monthOfYear, dayOfMonth);
|
||||
}
|
||||
|
||||
public DismissableDatePickerDialog(
|
||||
Context context,
|
||||
int theme,
|
||||
@Nullable DatePickerDialog.OnDateSetListener callback,
|
||||
int year,
|
||||
int monthOfYear,
|
||||
int dayOfMonth) {
|
||||
super(context, theme, callback, year, monthOfYear, dayOfMonth);
|
||||
fixSpinner(context, year, monthOfYear, dayOfMonth);
|
||||
}
|
||||
|
||||
private void fixSpinner(Context context, int year, int month, int dayOfMonth) {
|
||||
if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N) {
|
||||
try {
|
||||
// Get the theme's android:datePickerMode
|
||||
final int MODE_SPINNER = 2;
|
||||
Class<?> styleableClass = Class.forName("com.android.internal.R$styleable");
|
||||
Field datePickerStyleableField = styleableClass.getField("DatePicker");
|
||||
int[] datePickerStyleable = (int[]) datePickerStyleableField.get(null);
|
||||
|
||||
final TypedArray a =
|
||||
context.obtainStyledAttributes(
|
||||
null, datePickerStyleable, android.R.attr.datePickerStyle, 0);
|
||||
Field datePickerModeStyleableField = styleableClass.getField("DatePicker_datePickerMode");
|
||||
int datePickerModeStyleable = datePickerModeStyleableField.getInt(null);
|
||||
final int mode = a.getInt(datePickerModeStyleable, MODE_SPINNER);
|
||||
a.recycle();
|
||||
|
||||
if (mode == MODE_SPINNER) {
|
||||
DatePicker datePicker =
|
||||
(DatePicker)
|
||||
findField(DatePickerDialog.class, DatePicker.class, "mDatePicker").get(this);
|
||||
Class<?> delegateClass = Class.forName("android.widget.DatePickerSpinnerDelegate");
|
||||
Field delegateField = findField(DatePicker.class, delegateClass, "mDelegate");
|
||||
Object delegate = delegateField.get(datePicker);
|
||||
Class<?> spinnerDelegateClass;
|
||||
spinnerDelegateClass = Class.forName("android.widget.DatePickerSpinnerDelegate");
|
||||
|
||||
// In 7.0 Nougat for some reason the datePickerMode is ignored and the delegate is
|
||||
// DatePickerClockDelegate
|
||||
if (delegate.getClass() != spinnerDelegateClass) {
|
||||
delegateField.set(datePicker, null); // throw out the DatePickerClockDelegate!
|
||||
datePicker.removeAllViews(); // remove the DatePickerClockDelegate views
|
||||
Method createSpinnerUIDelegate =
|
||||
DatePicker.class.getDeclaredMethod(
|
||||
"createSpinnerUIDelegate",
|
||||
Context.class,
|
||||
AttributeSet.class,
|
||||
int.class,
|
||||
int.class);
|
||||
createSpinnerUIDelegate.setAccessible(true);
|
||||
|
||||
// Instantiate a DatePickerSpinnerDelegate throughout createSpinnerUIDelegate method
|
||||
delegate =
|
||||
createSpinnerUIDelegate.invoke(
|
||||
datePicker, context, null, android.R.attr.datePickerStyle, 0);
|
||||
delegateField.set(
|
||||
datePicker, delegate); // set the DatePicker.mDelegate to the spinner delegate
|
||||
datePicker.setCalendarViewShown(false);
|
||||
// Initialize the date for the DatePicker delegate again
|
||||
datePicker.init(year, month, dayOfMonth, this);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Field findField(Class objectClass, Class fieldClass, String expectedName) {
|
||||
try {
|
||||
Field field = objectClass.getDeclaredField(expectedName);
|
||||
field.setAccessible(true);
|
||||
return field;
|
||||
} catch (NoSuchFieldException e) {
|
||||
} // ignore
|
||||
// search for it if it wasn't found under the expected ivar name
|
||||
for (Field searchField : objectClass.getDeclaredFields()) {
|
||||
if (searchField.getType() == fieldClass) {
|
||||
searchField.setAccessible(true);
|
||||
return searchField;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,6 @@ rn_android_library(
|
||||
react_native_target("java/com/facebook/react/modules/camera:camera"),
|
||||
react_native_target("java/com/facebook/react/modules/clipboard:clipboard"),
|
||||
react_native_target("java/com/facebook/react/modules/core:core"),
|
||||
react_native_target("java/com/facebook/react/modules/datepicker:datepicker"),
|
||||
react_native_target("java/com/facebook/react/modules/debug:debug"),
|
||||
react_native_target("java/com/facebook/react/modules/dialog:dialog"),
|
||||
react_native_target("java/com/facebook/react/modules/fresco:fresco"),
|
||||
|
||||
@@ -23,7 +23,6 @@ import com.facebook.react.modules.blob.BlobModule;
|
||||
import com.facebook.react.modules.blob.FileReaderModule;
|
||||
import com.facebook.react.modules.camera.ImageStoreManager;
|
||||
import com.facebook.react.modules.clipboard.ClipboardModule;
|
||||
import com.facebook.react.modules.datepicker.DatePickerDialogModule;
|
||||
import com.facebook.react.modules.dialog.DialogModule;
|
||||
import com.facebook.react.modules.fresco.FrescoModule;
|
||||
import com.facebook.react.modules.i18nmanager.I18nManagerModule;
|
||||
@@ -72,7 +71,6 @@ import java.util.Map;
|
||||
FileReaderModule.class,
|
||||
AsyncStorageModule.class,
|
||||
ClipboardModule.class,
|
||||
DatePickerDialogModule.class,
|
||||
DialogModule.class,
|
||||
FrescoModule.class,
|
||||
I18nManagerModule.class,
|
||||
@@ -117,8 +115,6 @@ public class MainReactPackage extends TurboReactPackage {
|
||||
return new AsyncStorageModule(context);
|
||||
case ClipboardModule.NAME:
|
||||
return new ClipboardModule(context);
|
||||
case DatePickerDialogModule.FRAGMENT_TAG:
|
||||
return new DatePickerDialogModule(context);
|
||||
case DialogModule.NAME:
|
||||
return new DialogModule(context);
|
||||
case FrescoModule.NAME:
|
||||
@@ -199,7 +195,6 @@ public class MainReactPackage extends TurboReactPackage {
|
||||
FileReaderModule.class,
|
||||
AsyncStorageModule.class,
|
||||
ClipboardModule.class,
|
||||
DatePickerDialogModule.class,
|
||||
DialogModule.class,
|
||||
FrescoModule.class,
|
||||
I18nManagerModule.class,
|
||||
|
||||
Reference in New Issue
Block a user