diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index f284f5758b65d6e7f05766c90a6ad163f1fe5bf8..0000000000000000000000000000000000000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,204 +0,0 @@ -version: 2.1 - -orbs: - rn: react-native-community/react-native@7 - android: circleci/android@2 - -# - rn/yarn_install -# fails with Error untarring cache: Error extracting tarball /var/folders/bq/mjrgbpkx5h1g_b22fpv0tlzc0000gn/T/cache376822577 : tmp/yarn/: Cannot extract through symlink tmp/yarn tmp/yarn/v6/: Cannot extract through symlink tmp/yarn/v6 tmp/yarn/v6/.tmp/: Cannot extract through symlink tmp/yarn/v6/.tmp tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/: Cannot extract through symlink tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules/: Cannot extract through symlink tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules/@babel/: Cannot extract through symlink tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules/@babel tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules/@babel/code-frame/: Cannot extract: exit status 1 -# that is why we use yarn install --frozen-lockfile but that is SLOW! help us to fix this! - -jobs: - analyse_js: - executor: - name: rn/linux_js - node_version: 'lts' - steps: - - checkout - # - rn/yarn_install - # fails with Error untarring cache: Error extracting tarball /var/folders/bq/mjrgbpkx5h1g_b22fpv0tlzc0000gn/T/cache376822577 : tmp/yarn/: Cannot extract through symlink tmp/yarn tmp/yarn/v6/: Cannot extract through symlink tmp/yarn/v6 tmp/yarn/v6/.tmp/: Cannot extract through symlink tmp/yarn/v6/.tmp tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/: Cannot extract through symlink tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules/: Cannot extract through symlink tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules/@babel/: Cannot extract through symlink tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules/@babel tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules/@babel/code-frame/: Cannot extract: exit status 1 - - run: - command: yarn install --frozen-lockfile - name: yarn install - - run: - command: yarn lint - name: Run ESLint - - run: - command: yarn flow - name: Flow - - run: - command: yarn test - name: Jest - - new_arch_ios_build_only: - executor: - name: rn/macos - xcode_version: '15.0.0' - steps: - - checkout - - run: - command: yarn install --frozen-lockfile - name: yarn install - - run: - command: (cd example && RCT_NEW_ARCH_ENABLED=1 npx pod-install) - name: pod install - - run: - command: yarn detox:ios:build:release - name: build app with new arch - - - e2e_release_ios: - executor: - name: rn/macos - xcode_version: '15.0.0' - steps: - - checkout - - run: - name: install applesimutils - command: | - HOMEBREW_NO_INSTALL_CLEANUP=1 HOMEBREW_NO_AUTO_UPDATE=1 brew tap wix/brew >/dev/null - HOMEBREW_NO_INSTALL_CLEANUP=1 HOMEBREW_NO_AUTO_UPDATE=1 brew install applesimutils >/dev/null - - rn/ios_simulator_start: - device: 'iPhone 14' - # - rn/yarn_install - - run: - command: yarn install --frozen-lockfile && npx patch-package - name: yarn install - - run: - command: yarn bundle:ios - name: bundle js -# - rn/pod_install: -# pod_install_directory: 'example/ios' - - run: - command: (cd example && npx pod-install) - name: pod install - - run: - command: yarn detox:ios:build:release - name: build app for e2e tests - - run: - command: yarn detox:ios:test:release - name: run e2e tests - - store_artifacts: - path: ./artifacts - - e2e_release_android: - executor: - name: android/android-machine - resource-class: large - tag: '2023.04.1' - steps: - - checkout - - run: - command: avdmanager list - name: list avds - - run: - command: sdkmanager --list - name: list sdks - - android/create-avd: - avd-name: TestingAVD - system-image: system-images;android-29;default;x86 - additional-args: --device pixel_3_xl - install: true - background: false - - android/start-emulator: - avd-name: TestingAVD - no-window: true - wait-for-emulator: true - disable-animations: true - restore-gradle-cache-post-emulator-launch: false - post-emulator-launch-assemble-command: "pwd" - # - android/disable-animations - - run: - command: npm install --global yarn - name: install yarn - - run: - command: yarn install --frozen-lockfile && npx patch-package - name: yarn install - - run: - command: yarn bundle:android - name: bundle js - - run: - command: ORG_GRADLE_PROJECT_newArchEnabled=false yarn detox:android:build:release - name: build app for e2e tests - - run: - command: yarn detox:android:test:release - name: run e2e tests - - store_artifacts: - path: ./artifacts - - - e2e_release_android_new_arch: - executor: - name: android/android-machine - resource-class: large - tag: '2023.04.1' - steps: - - checkout - - run: - command: avdmanager list - name: list avds - - android/create-avd: - avd-name: TestingAVD - system-image: system-images;android-29;default;x86 - additional-args: --device pixel_3_xl - install: true - background: false - - android/start-emulator: - avd-name: TestingAVD - no-window: true - wait-for-emulator: true - disable-animations: true - restore-gradle-cache-post-emulator-launch: false - post-emulator-launch-assemble-command: "pwd" - - run: - command: npm install --global yarn - name: install yarn - - run: - command: yarn install --frozen-lockfile && npx patch-package - name: yarn install - - run: - command: yarn bundle:android - name: bundle js - - run: - command: ORG_GRADLE_PROJECT_newArchEnabled=true yarn detox:android:build:release - name: build app for e2e tests - # - android/wait-for-emulator - # - android/disable-animations - - run: - command: yarn detox:android:test:release - name: run e2e tests - - store_artifacts: - path: ./artifacts - - publish: - executor: - name: rn/linux_js - node_version: 'lts' - steps: - - checkout - # - rn/yarn_install - # fails with Error untarring cache: Error extracting tarball /var/folders/bq/mjrgbpkx5h1g_b22fpv0tlzc0000gn/T/cache376822577 : tmp/yarn/: Cannot extract through symlink tmp/yarn tmp/yarn/v6/: Cannot extract through symlink tmp/yarn/v6 tmp/yarn/v6/.tmp/: Cannot extract through symlink tmp/yarn/v6/.tmp tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/: Cannot extract through symlink tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules/: Cannot extract through symlink tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules/@babel/: Cannot extract through symlink tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules/@babel tmp/yarn/v6/npm-@babel-code-frame-7.8.3-33e25903d7481181534e12ec0a25f16b6fcf419e-integrity/node_modules/@babel/code-frame/: Cannot extract: exit status 1 - - run: - command: yarn install --frozen-lockfile - name: yarn install - - run: - command: npx semantic-release - name: Publish to NPM - -workflows: - test: - jobs: - - analyse_js - - e2e_release_ios - - e2e_release_android - - e2e_release_android_new_arch - - new_arch_ios_build_only - - publish: - requires: - - e2e_release_android - - e2e_release_android_new_arch - - e2e_release_ios - - new_arch_ios_build_only - filters: - branches: - only: master diff --git a/RNDateTimePicker.podspec b/RNDateTimePicker.podspec deleted file mode 100644 index a6473fb5d235ba1dad51788996ea6800da27d97c..0000000000000000000000000000000000000000 --- a/RNDateTimePicker.podspec +++ /dev/null @@ -1,25 +0,0 @@ -require 'json' - -package = JSON.parse(File.read(File.join(__dir__, 'package.json'))) - -Pod::Spec.new do |s| - s.name = "RNDateTimePicker" - s.version = package['version'] - s.summary = package['description'] - s.description = package['description'] - s.license = package['license'] - s.author = package['author'] - s.homepage = package['homepage'] - s.platform = :ios, "11.0" - s.source = { :git => "https://github.com/react-native-community/datetimepicker", :tag => "v#{s.version}" } - s.source_files = "ios/**/*.{h,m,mm,cpp}" - s.requires_arc = true - - if ENV['RCT_NEW_ARCH_ENABLED'] == '1' - install_modules_dependencies(s) - else - s.exclude_files = "ios/fabric" - - s.dependency "React-Core" - end -end diff --git a/android/build.gradle b/android/build.gradle deleted file mode 100644 index 20cc6954eafd00485dfa4387b0d2d603c27d9405..0000000000000000000000000000000000000000 --- a/android/build.gradle +++ /dev/null @@ -1,67 +0,0 @@ -buildscript { - repositories { - google() - mavenCentral() - } -} - -def getExtOrIntegerDefault(name) { - return rootProject.ext.has(name) ? rootProject.ext.get(name) : (project.properties['ReactNativeDateTimePicker_' + name]).toInteger() -} - -def isNewArchitectureEnabled() { - // To opt-in for the New Architecture, you can either: - // - Set `newArchEnabled` to true inside the `gradle.properties` file - // - Invoke gradle with `-newArchEnabled=true` - // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true` - return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true" -} - -apply plugin: 'com.android.library' -if (isNewArchitectureEnabled()) { - apply plugin: "com.facebook.react" -} - - -android { - def agpVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION - if (agpVersion.tokenize('.')[0].toInteger() >= 7) { - namespace "com.reactcommunity.rndatetimepicker" - } - - compileSdkVersion getExtOrIntegerDefault('compileSdkVersion') - - // Used to override the NDK path/version on internal CI or by allowing - // users to customize the NDK path/version from their root project (e.g. for M1 support) - if (rootProject.hasProperty("ndkPath")) { - ndkPath rootProject.ext.ndkPath - } - if (rootProject.hasProperty("ndkVersion")) { - ndkVersion rootProject.ext.ndkVersion - } - - defaultConfig { - minSdkVersion getExtOrIntegerDefault('minSdkVersion') - targetSdkVersion getExtOrIntegerDefault('targetSdkVersion') - buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() - } - - sourceSets.main { - java { - if (!isNewArchitectureEnabled()) { - srcDirs += 'src/paper/java' - } - } - } -} - -repositories { - google() - mavenLocal() - mavenCentral() -} - -dependencies { - //noinspection GradleDynamicVersion - implementation 'com.facebook.react:react-native:+' -} diff --git a/android/src/main/AndroidManifest.xml b/android/src/main/AndroidManifest.xml deleted file mode 100644 index 714a9345b25e931c538694eef5bc3c4d73b6e25e..0000000000000000000000000000000000000000 --- a/android/src/main/AndroidManifest.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/Common.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/Common.java deleted file mode 100644 index 9effd097496024d13828b472cca93a29c244adc1..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/Common.java +++ /dev/null @@ -1,205 +0,0 @@ -package com.reactcommunity.rndatetimepicker; - -import android.app.AlertDialog; -import android.content.Context; -import android.content.DialogInterface; -import android.content.res.Resources; -import android.graphics.Color; -import android.os.Bundle; -import android.util.TypedValue; -import android.widget.Button; - -import androidx.annotation.ColorInt; -import androidx.annotation.ColorRes; -import androidx.annotation.NonNull; -import androidx.core.content.ContextCompat; -import androidx.fragment.app.DialogFragment; -import androidx.fragment.app.FragmentActivity; -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 { - - public static final String POSITIVE = "positive"; - public static final String NEUTRAL = "neutral"; - public static final String NEGATIVE = "negative"; - public static final String LABEL = "label"; - public static final String TEXT_COLOR = "textColor"; - - public static void dismissDialog(FragmentActivity activity, String fragmentTag, Promise promise) { - if (activity == null) { - promise.reject( - RNConstants.ERROR_NO_ACTIVITY, - "Tried to close a " + fragmentTag + " dialog while not attached to an Activity"); - return; - } - - try { - FragmentManager fragmentManager = activity.getSupportFragmentManager(); - final DialogFragment oldFragment = (DialogFragment) fragmentManager.findFragmentByTag(fragmentTag); - - boolean fragmentFound = oldFragment != null; - if (fragmentFound) { - oldFragment.dismiss(); - } - - promise.resolve(fragmentFound); - } catch (Exception e) { - promise.reject(e); - } - } - - public static int getDefaultDialogButtonTextColor(@NonNull Context activity) { - TypedValue typedValue = new TypedValue(); - Resources.Theme theme = activity.getTheme(); - theme.resolveAttribute(android.R.attr.textColorPrimary, typedValue, true); - @ColorRes int colorRes = (typedValue.resourceId != 0) ? typedValue.resourceId : typedValue.data; - @ColorInt int colorId = ContextCompat.getColor(activity, colorRes); - return colorId; - } - - @NonNull - public static DialogInterface.OnShowListener setButtonTextColor(@NonNull final Context activityContext, final AlertDialog dialog, final Bundle args, final boolean needsColorOverride) { - 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); - }; - } - - private static void setTextColor(Button button, String buttonKey, final Bundle args, final boolean needsColorOverride, int textColorPrimary) { - if (button == null) return; - - Integer color = getButtonColor(args, buttonKey); - if (needsColorOverride || color != null) { - button.setTextColor(color != null ? color : textColorPrimary); - } - } - - private static Integer getButtonColor(final Bundle args, String buttonKey) { - Bundle buttons = args.getBundle(RNConstants.ARG_DIALOG_BUTTONS); - if (buttons == null) { - return null; - } - Bundle buttonParams = buttons.getBundle(buttonKey); - if (buttonParams == null) { - return null; - } - // yes, this cast is safe. the color is passed as int from JS (RN.processColor) - int color = (int) buttonParams.getDouble(TEXT_COLOR, Color.TRANSPARENT); - if (color == Color.TRANSPARENT) { - return null; - } - return color; - } - - public static RNTimePickerDisplay getDisplayTime(Bundle args) { - RNTimePickerDisplay display = RNTimePickerDisplay.DEFAULT; - if (args != null && args.getString(RNConstants.ARG_DISPLAY, null) != null) { - display = RNTimePickerDisplay.valueOf(args.getString(RNConstants.ARG_DISPLAY).toUpperCase(Locale.US)); - } - return display; - } - - public static RNDatePickerDisplay getDisplayDate(Bundle args) { - RNDatePickerDisplay display = RNDatePickerDisplay.DEFAULT; - if (args != null && args.getString(RNConstants.ARG_DISPLAY, null) != null) { - display = RNDatePickerDisplay.valueOf(args.getString(RNConstants.ARG_DISPLAY).toUpperCase(Locale.US)); - } - return display; - } - - public static void setButtonTitles(@NonNull Bundle args, AlertDialog dialog, DialogInterface.OnClickListener onNeutralButtonActionListener) { - Bundle buttons = args.getBundle(RNConstants.ARG_DIALOG_BUTTONS); - if (buttons == null) { - return; - } - setButtonLabel(buttons.getBundle(NEUTRAL), dialog, AlertDialog.BUTTON_NEUTRAL, onNeutralButtonActionListener); - setButtonLabel(buttons.getBundle(POSITIVE), dialog, AlertDialog.BUTTON_POSITIVE, (DialogInterface.OnClickListener) dialog); - setButtonLabel(buttons.getBundle(NEGATIVE), dialog, AlertDialog.BUTTON_NEGATIVE, (DialogInterface.OnClickListener) dialog); - } - - private static void setButtonLabel(Bundle buttonConfig, AlertDialog dialog, int whichButton, DialogInterface.OnClickListener listener) { - if (buttonConfig == null || buttonConfig.getString(LABEL) == null) { - return; - } - 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((int)args.getLong(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 ("GMT".equals(timeZoneName)) { - return TimeZone.getTimeZone("GMT"); - } else if (!"GMT".equals(TimeZone.getTimeZone(timeZoneName).getID())) { - return TimeZone.getTimeZone(timeZoneName); - } - RNLog.w(null, "'" + timeZoneName + "' does not exist in TimeZone.getAvailableIDs(). Falling back to TimeZone.getDefault()=" + TimeZone.getDefault().getID()); - } - - return TimeZone.getDefault(); - } - - 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; - } -} diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/DatePickerModule.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/DatePickerModule.java deleted file mode 100644 index c7272205dae49171d4b1e27a64d64ec0963871df..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/DatePickerModule.java +++ /dev/null @@ -1,189 +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.reactcommunity.rndatetimepicker; - -import android.app.DatePickerDialog.OnDateSetListener; -import android.content.DialogInterface; -import android.content.DialogInterface.OnDismissListener; -import android.content.DialogInterface.OnClickListener; -import android.os.Bundle; -import android.widget.DatePicker; -import androidx.annotation.NonNull; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; - -import com.facebook.react.bridge.*; -import com.facebook.react.common.annotations.VisibleForTesting; -import com.facebook.react.module.annotations.ReactModule; - -import static com.reactcommunity.rndatetimepicker.Common.dismissDialog; - -import java.util.Calendar; - -/** - * {@link NativeModule} that allows JS to show a native date picker dialog and get called back when - * the user selects a date. - */ -@ReactModule(name = DatePickerModule.NAME) -public class DatePickerModule extends NativeModuleDatePickerSpec { - - @VisibleForTesting - public static final String NAME = "RNCDatePicker"; - - public DatePickerModule(ReactApplicationContext reactContext) { - super(reactContext); - } - - @NonNull - @Override - public String getName() { - return NAME; - } - - private class DatePickerDialogListener implements OnDateSetListener, OnDismissListener, OnClickListener { - - private final Promise mPromise; - private final Bundle mArgs; - private boolean mPromiseResolved = false; - - public DatePickerDialogListener(final Promise promise, Bundle arguments) { - mPromise = promise; - mArgs = 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.putDouble("timestamp", calendar.getTimeInMillis()); - result.putDouble("utcOffset", calendar.getTimeZone().getOffset(calendar.getTimeInMillis()) / 1000 / 60); - - mPromise.resolve(result); - mPromiseResolved = true; - } - } - - @Override - public void onDismiss(DialogInterface dialog) { - if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) { - WritableMap result = new WritableNativeMap(); - result.putString("action", RNConstants.ACTION_DISMISSED); - mPromise.resolve(result); - mPromiseResolved = true; - } - } - - @Override - public void onClick(DialogInterface dialog, int which) { - if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) { - WritableMap result = new WritableNativeMap(); - result.putString("action", RNConstants.ACTION_NEUTRAL_BUTTON); - mPromise.resolve(result); - mPromiseResolved = true; - } - } - } - - @ReactMethod - public void dismiss(Promise promise) { - FragmentActivity activity = (FragmentActivity) getCurrentActivity(); - dismissDialog(activity, NAME, promise); - } - /** - * Show a date picker dialog. - * - * @param options a map containing options. Available keys are: - * - * - * - * @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(final ReadableMap options, final Promise promise) { - FragmentActivity activity = (FragmentActivity) getCurrentActivity(); - if (activity == null) { - promise.reject( - RNConstants.ERROR_NO_ACTIVITY, - "Tried to open a DatePicker dialog while not attached to an Activity"); - return; - } - - final FragmentManager fragmentManager = activity.getSupportFragmentManager(); - - UiThreadUtil.runOnUiThread(() -> { - RNDatePickerDialogFragment oldFragment = - (RNDatePickerDialogFragment) fragmentManager.findFragmentByTag(NAME); - - Bundle arguments = createFragmentArguments(options); - - if (oldFragment != null) { - oldFragment.update(arguments); - return; - } - - RNDatePickerDialogFragment fragment = new RNDatePickerDialogFragment(); - - fragment.setArguments(arguments); - - 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 = 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)); - } - if (options.hasKey(RNConstants.ARG_MAXDATE) && !options.isNull(RNConstants.ARG_MAXDATE)) { - args.putLong(RNConstants.ARG_MAXDATE, (long) options.getDouble(RNConstants.ARG_MAXDATE)); - } - if (options.hasKey(RNConstants.ARG_DISPLAY) && !options.isNull(RNConstants.ARG_DISPLAY)) { - args.putString(RNConstants.ARG_DISPLAY, options.getString(RNConstants.ARG_DISPLAY)); - } - 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)); - } - if (options.hasKey(RNConstants.ARG_TESTID) && !options.isNull(RNConstants.ARG_TESTID)) { - args.putString(RNConstants.ARG_TESTID, options.getString(RNConstants.ARG_TESTID)); - } - return args; - } -} diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/MinuteIntervalSnappableTimePickerDialog.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/MinuteIntervalSnappableTimePickerDialog.java deleted file mode 100644 index f977e1128912ad1054191c584fd7a18550441497..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/MinuteIntervalSnappableTimePickerDialog.java +++ /dev/null @@ -1,294 +0,0 @@ -package com.reactcommunity.rndatetimepicker; - -import java.util.ArrayList; -import java.util.List; - -import android.annotation.SuppressLint; -import android.app.TimePickerDialog; -import android.content.DialogInterface; -import android.content.Context; -import android.os.Build; -import android.os.Handler; -import android.util.Log; -import android.widget.TimePicker; -import android.view.View; -import android.widget.EditText; -import android.widget.NumberPicker; - -class MinuteIntervalSnappableTimePickerDialog extends TimePickerDialog { - private TimePicker mTimePicker; - private int mTimePickerInterval; - private RNTimePickerDisplay mDisplay; - private final OnTimeSetListener mTimeSetListener; - private Handler handler = new Handler(); - private Runnable runnable; - private Context mContext; - - public MinuteIntervalSnappableTimePickerDialog( - Context context, - OnTimeSetListener listener, - int hourOfDay, - int minute, - int minuteInterval, - boolean is24HourView, - RNTimePickerDisplay display - ) { - super(context, listener, hourOfDay, minute, is24HourView); - mTimePickerInterval = minuteInterval; - mTimeSetListener = listener; - mDisplay = display; - mContext = context; - } - - public MinuteIntervalSnappableTimePickerDialog( - Context context, - int theme, - OnTimeSetListener listener, - int hourOfDay, - int minute, - int minuteInterval, - boolean is24HourView, - RNTimePickerDisplay display - ) { - super(context, theme, listener, hourOfDay, minute, is24HourView); - mTimePickerInterval = minuteInterval; - mTimeSetListener = listener; - mDisplay = display; - mContext = context; - } - - public static boolean isValidMinuteInterval(int interval) { - return interval >= 1 && interval <= 30 && 60 % interval == 0; - } - - private boolean timePickerHasCustomMinuteInterval() { - return mTimePickerInterval != RNConstants.DEFAULT_TIME_PICKER_INTERVAL; - } - - private boolean isSpinner() { - return mDisplay == RNTimePickerDisplay.SPINNER; - } - - /** - * Converts values returned from picker to actual minutes - * - * @param minutesOrSpinnerIndex the internal value of what the user had selected - * @return returns 'real' minutes (0-59) - */ - private int getRealMinutes(int minutesOrSpinnerIndex) { - if (isSpinner()) { - return minutesOrSpinnerIndex * mTimePickerInterval; - } - - return minutesOrSpinnerIndex; - } - - private int getRealMinutes() { - int minute = mTimePicker.getCurrentMinute(); - return getRealMinutes(minute); - } - - /** - * 'Snaps' real minutes or spinner value index to nearest valid value - * in spinner mode you need to make sure to transform the picked value (which is an index) - * to a real value before passing! - * - * @param realMinutes 'real' minutes (0-59) - * @return nearest valid real minute - */ - private int snapRealMinutesToInterval(int realMinutes) { - float stepsInMinutes = (float) realMinutes / (float) mTimePickerInterval; - - int rounded = Math.round(stepsInMinutes) * mTimePickerInterval; - return rounded == 60 ? rounded - mTimePickerInterval : rounded; - } - - private void assertNotSpinner(String s) { - if (isSpinner()) { - throw new RuntimeException(s); - } - } - - /** - * Determines if picked real minutes are ok with the minuteInterval - * - * @param realMinutes 'real' minutes (0-59) - */ - private boolean minutesNeedCorrection(int realMinutes) { - assertNotSpinner("minutesNeedCorrection is not intended to be used with spinner, spinner won't allow picking invalid values"); - - return timePickerHasCustomMinuteInterval() && realMinutes != snapRealMinutesToInterval(realMinutes); - } - - /** - * Determines if the picker is in text input mode (keyboard icon in 'clock' mode) - */ - private boolean pickerIsInTextInputMode() { - int textInputPickerId = mContext.getResources().getIdentifier("input_mode", "id", "android"); - final View textInputPicker = this.findViewById(textInputPickerId); - - return textInputPicker != null && textInputPicker.hasFocus(); - } - - /** - * Corrects minute values if they don't align with minuteInterval - *

- * in text input mode, correction will be postponed slightly to let the user finish the input - * in clock mode we also delay it to give user visual cue about the correction - *

- * - * @param view the picker's view - * @param hourOfDay the picker's selected hours - * @param correctedMinutes 'real' minutes (0-59) aligned to minute interval - */ - private void correctEnteredMinutes(final TimePicker view, final int hourOfDay, final int correctedMinutes) { - assertNotSpinner("spinner never needs to be corrected because wrong values are not offered to user (both in scrolling and textInput mode)!"); - // 'correction' callback - runnable = new Runnable() { - @Override - public void run() { - 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); - } - - @Override - public void onTimeChanged(final TimePicker view, final int hourOfDay, final int minute) { - final int realMinutes = getRealMinutes(minute); - // *always* remove pending 'validation' callbacks, otherwise a valid value might be rewritten - handler.removeCallbacks(runnable); - - if (!isSpinner() && minutesNeedCorrection(realMinutes)) { - int correctedMinutes = snapRealMinutesToInterval(realMinutes); - - // will fire another onTimeChanged - correctEnteredMinutes(view, hourOfDay, correctedMinutes); - } else { - super.onTimeChanged(view, hourOfDay, minute); - } - } - - @Override - public void onClick(DialogInterface dialog, int which) { - 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); - } - } - - @Override - public void updateTime(int hourOfDay, int minuteOfHour) { - if (timePickerHasCustomMinuteInterval()) { - if (isSpinner()) { - final int realMinutes = getRealMinutes(); - int selectedIndex = snapRealMinutesToInterval(realMinutes) / mTimePickerInterval; - super.updateTime(hourOfDay, selectedIndex); - } else { - super.updateTime(hourOfDay, snapRealMinutesToInterval(minuteOfHour)); - } - } else { - super.updateTime(hourOfDay, minuteOfHour); - } - } - - /** - * Apply visual style in 'spinner' mode - * Adjust minutes to correspond selected interval - */ - @Override - public void onAttachedToWindow() { - super.onAttachedToWindow(); - - int timePickerId = mContext.getResources().getIdentifier("timePicker", "id", "android"); - mTimePicker = this.findViewById(timePickerId); - - if (timePickerHasCustomMinuteInterval()) { - setupPickerDialog(); - } - } - - private void setupPickerDialog() { - if (mTimePicker == null) { - Log.e("RN-datetimepicker", "time picker was null"); - return; - } - int realMinuteBackup = mTimePicker.getCurrentMinute(); - - if (isSpinner()) { - setSpinnerDisplayedValues(); - int selectedIndex = snapRealMinutesToInterval(realMinuteBackup) / mTimePickerInterval; - mTimePicker.setCurrentMinute(selectedIndex); - } else { - int snappedRealMinute = snapRealMinutesToInterval(realMinuteBackup); - mTimePicker.setCurrentMinute(snappedRealMinute); - } - } - - @SuppressLint("DefaultLocale") - private void setSpinnerDisplayedValues() { - int minutePickerId = mContext.getResources().getIdentifier("minute", "id", "android"); - NumberPicker minutePicker = this.findViewById(minutePickerId); - - minutePicker.setMinValue(0); - minutePicker.setMaxValue((60 / mTimePickerInterval) - 1); - - List displayedValues = new ArrayList<>(60 / mTimePickerInterval); - for (int displayedMinute = 0; displayedMinute < 60; displayedMinute += mTimePickerInterval) { - displayedValues.add(String.format("%02d", displayedMinute)); - } - - minutePicker.setDisplayedValues(displayedValues.toArray(new String[0])); - } - - @Override - public void onDetachedFromWindow() { - handler.removeCallbacks(runnable); - super.onDetachedFromWindow(); - } -} diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNConstants.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNConstants.java deleted file mode 100644 index 99530d51ce4ffacd6c38fbfe54c210cdf7b5f4e6..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNConstants.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.reactcommunity.rndatetimepicker; - -import android.app.TimePickerDialog; - -public final class RNConstants { - public static final String ERROR_NO_ACTIVITY = "E_NO_ACTIVITY"; - public static final String ARG_VALUE = "value"; - public static final String ARG_MINDATE = "minimumDate"; - public static final String ARG_MAXDATE = "maximumDate"; - public static final String ARG_INTERVAL = "minuteInterval"; - public static final String ARG_IS24HOUR = "is24Hour"; - 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 ARG_TESTID = "testID"; - public static final String ACTION_DATE_SET = "dateSetAction"; - public static final String ACTION_TIME_SET = "timeSetAction"; - public static final String ACTION_DISMISSED = "dismissedAction"; - public static final String ACTION_NEUTRAL_BUTTON = "neutralButtonAction"; - - /** - * Minimum date supported by {@link TimePickerDialog}, 01 Jan 1900 - */ - public static final long DEFAULT_MIN_DATE = -2208988800001l; - - /** - * Minimum and default time picker minute interval - */ - public static final int DEFAULT_TIME_PICKER_INTERVAL = 1; -} diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDate.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDate.java deleted file mode 100644 index 137869a98650367957b9a6a46322014cfdb26916..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDate.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.reactcommunity.rndatetimepicker; - -import java.util.Calendar; -import java.util.TimeZone; -import android.os.Bundle; - -public class RNDate { - private Calendar now; - - public RNDate(Bundle args) { - now = Calendar.getInstance(); - - if (args != null && args.containsKey(RNConstants.ARG_VALUE)) { - now.setTimeInMillis((args.getLong(RNConstants.ARG_VALUE))); - } - - - now.setTimeZone(Common.getTimeZone(args)); - } - - public int year() { return now.get(Calendar.YEAR); } - public int month() { return now.get(Calendar.MONTH); } - public int day() { return now.get(Calendar.DAY_OF_MONTH); } - public int hour() { return now.get(Calendar.HOUR_OF_DAY); } - public int minute() { return now.get(Calendar.MINUTE); } -} diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDialogFragment.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDialogFragment.java deleted file mode 100644 index 72de7cbba2a0473d4fc85a51bf7a050a5f1e7825..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDialogFragment.java +++ /dev/null @@ -1,161 +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.reactcommunity.rndatetimepicker; - -import static com.reactcommunity.rndatetimepicker.Common.getDisplayDate; -import static com.reactcommunity.rndatetimepicker.Common.setButtonTextColor; -import static com.reactcommunity.rndatetimepicker.Common.setButtonTitles; - -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.content.DialogInterface.OnClickListener; -import android.os.Build; -import android.os.Bundle; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.DialogFragment; - -import android.widget.DatePicker; - -import java.util.Calendar; -import java.util.Locale; - -@SuppressLint("ValidFragment") -public class RNDatePickerDialogFragment extends DialogFragment { - private DatePickerDialog instance; - - @Nullable - private OnDateSetListener mOnDateSetListener; - @Nullable - private OnDismissListener mOnDismissListener; - @Nullable - private OnClickListener mOnNeutralButtonActionListener; - - @NonNull - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - Bundle args = getArguments(); - instance = createDialog(args); - return instance; - } - - public void update(Bundle args) { - final RNDate date = new RNDate(args); - instance.updateDate(date.year(), date.month(), date.day()); - } - - static @NonNull - DatePickerDialog getDialog( - Bundle args, - Context activityContext, - @Nullable OnDateSetListener onDateSetListener) { - final RNDate date = new RNDate(args); - final int year = date.year(); - final int month = date.month(); - final int day = date.day(); - - RNDatePickerDisplay display = getDisplayDate(args); - - if (args != null && args.getString(RNConstants.ARG_DISPLAY, null) != null) { - display = RNDatePickerDisplay.valueOf(args.getString(RNConstants.ARG_DISPLAY).toUpperCase(Locale.US)); - } - - if (display == RNDatePickerDisplay.SPINNER) { - return new RNDismissableDatePickerDialog( - activityContext, - R.style.SpinnerDatePickerDialog, - onDateSetListener, - year, - month, - day, - display - ); - } - return new RNDismissableDatePickerDialog( - activityContext, - onDateSetListener, - year, - month, - day, - display - ); - } - - private DatePickerDialog createDialog(Bundle args) { - Context activityContext = getActivity(); - DatePickerDialog dialog = getDialog(args, activityContext, mOnDateSetListener); - - if (args != null) { - setButtonTitles(args, dialog, mOnNeutralButtonActionListener); - if (activityContext != null) { - RNDatePickerDisplay display = getDisplayDate(args); - boolean needsColorOverride = display == RNDatePickerDisplay.SPINNER; - dialog.setOnShowListener(setButtonTextColor(activityContext, dialog, args, needsColorOverride)); - } - } - - final DatePicker datePicker = dialog.getDatePicker(); - final long minDate = Common.minDateWithTimeZone(args); - final long maxDate = Common.maxDateWithTimeZone(args); - - if (args.containsKey(RNConstants.ARG_MINDATE)) { - datePicker.setMinDate(minDate); - } 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(RNConstants.DEFAULT_MIN_DATE); - } - if (args.containsKey(RNConstants.ARG_MAXDATE)) { - datePicker.setMaxDate(maxDate); - } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && (args.containsKey(RNConstants.ARG_MAXDATE) || args.containsKey(RNConstants.ARG_MINDATE))) { - datePicker.setOnDateChangedListener((view, year, monthOfYear, dayOfMonth) -> { - Calendar calendar = Calendar.getInstance(Common.getTimeZone(args)); - calendar.set(year, monthOfYear, dayOfMonth, 0, 0, 0); - long timestamp = Math.min(Math.max(calendar.getTimeInMillis(), minDate), maxDate); - calendar.setTimeInMillis(timestamp); - if (datePicker.getYear() != calendar.get(Calendar.YEAR) || datePicker.getMonth() != calendar.get(Calendar.MONTH) || datePicker.getDayOfMonth() != calendar.get(Calendar.DAY_OF_MONTH)) { - datePicker.updateDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH)); - } - }); - } - - if (args.containsKey(RNConstants.ARG_TESTID)) { - datePicker.setTag(args.getString(RNConstants.ARG_TESTID)); - } - - return dialog; - } - - @Override - public void onDismiss(@NonNull 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; - } - - /*package*/ void setOnNeutralButtonActionListener(@Nullable OnClickListener onNeutralButtonActionListener) { - mOnNeutralButtonActionListener = onNeutralButtonActionListener; - } -} diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDisplay.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDisplay.java deleted file mode 100644 index d4cd72f6e69f8a98306213938fe62db7000ec302..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDisplay.java +++ /dev/null @@ -1,16 +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.reactcommunity.rndatetimepicker; - -/** - * Date picker display options. - */ -public enum RNDatePickerDisplay { - SPINNER, - DEFAULT -} diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDateTimePickerPackage.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDateTimePickerPackage.java deleted file mode 100644 index ceafa6ba69192821851415425711e76bccb2ab79..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDateTimePickerPackage.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.reactcommunity.rndatetimepicker; - - -import androidx.annotation.Nullable; - -import com.facebook.react.TurboReactPackage; -import com.facebook.react.bridge.NativeModule; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.module.model.ReactModuleInfo; -import com.facebook.react.module.model.ReactModuleInfoProvider; - -import java.util.HashMap; -import java.util.Map; - -public class RNDateTimePickerPackage extends TurboReactPackage { - @Nullable - @Override - public NativeModule getModule(String name, ReactApplicationContext reactContext) { - if (name.equals(DatePickerModule.NAME)) { - return new DatePickerModule(reactContext); - } else if (name.equals(TimePickerModule.NAME)) { - return new TimePickerModule(reactContext); - } else { - return null; - } - } - - @Override - public ReactModuleInfoProvider getReactModuleInfoProvider() { - return () -> { - boolean isTurboModule = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED; - final Map moduleInfos = new HashMap<>(); - moduleInfos.put( - DatePickerModule.NAME, - new ReactModuleInfo( - DatePickerModule.NAME, - DatePickerModule.NAME, - false, // canOverrideExistingModule - false, // needsEagerInit - false, // hasConstants - false, // isCxxModule - isTurboModule // isTurboModule - )); - moduleInfos.put( - TimePickerModule.NAME, - new ReactModuleInfo( - TimePickerModule.NAME, - TimePickerModule.NAME, - false, // canOverrideExistingModule - false, // needsEagerInit - false, // hasConstants - false, // isCxxModule - isTurboModule // isTurboModule - )); - return moduleInfos; - }; - } -} diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDismissableDatePickerDialog.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDismissableDatePickerDialog.java deleted file mode 100644 index 88edebca4f24a34b9a2481a213fde60f13ae032c..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDismissableDatePickerDialog.java +++ /dev/null @@ -1,114 +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.reactcommunity.rndatetimepicker; - -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; - -import static com.reactcommunity.rndatetimepicker.ReflectionHelper.findField; - -/** - *

- * Certain versions of Android (Jellybean-KitKat) have a bug where when dismissed, the - * {@link DatePickerDialog} still calls the OnDateSetListener. This class works around that issue. - *

- * - *

- * See: Issue 34833 - *

- */ -public class RNDismissableDatePickerDialog extends DatePickerDialog { - - public RNDismissableDatePickerDialog( - Context context, - @Nullable DatePickerDialog.OnDateSetListener callback, - int year, - int monthOfYear, - int dayOfMonth, - RNDatePickerDisplay display) { - super(context, callback, year, monthOfYear, dayOfMonth); - fixSpinner(context, year, monthOfYear, dayOfMonth, display); - } - - public RNDismissableDatePickerDialog( - Context context, - int theme, - @Nullable DatePickerDialog.OnDateSetListener callback, - int year, - int monthOfYear, - int dayOfMonth, - RNDatePickerDisplay display) { - super(context, theme, callback, year, monthOfYear, dayOfMonth); - fixSpinner(context, year, monthOfYear, dayOfMonth, display); - } - - @Override - protected void onStop() { - // do *not* call super.onStop() on KitKat on lower, as that would erroneously call the - // OnDateSetListener when the dialog is dismissed, or call it twice when "OK" is pressed. - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { - super.onStop(); - } - } - - private void fixSpinner(Context context, int year, int month, int dayOfMonth, RNDatePickerDisplay display) { - if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N && display == RNDatePickerDisplay.SPINNER) { - try { - // Get the theme's android:datePickerMode - 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); - a.recycle(); - - 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); - } - } - if (display == RNDatePickerDisplay.SPINNER){ - if(this.getDatePicker() != null) - this.getDatePicker().setCalendarViewShown(false); - } - } -} diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDismissableTimePickerDialog.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDismissableTimePickerDialog.java deleted file mode 100644 index 073bd8d142cb894f71603512d84b86e88996cc26..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDismissableTimePickerDialog.java +++ /dev/null @@ -1,108 +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.reactcommunity.rndatetimepicker; - -import static com.reactcommunity.rndatetimepicker.ReflectionHelper.findField; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; - -import android.app.TimePickerDialog; -import android.content.Context; -import android.content.res.TypedArray; -import android.os.Build; -import android.util.AttributeSet; -import android.widget.TimePicker; - -import androidx.annotation.Nullable; - -/** - *

- * Certain versions of Android (Jellybean-KitKat) have a bug where when dismissed, the - * {@link TimePickerDialog} still calls the OnTimeSetListener. This class works around that issue - * by *not* calling super.onStop on KitKat on lower, as that would erroneously call the - * OnTimeSetListener when the dialog is dismissed, or call it twice when "OK" is pressed. - *

- * - *

- * See: Issue 34833 - *

- */ - -public class RNDismissableTimePickerDialog extends MinuteIntervalSnappableTimePickerDialog { - - public RNDismissableTimePickerDialog( - Context context, - @Nullable TimePickerDialog.OnTimeSetListener callback, - int hourOfDay, - int minute, - int minuteInterval, - boolean is24HourView, - RNTimePickerDisplay display - ) { - super(context, callback, hourOfDay, minute, minuteInterval, is24HourView, display); - fixSpinner(context, hourOfDay, minute, is24HourView, display); - } - - public RNDismissableTimePickerDialog( - Context context, - int theme, - @Nullable TimePickerDialog.OnTimeSetListener callback, - int hourOfDay, - int minute, - int minuteInterval, - boolean is24HourView, - RNTimePickerDisplay display - ) { - super(context, theme, callback, hourOfDay, minute, minuteInterval, is24HourView, display); - fixSpinner(context, hourOfDay, minute, is24HourView, display); - } - - @Override - protected void onStop() { - if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT) { - super.onStop(); - } - } - - private void fixSpinner(Context context, int hourOfDay, int minute, boolean is24HourView, RNTimePickerDisplay display) { - if (Build.VERSION.SDK_INT == Build.VERSION_CODES.N && display == RNTimePickerDisplay.SPINNER) { - try { - Class styleableClass = Class.forName("com.android.internal.R$styleable"); - Field timePickerStyleableField = styleableClass.getField("TimePicker"); - int[] timePickerStyleable = (int[]) timePickerStyleableField.get(null); - final TypedArray a = context.obtainStyledAttributes(null, timePickerStyleable, android.R.attr.timePickerStyle, 0); - a.recycle(); - - TimePicker timePicker = (TimePicker) findField(TimePickerDialog.class, TimePicker.class, "mTimePicker").get(this); - Class delegateClass = Class.forName("android.widget.TimePicker$TimePickerDelegate"); - Field delegateField = findField(TimePicker.class, delegateClass, "mDelegate"); - Object delegate = delegateField.get(timePicker); - Class spinnerDelegateClass; - spinnerDelegateClass = Class.forName("android.widget.TimePickerSpinnerDelegate"); - // In 7.0 Nougat for some reason the timePickerMode is ignored and the delegate is TimePickerClockDelegate - if (delegate.getClass() != spinnerDelegateClass) { - delegateField.set(timePicker, null); // throw out the TimePickerClockDelegate! - timePicker.removeAllViews(); // remove the TimePickerClockDelegate views - Constructor spinnerDelegateConstructor = spinnerDelegateClass.getConstructor(TimePicker.class, Context.class, AttributeSet.class, int.class, int.class); - spinnerDelegateConstructor.setAccessible(true); - // Instantiate a TimePickerSpinnerDelegate - delegate = spinnerDelegateConstructor.newInstance(timePicker, context, null, android.R.attr.timePickerStyle, 0); - delegateField.set(timePicker, delegate); // set the TimePicker.mDelegate to the spinner delegate - // Set up the TimePicker again, with the TimePickerSpinnerDelegate - timePicker.setIs24HourView(is24HourView); - timePicker.setCurrentHour(hourOfDay); - timePicker.setCurrentMinute(minute); - timePicker.setOnTimeChangedListener(this); - } - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } -} diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogFragment.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogFragment.java deleted file mode 100644 index f3c8830e5aa9e5e45942518cc35dc37fb9033c0b..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogFragment.java +++ /dev/null @@ -1,130 +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.reactcommunity.rndatetimepicker; - -import static com.reactcommunity.rndatetimepicker.Common.getDisplayTime; -import static com.reactcommunity.rndatetimepicker.Common.setButtonTextColor; -import static com.reactcommunity.rndatetimepicker.Common.setButtonTitles; - -import android.app.Dialog; -import android.app.TimePickerDialog; -import android.app.TimePickerDialog.OnTimeSetListener; -import android.content.Context; -import android.content.DialogInterface; -import android.content.DialogInterface.OnDismissListener; -import android.content.DialogInterface.OnClickListener; -import android.os.Bundle; -import android.text.format.DateFormat; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.fragment.app.DialogFragment; - -@SuppressWarnings("ValidFragment") -public class RNTimePickerDialogFragment extends DialogFragment { - private TimePickerDialog instance; - - @Nullable - private OnTimeSetListener mOnTimeSetListener; - @Nullable - private OnDismissListener mOnDismissListener; - @Nullable - private OnClickListener mOnNeutralButtonActionListener; - - @NonNull - @Override - public Dialog onCreateDialog(Bundle savedInstanceState) { - final Bundle args = getArguments(); - instance = createDialog(args); - return instance; - } - - public void update(Bundle args) { - final RNDate date = new RNDate(args); - instance.updateTime(date.hour(), date.minute()); - } - - static TimePickerDialog getDialog( - Bundle args, - Context activityContext, - @Nullable OnTimeSetListener onTimeSetListener) { - - final RNDate date = new RNDate(args); - final int hour = date.hour(); - final int minute = date.minute(); - boolean is24hour = DateFormat.is24HourFormat(activityContext); - if (args != null) { - is24hour = args.getBoolean(RNConstants.ARG_IS24HOUR, DateFormat.is24HourFormat(activityContext)); - } - - int minuteInterval = RNConstants.DEFAULT_TIME_PICKER_INTERVAL; - if (args != null && MinuteIntervalSnappableTimePickerDialog.isValidMinuteInterval(args.getInt(RNConstants.ARG_INTERVAL))) { - minuteInterval = args.getInt(RNConstants.ARG_INTERVAL); - } - - RNTimePickerDisplay display = getDisplayTime(args); - - if (display == RNTimePickerDisplay.SPINNER) { - return new RNDismissableTimePickerDialog( - activityContext, - R.style.SpinnerTimePickerDialog, - onTimeSetListener, - hour, - minute, - minuteInterval, - is24hour, - display - ); - } - return new RNDismissableTimePickerDialog( - activityContext, - onTimeSetListener, - hour, - minute, - minuteInterval, - is24hour, - display - ); - } - - private TimePickerDialog createDialog(Bundle args) { - Context activityContext = getActivity(); - TimePickerDialog dialog = getDialog(args, activityContext, mOnTimeSetListener); - - if (args != null) { - setButtonTitles(args, dialog, mOnNeutralButtonActionListener); - if (activityContext != null) { - RNTimePickerDisplay display = getDisplayTime(args); - boolean needsColorOverride = display == RNTimePickerDisplay.SPINNER; - dialog.setOnShowListener(setButtonTextColor(activityContext, dialog, args, needsColorOverride)); - } - } - return dialog; - } - - @Override - public void onDismiss(@NonNull DialogInterface dialog) { - super.onDismiss(dialog); - if (mOnDismissListener != null) { - mOnDismissListener.onDismiss(dialog); - } - } - - public void setOnDismissListener(@Nullable OnDismissListener onDismissListener) { - mOnDismissListener = onDismissListener; - } - - public void setOnTimeSetListener(@Nullable OnTimeSetListener onTimeSetListener) { - mOnTimeSetListener = onTimeSetListener; - } - - /*package*/ void setOnNeutralButtonActionListener(@Nullable OnClickListener onNeutralButtonActionListener) { - mOnNeutralButtonActionListener = onNeutralButtonActionListener; - } -} diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDisplay.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDisplay.java deleted file mode 100644 index 6044b704752b6610b743ed240d7a270f84d12b6e..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDisplay.java +++ /dev/null @@ -1,17 +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.reactcommunity.rndatetimepicker; - -/** - * Date picker display options. - */ -public enum RNTimePickerDisplay { - SPINNER, - DEFAULT -} diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/ReflectionHelper.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/ReflectionHelper.java deleted file mode 100644 index 218bbc1d573b903e30b0b3062578a08b87843a7a..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/ReflectionHelper.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.reactcommunity.rndatetimepicker; - -import androidx.annotation.Nullable; - -import java.lang.reflect.Field; - -public class ReflectionHelper { - - @Nullable - public 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; - } -} diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/TimePickerModule.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/TimePickerModule.java deleted file mode 100644 index 877b37b1deb169ca827eaa227105e8e459bea704..0000000000000000000000000000000000000000 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/TimePickerModule.java +++ /dev/null @@ -1,161 +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.reactcommunity.rndatetimepicker; - -import com.facebook.react.bridge.*; -import com.facebook.react.common.annotations.VisibleForTesting; -import com.facebook.react.module.annotations.ReactModule; - -import android.app.TimePickerDialog.OnTimeSetListener; -import android.content.DialogInterface; -import android.content.DialogInterface.OnDismissListener; -import android.content.DialogInterface.OnClickListener; -import android.os.Bundle; -import android.widget.TimePicker; - -import androidx.annotation.NonNull; -import androidx.fragment.app.FragmentActivity; -import androidx.fragment.app.FragmentManager; - -import static com.reactcommunity.rndatetimepicker.Common.dismissDialog; - -import java.util.Calendar; - -/** - * {@link NativeModule} that allows JS to show a native time picker dialog and get called back when - * the user selects a time. - */ -@ReactModule(name = TimePickerModule.NAME) -public class TimePickerModule extends NativeModuleTimePickerSpec { - - @VisibleForTesting - public static final String NAME = "RNCTimePicker"; - - public TimePickerModule(ReactApplicationContext reactContext) { - super(reactContext); - } - - @NonNull - @Override - public String getName() { - return NAME; - } - - private class TimePickerDialogListener implements OnTimeSetListener, OnDismissListener, OnClickListener { - private final Promise mPromise; - private final Bundle mArgs; - private boolean mPromiseResolved = false; - - public TimePickerDialogListener(Promise promise, Bundle arguments) { - mPromise = promise; - mArgs = arguments; - } - - @Override - public void onTimeSet(TimePicker view, int hour, int minute) { - if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) { - final RNDate date = new RNDate(mArgs); - Calendar calendar = Calendar.getInstance(Common.getTimeZone(mArgs)); - calendar.set(date.year(), date.month(), date.day(), hour, minute, 0); - calendar.set(Calendar.MILLISECOND, 0); - - WritableMap result = new WritableNativeMap(); - result.putString("action", RNConstants.ACTION_TIME_SET); - result.putDouble("timestamp", calendar.getTimeInMillis()); - result.putDouble("utcOffset", calendar.getTimeZone().getOffset(calendar.getTimeInMillis()) / 1000 / 60); - - mPromise.resolve(result); - mPromiseResolved = true; - } - } - - @Override - public void onDismiss(DialogInterface dialog) { - if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) { - WritableMap result = new WritableNativeMap(); - result.putString("action", RNConstants.ACTION_DISMISSED); - mPromise.resolve(result); - mPromiseResolved = true; - } - } - - @Override - public void onClick(DialogInterface dialog, int which) { - if (!mPromiseResolved && getReactApplicationContext().hasActiveReactInstance()) { - WritableMap result = new WritableNativeMap(); - result.putString("action", RNConstants.ACTION_NEUTRAL_BUTTON); - mPromise.resolve(result); - mPromiseResolved = true; - } - } - } - - @ReactMethod - public void dismiss(Promise promise) { - FragmentActivity activity = (FragmentActivity) getCurrentActivity(); - dismissDialog(activity, NAME, promise); - } - - @ReactMethod - public void open(final ReadableMap options, final Promise promise) { - FragmentActivity activity = (FragmentActivity) getCurrentActivity(); - if (activity == null) { - promise.reject( - RNConstants.ERROR_NO_ACTIVITY, - "Tried to open a TimePicker 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. - final FragmentManager fragmentManager = activity.getSupportFragmentManager(); - - UiThreadUtil.runOnUiThread(() -> { - RNTimePickerDialogFragment oldFragment = - (RNTimePickerDialogFragment) fragmentManager.findFragmentByTag(NAME); - - Bundle arguments = createFragmentArguments(options); - - if (oldFragment != null) { - oldFragment.update(arguments); - return; - } - - RNTimePickerDialogFragment fragment = new RNTimePickerDialogFragment(); - - fragment.setArguments(arguments); - - final TimePickerDialogListener listener = new TimePickerDialogListener(promise, arguments); - fragment.setOnDismissListener(listener); - fragment.setOnTimeSetListener(listener); - fragment.setOnNeutralButtonActionListener(listener); - fragment.show(fragmentManager, NAME); - }); - } - - private Bundle createFragmentArguments(ReadableMap options) { - final Bundle args = Common.createFragmentArguments(options); - - if (options.hasKey(RNConstants.ARG_IS24HOUR) && !options.isNull(RNConstants.ARG_IS24HOUR)) { - args.putBoolean(RNConstants.ARG_IS24HOUR, options.getBoolean(RNConstants.ARG_IS24HOUR)); - } - if (options.hasKey(RNConstants.ARG_DISPLAY) && !options.isNull(RNConstants.ARG_DISPLAY)) { - args.putString(RNConstants.ARG_DISPLAY, options.getString(RNConstants.ARG_DISPLAY)); - } - 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_INTERVAL) && !options.isNull(RNConstants.ARG_INTERVAL)) { - args.putInt(RNConstants.ARG_INTERVAL, options.getInt(RNConstants.ARG_INTERVAL)); - } - 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; - } -} diff --git a/android/src/main/res/values-night/styles.xml b/android/src/main/res/values-night/styles.xml deleted file mode 100644 index f21de701d85e191eb0f88c2249e2e4cab5d2c2d5..0000000000000000000000000000000000000000 --- a/android/src/main/res/values-night/styles.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - diff --git a/android/src/main/res/values/styles.xml b/android/src/main/res/values/styles.xml deleted file mode 100644 index 3e34841a8cf54fb5711a24dc34ab0a7083051798..0000000000000000000000000000000000000000 --- a/android/src/main/res/values/styles.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - diff --git a/android/src/paper/java/com/reactcommunity/rndatetimepicker/NativeModuleDatePickerSpec.java b/android/src/paper/java/com/reactcommunity/rndatetimepicker/NativeModuleDatePickerSpec.java deleted file mode 100644 index 950a753f76a9b9eed6794da5540f34265a62b232..0000000000000000000000000000000000000000 --- a/android/src/paper/java/com/reactcommunity/rndatetimepicker/NativeModuleDatePickerSpec.java +++ /dev/null @@ -1,36 +0,0 @@ - -/** - * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). - * - * Then it was commited. It is here to support the old architecture. - * If you use the new architecture, this file won't be included and instead will be generated by the codegen. - * - * @generated by codegen project: GenerateModuleJavaSpec.js - * - * @nolint - */ - -package com.reactcommunity.rndatetimepicker; - -import com.facebook.proguard.annotations.DoNotStrip; -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.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeModuleDatePickerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeModuleDatePickerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - @DoNotStrip - public abstract void dismiss(Promise promise); - - @ReactMethod - @DoNotStrip - public abstract void open(ReadableMap params, Promise promise); -} diff --git a/android/src/paper/java/com/reactcommunity/rndatetimepicker/NativeModuleTimePickerSpec.java b/android/src/paper/java/com/reactcommunity/rndatetimepicker/NativeModuleTimePickerSpec.java deleted file mode 100644 index 7c46411d21d9f0e0fabe0ae1260978588a051617..0000000000000000000000000000000000000000 --- a/android/src/paper/java/com/reactcommunity/rndatetimepicker/NativeModuleTimePickerSpec.java +++ /dev/null @@ -1,36 +0,0 @@ - -/** - * This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). - * - * Then it was commited. It is here to support the old architecture. - * If you use the new architecture, this file won't be included and instead will be generated by the codegen. - * - * @generated by codegen project: GenerateModuleJavaSpec.js - * - * @nolint - */ - -package com.reactcommunity.rndatetimepicker; - -import com.facebook.proguard.annotations.DoNotStrip; -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.ReactModuleWithSpec; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.turbomodule.core.interfaces.TurboModule; - -public abstract class NativeModuleTimePickerSpec extends ReactContextBaseJavaModule implements ReactModuleWithSpec, TurboModule { - public NativeModuleTimePickerSpec(ReactApplicationContext reactContext) { - super(reactContext); - } - - @ReactMethod - @DoNotStrip - public abstract void dismiss(Promise promise); - - @ReactMethod - @DoNotStrip - public abstract void open(ReadableMap params, Promise promise); -} diff --git a/docs/images/android_date.png b/docs/images/android_date.png deleted file mode 100644 index f4885454116d46217db3890dbcfe65bd8fd89e9f..0000000000000000000000000000000000000000 Binary files a/docs/images/android_date.png and /dev/null differ diff --git a/docs/images/android_time.png b/docs/images/android_time.png deleted file mode 100644 index f0a779da87271a3271e20c29d0026674e85ffc0e..0000000000000000000000000000000000000000 Binary files a/docs/images/android_time.png and /dev/null differ diff --git a/docs/images/ios_date_new.png b/docs/images/ios_date_new.png deleted file mode 100644 index 300205ce84ec27c6e31dcff0aa2af69dc9d03b4c..0000000000000000000000000000000000000000 Binary files a/docs/images/ios_date_new.png and /dev/null differ diff --git a/docs/images/ios_date_old.png b/docs/images/ios_date_old.png deleted file mode 100644 index e1170b357e40ad3ab35236c87b84fbbda5da62d1..0000000000000000000000000000000000000000 Binary files a/docs/images/ios_date_old.png and /dev/null differ diff --git a/docs/images/ios_time.png b/docs/images/ios_time.png deleted file mode 100644 index 835689fa076c4eaf94866715261f3ec523b15765..0000000000000000000000000000000000000000 Binary files a/docs/images/ios_time.png and /dev/null differ diff --git a/docs/images/windows_date.png b/docs/images/windows_date.png deleted file mode 100644 index 9f1ba0dd1c636c5cb6a07458e6bf763481975a1f..0000000000000000000000000000000000000000 Binary files a/docs/images/windows_date.png and /dev/null differ diff --git a/docs/images/windows_time_1.png b/docs/images/windows_time_1.png deleted file mode 100644 index 048f5f0e4790ba4f35467dd12163d91870659e10..0000000000000000000000000000000000000000 Binary files a/docs/images/windows_time_1.png and /dev/null differ diff --git a/docs/images/windows_time_2.png b/docs/images/windows_time_2.png deleted file mode 100644 index ac87e57b681473712ec6d79e9bdbe76869e2ff37..0000000000000000000000000000000000000000 Binary files a/docs/images/windows_time_2.png and /dev/null differ diff --git a/docs/manual-installation.md b/docs/manual-installation.md deleted file mode 100644 index 8684fce265642a6b81947e7cae96e373ec55b42c..0000000000000000000000000000000000000000 --- a/docs/manual-installation.md +++ /dev/null @@ -1,105 +0,0 @@ -## Manual installation - -#### iOS - -1. Install CocoaPods, here the [installation guide](https://guides.cocoapods.org/using/getting-started.html). -2. Inside the iOS folder run `pod init`, this will create the initial `pod` file. -3. Update your `pod` file to look like the following ( Remember to replace `MyApp` with your target name ): - - ```ruby - # Allowed sources - source 'https://github.com/CocoaPods/Specs.git' - - target 'MyApp' do - # As we use Swift, ensure that `use_frameworks` is enabled. - use_frameworks! - - # Specific iOS platform we are targetting - platform :ios, '8.0' - - # Point to the installed version - pod 'RNDateTimePicker', :path => '../node_modules/@react-native-community/datetimepicker/RNDateTimePicker.podspec' - - # React/React-Native specific pods - pod 'React', :path => '../node_modules/react-native', :subspecs => [ - 'Core', - 'CxxBridge', # Include this for RN >= 0.47 - 'DevSupport', # Include this to enable In-App Devmenu if RN >= 0.43 - 'RCTText', - 'RCTNetwork', - 'RCTWebSocket', # Needed for debugging - ] - - # Explicitly include Yoga if you are using RN >= 0.42.0 - pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga' - - # Third party deps podspec link - pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' - pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' - pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' - - end - ``` - -4. Run `pod install` inside the same folder where the `pod` file was created -5. `npm run start` -6. `npm run start:ios` - -#### Android - -1. Add the following lines to `android/settings.gradle`: - - ```gradle - include ':@react-native-community_datetimepicker' - project(':@react-native-community_datetimepicker').projectDir = new File(rootProject.projectDir, '../node_modules/@react-native-community/datetimepicker/android') - ``` - -2. Add the compile line to the dependencies in `android/app/build.gradle`: - - ```gradle - dependencies { - ... - implementation project(':@react-native-community_datetimepicker') - } - ``` - -3. Add the import and link the package in `MainApplication.java`: - - ```diff - + import com.reactcommunity.rndatetimepicker.RNDateTimePickerPackage; - - public class MainApplication extends Application implements ReactApplication { - - @Override - protected List getPackages() { - @SuppressWarnings("UnnecessaryLocalVariable") - List packages = new PackageList(this).getPackages(); - // Packages that cannot be autolinked yet can be added manually here, for example: - + packages.add(new RNDateTimePickerPackage()); - return packages; - } - } - ``` - -#### Windows - -##### Add the DateTimePickerWindows project to your solution - -1. Open the solution in Visual Studio 2019 -2. Right-click solution icon in Solution Explorer > Add > Existing Project - Select 'D:\pathToYourApp\node_modules\@react-native-community\datetimepicker\windows\DateTimePickerWindows\DateTimePickerWindows.vcxproj' - -##### **windows/myapp.sln** - -Add a reference to `DateTimePickerWindows` to your main application project. From Visual Studio 2019: - -Right-click main application project > Add > Reference... -Check 'DateTimePickerWindows' from the 'Project > Solution' tab on the left. - -##### **pch.h** - -Add `#include "winrt/DateTimePicker.h"`. - -##### **app.cpp** - -Add `PackageProviders().Append(winrt::DateTimePicker::ReactPackageProvider());` before `InitializeComponent();`. diff --git a/docs/migration.md b/docs/migration.md deleted file mode 100644 index f7ca9fb2742f9589ab7af0c08adf1dbc8a4c1215..0000000000000000000000000000000000000000 --- a/docs/migration.md +++ /dev/null @@ -1,224 +0,0 @@ -## Migration from the older components - -`RNDateTimePicker` is the new common name used to represent the old versions of iOS and Android. - -On Android, open picker modals will update the selected date and/or time if the prop `value` changes. For example, if a HOC holding state, updates the `value` prop. Previously the component used to close the modal and render a new one on consecutive calls. - -### DatePickerIOS - -- `initialDate` is deprecated, use `value` instead. - - ```js - // Before - - ``` - - ```js - // Now - - ``` - -- `date` is deprecated, use `value` instead. - - ```js - // Before - - ``` - - ```js - // Now - - ``` - -- `onChange` now returns also the date. - - ```js - // Before - onChange = (event) => {}; - ; - ``` - - ```js - // Now - onChange = (event, date) => {}; - ; - ``` - -- `onDateChange` is deprecated, use `onChange` instead. - - ```js - // Before - setDate = (date) => {}; - ; - ``` - - ```js - // Now - setDate = (event, date) => {}; - ; - ``` - -### DatePickerAndroid - -- `date` is deprecated, use `value` instead. - - ```js - // Before - try { - const {action, year, month, day} = await DatePickerAndroid.open({ - date: new Date(), - }); - } catch ({code, message}) { - console.warn('Cannot open date picker', message); - } - ``` - - ```js - // Now - - ``` - -- `minDate` and `maxDate` are deprecated, use `minimumDate` and `maximumDate` instead. - - ```js - // Before - try { - const {action, year, month, day} = await DatePickerAndroid.open({ - minDate: new Date(), - maxDate: new Date(), - }); - } catch ({code, message}) { - console.warn('Cannot open date picker', message); - } - ``` - - ```js - // Now - - ``` - -- `dateSetAction` is deprecated, use `onChange` instead. - - ```js - // Before - try { - const {action, year, month, day} = await DatePickerAndroid.open(); - if (action === DatePickerAndroid.dateSetAction) { - // Selected year, month (0-11), day - } - } catch ({code, message}) { - console.warn('Cannot open date picker', message); - } - ``` - - ```js - // Now - setDate = (event, date) => { - if (date !== undefined) { - // timeSetAction - } - }; - ; - ``` - -- `dismissedAction` is deprecated, use `onChange` instead. - - ```js - // Before - try { - const {action, year, month, day} = await DatePickerAndroid.open(); - if (action === DatePickerAndroid.dismissedAction) { - // Dismissed - } - } catch ({code, message}) { - console.warn('Cannot open date picker', message); - } - ``` - - ```js - // Now - setDate = (event, date) => { - if (date === undefined) { - // dismissedAction - } - }; - ; - ``` - -### TimePickerAndroid - -- `hour` and `minute` are deprecated, use `value` instead. - - ```js - // Before - try { - const {action, hour, minute} = await TimePickerAndroid.open({ - hour: 14, - minute: 0, - is24Hour: false, // Will display '2 PM' - }); - if (action !== TimePickerAndroid.dismissedAction) { - // Selected hour (0-23), minute (0-59) - } - } catch ({code, message}) { - console.warn('Cannot open time picker', message); - } - ``` - - ```js - // Now - // It will use the hour and minute defined in date - - ``` - -- `timeSetAction` is deprecated, use `onChange` instead. - - ```js - // Before - try { - const {action, hour, minute} = await TimePickerAndroid.open(); - if (action === TimePickerAndroid.timeSetAction) { - // Selected hour (0-23), minute (0-59) - } - } catch ({code, message}) { - console.warn('Cannot open time picker', message); - } - ``` - - ```js - // Now - setTime = (event, date) => { - if (date !== undefined) { - // Use the hour and minute from the date object - } - }; - ; - ``` - -- `dismissedAction` is deprecated, use `onChange` instead. - - ```js - // Before - try { - const {action, hour, minute} = await TimePickerAndroid.open(); - if (action === TimePickerAndroid.dismissedAction) { - // Dismissed - } - } catch ({code, message}) { - console.warn('Cannot open time picker', message); - } - ``` - - ```js - // Now - setTime = (event, date) => { - if (date === undefined) { - // dismissedAction - } - }; - ; - ``` diff --git a/example/.gitignore b/example/.gitignore deleted file mode 100644 index 7a6efe5dde4f327cac6424a127e712b88ec257c1..0000000000000000000000000000000000000000 --- a/example/.gitignore +++ /dev/null @@ -1,14 +0,0 @@ -*.binlog -*.hprof -*.xcworkspace/ -*.zip -.DS_Store -.gradle/ -.idea/ -.vs/ -Pods/ -build/ -dist/ -local.properties -msbuild.binlog -node_modules/ diff --git a/example/.watchmanconfig b/example/.watchmanconfig deleted file mode 100644 index 9e26dfeeb6e641a33dae4961196235bdb965b21b..0000000000000000000000000000000000000000 --- a/example/.watchmanconfig +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/example/App.js b/example/App.js deleted file mode 100644 index 2a591ac0603fc5d73f8268ae96a41f202b8a7387..0000000000000000000000000000000000000000 --- a/example/App.js +++ /dev/null @@ -1,634 +0,0 @@ -import { - SafeAreaView, - ScrollView, - StyleSheet, - View, - Text, - StatusBar, - Button, - Platform, - TextInput, - useColorScheme, - Switch, - Alert, - FlatList, -} from 'react-native'; -import DateTimePicker from '@react-native-community/datetimepicker'; -import SegmentedControl from './SegmentedControl'; -import {Colors} from 'react-native/Libraries/NewAppScreen'; -import React, {useRef, useState} from 'react'; -import {Picker} from 'react-native-windows'; -import moment from 'moment-timezone'; -import { - ANDROID_MODE, - DAY_OF_WEEK, - IOS_MODE, - ANDROID_DISPLAY, - IOS_DISPLAY, -} from '../src/constants'; -import * as RNLocalize from 'react-native-localize'; - -const timezone = [ - 120, - 0, - -120, - undefined, - 'America/New_York', - 'America/Vancouver', - 'Europe/London', - 'Europe/Istanbul', - 'Asia/Hong_Kong', - 'Australia/Brisbane', - 'Australia/Sydney', - 'Australia/Adelaide', -]; - -const ThemedText = (props) => { - const isDarkMode = useColorScheme() === 'dark'; - - const textColorByMode = {color: isDarkMode ? Colors.white : Colors.black}; - - const TextElement = React.createElement(Text, props); - return React.cloneElement(TextElement, { - style: [props.style, textColorByMode], - }); -}; -const ThemedTextInput = (props) => { - const isDarkMode = useColorScheme() === 'dark'; - - const textColorByMode = {color: isDarkMode ? Colors.white : Colors.black}; - - const TextElement = React.createElement(TextInput, props); - return React.cloneElement(TextElement, { - style: [props.style, styles.textInput, textColorByMode], - placeholderTextColor: isDarkMode ? Colors.white : Colors.black, - }); -}; - -const Info = ({testID, title, body}) => { - return ( - - {title} - - {body} - - - ); -}; - -const MODE_VALUES = Platform.select({ - ios: Object.values(IOS_MODE), - android: Object.values(ANDROID_MODE), - windows: [], -}); -const DISPLAY_VALUES = Platform.select({ - ios: Object.values(IOS_DISPLAY), - android: Object.values(ANDROID_DISPLAY), - windows: [], -}); -const MINUTE_INTERVALS = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30]; - -export const App = () => { - // Sat, 13 Nov 2021 10:00:00 GMT (local: Saturday, November 13, 2021 11:00:00 AM GMT+01:00) - const sourceMoment = moment.unix(1636765200); - const sourceDate = sourceMoment.local().toDate(); - const [date, setDate] = useState(sourceDate); - const [tzOffsetInMinutes, setTzOffsetInMinutes] = useState(undefined); - const [tzName, setTzName] = useState(RNLocalize.getTimeZone()); - const [mode, setMode] = useState(MODE_VALUES[0]); - const [show, setShow] = useState(false); - const [textColor, setTextColor] = useState(); - const [accentColor, setAccentColor] = useState(); - const [display, setDisplay] = useState(DISPLAY_VALUES[0]); - const [interval, setMinInterval] = useState(1); - const [neutralButtonLabel, setNeutralButtonLabel] = useState(undefined); - const [disabled, setDisabled] = useState(false); - const [minimumDate, setMinimumDate] = useState(); - const [maximumDate, setMaximumDate] = useState(); - - // Windows-specific - const [time, setTime] = useState(undefined); - const [maxDate] = useState(new Date('2021')); - const [minDate] = useState(new Date('2018')); - const [is24Hours, set24Hours] = useState(false); - const [firstDayOfWeek, setFirstDayOfWeek] = useState(DAY_OF_WEEK.Monday); - const [dateFormat, setDateFormat] = useState('longdate'); - const [dayOfWeekFormat, setDayOfWeekFormat] = useState( - '{dayofweek.abbreviated(2)}', - ); - - const scrollRef = useRef(null); - - const handleResetPress = () => { - setDate(undefined); - }; - - const onChange = (event, selectedDate) => { - if (Platform.OS === 'android') { - setShow(false); - } - if (event.type === 'dismissed') { - Alert.alert( - 'picker was dismissed', - undefined, - [ - { - text: 'great', - }, - ], - {cancelable: true}, - ); - return; - } - - if (event.type === 'neutralButtonPressed') { - setDate(new Date(0)); - } else { - setDate(selectedDate); - } - }; - - const onTimeChange = (event: any, newTime?: Date) => { - if (Platform.OS === 'windows') { - setTime(newTime); - } - }; - - const isDarkMode = useColorScheme() === 'dark'; - - const backgroundStyle = { - backgroundColor: isDarkMode ? Colors.dark : Colors.lighter, - }; - - const renderItem = ({item}) => { - const isNumber = typeof item === 'number'; - const title = isNumber - ? item > 0 - ? `+${item} mins` - : `${item} mins` - : item; - return ( - -