From bc6cb5cb21f6150e97c1b397de7d81be99d94bff Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sun, 4 Sep 2022 02:35:26 +0900 Subject: [PATCH 01/38] =?UTF-8?q?test:=20=EC=8A=A4=EB=83=85=EC=83=B7=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/QuackFloatingActionButton.kt | 45 +++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFloatingActionButton.kt diff --git a/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFloatingActionButton.kt b/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFloatingActionButton.kt new file mode 100644 index 000000000..e5cbf499c --- /dev/null +++ b/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFloatingActionButton.kt @@ -0,0 +1,45 @@ +/* + * Designed and developed by 2022 SungbinLand, Team Duckie + * + * [QuackFloatingActionButton.kt] created by Ji Sungbin on 22. 9. 4. 오전 2:23 + * + * Licensed under the MIT. + * Please see full license: https://github.com/sungbinland/quack-quack/blob/main/LICENSE + */ + +@file:Suppress("TestFunctionName", "SpellCheckingInspection") + +package team.duckie.quackquack.ui + +import com.google.testing.junit.testparameterinjector.TestParameter +import com.google.testing.junit.testparameterinjector.TestParameterInjector +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import team.duckie.quackquack.ui.rule.AnimationTestRule +import team.duckie.quackquack.ui.textstyle.QuackFontScale +import team.duckie.quackquack.ui.util.boxSnapshot +import team.duckie.quackquack.ui.util.buildPaparazzi + +@RunWith(TestParameterInjector::class) +class QuackFloatingActionButton { + @get:Rule + val paparazzi = buildPaparazzi() + + @get:Rule + val animationTest = AnimationTestRule() + + @Test + fun QuackFloatingActionButton( + @TestParameter("0.5", "1.0", "1.5", "2.0") fontScale: Double, + ) { + paparazzi.boxSnapshot( + name = "[fontScale:$fontScale]", + ) { + QuackFontScale = fontScale + team.duckie.quackquack.ui.component.FloatingActionButton( + onClick = {}, + ) + } + } +} From ba17c33242c6628017e9edc4fd285b926d5389b9 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sun, 4 Sep 2022 02:35:44 +0900 Subject: [PATCH 02/38] =?UTF-8?q?feat:=20click=20=EC=9D=B4=EB=B2=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=97=86=EB=8A=94=20icon?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/image.kt | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/image.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/image.kt index 6825272f3..8aa3ca470 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/image.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/image.kt @@ -79,3 +79,29 @@ internal fun QuackImage( ), ) } + +/** + * 이미지 하나만 표시하는 컴포넌트의 아이콘 버전 + * + * @param icon 표시할 아이콘의 drawable 아이디. + * 만약 null 이 들어온다면 아이콘을 그리지 않습니다. + * @param tint 아이콘에 적용할 틴트 값 + * @param onClick 아이콘이 클릭됐을 때 실행할 람다식 + */ +@Composable +@NonRestartableComposable +internal fun QuackNonClickableImage( + icon: QuackIcon?, + tint: QuackColor = QuackColor.Black, +) { + if (icon == null) return + Image( + painter = painterResource( + id = icon.drawableId, + ), + contentDescription = null, + colorFilter = ColorFilter.tint( + color = tint.value, + ), + ) +} From b1d02b77279b10fee6633a57c976321ebcfac542 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sun, 4 Sep 2022 02:35:59 +0900 Subject: [PATCH 03/38] =?UTF-8?q?feat;=20fab=EB=B2=84=ED=8A=BC=20dialog=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20=ED=95=84=EC=9A=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/fab.kt | 286 ++++++++++++++++++ 1 file changed, 286 insertions(+) create mode 100644 ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt new file mode 100644 index 000000000..d767f8413 --- /dev/null +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -0,0 +1,286 @@ +/* + * Designed and developed by 2022 SungbinLand, Team Duckie + * + * [fab.kt] created by Ji Sungbin on 22. 9. 3. 오후 1:15 + * + * Licensed under the MIT. + * Please see full license: https://github.com/sungbinland/quack-quack/blob/main/LICENSE + */ + +package team.duckie.quackquack.ui.component + +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.offset +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.runtime.Composable +import androidx.compose.runtime.Immutable +import androidx.compose.runtime.NonRestartableComposable +import androidx.compose.runtime.Stable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import androidx.compose.ui.Alignment +import androidx.compose.ui.ExperimentalComposeUiApi +import androidx.compose.ui.Modifier +import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.layout.boundsInRoot +import androidx.compose.ui.layout.boundsInWindow +import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.layout.positionInParent +import androidx.compose.ui.layout.positionInRoot +import androidx.compose.ui.layout.positionInWindow +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import androidx.compose.ui.window.Dialog +import androidx.compose.ui.window.DialogProperties +import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf +import team.duckie.quackquack.ui.color.QuackColor +import team.duckie.quackquack.ui.constant.QuackHeight +import team.duckie.quackquack.ui.constant.QuackWidth +import team.duckie.quackquack.ui.icon.QuackIcon +import team.duckie.quackquack.ui.modifier.applyQuackSize +import team.duckie.quackquack.ui.modifier.quackClickable +import team.duckie.quackquack.ui.textstyle.QuackTextStyle + +private val QuackFloatingActionButtonSize = 48.dp + +private val QuackFloatingActionButtonShape = CircleShape +private val QuackPopUpMenuShape = RoundedCornerShape(12.dp) + +private val QuackFabTopPadding = 20.dp +private val QuackFabHorizontalPadding = 16.dp +private val QuackFabItemPadding = 16.dp + +private val QuackFabItemSpacing = 8.dp + +@Immutable +class QuackPopUpMenuItem( + val quackIcon: QuackIcon, + val text: String, + val onClick: () -> Unit, +) + +private val dummyPopUpMenuItem = persistentListOf( + QuackPopUpMenuItem( + quackIcon = QuackIcon.Close, + text = "피드", + onClick = {} + ), + QuackPopUpMenuItem( + quackIcon = QuackIcon.Close, + text = "덕딜", + onClick = {} + ), +) + +@Composable +fun FloatingMenuActionButton( + items: PersistentList, +) { + var expanded by remember { mutableStateOf(false) } + var positionInRoot by remember { mutableStateOf(Offset.Zero) } + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center, + ) { + QuackText( + text = "${positionInRoot.x} , ${positionInRoot.y}}", + style = QuackTextStyle.Body1, + ) + } + BasicFloatingActionButton( + modifier = Modifier + .onGloballyPositioned { layoutCoordinates -> + positionInRoot = layoutCoordinates.positionInRoot() + }, + onClick = { + expanded = true + }, + ) + if (expanded) { + Column { + QuackDialog( + buttonOffset = positionInRoot, + onDismissRequest = { + expanded = false + }, + ) { + Column( + horizontalAlignment = Alignment.End, + ) { + QuackDialogMenu( + items = items, + ) + Spacer( + modifier = Modifier.height( + height = QuackFabItemSpacing, + ), + ) + BasicFloatingActionButton( + onClick = { + expanded = true + } + ) + } + } + } + + } + +} + +@OptIn(ExperimentalComposeUiApi::class) +@Composable +private fun QuackDialog( + buttonOffset: Offset, + onDismissRequest: () -> Unit, + content: @Composable () -> Unit, +) { + Dialog( + onDismissRequest = onDismissRequest, + properties = DialogProperties( + dismissOnBackPress = true, + usePlatformDefaultWidth = false, + ), + ) { + Box( + modifier = Modifier + .fillMaxSize() + .clickable { + onDismissRequest() + }, + contentAlignment = Alignment.TopStart, + ) { + Box( + modifier = Modifier.offset( + x = (buttonOffset.x).dp, + y = (buttonOffset.y).dp, + ), + ) { + content() + } + + } + } +} + +@Composable +@NonRestartableComposable +private fun QuackDialogMenu( + items: PersistentList, +) { + QuackSurface( + modifier = Modifier.applyQuackSize( + width = QuackWidth.Wrap, + height = QuackHeight.Wrap, + ), + shape = QuackPopUpMenuShape, + backgroundColor = QuackColor.White, + ) { + Column( + modifier = Modifier + .padding( + horizontal = QuackFabHorizontalPadding, + ) + .padding( + top = QuackFabTopPadding + ), + verticalArrangement = Arrangement.Center, + horizontalAlignment = Alignment.CenterHorizontally, + ) { + items.forEach { item: QuackPopUpMenuItem -> + QuackDialogMenuContent( + itemIcon = item.quackIcon, + itemText = item.text, + onClickItem = item.onClick, + ) + Spacer( + modifier = Modifier.height( + height = QuackFabItemPadding, + ), + ) + } + } + } +} + + +@Composable +@NonRestartableComposable +internal fun QuackDialogMenuContent( + itemIcon: QuackIcon, + itemText: String, + onClickItem: () -> Unit, +) { + Row( + modifier = Modifier.quackClickable { + onClickItem() + }, + verticalAlignment = Alignment.CenterVertically, + ) + { + QuackNonClickableImage( + icon = itemIcon, + ) + QuackText( + text = itemText, + style = QuackTextStyle.Subtitle, + ) + } +} + +@Composable +fun FloatingActionButton( + onClick: () -> Unit, +) { + BasicFloatingActionButton( + onClick = onClick, + ) +} + +@Composable +private fun BasicFloatingActionButton( + modifier: Modifier = Modifier, + onClick: () -> Unit, +) { + QuackSurface( + modifier = modifier + .applyQuackSize( + width = QuackWidth.Custom(QuackFloatingActionButtonSize), + height = QuackHeight.Custom(QuackFloatingActionButtonSize), + ), + shape = QuackFloatingActionButtonShape, + backgroundColor = QuackColor.DuckieOrange, + ) { + QuackImage( + icon = QuackIcon.Close, + onClick = onClick, + ) + } +} + +@Preview +@Composable +fun fabPreview() { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.BottomCenter, + ) { + FloatingMenuActionButton( + items = dummyPopUpMenuItem, + ) + } +} From d9f06966cac80c172da1988f0e1395f6547bc6f3 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sun, 4 Sep 2022 14:00:57 +0900 Subject: [PATCH 04/38] =?UTF-8?q?feat:=20fab=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/fab.kt | 260 +++++++++++------- 1 file changed, 164 insertions(+), 96 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index d767f8413..e4eaf7723 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -9,6 +9,7 @@ package team.duckie.quackquack.ui.component +import androidx.compose.foundation.background import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -19,6 +20,7 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable @@ -32,21 +34,16 @@ import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Offset -import androidx.compose.ui.layout.boundsInRoot -import androidx.compose.ui.layout.boundsInWindow import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.layout.positionInParent -import androidx.compose.ui.layout.positionInRoot import androidx.compose.ui.layout.positionInWindow -import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.platform.LocalDensity -import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import kotlinx.collections.immutable.PersistentList -import kotlinx.collections.immutable.persistentListOf import team.duckie.quackquack.ui.color.QuackColor import team.duckie.quackquack.ui.constant.QuackHeight import team.duckie.quackquack.ui.constant.QuackWidth @@ -55,13 +52,13 @@ import team.duckie.quackquack.ui.modifier.applyQuackSize import team.duckie.quackquack.ui.modifier.quackClickable import team.duckie.quackquack.ui.textstyle.QuackTextStyle -private val QuackFloatingActionButtonSize = 48.dp +private val QuackFabSize = 48.dp -private val QuackFloatingActionButtonShape = CircleShape +private val QuackFabShape = CircleShape private val QuackPopUpMenuShape = RoundedCornerShape(12.dp) -private val QuackFabTopPadding = 20.dp -private val QuackFabHorizontalPadding = 16.dp +private val QuackMenuTopPadding = 20.dp +private val QuackMenuHorizontalPadding = 16.dp private val QuackFabItemPadding = 16.dp private val QuackFabItemSpacing = 8.dp @@ -73,79 +70,92 @@ class QuackPopUpMenuItem( val onClick: () -> Unit, ) -private val dummyPopUpMenuItem = persistentListOf( - QuackPopUpMenuItem( - quackIcon = QuackIcon.Close, - text = "피드", - onClick = {} - ), - QuackPopUpMenuItem( - quackIcon = QuackIcon.Close, - text = "덕딜", - onClick = {} - ), -) - +/** + * QuackMenuFloatingActionButton를 구현하였습니다. + * + * [QuackFloatingActionButton] 과는 다르게, 버튼을 클릭하였을 때 + * DialogMenu가 출력됩니다. + * [QuackPopUpMenuItem]를 통해 메뉴 아이템에 들어갈 icon, text, onClick을 설정할 수 있습니다. + * + * @param items 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트[QuackPopUpMenuItem] + * @see QuackPopUpMenuItem + */ @Composable -fun FloatingMenuActionButton( +fun QuackMenuFloatingActionButton( items: PersistentList, ) { var expanded by remember { mutableStateOf(false) } var positionInRoot by remember { mutableStateOf(Offset.Zero) } - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center, - ) { - QuackText( - text = "${positionInRoot.x} , ${positionInRoot.y}}", - style = QuackTextStyle.Body1, - ) - } - BasicFloatingActionButton( + var menuSize by remember { mutableStateOf(IntSize.Zero) } + var buttonSize by remember { mutableStateOf(IntSize.Zero) } + QuackBasicFloatingActionButton( modifier = Modifier .onGloballyPositioned { layoutCoordinates -> - positionInRoot = layoutCoordinates.positionInRoot() + positionInRoot = layoutCoordinates.positionInWindow() + buttonSize = layoutCoordinates.size }, + icon = QuackIcon.Plus, onClick = { expanded = true }, ) if (expanded) { - Column { - QuackDialog( - buttonOffset = positionInRoot, - onDismissRequest = { - expanded = false + QuackDialog( + buttonOffset = positionInRoot, + menuSize = menuSize, + buttonSize = buttonSize, + onDismissRequest = { + expanded = false + }, + ) { + Column( + modifier = Modifier.onGloballyPositioned { layoutCoordinates -> + menuSize = layoutCoordinates.size }, + horizontalAlignment = Alignment.End, ) { - Column( - horizontalAlignment = Alignment.End, - ) { - QuackDialogMenu( - items = items, - ) - Spacer( - modifier = Modifier.height( - height = QuackFabItemSpacing, - ), - ) - BasicFloatingActionButton( - onClick = { - expanded = true - } - ) - } + QuackDialogMenu( + items = items, + ) + Spacer( + modifier = Modifier.height( + height = QuackFabItemSpacing, + ), + ) + QuackBasicFloatingActionButton( + icon = QuackIcon.Close, + onClick = { + expanded = false + }, + ) } } - } - } +/** + * QuackMenuFloatingActionButton를 클릭했을 때 나오는 다이얼로그 입니다. + * + * Dialog는 내부적으로 Android Dialog로 구현되어있고, Compose View로 래핑되어 있습니다. + * 따라서 위치를 수동으로 조절할 수는 없고, Full Size Box에서 offset으로 조정되어야 합니다. + * + * 따라서 FloatingActionButton의 Offset을 구한 다음, + * Menu 크기만큼 더하고 Button 크기만큼 빼면 위치를 조정시킬 수 있습니다. + * + * dpOffsetX - menuWidth + buttonWidth + * + * @param buttonOffset FloatingActionButton의 offset + * @param menuSize menu container 크기 + * @param buttonSize button container 크기 + * @param onDismissRequest Menu를 닫으라는 명령이 떨어졌을 때의 동작 + * @param content Dialog 내부에 들어갈 Composable + */ @OptIn(ExperimentalComposeUiApi::class) @Composable private fun QuackDialog( buttonOffset: Offset, + menuSize: IntSize, + buttonSize: IntSize, onDismissRequest: () -> Unit, content: @Composable () -> Unit, ) { @@ -156,27 +166,51 @@ private fun QuackDialog( usePlatformDefaultWidth = false, ), ) { + val dpOffsetX = pixelToDp( + pixel = buttonOffset.x + ) + val dpOffsetY = pixelToDp( + pixel = buttonOffset.y + ) + val menuWidth = pixelToDp( + pixel = menuSize.width.toFloat() + ) + val menuHeight = pixelToDp( + pixel = menuSize.height.toFloat() + ) + val buttonWidth = pixelToDp( + pixel = buttonSize.width.toFloat() + ) + val buttonHeight = pixelToDp( + pixel = buttonSize.height.toFloat() + ) Box( modifier = Modifier .fillMaxSize() .clickable { onDismissRequest() - }, + } + .offset( + x = dpOffsetX - menuWidth + buttonWidth, + y = dpOffsetY - menuHeight + buttonHeight / 2, + ), contentAlignment = Alignment.TopStart, ) { - Box( - modifier = Modifier.offset( - x = (buttonOffset.x).dp, - y = (buttonOffset.y).dp, - ), - ) { + Box { content() } - } } } +/** + * QuackDialogMenu를 구현하였습니다. + * + * 메뉴의 아이템 리스트를 보여주는 Composable 입니다. + * + * @param items 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트[QuackPopUpMenuItem] + * @see QuackPopUpMenuItem + */ @Composable @NonRestartableComposable private fun QuackDialogMenu( @@ -193,10 +227,10 @@ private fun QuackDialogMenu( Column( modifier = Modifier .padding( - horizontal = QuackFabHorizontalPadding, + horizontal = QuackMenuHorizontalPadding, ) .padding( - top = QuackFabTopPadding + top = QuackMenuTopPadding, ), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, @@ -217,7 +251,15 @@ private fun QuackDialogMenu( } } - +/** + * QuackDialogMenuContent를 구현하였습니다. + * + * 메뉴의 Item List Content 입니다. + * + * @param itemIcon item의 icon + * @param itemText item의 text + * @param onClickItem item의 클릭 이벤트 + */ @Composable @NonRestartableComposable internal fun QuackDialogMenuContent( @@ -230,8 +272,7 @@ internal fun QuackDialogMenuContent( onClickItem() }, verticalAlignment = Alignment.CenterVertically, - ) - { + ) { QuackNonClickableImage( icon = itemIcon, ) @@ -242,45 +283,72 @@ internal fun QuackDialogMenuContent( } } +/** + * QuackFloatingActionButton을 구현하였습니다. + * + * Box로 구현되어 있기 때문에, 다른 Composable 위에 배치될 수 있습니다. + * + * @param icon FloatingActionButton에 들어갈 icon + * @param onClick 버튼 클릭 이벤트 + */ @Composable -fun FloatingActionButton( +fun QuackFloatingActionButton( + icon: QuackIcon, onClick: () -> Unit, ) { - BasicFloatingActionButton( + QuackBasicFloatingActionButton( + icon = icon, onClick = onClick, ) } +/** + * QuackFloatingActionButton의 기초가 되는 Composable + * + * Content의 사이즈를 알아야 하는 경우로 인해 Modifier를 가집니다. + * + * @param modifier [Modifier] + * @param icon FloatingActionButton에 들어갈 icon + * @param onClick 버튼 클릭 이벤트 + */ @Composable -private fun BasicFloatingActionButton( +private fun QuackBasicFloatingActionButton( modifier: Modifier = Modifier, + icon: QuackIcon, onClick: () -> Unit, ) { - QuackSurface( + Box( modifier = modifier - .applyQuackSize( - width = QuackWidth.Custom(QuackFloatingActionButtonSize), - height = QuackHeight.Custom(QuackFloatingActionButtonSize), - ), - shape = QuackFloatingActionButtonShape, - backgroundColor = QuackColor.DuckieOrange, + .size( + QuackFabSize, + ) + .clip( + shape = QuackFabShape, + ) + .background( + color = QuackColor.DuckieOrange.value, + ) + .clickable { + onClick() + }, + contentAlignment = Alignment.Center, ) { - QuackImage( - icon = QuackIcon.Close, - onClick = onClick, + QuackNonClickableImage( + tint = QuackColor.White, + icon = icon, ) } } -@Preview +/** + * pixel로 주어지는 offset을 dp로 변경하기 위한 function + * + * @param pixel dp로 변경할 pixel + */ @Composable -fun fabPreview() { - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.BottomCenter, - ) { - FloatingMenuActionButton( - items = dummyPopUpMenuItem, - ) - } +@Stable +internal fun pixelToDp(pixel: Float) = with( + receiver = LocalDensity.current, +) { + pixel.toDp() } From 6219c47a319173a20a885725e7f825afb8d6bdfc Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sun, 4 Sep 2022 14:01:06 +0900 Subject: [PATCH 05/38] =?UTF-8?q?feat:=20icon=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/duckie/quackquack/ui/icon/QuackIcon.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/icon/QuackIcon.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/icon/QuackIcon.kt index 2c78f8a60..960e97028 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/icon/QuackIcon.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/icon/QuackIcon.kt @@ -178,5 +178,20 @@ value class QuackIcon private constructor( val Heart = QuackIcon( drawableId = R.drawable.ic_heart_24, ) + + @Stable + val WriteFeed = QuackIcon( + drawableId = R.drawable.ic_write_feed_24, + ) + + @Stable + val DrawerBuy = QuackIcon( + drawableId = R.drawable.ic_drawer_buy_24, + ) + + @Stable + val DMNew = QuackIcon( + drawableId = R.drawable.ic_dm_new_20_white, + ) } } From a5994671d928455009b64a8caa60192fd4d74ee5 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sun, 4 Sep 2022 14:01:15 +0900 Subject: [PATCH 06/38] =?UTF-8?q?feat:=20icon=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/res/drawable/ic_dm_new_20_white.xml | 50 +++++++++++++++++++ .../main/res/drawable/ic_drawer_buy_24.xml | 28 +++++++++++ .../main/res/drawable/ic_write_feed_24.xml | 36 +++++++++++++ 3 files changed, 114 insertions(+) create mode 100644 ui-components/src/main/res/drawable/ic_dm_new_20_white.xml create mode 100644 ui-components/src/main/res/drawable/ic_drawer_buy_24.xml create mode 100644 ui-components/src/main/res/drawable/ic_write_feed_24.xml diff --git a/ui-components/src/main/res/drawable/ic_dm_new_20_white.xml b/ui-components/src/main/res/drawable/ic_dm_new_20_white.xml new file mode 100644 index 000000000..3ae7ad30f --- /dev/null +++ b/ui-components/src/main/res/drawable/ic_dm_new_20_white.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + diff --git a/ui-components/src/main/res/drawable/ic_drawer_buy_24.xml b/ui-components/src/main/res/drawable/ic_drawer_buy_24.xml new file mode 100644 index 000000000..fb1f047c8 --- /dev/null +++ b/ui-components/src/main/res/drawable/ic_drawer_buy_24.xml @@ -0,0 +1,28 @@ + + + + + + + + + + diff --git a/ui-components/src/main/res/drawable/ic_write_feed_24.xml b/ui-components/src/main/res/drawable/ic_write_feed_24.xml new file mode 100644 index 000000000..167f228f3 --- /dev/null +++ b/ui-components/src/main/res/drawable/ic_write_feed_24.xml @@ -0,0 +1,36 @@ + + + + + + + + From b3c70895cf362a2a76c1523a176e429365d85979 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sun, 4 Sep 2022 14:01:25 +0900 Subject: [PATCH 07/38] =?UTF-8?q?test:=20=EC=8A=A4=EB=83=85=EC=83=B7=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/QuackFloatingActionButton.kt | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFloatingActionButton.kt b/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFloatingActionButton.kt index e5cbf499c..5bae90120 100644 --- a/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFloatingActionButton.kt +++ b/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFloatingActionButton.kt @@ -13,16 +13,19 @@ package team.duckie.quackquack.ui import com.google.testing.junit.testparameterinjector.TestParameter import com.google.testing.junit.testparameterinjector.TestParameterInjector +import kotlinx.collections.immutable.persistentListOf import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith +import team.duckie.quackquack.ui.component.QuackPopUpMenuItem +import team.duckie.quackquack.ui.icon.QuackIcon import team.duckie.quackquack.ui.rule.AnimationTestRule import team.duckie.quackquack.ui.textstyle.QuackFontScale import team.duckie.quackquack.ui.util.boxSnapshot import team.duckie.quackquack.ui.util.buildPaparazzi @RunWith(TestParameterInjector::class) -class QuackFloatingActionButton { +class QuackFloatingActionButtonSnapShot { @get:Rule val paparazzi = buildPaparazzi() @@ -37,9 +40,36 @@ class QuackFloatingActionButton { name = "[fontScale:$fontScale]", ) { QuackFontScale = fontScale - team.duckie.quackquack.ui.component.FloatingActionButton( + team.duckie.quackquack.ui.component.QuackFloatingActionButton( + icon = QuackIcon.DMNew, onClick = {}, ) } } + + @Test + fun QuackMenuFloatingActionButton( + @TestParameter("0.5", "1.0", "1.5", "2.0") fontScale: Double, + ) { + paparazzi.boxSnapshot( + name = "[fontScale:$fontScale]", + ) { + QuackFontScale = fontScale + team.duckie.quackquack.ui.component.QuackMenuFloatingActionButton( + items = persistentListOf( + QuackPopUpMenuItem( + quackIcon = QuackIcon.WriteFeed, + text = "피드", + onClick = {} + ), + QuackPopUpMenuItem( + quackIcon = QuackIcon.DrawerBuy, + text = "덕딜", + onClick = {} + ), + ) + ) + } + } } + From 54927c109370ce7d7a6c30d9b7913604959889c3 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sun, 4 Sep 2022 14:48:52 +0900 Subject: [PATCH 08/38] =?UTF-8?q?remove:=20nonClickableImage=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/image.kt | 26 ------------------- 1 file changed, 26 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/image.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/image.kt index d2fdc5158..f7eb9a460 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/image.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/image.kt @@ -80,29 +80,3 @@ fun QuackImage( ), ) } - -/** - * 이미지 하나만 표시하는 컴포넌트의 아이콘 버전 - * - * @param icon 표시할 아이콘의 drawable 아이디. - * 만약 null 이 들어온다면 아이콘을 그리지 않습니다. - * @param tint 아이콘에 적용할 틴트 값 - * @param onClick 아이콘이 클릭됐을 때 실행할 람다식 - */ -@Composable -@NonRestartableComposable -internal fun QuackNonClickableImage( - icon: QuackIcon?, - tint: QuackColor = QuackColor.Black, -) { - if (icon == null) return - Image( - painter = painterResource( - id = icon.drawableId, - ), - contentDescription = null, - colorFilter = ColorFilter.tint( - color = tint.value, - ), - ) -} From ee106339cf22c8d13c0f62ab737c25a68c459fbb Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sun, 4 Sep 2022 14:49:11 +0900 Subject: [PATCH 09/38] =?UTF-8?q?test:=20=EC=8A=A4=EB=83=85=EC=83=B7=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/{QuackFloatingActionButton.kt => QuackFab.kt} | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) rename ui-components/src/test/kotlin/team/duckie/quackquack/ui/{QuackFloatingActionButton.kt => QuackFab.kt} (91%) diff --git a/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFloatingActionButton.kt b/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFab.kt similarity index 91% rename from ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFloatingActionButton.kt rename to ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFab.kt index 5bae90120..47775e2b4 100644 --- a/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFloatingActionButton.kt +++ b/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFab.kt @@ -1,7 +1,7 @@ /* * Designed and developed by 2022 SungbinLand, Team Duckie * - * [QuackFloatingActionButton.kt] created by Ji Sungbin on 22. 9. 4. 오전 2:23 + * [QuackFab.kt] created by Ji Sungbin on 22. 9. 4. 오전 2:23 * * Licensed under the MIT. * Please see full license: https://github.com/sungbinland/quack-quack/blob/main/LICENSE @@ -25,7 +25,7 @@ import team.duckie.quackquack.ui.util.boxSnapshot import team.duckie.quackquack.ui.util.buildPaparazzi @RunWith(TestParameterInjector::class) -class QuackFloatingActionButtonSnapShot { +class QuackFab { @get:Rule val paparazzi = buildPaparazzi() @@ -60,16 +60,15 @@ class QuackFloatingActionButtonSnapShot { QuackPopUpMenuItem( quackIcon = QuackIcon.WriteFeed, text = "피드", - onClick = {} + onClick = {}, ), QuackPopUpMenuItem( quackIcon = QuackIcon.DrawerBuy, text = "덕딜", - onClick = {} + onClick = {}, ), - ) + ), ) } } } - From 98e2d5760b58859501f25797691f3e6a798ca034 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Sun, 4 Sep 2022 14:49:38 +0900 Subject: [PATCH 10/38] =?UTF-8?q?refactor:=20quackClickable=20=EC=82=AC?= =?UTF-8?q?=EC=9A=A9=20=EB=B0=8F=20NonclickImageIcon=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/duckie/quackquack/ui/component/fab.kt | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index e4eaf7723..e968f637f 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -273,8 +273,9 @@ internal fun QuackDialogMenuContent( }, verticalAlignment = Alignment.CenterVertically, ) { - QuackNonClickableImage( + QuackImage( icon = itemIcon, + onClick = null, ) QuackText( text = itemText, @@ -328,14 +329,15 @@ private fun QuackBasicFloatingActionButton( .background( color = QuackColor.DuckieOrange.value, ) - .clickable { - onClick() - }, + .quackClickable( + onClick = onClick, + ), contentAlignment = Alignment.Center, ) { - QuackNonClickableImage( + QuackImage( tint = QuackColor.White, icon = icon, + onClick = null, ) } } From c885f3b19e24ab84e71aec836e535438752bb108 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 14:12:03 +0900 Subject: [PATCH 11/38] =?UTF-8?q?refactor=20:=20=EB=B3=80=EC=88=98?= =?UTF-8?q?=EC=99=80=20=ED=95=A8=EC=88=98=20=EC=82=AC=EC=9D=B4=20empty=20l?= =?UTF-8?q?ine=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/fab.kt | 43 ++++++++++--------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index e968f637f..fbfc2f7c8 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -71,13 +71,13 @@ class QuackPopUpMenuItem( ) /** - * QuackMenuFloatingActionButton를 구현하였습니다. + * QuackMenuFloatingActionButton 를 구현하였습니다. * * [QuackFloatingActionButton] 과는 다르게, 버튼을 클릭하였을 때 - * DialogMenu가 출력됩니다. - * [QuackPopUpMenuItem]를 통해 메뉴 아이템에 들어갈 icon, text, onClick을 설정할 수 있습니다. + * DialogMenu 가 출력됩니다. + * [QuackPopUpMenuItem]를 통해 메뉴 아이템에 들어갈 icon, text, onClick 을 설정할 수 있습니다. * - * @param items 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트[QuackPopUpMenuItem] + * @param items 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackPopUpMenuItem] * @see QuackPopUpMenuItem */ @Composable @@ -88,6 +88,7 @@ fun QuackMenuFloatingActionButton( var positionInRoot by remember { mutableStateOf(Offset.Zero) } var menuSize by remember { mutableStateOf(IntSize.Zero) } var buttonSize by remember { mutableStateOf(IntSize.Zero) } + QuackBasicFloatingActionButton( modifier = Modifier .onGloballyPositioned { layoutCoordinates -> @@ -134,20 +135,20 @@ fun QuackMenuFloatingActionButton( } /** - * QuackMenuFloatingActionButton를 클릭했을 때 나오는 다이얼로그 입니다. + * QuackMenuFloatingActionButton 를 클릭했을 때 나오는 다이얼로그 입니다. * - * Dialog는 내부적으로 Android Dialog로 구현되어있고, Compose View로 래핑되어 있습니다. - * 따라서 위치를 수동으로 조절할 수는 없고, Full Size Box에서 offset으로 조정되어야 합니다. + * Dialog 는 내부적으로 Android Dialog 로 구현되어있고, Compose View 로 래핑되어 있습니다. + * 따라서 위치를 수동으로 조절할 수는 없고, Full Size Box 에서 offset 으로 조정되어야 합니다. * - * 따라서 FloatingActionButton의 Offset을 구한 다음, + * 따라서 FloatingActionButton 의 Offset 을 구한 다음, * Menu 크기만큼 더하고 Button 크기만큼 빼면 위치를 조정시킬 수 있습니다. * * dpOffsetX - menuWidth + buttonWidth * - * @param buttonOffset FloatingActionButton의 offset + * @param buttonOffset FloatingActionButton 의 offset * @param menuSize menu container 크기 * @param buttonSize button container 크기 - * @param onDismissRequest Menu를 닫으라는 명령이 떨어졌을 때의 동작 + * @param onDismissRequest Menu 를 닫으라는 명령이 떨어졌을 때의 동작 * @param content Dialog 내부에 들어갈 Composable */ @OptIn(ExperimentalComposeUiApi::class) @@ -204,11 +205,11 @@ private fun QuackDialog( } /** - * QuackDialogMenu를 구현하였습니다. + * QuackDialogMenu 를 구현하였습니다. * * 메뉴의 아이템 리스트를 보여주는 Composable 입니다. * - * @param items 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트[QuackPopUpMenuItem] + * @param items 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackPopUpMenuItem] * @see QuackPopUpMenuItem */ @Composable @@ -252,7 +253,7 @@ private fun QuackDialogMenu( } /** - * QuackDialogMenuContent를 구현하였습니다. + * QuackDialogMenuContent 를 구현하였습니다. * * 메뉴의 Item List Content 입니다. * @@ -285,11 +286,11 @@ internal fun QuackDialogMenuContent( } /** - * QuackFloatingActionButton을 구현하였습니다. + * QuackFloatingActionButton 을 구현하였습니다. * - * Box로 구현되어 있기 때문에, 다른 Composable 위에 배치될 수 있습니다. + * Box 로 구현되어 있기 때문에, 다른 Composable 위에 배치될 수 있습니다. * - * @param icon FloatingActionButton에 들어갈 icon + * @param icon FloatingActionButton 에 들어갈 icon * @param onClick 버튼 클릭 이벤트 */ @Composable @@ -304,12 +305,12 @@ fun QuackFloatingActionButton( } /** - * QuackFloatingActionButton의 기초가 되는 Composable + * QuackFloatingActionButton 의 기초가 되는 Composable * - * Content의 사이즈를 알아야 하는 경우로 인해 Modifier를 가집니다. + * Content 의 사이즈를 알아야 하는 경우로 인해 Modifier 를 가집니다. * * @param modifier [Modifier] - * @param icon FloatingActionButton에 들어갈 icon + * @param icon FloatingActionButton 에 들어갈 icon * @param onClick 버튼 클릭 이벤트 */ @Composable @@ -343,9 +344,9 @@ private fun QuackBasicFloatingActionButton( } /** - * pixel로 주어지는 offset을 dp로 변경하기 위한 function + * pixel로 주어지는 offset 을 dp로 변경하기 위한 function * - * @param pixel dp로 변경할 pixel + * @param pixel dp 로 변경할 pixel */ @Composable @Stable From 8b4b24b0ccad52ecff675a055c2eb3919b9520ff Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 14:12:36 +0900 Subject: [PATCH 12/38] =?UTF-8?q?refactor:=20kdoc=20=EC=88=98=EC=A0=95=20?= =?UTF-8?q?=EB=B0=8F=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=EB=9E=8C?= =?UTF-8?q?=EB=8B=A4=20=EC=83=9D=EC=84=B1=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/fab.kt | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index fbfc2f7c8..0aa40edee 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -10,9 +10,9 @@ package team.duckie.quackquack.ui.component import androidx.compose.foundation.background -import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer @@ -75,7 +75,7 @@ class QuackPopUpMenuItem( * * [QuackFloatingActionButton] 과는 다르게, 버튼을 클릭하였을 때 * DialogMenu 가 출력됩니다. - * [QuackPopUpMenuItem]를 통해 메뉴 아이템에 들어갈 icon, text, onClick 을 설정할 수 있습니다. + * [QuackPopUpMenuItem] 을 통해 메뉴 아이템에 들어갈 icon, text, onClick 을 설정할 수 있습니다. * * @param items 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackPopUpMenuItem] * @see QuackPopUpMenuItem @@ -158,7 +158,7 @@ private fun QuackDialog( menuSize: IntSize, buttonSize: IntSize, onDismissRequest: () -> Unit, - content: @Composable () -> Unit, + content: @Composable BoxScope.() -> Unit, ) { Dialog( onDismissRequest = onDismissRequest, @@ -188,18 +188,18 @@ private fun QuackDialog( Box( modifier = Modifier .fillMaxSize() - .clickable { - onDismissRequest() - } + .quackClickable( + onClick = onDismissRequest + ) .offset( x = dpOffsetX - menuWidth + buttonWidth, y = dpOffsetY - menuHeight + buttonHeight / 2, ), contentAlignment = Alignment.TopStart, ) { - Box { - content() - } + Box( + content = content + ) } } } @@ -269,9 +269,9 @@ internal fun QuackDialogMenuContent( onClickItem: () -> Unit, ) { Row( - modifier = Modifier.quackClickable { - onClickItem() - }, + modifier = Modifier.quackClickable( + onClick = onClickItem, + ), verticalAlignment = Alignment.CenterVertically, ) { QuackImage( From 1e5fad94372136f39dc5bbbceac664dab1ed987c Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 14:50:36 +0900 Subject: [PATCH 13/38] =?UTF-8?q?feat:=20Playground=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- playground/src/main/AndroidManifest.xml | 1 + .../quackquack/playground/MainActivity.kt | 2 + .../playground/realworld/FabPlayground.kt | 73 +++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt diff --git a/playground/src/main/AndroidManifest.xml b/playground/src/main/AndroidManifest.xml index dfd4d8f7f..f7ea7a822 100644 --- a/playground/src/main/AndroidManifest.xml +++ b/playground/src/main/AndroidManifest.xml @@ -33,6 +33,7 @@ + diff --git a/playground/src/main/kotlin/team/duckie/quackquack/playground/MainActivity.kt b/playground/src/main/kotlin/team/duckie/quackquack/playground/MainActivity.kt index 7f4f709ba..a5e8acdc8 100644 --- a/playground/src/main/kotlin/team/duckie/quackquack/playground/MainActivity.kt +++ b/playground/src/main/kotlin/team/duckie/quackquack/playground/MainActivity.kt @@ -17,6 +17,7 @@ import kotlinx.coroutines.flow.first import team.duckie.quackquack.playground.base.BaseActivity import team.duckie.quackquack.playground.base.PlaygroundActivities import team.duckie.quackquack.playground.realworld.ButtonPlayground +import team.duckie.quackquack.playground.realworld.FabPlayground import team.duckie.quackquack.playground.realworld.TabPlayground import team.duckie.quackquack.playground.realworld.TextFieldPlayground import team.duckie.quackquack.playground.theme.PlaygroundTheme @@ -30,6 +31,7 @@ class MainActivity : BaseActivity() { TabPlayground::class, ButtonPlayground::class, TextFieldPlayground::class, + FabPlayground::class, ) override fun onCreate(savedInstanceState: Bundle?) { diff --git a/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt b/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt new file mode 100644 index 000000000..8614579c6 --- /dev/null +++ b/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt @@ -0,0 +1,73 @@ +/* + * Designed and developed by 2022 SungbinLand, Team Duckie + * + * [FabPlayground.kt] created by Ji Sungbin on 22. 9. 6. 오후 2:19 + * + * Licensed under the MIT. + * Please see full license: https://github.com/sungbinland/quack-quack/blob/main/LICENSE + */ + +package team.duckie.quackquack.playground.realworld + +import android.os.Bundle +import androidx.activity.compose.setContent +import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue +import kotlinx.collections.immutable.persistentListOf +import team.duckie.quackquack.playground.base.BaseActivity +import team.duckie.quackquack.playground.base.PlaygroundSection +import team.duckie.quackquack.playground.theme.PlaygroundTheme +import team.duckie.quackquack.ui.component.QuackFloatingActionButton +import team.duckie.quackquack.ui.component.QuackMenuFloatingActionButton +import team.duckie.quackquack.ui.component.QuackPopUpMenuItem +import team.duckie.quackquack.ui.icon.QuackIcon + +class FabPlayground : BaseActivity() { + @Suppress("RemoveExplicitTypeArguments") + private val items = persistentListOf Unit>>( + "QuackFloatingActionButton" to { QuackFloatingActionButtonDemo() }, + "QuackMenuFloatingActionButton" to { QuackMenuFloatingActionButtonDemo() }, + ) + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + setContent { + PlaygroundTheme { + PlaygroundSection( + title = "Fab", + items = items, + ) + } + } + } +} + +@Composable +fun QuackFloatingActionButtonDemo() { + QuackFloatingActionButton( + icon = QuackIcon.DMNew, + onClick = {}, + ) +} + + +@Composable +fun QuackMenuFloatingActionButtonDemo() { + QuackMenuFloatingActionButton( + items = persistentListOf( + QuackPopUpMenuItem( + icon = QuackIcon.WriteFeed, + text = "피드", + onClick = {}, + ), + QuackPopUpMenuItem( + icon = QuackIcon.DrawerBuy, + text = "덕딜", + onClick = {}, + ), + ) + ) +} From 3c28e789d6990fa2a5d990b9a915648eb1678b0d Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 14:52:39 +0900 Subject: [PATCH 14/38] =?UTF-8?q?refactor=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20=EC=86=8D=EC=84=B1=20=EB=AA=85=EC=8B=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index 0aa40edee..e4822a9dc 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -163,7 +163,6 @@ private fun QuackDialog( Dialog( onDismissRequest = onDismissRequest, properties = DialogProperties( - dismissOnBackPress = true, usePlatformDefaultWidth = false, ), ) { From 1caa739f672cc2f9411489aaa960889aa3db7634 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 15:54:13 +0900 Subject: [PATCH 15/38] =?UTF-8?q?style:=20resource=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=95=EB=A0=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/res/drawable/ic_dm_new_20_white.xml | 84 +++++++++---------- .../main/res/drawable/ic_drawer_buy_24.xml | 42 +++++----- .../main/res/drawable/ic_write_feed_24.xml | 60 ++++++------- 3 files changed, 90 insertions(+), 96 deletions(-) diff --git a/ui-components/src/main/res/drawable/ic_dm_new_20_white.xml b/ui-components/src/main/res/drawable/ic_dm_new_20_white.xml index 3ae7ad30f..414c97d61 100644 --- a/ui-components/src/main/res/drawable/ic_dm_new_20_white.xml +++ b/ui-components/src/main/res/drawable/ic_dm_new_20_white.xml @@ -3,48 +3,44 @@ android:height="20dp" android:viewportWidth="20" android:viewportHeight="20"> - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + diff --git a/ui-components/src/main/res/drawable/ic_drawer_buy_24.xml b/ui-components/src/main/res/drawable/ic_drawer_buy_24.xml index fb1f047c8..33d0dd676 100644 --- a/ui-components/src/main/res/drawable/ic_drawer_buy_24.xml +++ b/ui-components/src/main/res/drawable/ic_drawer_buy_24.xml @@ -3,26 +3,24 @@ android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> - - - - - - - - + + + + + + + + diff --git a/ui-components/src/main/res/drawable/ic_write_feed_24.xml b/ui-components/src/main/res/drawable/ic_write_feed_24.xml index 167f228f3..b2e5dfb08 100644 --- a/ui-components/src/main/res/drawable/ic_write_feed_24.xml +++ b/ui-components/src/main/res/drawable/ic_write_feed_24.xml @@ -3,34 +3,34 @@ android:height="24dp" android:viewportWidth="24" android:viewportHeight="24"> - - - - - - + + + + + + From bb084f40427a2e310309475aaf534595ca2dd9f6 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 16:15:34 +0900 Subject: [PATCH 16/38] =?UTF-8?q?refactor:=20offset=20=ED=95=A8=EC=88=98?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/fab.kt | 88 +++++++++++-------- 1 file changed, 50 insertions(+), 38 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index e4822a9dc..5890f06fb 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -26,7 +26,6 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable import androidx.compose.runtime.Immutable import androidx.compose.runtime.NonRestartableComposable -import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember @@ -37,8 +36,10 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Offset import androidx.compose.ui.layout.onGloballyPositioned +import androidx.compose.ui.layout.positionInParent import androidx.compose.ui.layout.positionInWindow import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.unit.IntOffset import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog @@ -65,7 +66,7 @@ private val QuackFabItemSpacing = 8.dp @Immutable class QuackPopUpMenuItem( - val quackIcon: QuackIcon, + val icon: QuackIcon, val text: String, val onClick: () -> Unit, ) @@ -166,34 +167,58 @@ private fun QuackDialog( usePlatformDefaultWidth = false, ), ) { - val dpOffsetX = pixelToDp( - pixel = buttonOffset.x - ) - val dpOffsetY = pixelToDp( - pixel = buttonOffset.y - ) - val menuWidth = pixelToDp( - pixel = menuSize.width.toFloat() - ) - val menuHeight = pixelToDp( - pixel = menuSize.height.toFloat() - ) - val buttonWidth = pixelToDp( - pixel = buttonSize.width.toFloat() - ) - val buttonHeight = pixelToDp( - pixel = buttonSize.height.toFloat() - ) + val density = LocalDensity.current + val dpOffsetX = with( + receiver = density, + ) { + buttonOffset.x.toDp() + } + val dpOffsetY = with( + receiver = density, + ) { + buttonOffset.y.toDp() + } + val menuWidth = with( + receiver = density, + ) { + menuSize.width.toDp() + } + val menuHeight = with( + receiver = density, + ) { + menuSize.height.toDp() + } + val buttonWidth = with( + receiver = density, + ) { + buttonSize.width.toDp() + } + val buttonHeight = with( + receiver = density, + ) { + buttonSize.height.toDp() + } + var xOffset by remember { + mutableStateOf(0) + } + var yOffset by remember { + mutableStateOf(0) + } + xOffset = (dpOffsetX - menuWidth + buttonWidth).value.toInt() + yOffset = (dpOffsetY - menuHeight + buttonHeight).value.toInt() + Box( modifier = Modifier .fillMaxSize() .quackClickable( onClick = onDismissRequest ) - .offset( - x = dpOffsetX - menuWidth + buttonWidth, - y = dpOffsetY - menuHeight + buttonHeight / 2, - ), + .offset { + IntOffset( + x = xOffset, + y = yOffset, + ) + }, contentAlignment = Alignment.TopStart, ) { Box( @@ -237,7 +262,7 @@ private fun QuackDialogMenu( ) { items.forEach { item: QuackPopUpMenuItem -> QuackDialogMenuContent( - itemIcon = item.quackIcon, + itemIcon = item.icon, itemText = item.text, onClickItem = item.onClick, ) @@ -341,16 +366,3 @@ private fun QuackBasicFloatingActionButton( ) } } - -/** - * pixel로 주어지는 offset 을 dp로 변경하기 위한 function - * - * @param pixel dp 로 변경할 pixel - */ -@Composable -@Stable -internal fun pixelToDp(pixel: Float) = with( - receiver = LocalDensity.current, -) { - pixel.toDp() -} From 1854bbbe0e05e43f3170ce488e78c562768670d3 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 16:17:09 +0900 Subject: [PATCH 17/38] =?UTF-8?q?refactor:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20null=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt | 2 -- 1 file changed, 2 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index 5890f06fb..89ee153cb 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -300,7 +300,6 @@ internal fun QuackDialogMenuContent( ) { QuackImage( icon = itemIcon, - onClick = null, ) QuackText( text = itemText, @@ -362,7 +361,6 @@ private fun QuackBasicFloatingActionButton( QuackImage( tint = QuackColor.White, icon = icon, - onClick = null, ) } } From 04b81ca63f306a13f9630dceecb7cb5f96ad1598 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 16:46:05 +0900 Subject: [PATCH 18/38] =?UTF-8?q?refactor:=20QuackText=EC=97=90=20style=20?= =?UTF-8?q?=EC=A3=BC=EB=8A=94=20=EB=8C=80=EC=8B=A0=20=EB=8C=80=EC=8B=A0=20?= =?UTF-8?q?QuackSubTitle=20=EC=82=AC=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/team/duckie/quackquack/ui/component/fab.kt | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index 89ee153cb..cf6e56e08 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -281,9 +281,9 @@ private fun QuackDialogMenu( * * 메뉴의 Item List Content 입니다. * - * @param itemIcon item의 icon - * @param itemText item의 text - * @param onClickItem item의 클릭 이벤트 + * @param itemIcon item 의 icon + * @param itemText item 의 text + * @param onClickItem item 의 클릭 이벤트 */ @Composable @NonRestartableComposable @@ -301,9 +301,8 @@ internal fun QuackDialogMenuContent( QuackImage( icon = itemIcon, ) - QuackText( + QuackSubtitle( text = itemText, - style = QuackTextStyle.Subtitle, ) } } From f82179e0c942ea9cb71534ad1620b73350e7b3ce Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 17:49:06 +0900 Subject: [PATCH 19/38] =?UTF-8?q?refactor:=20Playground=20argument=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../playground/realworld/FabPlayground.kt | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt b/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt index 8614579c6..56dd39784 100644 --- a/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt +++ b/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt @@ -56,7 +56,20 @@ fun QuackFloatingActionButtonDemo() { @Composable fun QuackMenuFloatingActionButtonDemo() { + var expanded by remember { + mutableStateOf( + value = false + ) + } + QuackMenuFloatingActionButton( + expanded = expanded, + onClickButton = { + expanded = true + }, + onDismissRequest = { + expanded = false + }, items = persistentListOf( QuackPopUpMenuItem( icon = QuackIcon.WriteFeed, @@ -68,6 +81,6 @@ fun QuackMenuFloatingActionButtonDemo() { text = "덕딜", onClick = {}, ), - ) + ), ) } From d7f2a631e673353688de1d085c92a1852d816fae Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 17:49:56 +0900 Subject: [PATCH 20/38] =?UTF-8?q?refactor:=20expanded=20=EC=A0=9C=EC=96=B4?= =?UTF-8?q?=EA=B6=8C=20=EC=A0=9C=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/duckie/quackquack/ui/component/fab.kt | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index cf6e56e08..e057d9a22 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -36,7 +36,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.geometry.Offset import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.layout.positionInParent import androidx.compose.ui.layout.positionInWindow import androidx.compose.ui.platform.LocalDensity import androidx.compose.ui.unit.IntOffset @@ -51,7 +50,6 @@ import team.duckie.quackquack.ui.constant.QuackWidth import team.duckie.quackquack.ui.icon.QuackIcon import team.duckie.quackquack.ui.modifier.applyQuackSize import team.duckie.quackquack.ui.modifier.quackClickable -import team.duckie.quackquack.ui.textstyle.QuackTextStyle private val QuackFabSize = 48.dp @@ -83,9 +81,11 @@ class QuackPopUpMenuItem( */ @Composable fun QuackMenuFloatingActionButton( + expanded: Boolean, + onClickButton: () -> Unit, + onDismissRequest: () -> Unit, items: PersistentList, ) { - var expanded by remember { mutableStateOf(false) } var positionInRoot by remember { mutableStateOf(Offset.Zero) } var menuSize by remember { mutableStateOf(IntSize.Zero) } var buttonSize by remember { mutableStateOf(IntSize.Zero) } @@ -97,18 +97,14 @@ fun QuackMenuFloatingActionButton( buttonSize = layoutCoordinates.size }, icon = QuackIcon.Plus, - onClick = { - expanded = true - }, + onClick = onClickButton, ) if (expanded) { QuackDialog( buttonOffset = positionInRoot, menuSize = menuSize, buttonSize = buttonSize, - onDismissRequest = { - expanded = false - }, + onDismissRequest = onDismissRequest, ) { Column( modifier = Modifier.onGloballyPositioned { layoutCoordinates -> @@ -126,9 +122,7 @@ fun QuackMenuFloatingActionButton( ) QuackBasicFloatingActionButton( icon = QuackIcon.Close, - onClick = { - expanded = false - }, + onClick = onDismissRequest, ) } } From 17c816ee8b1d4ac7a6adbc320c9b9396fcd397e2 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 17:50:18 +0900 Subject: [PATCH 21/38] =?UTF-8?q?test:=20=EC=8A=A4=EB=83=85=EC=83=B7=20?= =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20expanded=20parameter=EB=A1=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B3=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/duckie/quackquack/ui/QuackFab.kt | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFab.kt b/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFab.kt index 47775e2b4..cd85c0c3a 100644 --- a/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFab.kt +++ b/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFab.kt @@ -21,13 +21,18 @@ import team.duckie.quackquack.ui.component.QuackPopUpMenuItem import team.duckie.quackquack.ui.icon.QuackIcon import team.duckie.quackquack.ui.rule.AnimationTestRule import team.duckie.quackquack.ui.textstyle.QuackFontScale +import team.duckie.quackquack.ui.util.PaparazziConfig import team.duckie.quackquack.ui.util.boxSnapshot import team.duckie.quackquack.ui.util.buildPaparazzi @RunWith(TestParameterInjector::class) class QuackFab { @get:Rule - val paparazzi = buildPaparazzi() + val paparazzi = buildPaparazzi { + this.apply { + screenHeight = 500 + } + } @get:Rule val animationTest = AnimationTestRule() @@ -49,21 +54,25 @@ class QuackFab { @Test fun QuackMenuFloatingActionButton( + @TestParameter expanded: Boolean, @TestParameter("0.5", "1.0", "1.5", "2.0") fontScale: Double, ) { paparazzi.boxSnapshot( - name = "[fontScale:$fontScale]", + name = "[expanded:$expanded]-[fontScale:$fontScale]", ) { QuackFontScale = fontScale team.duckie.quackquack.ui.component.QuackMenuFloatingActionButton( + expanded = expanded, + onClickButton = {}, + onDismissRequest = {}, items = persistentListOf( QuackPopUpMenuItem( - quackIcon = QuackIcon.WriteFeed, + icon = QuackIcon.WriteFeed, text = "피드", onClick = {}, ), QuackPopUpMenuItem( - quackIcon = QuackIcon.DrawerBuy, + icon = QuackIcon.DrawerBuy, text = "덕딜", onClick = {}, ), From 7d751b712bfaf7a83e6976974ba6255c7ec64208 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 20:02:15 +0900 Subject: [PATCH 22/38] =?UTF-8?q?refactor:=20Spacer=20=EC=A0=9C=EA=B1=B0?= =?UTF-8?q?=20=ED=9B=84=20padding=EC=9C=BC=EB=A1=9C=20=EB=8C=80=EC=B2=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/fab.kt | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index e057d9a22..69eb8da76 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -111,15 +111,13 @@ fun QuackMenuFloatingActionButton( menuSize = layoutCoordinates.size }, horizontalAlignment = Alignment.End, + verticalArrangement = Arrangement.spacedBy( + space = QuackFabItemSpacing, + ), ) { QuackDialogMenu( items = items, ) - Spacer( - modifier = Modifier.height( - height = QuackFabItemSpacing, - ), - ) QuackBasicFloatingActionButton( icon = QuackIcon.Close, onClick = onDismissRequest, @@ -254,16 +252,9 @@ private fun QuackDialogMenu( verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, ) { - items.forEach { item: QuackPopUpMenuItem -> + items.forEach { item: QuackDialogMenuItem -> QuackDialogMenuContent( - itemIcon = item.icon, - itemText = item.text, - onClickItem = item.onClick, - ) - Spacer( - modifier = Modifier.height( - height = QuackFabItemPadding, - ), + item = item, ) } } From 0945183de9a178600c6ba47de4516549dd75b070 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 20:17:14 +0900 Subject: [PATCH 23/38] =?UTF-8?q?refactor:=20QuackPopupItem=20->=20QuackDi?= =?UTF-8?q?alogItem=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD=20?= =?UTF-8?q?=EB=B0=8F=20DialogMenu=20Content=20parameter=20class=EB=A1=9C?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/fab.kt | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index 69eb8da76..ce34fbcda 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -15,9 +15,7 @@ import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size @@ -63,7 +61,7 @@ private val QuackFabItemPadding = 16.dp private val QuackFabItemSpacing = 8.dp @Immutable -class QuackPopUpMenuItem( +class QuackDialogMenuItem( val icon: QuackIcon, val text: String, val onClick: () -> Unit, @@ -74,17 +72,17 @@ class QuackPopUpMenuItem( * * [QuackFloatingActionButton] 과는 다르게, 버튼을 클릭하였을 때 * DialogMenu 가 출력됩니다. - * [QuackPopUpMenuItem] 을 통해 메뉴 아이템에 들어갈 icon, text, onClick 을 설정할 수 있습니다. + * [QuackDialogMenuItem] 을 통해 메뉴 아이템에 들어갈 icon, text, onClick 을 설정할 수 있습니다. * - * @param items 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackPopUpMenuItem] - * @see QuackPopUpMenuItem + * @param items 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackDialogMenuItem] + * @see QuackDialogMenuItem */ @Composable fun QuackMenuFloatingActionButton( expanded: Boolean, onClickButton: () -> Unit, onDismissRequest: () -> Unit, - items: PersistentList, + items: PersistentList, ) { var positionInRoot by remember { mutableStateOf(Offset.Zero) } var menuSize by remember { mutableStateOf(IntSize.Zero) } @@ -225,13 +223,13 @@ private fun QuackDialog( * * 메뉴의 아이템 리스트를 보여주는 Composable 입니다. * - * @param items 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackPopUpMenuItem] - * @see QuackPopUpMenuItem + * @param items 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackDialogMenuItem] + * @see QuackDialogMenuItem */ @Composable @NonRestartableComposable private fun QuackDialogMenu( - items: PersistentList, + items: PersistentList, ) { QuackSurface( modifier = Modifier.applyQuackSize( @@ -264,30 +262,30 @@ private fun QuackDialogMenu( /** * QuackDialogMenuContent 를 구현하였습니다. * - * 메뉴의 Item List Content 입니다. + * DialogMenu 의 item 이 어떻게 구성되는지 정의합니다. * - * @param itemIcon item 의 icon - * @param itemText item 의 text - * @param onClickItem item 의 클릭 이벤트 + * @param item DialogMenu 에 들어갈 [QuackDialogMenuItem] */ @Composable @NonRestartableComposable internal fun QuackDialogMenuContent( - itemIcon: QuackIcon, - itemText: String, - onClickItem: () -> Unit, + item: QuackDialogMenuItem, ) { Row( - modifier = Modifier.quackClickable( - onClick = onClickItem, - ), + modifier = Modifier + .padding( + bottom = QuackFabItemPadding, + ) + .quackClickable( + onClick = item.onClick, + ), verticalAlignment = Alignment.CenterVertically, ) { QuackImage( - icon = itemIcon, + icon = item.icon, ) QuackSubtitle( - text = itemText, + text = item.text, ) } } From c6b45cf69cd51413fb7c7d958b590b908b16f2df Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 20:17:35 +0900 Subject: [PATCH 24/38] =?UTF-8?q?feat:=20Item=EA=B3=BC=20Text=20=EC=82=AC?= =?UTF-8?q?=EC=9D=B4=20=EA=B0=84=EA=B2=A9=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/team/duckie/quackquack/ui/component/fab.kt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index ce34fbcda..d9cf125c8 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -57,8 +57,8 @@ private val QuackPopUpMenuShape = RoundedCornerShape(12.dp) private val QuackMenuTopPadding = 20.dp private val QuackMenuHorizontalPadding = 16.dp private val QuackFabItemPadding = 16.dp - private val QuackFabItemSpacing = 8.dp +private val QuackIconTextSpacing = 4.dp @Immutable class QuackDialogMenuItem( @@ -280,6 +280,9 @@ internal fun QuackDialogMenuContent( onClick = item.onClick, ), verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy( + space = QuackIconTextSpacing, + ), ) { QuackImage( icon = item.icon, From 7a7269cab1e706deadc454b36045f0eb46dbf7dd Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 20:18:03 +0900 Subject: [PATCH 25/38] =?UTF-8?q?refactor:=20QuackPopupItem=20->=20QuackDi?= =?UTF-8?q?alogItem=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/playground/realworld/FabPlayground.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt b/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt index 56dd39784..e148ee733 100644 --- a/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt +++ b/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt @@ -20,9 +20,9 @@ import kotlinx.collections.immutable.persistentListOf import team.duckie.quackquack.playground.base.BaseActivity import team.duckie.quackquack.playground.base.PlaygroundSection import team.duckie.quackquack.playground.theme.PlaygroundTheme +import team.duckie.quackquack.ui.component.QuackDialogMenuItem import team.duckie.quackquack.ui.component.QuackFloatingActionButton import team.duckie.quackquack.ui.component.QuackMenuFloatingActionButton -import team.duckie.quackquack.ui.component.QuackPopUpMenuItem import team.duckie.quackquack.ui.icon.QuackIcon class FabPlayground : BaseActivity() { @@ -71,12 +71,12 @@ fun QuackMenuFloatingActionButtonDemo() { expanded = false }, items = persistentListOf( - QuackPopUpMenuItem( + QuackDialogMenuItem( icon = QuackIcon.WriteFeed, text = "피드", onClick = {}, ), - QuackPopUpMenuItem( + QuackDialogMenuItem( icon = QuackIcon.DrawerBuy, text = "덕딜", onClick = {}, From f5b85bd37924a46ab3233425e1853f1df0ae33c2 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 21:45:20 +0900 Subject: [PATCH 26/38] =?UTF-8?q?refactor:=20Column=20=EC=97=90=EC=84=9C?= =?UTF-8?q?=20LazyColumn=20=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/fab.kt | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index d9cf125c8..971dd52b9 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -19,6 +19,9 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.LazyListScope +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.runtime.Composable @@ -114,7 +117,7 @@ fun QuackMenuFloatingActionButton( ), ) { QuackDialogMenu( - items = items, + menuItems = items, ) QuackBasicFloatingActionButton( icon = QuackIcon.Close, @@ -229,7 +232,7 @@ private fun QuackDialog( @Composable @NonRestartableComposable private fun QuackDialogMenu( - items: PersistentList, + menuItems: PersistentList, ) { QuackSurface( modifier = Modifier.applyQuackSize( @@ -239,18 +242,21 @@ private fun QuackDialogMenu( shape = QuackPopUpMenuShape, backgroundColor = QuackColor.White, ) { - Column( - modifier = Modifier - .padding( - horizontal = QuackMenuHorizontalPadding, - ) - .padding( + LazyColumn( + contentPadding = PaddingValues( + start = QuackMenuHorizontalPadding, + end = QuackMenuHorizontalPadding, top = QuackMenuTopPadding, ), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, ) { - items.forEach { item: QuackDialogMenuItem -> + items( + items = menuItems, + key = { item: QuackDialogMenuItem -> + item.text + }, + ) { item: QuackDialogMenuItem -> QuackDialogMenuContent( item = item, ) From 9e7201290e0f9474784d48f6475945c7163a3e18 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 21:56:08 +0900 Subject: [PATCH 27/38] =?UTF-8?q?refactor:=20=20@NonRestartableComposable?= =?UTF-8?q?=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=EA=B2=83=EB=93=A4=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=ED=95=98=EA=B3=A0=20=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EA=B2=83=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kotlin/team/duckie/quackquack/ui/component/fab.kt | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index 971dd52b9..65974980d 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -14,13 +14,13 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.BoxScope import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.offset import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.LazyColumn -import androidx.compose.foundation.lazy.LazyListScope import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape @@ -226,11 +226,10 @@ private fun QuackDialog( * * 메뉴의 아이템 리스트를 보여주는 Composable 입니다. * - * @param items 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackDialogMenuItem] + * @param menuItems 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackDialogMenuItem] * @see QuackDialogMenuItem */ @Composable -@NonRestartableComposable private fun QuackDialogMenu( menuItems: PersistentList, ) { @@ -246,8 +245,8 @@ private fun QuackDialogMenu( contentPadding = PaddingValues( start = QuackMenuHorizontalPadding, end = QuackMenuHorizontalPadding, - top = QuackMenuTopPadding, - ), + top = QuackMenuTopPadding, + ), verticalArrangement = Arrangement.Center, horizontalAlignment = Alignment.CenterHorizontally, ) { @@ -308,6 +307,7 @@ internal fun QuackDialogMenuContent( * @param onClick 버튼 클릭 이벤트 */ @Composable +@NonRestartableComposable fun QuackFloatingActionButton( icon: QuackIcon, onClick: () -> Unit, @@ -328,6 +328,7 @@ fun QuackFloatingActionButton( * @param onClick 버튼 클릭 이벤트 */ @Composable +@NonRestartableComposable private fun QuackBasicFloatingActionButton( modifier: Modifier = Modifier, icon: QuackIcon, From 146fe059b74080f7f956bcf141575ed117132dc3 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 22:43:09 +0900 Subject: [PATCH 28/38] =?UTF-8?q?feat:=20class=EC=97=90=20hashcode?= =?UTF-8?q?=EC=99=80=20equals=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/fab.kt | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index 65974980d..228a69a47 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -68,7 +68,27 @@ class QuackDialogMenuItem( val icon: QuackIcon, val text: String, val onClick: () -> Unit, -) +) { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as QuackDialogMenuItem + + if (icon != other.icon) return false + if (text != other.text) return false + if (onClick != other.onClick) return false + + return true + } + + override fun hashCode(): Int { + var result = icon.hashCode() + result = 31 * result + text.hashCode() + result = 31 * result + onClick.hashCode() + return result + } +} /** * QuackMenuFloatingActionButton 를 구현하였습니다. From 38099fc764708892917db55a199fff0a59f5f837 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 23:28:40 +0900 Subject: [PATCH 29/38] =?UTF-8?q?feat:=20AnimatedVisibility=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/kotlin/team/duckie/quackquack/ui/component/fab.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index 228a69a47..4a3eb5c12 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -9,6 +9,7 @@ package team.duckie.quackquack.ui.component +import androidx.compose.animation.AnimatedVisibility import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -120,7 +121,10 @@ fun QuackMenuFloatingActionButton( icon = QuackIcon.Plus, onClick = onClickButton, ) - if (expanded) { + + AnimatedVisibility( + visible = expanded, + ) { QuackDialog( buttonOffset = positionInRoot, menuSize = menuSize, From ca63030d08ed1c2bd9ff37568de6e85692c4161b Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 23:55:44 +0900 Subject: [PATCH 30/38] =?UTF-8?q?refactor:=20Item=EC=9D=98=20=EC=A4=91?= =?UTF-8?q?=EB=B3=B5=20=ED=81=B4=EB=A6=AD=20=EC=9D=B4=EB=B2=A4=ED=8A=B8=20?= =?UTF-8?q?=EC=97=86=EC=95=A0=EA=B3=A0,=20(QuackDialogMenuItem)=20->=20Uni?= =?UTF-8?q?t=20=EB=9E=8C=EB=8B=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../quackquack/playground/realworld/FabPlayground.kt | 5 ++--- .../kotlin/team/duckie/quackquack/ui/QuackFab.kt | 12 +++++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt b/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt index e148ee733..aeb53b17d 100644 --- a/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt +++ b/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt @@ -70,17 +70,16 @@ fun QuackMenuFloatingActionButtonDemo() { onDismissRequest = { expanded = false }, - items = persistentListOf( + menuItems = persistentListOf( QuackDialogMenuItem( icon = QuackIcon.WriteFeed, text = "피드", - onClick = {}, ), QuackDialogMenuItem( icon = QuackIcon.DrawerBuy, text = "덕딜", - onClick = {}, ), ), + onClickMenuItem = {}, ) } diff --git a/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFab.kt b/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFab.kt index cd85c0c3a..567337ac5 100644 --- a/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFab.kt +++ b/ui-components/src/test/kotlin/team/duckie/quackquack/ui/QuackFab.kt @@ -17,11 +17,10 @@ import kotlinx.collections.immutable.persistentListOf import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith -import team.duckie.quackquack.ui.component.QuackPopUpMenuItem +import team.duckie.quackquack.ui.component.QuackDialogMenuItem import team.duckie.quackquack.ui.icon.QuackIcon import team.duckie.quackquack.ui.rule.AnimationTestRule import team.duckie.quackquack.ui.textstyle.QuackFontScale -import team.duckie.quackquack.ui.util.PaparazziConfig import team.duckie.quackquack.ui.util.boxSnapshot import team.duckie.quackquack.ui.util.buildPaparazzi @@ -65,18 +64,17 @@ class QuackFab { expanded = expanded, onClickButton = {}, onDismissRequest = {}, - items = persistentListOf( - QuackPopUpMenuItem( + menuItems = persistentListOf( + QuackDialogMenuItem( icon = QuackIcon.WriteFeed, text = "피드", - onClick = {}, ), - QuackPopUpMenuItem( + QuackDialogMenuItem( icon = QuackIcon.DrawerBuy, text = "덕딜", - onClick = {}, ), ), + onClickMenuItem = {}, ) } } From a301b211738b3a52b888868204fae549048281b6 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 23:56:11 +0900 Subject: [PATCH 31/38] =?UTF-8?q?test:=20=ED=8C=8C=EB=9D=BC=EB=AF=B8?= =?UTF-8?q?=ED=84=B0=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=9D=BC=20?= =?UTF-8?q?=EB=9E=8C=EB=8B=A4=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/fab.kt | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index 4a3eb5c12..edd4ebdbb 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -68,7 +68,6 @@ private val QuackIconTextSpacing = 4.dp class QuackDialogMenuItem( val icon: QuackIcon, val text: String, - val onClick: () -> Unit, ) { override fun equals(other: Any?): Boolean { if (this === other) return true @@ -78,7 +77,6 @@ class QuackDialogMenuItem( if (icon != other.icon) return false if (text != other.text) return false - if (onClick != other.onClick) return false return true } @@ -86,7 +84,6 @@ class QuackDialogMenuItem( override fun hashCode(): Int { var result = icon.hashCode() result = 31 * result + text.hashCode() - result = 31 * result + onClick.hashCode() return result } } @@ -106,7 +103,8 @@ fun QuackMenuFloatingActionButton( expanded: Boolean, onClickButton: () -> Unit, onDismissRequest: () -> Unit, - items: PersistentList, + menuItems: PersistentList, + onClickMenuItem: (item: QuackDialogMenuItem) -> Unit, ) { var positionInRoot by remember { mutableStateOf(Offset.Zero) } var menuSize by remember { mutableStateOf(IntSize.Zero) } @@ -121,7 +119,6 @@ fun QuackMenuFloatingActionButton( icon = QuackIcon.Plus, onClick = onClickButton, ) - AnimatedVisibility( visible = expanded, ) { @@ -141,7 +138,9 @@ fun QuackMenuFloatingActionButton( ), ) { QuackDialogMenu( - menuItems = items, + menuItems = menuItems, + onClickMenuItem = onClickMenuItem, + onDismissRequest = onDismissRequest, ) QuackBasicFloatingActionButton( icon = QuackIcon.Close, @@ -256,6 +255,8 @@ private fun QuackDialog( @Composable private fun QuackDialogMenu( menuItems: PersistentList, + onClickMenuItem: (item: QuackDialogMenuItem) -> Unit, + onDismissRequest: () -> Unit, ) { QuackSurface( modifier = Modifier.applyQuackSize( @@ -281,7 +282,9 @@ private fun QuackDialogMenu( }, ) { item: QuackDialogMenuItem -> QuackDialogMenuContent( - item = item, + menuItem = item, + onClickMenuItem = onClickMenuItem, + onDismissRequest = onDismissRequest, ) } } @@ -298,7 +301,9 @@ private fun QuackDialogMenu( @Composable @NonRestartableComposable internal fun QuackDialogMenuContent( - item: QuackDialogMenuItem, + menuItem: QuackDialogMenuItem, + onClickMenuItem: (item: QuackDialogMenuItem) -> Unit, + onDismissRequest: () -> Unit, ) { Row( modifier = Modifier @@ -306,7 +311,10 @@ internal fun QuackDialogMenuContent( bottom = QuackFabItemPadding, ) .quackClickable( - onClick = item.onClick, + onClick = { + onClickMenuItem(menuItem) + onDismissRequest() + }, ), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy( @@ -314,10 +322,10 @@ internal fun QuackDialogMenuContent( ), ) { QuackImage( - icon = item.icon, + icon = menuItem.icon, ) QuackSubtitle( - text = item.text, + text = menuItem.text, ) } } From 1a6a8ff4bbe80724f8d6ff61e9e5e9cc678839e8 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Tue, 6 Sep 2022 23:57:04 +0900 Subject: [PATCH 32/38] =?UTF-8?q?refactor:=20named=20arguments=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index edd4ebdbb..8d68e04b6 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -369,7 +369,7 @@ private fun QuackBasicFloatingActionButton( Box( modifier = modifier .size( - QuackFabSize, + size = QuackFabSize, ) .clip( shape = QuackFabShape, From 83729e3f9f72903848684e5e5bc35bde01ed5d0f Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Wed, 7 Sep 2022 00:20:52 +0900 Subject: [PATCH 33/38] =?UTF-8?q?docs:=20=ED=8C=8C=EB=9D=BC=EB=AF=B8?= =?UTF-8?q?=ED=84=B0=20=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20?= =?UTF-8?q?Kdoc=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/fab.kt | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index 8d68e04b6..65f9bc6a2 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -93,9 +93,13 @@ class QuackDialogMenuItem( * * [QuackFloatingActionButton] 과는 다르게, 버튼을 클릭하였을 때 * DialogMenu 가 출력됩니다. - * [QuackDialogMenuItem] 을 통해 메뉴 아이템에 들어갈 icon, text, onClick 을 설정할 수 있습니다. + * [QuackDialogMenuItem] 을 통해 메뉴 아이템에 들어갈 icon, text 를 설정할 수 있습니다. * - * @param items 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackDialogMenuItem] + * @param expanded 메뉴가 현재 열려 있고 사용자에게 표시되는지 여부 + * @param onClickButton 버튼을 클릭했을 때 호출되는 콜백 + * @param onDismissRequest 사용자가 메뉴 닫기를 요청할 때 호출되는 콜백 + * @param menuItems 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackDialogMenuItem] + * @param onClickMenuItem 사용자가 메뉴 아이템을 클릭했을 때 호출되는 콜백 * @see QuackDialogMenuItem */ @Composable @@ -152,7 +156,7 @@ fun QuackMenuFloatingActionButton( } /** - * QuackMenuFloatingActionButton 를 클릭했을 때 나오는 다이얼로그 입니다. + * [QuackMenuFloatingActionButton] 를 클릭했을 때 나오는 다이얼로그 입니다. * * Dialog 는 내부적으로 Android Dialog 로 구현되어있고, Compose View 로 래핑되어 있습니다. * 따라서 위치를 수동으로 조절할 수는 없고, Full Size Box 에서 offset 으로 조정되어야 합니다. @@ -165,7 +169,7 @@ fun QuackMenuFloatingActionButton( * @param buttonOffset FloatingActionButton 의 offset * @param menuSize menu container 크기 * @param buttonSize button container 크기 - * @param onDismissRequest Menu 를 닫으라는 명령이 떨어졌을 때의 동작 + * @param onDismissRequest 사용자가 메뉴 닫기를 요청할 때 호출되는 콜백 * @param content Dialog 내부에 들어갈 Composable */ @OptIn(ExperimentalComposeUiApi::class) @@ -247,9 +251,11 @@ private fun QuackDialog( /** * QuackDialogMenu 를 구현하였습니다. * - * 메뉴의 아이템 리스트를 보여주는 Composable 입니다. + * Dialog Menu 에 표시될 Item List 입니다. * * @param menuItems 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackDialogMenuItem] + * @param onClickMenuItem 사용자가 메뉴 아이템을 클릭했을 때 호출되는 콜백 + * @param onDismissRequest 사용자가 메뉴 닫기를 요청할 때 호출되는 콜백 * @see QuackDialogMenuItem */ @Composable @@ -296,7 +302,9 @@ private fun QuackDialogMenu( * * DialogMenu 의 item 이 어떻게 구성되는지 정의합니다. * - * @param item DialogMenu 에 들어갈 [QuackDialogMenuItem] + * @param menuItem DialogMenu 에 들어갈 [QuackDialogMenuItem] + * @param onClickMenuItem 사용자가 메뉴 아이템을 클릭했을 때 호출되는 콜백 + * @param onDismissRequest 사용자가 메뉴 닫기를 요청할 때 호출되는 콜백 */ @Composable @NonRestartableComposable From f8ed180675f4f69be4ee74c8162e6b8bf3afa4c0 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Thu, 8 Sep 2022 22:14:48 +0900 Subject: [PATCH 34/38] =?UTF-8?q?refactor:=20fab=20offset,size=20=EB=9E=8C?= =?UTF-8?q?=EB=8B=A4=EB=A1=9C=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/fab.kt | 129 ++++++++---------- 1 file changed, 56 insertions(+), 73 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index 65f9bc6a2..ec2d142cf 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -6,7 +6,6 @@ * Licensed under the MIT. * Please see full license: https://github.com/sungbinland/quack-quack/blob/main/LICENSE */ - package team.duckie.quackquack.ui.component import androidx.compose.animation.AnimatedVisibility @@ -36,16 +35,17 @@ import androidx.compose.ui.Alignment import androidx.compose.ui.ExperimentalComposeUiApi import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip -import androidx.compose.ui.geometry.Offset +import androidx.compose.ui.layout.boundsInWindow import androidx.compose.ui.layout.onGloballyPositioned -import androidx.compose.ui.layout.positionInWindow import androidx.compose.ui.platform.LocalDensity +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.Density import androidx.compose.ui.unit.IntOffset -import androidx.compose.ui.unit.IntSize import androidx.compose.ui.unit.dp import androidx.compose.ui.window.Dialog import androidx.compose.ui.window.DialogProperties import kotlinx.collections.immutable.PersistentList +import kotlinx.collections.immutable.persistentListOf import team.duckie.quackquack.ui.color.QuackColor import team.duckie.quackquack.ui.constant.QuackHeight import team.duckie.quackquack.ui.constant.QuackWidth @@ -98,7 +98,7 @@ class QuackDialogMenuItem( * @param expanded 메뉴가 현재 열려 있고 사용자에게 표시되는지 여부 * @param onClickButton 버튼을 클릭했을 때 호출되는 콜백 * @param onDismissRequest 사용자가 메뉴 닫기를 요청할 때 호출되는 콜백 - * @param menuItems 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackDialogMenuItem] + * @param menuItems 버튼을 클릭했을 때 나오는 메뉴의 [QuackDialogMenuItem] 리스트 * @param onClickMenuItem 사용자가 메뉴 아이템을 클릭했을 때 호출되는 콜백 * @see QuackDialogMenuItem */ @@ -110,15 +110,21 @@ fun QuackMenuFloatingActionButton( menuItems: PersistentList, onClickMenuItem: (item: QuackDialogMenuItem) -> Unit, ) { - var positionInRoot by remember { mutableStateOf(Offset.Zero) } - var menuSize by remember { mutableStateOf(IntSize.Zero) } - var buttonSize by remember { mutableStateOf(IntSize.Zero) } + val density = LocalDensity.current + var buttonXOffset by remember { mutableStateOf(0.dp) } + var buttonYOffset by remember { mutableStateOf(0.dp) } + var buttonWidth by remember { mutableStateOf(0) } + var dialogContentWidth by remember { mutableStateOf(0) } + var dialogContentHeight by remember { mutableStateOf(0) } QuackBasicFloatingActionButton( modifier = Modifier .onGloballyPositioned { layoutCoordinates -> - positionInRoot = layoutCoordinates.positionInWindow() - buttonSize = layoutCoordinates.size + with(density) { + buttonXOffset = layoutCoordinates.boundsInWindow().center.x.toDp() + buttonYOffset = layoutCoordinates.boundsInWindow().center.y.toDp() + buttonWidth = layoutCoordinates.size.width + } }, icon = QuackIcon.Plus, onClick = onClickButton, @@ -127,15 +133,20 @@ fun QuackMenuFloatingActionButton( visible = expanded, ) { QuackDialog( - buttonOffset = positionInRoot, - menuSize = menuSize, - buttonSize = buttonSize, + offsetProvider = { + IntOffset( + x = buttonXOffset.roundToPx() - dialogContentWidth + buttonWidth / 2, + y = buttonYOffset.roundToPx() - dialogContentHeight, + ) + }, onDismissRequest = onDismissRequest, ) { Column( - modifier = Modifier.onGloballyPositioned { layoutCoordinates -> - menuSize = layoutCoordinates.size - }, + modifier = Modifier + .onGloballyPositioned { layoutCoordinates -> + dialogContentWidth = layoutCoordinates.size.width + dialogContentHeight = layoutCoordinates.size.height + }, horizontalAlignment = Alignment.End, verticalArrangement = Arrangement.spacedBy( space = QuackFabItemSpacing, @@ -166,18 +177,14 @@ fun QuackMenuFloatingActionButton( * * dpOffsetX - menuWidth + buttonWidth * - * @param buttonOffset FloatingActionButton 의 offset - * @param menuSize menu container 크기 - * @param buttonSize button container 크기 + * @param offsetProvider 내부 Composable 이 배치 될 offset * @param onDismissRequest 사용자가 메뉴 닫기를 요청할 때 호출되는 콜백 * @param content Dialog 내부에 들어갈 Composable */ @OptIn(ExperimentalComposeUiApi::class) @Composable private fun QuackDialog( - buttonOffset: Offset, - menuSize: IntSize, - buttonSize: IntSize, + offsetProvider: Density.() -> IntOffset, onDismissRequest: () -> Unit, content: @Composable BoxScope.() -> Unit, ) { @@ -187,62 +194,18 @@ private fun QuackDialog( usePlatformDefaultWidth = false, ), ) { - val density = LocalDensity.current - val dpOffsetX = with( - receiver = density, - ) { - buttonOffset.x.toDp() - } - val dpOffsetY = with( - receiver = density, - ) { - buttonOffset.y.toDp() - } - val menuWidth = with( - receiver = density, - ) { - menuSize.width.toDp() - } - val menuHeight = with( - receiver = density, - ) { - menuSize.height.toDp() - } - val buttonWidth = with( - receiver = density, - ) { - buttonSize.width.toDp() - } - val buttonHeight = with( - receiver = density, - ) { - buttonSize.height.toDp() - } - var xOffset by remember { - mutableStateOf(0) - } - var yOffset by remember { - mutableStateOf(0) - } - xOffset = (dpOffsetX - menuWidth + buttonWidth).value.toInt() - yOffset = (dpOffsetY - menuHeight + buttonHeight).value.toInt() - Box( modifier = Modifier .fillMaxSize() .quackClickable( onClick = onDismissRequest - ) - .offset { - IntOffset( - x = xOffset, - y = yOffset, - ) - }, - contentAlignment = Alignment.TopStart, + ), ) { Box( - content = content + modifier = Modifier.offset( + offset = offsetProvider, + ), + content = content, ) } } @@ -253,7 +216,7 @@ private fun QuackDialog( * * Dialog Menu 에 표시될 Item List 입니다. * - * @param menuItems 버튼을 클릭했을 때 나오는 메뉴의 아이템 리스트 [QuackDialogMenuItem] + * @param menuItems 버튼을 클릭했을 때 나오는 메뉴의 [QuackDialogMenuItem] 리스트 * @param onClickMenuItem 사용자가 메뉴 아이템을 클릭했을 때 호출되는 콜백 * @param onDismissRequest 사용자가 메뉴 닫기를 요청할 때 호출되는 콜백 * @see QuackDialogMenuItem @@ -302,7 +265,7 @@ private fun QuackDialogMenu( * * DialogMenu 의 item 이 어떻게 구성되는지 정의합니다. * - * @param menuItem DialogMenu 에 들어갈 [QuackDialogMenuItem] + * @param menuItem [QuackDialogMenu] 에 들어갈 [QuackDialogMenuItem] * @param onClickMenuItem 사용자가 메뉴 아이템을 클릭했을 때 호출되는 콜백 * @param onDismissRequest 사용자가 메뉴 닫기를 요청할 때 호출되는 콜백 */ @@ -396,3 +359,23 @@ private fun QuackBasicFloatingActionButton( ) } } + +@Preview +@Composable +private fun Prev() { + var expanded by remember { mutableStateOf(false) } + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center, + ) { + QuackMenuFloatingActionButton( + expanded = expanded, + onClickButton = { expanded = true }, + onDismissRequest = { expanded = false }, + menuItems = persistentListOf( + QuackDialogMenuItem(QuackIcon.DrawerBuy, "2") + ), + onClickMenuItem = {}, + ) + } +} From 3ac360b98b5af731535b84c52ff35acbf4378ab4 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Thu, 8 Sep 2022 22:14:59 +0900 Subject: [PATCH 35/38] =?UTF-8?q?refactor:=20Playground=20Box=EB=A1=9C=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../quackquack/playground/base/common.kt | 131 +++++++++++++----- .../playground/realworld/FabPlayground.kt | 2 +- 2 files changed, 96 insertions(+), 37 deletions(-) diff --git a/playground/src/main/kotlin/team/duckie/quackquack/playground/base/common.kt b/playground/src/main/kotlin/team/duckie/quackquack/playground/base/common.kt index cc36dac87..c3847b589 100644 --- a/playground/src/main/kotlin/team/duckie/quackquack/playground/base/common.kt +++ b/playground/src/main/kotlin/team/duckie/quackquack/playground/base/common.kt @@ -18,17 +18,20 @@ import android.app.Activity import android.content.Intent import androidx.compose.foundation.ExperimentalFoundationApi import androidx.compose.foundation.background +import androidx.compose.foundation.border +import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsetsSides +import androidx.compose.foundation.layout.fillMaxHeight import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth -import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.only import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.systemBars import androidx.compose.foundation.layout.windowInsetsPadding import androidx.compose.foundation.layout.wrapContentSize @@ -37,10 +40,13 @@ import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.ArrowBack import androidx.compose.material3.AlertDialog import androidx.compose.material3.Button import androidx.compose.material3.ButtonDefaults import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon import androidx.compose.material3.MaterialTheme import androidx.compose.material3.Scaffold import androidx.compose.material3.SmallTopAppBar @@ -62,12 +68,13 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.unit.dp -import androidx.compose.ui.window.Dialog +import androidx.compose.ui.zIndex import androidx.datastore.preferences.core.edit import kotlin.math.roundToInt import kotlin.reflect.KClass import kotlinx.collections.immutable.PersistentList import kotlinx.coroutines.launch +import team.duckie.quackquack.playground.theme.md_theme_light_primaryContainer import team.duckie.quackquack.playground.util.PreferenceConfigs import team.duckie.quackquack.playground.util.dataStore import team.duckie.quackquack.playground.util.rememberToast @@ -138,7 +145,9 @@ fun PlaygroundActivities( containerColor = MaterialTheme.colorScheme.secondary, ), ) { - Text(text = "Playground 설정") + Text( + text = "Playground 설정", + ) } } @@ -159,7 +168,9 @@ fun PlaygroundActivities( ) { Text( text = (activity.simpleName ?: activity.toString()) - .removeSuffix(suffix = "Playground"), + .removeSuffix( + suffix = "Playground", + ), ) } } @@ -189,7 +200,7 @@ fun PlaygroundSection( items.forEachIndexed { index, (_, composable) -> PreviewAlert( visible = previewVisibleStates[index], - onDismissRequest = { + onBackPressed = { previewVisibleStates[index] = !previewVisibleStates[index] }, content = composable, @@ -232,7 +243,9 @@ fun PlaygroundSection( containerColor = MaterialTheme.colorScheme.secondary, ), ) { - Text(text = "Playground 설정") + Text( + text = "Playground 설정", + ) } } @@ -248,7 +261,9 @@ fun PlaygroundSection( previewVisibleStates[index] = true }, ) { - Text(text = contentTitle) + Text( + text = contentTitle, + ) } } } @@ -313,17 +328,23 @@ private fun PlaygroundSettingAlert( AlertDialog( modifier = Modifier.wrapContentSize(), title = { - Text(text = "Playground 설정") + Text( + text = "Playground 설정", + ) }, text = { Column( modifier = Modifier.wrapContentSize(), ) { - Text(text = "애니메이션 지속 시간") + Text( + text = "애니메이션 지속 시간", + ) TextField( modifier = Modifier .fillMaxWidth() - .padding(top = 4.dp), + .padding( + top = 4.dp, + ), value = animationDurationInputState, onValueChange = { newAnimationDuration -> animationDurationInputState = newAnimationDuration @@ -331,7 +352,9 @@ private fun PlaygroundSettingAlert( singleLine = true, trailingIcon = { Text( - modifier = Modifier.padding(end = 16.dp), + modifier = Modifier.padding( + end = 16.dp, + ), text = "단위: 초", ) }, @@ -340,13 +363,17 @@ private fun PlaygroundSettingAlert( ), ) Text( - modifier = Modifier.padding(top = 20.dp), + modifier = Modifier.padding( + top = 20.dp, + ), text = "Font Scale", ) TextField( modifier = Modifier .fillMaxWidth() - .padding(top = 4.dp), + .padding( + top = 4.dp, + ), value = fontScaleInputState, onValueChange = { newFontScale -> fontScaleInputState = newFontScale @@ -354,7 +381,9 @@ private fun PlaygroundSettingAlert( singleLine = true, trailingIcon = { Text( - modifier = Modifier.padding(end = 16.dp), + modifier = Modifier.padding( + end = 16.dp, + ), text = "배수", ) }, @@ -369,7 +398,9 @@ private fun PlaygroundSettingAlert( Button( onClick = ::dismiss, ) { - Text(text = "저장") + Text( + text = "저장", + ) } }, dismissButton = { @@ -379,17 +410,20 @@ private fun PlaygroundSettingAlert( toast("Playground 설정을 초기화 했어요") }, ) { - Text(text = "초기화") + Text( + text = "초기화", + ) } }, ) } } + @Composable private fun PreviewAlert( visible: Boolean, - onDismissRequest: () -> Unit, + onBackPressed: () -> Unit, content: @Composable () -> Unit, ) { if (visible) { @@ -398,30 +432,55 @@ private fun PreviewAlert( size = 15.dp, ) } - - Dialog( - onDismissRequest = onDismissRequest, - content = { - Box( + Box( + modifier = Modifier + .fillMaxSize() + .zIndex( + zIndex = 1.0f, + ), + contentAlignment = Alignment.Center, + ) { + Box( + modifier = Modifier + .border( + width = 5.dp, + color = md_theme_light_primaryContainer, + shape = alertShape, + ) + .clip( + shape = alertShape, + ) + .fillMaxWidth( + fraction = 0.8f, + ) + .fillMaxHeight( + fraction = 0.7f, + ) + .background( + color = Color.White, + ), + contentAlignment = Alignment.Center, + ) { + content() + Icon( modifier = Modifier - .clip( - shape = alertShape, + .size( + size = 48.dp, ) - .fillMaxWidth() - .height( - height = 500.dp, + .clickable( + onClick = onBackPressed, ) - .background( - color = Color.White, + .align( + alignment = Alignment.TopStart, ) .padding( - horizontal = 16.dp, + start = 16.dp, + top = 16.dp, ), - contentAlignment = Alignment.Center, - ) { - content() - } - }, - ) + imageVector = Icons.Default.ArrowBack, + contentDescription = "back" + ) + } + } } } diff --git a/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt b/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt index aeb53b17d..f6f845bf4 100644 --- a/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt +++ b/playground/src/main/kotlin/team/duckie/quackquack/playground/realworld/FabPlayground.kt @@ -58,7 +58,7 @@ fun QuackFloatingActionButtonDemo() { fun QuackMenuFloatingActionButtonDemo() { var expanded by remember { mutableStateOf( - value = false + value = false, ) } From fe588ee8a469b2555e697322ce6e13addfd09f73 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Thu, 8 Sep 2022 23:03:24 +0900 Subject: [PATCH 36/38] =?UTF-8?q?fix:=20NewLine=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/lint/compose/NewLineArgumentDetector.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/lint-compose/src/main/kotlin/team/duckie/quackquack/lint/compose/NewLineArgumentDetector.kt b/lint-compose/src/main/kotlin/team/duckie/quackquack/lint/compose/NewLineArgumentDetector.kt index ddfb20520..2199f1e51 100644 --- a/lint-compose/src/main/kotlin/team/duckie/quackquack/lint/compose/NewLineArgumentDetector.kt +++ b/lint-compose/src/main/kotlin/team/duckie/quackquack/lint/compose/NewLineArgumentDetector.kt @@ -128,4 +128,3 @@ class NewLineArgumentDetector : Detector(), SourceCodeScanner { private fun String.isNewLine() = this.startsWith("\n") } - From 27071e063d20a1089f5845d271e51139ad640b54 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Thu, 8 Sep 2022 23:40:18 +0900 Subject: [PATCH 37/38] =?UTF-8?q?refactor:=20lint=20module=20=EB=A6=B0?= =?UTF-8?q?=ED=8A=B8=20=EC=97=90=EB=9F=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/duckie/quackquack/lint/compose/NewLineArgumentTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/lint-compose/src/test/kotlin/team/duckie/quackquack/lint/compose/NewLineArgumentTest.kt b/lint-compose/src/test/kotlin/team/duckie/quackquack/lint/compose/NewLineArgumentTest.kt index 15b0c2196..a08205b35 100644 --- a/lint-compose/src/test/kotlin/team/duckie/quackquack/lint/compose/NewLineArgumentTest.kt +++ b/lint-compose/src/test/kotlin/team/duckie/quackquack/lint/compose/NewLineArgumentTest.kt @@ -131,4 +131,3 @@ class NewLineArgumentTest { ) } } - From 1833c3bc9b4f52b51faef07a53ea8f6d84393508 Mon Sep 17 00:00:00 2001 From: EvergreenTree97 Date: Thu, 8 Sep 2022 23:40:39 +0900 Subject: [PATCH 38/38] =?UTF-8?q?refactor:=20offset=20=EA=B5=AC=ED=95=98?= =?UTF-8?q?=EB=8A=94=EA=B1=B0=20kdoc=EC=97=90=20=EC=9E=90=EC=84=B8?= =?UTF-8?q?=ED=9E=88=20=EB=AA=85=EC=8B=9C=20=EB=B0=8F=20=EB=A6=B0=ED=8A=B8?= =?UTF-8?q?=20=EC=97=90=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../duckie/quackquack/ui/component/fab.kt | 59 +++++++++---------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt index ec2d142cf..2944a9ee2 100644 --- a/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt +++ b/ui-components/src/main/kotlin/team/duckie/quackquack/ui/component/fab.kt @@ -108,14 +108,26 @@ fun QuackMenuFloatingActionButton( onClickButton: () -> Unit, onDismissRequest: () -> Unit, menuItems: PersistentList, - onClickMenuItem: (item: QuackDialogMenuItem) -> Unit, + onClickMenuItem: ( + item: QuackDialogMenuItem, + ) -> Unit, ) { val density = LocalDensity.current - var buttonXOffset by remember { mutableStateOf(0.dp) } - var buttonYOffset by remember { mutableStateOf(0.dp) } - var buttonWidth by remember { mutableStateOf(0) } - var dialogContentWidth by remember { mutableStateOf(0) } - var dialogContentHeight by remember { mutableStateOf(0) } + var buttonXOffset by remember { + mutableStateOf(0.dp) + } + var buttonYOffset by remember { + mutableStateOf(0.dp) + } + var buttonWidth by remember { + mutableStateOf(0) + } + var dialogContentWidth by remember { + mutableStateOf(0) + } + var dialogContentHeight by remember { + mutableStateOf(0) + } QuackBasicFloatingActionButton( modifier = Modifier @@ -173,9 +185,12 @@ fun QuackMenuFloatingActionButton( * 따라서 위치를 수동으로 조절할 수는 없고, Full Size Box 에서 offset 으로 조정되어야 합니다. * * 따라서 FloatingActionButton 의 Offset 을 구한 다음, - * Menu 크기만큼 더하고 Button 크기만큼 빼면 위치를 조정시킬 수 있습니다. * - * dpOffsetX - menuWidth + buttonWidth + * xOffset = buttonXOffset - dialogContentWidth + buttonWidth / 2 + * + * yOffset = buttonYOffset - dialogContentHeight + * + * 으로 위치를 조정시킬 수 있습니다. * * @param offsetProvider 내부 Composable 이 배치 될 offset * @param onDismissRequest 사용자가 메뉴 닫기를 요청할 때 호출되는 콜백 @@ -224,7 +239,9 @@ private fun QuackDialog( @Composable private fun QuackDialogMenu( menuItems: PersistentList, - onClickMenuItem: (item: QuackDialogMenuItem) -> Unit, + onClickMenuItem: ( + item: QuackDialogMenuItem, + ) -> Unit, onDismissRequest: () -> Unit, ) { QuackSurface( @@ -273,7 +290,9 @@ private fun QuackDialogMenu( @NonRestartableComposable internal fun QuackDialogMenuContent( menuItem: QuackDialogMenuItem, - onClickMenuItem: (item: QuackDialogMenuItem) -> Unit, + onClickMenuItem: ( + item: QuackDialogMenuItem, + ) -> Unit, onDismissRequest: () -> Unit, ) { Row( @@ -359,23 +378,3 @@ private fun QuackBasicFloatingActionButton( ) } } - -@Preview -@Composable -private fun Prev() { - var expanded by remember { mutableStateOf(false) } - Box( - modifier = Modifier.fillMaxSize(), - contentAlignment = Alignment.Center, - ) { - QuackMenuFloatingActionButton( - expanded = expanded, - onClickButton = { expanded = true }, - onDismissRequest = { expanded = false }, - menuItems = persistentListOf( - QuackDialogMenuItem(QuackIcon.DrawerBuy, "2") - ), - onClickMenuItem = {}, - ) - } -}