Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for date range picker on Android #956

Open
wants to merge 7 commits into
base: master
Choose a base branch
from

Conversation

sidorchukandrew
Copy link
Collaborator

Summary

This adds support for Material 3's date range picker. I've added this as an imperative API similar to how the date and time pickers can be called imperatively on Android. Many of the props the new date Material date picker supports are supported here as well. There are some small differences in the following props: value and onChange.

value must be a Range object that looks like {start: Date?, end: Date?}. These are optional and the value prop itself is optional. Leaving it undefined will open the picker with a clean slate.

onChange returns a startTimestamp and endTimestamp in the nativeEvent payload and returns a Range object as the second parameter.

See the README for a screenshot.

Test Plan

What's required for testing (prerequisites)?

What are the steps to reproduce (after prerequisites)?

Compatibility

OS Implemented
iOS
Android

Checklist

  • I have tested this on a device and a simulator
  • I added the documentation in README.md
  • I updated the typed files (TS and Flow)
  • I added a sample use of the API in the example project (example/App.js)
  • I have added automated tests, either in JS or e2e tests, as applicable

This implementation models how the Material date picker was
implemented. However, the range picker returns two values and
accepts two values for the start and end of the range.
Since this is a new module, I think we should only support the
imperative API the same way we encourage developers to use the
imperative API for the date and time pickers.
@sidorchukandrew sidorchukandrew marked this pull request as ready for review February 4, 2025 15:19
Copy link
Member

@vonovak vonovak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! Left some comments for improvement :) 👍


class MaterialRangePickerModule(reactContext: ReactApplicationContext): NativeModuleMaterialRangePickerSpec(reactContext) {
companion object {
const val NAME = "RNCMaterialRangePicker"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm not mistaken, NativeModuleMaterialRangePickerSpec generated by codegen already should contain the name, and so specifying it here should not be needed. also override fun getName should be in the generated code.
if not, it's fine

Comment on lines +27 to +34
val activity = currentActivity as FragmentActivity?
if (activity == null) {
promise.reject(
RNConstants.ERROR_NO_ACTIVITY,
"Tried to open a MaterialRangePicker dialog while not attached to an Activity"
)
return
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
val activity = currentActivity as FragmentActivity?
if (activity == null) {
promise.reject(
RNConstants.ERROR_NO_ACTIVITY,
"Tried to open a MaterialRangePicker dialog while not attached to an Activity"
)
return
}
val activity = currentActivity as FragmentActivity? ?: run {
return promise.reject(
RNConstants.ERROR_NO_ACTIVITY,
"Tried to open a MaterialRangePicker dialog while not attached to an Activity"
)
}

this is more kotlin-style; just a suggestion. I'm not sure how it'll work with the cast though.


if (args.containsKey(RNConstants.ARG_START_TIMESTAMP)) {
// override "value" so we can use the same constructor from RNDate
args.putLong(RNConstants.ARG_VALUE, args.getLong((RNConstants.ARG_START_TIMESTAMP)))
Copy link
Member

@vonovak vonovak Mar 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rather than mutating args in order to use some constructor of RNDate, I'd add another constructor to RNDate which accepts Long value

Comment on lines +67 to +70
val title = args.getString(RNConstants.ARG_TITLE)
if (!title.isNullOrEmpty()) {
builder.setTitleText(args.getString(RNConstants.ARG_TITLE))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
val title = args.getString(RNConstants.ARG_TITLE)
if (!title.isNullOrEmpty()) {
builder.setTitleText(args.getString(RNConstants.ARG_TITLE))
}
args.getString(RNConstants.ARG_TITLE)?.let {
builder.setTitleText(it)
}

more kotlin-y. You can use this pattern more across this file pls, e.g in setButtons.

Comment on lines +163 to +171
val result = WritableNativeMap()

result.putString("action", RNConstants.ACTION_RANGE_SET)
result.putDouble("startTimestamp", getStartTimestamp(selection))
result.putDouble("endTimestamp", getEndTimestamp(selection))
result.putDouble(
"utcOffset",
getStartTimestamp(selection) / 1000 / 60
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
val result = WritableNativeMap()
result.putString("action", RNConstants.ACTION_RANGE_SET)
result.putDouble("startTimestamp", getStartTimestamp(selection))
result.putDouble("endTimestamp", getEndTimestamp(selection))
result.putDouble(
"utcOffset",
getStartTimestamp(selection) / 1000 / 60
)
val result = WritableNativeMap().apply {
putString("action", RNConstants.ACTION_RANGE_SET)
putDouble("startTimestamp", getStartTimestamp(selection))
putDouble("endTimestamp", getEndTimestamp(selection))
putDouble(
"utcOffset",
getStartTimestamp(selection) / 1000 / 60
)
}

more koltin-y. You can use apply in many places throughout this file to save keystrokes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants