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

#277 [Feat] 컴포즈 SingleEventHandler 구현 및 적용 #317

Merged
merged 13 commits into from
Sep 19, 2023
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import hous.release.designsystem.component.user_interaction.SingleEventArea
import hous.release.designsystem.theme.HousG4
import hous.release.designsystem.theme.HousTheme

Expand All @@ -20,11 +21,18 @@ fun RulePhotoStatusBar(
onOpenGallery: () -> Unit = {}
) {
Row(
modifier = modifier.fillMaxWidth().padding(start = 16.dp, end = 28.dp),
modifier = modifier
.fillMaxWidth()
.padding(start = 16.dp, end = 28.dp),
horizontalArrangement = Arrangement.SpaceBetween,
verticalAlignment = Alignment.CenterVertically
) {
RuleAddPhotoButton(photoCount in (0..4), onOpenGallery)
SingleEventArea { handler ->
RuleAddPhotoButton(
isActiveButton = photoCount in (0..4),
onClick = { handler.handle(onOpenGallery) }
)
}
murjune marked this conversation as resolved.
Show resolved Hide resolved

Text(
text = "$photoCount/5",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import androidx.compose.ui.res.vectorResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import hous.release.designsystem.R
import hous.release.designsystem.component.user_interaction.SingleEventArea
import hous.release.designsystem.theme.HousBlue
import hous.release.designsystem.theme.HousWhite

Expand All @@ -38,28 +39,31 @@ fun FabScreenSlot(
fun HousFloatingButton(
onClick: () -> Unit = {}
) {
FloatingActionButton(
onClick = onClick,
backgroundColor = HousBlue,
contentColor = HousWhite,
modifier = Modifier.size(92.dp).padding(16.dp)
) {
Icon(
imageVector = ImageVector.vectorResource(id = R.drawable.ic_plus),
contentDescription = "Add"
)
SingleEventArea { cutter ->
FloatingActionButton(
onClick = { cutter.handle(onClick) },
backgroundColor = HousBlue,
contentColor = HousWhite,
modifier = Modifier.size(92.dp)
.padding(16.dp)
) {
Icon(
imageVector = ImageVector.vectorResource(id = R.drawable.ic_plus),
contentDescription = "Add"
)
}
Comment on lines +42 to +54
Copy link
Contributor

Choose a reason for hiding this comment

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

오 이런식으로 쓰는군요 !!

}
}

@Composable
@Preview(showBackground = true)
fun Preview() {
private fun Preview() {
HousFloatingButton()
}

@Composable
@Preview(widthDp = 360, heightDp = 640, showBackground = true)
fun PreviewFabContainerWithContent() {
private fun PreviewFabContainerWithContent() {
FabScreenSlot(
fabOnClick = {},
content = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package hous.release.designsystem.component.user_interaction

import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import hous.release.designsystem.util.SingleEventHandler

/**
* 여러 번 클릭 이벤트를 막아주는 Wrapper Composable
* */
@Composable
fun <T> SingleEventArea(
content: @Composable (SingleEventHandler) -> T
) {
val singleEventHandler = remember { SingleEventHandler.instance() }

content(singleEventHandler)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package hous.release.designsystem.modifier

import androidx.compose.foundation.LocalIndication
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.composed
import androidx.compose.ui.platform.debugInspectorInfo
import androidx.compose.ui.semantics.Role
import hous.release.designsystem.util.SingleEventHandler

/**
* 여러 번 클릭 이벤트를 막아주는 Modifier
* */
fun Modifier.clickableSingle(
enabled: Boolean = true,
onClickLabel: String? = null,
role: Role? = null,
onClick: () -> Unit
): Modifier = composed(
inspectorInfo = debugInspectorInfo {
name = "clickable"
properties["enabled"] = enabled
properties["onClickLabel"] = onClickLabel
properties["role"] = role
properties["onClick"] = onClick
}
) {
val singleEventHandler = remember { SingleEventHandler.instance() }
Modifier.clickable(
enabled = enabled,
onClickLabel = onClickLabel,
onClick = { singleEventHandler.handle { onClick() } },
role = role,
indication = LocalIndication.current,
interactionSource = remember { MutableInteractionSource() }
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package hous.release.designsystem.util

import kotlin.time.Duration
import kotlin.time.Duration.Companion.milliseconds
import kotlin.time.ExperimentalTime
import kotlin.time.TimeMark
import kotlin.time.TimeSource

/**
* 여러 번 클릭 이벤트를 막아주는 EventHandler
* */
@OptIn(ExperimentalTime::class)
fun interface SingleEventHandler {

fun handle(event: () -> Unit)

private class SingleEventHandlerImpl : SingleEventHandler {
private val currentTime: TimeMark get() = TimeSource.Monotonic.markNow()
private val throttleDuration: Duration = 300.milliseconds
private lateinit var lastEventTime: TimeMark

override fun handle(event: () -> Unit) {
if (::lastEventTime.isInitialized.not() || (lastEventTime + throttleDuration).hasPassedNow()) {
event()
}
lastEventTime = currentTime
}
}

companion object {
fun instance(): SingleEventHandler = SingleEventHandlerImpl()
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package hous.release.designsystem.util
package hous.release.designsystem.util.extension

import androidx.compose.runtime.Composable
import androidx.compose.ui.platform.LocalDensity
Expand Down
Loading