This commit is contained in:
Hailey
2024-10-02 17:53:33 -07:00
parent d007151f49
commit 2ac8308ecb
4 changed files with 100 additions and 78 deletions
@@ -11,7 +11,10 @@ import expo.modules.kotlin.AppContext
import expo.modules.kotlin.viewevent.EventDispatcher
import expo.modules.kotlin.views.ExpoView
class BottomSheetView(context: Context, appContext: AppContext) : ExpoView(context, appContext) {
class BottomSheetView(
context: Context,
appContext: AppContext,
) : ExpoView(context, appContext) {
val sheetState = mutableStateOf(SheetState())
private var reactRootView: ReactRootView? = null
@@ -33,9 +36,11 @@ class BottomSheetView(context: Context, appContext: AppContext) : ExpoView(conte
field = value
this.sheetState.value.isOpen = value
onStateChange(mapOf(
"state" to if (value) "open" else "closed"
))
onStateChange(
mapOf(
"state" to if (value) "open" else "closed",
),
)
}
private var isOpening: Boolean = false
@@ -58,13 +63,26 @@ class BottomSheetView(context: Context, appContext: AppContext) : ExpoView(conte
// Lifecycle
override fun addView(child: View?, index: Int) {
override fun addView(
child: View?,
index: Int,
) {
this.innerView = child
}
override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
override fun onLayout(
changed: Boolean,
l: Int,
t: Int,
r: Int,
b: Int,
) {
this.innerView?.let {
val height = it.allViews.last().measuredHeight.toFloat()
val height =
it.allViews
.last()
.measuredHeight
.toFloat()
this.present(height)
}
}
@@ -92,32 +110,33 @@ class BottomSheetView(context: Context, appContext: AppContext) : ExpoView(conte
this.reactRootView = reactRootView
this.isOpening = true
this.sheetView = ComposeView(context).also {
it.setContent {
SheetView(
state = sheetState,
innerView = reactRootView,
contentHeight = innerView.height.toFloat(),
onDismissRequest = {
onAttemptDismiss(mapOf())
if (!preventDismiss) {
dismiss()
}
},
onExpanded = {
isOpening = false
isOpen = true
hasInitiallyOpened = true
},
onHidden = {
if (hasInitiallyOpened) {
destroy()
}
}
)
this.sheetView =
ComposeView(context).also {
it.setContent {
SheetView(
state = sheetState,
innerView = reactRootView,
contentHeight = innerView.height.toFloat(),
onDismissRequest = {
onAttemptDismiss(mapOf())
if (!preventDismiss) {
dismiss()
}
},
onExpanded = {
isOpening = false
isOpen = true
hasInitiallyOpened = true
},
onHidden = {
if (hasInitiallyOpened) {
destroy()
}
},
)
}
getRootLayout().addView(it)
}
getRootLayout().addView(it)
}
}
fun dismiss() {
@@ -127,7 +146,5 @@ class BottomSheetView(context: Context, appContext: AppContext) : ExpoView(conte
// Utils
private fun getRootLayout(): FrameLayout {
return appContext.currentActivity!!.findViewById(android.R.id.content)
}
private fun getRootLayout(): FrameLayout = appContext.currentActivity!!.findViewById(android.R.id.content)
}
@@ -5,46 +5,49 @@ import expo.modules.kotlin.modules.Module
import expo.modules.kotlin.modules.ModuleDefinition
class BottomSheetModule : Module() {
override fun definition() = ModuleDefinition {
Name("BlueskyBottomSheet")
override fun definition() =
ModuleDefinition {
Name("BlueskyBottomSheet")
Function("getSafeAreaInset") {
return@Function 10 // @TODO
}
View(BottomSheetView::class) {
Events(arrayOf(
"onStateChange",
"onAttemptDismiss",
))
AsyncFunction("dismiss") { view: BottomSheetView ->
view.dismiss()
Function("getSafeAreaInset") {
return@Function 10 // @TODO
}
Prop("preventDismiss") { view: BottomSheetView, prop: Boolean ->
view.preventDismiss = prop
}
View(BottomSheetView::class) {
Events(
arrayOf(
"onStateChange",
"onAttemptDismiss",
),
)
Prop("minHeight") { view: BottomSheetView, prop: Float ->
view.minHeight = prop
}
AsyncFunction("dismiss") { view: BottomSheetView ->
view.dismiss()
}
Prop("maxHeight") { view: BottomSheetView, prop: Float ->
view.maxHeight = prop
}
Prop("preventDismiss") { view: BottomSheetView, prop: Boolean ->
view.preventDismiss = prop
}
Prop("cornerRadius") { view: BottomSheetView, prop: Float ->
view.sheetState.value.cornerRadius = prop
}
Prop("minHeight") { view: BottomSheetView, prop: Float ->
view.minHeight = prop
}
Prop("containerBackgroundColor") { view: BottomSheetView, prop: String ->
view.sheetState.value.containerBackgroundColor = Color.parseColor(prop)
}
Prop("maxHeight") { view: BottomSheetView, prop: Float ->
view.maxHeight = prop
}
Prop("preventExpansion") { view: BottomSheetView, prop: Boolean ->
view.sheetState.value.preventExpansion = prop
Prop("cornerRadius") { view: BottomSheetView, prop: Float ->
view.sheetState.value.cornerRadius = prop
}
Prop("containerBackgroundColor") { view: BottomSheetView, prop: String ->
view.sheetState.value.containerBackgroundColor = Color.parseColor(prop)
}
Prop("preventExpansion") { view: BottomSheetView, prop: Boolean ->
view.sheetState.value.preventExpansion = prop
}
}
}
}
}
@@ -21,7 +21,7 @@ import androidx.compose.ui.viewinterop.AndroidView
data class SheetState(
var isOpen: Boolean = false,
var cornerRadius: Float? = null,
var containerBackgroundColor: Int ? = null,
var containerBackgroundColor: Int? = null,
var preventExpansion: Boolean = false,
)
@@ -40,20 +40,22 @@ fun SheetView(
ModalBottomSheet(
sheetState = sheetState,
onDismissRequest = onDismissRequest,
shape = RoundedCornerShape(
topStart = state.value.cornerRadius ?: 0f,
topEnd = state.value.cornerRadius ?: 0f,
),
shape =
RoundedCornerShape(
topStart = state.value.cornerRadius ?: 0f,
topEnd = state.value.cornerRadius ?: 0f,
),
containerColor = Color(state.value.containerBackgroundColor ?: android.graphics.Color.TRANSPARENT),
) {
Column(
Modifier.fillMaxWidth()
Modifier
.fillMaxWidth()
.height(contentHeight.dp)
// Prevent covering up the handle
.padding(top = 34.dp)
.padding(top = 34.dp),
) {
AndroidView(
factory = { innerView }
factory = { innerView },
)
}
}
+3 -3
View File
@@ -11,15 +11,15 @@ class SheetManager {
static let shared = SheetManager()
private var sheetViews = NSHashTable<SheetView>(options: .weakMemory)
func add(_ view: SheetView) {
sheetViews.add(view)
}
func remove(_ view: SheetView) {
sheetViews.remove(view)
}
func dismissAll() {
sheetViews.allObjects.forEach { sheetView in
sheetView.dismiss()