Skip to content

Commit 1a6e9f5

Browse files
authored
Merge pull request #61 from YAPP-Github/feature/#56-custom-toast
[Feature/#56] 커스텀 토스트 메시지 구현
2 parents 997a706 + 9287a72 commit 1a6e9f5

File tree

11 files changed

+297
-24
lines changed

11 files changed

+297
-24
lines changed

app/src/main/java/com/threegap/bitnagil/MainActivity.kt

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,16 @@ import android.os.Bundle
44
import androidx.activity.ComponentActivity
55
import androidx.activity.compose.setContent
66
import androidx.activity.enableEdgeToEdge
7-
import com.threegap.bitnagil.designsystem.BitnagilTheme
7+
import androidx.compose.foundation.layout.Box
8+
import androidx.compose.foundation.layout.fillMaxSize
9+
import androidx.compose.foundation.layout.padding
10+
import androidx.compose.runtime.LaunchedEffect
11+
import androidx.compose.ui.Alignment
12+
import androidx.compose.ui.Modifier
13+
import androidx.compose.ui.unit.dp
14+
import com.threegap.bitnagil.designsystem.component.atom.BitnagilToastContainer
15+
import com.threegap.bitnagil.designsystem.component.atom.rememberBitnagilToast
16+
import com.threegap.bitnagil.presentation.common.toast.GlobalBitnagilToast
817
import dagger.hilt.android.AndroidEntryPoint
918

1019
@AndroidEntryPoint
@@ -14,10 +23,23 @@ class MainActivity : ComponentActivity() {
1423
enableEdgeToEdge()
1524
setContent {
1625
val mainNavigator = rememberMainNavigator()
17-
BitnagilTheme {
26+
val globalToast = rememberBitnagilToast()
27+
28+
LaunchedEffect(globalToast) {
29+
GlobalBitnagilToast.initialize(globalToast)
30+
}
31+
32+
Box(modifier = Modifier.fillMaxSize()) {
1833
MainScreen(
1934
navigator = mainNavigator,
2035
)
36+
37+
BitnagilToastContainer(
38+
state = globalToast,
39+
modifier = Modifier
40+
.align(Alignment.BottomCenter)
41+
.padding(bottom = 100.dp),
42+
)
2143
}
2244
}
2345
}

app/src/main/java/com/threegap/bitnagil/navigation/home/HomeNavHost.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.threegap.bitnagil.designsystem.R
2525
import com.threegap.bitnagil.designsystem.component.atom.BitnagilFloatingActionMenu
2626
import com.threegap.bitnagil.designsystem.component.atom.FloatingActionItem
2727
import com.threegap.bitnagil.designsystem.modifier.clickableWithoutRipple
28+
import com.threegap.bitnagil.presentation.common.toast.GlobalBitnagilToast
2829
import com.threegap.bitnagil.presentation.home.HomeScreenContainer
2930
import com.threegap.bitnagil.presentation.mypage.MyPageScreenContainer
3031
import com.threegap.bitnagil.presentation.recommendroutine.RecommendRoutineScreenContainer
@@ -114,8 +115,7 @@ fun HomeNavHost(
114115
onToggle = { expanded -> showFloatingOverlay = expanded },
115116
modifier = Modifier
116117
.align(Alignment.BottomEnd)
117-
.padding(16.dp)
118-
.padding(bottom = 80.dp),
118+
.padding(end = 16.dp, bottom = 80.dp),
119119
)
120120
}
121121
}
@@ -131,6 +131,7 @@ fun DoubleBackButtonPressedHandler() {
131131
(context as? Activity)?.finish()
132132
} else {
133133
backPressedTimeMillis = System.currentTimeMillis()
134+
GlobalBitnagilToast.showWarning("버튼을 한 번 더 누르면 종료됩니다.")
134135
}
135136
}
136137
}
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
package com.threegap.bitnagil.designsystem.component.atom
2+
3+
import androidx.annotation.DrawableRes
4+
import androidx.compose.animation.AnimatedVisibility
5+
import androidx.compose.animation.fadeIn
6+
import androidx.compose.animation.fadeOut
7+
import androidx.compose.animation.slideInVertically
8+
import androidx.compose.animation.slideOutVertically
9+
import androidx.compose.foundation.background
10+
import androidx.compose.foundation.layout.Arrangement
11+
import androidx.compose.foundation.layout.Box
12+
import androidx.compose.foundation.layout.Column
13+
import androidx.compose.foundation.layout.Row
14+
import androidx.compose.foundation.layout.padding
15+
import androidx.compose.foundation.layout.size
16+
import androidx.compose.foundation.shape.RoundedCornerShape
17+
import androidx.compose.material3.Text
18+
import androidx.compose.runtime.Composable
19+
import androidx.compose.runtime.LaunchedEffect
20+
import androidx.compose.runtime.getValue
21+
import androidx.compose.runtime.mutableIntStateOf
22+
import androidx.compose.runtime.mutableStateOf
23+
import androidx.compose.runtime.remember
24+
import androidx.compose.runtime.setValue
25+
import androidx.compose.ui.Alignment
26+
import androidx.compose.ui.Modifier
27+
import androidx.compose.ui.text.style.TextAlign
28+
import androidx.compose.ui.tooling.preview.Preview
29+
import androidx.compose.ui.unit.dp
30+
import com.threegap.bitnagil.designsystem.BitnagilTheme
31+
import com.threegap.bitnagil.designsystem.R
32+
import kotlinx.coroutines.delay
33+
34+
@Composable
35+
fun BitnagilToastMessage(
36+
text: String,
37+
modifier: Modifier = Modifier,
38+
@DrawableRes id: Int? = null,
39+
) {
40+
Box(
41+
modifier = modifier
42+
.background(
43+
color = BitnagilTheme.colors.navy400,
44+
shape = RoundedCornerShape(8.dp),
45+
)
46+
.padding(vertical = 10.dp, horizontal = 20.dp),
47+
contentAlignment = Alignment.Center,
48+
) {
49+
Row(
50+
verticalAlignment = Alignment.CenterVertically,
51+
) {
52+
if (id != null) {
53+
BitnagilIcon(
54+
id = id,
55+
tint = BitnagilTheme.colors.error,
56+
modifier = Modifier
57+
.padding(end = 4.dp)
58+
.size(24.dp),
59+
)
60+
}
61+
Text(
62+
text = text,
63+
color = BitnagilTheme.colors.white,
64+
style = BitnagilTheme.typography.body2Medium,
65+
textAlign = TextAlign.Center,
66+
)
67+
}
68+
}
69+
}
70+
71+
@Composable
72+
fun BitnagilToastContainer(
73+
state: BitnagilToastState,
74+
modifier: Modifier = Modifier,
75+
duration: Long = 2000L,
76+
) {
77+
if (state.isVisible) {
78+
LaunchedEffect(state.toastId) {
79+
if (state.isVisible) {
80+
delay(duration)
81+
state.hide()
82+
}
83+
}
84+
85+
AnimatedVisibility(
86+
visible = state.isVisible,
87+
enter = fadeIn() + slideInVertically { it / 2 },
88+
exit = fadeOut() + slideOutVertically { it / 2 },
89+
modifier = modifier,
90+
) {
91+
BitnagilToastMessage(
92+
text = state.text,
93+
id = state.icon,
94+
)
95+
}
96+
}
97+
}
98+
99+
class BitnagilToastState {
100+
private var _text by mutableStateOf("")
101+
private var _icon by mutableStateOf<Int?>(null)
102+
private var _isVisible by mutableStateOf(false)
103+
private var _toastId by mutableIntStateOf(0)
104+
private var _lastShowTime = 0L
105+
106+
val text: String get() = _text
107+
val icon: Int? get() = _icon
108+
val isVisible: Boolean get() = _isVisible
109+
val toastId: Int get() = _toastId
110+
111+
fun show(text: String, icon: Int? = null) {
112+
if (shouldPreventDuplicateShow(text, icon)) {
113+
return
114+
}
115+
showToast(text, icon)
116+
}
117+
118+
fun hide() {
119+
_isVisible = false
120+
}
121+
122+
private fun shouldPreventDuplicateShow(text: String, icon: Int?): Boolean {
123+
val currentTime = System.currentTimeMillis()
124+
return _text == text && _icon == icon && currentTime - _lastShowTime < 500L
125+
}
126+
127+
private fun showToast(text: String, icon: Int?) {
128+
_text = text
129+
_icon = icon
130+
_isVisible = true
131+
_lastShowTime = System.currentTimeMillis()
132+
_toastId += 1
133+
}
134+
}
135+
136+
@Composable
137+
fun rememberBitnagilToast(): BitnagilToastState = remember { BitnagilToastState() }
138+
139+
@Preview
140+
@Composable
141+
private fun BitnagilToastMessagePreview() {
142+
Column(
143+
verticalArrangement = Arrangement.spacedBy(8.dp),
144+
) {
145+
BitnagilToastMessage(
146+
text = "버튼을 한 번 더 누르면 종료됩니다.",
147+
id = R.drawable.ic_warning,
148+
)
149+
150+
BitnagilToastMessage(
151+
text = "루틴 완료 상태 저장에 실패했어요.\n다시 시도해 주세요.",
152+
)
153+
}
154+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<vector xmlns:android="http://schemas.android.com/apk/res/android"
2+
android:width="55dp"
3+
android:height="55dp"
4+
android:viewportWidth="55"
5+
android:viewportHeight="55">
6+
<group>
7+
<clip-path android:pathData="M0,0h55v55h-55z" />
8+
<path
9+
android:fillColor="#C2C4C8"
10+
android:pathData="M0.17,27.508C0.17,27.137 0.394,26.782 0.409,26.411C0.425,26.04 0.432,25.685 0.463,25.315C0.494,24.944 0.417,24.573 0.463,24.21C0.509,23.847 0.679,23.5 0.733,23.145C0.787,22.789 0.757,22.403 0.826,22.048C0.895,21.693 1.019,21.345 1.104,20.99C1.189,20.635 1.019,20.21 1.119,19.855C1.22,19.499 1.266,19.121 1.382,18.774C1.498,18.426 1.752,18.117 1.876,17.777C1.999,17.438 2.239,17.129 2.378,16.789C2.517,16.449 2.486,16.024 2.64,15.692C2.794,15.36 3.057,15.074 3.227,14.75C3.397,14.426 3.466,14.04 3.651,13.715C3.837,13.391 4.045,13.09 4.246,12.773C4.446,12.457 4.632,12.14 4.84,11.839C5.048,11.538 5.272,11.229 5.488,10.943C5.705,10.657 6.206,10.572 6.438,10.286C6.669,10.001 6.932,9.754 7.179,9.476C7.426,9.198 7.658,8.927 7.912,8.657C8.167,8.387 8.182,7.892 8.453,7.638C8.723,7.383 9.024,7.167 9.302,6.919C9.58,6.672 9.811,6.379 10.097,6.147C10.382,5.915 10.676,5.684 10.969,5.468C11.262,5.251 11.602,5.081 11.911,4.873C12.22,4.664 12.49,4.41 12.806,4.217C13.123,4.023 13.462,3.869 13.779,3.684C14.095,3.498 14.458,3.382 14.783,3.213C15.107,3.043 15.369,2.742 15.701,2.579C16.033,2.417 16.488,2.533 16.828,2.394C17.168,2.255 17.5,2.101 17.839,1.969C18.179,1.838 18.557,1.823 18.912,1.707C19.267,1.591 19.514,1.174 19.869,1.066C20.225,0.958 20.58,0.857 20.935,0.772C21.29,0.687 21.66,0.641 22.023,0.571C22.386,0.502 22.749,0.425 23.112,0.371C23.474,0.317 23.853,0.363 24.223,0.317C24.594,0.27 24.941,0.147 25.312,0.116C25.682,0.085 26.045,0.031 26.416,0.015C26.786,0 27.156,-0.008 27.519,-0.008C27.882,-0.008 28.253,0.255 28.615,0.27C28.978,0.286 29.341,0.348 29.704,0.378C30.067,0.409 30.453,0.263 30.816,0.309C31.178,0.355 31.526,0.517 31.888,0.571C32.251,0.626 32.599,0.765 32.954,0.834C33.309,0.904 33.672,0.958 34.027,1.043C34.382,1.127 34.76,1.151 35.107,1.251C35.455,1.351 35.879,1.266 36.227,1.382C36.574,1.498 36.906,1.676 37.253,1.807C37.601,1.938 37.879,2.224 38.218,2.371C38.558,2.518 38.905,2.626 39.237,2.78C39.569,2.935 39.801,3.29 40.125,3.46C40.449,3.63 40.827,3.691 41.144,3.877C41.46,4.062 41.908,4.031 42.217,4.232C42.526,4.433 42.641,4.919 42.943,5.128C43.243,5.336 43.768,5.236 44.062,5.46C44.355,5.684 44.509,6.085 44.795,6.317C45.081,6.549 45.32,6.834 45.59,7.082C45.86,7.329 46.239,7.46 46.501,7.715C46.764,7.97 47.003,8.255 47.258,8.518C47.512,8.781 47.628,9.174 47.875,9.445C48.122,9.715 48.423,9.939 48.655,10.225C48.886,10.51 49.218,10.711 49.442,11.012C49.666,11.314 49.705,11.723 49.921,12.032C50.137,12.341 50.585,12.472 50.785,12.781C50.986,13.09 50.955,13.538 51.14,13.862C51.326,14.186 51.604,14.441 51.773,14.773C51.943,15.105 52.105,15.43 52.26,15.762C52.414,16.094 52.707,16.372 52.854,16.712C53.001,17.051 52.885,17.492 53.016,17.839C53.147,18.187 53.124,18.573 53.24,18.92C53.356,19.268 53.595,19.569 53.695,19.924C53.796,20.279 53.873,20.635 53.958,20.99C54.043,21.345 54.236,21.677 54.305,22.04C54.375,22.403 54.498,22.751 54.552,23.114C54.606,23.477 54.622,23.847 54.668,24.21C54.714,24.573 54.792,24.936 54.815,25.307C54.838,25.677 54.946,26.04 54.961,26.403C54.977,26.766 54.815,27.145 54.815,27.515C54.815,27.886 54.961,28.257 54.946,28.62C54.931,28.983 54.691,29.346 54.66,29.709C54.63,30.072 54.545,30.435 54.498,30.798C54.452,31.16 54.56,31.547 54.498,31.91C54.437,32.272 54.56,32.674 54.483,33.029C54.406,33.385 54.22,33.732 54.136,34.087C54.05,34.443 53.75,34.744 53.649,35.099C53.549,35.454 53.68,35.879 53.564,36.227C53.448,36.574 53.302,36.922 53.171,37.261C53.039,37.601 52.653,37.848 52.507,38.18C52.36,38.512 52.314,38.898 52.159,39.231C52.005,39.563 51.866,39.902 51.696,40.227C51.526,40.551 51.187,40.775 51.001,41.099C50.816,41.424 50.785,41.825 50.585,42.134C50.384,42.443 50.098,42.69 49.89,42.991C49.681,43.293 49.512,43.617 49.288,43.91C49.064,44.204 48.894,44.536 48.662,44.822C48.431,45.107 48.215,45.409 47.975,45.687C47.736,45.965 47.543,46.297 47.288,46.559C47.034,46.822 46.771,47.084 46.509,47.339C46.246,47.594 45.953,47.826 45.683,48.073C45.413,48.32 45.05,48.467 44.764,48.698C44.479,48.93 44.178,49.139 43.884,49.355C43.591,49.571 43.228,49.695 42.927,49.903C42.626,50.112 42.294,50.266 41.985,50.459C41.676,50.652 41.507,51.085 41.19,51.262C40.874,51.44 40.426,51.386 40.102,51.556C39.778,51.726 39.453,51.88 39.121,52.042C38.79,52.204 38.566,52.583 38.226,52.73C37.886,52.876 37.508,52.915 37.168,53.046C36.829,53.178 36.543,53.479 36.196,53.595C35.848,53.71 35.509,53.865 35.154,53.965C34.799,54.066 34.374,53.88 34.011,53.965C33.648,54.05 33.324,54.228 32.961,54.297C32.599,54.367 32.22,54.297 31.858,54.359C31.495,54.421 31.14,54.467 30.769,54.514C30.399,54.56 30.051,54.691 29.688,54.722C29.326,54.753 28.963,54.931 28.6,54.938C28.237,54.946 27.867,55 27.496,55C27.126,55 26.755,54.931 26.392,54.915C26.029,54.9 25.651,54.961 25.281,54.931C24.91,54.9 24.578,54.56 24.215,54.514C23.853,54.467 23.482,54.467 23.119,54.413C22.757,54.359 22.347,54.537 21.992,54.459C21.637,54.382 21.267,54.32 20.904,54.236C20.541,54.151 20.186,54.035 19.839,53.934C19.491,53.834 19.128,53.71 18.781,53.595C18.434,53.479 18.125,53.231 17.785,53.1C17.446,52.969 17.098,52.83 16.766,52.691C16.434,52.552 16.056,52.475 15.724,52.313C15.392,52.15 15.207,51.71 14.883,51.54C14.559,51.37 14.057,51.517 13.74,51.332C13.424,51.146 13.092,50.961 12.783,50.768C12.474,50.575 12.142,50.39 11.841,50.181C11.54,49.973 11.378,49.563 11.085,49.347C10.792,49.131 10.421,49 10.135,48.768C9.85,48.536 9.749,48.096 9.472,47.849C9.194,47.602 8.869,47.432 8.599,47.177C8.329,46.922 7.989,46.752 7.735,46.49C7.48,46.227 7.241,45.949 6.994,45.671C6.747,45.393 6.585,45.053 6.353,44.768C6.121,44.482 5.905,44.188 5.681,43.895C5.458,43.602 5.265,43.3 5.048,42.991C4.832,42.682 4.516,42.466 4.315,42.157C4.114,41.848 4.13,41.416 3.945,41.099C3.759,40.783 3.481,40.52 3.312,40.196C3.142,39.871 2.926,39.57 2.771,39.238C2.617,38.906 2.385,38.605 2.239,38.265C2.092,37.925 2.069,37.539 1.938,37.2C1.806,36.86 1.606,36.535 1.49,36.188C1.374,35.84 1.235,35.493 1.135,35.138C1.034,34.782 1.181,34.365 1.096,34.01C1.011,33.655 0.942,33.3 0.872,32.937C0.803,32.574 0.757,32.218 0.695,31.855C0.633,31.493 0.309,31.168 0.262,30.805C0.216,30.442 0.069,30.079 0.039,29.716C0.008,29.353 -0.023,28.975 -0.039,28.612C-0.054,28.249 0.131,27.871 0.131,27.5L0.17,27.508Z" />
11+
<path
12+
android:fillColor="#ffffff"
13+
android:pathData="M27.512,33.485V33.462C27.072,33.462 26.755,33.13 26.392,32.929C26.029,32.728 25.512,32.659 25.288,32.296C25.065,31.933 25.173,31.469 25.149,31.029C25.126,30.465 25.165,30.465 25.134,29.902C25.103,29.338 25.026,29.346 25.003,28.782C24.98,28.218 25.018,28.218 24.995,27.654C24.972,27.091 24.825,27.098 24.802,26.535C24.779,25.971 24.64,25.979 24.617,25.415C24.594,24.851 24.617,24.851 24.594,24.287C24.57,23.724 24.648,23.724 24.617,23.152C24.586,22.581 24.709,22.581 24.686,22.017C24.663,21.453 24.524,21.461 24.501,20.897C24.478,20.333 24.517,20.333 24.501,19.77C24.486,19.206 24.416,19.206 24.393,18.642C24.37,18.079 24.47,18.071 24.447,17.507C24.424,16.943 24.563,16.936 24.54,16.372C24.517,15.808 24.501,15.808 24.478,15.237C24.462,14.889 24.455,14.596 24.563,14.294C24.671,13.993 24.779,13.661 25.003,13.414C25.227,13.167 25.582,13.144 25.898,13.012C26.215,12.881 26.454,12.572 26.801,12.572C27.535,12.572 27.535,12.541 28.26,12.541C28.608,12.541 28.963,12.649 29.264,12.781C29.565,12.912 29.688,13.306 29.92,13.545C30.152,13.785 30.453,13.947 30.568,14.264C30.684,14.58 30.553,14.889 30.538,15.237C30.514,15.8 30.684,15.808 30.653,16.372C30.622,16.936 30.707,16.936 30.684,17.499C30.661,18.063 30.522,18.055 30.499,18.619C30.476,19.183 30.7,19.191 30.677,19.754C30.653,20.318 30.707,20.318 30.677,20.882C30.646,21.445 30.576,21.438 30.553,22.002C30.53,22.565 30.213,22.55 30.182,23.114C30.152,23.677 30.167,23.677 30.136,24.241C30.105,24.805 30.36,24.82 30.329,25.384C30.298,25.948 30.128,25.94 30.105,26.504C30.082,27.067 30.159,27.067 30.128,27.631C30.097,28.195 30.044,28.195 30.02,28.759C29.997,29.323 30.206,29.338 30.175,29.902C30.144,30.465 29.835,30.45 29.804,31.021C29.781,31.462 29.881,31.902 29.665,32.249C29.449,32.597 29.001,32.728 28.631,32.937C28.26,33.145 27.944,33.477 27.504,33.477L27.512,33.485Z" />
14+
<path
15+
android:fillColor="#ffffff"
16+
android:pathData="M24.902,39.717C24.902,39.362 24.949,39.014 25.08,38.705C25.211,38.396 25.396,38.072 25.636,37.833C25.875,37.593 26.184,37.408 26.508,37.277C26.832,37.146 27.156,37.053 27.519,37.053C27.882,37.053 28.222,37.13 28.538,37.261C28.855,37.393 29.109,37.64 29.356,37.879C29.604,38.118 29.858,38.366 29.989,38.69C30.121,39.014 30.128,39.354 30.128,39.717C30.128,40.08 30.051,40.404 29.92,40.713C29.789,41.022 29.611,41.331 29.372,41.57C29.133,41.81 28.839,41.995 28.515,42.126C28.191,42.258 27.874,42.358 27.519,42.358C27.164,42.358 26.801,42.32 26.493,42.188C26.184,42.057 25.875,41.848 25.628,41.601C25.381,41.354 25.196,41.053 25.065,40.729C24.933,40.404 24.902,40.072 24.902,39.709V39.717Z" />
17+
</group>
18+
</vector>

0 commit comments

Comments
 (0)