Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,22 +1,30 @@
package com.example.data.datasource.remote

import com.example.data.constant.ErrorCode
import com.example.data.model.request.NotificationRequest
import com.example.data.model.request.PatchProfileRequest
import com.example.data.model.response.BaseResponse
import com.example.data.model.response.UserInfoResponse
import com.example.data.service.UserService
import com.example.network.NetworkException
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.SerializationException
import kotlinx.serialization.json.Json
import okhttp3.MediaType.Companion.toMediaTypeOrNull
import okhttp3.MultipartBody
import okhttp3.RequestBody.Companion.asRequestBody
import retrofit2.HttpException
import timber.log.Timber
import java.io.File
import java.net.HttpURLConnection
import javax.inject.Inject

@OptIn(InternalSerializationApi::class)
class UserRemoteDataSource
@Inject
constructor(
private val userService: UserService,
private val json: Json,
) {
suspend fun patchProfile(
nickname: String?,
Expand All @@ -38,8 +46,25 @@ class UserRemoteDataSource
nickname,
),
)
} catch (e: Exception) {
Timber.e(e)
} catch (e: HttpException) {
if (e.code() == HttpURLConnection.HTTP_CONFLICT) {
val errorString = e.response()?.errorBody()?.string()
Timber.d("errorString : $errorString")

if (errorString != null) {
try {
val errorResponse = json.decodeFromString<BaseResponse<String?>>(errorString)
Timber.d("errorResponse : $errorResponse")
if (errorResponse.code == ErrorCode.DUPLICATED_NICKNAME) {
throw NetworkException(ErrorCode.DUPLICATED_NICKNAME, errorResponse.message)
}
} catch (e: SerializationException) {
// JSON 형식이 잘못됨 (괄호 누락 등)
} catch (e: IllegalArgumentException) {
// 데이터 타입 불일치
}
}
}
throw e
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@ import androidx.paging.Pager
import androidx.paging.PagingConfig
import androidx.paging.PagingData
import androidx.paging.map
import com.example.data.constant.ErrorCode
import com.example.data.datasource.local.FileLocalDataSource
import com.example.data.datasource.local.TokenLocalDataSource
import com.example.data.datasource.local.UserLocalDataSource
import com.example.data.datasource.remote.RegisteredTracksPagingSource
import com.example.data.datasource.remote.ScrappedTracksPagingSource
import com.example.data.datasource.remote.UserRemoteDataSource
import com.example.data.service.UserService
import com.example.domain.model.NicknameValidationResult
import com.example.domain.model.ProfileImageState
import com.example.domain.model.RegisteredTrack
import com.example.domain.model.ScrappedTrack
import com.example.domain.model.User
import com.example.domain.repository.UserRepository
import com.example.network.NetworkException
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
Expand Down Expand Up @@ -57,7 +60,7 @@ class UserRepositoryImpl
override suspend fun updateProfile(
nickname: String?,
profileImageState: ProfileImageState,
): Result<Unit> =
): Result<NicknameValidationResult> =
runCatching {
val profileFile =
when (profileImageState) {
Expand All @@ -66,10 +69,17 @@ class UserRepositoryImpl
is ProfileImageState.Update -> fileLocalDataSource.createAndGetFile(profileImageState.imagePath)
}

userRemoteDataSource.patchProfile(
imageFile = profileFile,
nickname = nickname,
)
try {
userRemoteDataSource.patchProfile(
imageFile = profileFile,
nickname = nickname,
)
} catch (e: NetworkException) {
if (e.code == ErrorCode.DUPLICATED_NICKNAME) {
return Result.success(NicknameValidationResult.Error.Duplicated)
}
throw e
}

userLocalDataSource.updateNickname(nickname.orEmpty())

Expand All @@ -84,6 +94,8 @@ class UserRepositoryImpl
}
ProfileImageState.Keep -> {}
}

return Result.success(NicknameValidationResult.Success)
}

override fun getRegisteredTracks(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.example.designsystem.component
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
Expand All @@ -12,13 +13,15 @@ import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.layout.widthIn
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage
Expand All @@ -38,13 +41,6 @@ fun DPlayMusicListItem(
isEditorPick: Boolean = false,
onClick: () -> Unit = {},
) {
val ellipsisMusicContent =
if (musicContent.length > 28) {
musicContent.take(28) + "..."
} else {
musicContent
}

Box(
modifier =
modifier
Expand Down Expand Up @@ -78,17 +74,38 @@ fun DPlayMusicListItem(
onClick = onMoreClick,
modifier = Modifier.align(Alignment.End),
)
Row(verticalAlignment = Alignment.CenterVertically) {
Text(text = musicName, style = DPlayTheme.typography.bodyBold16, color = DPlayTheme.colors.dplayBlack)
Spacer(modifier = Modifier.width(6.dp))
BoxWithConstraints {
val maxTitleWidth = maxWidth * 0.5f

Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = musicName,
style = DPlayTheme.typography.bodyBold16,
color = DPlayTheme.colors.dplayBlack,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.widthIn(max = maxTitleWidth),
)

Spacer(modifier = Modifier.width(6.dp))

Text(text = musicArtistName, style = DPlayTheme.typography.capMed12, color = DPlayTheme.colors.gray400)
Text(
text = musicArtistName,
style = DPlayTheme.typography.capMed12,
color = DPlayTheme.colors.gray400,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
modifier = Modifier.weight(1f),
)
}
}
Spacer(modifier = Modifier.height(4.dp))
Text(
text = ellipsisMusicContent,
text = musicContent,
style = DPlayTheme.typography.capMed12,
color = DPlayTheme.colors.gray500,
maxLines = 1,
overflow = TextOverflow.Ellipsis,
)
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.domain.repository

import androidx.paging.PagingData
import com.example.domain.model.NicknameValidationResult
import com.example.domain.model.ProfileImageState
import com.example.domain.model.RegisteredTrack
import com.example.domain.model.ScrappedTrack
Expand All @@ -21,7 +22,7 @@ interface UserRepository {
suspend fun updateProfile(
nickname: String?,
profileImageState: ProfileImageState,
): Result<Unit>
): Result<NicknameValidationResult>

fun getRegisteredTracks(
userId: Long,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import com.example.designsystem.util.TextFieldConstant
import com.example.designsystem.util.noRippleClickable
import com.example.navigation.Navigator
import kotlinx.coroutines.flow.collectLatest
import timber.log.Timber

@Composable
fun EditProfileRoute(
Expand All @@ -52,9 +53,11 @@ fun EditProfileRoute(
rememberLauncherForActivityResult(
contract = ActivityResultContracts.PickVisualMedia(),
onResult = { uri ->
viewModel.handleIntent(
EditProfileContract.EditProfileIntent.OnAlbumImageSelect(uri),
)
uri?.let {
viewModel.handleIntent(
EditProfileContract.EditProfileIntent.OnAlbumImageSelect(it),
)
}
},
)

Expand Down Expand Up @@ -148,6 +151,7 @@ fun EditProfileScreen(
onClick = { onProfileImageClick() },
)
}
Timber.d("state.profileImagePath : ${state.profileImagePath}")

Spacer(modifier = Modifier.height(24.dp))

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.editprofile

import androidx.lifecycle.viewModelScope
import com.example.domain.model.NicknameValidationResult
import com.example.domain.model.ProfileImageState
import com.example.domain.repository.UserRepository
import com.example.domain.usecase.ValidateNicknameUseCase
Expand Down Expand Up @@ -79,8 +80,16 @@ class EditProfileViewModel
.updateProfile(
nickname = currentState.nickname,
profileImageState = currentState.profileImageState,
).onSuccess {
setSideEffect(EditProfileContract.EditProfileSideEffect.NavigateToBack)
).onSuccess { validationResult ->
if (validationResult is NicknameValidationResult.Error.Duplicated) {
updateState {
copy(
nicknameInputState = NicknameValidationResult.Error.Duplicated.toUiState(),
)
}
} else if (validationResult is NicknameValidationResult.Success) {
setSideEffect(EditProfileContract.EditProfileSideEffect.NavigateToBack)
}
}.onFailure { }
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class MyPageContract {
val userNickname: String = "디플레이",
val profileImagePath: String? = null,
val selectedTabIndex: Int = 0,
val registeredMusicCount: Int = -1,
val registeredMusicCount: Int = 0,
val isDeleteBottomSheetVisible: Boolean = false,
val selectedPostId: Long = -1,
val deletedTrackIds: PersistentSet<Long> = persistentSetOf(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ private fun UserInformationRow(
CircleButtonType.SmallEdit(
R.string.edit_profile_image_button_icon_description,
),
onClick = {},
onClick = { onProfileImageClick() },
)
}
}
Expand Down Expand Up @@ -517,7 +517,7 @@ private fun ScrappedMusicEmptyView() {
Spacer(modifier = Modifier.height(184.dp))

Text(
text = "아직 등록한 곡이 없어요",
text = "아직 저장한 곡이 없어요",
style = DPlayTheme.typography.bodySemi14,
color = DPlayTheme.colors.gray400,
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,11 @@ fun OnboardingProfileRoute(
rememberLauncherForActivityResult(
contract = ActivityResultContracts.PickVisualMedia(),
onResult = { uri ->
viewModel.handleIntent(
OnboardingContract.OnboardingIntent.OnAlbumImageSelect(uri),
)
uri?.let {
viewModel.handleIntent(
OnboardingContract.OnboardingIntent.OnAlbumImageSelect(uri),
)
}
},
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class SettingContract {
data class SettingState(
val isLoading: Boolean = false,
val isPushNotificationEnabled: Boolean = false,
val appVersion: String = "1.0.0",
val appVersion: String = "v1.0.0",
) : BaseContract.State

sealed interface SettingIntent : BaseContract.Intent {
Expand Down
2 changes: 1 addition & 1 deletion feature/setting/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<string name="logout_warning_left_button_label">취소</string>
<string name="logout_warning_right_button_label">로그아웃</string>
<string name="withdraw_warning_main_text">정말 탈퇴하시겠어요?</string>
<string name="withdraw_warning_sub_text">작성하신 글, 좋아요한 글, 저장한 글 등 모든 기록이 삭제되며 복구가 불가능해요.</string>
<string name="withdraw_warning_sub_text">작성하신 글, 좋아요한 글, 저장한 글 등\n모든 기록이 삭제되며 복구가 불가능해요.</string>
<string name="withdraw_warning_left_button_label">탈퇴하기</string>
<string name="withdraw_warning_right_button_label">머무르기</string>
<string name="setting_screen_title">설정</string>
Expand Down