-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Feature/#918] fortune 추가 구현 #924
Changes from all commits
f1c9e71
19f7420
8113939
e027982
56f0ed6
80d7f87
48712fe
9dcc56a
5516adc
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,6 +32,7 @@ import androidx.activity.viewModels | |
import androidx.appcompat.app.AppCompatActivity | ||
import androidx.compose.foundation.background | ||
import androidx.compose.foundation.layout.Arrangement | ||
import androidx.compose.foundation.layout.Box | ||
import androidx.compose.foundation.layout.Column | ||
import androidx.compose.foundation.layout.Spacer | ||
import androidx.compose.foundation.layout.fillMaxSize | ||
|
@@ -49,151 +50,201 @@ import androidx.compose.material3.HorizontalDivider | |
import androidx.compose.material3.Icon | ||
import androidx.compose.material3.IconButton | ||
import androidx.compose.material3.Scaffold | ||
import androidx.compose.material3.SnackbarHost | ||
import androidx.compose.material3.SnackbarHostState | ||
import androidx.compose.material3.Text | ||
import androidx.compose.material3.TopAppBarDefaults | ||
import androidx.compose.runtime.getValue | ||
import androidx.compose.runtime.remember | ||
import androidx.compose.runtime.rememberCoroutineScope | ||
import androidx.compose.ui.Modifier | ||
import androidx.compose.ui.draw.clip | ||
import androidx.compose.ui.platform.LocalContext | ||
import androidx.compose.ui.unit.dp | ||
import androidx.lifecycle.compose.collectAsStateWithLifecycle | ||
import dagger.hilt.android.AndroidEntryPoint | ||
import dagger.hilt.android.EntryPointAccessors | ||
import kotlinx.coroutines.launch | ||
import org.sopt.official.common.context.appContext | ||
import org.sopt.official.common.navigator.HOME_FORTUNE | ||
import org.sopt.official.common.navigator.NavigatorEntryPoint | ||
import org.sopt.official.designsystem.SoptTheme | ||
import org.sopt.official.feature.notification.detail.component.ErrorSnackBar | ||
import java.time.LocalDate | ||
|
||
private val navigator by lazy { | ||
EntryPointAccessors.fromApplication( | ||
appContext, | ||
NavigatorEntryPoint::class.java | ||
).navigatorProvider() | ||
EntryPointAccessors.fromApplication( | ||
appContext, | ||
NavigatorEntryPoint::class.java | ||
).navigatorProvider() | ||
} | ||
|
||
@AndroidEntryPoint | ||
class NotificationDetailActivity : AppCompatActivity() { | ||
private val viewModel by viewModels<NotificationDetailViewModel>() | ||
private val viewModel by viewModels<NotificationDetailViewModel>() | ||
|
||
@OptIn(ExperimentalMaterial3Api::class) | ||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
setContent { | ||
val notification by viewModel.notificationDetail.collectAsStateWithLifecycle() | ||
val context = LocalContext.current | ||
SoptTheme { | ||
Scaffold(modifier = Modifier | ||
.fillMaxSize() | ||
.background(SoptTheme.colors.background), | ||
containerColor = SoptTheme.colors.background, | ||
topBar = { | ||
CenterAlignedTopAppBar( | ||
title = { | ||
Text( | ||
text = "알림", | ||
style = SoptTheme.typography.body16M | ||
) | ||
}, | ||
navigationIcon = { | ||
IconButton(onClick = { onBackPressedDispatcher.onBackPressed() }) { | ||
Icon( | ||
Icons.AutoMirrored.Filled.ArrowBack, | ||
contentDescription = null, | ||
tint = SoptTheme.colors.onBackground | ||
) | ||
} | ||
}, | ||
colors = TopAppBarDefaults.topAppBarColors( | ||
containerColor = SoptTheme.colors.background, | ||
titleContentColor = SoptTheme.colors.onBackground, | ||
navigationIconContentColor = SoptTheme.colors.onBackground | ||
) | ||
) | ||
}) { innerPadding -> | ||
Column( | ||
modifier = Modifier | ||
.fillMaxSize() | ||
.background(SoptTheme.colors.background) | ||
.padding(innerPadding) | ||
.padding(top = 20.dp) | ||
.padding(horizontal = 20.dp), | ||
verticalArrangement = Arrangement.SpaceBetween | ||
) { | ||
Column( | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.clip(RoundedCornerShape(10.dp)) | ||
.background(SoptTheme.colors.onSurface800) | ||
.padding( | ||
vertical = 24.dp, | ||
horizontal = 12.dp | ||
) | ||
) { | ||
Text( | ||
notification?.title.orEmpty(), | ||
style = SoptTheme.typography.heading18B, | ||
color = SoptTheme.colors.onSurface10 | ||
) | ||
Spacer(modifier = Modifier.padding(14.dp)) | ||
HorizontalDivider(color = SoptTheme.colors.onSurface400) | ||
Text( | ||
notification?.content.orEmpty(), | ||
style = SoptTheme.typography.body16M, | ||
color = SoptTheme.colors.onSurface10, | ||
modifier = Modifier.padding(top = 24.dp) | ||
) | ||
} | ||
if (!notification?.deepLink.isNullOrBlank() || !notification?.webLink.isNullOrBlank()) { | ||
Column { | ||
Button( | ||
onClick = { | ||
context.startActivity( | ||
navigator.getSchemeActivityIntent( | ||
notificationId = notification?.notificationId.orEmpty(), | ||
link = notification?.webLink ?: notification?.deepLink ?: "" | ||
) | ||
@OptIn(ExperimentalMaterial3Api::class) | ||
override fun onCreate(savedInstanceState: Bundle?) { | ||
super.onCreate(savedInstanceState) | ||
setContent { | ||
val notification by viewModel.notificationDetail.collectAsStateWithLifecycle() | ||
val context = LocalContext.current | ||
|
||
val snackBarHostState = remember { SnackbarHostState() } | ||
val coroutineScope = rememberCoroutineScope() | ||
val onShowErrorSnackBar: (String?) -> Unit = { text -> | ||
coroutineScope.launch { | ||
snackBarHostState.currentSnackbarData?.dismiss() | ||
|
||
snackBarHostState.showSnackbar( | ||
message = text ?: "오류가 발생했어요. 다시 시도해주세요.", | ||
) | ||
}, | ||
colors = ButtonDefaults.buttonColors( | ||
containerColor = SoptTheme.colors.primary, | ||
contentColor = SoptTheme.colors.onPrimary | ||
), | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.height(56.dp), | ||
shape = RoundedCornerShape(10.dp) | ||
) { | ||
Text( | ||
text = "바로가기 >", | ||
style = SoptTheme.typography.body16M | ||
) | ||
} | ||
Spacer(modifier = Modifier.height(14.dp)) | ||
} | ||
} | ||
|
||
SoptTheme { | ||
Scaffold( | ||
modifier = Modifier | ||
.fillMaxSize() | ||
.background(SoptTheme.colors.background), | ||
containerColor = SoptTheme.colors.background, | ||
) { innerPadding -> | ||
Box { | ||
Column( | ||
modifier = Modifier | ||
.fillMaxSize() | ||
.padding(innerPadding) | ||
) { | ||
CenterAlignedTopAppBar( | ||
title = { | ||
Text( | ||
text = "알림", | ||
style = SoptTheme.typography.body16M | ||
) | ||
}, | ||
navigationIcon = { | ||
IconButton(onClick = { onBackPressedDispatcher.onBackPressed() }) { | ||
Icon( | ||
imageVector = Icons.AutoMirrored.Filled.ArrowBack, | ||
contentDescription = null, | ||
tint = SoptTheme.colors.onBackground | ||
) | ||
} | ||
}, | ||
colors = TopAppBarDefaults.topAppBarColors( | ||
containerColor = SoptTheme.colors.background, | ||
titleContentColor = SoptTheme.colors.onBackground, | ||
navigationIconContentColor = SoptTheme.colors.onBackground | ||
) | ||
) | ||
Column( | ||
modifier = Modifier | ||
.fillMaxSize() | ||
.background(SoptTheme.colors.background) | ||
.padding(top = 20.dp) | ||
.padding(horizontal = 20.dp), | ||
verticalArrangement = Arrangement.SpaceBetween | ||
) { | ||
Column( | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.clip(RoundedCornerShape(10.dp)) | ||
.background(SoptTheme.colors.onSurface800) | ||
.padding( | ||
vertical = 24.dp, | ||
horizontal = 12.dp | ||
) | ||
) { | ||
Text( | ||
text = notification?.title.orEmpty(), | ||
style = SoptTheme.typography.heading18B, | ||
color = SoptTheme.colors.onSurface10 | ||
) | ||
Spacer(modifier = Modifier.padding(14.dp)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. spacer는 보통 height나 width를 이용하는데 padding이랑 차이가 딱히 없겠죠? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 이것도 제가 짠건 아니긴 한데 ㅋㅋㅋㅋㅋㅋ 그저 가로로도 14만큼 할당돼서 정사각형 모양 패딩이 돼서 바로 옆에 뭐가 하나 더 붙어있다면 차이가 생길수는 있을거 같긴 하네요 |
||
HorizontalDivider(color = SoptTheme.colors.onSurface400) | ||
Text( | ||
text = notification?.content.orEmpty(), | ||
style = SoptTheme.typography.body16M, | ||
color = SoptTheme.colors.onSurface10, | ||
modifier = Modifier.padding(top = 24.dp) | ||
) | ||
} | ||
if (isValidLinks(deepLink = notification?.deepLink, webLink = notification?.webLink)) { | ||
Column { | ||
Button( | ||
onClick = { | ||
val link = notification?.webLink ?: notification?.deepLink | ||
|
||
when { | ||
link == HOME_FORTUNE && !isToday(notification?.createdAt?.split("T")?.get(0)) -> { | ||
onShowErrorSnackBar("앗, 오늘의 솝마디만 볼 수 있어요.") | ||
} | ||
|
||
else -> { | ||
context.startActivity( | ||
navigator.getSchemeActivityIntent( | ||
notificationId = notification?.notificationId.orEmpty(), | ||
link = link.orEmpty() | ||
) | ||
) | ||
} | ||
} | ||
}, | ||
colors = ButtonDefaults.buttonColors( | ||
containerColor = SoptTheme.colors.primary, | ||
contentColor = SoptTheme.colors.onPrimary | ||
), | ||
modifier = Modifier | ||
.fillMaxWidth() | ||
.height(56.dp), | ||
shape = RoundedCornerShape(10.dp) | ||
) { | ||
Text( | ||
text = "바로가기 >", | ||
style = SoptTheme.typography.body16M | ||
) | ||
} | ||
Spacer(modifier = Modifier.height(14.dp)) | ||
} | ||
} | ||
} | ||
} | ||
|
||
SnackbarHost( | ||
hostState = snackBarHostState, | ||
modifier = Modifier | ||
.padding(top = 16.dp) | ||
) { | ||
ErrorSnackBar(message = it.visuals.message) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
override fun onNewIntent(intent: Intent) { | ||
super.onNewIntent(intent) | ||
val notificationId = intent.getStringExtra("notificationId").orEmpty() | ||
viewModel.getNotificationDetail(notificationId) | ||
} | ||
private fun isValidLinks(deepLink: String?, webLink: String?): Boolean = | ||
!deepLink.isNullOrBlank() || !webLink.isNullOrBlank() | ||
|
||
private fun isToday(date: String?): Boolean = LocalDate.now().toString() == date | ||
|
||
companion object { | ||
@JvmStatic | ||
fun getIntent( | ||
context: Context, | ||
notificationId: String | ||
) = Intent( | ||
context, | ||
NotificationDetailActivity::class.java | ||
).putExtra( | ||
"notificationId", | ||
notificationId | ||
) | ||
} | ||
override fun onNewIntent(intent: Intent) { | ||
super.onNewIntent(intent) | ||
val notificationId = intent.getStringExtra("notificationId").orEmpty() | ||
viewModel.getNotificationDetail(notificationId) | ||
} | ||
|
||
companion object { | ||
@JvmStatic | ||
fun getIntent( | ||
context: Context, | ||
notificationId: String, | ||
) = Intent( | ||
context, | ||
NotificationDetailActivity::class.java | ||
).putExtra( | ||
"notificationId", | ||
notificationId | ||
) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이거 궁금했는데 background하나로 안쓰고 clip으로 따로 지정하는 이유가 있나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 Activity는 현우형이 짠 뷰라...
근데 저도 저렇게 하긴 합니다. 그래서 제 의견을 말씀드리면
백그라운드에 모양을 지정하게 되면 해당 컴포넌트는 각진 상태로 남아있되, 배경색만 해당 모양으로 됩니다.
그래서 해당 컴포넌트 자체를 깎기 위해서는 따로 clip을 해줘야 해용