com.facebook.react.modules.datepicker.DatePickerDialogModule.java Source code

Java tutorial

Introduction

Here is the source code for com.facebook.react.modules.datepicker.DatePickerDialogModule.java

Source

/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the BSD-style license found in the
 * LICENSE file in the root directory of this source tree. An additional grant
 * of patent rights can be found in the PATENTS file in the same directory.
 */

package com.facebook.react.modules.datepicker;

import javax.annotation.Nullable;

import java.util.Map;

import android.app.Activity;
import android.app.DatePickerDialog.OnDateSetListener;
import android.app.DialogFragment;
import android.app.FragmentManager;
import android.content.DialogInterface;
import android.content.DialogInterface.OnDismissListener;
import android.os.Bundle;
import android.widget.DatePicker;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.common.annotations.VisibleForTesting;

/**
 * {@link NativeModule} that allows JS to show a native date picker dialog and get called back when
 * the user selects a date.
 */
public class DatePickerDialogModule extends ReactContextBaseJavaModule {

    @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 ACTION_DATE_SET = "dateSetAction";
    /* package */ static final String ACTION_DISMISSED = "dismissedAction";

    public DatePickerDialogModule(ReactApplicationContext reactContext) {
        super(reactContext);
    }

    @Override
    public String getName() {
        return "DatePickerAndroid";
    }

    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().hasActiveCatalystInstance()) {
                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().hasActiveCatalystInstance()) {
                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>
     *   <li>
     *     {@code minDate} (timestamp in milliseconds) the minimum date the user should be allowed
     *     to select
     *   </li>
     *   <li>
     *     {@code maxDate} (timestamp in milliseconds) the maximum date the user should be allowed
     *     to select
     *    </li>
     * </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.
     */
    @ReactMethod
    public void open(@Nullable final ReadableMap options, Promise promise) {
        Activity activity = getCurrentActivity();
        if (activity == null) {
            promise.reject(ERROR_NO_ACTIVITY,
                    "Tried to open a DatePicker dialog while not attached to an Activity");
            return;
        }
        // We want to support both android.app.Activity and the pre-Honeycomb FragmentActivity
        // (for apps that use it for legacy reasons). This unfortunately leads to some code duplication.
        if (activity instanceof android.support.v4.app.FragmentActivity) {
            android.support.v4.app.FragmentManager fragmentManager = ((android.support.v4.app.FragmentActivity) activity)
                    .getSupportFragmentManager();
            android.support.v4.app.DialogFragment oldFragment = (android.support.v4.app.DialogFragment) fragmentManager
                    .findFragmentByTag(FRAGMENT_TAG);
            if (oldFragment != null) {
                oldFragment.dismiss();
            }
            SupportDatePickerDialogFragment fragment = new SupportDatePickerDialogFragment();
            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);
        } else {
            FragmentManager fragmentManager = activity.getFragmentManager();
            DialogFragment oldFragment = (DialogFragment) fragmentManager.findFragmentByTag(FRAGMENT_TAG);
            if (oldFragment != null) {
                oldFragment.dismiss();
            }
            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));
        }
        return args;
    }
}