Skip to content

Commit 766350e

Browse files
authored
[MERGE] #352 -> develop
[FEAT/#352] ๋งˆ์ดํŽ˜์ด์ง€ ๋ทฐ / UI ๊ตฌํ˜„, ์•Œ๋ฆผ ๊ถŒํ•œ ์„ค์ • ๊ตฌํ˜„
2 parents eb82547 + 5c07ac5 commit 766350e

45 files changed

Lines changed: 795 additions & 365 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

โ€Žapp/build.gradle.ktsโ€Ž

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ dependencies {
8585
implementation(projects.data.intern)
8686
implementation(projects.data.mypage)
8787
implementation(projects.data.scrap)
88-
implementation(projects.data.token)
88+
implementation(projects.data.user)
8989
implementation(projects.data.tokenreissue)
9090
implementation(projects.data.search)
9191
implementation(projects.data.update)
@@ -100,7 +100,4 @@ dependencies {
100100
implementation(libs.timber)
101101
implementation(libs.kakao.user)
102102
implementation(libs.kotlinx.serialization.json)
103-
implementation(platform(libs.firebase.bom))
104-
implementation(libs.firebase.analytics)
105-
implementation(libs.firebase.messaging)
106103
}
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
package com.terning.core.designsystem.component.dialog
2+
3+
import androidx.compose.foundation.background
4+
import androidx.compose.foundation.interaction.MutableInteractionSource
5+
import androidx.compose.foundation.interaction.collectIsPressedAsState
6+
import androidx.compose.foundation.layout.Box
7+
import androidx.compose.foundation.layout.Column
8+
import androidx.compose.foundation.layout.PaddingValues
9+
import androidx.compose.foundation.layout.defaultMinSize
10+
import androidx.compose.foundation.layout.height
11+
import androidx.compose.foundation.layout.padding
12+
import androidx.compose.foundation.layout.width
13+
import androidx.compose.foundation.layout.wrapContentWidth
14+
import androidx.compose.foundation.shape.RoundedCornerShape
15+
import androidx.compose.material.ripple.LocalRippleTheme
16+
import androidx.compose.material3.Button
17+
import androidx.compose.material3.ButtonDefaults
18+
import androidx.compose.material3.Text
19+
import androidx.compose.runtime.Composable
20+
import androidx.compose.runtime.CompositionLocalProvider
21+
import androidx.compose.runtime.getValue
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.graphics.Color
28+
import androidx.compose.ui.layout.onGloballyPositioned
29+
import androidx.compose.ui.platform.LocalDensity
30+
import androidx.compose.ui.res.stringResource
31+
import androidx.compose.ui.text.style.TextAlign
32+
import androidx.compose.ui.text.style.TextOverflow
33+
import androidx.compose.ui.tooling.preview.Preview
34+
import androidx.compose.ui.unit.dp
35+
import androidx.compose.ui.unit.max
36+
import androidx.compose.ui.window.Dialog
37+
import androidx.compose.ui.window.DialogProperties
38+
import com.terning.core.designsystem.R
39+
import com.terning.core.designsystem.theme.Grey400
40+
import com.terning.core.designsystem.theme.Grey500
41+
import com.terning.core.designsystem.theme.TerningMain
42+
import com.terning.core.designsystem.theme.TerningMain2
43+
import com.terning.core.designsystem.theme.TerningTheme
44+
import com.terning.core.designsystem.theme.White
45+
import com.terning.core.designsystem.util.NoRippleTheme
46+
47+
private const val MIN_DIALOG_WIDTH = 300
48+
private const val MIN_TEXT_HEIGHT = 94
49+
50+
/**
51+
* ์•ฑ์—์„œ ๊ณต์ง€ํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ์ด ์žˆ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค์ด์–ผ๋กœ๊ทธ ์ž…๋‹ˆ๋‹ค.
52+
*
53+
* @param titleText ๋‹ค์ด์–ผ๋กœ๊ทธ์˜ ์ œ๋ชฉ์ž…๋‹ˆ๋‹ค.
54+
* @param bodyText ๋‹ค์ด์–ผ๋กœ๊ทธ์˜ ์ƒ์„ธ ๋‚ด์šฉ์ž…๋‹ˆ๋‹ค.
55+
* @param buttonContent ๋‹ค์ด์–ผ๋กœ๊ทธ์˜ ๋‚ด์šฉ์„ ๊ตฌ์„ฑํ•˜๋Š” ๋ฒ„ํŠผ ์ปดํฌ์ €๋ธ” ์ฝ˜ํ…์ธ ์ž…๋‹ˆ๋‹ค.
56+
*/
57+
@Composable
58+
fun TerningNoticeDialog(
59+
titleText: String,
60+
bodyText: String,
61+
buttonContent: @Composable (Modifier) -> Unit,
62+
) {
63+
val density = LocalDensity.current
64+
val shape = RoundedCornerShape(20.dp)
65+
var dialogSize by remember { mutableStateOf(0.dp) }
66+
67+
Dialog(
68+
onDismissRequest = { },
69+
properties = DialogProperties(
70+
dismissOnBackPress = false,
71+
dismissOnClickOutside = false,
72+
usePlatformDefaultWidth = false,
73+
)
74+
) {
75+
Column(
76+
horizontalAlignment = Alignment.CenterHorizontally,
77+
modifier = Modifier
78+
.padding(horizontal = 10.dp)
79+
.wrapContentWidth()
80+
.background(color = White, shape = shape)
81+
.padding(12.dp),
82+
) {
83+
Text(
84+
text = titleText,
85+
style = TerningTheme.typography.title2,
86+
color = Grey500,
87+
modifier = Modifier.padding(top = 20.dp)
88+
)
89+
90+
Box(
91+
contentAlignment = Alignment.Center,
92+
modifier = Modifier
93+
.defaultMinSize(
94+
minHeight = MIN_TEXT_HEIGHT.dp
95+
)
96+
.onGloballyPositioned {
97+
dialogSize = with(density) {
98+
max(it.size.width.toDp(), MIN_DIALOG_WIDTH.dp)
99+
}
100+
}
101+
.padding(horizontal = 16.dp),
102+
) {
103+
Text(
104+
text = bodyText,
105+
style = TerningTheme.typography.body4.copy(
106+
textAlign = TextAlign.Center,
107+
),
108+
maxLines = 3,
109+
overflow = TextOverflow.Clip,
110+
color = Grey400,
111+
)
112+
}
113+
114+
buttonContent(Modifier.width(dialogSize))
115+
}
116+
}
117+
}
118+
119+
/**
120+
* ๊ณต์ง€ ๋‹ค์ด์–ผ๋กœ๊ทธ์— ๋“ค์–ด๊ฐ€๋Š” ๋ฒ„ํŠผ์ž…๋‹ˆ๋‹ค.
121+
*
122+
* @param text ๋ฒ„ํŠผ์˜ ํ…์ŠคํŠธ์ž…๋‹ˆ๋‹ค.
123+
* @param contentColor ๋ฒ„ํŠผ์˜ ๋ฐฐ๊ฒฝ ์ƒ‰์ƒ์ž…๋‹ˆ๋‹ค.
124+
* @param containerColor ๋ฒ„ํŠผ์˜ ํ…์ŠคํŠธ ์ƒ‰์ƒ์ž…๋‹ˆ๋‹ค.
125+
* @param pressedContainerColor ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅธ ์ƒํƒœ์ผ ๋•Œ์˜ ๋ฒ„ํŠผ์˜ ๋ฐฐ๊ฒฝ ์ƒ‰์ƒ์ž…๋‹ˆ๋‹ค.
126+
* @param onClick ๋ฒ„ํŠผ์„ ํด๋ฆญํ–ˆ์„ ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
127+
* @param modifier Modifier ์ˆ˜์ •์ž์ž…๋‹ˆ๋‹ค.
128+
*/
129+
@Composable
130+
fun NoticeDialogButton(
131+
text: String,
132+
contentColor: Color,
133+
containerColor: Color,
134+
pressedContainerColor: Color,
135+
onClick: () -> Unit,
136+
modifier: Modifier = Modifier,
137+
) {
138+
val interactionSource = remember { MutableInteractionSource() }
139+
val isPressed by interactionSource.collectIsPressedAsState()
140+
val backgroundColor = if (isPressed) pressedContainerColor else containerColor
141+
val shape = RoundedCornerShape(5.dp)
142+
143+
CompositionLocalProvider(LocalRippleTheme provides NoRippleTheme) {
144+
Button(
145+
contentPadding = PaddingValues(vertical = 12.dp),
146+
modifier = modifier
147+
.height(40.dp),
148+
interactionSource = interactionSource,
149+
enabled = true,
150+
colors = ButtonDefaults.buttonColors(
151+
containerColor = backgroundColor,
152+
contentColor = contentColor,
153+
),
154+
shape = shape,
155+
onClick = onClick
156+
) {
157+
Text(
158+
text = text,
159+
style = TerningTheme.typography.button3,
160+
)
161+
}
162+
}
163+
}
164+
165+
@Preview(showBackground = true)
166+
@Composable
167+
private fun TerningNoticeDialogPreview() {
168+
TerningNoticeDialog(
169+
titleText = "titleText",
170+
bodyText = "bodyText",
171+
) {
172+
NoticeDialogButton(
173+
text = stringResource(R.string.button_preview),
174+
contentColor = White,
175+
pressedContainerColor = TerningMain2,
176+
containerColor = TerningMain,
177+
onClick = { },
178+
modifier = Modifier,
179+
)
180+
}
181+
}

โ€Žcore/firebase/build.gradle.ktsโ€Ž

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ dependencies {
1313
implementation(projects.core.navigator)
1414

1515
// domain
16-
implementation(projects.domain.token)
16+
implementation(projects.domain.user)
1717

1818
// timber
1919
implementation(libs.timber)

โ€Žcore/firebase/src/main/java/com/terning/core/firebase/messageservice/TerningMessagingService.ktโ€Ž

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import androidx.core.net.toUri
1111
import com.google.firebase.messaging.FirebaseMessagingService
1212
import com.google.firebase.messaging.RemoteMessage
1313
import com.terning.core.firebase.R
14-
import com.terning.domain.token.repository.TokenRepository
14+
import com.terning.domain.user.repository.UserRepository
1515
import com.terning.navigator.NavigatorProvider
1616
import dagger.hilt.android.AndroidEntryPoint
1717
import timber.log.Timber
@@ -22,7 +22,7 @@ import javax.inject.Inject
2222
class TerningMessagingService : FirebaseMessagingService() {
2323

2424
@Inject
25-
lateinit var tokenRepository: TokenRepository
25+
lateinit var userRepository: UserRepository
2626

2727
@Inject
2828
lateinit var navigatorProvider: NavigatorProvider
@@ -36,28 +36,37 @@ class TerningMessagingService : FirebaseMessagingService() {
3636
override fun handleIntent(intent: Intent?) {
3737
super.handleIntent(intent)
3838

39-
if (intent?.getStringExtra(TITLE)?.isEmpty() == true) return
39+
if (intent?.getStringExtra(TITLE)?.isEmpty() == true
40+
|| !userRepository.getAlarmAvailable()
41+
) return
4042

4143
val title = intent?.getStringExtra(TITLE).orEmpty()
4244
val body = intent?.getStringExtra(BODY).orEmpty()
4345
val type = intent?.getStringExtra(TYPE).orEmpty()
4446

45-
sendNotification(title = title, body = body, type = type)
47+
sendNotification(
48+
title = title,
49+
body = body,
50+
type = type
51+
)
4652
}
4753

4854
override fun onMessageReceived(message: RemoteMessage) {
4955
super.onMessageReceived(message)
5056

51-
if (message.data.isEmpty())
52-
// TODO: ์กฐ๊ฑด ์ถ”๊ฐ€ by ์ด์œ ๋นˆ -> || !terningDataStore.alarmAvailable
53-
// TODO: #352๋ฒˆ ๋ธŒ๋ Œ์น˜์—์„œ ๊ด€๋ จ ์ฝ”๋“œ ์ˆ˜์ •ํ•˜๊ธฐ
54-
return
57+
if (message.data.isEmpty()
58+
|| !userRepository.getAlarmAvailable()
59+
) return
5560

5661
val title = message.data[TITLE].orEmpty()
5762
val body = message.data[BODY].orEmpty()
5863
val type = message.data[TYPE].orEmpty()
5964

60-
sendNotification(title = title, body = body, type = type)
65+
sendNotification(
66+
title = title,
67+
body = body,
68+
type = type
69+
)
6170
}
6271

6372
private fun sendNotification(title: String, body: String, type: String) {

โ€Žcore/local/src/main/java/com/terning/core/local/TerningDataStore.ktโ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@ interface TerningDataStore {
55
var refreshToken: String
66
var fcmToken: String
77
var userId: Long
8+
var alarmAvailable: Boolean
9+
var hasRequestedPermission: Boolean
810
fun clearInfo()
911
}

โ€Žcore/local/src/main/java/com/terning/core/local/TerningDataStoreImpl.ktโ€Ž

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,24 @@ class TerningDataStoreImpl @Inject constructor(
2323
get() = dataStore.getLong(USER_ID, 0L)
2424
set(value) = dataStore.edit { putLong(USER_ID, value) }
2525

26+
override var alarmAvailable: Boolean
27+
get() = dataStore.getBoolean(ALARM, false)
28+
set(value) = dataStore.edit { putBoolean(ALARM, value) }
29+
30+
override var hasRequestedPermission: Boolean
31+
get() = dataStore.getBoolean(PERMISSION_REQUESTED, false)
32+
set(value) = dataStore.edit { putBoolean(PERMISSION_REQUESTED, value) }
33+
2634
override fun clearInfo() {
27-
dataStore.edit().clear().commit()
35+
dataStore.edit().clear().apply()
2836
}
2937

3038
companion object {
3139
private const val ACCESS_TOKEN = "ACCESS_TOKEN"
3240
private const val REFRESH_TOKEN = "REFRESH_TOKEN"
3341
private const val FCM_TOKEN = "FCM_TOKEN"
3442
private const val USER_ID = "USER_ID"
43+
private const val ALARM = "ALARM"
44+
private const val PERMISSION_REQUESTED = "PERMISSION_REQUESTED"
3545
}
3646
}
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
}
66

77
android {
8-
setNamespace("data.token")
8+
setNamespace("data.user")
99
}
1010

1111
dependencies {
@@ -14,5 +14,5 @@ dependencies {
1414
implementation(projects.core.firebase)
1515

1616
//domain
17-
implementation(projects.domain.token)
17+
implementation(projects.domain.user)
1818
}
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
package com.terning.data.token.di
1+
package com.terning.data.user.di
22

3-
import com.terning.data.token.repositoryimpl.TokenRepositoryImpl
4-
import com.terning.domain.token.repository.TokenRepository
3+
import com.terning.data.user.repositoryimpl.UserRepositoryImpl
4+
import com.terning.domain.user.repository.UserRepository
55
import dagger.Binds
66
import dagger.Module
77
import dagger.hilt.InstallIn
@@ -13,5 +13,5 @@ import javax.inject.Singleton
1313
abstract class RepositoryModule {
1414
@Binds
1515
@Singleton
16-
abstract fun bindTokenRepository(tokenRepositoryImpl: TokenRepositoryImpl): TokenRepository
16+
abstract fun bindUserRepository(userRepositoryImpl: UserRepositoryImpl): UserRepository
1717
}

0 commit comments

Comments
ย (0)