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/#725] poke ananymous #732

Merged
merged 23 commits into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
52117e4
feat #725: PokeUser class 변경
chattymin Jun 3, 2024
1609210
feat #725: PokeFriend를 isAnonymous에 따른 분기처리추가
chattymin Jun 3, 2024
d9d401a
feat #725: Small User View를 isAnonymous에 따른 분기처리추가
chattymin Jun 3, 2024
3212487
feat #725: poke home 서버 의존적 recycleview 적용
chattymin Jun 4, 2024
6674c3c
feat #725: someone poke anonymous
chattymin Jun 4, 2024
401898d
feat #725: someone poke anonymous item
chattymin Jun 4, 2024
c5fae64
add #725: mate lottie
chattymin Jun 5, 2024
3ea8480
feat #725: pokeNum에 따른 lottie 구현
chattymin Jun 5, 2024
3a2c1ab
feat #725: string res 적용
chattymin Jun 5, 2024
3a5acce
feat #725: 1차 qa 일부 적용
chattymin Jun 7, 2024
7a1564a
feat #725: onboarding 타이틀 오류 수정
chattymin Jun 7, 2024
6010b94
feat #725: 변수 수정
chattymin Jun 8, 2024
b8bea26
feat #725: Add FriendListSummary AnonymousFriend Lottie
chattymin Jun 8, 2024
f47ddea
feat #725: Add FriendListDetail
chattymin Jun 8, 2024
d8a7f2e
feat #725: code clear
chattymin Jun 8, 2024
b2f908e
feat #725: spotlessApply
chattymin Jun 8, 2024
2536869
fix #725: View.AddAnimatorEndListener 추가 및 적용
chattymin Jun 9, 2024
885f815
fix #725: AddOnAnimatorEndListener 수정 및 적용
chattymin Jun 9, 2024
dcf93fb
fix #725: "Loading" 제거
chattymin Jun 9, 2024
d2a0421
fix #725: lifecycleScope 수정
chattymin Jun 9, 2024
1d43000
fix #725: dummyData 제거
chattymin Jun 9, 2024
4b0d31d
fix #725: 매직넘버 제거 및 함수화
chattymin Jun 9, 2024
b30a930
fix #725: spotlessApply
chattymin Jun 9, 2024
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
Expand Up @@ -54,6 +54,12 @@ data class PokeUserResult(
val isFirstMeet: Boolean,
@SerialName("isAlreadyPoke")
val isAlreadyPoke: Boolean,
@SerialName("isAnonymous")
val isAnonymous: Boolean,
@SerialName("anonymousName")
val anonymousName: String,
@SerialName("anonymousImage")
val anonymousImage: String,
) {
fun toEntity(): PokeUser = PokeUser(
userId = userId,
Expand All @@ -68,5 +74,8 @@ data class PokeUserResult(
mutualRelationMessage = mutualRelationMessage,
isFirstMeet = isFirstMeet,
isAlreadyPoke = isAlreadyPoke,
isAnonymous = isAnonymous,
anonymousName = anonymousName,
anonymousImage = anonymousImage
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,7 @@ data class PokeUser(
val mutualRelationMessage: String,
val isFirstMeet: Boolean,
var isAlreadyPoke: Boolean,
val isAnonymous: Boolean,
val anonymousName: String,
val anonymousImage: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,17 @@ import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import coil.load
import coil.transform.CircleCropTransformation
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import dagger.hilt.android.AndroidEntryPoint
import javax.inject.Inject
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.sopt.official.analytics.AmplitudeTracker
import org.sopt.official.analytics.EventType
import org.sopt.official.common.util.colorOf
Expand All @@ -53,11 +57,14 @@ import org.sopt.official.domain.poke.type.PokeMessageType
import org.sopt.official.feature.poke.R
import org.sopt.official.feature.poke.UiState
import org.sopt.official.feature.poke.databinding.FragmentFriendListDetailBottomSheetBinding
import org.sopt.official.feature.poke.main.PokeMainActivity
import org.sopt.official.feature.poke.message.MessageListBottomSheetFragment
import org.sopt.official.feature.poke.user.ItemDecorationDivider
import org.sopt.official.feature.poke.user.PokeUserListAdapter
import org.sopt.official.feature.poke.user.PokeUserListClickListener
import org.sopt.official.feature.poke.user.PokeUserListItemViewType
import org.sopt.official.feature.poke.util.addOnAnimationEndListener
import org.sopt.official.feature.poke.util.setRelationStrokeColor
import org.sopt.official.feature.poke.util.showPokeToast

@AndroidEntryPoint
Expand Down Expand Up @@ -111,11 +118,43 @@ class FriendListDetailBottomSheetFragment : BottomSheetDialogFragment() {
)
}

initLottieListener()
initRecyclerView()
launchPokeMessageListUiStateFlow()
launchPokeUserUiStateFlow()
}

private fun initLottieListener() {
with(binding) {
animationFriendViewLottie.addOnAnimationEndListener {
if (viewModel.anonymousFriend.value != null) { // 천생연분 -> 정체 공개
lifecycleScope.launch {
// 로티
layoutAnonymousFriendLottie.visibility = View.GONE
layoutAnonymousFriendOpen.visibility = View.VISIBLE

val anonymousFriend = viewModel.anonymousFriend.value
anonymousFriend?.let {
tvAnonymousFreindName.text = getString(R.string.anonymous_user_identity, it.anonymousName)
tvAnonymousFreindInfo.text = getString(R.string.anonymous_user_info, it.generation, it.part, it.name)
imgAnonymousFriendOpen.load(it.profileImage.ifEmpty { R.drawable.ic_empty_profile }) {
transformations(CircleCropTransformation())
}

imgAnonymousFriendOpenOutline.setRelationStrokeColor(it.mutualRelationMessage)
}

delay(2000)
layoutAnonymousFriendOpen.visibility = View.GONE
viewModel.setAnonymousFriend(null)
}
} else {
layoutAnonymousFriendLottie.visibility = View.GONE
}
}
}
}

private fun initRecyclerView() {
binding.includeFriendListBlock.apply {
pokeFriendType?.let {
Expand Down Expand Up @@ -214,7 +253,7 @@ class FriendListDetailBottomSheetFragment : BottomSheetDialogFragment() {
viewModel.friendListDetailUiState
.onEach {
when (it) {
is UiState.Loading -> "Loading"
is UiState.Loading -> {}
is UiState.Success<List<PokeUser>> -> updateRecyclerView(it.data)
is UiState.ApiError -> activity?.showPokeToast(getString(R.string.toast_poke_error))
is UiState.Failure -> activity?.showPokeToast(it.throwable.message ?: getString(R.string.toast_poke_error))
Expand Down Expand Up @@ -245,20 +284,41 @@ class FriendListDetailBottomSheetFragment : BottomSheetDialogFragment() {
viewModel.pokeUserUiState
.onEach {
when (it) {
is UiState.Loading -> "Loading"
is UiState.Loading -> {}
is UiState.Success<PokeUser> -> {
messageListBottomSheet?.dismiss()
activity?.showPokeToast(getString(R.string.toast_poke_user_success))
if (PokeMainActivity.isBestFriend(it.data.pokeNum, it.data.isAnonymous)) {
with(binding) {
layoutAnonymousFriendLottie.visibility = View.VISIBLE
tvFreindLottie.text = getString(R.string.anonymous_to_friend, it.data.anonymousName, "단짝친구가")
tvFreindLottieHint.text =
getString(R.string.anonymous_user_info_part, it.data.generation, it.data.part)
animationFriendViewLottie.apply {
setAnimation(R.raw.friendtobestfriend)
}.playAnimation()
}
} else if (PokeMainActivity.isSoulMate(it.data.pokeNum, it.data.isAnonymous)) {
viewModel.setAnonymousFriend(it.data)
with(binding) {
layoutAnonymousFriendLottie.visibility = View.VISIBLE
tvFreindLottie.text = getString(R.string.anonymous_to_friend, it.data.anonymousName, "천생연분이")
animationFriendViewLottie.apply {
setAnimation(R.raw.bestfriendtosoulmate)
}.playAnimation()
}
} else {
showPokeToast(getString(R.string.toast_poke_user_success))
}
}

is UiState.ApiError -> {
messageListBottomSheet?.dismiss()
activity?.showPokeToast(getString(R.string.poke_user_alert_exceeded))
showPokeToast(getString(R.string.poke_user_alert_exceeded))
}

is UiState.Failure -> {
messageListBottomSheet?.dismiss()
activity?.showPokeToast(it.throwable.message ?: getString(R.string.toast_poke_error))
showPokeToast(it.throwable.message ?: getString(R.string.toast_poke_error))
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ class FriendListDetailViewModel @Inject constructor(
private val _pokeUserUiState = MutableStateFlow<UiState<PokeUser>>(UiState.Loading)
val pokeUserUiState: StateFlow<UiState<PokeUser>> get() = _pokeUserUiState

private val _anonymousFriend = MutableStateFlow<PokeUser?>(null)
val anonymousFriend: StateFlow<PokeUser?>
get() = _anonymousFriend

private var totalPageSize = -1
private var currentPaginationIndex = 0
private var friendListJob: Job? = null
Expand Down Expand Up @@ -132,4 +136,8 @@ class FriendListDetailViewModel @Inject constructor(
}
}
}

fun setAnonymousFriend(pokeUser: PokeUser?) {
_anonymousFriend.value = pokeUser
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,19 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.view.View
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.lifecycle.lifecycleScope
import coil.load
import coil.transform.CircleCropTransformation
import dagger.hilt.android.AndroidEntryPoint
import java.io.Serializable
import javax.inject.Inject
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import org.sopt.official.analytics.AmplitudeTracker
import org.sopt.official.analytics.EventType
import org.sopt.official.auth.model.UserStatus
Expand All @@ -52,11 +57,14 @@ import org.sopt.official.feature.poke.R
import org.sopt.official.feature.poke.UiState
import org.sopt.official.feature.poke.databinding.ActivityFriendListSummaryBinding
import org.sopt.official.feature.poke.friend.detail.FriendListDetailBottomSheetFragment
import org.sopt.official.feature.poke.main.PokeMainActivity
import org.sopt.official.feature.poke.message.MessageListBottomSheetFragment
import org.sopt.official.feature.poke.user.ItemDecorationDivider
import org.sopt.official.feature.poke.user.PokeUserListAdapter
import org.sopt.official.feature.poke.user.PokeUserListClickListener
import org.sopt.official.feature.poke.user.PokeUserListItemViewType
import org.sopt.official.feature.poke.util.addOnAnimationEndListener
import org.sopt.official.feature.poke.util.setRelationStrokeColor
import org.sopt.official.feature.poke.util.showPokeToast

@AndroidEntryPoint
Expand Down Expand Up @@ -89,6 +97,7 @@ class FriendListSummaryActivity : AppCompatActivity() {
setContentView(binding.root)

initAppBar()
initLottieListener()
initFriendListBlock()
launchFriendListSummaryUiStateFlow()
launchPokeUserUiStateFlow()
Expand All @@ -106,6 +115,37 @@ class FriendListSummaryActivity : AppCompatActivity() {
}
}

private fun initLottieListener() {
with(binding) {
animationFriendViewLottie.addOnAnimationEndListener {
if (viewModel.anonymousFriend.value != null) { // 천생연분 -> 정체 공개
lifecycleScope.launch {
// 로티
layoutAnonymousFriendLottie.visibility = View.GONE
layoutAnonymousFriendOpen.visibility = View.VISIBLE

val anonymousFriend = viewModel.anonymousFriend.value
anonymousFriend?.let {
tvAnonymousFreindName.text = getString(R.string.anonymous_user_identity, it.anonymousName)
tvAnonymousFreindInfo.text = getString(R.string.anonymous_user_info, it.generation, it.part, it.name)
imgAnonymousFriendOpen.load(it.profileImage.ifEmpty { R.drawable.ic_empty_profile }) {
transformations(CircleCropTransformation())
}

imgAnonymousFriendOpenOutline.setRelationStrokeColor(it.mutualRelationMessage)
}

delay(2000)
layoutAnonymousFriendOpen.visibility = View.GONE
viewModel.setAnonymousFriend(null)
}
} else {
layoutAnonymousFriendLottie.visibility = View.GONE
}
}
}
}

private fun initFriendListBlock() {
binding.swipeRefreshLayout.setOnRefreshListener {
viewModel.getFriendListSummary()
Expand Down Expand Up @@ -170,7 +210,7 @@ class FriendListSummaryActivity : AppCompatActivity() {
viewModel.friendListSummaryUiState
.onEach {
when (it) {
is UiState.Loading -> "Loading"
is UiState.Loading -> {}
is UiState.Success<FriendListSummary> -> updateRecyclerView(it.data)
is UiState.ApiError -> showPokeToast(getString(R.string.toast_poke_error))
is UiState.Failure -> showPokeToast(it.throwable.message ?: getString(R.string.toast_poke_error))
Expand Down Expand Up @@ -279,11 +319,33 @@ class FriendListSummaryActivity : AppCompatActivity() {
viewModel.pokeUserUiState
.onEach {
when (it) {
is UiState.Loading -> "Loading"
is UiState.Loading -> {}
is UiState.Success<PokeUser> -> {
messageListBottomSheet?.dismiss()
viewModel.getFriendListSummary()
showPokeToast(getString(R.string.toast_poke_user_success))

if (PokeMainActivity.isBestFriend(it.data.pokeNum, it.data.isAnonymous)) {
with(binding) {
layoutAnonymousFriendLottie.visibility = View.VISIBLE
tvFreindLottie.text = getString(R.string.anonymous_to_friend, it.data.anonymousName, "단짝친구가")
tvFreindLottieHint.text =
getString(R.string.anonymous_user_info_part, it.data.generation, it.data.part)
animationFriendViewLottie.apply {
setAnimation(R.raw.friendtobestfriend)
}.playAnimation()
}
} else if (PokeMainActivity.isSoulMate(it.data.pokeNum, it.data.isAnonymous)) {
viewModel.setAnonymousFriend(it.data)
with(binding) {
layoutAnonymousFriendLottie.visibility = View.VISIBLE
tvFreindLottie.text = getString(R.string.anonymous_to_friend, it.data.anonymousName, "천생연분이")
animationFriendViewLottie.apply {
setAnimation(R.raw.bestfriendtosoulmate)
}.playAnimation()
}
} else {
showPokeToast(getString(R.string.toast_poke_user_success))
}
}

is UiState.ApiError -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@ class FriendListSummaryViewModel @Inject constructor(
private val _pokeUserUiState = MutableStateFlow<UiState<PokeUser>>(UiState.Loading)
val pokeUserUiState: StateFlow<UiState<PokeUser>> get() = _pokeUserUiState

private val _anonymousFriend = MutableStateFlow<PokeUser?>(null)
val anonymousFriend: StateFlow<PokeUser?>
get() = _anonymousFriend

init {
getFriendListSummary()
}
Expand Down Expand Up @@ -90,4 +94,8 @@ class FriendListSummaryViewModel @Inject constructor(
}
}
}

fun setAnonymousFriend(pokeUser: PokeUser?) {
_anonymousFriend.value = pokeUser
}
}
Loading