Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature/#918] fortune 추가 구현 #924

Merged
merged 9 commits into from
Oct 20, 2024
2,694 changes: 2,685 additions & 9 deletions app/src/release/generated/baselineProfiles/baseline-prof.txt

Large diffs are not rendered by default.

2,694 changes: 2,685 additions & 9 deletions app/src/release/generated/baselineProfiles/startup-prof.txt

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ enum class DeepLinkType(
override fun getIntent(context: Context, userStatus: UserStatus, deepLink: String) =
userStatus.setIntent(navigator.getPokeNotificationActivityIntent(userStatus.name))
},
FORTUNE("home/fortune") {
FORTUNE(HOME_FORTUNE) {
override fun getIntent(context: Context, userStatus: UserStatus, deepLink: String) =
userStatus.setIntent(navigator.getFortuneActivityIntent())
},
Expand Down Expand Up @@ -115,3 +115,5 @@ enum class DeepLinkType(
}
}
}

const val HOME_FORTUNE = "home/fortune"
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,7 @@ class FortuneActivity : AppCompatActivity() {
SoptTheme {
CompositionLocalProvider(LocalAmplitudeTracker provides amplitudeTracker) {
FoundationScreen(
onClickLeadingIcon = {
startActivity(navigator.getNotificationActivityIntent())
},
onClickLeadingIcon = ::finish,
navigateToHome = {
startActivity(navigator.getAuthActivityIntent())
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ private fun HomeScreen(
Spacer(modifier = Modifier.weight(1f))

FortuneButton(
title = "오늘의 운세 보러 가기",
title = "오늘의 운세 확인하기",
onClick = onFortuneDetailClick,
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Comment on lines +151 to +152
Copy link
Contributor

Choose a reason for hiding this comment

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

이거 궁금했는데 background하나로 안쓰고 clip으로 따로 지정하는 이유가 있나요?

Copy link
Member Author

Choose a reason for hiding this comment

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

이 Activity는 현우형이 짠 뷰라...
근데 저도 저렇게 하긴 합니다. 그래서 제 의견을 말씀드리면
백그라운드에 모양을 지정하게 되면 해당 컴포넌트는 각진 상태로 남아있되, 배경색만 해당 모양으로 됩니다.
그래서 해당 컴포넌트 자체를 깎기 위해서는 따로 clip을 해줘야 해용

.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))
Copy link
Contributor

Choose a reason for hiding this comment

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

spacer는 보통 height나 width를 이용하는데 padding이랑 차이가 딱히 없겠죠?

Copy link
Member Author

Choose a reason for hiding this comment

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

이것도 제가 짠건 아니긴 한데 ㅋㅋㅋㅋㅋㅋ
이 뷰에선 문제 없어보여요!

그저 가로로도 14만큼 할당돼서 정사각형 모양 패딩이 돼서 바로 옆에 뭐가 하나 더 붙어있다면 차이가 생길수는 있을거 같긴 하네요
물론 저도 height랑 width를 이용하긴 합니당

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
)
}
}
Loading