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

feat: add initialIndex & onMount props #30

Merged
merged 18 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,4 @@ nmHoistingLimits: workspaces
nodeLinker: node-modules

plugins:
spec: "@yarnpkg/plugin-interactive-tools"
spec: "@yarnpkg/plugin-workspace-tools"
spec: "@yarnpkg/plugin-workspace-tools"
18 changes: 12 additions & 6 deletions android/src/main/java/com/lodev09/truesheet/TrueSheetDialog.kt
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,7 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
else -> (maxScreenHeight * 0.5).toInt()
}

return when (maxSheetHeight) {
null -> height
else -> minOf(height, maxSheetHeight ?: maxScreenHeight)
}
return maxSheetHeight?.let { minOf(height, it, maxScreenHeight) } ?: minOf(height, maxScreenHeight)
}

/**
Expand Down Expand Up @@ -216,7 +213,7 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
* Also update footer's Y position.
*/
fun registerKeyboardManager() {
keyboardManager.registerKeyboardListener(object : KeyboardManager.OnKeyboardListener {
keyboardManager.registerKeyboardListener(object : KeyboardManager.OnKeyboardChangeListener {
override fun onKeyboardStateChange(isVisible: Boolean, visibleHeight: Int?) {
maxScreenHeight = when (isVisible) {
true -> visibleHeight ?: 0
Expand All @@ -228,6 +225,10 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
})
}

fun setOnSizeChangeListener(listener: RootSheetView.OnSizeChangeListener) {
rootSheetView.setOnSizeChangeListener(listener)
}

/**
* Remove keyboard listener.
*/
Expand Down Expand Up @@ -263,7 +264,12 @@ class TrueSheetDialog(private val reactContext: ThemedReactContext, private val
isFitToContents = false

setPeekHeight(getSizeHeight(sizes[0]), isShowing)
halfExpandedRatio = getSizeHeight(sizes[1]).toFloat() / maxScreenHeight.toFloat()

val size2 = getSizeHeight(sizes[1])
if (size2 < maxScreenHeight) {
halfExpandedRatio = size2.toFloat() / maxScreenHeight.toFloat()
}

maxHeight = getSizeHeight(sizes[2])
}
}
Expand Down
59 changes: 46 additions & 13 deletions android/src/main/java/com/lodev09/truesheet/TrueSheetView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import com.facebook.react.uimanager.events.EventDispatcher
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.lodev09.truesheet.core.DismissEvent
import com.lodev09.truesheet.core.PresentEvent
import com.lodev09.truesheet.core.ReadyEvent
import com.lodev09.truesheet.core.RootSheetView
import com.lodev09.truesheet.core.SizeChangeEvent

Expand All @@ -27,6 +28,8 @@ class TrueSheetView(context: Context) :
private val surfaceId: Int
get() = UIManagerHelper.getSurfaceId(this)

private var initialIndex: Int = -1

/**
* Current activeIndex.
*/
Expand All @@ -52,11 +55,6 @@ class TrueSheetView(context: Context) :
*/
private val rootSheetView: RootSheetView

/**
* 2nd child of the container view.
*/
private var footerView: ViewGroup? = null

init {
reactContext.addLifecycleEventListener(this)
eventDispatcher = UIManagerHelper.getEventDispatcherForReactTag(reactContext, id)
Expand All @@ -83,7 +81,7 @@ class TrueSheetView(context: Context) :
presentPromise = null
}

// dispatch onPresent event
// Dispatch onPresent event
eventDispatcher?.dispatchEvent(PresentEvent(surfaceId, id, sheetDialog.getSizeInfoForIndex(currentSizeIndex)))
}

Expand All @@ -97,10 +95,17 @@ class TrueSheetView(context: Context) :
dismissPromise = null
}

// dispatch onDismiss event
// Dispatch onDismiss event
eventDispatcher?.dispatchEvent(DismissEvent(surfaceId, id))
}

// Configure when showing and size changed
setOnSizeChangeListener(object : RootSheetView.OnSizeChangeListener {
override fun onSizeChange(width: Int, height: Int) {
maxScreenHeight = height
}
})

// Configure sheet behavior events
behavior.addBottomSheetCallback(
object : BottomSheetBehavior.BottomSheetCallback() {
Expand Down Expand Up @@ -132,7 +137,7 @@ class TrueSheetView(context: Context) :
currentSizeIndex = sizeInfo.index
setupDimmedBackground(sizeInfo.index)

// dispatch onSizeChange event
// Dispatch onSizeChange event
eventDispatcher?.dispatchEvent(SizeChangeEvent(surfaceId, id, sizeInfo))
}
}
Expand Down Expand Up @@ -164,13 +169,27 @@ class TrueSheetView(context: Context) :
visibility = GONE

(child as ViewGroup).let {
// Container View's first child is the Content View
footerView = it.getChildAt(1) as ViewGroup

sheetDialog.footerView = footerView

// rootView's first child is the Container View
rootSheetView.addView(it, index)

// Initialize content
UiThreadUtil.runOnUiThread {
// 1st child is the content view
val contentView = it.getChildAt(0) as ViewGroup
setContentHeight(contentView.height)

// 2nd child is the footer view
val footerView = it.getChildAt(1) as ViewGroup
sheetDialog.footerView = footerView
setFooterHeight(footerView.height)

if (initialIndex >= 0) {
sheetDialog.present(initialIndex)
}

// Dispatch onReady event
eventDispatcher?.dispatchEvent(ReadyEvent(surfaceId, id))
}
}
}

Expand Down Expand Up @@ -224,28 +243,42 @@ class TrueSheetView(context: Context) :
}

fun setMaxHeight(height: Int) {
if (sheetDialog.maxSheetHeight == height) return

sheetDialog.maxSheetHeight = height
configureIfShowing()
}

fun setContentHeight(height: Int) {
if (sheetDialog.contentHeight == height) return

sheetDialog.contentHeight = height
configureIfShowing()
}

fun setFooterHeight(height: Int) {
if (sheetDialog.footerHeight == height) return

sheetDialog.footerHeight = height
configureIfShowing()
}

fun setDimmed(dimmed: Boolean) {
if (sheetDialog.dimmed == dimmed) return

sheetDialog.dimmed = dimmed
if (sheetDialog.isShowing) {
sheetDialog.setupDimmedBackground(currentSizeIndex)
}
}

fun setInitialIndex(index: Int) {
initialIndex = index
}

fun setDimmedIndex(index: Int) {
if (sheetDialog.dimmedIndex == index) return

sheetDialog.dimmedIndex = index
if (sheetDialog.isShowing) {
sheetDialog.setupDimmedBackground(currentSizeIndex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.facebook.react.uimanager.ViewGroupManager
import com.facebook.react.uimanager.annotations.ReactProp
import com.lodev09.truesheet.core.DismissEvent
import com.lodev09.truesheet.core.PresentEvent
import com.lodev09.truesheet.core.ReadyEvent
import com.lodev09.truesheet.core.SizeChangeEvent
import com.lodev09.truesheet.core.Utils

Expand All @@ -24,6 +25,7 @@ class TrueSheetViewManager : ViewGroupManager<TrueSheetView>() {

override fun getExportedCustomDirectEventTypeConstants(): MutableMap<String, Any>? =
MapBuilder.builder<String, Any>()
.put(ReadyEvent.EVENT_NAME, MapBuilder.of("registrationName", "onReady"))
.put(PresentEvent.EVENT_NAME, MapBuilder.of("registrationName", "onPresent"))
.put(DismissEvent.EVENT_NAME, MapBuilder.of("registrationName", "onDismiss"))
.put(SizeChangeEvent.EVENT_NAME, MapBuilder.of("registrationName", "onSizeChange"))
Expand All @@ -44,6 +46,11 @@ class TrueSheetViewManager : ViewGroupManager<TrueSheetView>() {
view.setDimmed(dimmed)
}

@ReactProp(name = "initialIndex")
lodev09 marked this conversation as resolved.
Show resolved Hide resolved
fun setInitialIndex(view: TrueSheetView, index: Int) {
view.setInitialIndex(index)
}

@ReactProp(name = "dimmedIndex")
fun setDimmedIndex(view: TrueSheetView, index: Int) {
view.setDimmedIndex(index)
Expand Down
11 changes: 11 additions & 0 deletions android/src/main/java/com/lodev09/truesheet/core/Events.kt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,17 @@ class PresentEvent(surfaceId: Int, viewId: Int, private val sizeInfo: SizeInfo)
}
}

// onReady
class ReadyEvent(surfaceId: Int, viewId: Int) : Event<PresentEvent>(surfaceId, viewId) {
override fun getEventName() = EVENT_NAME

override fun getEventData(): WritableMap = Arguments.createMap()

companion object {
const val EVENT_NAME = "ready"
}
}

// onDismiss
class DismissEvent(surfaceId: Int, viewId: Int) : Event<PresentEvent>(surfaceId, viewId) {
override fun getEventName() = EVENT_NAME
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import android.view.inputmethod.InputMethodManager
import com.facebook.react.bridge.ReactContext

class KeyboardManager(reactContext: ReactContext) {
interface OnKeyboardListener {
interface OnKeyboardChangeListener {
fun onKeyboardStateChange(isVisible: Boolean, visibleHeight: Int?)
}

Expand All @@ -20,7 +20,7 @@ class KeyboardManager(reactContext: ReactContext) {
contentView = activity?.findViewById(android.R.id.content)
}

fun registerKeyboardListener(listener: OnKeyboardListener?) {
fun registerKeyboardListener(listener: OnKeyboardChangeListener?) {
contentView?.apply {
unregisterKeyboardListener()

Expand Down
41 changes: 26 additions & 15 deletions android/src/main/java/com/lodev09/truesheet/core/RootSheetView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,26 @@ import com.facebook.react.views.view.ReactViewGroup
* styleHeight on the LayoutShadowNode to be the window size. This is done through the
* UIManagerModule, and will then cause the children to layout as if they can fill the window.
*/
class RootSheetView(context: Context?) :
class RootSheetView(private val context: Context?) :
ReactViewGroup(context),
RootView {
private var hasAdjustedSize = false
private var viewWidth = 0
private var viewHeight = 0

private val mJSTouchDispatcher = JSTouchDispatcher(this)
private var mJSPointerDispatcher: JSPointerDispatcher? = null
private val jSTouchDispatcher = JSTouchDispatcher(this)
private var jSPointerDispatcher: JSPointerDispatcher? = null
private var sizeChangeListener: OnSizeChangeListener? = null

var eventDispatcher: EventDispatcher? = null

interface OnSizeChangeListener {
fun onSizeChange(width: Int, height: Int)
}

init {
if (ReactFeatureFlags.dispatchPointerEvents) {
mJSPointerDispatcher = JSPointerDispatcher(this)
jSPointerDispatcher = JSPointerDispatcher(this)
}
}

Expand All @@ -50,6 +55,12 @@ class RootSheetView(context: Context?) :
viewWidth = w
viewHeight = h
updateFirstChildView()

sizeChangeListener?.onSizeChange(w, h)
}

fun setOnSizeChangeListener(listener: OnSizeChangeListener) {
sizeChangeListener = listener
}

private fun updateFirstChildView() {
Expand Down Expand Up @@ -88,15 +99,15 @@ class RootSheetView(context: Context?) :
get() = context as ThemedReactContext

override fun onInterceptTouchEvent(event: MotionEvent): Boolean {
mJSTouchDispatcher.handleTouchEvent(event, eventDispatcher)
mJSPointerDispatcher?.handleMotionEvent(event, eventDispatcher, true)
jSTouchDispatcher.handleTouchEvent(event, eventDispatcher)
jSPointerDispatcher?.handleMotionEvent(event, eventDispatcher, true)
return super.onInterceptTouchEvent(event)
}

@SuppressLint("ClickableViewAccessibility")
override fun onTouchEvent(event: MotionEvent): Boolean {
mJSTouchDispatcher.handleTouchEvent(event, eventDispatcher)
mJSPointerDispatcher?.handleMotionEvent(event, eventDispatcher, false)
jSTouchDispatcher.handleTouchEvent(event, eventDispatcher)
jSPointerDispatcher?.handleMotionEvent(event, eventDispatcher, false)
super.onTouchEvent(event)

// In case when there is no children interested in handling touch event, we return true from
Expand All @@ -105,28 +116,28 @@ class RootSheetView(context: Context?) :
}

override fun onInterceptHoverEvent(event: MotionEvent): Boolean {
mJSPointerDispatcher?.handleMotionEvent(event, eventDispatcher, true)
jSPointerDispatcher?.handleMotionEvent(event, eventDispatcher, true)
return super.onHoverEvent(event)
}

override fun onHoverEvent(event: MotionEvent): Boolean {
mJSPointerDispatcher?.handleMotionEvent(event, eventDispatcher, false)
jSPointerDispatcher?.handleMotionEvent(event, eventDispatcher, false)
return super.onHoverEvent(event)
}

@Deprecated("Deprecated in Java")
override fun onChildStartedNativeGesture(ev: MotionEvent?) {
mJSTouchDispatcher.onChildStartedNativeGesture(ev, eventDispatcher)
jSTouchDispatcher.onChildStartedNativeGesture(ev, eventDispatcher)
}

override fun onChildStartedNativeGesture(childView: View, ev: MotionEvent) {
mJSTouchDispatcher.onChildStartedNativeGesture(ev, eventDispatcher)
mJSPointerDispatcher?.onChildStartedNativeGesture(childView, ev, eventDispatcher)
jSTouchDispatcher.onChildStartedNativeGesture(ev, eventDispatcher)
jSPointerDispatcher?.onChildStartedNativeGesture(childView, ev, eventDispatcher)
}

override fun onChildEndedNativeGesture(childView: View, ev: MotionEvent) {
mJSTouchDispatcher.onChildEndedNativeGesture(ev, eventDispatcher)
mJSPointerDispatcher?.onChildEndedNativeGesture()
jSTouchDispatcher.onChildEndedNativeGesture(ev, eventDispatcher)
jSPointerDispatcher?.onChildEndedNativeGesture()
}

override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
Expand Down
Binary file modified docs/docs/guides/dimming/dimming.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/docs/intro.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import preview from '/img/preview.gif'

The **_true_** native bottom sheet experience for your [React Native](https://reactnative.dev) Apps.

<img alt="preview" src={preview} width="600"/>
<img alt="preview" src={preview} width="300"/>

## Features

Expand Down
16 changes: 16 additions & 0 deletions docs/docs/reference/01-props.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,18 @@ Specify whether the sheet background is dimmed. Set to `false` to allow interact
| - | - | - | - |
| `boolean` | `true` | ✅ | ✅ |

### `initialIndex`

Initially present the sheet, after loading, at a given size index.

| Type | Default | 🍎 | 🤖 |
| - | - | - | - |
| `number` | `-1` | ✅ | ✅ |

:::info
This property is only used during the initial load.
:::

### `dimmedIndex`

The size index that the sheet should start to dim the background.
Expand Down Expand Up @@ -185,6 +197,10 @@ const App = () => {
}
```

### `onReady`

This is called when the sheet is ready to present. Use this event to [`present`](/reference/methods#present) the sheet during mount.

### `onPresent`

Comes with [`SizeInfo`](/reference/types#sizeinfo).
Expand Down
Loading