diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 373e249..bbd44e1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,6 +16,10 @@ android:supportsRtl="true" android:theme="@style/Theme.Comus" tools:targetApi="31"> + + + @@ -39,12 +43,13 @@ android:name=".MainActivity" android:exported="true" android:label="@string/app_name" > - + + diff --git a/app/src/main/java/com/example/com_us/ui/home/HomeFragment.kt b/app/src/main/java/com/example/com_us/ui/home/HomeFragment.kt index 95b146b..145b3e2 100644 --- a/app/src/main/java/com/example/com_us/ui/home/HomeFragment.kt +++ b/app/src/main/java/com/example/com_us/ui/home/HomeFragment.kt @@ -6,9 +6,13 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.view.ViewTreeObserver +import android.widget.Toast import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels +import androidx.lifecycle.Lifecycle import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle import com.bumptech.glide.Glide import com.bumptech.glide.load.resource.bitmap.RoundedCorners import com.bumptech.glide.request.RequestOptions @@ -16,14 +20,16 @@ import com.example.com_us.R import com.example.com_us.data.model.home.Block import com.example.com_us.data.model.home.Category import com.example.com_us.databinding.FragmentHomeBinding +import com.example.com_us.ui.ApiResult import com.example.com_us.ui.question.theme.ThemeQuestionListActivity import com.example.com_us.util.ColorMatch import com.example.com_us.util.ServerResponseHandler import com.example.com_us.util.ThemeType import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch @AndroidEntryPoint -class HomeFragment : Fragment(), View.OnClickListener, ServerResponseHandler { +class HomeFragment : Fragment(), View.OnClickListener { private lateinit var blockList: List> @@ -55,9 +61,6 @@ class HomeFragment : Fragment(), View.OnClickListener, ServerResponseHandler { listOf(binding.viewHomeBlock30, binding.viewHomeBlock31, binding.viewHomeBlock32, binding.viewHomeBlock33), ) - homeViewModel.serverResponseHandler = this - homeViewModel.loadHomeData() - setSwipeRefresh() setThemeClickListener() setHomeData() @@ -91,19 +94,41 @@ class HomeFragment : Fragment(), View.OnClickListener, ServerResponseHandler { private fun setHomeData() { val emojiText = String(Character.toChars(resources.getInteger(R.integer.waving_hand_sign))) - homeViewModel.homeData.observe(viewLifecycleOwner) { - val chatMinute = it.user.todayChatTime.substring(3, 5).toInt() - binding.textviewHomeGreeting.text = String.format(resources.getString(R.string.home_title_greeting_user_hi), it.user.name, emojiText) - binding.textviewHomeMinute.text = String.format(resources.getString(R.string.home_sub_today_conversation_minute), chatMinute) - Glide.with(this) - .load(it.user.imageUrl) - .apply(RequestOptions().transform(RoundedCorners(300))) - .into(binding.imageviewHomeUsericon) - - setThemeProgress(it.category) - setBlock(it.block) - isReload.value = true + viewLifecycleOwner.lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + homeViewModel.homeUiState.collect { + when (it) { + is ApiResult.Success -> { + binding.constraintHome.visibility = View.VISIBLE + val chatMinute = it.data.user.todayChatTime.substring(3, 5).toInt() + binding.textviewHomeGreeting.text = String.format( + resources.getString(R.string.home_title_greeting_user_hi), + it.data.user.name, + emojiText + ) + binding.textviewHomeMinute.text = String.format( + resources.getString(R.string.home_sub_today_conversation_minute), + chatMinute + ) + Glide.with(this@HomeFragment) + .load(it.data.user.imageUrl) + .apply(RequestOptions().transform(RoundedCorners(300))) + .into(binding.imageviewHomeUsericon) + + setThemeProgress(it.data.category) + setBlock(it.data.block) + isReload.value = true + + } + is ApiResult.Error -> { + Toast.makeText(context,"잠시 후에 다시 시도해주세요!",Toast.LENGTH_SHORT).show() + } + else -> {} + } + } + } } + } override fun onClick(view: View) { @@ -190,10 +215,4 @@ class HomeFragment : Fragment(), View.OnClickListener, ServerResponseHandler { _binding = null } - override fun onServerSuccess() { - binding.constraintHome.visibility = View.VISIBLE - } - - override fun onServerFailure() { - } } diff --git a/app/src/main/java/com/example/com_us/ui/home/HomeViewModel.kt b/app/src/main/java/com/example/com_us/ui/home/HomeViewModel.kt index e6ba048..a68b046 100644 --- a/app/src/main/java/com/example/com_us/ui/home/HomeViewModel.kt +++ b/app/src/main/java/com/example/com_us/ui/home/HomeViewModel.kt @@ -5,30 +5,41 @@ import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.example.com_us.data.default_repository.NetworkError import com.example.com_us.data.repository.HomeRepository import com.example.com_us.data.model.home.ResponseHomeDataDto +import com.example.com_us.ui.ApiResult import com.example.com_us.util.ServerResponseHandler import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import javax.inject.Inject @HiltViewModel class HomeViewModel @Inject constructor(private val homeRepository: HomeRepository) : ViewModel() { - private val _homeData = MutableLiveData() - val homeData: LiveData = _homeData + private val _homeUiState= MutableStateFlow>(ApiResult.Initial) + val homeUiState = _homeUiState.asStateFlow() var serverResponseHandler: ServerResponseHandler? = null + init { + loadHomeData() + } + fun loadHomeData(){ viewModelScope.launch { homeRepository.getHomeData() .onSuccess { - _homeData.value = it - serverResponseHandler?.onServerSuccess() + _homeUiState.value = ApiResult.Success(it) } .onFailure { - Log.d("GET: [HOME DATA] DATA FAILURE", it.toString()) - serverResponseHandler?.onServerFailure() + val errorMessage = when(it) { + is NetworkError.NetworkException -> { it.message } + is NetworkError.NullDataError -> { "데이터가 준비중이에요!" } + else -> "알 수 없는 에러가 발생했습니다. 다시 시도해주세요!" + } + if (errorMessage!= null ) _homeUiState.value = ApiResult.Error(errorMessage) } } } diff --git a/app/src/main/java/com/example/com_us/ui/login/LoginActivity.kt b/app/src/main/java/com/example/com_us/ui/login/LoginActivity.kt new file mode 100644 index 0000000..1cf1f4b --- /dev/null +++ b/app/src/main/java/com/example/com_us/ui/login/LoginActivity.kt @@ -0,0 +1,19 @@ +package com.example.com_us.ui.login + +import android.os.Bundle +import androidx.appcompat.app.AppCompatActivity +import com.example.com_us.databinding.ActivityLoginBinding +import com.example.com_us.databinding.ActivityQuestionCheckAnswerBinding +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class LoginActivity : AppCompatActivity() { + + private lateinit var binding: ActivityLoginBinding + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = ActivityLoginBinding.inflate(layoutInflater) + setContentView(binding.root) + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/com_us/ui/question/list/AllQuestionListFragment.kt b/app/src/main/java/com/example/com_us/ui/question/list/AllQuestionListFragment.kt index f3cbe63..ca67618 100644 --- a/app/src/main/java/com/example/com_us/ui/question/list/AllQuestionListFragment.kt +++ b/app/src/main/java/com/example/com_us/ui/question/list/AllQuestionListFragment.kt @@ -97,10 +97,11 @@ class AllQuestionListFragment : Fragment(), View.OnClickListener { } } } - else -> { + is ApiResult.Error -> { binding.constraintQuestion.visibility = View.GONE Toast.makeText(context, it.toString(), Toast.LENGTH_SHORT).show() } + else -> {} } } } diff --git a/app/src/main/java/com/example/com_us/ui/question/result/ResultBeforeSignActivity.kt b/app/src/main/java/com/example/com_us/ui/question/result/ResultBeforeSignActivity.kt index 89296fb..8be505e 100644 --- a/app/src/main/java/com/example/com_us/ui/question/result/ResultBeforeSignActivity.kt +++ b/app/src/main/java/com/example/com_us/ui/question/result/ResultBeforeSignActivity.kt @@ -1,19 +1,24 @@ package com.example.com_us.ui.question.result -import android.content.Intent import android.net.Uri import android.os.Bundle import android.view.MenuItem import android.view.View +import android.widget.Toast import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.Lifecycle import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.lifecycleScope +import androidx.lifecycle.repeatOnLifecycle import com.example.com_us.R import com.example.com_us.data.model.question.response.question.ResponseAnswerDetailDto import com.example.com_us.databinding.ActivityQuestionCheckAnswerBinding +import com.example.com_us.ui.ApiResult import com.example.com_us.ui.question.sign.SignAnswerDialog import com.example.com_us.util.QuestionManager import dagger.hilt.android.AndroidEntryPoint +import kotlinx.coroutines.launch // 답변 선택 시 처음으로 이동하는 화면 (질문, 답변 , 수형 영상, 따라해보기 버튼) @AndroidEntryPoint @@ -37,7 +42,7 @@ class ResultBeforeSignActivity : AppCompatActivity(){ question = intent.getStringExtra("question").toString() category = intent.getStringExtra("category").toString() - if(!answer.isNullOrEmpty()){ + if (!answer.isNullOrEmpty()) { QuestionManager.question = question viewModel.loadAnswerDetail(answer) } @@ -46,16 +51,29 @@ class ResultBeforeSignActivity : AppCompatActivity(){ setContentView(binding.root) setActionBar() - viewModel.answerDetail.observe(this) { - if(!it.isNullOrEmpty()){ - QuestionManager.signLanguageInfo = it - signData = it - setAnswerDetail() - binding.buttonAnswerFollowalong.setOnClickListener { - moveToFollowAlongDialog() + + lifecycleScope.launch { + repeatOnLifecycle(Lifecycle.State.STARTED) { + viewModel.answerDetail.collect { + when (it) { + is ApiResult.Success -> { + QuestionManager.signLanguageInfo = it.data + signData = it.data + setAnswerDetail() + binding.buttonAnswerFollowalong.setOnClickListener { + moveToFollowAlongDialog() + } + } + + is ApiResult.Error -> { + Toast.makeText(this@ResultBeforeSignActivity, it.toString(), Toast.LENGTH_SHORT).show() + } + else -> {} + } } } } + } private fun setActionBar() { @@ -109,11 +127,23 @@ class ResultBeforeSignActivity : AppCompatActivity(){ videoPlayCount.value = -1 viewModel.answerDetail.value - val dialog = viewModel.answerDetail.value?.let { - SignAnswerDialog.newInstance(question, answer, category, - it - ) + viewModel.answerDetail.value.let { + when(it) { + is ApiResult.Success -> { + val dialog = + SignAnswerDialog.newInstance(question, answer, category, + it.data + ) + dialog.isCancelable = false + dialog.show(supportFragmentManager, "FollowAlongDialog") + + } + else -> { + Toast.makeText(this , "잠시 후에 다시 시도해주세요",Toast.LENGTH_SHORT).show() + } + } } + print(viewModel.answerDetail.value) // 다이얼로그가 뜨면 아래 내용 질문만 희미하게 보이게 하기 @@ -123,9 +153,7 @@ class ResultBeforeSignActivity : AppCompatActivity(){ binding.textviewAnswerDescrp.visibility = View.GONE binding.buttonAnswerFollowalong.visibility = View.GONE binding.videoviewAnswerSign.visibility = View.GONE - dialog?.isCancelable = false - dialog?.show(supportFragmentManager, "FollowAlongDialog") } diff --git a/app/src/main/java/com/example/com_us/ui/question/result/ResultViewModel.kt b/app/src/main/java/com/example/com_us/ui/question/result/ResultViewModel.kt index 5e8ba86..28a5628 100644 --- a/app/src/main/java/com/example/com_us/ui/question/result/ResultViewModel.kt +++ b/app/src/main/java/com/example/com_us/ui/question/result/ResultViewModel.kt @@ -1,13 +1,17 @@ package com.example.com_us.ui.question.result import android.util.Log +import androidx.compose.runtime.MutableState import androidx.lifecycle.LiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.example.com_us.data.model.question.response.question.ResponseAnswerDetailDto import com.example.com_us.data.repository.QuestionRepository +import com.example.com_us.ui.ApiResult import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.launch import javax.inject.Inject @@ -16,15 +20,15 @@ class ResultViewModel @Inject constructor( private val questionRepository : QuestionRepository ) : ViewModel() { - private val _answerDetail = MutableLiveData>() - val answerDetail: LiveData> = _answerDetail + private val _answerDetail = MutableStateFlow>>(ApiResult.Initial) + val answerDetail =_answerDetail.asStateFlow() fun loadAnswerDetail(answer: String){ viewModelScope.launch { questionRepository.getAnswerDetail(answer) .onSuccess { - _answerDetail.value = it + _answerDetail.value = ApiResult.Success(it) } .onFailure { Log.d("GET: [ANSWER DETAIL]", it.toString()) diff --git a/app/src/main/java/com/example/com_us/ui/question/theme/ThemeQuestionListActivity.kt b/app/src/main/java/com/example/com_us/ui/question/theme/ThemeQuestionListActivity.kt index ae75a59..e658874 100644 --- a/app/src/main/java/com/example/com_us/ui/question/theme/ThemeQuestionListActivity.kt +++ b/app/src/main/java/com/example/com_us/ui/question/theme/ThemeQuestionListActivity.kt @@ -60,9 +60,10 @@ class ThemeQuestionListActivity : AppCompatActivity() { } } } - else -> { + is ApiResult.Error -> { Toast.makeText(this@ThemeQuestionListActivity,it.toString(),Toast.LENGTH_SHORT).show() } + else -> {} } } } diff --git a/app/src/main/res/drawable/btn_google_login.png b/app/src/main/res/drawable/btn_google_login.png new file mode 100644 index 0000000..4f15111 Binary files /dev/null and b/app/src/main/res/drawable/btn_google_login.png differ diff --git a/app/src/main/res/drawable/ic_logo.xml b/app/src/main/res/drawable/ic_logo.xml new file mode 100644 index 0000000..862d47d --- /dev/null +++ b/app/src/main/res/drawable/ic_logo.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/layout/activity_login.xml b/app/src/main/res/layout/activity_login.xml new file mode 100644 index 0000000..281f59d --- /dev/null +++ b/app/src/main/res/layout/activity_login.xml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + \ No newline at end of file