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
Expand Up @@ -86,17 +86,22 @@ class AccountFragment : Fragment() {
viewModel.userIdState.collect { state ->
when (state) {

is UiState.Idle -> Unit
is UiState.Idle -> {
binding.tvRealAccountId.visibility = View.INVISIBLE
}

is UiState.Loading -> {
binding.tvRealAccountId.visibility = View.INVISIBLE
//์ถ”ํ›„ ๋กœ๋”ฉ๋ทฐ๋ฅผ ์‚ฝ์ž…ํ•˜์ž
}

is UiState.Success -> {
binding.tvRealAccountId.visibility = View.VISIBLE
binding.tvRealAccountId.text = state.data
}

is UiState.Failure -> {
binding.tvRealAccountId.visibility = View.INVISIBLE
Toast.makeText(requireContext(), "์œ ์ € id๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.", Toast.LENGTH_SHORT).show()
}
}
Expand Down Expand Up @@ -188,7 +193,7 @@ class AccountFragment : Fragment() {
accountDeleteDialog1Fragment.show(childFragmentManager, "AccountDeleteDialog1Fragment")
}

// โœ… ๊ณ ๊ฐ์ง€์› ํด๋ฆญ
// ๊ณ ๊ฐ์ง€์› ํด๋ฆญ
tvSupport.setOnClickListener {
copySupportEmailToClipboard()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import com.egobook.app.domain.model.auth.AuthError
class AccountViewModel @Inject constructor(
private val accountRepository: AccountRepository
) : ViewModel() {
private val _userIdState = MutableStateFlow<UiState<String>>(UiState.Idle)
val userIdState = _userIdState.asStateFlow()
private val _userIdState = MutableStateFlow<UiState<String>>(UiState.Idle)
val userIdState = _userIdState.asStateFlow()

private val _linkState = MutableStateFlow<UiState<Unit>>(UiState.Idle)
val linkState = _linkState.asStateFlow()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import com.egobook.app.databinding.FragmentDiaryListBinding
import com.egobook.app.domain.model.diary.entity.DiarySummary
import com.egobook.app.ui.diary.adapter.DiaryRVAdapter
import com.egobook.app.ui.diary.viewmodel.DiariesViewModel
import com.egobook.app.util.UiState
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch

Expand Down Expand Up @@ -64,20 +65,48 @@ class DiaryListFragment : Fragment() {
viewLifecycleOwner.lifecycleScope.launch {
viewLifecycleOwner.repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.state.collectLatest { state ->
state.diaries.collectLatest { pagingData ->
diaryRVAdapter.submitData(pagingData)
when (val diariesState = state.diaries) {
is UiState.Loading -> {
// Paging3์˜ LoadState๋กœ ๋กœ๋”ฉ ๊ด€๋ฆฌ
}
is UiState.Success -> {
// ๋ฐ์ดํ„ฐ Flow ์ˆ˜์ง‘
launch {
diariesState.data.collectLatest { pagingData ->
diaryRVAdapter.submitData(pagingData)
}
}
}
is UiState.Failure -> {
// TODO: ์—๋Ÿฌ ์ฒ˜๋ฆฌ
}
is UiState.Idle -> { }
}
}
}
}
// LoadState๋ฅผ ๊ด€์ฐฐํ•˜์—ฌ ๋นˆ ์ƒํƒœ ์ฒ˜๋ฆฌ

// Paging3 LoadState๋กœ ํ”„๋กœ๊ทธ๋ ˆ์Šค๋ฐ” + ๋นˆ ์ƒํƒœ ๊ด€๋ฆฌ
viewLifecycleOwner.lifecycleScope.launch {
diaryRVAdapter.loadStateFlow.collectLatest { loadStates ->
val isEmpty = loadStates.refresh is LoadState.NotLoading && diaryRVAdapter.itemCount == 0

binding.layoutEmpty.isVisible = isEmpty
binding.rvDiary.isVisible = !isEmpty
when (val refreshState = loadStates.refresh) {
is LoadState.Loading -> {
// ์ดˆ๊ธฐ ๋กœ๋”ฉ ์ค‘
binding.progressBar.isVisible = true
binding.rvDiary.isVisible = false
binding.layoutEmpty.isVisible = false
}
is LoadState.NotLoading -> {
binding.progressBar.isVisible = false
val isEmpty = diaryRVAdapter.itemCount == 0
binding.layoutEmpty.isVisible = isEmpty
binding.rvDiary.isVisible = !isEmpty
}
is LoadState.Error -> {
binding.progressBar.isVisible = false
// TODO: ์—๋Ÿฌ UI ์ฒ˜๋ฆฌ
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
package com.egobook.app.ui.diary.view

import android.graphics.Color
import android.os.Bundle
import android.text.Editable
import android.text.InputFilter
import android.text.TextWatcher
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import android.widget.Toast
import androidx.annotation.DrawableRes
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
import androidx.lifecycle.Lifecycle
Expand All @@ -27,6 +26,7 @@ import com.egobook.app.ui.util.toDateTimeString
import com.egobook.app.ui.util.toDayOfMonthString
import com.egobook.app.ui.util.toMonthString
import com.egobook.app.ui.util.toYearString
import com.egobook.app.util.UiState
import com.google.android.material.imageview.ShapeableImageView
import com.google.gson.Gson
import dagger.hilt.android.AndroidEntryPoint
Expand Down Expand Up @@ -90,7 +90,8 @@ class DiaryWriteFragment : Fragment() {
setupDiaryContentEditText() // ์ผ๊ธฐ ๋‚ด์šฉ ์ž…๋ ฅ ํ•„๋“œ ์„ค์ • (๊ธ€์ž์ˆ˜ ์ œํ•œ, TextWatcher)
observeSelectedDate() // ์„ ํƒ๋œ ๋‚ ์งœ ๊ด€์ฐฐ ๋ฐ UI ์—…๋ฐ์ดํŠธ
observeContentState() // ์ปจํ…์ธ  ์ƒํƒœ ๊ด€์ฐฐ (๊ธ€์ž์ˆ˜, ๊ฐ์ • ์„น์…˜, ์ €์žฅ ๋ฒ„ํŠผ ํ™œ์„ฑํ™”)
observeSaveResult() // ์ €์žฅ ์„ฑ๊ณต/์‹คํŒจ ๊ด€์ฐฐ
observeSaveResult() // ์ €์žฅ ์„ฑ๊ณต/์‹คํŒจ ๊ด€์ฐฐ
observeDiaryLoadState() // ์ˆ˜์ • ๋ชจ๋“œ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ์ƒํƒœ ๊ด€์ฐฐ
}

private fun setupDiaryTypeCards() {
Expand Down Expand Up @@ -176,6 +177,11 @@ class DiaryWriteFragment : Fragment() {
viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.contentState.collectLatest { state ->
// ๋กœ๋”ฉ ์ค‘์ด๋ฉด UI ์—…๋ฐ์ดํŠธ ์Šคํ‚ต (ํ”„๋กœ๊ทธ๋ ˆ์Šค๋ฐ” ํ‘œ์‹œ ์ค‘)
if (state.diaryLoadState is UiState.Loading) {
return@collectLatest
}

// ๊ธ€์ž์ˆ˜ ํ‘œ์‹œ ์—…๋ฐ์ดํŠธ (์˜ˆ: 0/400, 1/400, ...)
binding.tvCharCount.text = "${state.charCount}/${state.maxCharCount}"

Expand Down Expand Up @@ -208,6 +214,42 @@ class DiaryWriteFragment : Fragment() {
}
}
}

private fun observeDiaryLoadState() {
viewLifecycleOwner.lifecycleScope.launch {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.contentState.collectLatest { state ->
when (val loadState = state.diaryLoadState) {
is UiState.Loading -> {
binding.progressBar.isVisible = true
// ์ž…๋ ฅ UI ์ˆจ๊ธฐ๊ธฐ
binding.guideLayout.isVisible = false
binding.typeLayout.isVisible = false
binding.tvHowIsYourFeeling.isVisible = false
binding.stateLayout.isVisible = false
binding.emotionLayout.isVisible = false
binding.inputBoxLayout.isVisible = false
binding.btnSave.isVisible = false
}
is UiState.Success, is UiState.Idle -> {
binding.progressBar.isVisible = false
// ์ž…๋ ฅ UI ํ‘œ์‹œ
binding.guideLayout.isVisible = true
binding.typeLayout.isVisible = true
// ๊ฐ์ • ์„น์…˜์€ ์„ ํƒ ์ƒํƒœ์— ๋”ฐ๋ผ ํ‘œ์‹œ (observeContentState์—์„œ ์ฒ˜๋ฆฌ)
binding.inputBoxLayout.isVisible = true
binding.btnSave.isVisible = true
}
is UiState.Failure -> {
binding.progressBar.isVisible = false
// ์—๋Ÿฌ ์ฒ˜๋ฆฌ (ํ•„์š”์‹œ ํ† ์ŠคํŠธ ๋˜๋Š” ์—๋Ÿฌ UI ํ‘œ์‹œ)
Toast.makeText(requireContext(), loadState.message ?: "๋ฐ์ดํ„ฐ ๋กœ๋“œ์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.", Toast.LENGTH_SHORT).show()
}
}
}
}
}
}

private fun updateEmotionImages(selectedLevel: Int) {
// ๋ชจ๋“  ๊ฐ์ • ์ด๋ฏธ์ง€ ์—…๋ฐ์ดํŠธ
Expand Down Expand Up @@ -257,6 +299,11 @@ class DiaryWriteFragment : Fragment() {
repeatOnLifecycle(Lifecycle.State.STARTED) {
viewModel.saveResult.collectLatest { result ->
when (result) {
is DiaryWriteViewModel.SaveResult.Loading -> {
// ์ €์žฅ ์ค‘
binding.progressBar.visibility = View.VISIBLE
binding.btnSave.isEnabled = false
}
is DiaryWriteViewModel.SaveResult.Success -> {
// ์ €์žฅ ์„ฑ๊ณต -> ๊ฒฐ๊ณผ๋ฅผ ์ด์ „ ํ™”๋ฉด(DiaryFragment)์— ์ „๋‹ฌํ•˜๊ณ  ์ด๋™
val messages = result.toastMessages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import com.egobook.app.domain.model.diary.entity.DiarySummary
import com.egobook.app.domain.model.diary.entity.DiaryType
import com.egobook.app.domain.usecase.diaryusecase.DiaryUseCases
import com.egobook.app.ui.diary.mapper.DiaryEntityMapper
import com.egobook.app.util.UiState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.emptyFlow
import kotlinx.coroutines.launch
import java.time.LocalDate
import javax.inject.Inject

Expand Down Expand Up @@ -61,11 +61,15 @@ class DiariesViewModel @Inject constructor(
//์ƒํƒœ๋ฅผ ๋ณด์ง€ ๋ง๊ณ  ๋ทฐ๋ชจ๋ธ ๋‚ด๋ถ€ state ๊ธฐ๋ฐ˜์œผ๋กœ๋งŒ ๋™์ž‘
private fun loadDiaries(selectedDate: LocalDate, types: Set<DiaryType>?) {
val filter = DiaryFilter(selectedDate, types)

// ๋กœ๋”ฉ ์ƒํƒœ ์„ค์ •
_state.value = state.value.copy(diaries = UiState.Loading)

val diariesFlow = diaryUseCases
.getDiaries(filter)
.cachedIn(viewModelScope)

_state.value = state.value.copy(diaries = diariesFlow)
_state.value = state.value.copy(diaries = UiState.Success(diariesFlow))

// dailyCount๋„ ํ•จ๊ป˜ ๋กœ๋“œ
//loadDailyCount(selectedDate)
Expand Down Expand Up @@ -99,7 +103,7 @@ sealed class DiariesEvent {
}

data class DiariesState(
val diaries: Flow<PagingData<DiarySummary>> = emptyFlow(),
val diaries: UiState<Flow<PagingData<DiarySummary>>> = UiState.Idle,
val selectedTabType: Set<DiaryType>? = null,

// ๋‚ด๋ถ€ ๋กœ์ง์šฉ
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope
import com.egobook.app.domain.usecase.diaryusecase.DiaryUseCases
import com.egobook.app.ui.diary.mapper.DiaryEntityMapper
import com.egobook.app.ui.diary.model.ToastMessage
import com.egobook.app.util.UiState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.MutableStateFlow
Expand All @@ -16,7 +17,6 @@ import kotlinx.coroutines.launch
import java.time.LocalDate
import java.time.LocalDateTime
import javax.inject.Inject
import com.egobook.app.domain.model.diary.entity.DiaryRewards


@HiltViewModel
Expand Down Expand Up @@ -64,6 +64,9 @@ class DiaryWriteViewModel @Inject constructor(
*/
private fun loadDiaryForEdit() {
viewModelScope.launch {
// ๋กœ๋”ฉ ์ƒํƒœ ์„ค์ •
_contentState.value = _contentState.value.copy(diaryLoadState = UiState.Loading)

diaryUseCases.getDiary(diaryId)
.onSuccess { diary ->
if (diary != null) {
Expand All @@ -78,12 +81,20 @@ class DiaryWriteViewModel @Inject constructor(
selectedTypes = displayTypes,
selectedEmotionLevel = diary.emotionLevel ?: 3,
charCount = diary.content.length,
isSaveButtonEnabled = true
isSaveButtonEnabled = true,
diaryLoadState = UiState.Success(Unit)
)
} else {
_contentState.value = _contentState.value.copy(
diaryLoadState = UiState.Failure("์ผ๊ธฐ๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.")
)
}
}
.onFailure {
// ๋กœ๋“œ ์‹คํŒจ ์‹œ ์—๋Ÿฌ ์ฒ˜๋ฆฌ (ํ•„์š”์‹œ Toast ๋“ฑ์œผ๋กœ ์•Œ๋ฆผ)
.onFailure { error ->
// ๋กœ๋“œ ์‹คํŒจ ์‹œ ์—๋Ÿฌ ์ƒํƒœ ์„ค์ •
_contentState.value = _contentState.value.copy(
diaryLoadState = UiState.Failure(error.message)
)
}
}
}
Expand Down Expand Up @@ -160,6 +171,8 @@ class DiaryWriteViewModel @Inject constructor(
* ์ˆ˜์ • ๋ชจ๋“œ ์ €์žฅ ์ฒ˜๋ฆฌ
*/
private suspend fun saveEditMode(state: ContentState) {
_saveResult.emit(SaveResult.Loading)

val emotionLevel = if (state.selectedTypes.contains("๊ฐ์ •")) {
state.selectedEmotionLevel
} else {
Expand Down Expand Up @@ -191,6 +204,8 @@ class DiaryWriteViewModel @Inject constructor(
private suspend fun saveCreateMode(state: ContentState) {
val now = LocalDateTime.now()

_saveResult.emit(SaveResult.Loading)

val newDiary = DiaryEntityMapper.createNewDiary(
selectedTypes = state.selectedTypes,
content = state.content,
Expand All @@ -217,6 +232,7 @@ class DiaryWriteViewModel @Inject constructor(
}

sealed class SaveResult {
object Loading: SaveResult()
data class Success(val toastMessages: List<ToastMessage>) : SaveResult()
data class Error(val message: String?) : SaveResult()
}
Expand All @@ -237,7 +253,8 @@ class DiaryWriteViewModel @Inject constructor(
val isHintVisible: Boolean = false,
val charCount: Int = 0,
val maxCharCount: Int = 400,
val isSaveButtonEnabled: Boolean = false // ์ €์žฅ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” ์œ ๋ฌด
val isSaveButtonEnabled: Boolean = false, // ์ €์žฅ ๋ฒ„ํŠผ ํ™œ์„ฑํ™” ์œ ๋ฌด
val diaryLoadState: UiState<Unit> = UiState.Idle // ์ˆ˜์ • ๋ชจ๋“œ ๋ฐ์ดํ„ฐ ๋กœ๋“œ ์ƒํƒœ
)

}
Loading
Loading