Skip to content

Commit

Permalink
feat: 닉네임 변경 기능 구현 (#569)
Browse files Browse the repository at this point in the history
* design: 마이페이지에 닉네임 변경 뷰로 가는 이미지 추가

* design: 내 프로필 변경(닉네임 변경) 뷰 생성

* feat: 마이페이지에서 프로필 변경 뷰로 이동하는 기능 구현

* feat: profile 작업을 위한 profile 서비스, profile 레포지토리 생성

* feat: hilt 적용

* feat: 닉네임 변경 기능 구현

* feat: 마이페이지에서 내 이름을 가져올 때 랭킹이 아닌 프로필 레포지토리를 사용해 가져오도록 변경

* refactor: 오류 문구 수정

* refactor: 인자 타입 변경

* refactor: 데이터 바이딩 변수 할당

* feat: 닉네임 변경 후 마이페이지로 돌아왔을 때 바뀐 닉네임으로 보이도록 변경

* design: 닉네임 뷰 배경 이미지 추가

* fix: 닉네임 변경 안되는 오류 수정

* design: 공백 추가

* refactor: 버튼 round 처리

* refactor: edittext 색상 변경

* refactor: edittext 색상 변경
  • Loading branch information
hyunji1203 authored Nov 16, 2023
1 parent 44b4acc commit ce5d6a3
Show file tree
Hide file tree
Showing 18 changed files with 394 additions and 44 deletions.
43 changes: 23 additions & 20 deletions android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@
android:theme="@style/Theme.Naaga"
android:usesCleartextTraffic="true"
tools:targetApi="33">
<activity
android:name=".presentation.profile.ProfileActivity"
android:exported="false" />

<meta-data
android:name="com.naver.maps.map.CLIENT_ID"
Expand All @@ -40,44 +43,44 @@
</activity>
<activity
android:name=".presentation.beginadventure.BeginAdventureActivity"
android:screenOrientation="portrait"
android:exported="false" />
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".presentation.onadventure.OnAdventureActivity"
android:screenOrientation="portrait"
android:exported="false" />
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".presentation.adventurehistory.AdventureHistoryActivity"
android:screenOrientation="portrait"
android:exported="false" />
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".presentation.upload.UploadActivity"
android:screenOrientation="portrait"
android:exported="false" />
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".presentation.rank.RankActivity"
android:screenOrientation="portrait"
android:exported="false" />
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".presentation.adventureresult.AdventureResultActivity"
android:screenOrientation="portrait"
android:exported="false" />
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".presentation.mypage.MyPageActivity"
android:screenOrientation="portrait"
android:exported="false" />
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".presentation.login.LoginActivity"
android:screenOrientation="portrait"
android:exported="false" />
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".presentation.setting.SettingActivity"
android:screenOrientation="portrait"
android:exported="false" />
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name=".presentation.adventuredetail.AdventureDetailActivity"
android:screenOrientation="portrait"
android:exported="false" />
android:exported="false"
android:screenOrientation="portrait" />
<activity
android:name="com.kakao.sdk.auth.AuthCodeHandlerActivity"
android:exported="true">
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.now.naaga.data.remote.dto

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class NicknameDto(
@SerialName("nickname")
val nickname: String,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package com.now.naaga.data.remote.retrofit.service

import com.now.naaga.data.remote.dto.NicknameDto
import com.now.naaga.data.remote.dto.PlayerDto
import retrofit2.Response
import retrofit2.http.Body
import retrofit2.http.GET
import retrofit2.http.PATCH

interface ProfileService {
@GET("/profiles/my")
suspend fun getProfile(): Response<PlayerDto>

@PATCH("/profiles/my")
suspend fun modifyNickname(
@Body nicknameDto: NicknameDto,
): Response<NicknameDto>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.now.naaga.data.repository

import com.now.domain.model.Player
import com.now.domain.repository.ProfileRepository
import com.now.naaga.data.mapper.toDomain
import com.now.naaga.data.remote.dto.NicknameDto
import com.now.naaga.data.remote.retrofit.service.ProfileService
import com.now.naaga.util.extension.getValueOrThrow

class DefaultProfileRepository(
private val profileService: ProfileService,
) : ProfileRepository {
override suspend fun fetchProfile(): Player {
val response = profileService.getProfile().getValueOrThrow()
return response.toDomain()
}

override suspend fun modifyNickname(nickname: String): String {
val nicknameDto = NicknameDto(nickname)
val response = profileService.modifyNickname(nicknameDto).getValueOrThrow()
return response.nickname
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,22 @@ import com.now.domain.repository.AdventureRepository
import com.now.domain.repository.AuthRepository
import com.now.domain.repository.LetterRepository
import com.now.domain.repository.PlaceRepository
import com.now.domain.repository.ProfileRepository
import com.now.domain.repository.RankRepository
import com.now.domain.repository.StatisticsRepository
import com.now.naaga.data.local.AuthDataSource
import com.now.naaga.data.remote.retrofit.service.AdventureService
import com.now.naaga.data.remote.retrofit.service.AuthService
import com.now.naaga.data.remote.retrofit.service.LetterService
import com.now.naaga.data.remote.retrofit.service.PlaceService
import com.now.naaga.data.remote.retrofit.service.ProfileService
import com.now.naaga.data.remote.retrofit.service.RankService
import com.now.naaga.data.remote.retrofit.service.StatisticsService
import com.now.naaga.data.repository.DefaultAdventureRepository
import com.now.naaga.data.repository.DefaultAuthRepository
import com.now.naaga.data.repository.DefaultLetterRepository
import com.now.naaga.data.repository.DefaultPlaceRepository
import com.now.naaga.data.repository.DefaultProfileRepository
import com.now.naaga.data.repository.DefaultRankRepository
import com.now.naaga.data.repository.DefaultStatisticsRepository
import dagger.Module
Expand Down Expand Up @@ -55,4 +58,9 @@ class RepositoryModule {
@Provides
fun provideLetterRepository(letterService: LetterService): LetterRepository =
DefaultLetterRepository(letterService)

@Singleton
@Provides
fun provideProfileRepository(profileService: ProfileService): ProfileRepository =
DefaultProfileRepository(profileService)
}
5 changes: 5 additions & 0 deletions android/app/src/main/java/com/now/naaga/di/ServiceModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import com.now.naaga.data.remote.retrofit.service.AdventureService
import com.now.naaga.data.remote.retrofit.service.AuthService
import com.now.naaga.data.remote.retrofit.service.LetterService
import com.now.naaga.data.remote.retrofit.service.PlaceService
import com.now.naaga.data.remote.retrofit.service.ProfileService
import com.now.naaga.data.remote.retrofit.service.RankService
import com.now.naaga.data.remote.retrofit.service.StatisticsService
import dagger.Module
Expand Down Expand Up @@ -61,4 +62,8 @@ class ServiceModule {
@Singleton
@Provides
fun provideLetterService(retrofit: Retrofit): LetterService = retrofit.create(LetterService::class.java)

@Singleton
@Provides
fun provideProfileService(retrofit: Retrofit): ProfileService = retrofit.create(ProfileService::class.java)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.now.naaga.presentation.mypage
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import com.now.domain.model.Statistics
Expand All @@ -14,6 +15,7 @@ import com.now.naaga.data.throwable.DataThrowable
import com.now.naaga.databinding.ActivityMyPageBinding
import com.now.naaga.presentation.adventurehistory.AdventureHistoryActivity
import com.now.naaga.presentation.mypage.statistics.MyPageStatisticsAdapter
import com.now.naaga.presentation.profile.ProfileActivity
import com.now.naaga.presentation.uimodel.model.StatisticsUiModel
import com.now.naaga.util.extension.showToast
import dagger.hilt.android.AndroidEntryPoint
Expand All @@ -23,6 +25,14 @@ class MyPageActivity : AppCompatActivity(), AnalyticsDelegate by DefaultAnalytic
private lateinit var binding: ActivityMyPageBinding
private val viewModel: MyPageViewModel by viewModels()

private val myPageActivityLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == RESULT_OK) {
val nickname = it.data?.getStringExtra(NICKNAME_KEY) ?: ""
binding.tvMypageNickname.text = nickname
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMyPageBinding.inflate(layoutInflater)
Expand All @@ -48,10 +58,14 @@ class MyPageActivity : AppCompatActivity(), AnalyticsDelegate by DefaultAnalytic
val intent = AdventureHistoryActivity.getIntent(this)
startActivity(intent)
}
binding.ivMypageProfileModify.setOnClickListener {
val intent = ProfileActivity.getIntent(this)
myPageActivityLauncher.launch(intent)
}
}

private fun fetchData() {
viewModel.fetchRank()
viewModel.fetchProfile()
viewModel.fetchStatistics()
viewModel.fetchPlaces()
}
Expand Down Expand Up @@ -82,8 +96,16 @@ class MyPageActivity : AppCompatActivity(), AnalyticsDelegate by DefaultAnalytic
}

companion object {
private const val NICKNAME_KEY = "nickname"

fun getIntent(context: Context): Intent {
return Intent(context, MyPageActivity::class.java)
}

fun getIntent(context: Context, nickname: String): Intent {
return Intent(context, MyPageActivity::class.java).apply {
putExtra(NICKNAME_KEY, nickname)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.now.domain.model.Place
import com.now.domain.model.Rank
import com.now.domain.model.Player
import com.now.domain.model.Statistics
import com.now.domain.model.type.OrderType
import com.now.domain.model.type.SortType
import com.now.domain.repository.PlaceRepository
import com.now.domain.repository.RankRepository
import com.now.domain.repository.ProfileRepository
import com.now.domain.repository.StatisticsRepository
import com.now.naaga.data.throwable.DataThrowable
import dagger.hilt.android.lifecycle.HiltViewModel
Expand All @@ -20,12 +20,12 @@ import javax.inject.Inject

@HiltViewModel
class MyPageViewModel @Inject constructor(
private val rankRepository: RankRepository,
private val profileRepository: ProfileRepository,
private val statisticsRepository: StatisticsRepository,
private val placeRepository: PlaceRepository,
) : ViewModel() {
private val _rank = MutableLiveData<Rank>()
val rank: LiveData<Rank> = _rank
private val _profile = MutableLiveData<Player>()
val profile: LiveData<Player> = _profile

private val _statistics = MutableLiveData<Statistics>()
val statistics: LiveData<Statistics> = _statistics
Expand All @@ -36,12 +36,12 @@ class MyPageViewModel @Inject constructor(
private val _throwable = MutableLiveData<DataThrowable>()
val throwable: LiveData<DataThrowable> = _throwable

fun fetchRank() {
fun fetchProfile() {
viewModelScope.launch {
runCatching {
rankRepository.getMyRank()
}.onSuccess { rank ->
_rank.value = rank
profileRepository.fetchProfile()
}.onSuccess { profile ->
_profile.value = profile
}.onFailure {
setThrowable(it)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.now.naaga.presentation.profile

import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import com.now.naaga.R
import com.now.naaga.databinding.ActivityProfileBinding
import com.now.naaga.presentation.mypage.MyPageActivity
import com.now.naaga.util.extension.showToast
import dagger.hilt.android.AndroidEntryPoint

@AndroidEntryPoint
class ProfileActivity : AppCompatActivity() {
private lateinit var binding: ActivityProfileBinding
private val viewModel: ProfileViewModel by viewModels()

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityProfileBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.lifecycleOwner = this
binding.viewModel = viewModel
subscribe()
setClickListeners()
}

private fun subscribe() {
viewModel.modifyStatus.observe(this) { status ->
if (status) {
showToast(getString(R.string.profile_modify_success_message))
setResult(RESULT_OK, MyPageActivity.getIntent(this, viewModel.nickname.value.toString()))
finish()
}
}
viewModel.throwable.observe(this) {
showToast(getString(R.string.profile_modify_fail_message))
}
}

private fun setClickListeners() {
binding.ivProfileBack.setOnClickListener {
finish()
}
binding.btnProfileNicknameModify.setOnClickListener {
if (viewModel.isFormValid()) {
viewModel.modifyNickname()
} else {
showToast(getString(R.string.profile_no_content_message))
}
}
}

companion object {
fun getIntent(context: Context): Intent {
return Intent(context, ProfileActivity::class.java)
}
}
}
Loading

0 comments on commit ce5d6a3

Please sign in to comment.