diff --git a/.kotlin/sessions/kotlin-compiler-9280088279672338011.salive b/.kotlin/sessions/kotlin-compiler-9280088279672338011.salive
new file mode 100644
index 00000000..e69de29b
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index db44d97f..6727d01a 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1,5 +1,5 @@
- Dplay
+ 디플레이
디플레이
오늘의 질문이 도착했어요
\ No newline at end of file
diff --git a/core/data/src/main/java/com/example/data/datasource/remote/AuthRemoteDataSource.kt b/core/data/src/main/java/com/example/data/datasource/remote/AuthRemoteDataSource.kt
index dc18566a..c6f3c46c 100644
--- a/core/data/src/main/java/com/example/data/datasource/remote/AuthRemoteDataSource.kt
+++ b/core/data/src/main/java/com/example/data/datasource/remote/AuthRemoteDataSource.kt
@@ -126,7 +126,7 @@ class AuthRemoteDataSource
suspend fun reissue(refreshToken: String): TokenResponse {
try {
- val response = authService.reissue(refreshToken = refreshToken)
+ val response = authService.reissue(refreshToken = "Bearer $refreshToken")
return response.data ?: throw Exception("Data is null")
} catch (e: Exception) {
throw e
diff --git a/core/data/src/main/java/com/example/data/datasource/remote/QuestionPostsPagingSource.kt b/core/data/src/main/java/com/example/data/datasource/remote/QuestionPostsPagingSource.kt
index 428ef20a..69b95655 100644
--- a/core/data/src/main/java/com/example/data/datasource/remote/QuestionPostsPagingSource.kt
+++ b/core/data/src/main/java/com/example/data/datasource/remote/QuestionPostsPagingSource.kt
@@ -9,6 +9,7 @@ class QuestionPostsPagingSource(
private val postService: PostService,
private val questionId: Long,
private val onTotalCountFetched: (Int) -> Unit,
+ private val onLockedFetched: (Boolean) -> Unit,
) : PagingSource() {
override fun getRefreshKey(state: PagingState): String? = null
@@ -26,6 +27,7 @@ class QuestionPostsPagingSource(
val data = response.data ?: throw Exception("data is null")
if (params.key == null) {
onTotalCountFetched(data.totalCount)
+ onLockedFetched(data.locked)
}
val posts = data.items
val nextCursor = data.nextCursor
diff --git a/core/data/src/main/java/com/example/data/mapper/todomain/TodayPosteResponseMapper.kt b/core/data/src/main/java/com/example/data/mapper/todomain/TodayPosteResponseMapper.kt
index 19759aa9..2d196ffc 100644
--- a/core/data/src/main/java/com/example/data/mapper/todomain/TodayPosteResponseMapper.kt
+++ b/core/data/src/main/java/com/example/data/mapper/todomain/TodayPosteResponseMapper.kt
@@ -3,7 +3,7 @@ package com.example.data.mapper.todomain
import com.example.data.model.response.TodayPostItemResponse
import com.example.data.model.response.TodayPostTrackResponse
import com.example.data.model.response.TodayPostsResponse
-import com.example.domain.model.BADGE
+import com.example.domain.model.Badge
import com.example.domain.model.DailyQuestion
import com.example.domain.model.FeedItem
import com.example.domain.model.HomeScreenData
@@ -28,7 +28,7 @@ fun TodayPostItemResponse.toDomain(): FeedItem =
postId = postId,
isScrapped = isScrapped,
content = content,
- badge = badge?.let { BADGE.valueOf(it) },
+ badge = badge?.let { Badge.valueOf(it) },
track = track.toDomain(),
writer = user.toDomain(),
like = like.toDomain(),
diff --git a/core/data/src/main/java/com/example/data/mapper/todomain/UserResponseMapper.kt b/core/data/src/main/java/com/example/data/mapper/todomain/UserResponseMapper.kt
index 85c7c5b5..00eba51a 100644
--- a/core/data/src/main/java/com/example/data/mapper/todomain/UserResponseMapper.kt
+++ b/core/data/src/main/java/com/example/data/mapper/todomain/UserResponseMapper.kt
@@ -8,4 +8,5 @@ fun UserResponse.toDomain(): Writer =
userId = this.userId,
nickname = this.nickname,
profileImg = this.profileImg,
+ isAdmin = this.isAdmin,
)
diff --git a/core/data/src/main/java/com/example/data/model/response/QuestionPostsResponse.kt b/core/data/src/main/java/com/example/data/model/response/QuestionPostsResponse.kt
index 22cfbeaa..8049f968 100644
--- a/core/data/src/main/java/com/example/data/model/response/QuestionPostsResponse.kt
+++ b/core/data/src/main/java/com/example/data/model/response/QuestionPostsResponse.kt
@@ -1,6 +1,6 @@
package com.example.data.model.response
-import com.example.domain.model.BADGE
+import com.example.domain.model.Badge
import com.example.domain.model.FeedItem
import com.example.domain.model.Like
import com.example.domain.model.Track
@@ -52,7 +52,7 @@ data class QuestionPostItemResponse(
postId = postId,
isScrapped = isScrapped,
content = content,
- badge = if (isEditorPick) BADGE.EDITOR else null,
+ badge = if (isEditorPick) Badge.EDITOR else null,
track =
Track(
trackId = track.trackId,
@@ -66,6 +66,7 @@ data class QuestionPostItemResponse(
userId = user.userId,
nickname = user.nickname,
profileImg = user.profileImg.orEmpty(),
+ isAdmin = user.isAdmin,
),
like =
Like(
diff --git a/core/data/src/main/java/com/example/data/model/response/UserResponse.kt b/core/data/src/main/java/com/example/data/model/response/UserResponse.kt
index dc4725ec..9ba74fbf 100644
--- a/core/data/src/main/java/com/example/data/model/response/UserResponse.kt
+++ b/core/data/src/main/java/com/example/data/model/response/UserResponse.kt
@@ -23,4 +23,6 @@ data class UserResponse(
val nickname: String,
@SerialName("profileImg")
val profileImg: String?,
+ @SerialName("isAdmin")
+ val isAdmin: Boolean,
)
diff --git a/core/data/src/main/java/com/example/data/repository/PostRepositoryImpl.kt b/core/data/src/main/java/com/example/data/repository/PostRepositoryImpl.kt
index 7049511e..ec56595c 100644
--- a/core/data/src/main/java/com/example/data/repository/PostRepositoryImpl.kt
+++ b/core/data/src/main/java/com/example/data/repository/PostRepositoryImpl.kt
@@ -88,6 +88,7 @@ class PostRepositoryImpl
override fun getPostsByQuestionId(
questionId: Long,
onTotalCountFetched: (Int) -> Unit,
+ onLockedFetched: (Boolean) -> Unit,
): Flow> =
Pager(
config =
@@ -101,6 +102,7 @@ class PostRepositoryImpl
postService = postService,
questionId = questionId,
onTotalCountFetched = onTotalCountFetched,
+ onLockedFetched = onLockedFetched,
)
},
).flow.map { pagingData ->
diff --git a/core/designsystem/src/main/java/com/example/designsystem/component/DPlayDayTopicItem.kt b/core/designsystem/src/main/java/com/example/designsystem/component/DPlayDayTopicItem.kt
index 758530d4..4e69b3e2 100644
--- a/core/designsystem/src/main/java/com/example/designsystem/component/DPlayDayTopicItem.kt
+++ b/core/designsystem/src/main/java/com/example/designsystem/component/DPlayDayTopicItem.kt
@@ -1,10 +1,15 @@
package com.example.designsystem.component
+import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.height
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.size
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
+import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
@@ -19,31 +24,45 @@ fun DPlayDayTopicItem(
onClick: () -> Unit,
modifier: Modifier = Modifier,
) {
- Row(modifier = modifier.fillMaxWidth().noRippleClickable(onClick = onClick)) {
- Text(
- text = dayText,
+ Row(
+ modifier =
+ modifier
+ .fillMaxWidth()
+ .noRippleClickable(onClick = onClick),
+ ) {
+ Box(
modifier =
Modifier
+ .size(50.dp)
.roundedBackgroundWithPadding(
backgroundColor = DPlayTheme.colors.gray600,
cornerRadius = 8.dp,
- padding = PaddingValues(horizontal = 16.5.dp, vertical = 16.dp),
),
- color = DPlayTheme.colors.gray100,
- style = DPlayTheme.typography.bodyBold14,
- )
- Text(
- text = topic,
+ contentAlignment = Alignment.Center,
+ ) {
+ Text(
+ text = dayText,
+ color = DPlayTheme.colors.gray100,
+ style = DPlayTheme.typography.bodyBold14,
+ )
+ }
+ Box(
modifier =
Modifier
+ .height(50.dp)
.weight(1f)
.roundedBackgroundWithPadding(
backgroundColor = DPlayTheme.colors.gray100,
cornerRadius = 8.dp,
- padding = PaddingValues(horizontal = 10.dp, vertical = 16.dp),
+ padding = PaddingValues(start = 10.dp),
),
- style = DPlayTheme.typography.bodySemi14,
- )
+ contentAlignment = Alignment.CenterStart,
+ ) {
+ Text(
+ text = topic,
+ style = DPlayTheme.typography.bodySemi14,
+ )
+ }
}
}
diff --git a/core/designsystem/src/main/java/com/example/designsystem/component/DPlayImageCheck.kt b/core/designsystem/src/main/java/com/example/designsystem/component/DPlayImageCheck.kt
index de5342a2..c726f15a 100644
--- a/core/designsystem/src/main/java/com/example/designsystem/component/DPlayImageCheck.kt
+++ b/core/designsystem/src/main/java/com/example/designsystem/component/DPlayImageCheck.kt
@@ -20,6 +20,7 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.stringResource
+import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage
@@ -62,11 +63,15 @@ fun DPlayImageCheck(
Spacer(modifier = Modifier.width(12.dp))
- Column {
+ Column(
+ modifier = Modifier.weight(1f),
+ ) {
Text(
text = musicName,
style = DPlayTheme.typography.bodySemi16,
color = DPlayTheme.colors.dplayBlack,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
)
Spacer(modifier = Modifier.height(4.dp))
@@ -75,11 +80,11 @@ fun DPlayImageCheck(
text = artistName,
style = DPlayTheme.typography.bodyMed14,
color = DPlayTheme.colors.gray400,
+ maxLines = 1,
+ overflow = TextOverflow.Ellipsis,
)
}
- Spacer(modifier = Modifier.weight(1f))
-
if (isChecked) {
DplayBaseIcon(
iconRes = R.drawable.ic_check_circle_darkgray_24,
diff --git a/core/designsystem/src/main/java/com/example/designsystem/component/DPlayLargeCover.kt b/core/designsystem/src/main/java/com/example/designsystem/component/DPlayLargeCover.kt
index b021ff60..dfd14ee9 100644
--- a/core/designsystem/src/main/java/com/example/designsystem/component/DPlayLargeCover.kt
+++ b/core/designsystem/src/main/java/com/example/designsystem/component/DPlayLargeCover.kt
@@ -39,6 +39,7 @@ import com.example.designsystem.util.noRippleClickable
@Composable
fun DPlayLargeCover(
isLikeChecked: Boolean,
+ isAdmin: Boolean,
likeCount: Int,
writerProfileImageUrl: String?,
writerNickname: String,
@@ -70,7 +71,12 @@ fun DPlayLargeCover(
}
}
- Box(modifier = modifier.fillMaxWidth().clip(textCoverShape)) {
+ Box(
+ modifier =
+ modifier
+ .fillMaxWidth()
+ .clip(textCoverShape),
+ ) {
Box(
modifier =
Modifier
@@ -141,7 +147,12 @@ fun DPlayLargeCover(
modifier = Modifier.noRippleClickable(onClick = onWriterProfileClick),
) {
AsyncImage(
- model = writerProfileImageUrl ?: R.drawable.base_profile_image,
+ model =
+ if (isAdmin) {
+ R.drawable.img_profile
+ } else {
+ writerProfileImageUrl ?: R.drawable.base_profile_image
+ },
contentDescription = null,
modifier =
Modifier
@@ -206,7 +217,7 @@ fun DPlayLargeCover(
.background(
color = color.dplayWhite,
shape = RoundedCornerShape(16.dp),
- ).padding(10.dp),
+ ).padding(6.dp),
onClick = onStreamClick,
)
}
@@ -250,6 +261,7 @@ private fun DPlayLockedLargeCoverPreview() {
onLikeClick = {},
onCoverClick = {},
onWriterProfileClick = {},
+ isAdmin = false,
)
}
}
@@ -270,6 +282,7 @@ private fun DPlayLargeCoverPreview() {
onCoverClick = {},
onWriterProfileClick = {},
isLocked = false,
+ isAdmin = false,
)
}
}
diff --git a/core/designsystem/src/main/java/com/example/designsystem/component/DPlayTooltip.kt b/core/designsystem/src/main/java/com/example/designsystem/component/DPlayTooltip.kt
index c17fce90..2f0a82bf 100644
--- a/core/designsystem/src/main/java/com/example/designsystem/component/DPlayTooltip.kt
+++ b/core/designsystem/src/main/java/com/example/designsystem/component/DPlayTooltip.kt
@@ -1,5 +1,6 @@
package com.example.designsystem.component
+import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
@@ -25,8 +26,9 @@ import com.example.designsystem.util.roundedBackgroundWithPadding
@Composable
fun DplayTooltip(
onCloseButtonClicked: () -> Unit,
- onTextButtonClicked: () -> Unit,
+ onTextButtonClicked: (() -> Unit)?,
modifier: Modifier = Modifier,
+ @StringRes textStringRes: Int = R.string.tooltip_default_description,
) {
Column(modifier = modifier) {
Box(
@@ -63,18 +65,20 @@ fun DplayTooltip(
Text(
style = DPlayTheme.typography.bodyMed14,
color = DPlayTheme.colors.dplayWhite,
- text = stringResource(R.string.tooltip_default_description),
+ text = stringResource(textStringRes),
)
DplayClickableIcon(
iconRes = R.drawable.ic_close_24,
onClick = onCloseButtonClicked,
)
}
- Spacer(modifier = Modifier.height(16.dp))
- DPlayUnderlineTextButton(
- onClick = onTextButtonClicked,
- text = stringResource(R.string.tooltip_learn_more),
- )
+ if (onTextButtonClicked != null) {
+ Spacer(modifier = Modifier.height(16.dp))
+ DPlayUnderlineTextButton(
+ onClick = onTextButtonClicked,
+ text = stringResource(R.string.tooltip_learn_more),
+ )
+ }
}
}
}
diff --git a/core/designsystem/src/main/java/com/example/designsystem/component/button/DplayGuidelineButton.kt b/core/designsystem/src/main/java/com/example/designsystem/component/button/DplayGuidelineButton.kt
index b4feb985..f76b1360 100644
--- a/core/designsystem/src/main/java/com/example/designsystem/component/button/DplayGuidelineButton.kt
+++ b/core/designsystem/src/main/java/com/example/designsystem/component/button/DplayGuidelineButton.kt
@@ -1,5 +1,6 @@
package com.example.designsystem.component.button
+import androidx.annotation.StringRes
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -24,6 +25,7 @@ import com.example.designsystem.theme.DPlayTheme
@Composable
fun DPlayGuidelineButton(
onClick: () -> Unit,
+ @StringRes textStringRes: Int,
modifier: Modifier = Modifier,
) {
DPlayButtonSlot(
@@ -47,7 +49,7 @@ fun DPlayGuidelineButton(
)
Text(
- text = stringResource(R.string.guideline_button_label),
+ text = stringResource(textStringRes),
style = DPlayTheme.typography.capMed12,
color = DPlayTheme.colors.gray400,
)
@@ -69,6 +71,7 @@ fun DPlayGuidelineButtonPreview() {
) {
DPlayGuidelineButton(
onClick = {},
+ textStringRes = R.string.guideline_button_label,
)
}
}
diff --git a/core/designsystem/src/main/res/drawable/img_key.png b/core/designsystem/src/main/res/drawable/img_key.png
index b4e34091..91a9ca0b 100644
Binary files a/core/designsystem/src/main/res/drawable/img_key.png and b/core/designsystem/src/main/res/drawable/img_key.png differ
diff --git a/core/domain/src/main/java/com/example/domain/model/FeedItem.kt b/core/domain/src/main/java/com/example/domain/model/FeedItem.kt
index b01a2d59..f702dfbf 100644
--- a/core/domain/src/main/java/com/example/domain/model/FeedItem.kt
+++ b/core/domain/src/main/java/com/example/domain/model/FeedItem.kt
@@ -5,13 +5,13 @@ data class FeedItem(
val postId: Long,
val isScrapped: Boolean,
val content: String,
- val badge: BADGE?,
+ val badge: Badge?,
val track: Track,
val writer: Writer,
val like: Like,
)
-enum class BADGE {
+enum class Badge {
EDITOR,
BEST,
NEW,
diff --git a/core/domain/src/main/java/com/example/domain/model/UserRelation.kt b/core/domain/src/main/java/com/example/domain/model/UserRelation.kt
index 7564ad27..53e050ce 100644
--- a/core/domain/src/main/java/com/example/domain/model/UserRelation.kt
+++ b/core/domain/src/main/java/com/example/domain/model/UserRelation.kt
@@ -2,6 +2,5 @@ package com.example.domain.model
enum class UserRelation {
ME,
- ADMIN,
OTHER;
}
\ No newline at end of file
diff --git a/core/domain/src/main/java/com/example/domain/model/Writer.kt b/core/domain/src/main/java/com/example/domain/model/Writer.kt
index 1bb7dcb5..054ac0a7 100644
--- a/core/domain/src/main/java/com/example/domain/model/Writer.kt
+++ b/core/domain/src/main/java/com/example/domain/model/Writer.kt
@@ -4,4 +4,5 @@ data class Writer(
val userId: Long,
val nickname: String,
val profileImg: String?,
+ val isAdmin: Boolean,
)
diff --git a/core/domain/src/main/java/com/example/domain/repository/PostRepository.kt b/core/domain/src/main/java/com/example/domain/repository/PostRepository.kt
index cc37996f..e5d1d7d7 100644
--- a/core/domain/src/main/java/com/example/domain/repository/PostRepository.kt
+++ b/core/domain/src/main/java/com/example/domain/repository/PostRepository.kt
@@ -41,5 +41,6 @@ interface PostRepository {
fun getPostsByQuestionId(
questionId: Long,
onTotalCountFetched: (Int) -> Unit,
+ onLockedFetched: (Boolean) -> Unit,
): Flow>
}
\ No newline at end of file
diff --git a/core/domain/src/main/java/com/example/domain/usecase/CheckUserRelationUseCase.kt b/core/domain/src/main/java/com/example/domain/usecase/CheckUserRelationUseCase.kt
index ceab1f44..e629bf89 100644
--- a/core/domain/src/main/java/com/example/domain/usecase/CheckUserRelationUseCase.kt
+++ b/core/domain/src/main/java/com/example/domain/usecase/CheckUserRelationUseCase.kt
@@ -11,13 +11,8 @@ class CheckUserRelationUseCase @Inject constructor(
suspend operator fun invoke(userId: Long): UserRelation {
val myId = userRepository.getUser().first()?.id
return when {
- userId == ADMIN_ID -> UserRelation.ADMIN
myId == userId -> UserRelation.ME
else -> UserRelation.OTHER
}
}
-
- companion object{
- const val ADMIN_ID = 1L
- }
}
\ No newline at end of file
diff --git a/core/navigation/src/main/java/com/example/navigation/Route.kt b/core/navigation/src/main/java/com/example/navigation/Route.kt
index e90ea58a..61e2cad4 100644
--- a/core/navigation/src/main/java/com/example/navigation/Route.kt
+++ b/core/navigation/src/main/java/com/example/navigation/Route.kt
@@ -3,7 +3,7 @@ package com.example.navigation
import androidx.annotation.DrawableRes
import androidx.navigation3.runtime.NavKey
import com.dplay.designsystem.R
-import com.example.domain.model.BADGE
+import com.example.domain.model.Badge
import com.example.ui.model.TrackState
import kotlinx.serialization.Serializable
@@ -71,7 +71,7 @@ data object Record : NavKey
@Serializable
data class Detail(
val postId: Long,
- val badge: BADGE? = null,
+ val badge: Badge? = null,
) : NavKey
@Serializable
diff --git a/feature/comment/src/main/java/com/example/comment/CommentScreen.kt b/feature/comment/src/main/java/com/example/comment/CommentScreen.kt
index 1ebacc78..ab484697 100644
--- a/feature/comment/src/main/java/com/example/comment/CommentScreen.kt
+++ b/feature/comment/src/main/java/com/example/comment/CommentScreen.kt
@@ -157,6 +157,7 @@ fun CommentScreen(
.onGloballyPositioned { coordinates ->
guideButtonHeightPx = coordinates.size.height
},
+ textStringRes = R.string.guideline_button_label,
)
if (state.isGuideVisible) {
diff --git a/feature/detail/src/main/java/com/example/detail/DetailContract.kt b/feature/detail/src/main/java/com/example/detail/DetailContract.kt
index 68cabeca..64fb6210 100644
--- a/feature/detail/src/main/java/com/example/detail/DetailContract.kt
+++ b/feature/detail/src/main/java/com/example/detail/DetailContract.kt
@@ -1,7 +1,7 @@
package com.example.detail
import com.example.designsystem.component.snackbar.type.SnackBarType
-import com.example.domain.model.BADGE
+import com.example.domain.model.Badge
import com.example.domain.model.Like
import com.example.domain.model.LoadingState
import com.example.domain.model.Track
@@ -14,6 +14,7 @@ class DetailContract {
val loadingState: LoadingState = LoadingState.LOADING,
val postId: Long = 0L,
val isScrapped: Boolean = false,
+ val initialIsScrapped: Boolean = false,
val content: String = "",
val isHost: Boolean = false,
val date: String = "",
@@ -30,21 +31,26 @@ class DetailContract {
userId = 0,
nickname = "",
profileImg = "",
+ isAdmin = false,
),
val like: Like =
Like(
isLiked = false,
count = 0,
),
- val badge: BADGE? = null,
+ val initialIsLiked: Boolean = false,
+ val badge: Badge? = null,
val bottomSheetVisible: Boolean = false,
val streamingTrackId: String? = null,
- ) : BaseContract.State
+ ) : BaseContract.State {
+ val homeRefreshRequired: Boolean
+ get() = isScrapped != initialIsScrapped || like.isLiked != initialIsLiked
+ }
sealed interface DetailIntent : BaseContract.Intent {
data class LoadData(
val postId: Long,
- val badge: BADGE? = null,
+ val badge: Badge? = null,
) : DetailIntent
data object OnBookmarkClick : DetailIntent
diff --git a/feature/detail/src/main/java/com/example/detail/DetailScreen.kt b/feature/detail/src/main/java/com/example/detail/DetailScreen.kt
index ca0e1805..96f76e48 100644
--- a/feature/detail/src/main/java/com/example/detail/DetailScreen.kt
+++ b/feature/detail/src/main/java/com/example/detail/DetailScreen.kt
@@ -1,5 +1,6 @@
package com.example.detail
+import androidx.activity.compose.BackHandler
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
@@ -24,8 +25,8 @@ import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
-import androidx.compose.ui.draw.blur
import androidx.compose.ui.draw.clip
+import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.tooling.preview.Preview
@@ -48,7 +49,7 @@ import com.example.designsystem.component.snackbar.LocalShowSnackBar
import com.example.designsystem.theme.DPlayTheme
import com.example.designsystem.util.noRippleClickable
import com.example.designsystem.util.roundedBackgroundWithPadding
-import com.example.domain.model.BADGE
+import com.example.domain.model.Badge
import com.example.domain.model.LoadingState
import com.example.navigation.MyPage
import com.example.navigation.Navigator
@@ -61,12 +62,16 @@ fun DetailRoute(
postId: Long,
navigator: Navigator,
viewModel: DetailViewModel = hiltViewModel(),
- badge: BADGE? = null,
+ badge: Badge? = null,
) {
val uiState by viewModel.uiState.collectAsStateWithLifecycle()
val showSnackBar = LocalShowSnackBar.current
val modalController = LocalModalController.current
+ BackHandler {
+ viewModel.handleIntent(DetailContract.DetailIntent.OnBackButtonClick)
+ }
+
LaunchedEffect(Unit) {
viewModel.handleIntent(DetailContract.DetailIntent.LoadData(postId = postId, badge = badge))
}
@@ -174,13 +179,8 @@ private fun DetailScreen(
.padding(horizontal = 16.dp)
Box {
- Box(modifier = Modifier.fillMaxSize()) {
- Box(
- modifier =
- Modifier.blur(
- radius = 20.dp,
- ),
- ) {
+ Box(modifier = Modifier.fillMaxSize().background(color = color.gray100)) {
+ Box {
AsyncImage(
model = state.track.coverImg,
contentDescription = null,
@@ -191,6 +191,23 @@ private fun DetailScreen(
.offset(y = (-80).dp),
contentScale = ContentScale.Crop,
)
+ Box(
+ modifier =
+ Modifier
+ .fillMaxWidth()
+ .aspectRatio(1f)
+ .offset(y = (-80).dp)
+ .background(
+ brush =
+ Brush.verticalGradient(
+ colors =
+ listOf(
+ DPlayTheme.colors.gray100.copy(alpha = 0f),
+ DPlayTheme.colors.gray100.copy(alpha = 1f),
+ ),
+ ),
+ ),
+ )
}
Column {
DplayDualIconTitleTopAppBar(
@@ -216,9 +233,9 @@ private fun DetailScreen(
state.badge?.let { badge ->
val chipType =
when (badge) {
- BADGE.BEST -> DPlayChipType.BEST
- BADGE.EDITOR -> DPlayChipType.EDITOR
- BADGE.NEW -> DPlayChipType.NEW
+ Badge.BEST -> DPlayChipType.BEST
+ Badge.EDITOR -> DPlayChipType.EDITOR
+ Badge.NEW -> DPlayChipType.NEW
}
Image(
painter = painterResource(id = chipType.drawableRes),
@@ -234,14 +251,14 @@ private fun DetailScreen(
Text(
text = state.track.songTitle,
- modifier = Modifier.align(Alignment.CenterHorizontally),
+ modifier = Modifier.padding(horizontal = 16.dp).align(Alignment.CenterHorizontally),
style = typography.bodyBold20,
color = color.dplayBlack,
)
Spacer(modifier = Modifier.height(4.dp))
Text(
text = state.track.artistName,
- modifier = Modifier.align(Alignment.CenterHorizontally),
+ modifier = Modifier.padding(horizontal = 16.dp).align(Alignment.CenterHorizontally),
style = typography.bodySemi14,
color = color.gray400,
)
@@ -290,7 +307,12 @@ private fun DetailScreen(
verticalAlignment = Alignment.CenterVertically,
) {
AsyncImage(
- model = state.writer.profileImg ?: R.drawable.base_profile_image,
+ model =
+ if (state.writer.isAdmin) {
+ R.drawable.img_profile
+ } else {
+ state.writer.profileImg ?: R.drawable.base_profile_image
+ },
contentDescription = null,
modifier =
Modifier
diff --git a/feature/detail/src/main/java/com/example/detail/DetailViewModel.kt b/feature/detail/src/main/java/com/example/detail/DetailViewModel.kt
index 8b20dcd3..1c0cec66 100644
--- a/feature/detail/src/main/java/com/example/detail/DetailViewModel.kt
+++ b/feature/detail/src/main/java/com/example/detail/DetailViewModel.kt
@@ -8,7 +8,7 @@ import com.example.common.event.ScrappedTrackRefreshTrigger
import com.example.designsystem.component.snackbar.type.SnackBarType
import com.example.detail.DetailContract.DetailSideEffect.NavigateToMyPage
import com.example.detail.DetailContract.DetailSideEffect.ShowSnackBar
-import com.example.domain.model.BADGE
+import com.example.domain.model.Badge
import com.example.domain.model.Like
import com.example.domain.model.LoadingState
import com.example.domain.model.UserRelation
@@ -62,6 +62,9 @@ class DetailViewModel
when (intent) {
is DetailContract.DetailIntent.LoadData -> loadData(intent.postId, intent.badge)
is DetailContract.DetailIntent.OnBackButtonClick -> {
+ if (currentState.homeRefreshRequired) {
+ viewModelScope.launch { homeRefreshTrigger.refresh() }
+ }
setSideEffect(DetailContract.DetailSideEffect.NavigateBackStack)
}
@@ -80,7 +83,7 @@ class DetailViewModel
is DetailContract.DetailIntent.OnReportClick -> reportPost()
is DetailContract.DetailIntent.OnStreamClick -> streamTrack()
is DetailContract.DetailIntent.OnWriterProfileClick -> {
- navigateToOthersProfile()
+ if (!currentState.writer.isAdmin) navigateToOthersProfile()
}
is DetailContract.DetailIntent.ChangeBottomSheetVisible -> {
@@ -91,7 +94,7 @@ class DetailViewModel
private fun loadData(
postId: Long,
- badge: BADGE?,
+ badge: Badge?,
) {
viewModelScope.launch {
postRepository
@@ -102,12 +105,14 @@ class DetailViewModel
loadingState = LoadingState.SUCCESS,
postId = postDetail.postId,
isScrapped = postDetail.isScrapped,
+ initialIsScrapped = postDetail.isScrapped,
content = postDetail.content,
isHost = postDetail.isHost,
date = postDetail.displayDate,
track = postDetail.track,
writer = postDetail.writer,
like = postDetail.like,
+ initialIsLiked = postDetail.like.isLiked,
badge = badge,
)
}
@@ -236,7 +241,6 @@ class DetailViewModel
when (userRelation) {
UserRelation.ME -> setSideEffect(NavigateToMyPage())
- UserRelation.ADMIN -> {}
UserRelation.OTHER -> setSideEffect(DetailContract.DetailSideEffect.NavigateToWriterProfile(userId))
}
}
diff --git a/feature/editprofile/src/main/java/com/example/editprofile/EditProfileScreen.kt b/feature/editprofile/src/main/java/com/example/editprofile/EditProfileScreen.kt
index 31c2f5c1..aa2e59f1 100644
--- a/feature/editprofile/src/main/java/com/example/editprofile/EditProfileScreen.kt
+++ b/feature/editprofile/src/main/java/com/example/editprofile/EditProfileScreen.kt
@@ -162,7 +162,7 @@ fun EditProfileScreen(
onFocusChange = {},
placeholder = stringResource(R.string.placeholder_nickname),
maxLength = TextFieldConstant.MAX_NICKNAME_LENGTH,
- modifier = Modifier.padding(horizontal = 8.dp),
+ modifier = Modifier.padding(horizontal = 16.dp),
)
Spacer(modifier = Modifier.weight(1f))
diff --git a/feature/home/src/main/java/com/example/home/HomeContract.kt b/feature/home/src/main/java/com/example/home/HomeContract.kt
index 1ed785d0..e9422eb3 100644
--- a/feature/home/src/main/java/com/example/home/HomeContract.kt
+++ b/feature/home/src/main/java/com/example/home/HomeContract.kt
@@ -1,7 +1,7 @@
package com.example.home
import com.example.designsystem.component.snackbar.type.SnackBarType
-import com.example.domain.model.BADGE
+import com.example.domain.model.Badge
import com.example.domain.model.DailyQuestion
import com.example.domain.model.FeedItem
import com.example.navigation.MyPageTab
@@ -62,7 +62,7 @@ class HomeContract {
data class NavigateToPostDetail(
val postId: Long,
- val badge: BADGE?,
+ val badge: Badge?,
) : HomeSideEffect
data object NavigateToRecord : HomeSideEffect
diff --git a/feature/home/src/main/java/com/example/home/HomeScreen.kt b/feature/home/src/main/java/com/example/home/HomeScreen.kt
index b727bd30..0d87b316 100644
--- a/feature/home/src/main/java/com/example/home/HomeScreen.kt
+++ b/feature/home/src/main/java/com/example/home/HomeScreen.kt
@@ -34,7 +34,7 @@ import com.example.designsystem.component.button.DPlayBookmarkButton
import com.example.designsystem.component.chip.type.DPlayChipType
import com.example.designsystem.component.snackbar.LocalShowSnackBar
import com.example.designsystem.theme.DPlayTheme
-import com.example.domain.model.BADGE
+import com.example.domain.model.Badge
import com.example.domain.model.FeedItem
import com.example.navigation.Detail
import com.example.navigation.MyPage
@@ -210,9 +210,9 @@ private fun HomePager(
val currentChipType: DPlayChipType? =
currentItem?.badge?.let {
when (it) {
- BADGE.BEST -> DPlayChipType.BEST
- BADGE.EDITOR -> DPlayChipType.EDITOR
- BADGE.NEW -> DPlayChipType.NEW
+ Badge.BEST -> DPlayChipType.BEST
+ Badge.EDITOR -> DPlayChipType.EDITOR
+ Badge.NEW -> DPlayChipType.NEW
}
}
@@ -230,6 +230,7 @@ private fun HomePager(
DPlayLargeCover(
modifier = Modifier.fillMaxWidth(),
+ isAdmin = item.writer.isAdmin,
isLocked = isLockedPage,
isLikeChecked = item.like.isLiked,
likeCount = item.like.count,
@@ -246,7 +247,9 @@ private fun HomePager(
onPostClick(item.postId)
}
},
- onWriterProfileClick = { onWriterProfileClick(item.writer.userId) },
+ onWriterProfileClick = {
+ if (!item.writer.isAdmin) onWriterProfileClick(item.writer.userId)
+ },
isStreaming = uiState.streamingTrackId == item.track.trackId,
)
}
diff --git a/feature/home/src/main/java/com/example/home/HomeViewModel.kt b/feature/home/src/main/java/com/example/home/HomeViewModel.kt
index fe4f5f15..ac73bca6 100644
--- a/feature/home/src/main/java/com/example/home/HomeViewModel.kt
+++ b/feature/home/src/main/java/com/example/home/HomeViewModel.kt
@@ -4,7 +4,6 @@ import androidx.lifecycle.viewModelScope
import com.example.common.audio.AudioPlayer
import com.example.common.event.HomeRefreshTrigger
import com.example.designsystem.component.snackbar.type.SnackBarType
-import com.example.domain.model.BADGE
import com.example.domain.model.FeedItem
import com.example.domain.model.Like
import com.example.domain.model.Track
@@ -16,7 +15,6 @@ import com.example.domain.usecase.CheckUserRelationUseCase
import com.example.navigation.MyPageTab
import com.example.ui.base.BaseViewModel
import dagger.hilt.android.lifecycle.HiltViewModel
-import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toImmutableList
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
@@ -136,6 +134,7 @@ class HomeViewModel
userId = -1L,
nickname = "",
profileImg = "",
+ isAdmin = false,
),
like =
Like(
@@ -266,163 +265,8 @@ class HomeViewModel
when (userRelation) {
UserRelation.ME -> setSideEffect(HomeContract.HomeSideEffect.NavigateToMyPage())
- UserRelation.ADMIN -> {}
UserRelation.OTHER -> setSideEffect(HomeContract.HomeSideEffect.NavigateToWriterProfile(userId))
}
}
}
}
-
-val dummyFeedItems =
- persistentListOf(
- FeedItem(
- postId = 111,
- isScrapped = true,
- content = "그냥 좋아요 이 노래",
- badge = BADGE.BEST,
- track =
- Track(
- trackId = "apple:203948",
- songTitle = "Song Title 1",
- coverImg = "https://picsum.photos/300",
- artistName = "Artist1, Artist2",
- isrc = "USUC1234567890",
- ),
- writer =
- Writer(
- userId = 222,
- nickname = "윤서암",
- profileImg = "https://picsum.photos/200",
- ),
- like =
- Like(
- isLiked = false,
- count = 24,
- ),
- ),
- FeedItem(
- postId = 112,
- isScrapped = false,
- content = "비 오는 날 꼭 듣는 노래에요",
- badge = BADGE.EDITOR,
- track =
- Track(
- trackId = "apple:204837",
- songTitle = "Song Title 2",
- coverImg = "https://picsum.photos/310",
- artistName = "Artist3",
- isrc = "USUC1234567891",
- ),
- writer =
- Writer(
- userId = 333,
- nickname = "민석",
- profileImg = "https://picsum.photos/201",
- ),
- like =
- Like(
- isLiked = true,
- count = 57,
- ),
- ),
- FeedItem(
- postId = 113,
- isScrapped = false,
- content = "출근길에 항상 듣습니다!",
- badge = BADGE.NEW,
- track =
- Track(
- trackId = "apple:204111",
- songTitle = "Song Title 3",
- coverImg = "https://picsum.photos/320",
- artistName = "Artist4",
- isrc = "USUC1234567892",
- ),
- writer =
- Writer(
- userId = 444,
- nickname = "서현",
- profileImg = "https://picsum.photos/202",
- ),
- like =
- Like(
- isLiked = false,
- count = 13,
- ),
- ),
- FeedItem(
- postId = 113,
- isScrapped = false,
- content = "출근길에 항상 듣습니다!",
- badge = BADGE.NEW,
- track =
- Track(
- trackId = "apple:204111",
- songTitle = "Song Title 3",
- coverImg = "https://picsum.photos/320",
- artistName = "Artist4",
- isrc = "USUC1234567893",
- ),
- writer =
- Writer(
- userId = 444,
- nickname = "서현",
- profileImg = "https://picsum.photos/202",
- ),
- like =
- Like(
- isLiked = false,
- count = 13,
- ),
- ),
- FeedItem(
- postId = 113,
- isScrapped = false,
- content = "출근길에 항상 듣습니다!",
- badge = BADGE.NEW,
- track =
- Track(
- trackId = "apple:204111",
- songTitle = "Song Title 3",
- coverImg = "https://picsum.photos/320",
- artistName = "Artist4",
- isrc = "USUC1234567894",
- ),
- writer =
- Writer(
- userId = 444,
- nickname = "서현",
- profileImg = "https://picsum.photos/202",
- ),
- like =
- Like(
- isLiked = false,
- count = 13,
- ),
- ),
- FeedItem(
- postId = 113,
- isScrapped = false,
- content = "출근길에 항상 듣습니다!",
- badge = BADGE.NEW,
- track =
- Track(
- trackId = "apple:204111",
- songTitle = "Song Title 3",
- coverImg = "https://picsum.photos/320",
- artistName = "Artist4",
- isrc = "USUC1234567895",
- ),
- writer =
- Writer(
- userId = 444,
- nickname = "서현",
- profileImg = "https://picsum.photos/202",
- ),
- like =
- Like(
- isLiked = false,
- count = 13,
- ),
- ),
- )
diff --git a/feature/onboarding/src/main/java/com/example/onboarding/OnboardingProfileScreen.kt b/feature/onboarding/src/main/java/com/example/onboarding/OnboardingProfileScreen.kt
index 9b71d012..c3565f9a 100644
--- a/feature/onboarding/src/main/java/com/example/onboarding/OnboardingProfileScreen.kt
+++ b/feature/onboarding/src/main/java/com/example/onboarding/OnboardingProfileScreen.kt
@@ -172,7 +172,7 @@ fun OnboardingProfileScreen(
onFocusChange = {},
placeholder = stringResource(R.string.placeholder_nickname),
maxLength = TextFieldConstant.MAX_NICKNAME_LENGTH,
- modifier = Modifier.padding(horizontal = 8.dp),
+ modifier = Modifier.padding(horizontal = 16.dp),
)
Spacer(modifier = Modifier.weight(1f))
diff --git a/feature/record/src/main/java/com/example/record/RecordContract.kt b/feature/record/src/main/java/com/example/record/RecordContract.kt
index 86d3145c..d0107007 100644
--- a/feature/record/src/main/java/com/example/record/RecordContract.kt
+++ b/feature/record/src/main/java/com/example/record/RecordContract.kt
@@ -14,6 +14,8 @@ class RecordContract {
val selectedQuestion: DailyQuestion? = null,
val datePickerBottomSheetVisible: Boolean = false,
val recordListTotalCount: Int = 0,
+ val tooltipVisible: Boolean = false,
+ val locked: Boolean = true,
) : BaseContract.State
sealed interface RecordIntent : BaseContract.Intent {
@@ -37,6 +39,10 @@ class RecordContract {
val year: Int,
val month: Int,
) : RecordIntent
+
+ data class ChangeTooltipVisible(
+ val isVisible: Boolean,
+ ) : RecordIntent
}
sealed interface RecordSideEffect : BaseContract.SideEffect {
diff --git a/feature/record/src/main/java/com/example/record/RecordListScreen.kt b/feature/record/src/main/java/com/example/record/RecordListScreen.kt
index 3891a74e..0bb60a87 100644
--- a/feature/record/src/main/java/com/example/record/RecordListScreen.kt
+++ b/feature/record/src/main/java/com/example/record/RecordListScreen.kt
@@ -1,5 +1,6 @@
package com.example.record
+import androidx.activity.compose.BackHandler
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
@@ -20,8 +21,10 @@ import com.dplay.record.R
import com.example.designsystem.component.DPlayMusicListItem
import com.example.designsystem.component.DPlaySubjectItem
import com.example.designsystem.component.DplayLeftIconTitleTopAppBar
+import com.example.designsystem.component.DplayTooltip
+import com.example.designsystem.component.button.DPlayGuidelineButton
import com.example.designsystem.theme.DPlayTheme
-import com.example.domain.model.BADGE
+import com.example.domain.model.Badge
import com.example.domain.model.FeedItem
import com.example.ui.emptyLazyPagingItems
@@ -29,10 +32,15 @@ import com.example.ui.emptyLazyPagingItems
fun RecordListScreen(
onBackButtonClick: () -> Unit,
onMusicClick: (postId: Long) -> Unit,
+ onGuideButtonClick: () -> Unit,
+ onTooltipCloseClick: () -> Unit,
modifier: Modifier = Modifier,
uiState: RecordContract.RecordState = RecordContract.RecordState(),
questionPosts: LazyPagingItems = emptyLazyPagingItems(),
) {
+ BackHandler {
+ onBackButtonClick()
+ }
Column(modifier = modifier.fillMaxSize()) {
DplayLeftIconTitleTopAppBar(
modifier = Modifier.fillMaxWidth(),
@@ -71,10 +79,27 @@ fun RecordListScreen(
musicName = item.track.songTitle,
musicArtistName = item.track.artistName,
musicContent = item.content,
- isEditorPick = (item.badge == BADGE.EDITOR),
+ isEditorPick = (item.badge == Badge.EDITOR),
onClick = { onMusicClick(item.postId) },
)
}
+
+ if (uiState.locked) {
+ item {
+ DPlayGuidelineButton(
+ onClick = onGuideButtonClick,
+ textStringRes = R.string.record_locked_guide_button_text,
+ )
+ if (uiState.tooltipVisible) {
+ Spacer(modifier = Modifier.height(8.dp))
+ DplayTooltip(
+ onCloseButtonClicked = onTooltipCloseClick,
+ textStringRes = R.string.record_locked_tooltip_description,
+ onTextButtonClicked = null,
+ )
+ }
+ }
+ }
}
}
}
@@ -86,6 +111,8 @@ private fun RecordListScreenPreview() {
RecordListScreen(
onBackButtonClick = {},
onMusicClick = {},
+ onGuideButtonClick = {},
+ onTooltipCloseClick = {},
)
}
}
diff --git a/feature/record/src/main/java/com/example/record/RecordRoute.kt b/feature/record/src/main/java/com/example/record/RecordRoute.kt
index ab83cd12..3603f366 100644
--- a/feature/record/src/main/java/com/example/record/RecordRoute.kt
+++ b/feature/record/src/main/java/com/example/record/RecordRoute.kt
@@ -53,6 +53,12 @@ fun RecordRoute(
onMusicClick = { postId ->
viewModel.handleIntent(RecordContract.RecordIntent.OnMusicClick(postId = postId))
},
+ onGuideButtonClick = {
+ viewModel.handleIntent(RecordContract.RecordIntent.ChangeTooltipVisible(isVisible = true))
+ },
+ onTooltipCloseClick = {
+ viewModel.handleIntent(RecordContract.RecordIntent.ChangeTooltipVisible(isVisible = false))
+ },
)
}
}
diff --git a/feature/record/src/main/java/com/example/record/RecordViewModel.kt b/feature/record/src/main/java/com/example/record/RecordViewModel.kt
index 83ac21f3..e12189f1 100644
--- a/feature/record/src/main/java/com/example/record/RecordViewModel.kt
+++ b/feature/record/src/main/java/com/example/record/RecordViewModel.kt
@@ -43,6 +43,9 @@ class RecordViewModel
onTotalCountFetched = { totalCount ->
updateState { copy(recordListTotalCount = totalCount) }
},
+ onLockedFetched = { locked ->
+ updateState { copy(locked = locked) }
+ },
)
} else {
flowOf(PagingData.empty())
@@ -51,6 +54,7 @@ class RecordViewModel
init {
val now = YearMonth.now()
+ setDate(year = now.year, month = now.month.value)
loadQuestions(year = now.year, month = now.month.value)
}
@@ -70,6 +74,10 @@ class RecordViewModel
is RecordContract.RecordIntent.ChangeBottomSheetVisible -> {
updateState { copy(datePickerBottomSheetVisible = intent.isVisible) }
}
+
+ is RecordContract.RecordIntent.ChangeTooltipVisible -> {
+ updateState { copy(tooltipVisible = intent.isVisible) }
+ }
}
}
diff --git a/feature/record/src/main/res/values/strings.xml b/feature/record/src/main/res/values/strings.xml
index 1b08b1e8..47d26ae9 100644
--- a/feature/record/src/main/res/values/strings.xml
+++ b/feature/record/src/main/res/values/strings.xml
@@ -1,4 +1,6 @@
총 %1$d개의 곡
+ 이 날의 추천은 여기까지에요.\n곡을 등록하지 않은 날에는 최대 3곡만 보여요.
+ 왜 일부 노래만 보이나요?
\ No newline at end of file