diff --git a/.circleci/config.yml b/.circleci/config.yml index b0310482..c4fdfb29 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,31 +1,24 @@ version: 2.1 orbs: - rn: react-native-community/react-native@4.4.2 + rn: react-native-community/react-native@5.6.2 + android: circleci/android@1.0.3 # - 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: - checkout_code: + analyse_js: executor: name: rn/linux_js - node_version: '12.10.0' + node_version: '14.17.0' steps: - checkout - - persist_to_workspace: - paths: . - root: . - analyse_js: - executor: rn/linux_js - steps: - - attach_workspace: - at: . # - 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 --ignore-engines + command: yarn install --frozen-lockfile name: yarn install - run: command: yarn lint @@ -36,84 +29,96 @@ jobs: - run: command: yarn test name: Jest + e2e_release_ios: executor: name: rn/macos - xcode_version: '11.4.0' + xcode_version: '13.1.0' steps: - - attach_workspace: - at: . - - rn/setup_macos_executor: - node_version: '12.10.0' + - 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 11' # - rn/yarn_install - run: - command: yarn install --frozen-lockfile --ignore-engines + command: yarn install --frozen-lockfile name: yarn install - rn/pod_install: pod_install_directory: 'example/ios' + - run: + command: curl https://raw.githubusercontent.com/facebook/react-native/6334ac35ac3cbc2c84b2d46d46ec118bf9bf714d/scripts/find-node.sh > node_modules/react-native/scripts/find-node.sh + name: fix issue with nvm # will be fixed in RN 67 (https://github.com/react-native-community/upgrade-support/issues/138) - run: command: yarn detox:ios:build:release - name: build for detox + name: build app for e2e tests - run: command: yarn detox:ios:test:release - name: test detox + name: run e2e tests - store_artifacts: path: ./artifacts + e2e_release_android: - # we need to use mac to run emulator with acceleration - # see https://support.circleci.com/hc/en-us/articles/360000028928-Testing-with-Android-emulator-on-CircleCI-2-0 executor: - name: rn/macos - xcode_version: '11.4.0' + name: android/android-machine + resource-class: large steps: - - attach_workspace: - at: . - - rn/setup_macos_executor: - node_version: '12.10.0' - # - rn/yarn_install + - checkout - run: - command: yarn install --frozen-lockfile --ignore-engines + name: change default node version + command: | + nvm install v15.11.0 + nvm alias default v15.11.0 + echo 'export PATH=/opt/circleci/.nvm/versions/node/v15.11.0/bin:$PATH' >> $BASH_ENV + - android/create-avd: + avd-name: TestingAVD + system-image: system-images;android-29;default;x86 + install: true + - android/start-emulator: + avd-name: TestingAVD + no-window: true + restore-gradle-cache-prefix: v1a + post-emulator-launch-assemble-command: "pwd" + - android/disable-animations + - run: + command: npm install --global yarn + name: install yarn + - run: + command: yarn install --frozen-lockfile name: yarn install - - rn/android_emulator_start: - logcat_grep: 'com.reactcommunity.rndatetimepicker' - run: command: yarn detox:android:build:release - name: build for detox + name: build app for e2e tests - run: command: yarn detox:android:test:release - name: test detox + name: run e2e tests - store_artifacts: path: ./artifacts + publish: - executor: rn/linux_js + executor: + name: rn/linux_js + node_version: '14.17.0' steps: - - attach_workspace: - at: . + - 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 --ignore-engines + command: yarn install --frozen-lockfile name: yarn install - run: command: npx semantic-release name: Publish to NPM - workflows: test: jobs: - - checkout_code - - analyse_js: - requires: - - checkout_code - - e2e_release_ios: - requires: - - analyse_js - - e2e_release_android: - requires: - - analyse_js + - analyse_js + - e2e_release_ios + - e2e_release_android - publish: requires: - e2e_release_android diff --git a/.flowconfig b/.flowconfig index 139d17dc..4320b707 100644 --- a/.flowconfig +++ b/.flowconfig @@ -8,20 +8,9 @@ ; Ignore polyfills node_modules/react-native/Libraries/polyfills/.* -; These should not be required directly -; require from fbjs/lib instead: require('fbjs/lib/warning') -node_modules/warning/.* - ; Flow doesn't support platforms .*/Libraries/Utilities/LoadingView.js -; These should not be required directly -; require from fbjs/lib instead: require('fbjs/lib/warning') -node_modules/warning/.* - -; Flow doesn't support platforms -.*/Libraries/Utilities/HMRLoadingView.js - [untyped] .*/node_modules/@react-native-community/cli/.*/.* @@ -32,12 +21,11 @@ node_modules/react-native/interface.js node_modules/react-native/flow/ [options] -module.system.node.resolve_dirname=node_modules -module.system.node.resolve_dirname=src emoji=true -esproposal.optional_chaining=enable -esproposal.nullish_coalescing=enable +exact_by_default=true + +format.bracket_spacing=false module.file_ext=.js module.file_ext=.json @@ -53,10 +41,6 @@ suppress_type=$FlowFixMe suppress_type=$FlowFixMeProps suppress_type=$FlowFixMeState -suppress_comment=\\(.\\|\n\\)*\\$FlowFixMe\\($\\|[^(]\\|(\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\) -suppress_comment=\\(.\\|\n\\)*\\$FlowIssue\\((\\(\\)? *\\(site=[a-z,_]*react_native\\(_ios\\)?_\\(oss\\|fb\\)[a-z,_]*\\)?)\\)?:? #[0-9]+ -suppress_comment=\\(.\\|\n\\)*\\$FlowExpectedError - [lints] sketchy-null-number=warn sketchy-null-mixed=warn @@ -65,10 +49,8 @@ untyped-type-import=warn nonstrict-import=warn deprecated-type=warn unsafe-getters-setters=warn -inexact-spread=warn unnecessary-invariant=warn signature-verification-failure=warn -deprecated-utility=error [strict] deprecated-type @@ -80,4 +62,4 @@ untyped-import untyped-type-import [version] -^0.113.0 +^0.158.0 diff --git a/README.md b/README.md index 801eaacb..4bbb438c 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,6 @@ Support us with a monthly donation and help us continue our activities. [Become - # React Native DateTimePicker This repository was moved out of the react native community GH organization, in accordance to [this proposal](https://github.com/react-native-community/discussions-and-proposals/issues/176). @@ -22,7 +21,7 @@ The module is still published on `npm` under the old namespace (as documented) b [![Lean Core Badge][lean-core-badge]][lean-core-issue] React Native date & time picker component for iOS, Android and Windows. - + @@ -87,7 +86,8 @@ React Native date & time picker component for iOS, Android and Windows. ## Requirements -- Xcode >= 11.6 +- Only Android API level >=21 (Android 5), iOS >= 11 are supported. +- Tested with Xcode 13.0 and RN 0.66.3. Other configurations are very likely to work as well but have not been tested. ## Expo users notice @@ -105,24 +105,12 @@ or yarn add @react-native-community/datetimepicker ``` -Autolinking is not yet implemented on Windows, so [Manual installation](#windows) is needed. +Autolinking is not yet implemented on Windows, so [manual installation ](/docs/manual-installation.md) is needed. #### RN >= 0.60 If you are using RN >= 0.60, only run `npx pod-install`. Then rebuild your project. -#### RN < 0.60 - -For RN < 0.60, you need to link the dependency using `react-native link`: - -```bash -react-native link @react-native-community/datetimepicker -``` - -Then run `npx pod-install` and rebuild your project. - -If this does not work, see [Manual installation](#manual-installation). - ## General Usage ```js @@ -270,7 +258,8 @@ Defines the minimum date that can be selected. Note that on Android, this only w #### `timeZoneOffsetInMinutes` (`optional`, `iOS and Android only`) -Allows changing of the timeZone of the date picker. By default it uses the device's time zone. +Allows changing of the timeZone of the date picker. By default, it uses the device's time zone. +We strongly recommend avoiding this prop on android because of known issues in the implementation (eg. [#528](https://github.com/react-native-datetimepicker/datetimepicker/issues/528)). ```js // GMT+1 @@ -321,21 +310,6 @@ Allows changing of the textColor of the date picker. Has effect only when `displ ``` -#### `themeVariant` (`optional`, `iOS only`) - -Allows overriding system theme variant (dark or light mode) used by the date picker. - -:warning: Has effect only on iOS 14 and later. On iOS 13 & less, use `textColor` to make the picker dark-theme compatible - -List of possible values: - -- `"light"` -- `"dark"` - -```js - -``` - #### `locale` (`optional`, `iOS only`) Allows changing of the locale of the component. By default it uses the device's locale. @@ -380,350 +354,42 @@ Sets style directly on picker component. By default, the picker height is fixed Please note that by default, picker's text color is controlled by the application theme (light / dark mode). In dark mode, text is white and in light mode, text is black. -This means that eg. if the device has dark mode turned on, and your screen background color is white, you will not see the picker. Please use the `Appearance` api to adjust the picker's background color so that it is visible, as we do in the [example App](/example/App.js) or [opt-out from dark mode](https://stackoverflow.com/a/56546554/2070942). +This means that eg. if the device has dark mode turned on, and your screen background color is white, you will not see the picker. Please use the `Appearance` api to adjust the picker's background color so that it is visible, as we do in the [example App](/example/App.js), use `themeVariant` prop or [opt-out from dark mode](https://stackoverflow.com/a/56546554/2070942). ```js ``` -#### `disabled` (`optional`, `iOS only`) - -If true, the user won't be able to interact with the view. - -## 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 - } - }; - ; - ``` - -## Contributing to the component - -Please see [CONTRIBUTING.md](CONTRIBUTING.md) - -## 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`: +#### `themeVariant` (`optional`, `iOS only`) - ```diff - + import com.reactcommunity.rndatetimepicker.RNDateTimePickerPackage; +Allows overriding system theme variant (dark or light mode) used by the date picker. - public class MainApplication extends Application implements ReactApplication { +:warning: Has effect only on iOS 14 and later. On iOS 13 & less, use `textColor` to make the picker dark-theme compatible - @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; - } - } - ``` +List of possible values: -#### Windows +- `"light"` +- `"dark"` -##### Add the DateTimePickerWindows project to your solution +```js + +``` -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' +#### `disabled` (`optional`, `iOS only`) -##### **windows/myapp.sln** +If true, the user won't be able to interact with the view. -Add a reference to `DateTimePickerWindows` to your main application project. From Visual Studio 2019: +## Migration from the older components -Right-click main application project > Add > Reference... -Check 'DateTimePickerWindows' from the 'Project > Solution' tab on the left. +Please see [migration.md](/docs/migration.md) -##### **pch.h** +## Contributing to the component -Add `#include "winrt/DateTimePicker.h"`. +Please see [CONTRIBUTING.md](CONTRIBUTING.md) -##### **app.cpp** +## Manual installation -Add `PackageProviders().Append(winrt::DateTimePicker::ReactPackageProvider());` before `InitializeComponent();`. +Please see [manual-installation.md](/docs/manual-installation.md) ## Running the example app diff --git a/android/build.gradle b/android/build.gradle index 012bf165..f0c168ed 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -1,7 +1,8 @@ apply plugin: 'com.android.library' def safeExtGet(prop, fallback) { - rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback + def retValue = rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback + return retValue } android { @@ -9,7 +10,7 @@ android { buildToolsVersion safeExtGet('buildToolsVersion', '28.0.3') defaultConfig { - minSdkVersion safeExtGet('minSdkVersion', 16) + minSdkVersion safeExtGet('minSdkVersion', 21) targetSdkVersion safeExtGet('targetSdkVersion', 28) versionCode 1 versionName "1.0" diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDialogFragment.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDialogFragment.java index 3466848f..e7728ad9 100644 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDialogFragment.java +++ b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNDatePickerDialogFragment.java @@ -66,47 +66,33 @@ DatePickerDialog getDialog( display = RNDatePickerDisplay.valueOf(args.getString(RNConstants.ARG_DISPLAY).toUpperCase(Locale.US)); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - switch (display) { - case CALENDAR: - case SPINNER: - String resourceName = display == RNDatePickerDisplay.CALENDAR - ? "CalendarDatePickerDialog" - : "SpinnerDatePickerDialog"; - return new RNDismissableDatePickerDialog( - activityContext, - activityContext.getResources().getIdentifier( - resourceName, - "style", - activityContext.getPackageName()), - onDateSetListener, - year, - month, - day, - display - ); - default: - return new RNDismissableDatePickerDialog( - activityContext, - onDateSetListener, - year, - month, - day, - display - ); - } - } else { - DatePickerDialog dialog = new RNDismissableDatePickerDialog(activityContext, onDateSetListener, year, month, day, display); - switch (display) { - case CALENDAR: - dialog.getDatePicker().setCalendarViewShown(true); - dialog.getDatePicker().setSpinnersShown(false); - break; - case SPINNER: - dialog.getDatePicker().setCalendarViewShown(false); - break; - } - return dialog; + switch (display) { + case CALENDAR: + case SPINNER: + String resourceName = display == RNDatePickerDisplay.CALENDAR + ? "CalendarDatePickerDialog" + : "SpinnerDatePickerDialog"; + return new RNDismissableDatePickerDialog( + activityContext, + activityContext.getResources().getIdentifier( + resourceName, + "style", + activityContext.getPackageName()), + onDateSetListener, + year, + month, + day, + display + ); + default: + return new RNDismissableDatePickerDialog( + activityContext, + onDateSetListener, + year, + month, + day, + display + ); } } diff --git a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogFragment.java b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogFragment.java index 0df49a20..c75a5f45 100644 --- a/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogFragment.java +++ b/android/src/main/java/com/reactcommunity/rndatetimepicker/RNTimePickerDialogFragment.java @@ -71,28 +71,24 @@ static TimePickerDialog getDialog( is24hour = args.getBoolean(RNConstants.ARG_IS24HOUR, DateFormat.is24HourFormat(activityContext)); } - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - switch (display) { - case CLOCK: - case SPINNER: - String resourceName = display == RNTimePickerDisplay.CLOCK - ? "ClockTimePickerDialog" - : "SpinnerTimePickerDialog"; - return new RNDismissableTimePickerDialog( - activityContext, - activityContext.getResources().getIdentifier( - resourceName, - "style", - activityContext.getPackageName() - ), - onTimeSetListener, - hour, - minute, - minuteInterval, - is24hour, - display - ); - } + if (display == RNTimePickerDisplay.CLOCK || display == RNTimePickerDisplay.SPINNER) { + String resourceName = display == RNTimePickerDisplay.CLOCK + ? "ClockTimePickerDialog" + : "SpinnerTimePickerDialog"; + return new RNDismissableTimePickerDialog( + activityContext, + activityContext.getResources().getIdentifier( + resourceName, + "style", + activityContext.getPackageName() + ), + onTimeSetListener, + hour, + minute, + minuteInterval, + is24hour, + display + ); } return new RNDismissableTimePickerDialog( activityContext, diff --git a/docs/manual-installation.md b/docs/manual-installation.md new file mode 100644 index 00000000..8684fce2 --- /dev/null +++ b/docs/manual-installation.md @@ -0,0 +1,105 @@ +## 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 new file mode 100644 index 00000000..f7ca9fb2 --- /dev/null +++ b/docs/migration.md @@ -0,0 +1,224 @@ +## 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/App.js b/example/App.js index b1270b55..df702d7b 100644 --- a/example/App.js +++ b/example/App.js @@ -12,7 +12,7 @@ import { Switch, } from 'react-native'; import DateTimePicker from '@react-native-community/datetimepicker'; -import SegmentedControl from '@react-native-community/segmented-control'; +import SegmentedControl from '@react-native-segmented-control/segmented-control'; import {Colors} from 'react-native/Libraries/NewAppScreen'; import React, {useState} from 'react'; import {Picker} from 'react-native-windows'; @@ -24,6 +24,7 @@ import { ANDROID_DISPLAY, IOS_DISPLAY, } from '../src/constants'; +import * as RNLocalize from 'react-native-localize'; const ThemedText = (props) => { const isDarkMode = useColorScheme() === 'dark'; @@ -60,8 +61,10 @@ const DISPLAY_VALUES = Platform.select({ const MINUTE_INTERVALS = [1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30]; export const App = () => { - const [date, setDate] = useState(new Date(1598051730000)); - const [tzOffsetInMinutes, setTzOffsetInMinutes] = useState(0); + // Sat, 13 Nov 2021 10:00:00 GMT (local: Saturday, November 13, 2021 11:00:00 AM GMT+01:00) + const sourceDate = moment.unix(1636797600).local().toDate(); + const [date, setDate] = useState(sourceDate); + const [tzOffsetInMinutes, setTzOffsetInMinutes] = useState(undefined); const [mode, setMode] = useState(MODE_VALUES[0]); const [show, setShow] = useState(false); const [color, setColor] = useState(); @@ -130,6 +133,11 @@ export const App = () => { Example DateTime Picker + + TZ: {RNLocalize.getTimeZone()}, TZOffset:{' '} + {new Date().getTimezoneOffset() / 60} original:{' '} + {moment(sourceDate).format('MM/DD/YYYY HH:mm')} + mode prop: { testID="neutralButtonLabelTextInput" /> - [android] show and dismiss picker after 3 secs @@ -207,8 +214,11 @@ export const App = () => { title="Show and dismiss picker!" /> - - +
iOS