diff --git a/android/app/src/main/java/com/now/naaga/presentation/adventureresult/AdventureResultActivity.kt b/android/app/src/main/java/com/now/naaga/presentation/adventureresult/AdventureResultActivity.kt index 7631fac5e..258636ac0 100644 --- a/android/app/src/main/java/com/now/naaga/presentation/adventureresult/AdventureResultActivity.kt +++ b/android/app/src/main/java/com/now/naaga/presentation/adventureresult/AdventureResultActivity.kt @@ -15,7 +15,6 @@ import com.now.naaga.data.firebase.analytics.AnalyticsDelegate import com.now.naaga.data.firebase.analytics.DefaultAnalyticsDelegate import com.now.naaga.data.firebase.analytics.RESULT_RESULT_RETURN import com.now.naaga.databinding.ActivityAdventureResultBinding -import com.now.naaga.presentation.beginadventure.BeginAdventureActivity class AdventureResultActivity : AppCompatActivity(), AnalyticsDelegate by DefaultAnalyticsDelegate() { private lateinit var binding: ActivityAdventureResultBinding @@ -91,7 +90,6 @@ class AdventureResultActivity : AppCompatActivity(), AnalyticsDelegate by Defaul private fun setClickListeners() { binding.btnAdventureResultReturn.setOnClickListener { logClickEvent(getViewEntryName(it), RESULT_RESULT_RETURN) - startActivity(BeginAdventureActivity.getIntent(this)) finish() } } diff --git a/android/app/src/main/java/com/now/naaga/presentation/beginadventure/BeginAdventureActivity.kt b/android/app/src/main/java/com/now/naaga/presentation/beginadventure/BeginAdventureActivity.kt index 2bb5f4bbc..6b42cffed 100644 --- a/android/app/src/main/java/com/now/naaga/presentation/beginadventure/BeginAdventureActivity.kt +++ b/android/app/src/main/java/com/now/naaga/presentation/beginadventure/BeginAdventureActivity.kt @@ -7,9 +7,12 @@ import android.content.pm.PackageManager import android.location.LocationManager import android.os.Bundle import android.provider.Settings +import android.view.View import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.ViewModelProvider +import com.now.domain.model.AdventureStatus import com.now.naaga.R import com.now.naaga.data.firebase.analytics.AnalyticsDelegate import com.now.naaga.data.firebase.analytics.BEGIN_BEGIN_ADVENTURE @@ -17,6 +20,7 @@ import com.now.naaga.data.firebase.analytics.BEGIN_GO_MYPAGE import com.now.naaga.data.firebase.analytics.BEGIN_GO_RANK import com.now.naaga.data.firebase.analytics.BEGIN_GO_UPLOAD import com.now.naaga.data.firebase.analytics.DefaultAnalyticsDelegate +import com.now.naaga.data.throwable.DataThrowable import com.now.naaga.databinding.ActivityBeginAdventureBinding import com.now.naaga.presentation.beginadventure.LocationPermissionDialog.Companion.TAG_LOCATION_DIALOG import com.now.naaga.presentation.mypage.MyPageActivity @@ -25,6 +29,13 @@ import com.now.naaga.presentation.rank.RankActivity class BeginAdventureActivity : AppCompatActivity(), AnalyticsDelegate by DefaultAnalyticsDelegate() { private lateinit var binding: ActivityBeginAdventureBinding + private lateinit var viewModel: BeginAdventureViewModel + + private val onAdventureActivityLauncher = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { _ -> + startLoading() + fetchInProgressAdventure() + } private val locationPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions -> @@ -49,9 +60,47 @@ class BeginAdventureActivity : AppCompatActivity(), AnalyticsDelegate by Default binding = ActivityBeginAdventureBinding.inflate(layoutInflater) setContentView(binding.root) + startLoading() registerAnalytics(this.lifecycle) + initViewModel() + fetchInProgressAdventure() requestLocationPermission() setClickListeners() + subscribe() + + binding.viewModel = viewModel + binding.lifecycleOwner = this + } + + private fun initViewModel() { + viewModel = ViewModelProvider(this, BeginAdventureViewModel.Factory)[BeginAdventureViewModel::class.java] + } + + private fun fetchInProgressAdventure() { + viewModel.fetchAdventure(AdventureStatus.IN_PROGRESS) + } + + private fun subscribe() { + viewModel.loading.observe(this) { loading -> + setLoadingView(loading) + } + viewModel.error.observe(this) { error: DataThrowable -> + Toast.makeText(this, error.message, Toast.LENGTH_SHORT).show() + } + } + + private fun setLoadingView(loading: Boolean) { + if (!loading) { + finishLoading() + } + } + + private fun startLoading() { + binding.lottieBeginAdventureLoading.visibility = View.VISIBLE + } + + private fun finishLoading() { + binding.lottieBeginAdventureLoading.visibility = View.GONE } private fun requestLocationPermission() { @@ -99,9 +148,17 @@ class BeginAdventureActivity : AppCompatActivity(), AnalyticsDelegate by Default startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)) Toast.makeText(this, GPS_TURN_ON_MESSAGE, Toast.LENGTH_SHORT).show() } else { - val intent = OnAdventureActivity.getIntent(this) - startActivity(intent) - finish() + onAdventureActivityLauncher.launch(getIntentWithAdventureOrWithout()) + } + } + + private fun getIntentWithAdventureOrWithout(): Intent { + val existingAdventure = viewModel.adventure.value + + return if (existingAdventure == null) { + OnAdventureActivity.getIntent(this) + } else { + OnAdventureActivity.getIntentWithAdventure(this, existingAdventure) } } diff --git a/android/app/src/main/java/com/now/naaga/presentation/beginadventure/BeginAdventureViewModel.kt b/android/app/src/main/java/com/now/naaga/presentation/beginadventure/BeginAdventureViewModel.kt new file mode 100644 index 000000000..1a43660f1 --- /dev/null +++ b/android/app/src/main/java/com/now/naaga/presentation/beginadventure/BeginAdventureViewModel.kt @@ -0,0 +1,48 @@ +package com.now.naaga.presentation.beginadventure + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.now.domain.model.Adventure +import com.now.domain.model.AdventureStatus +import com.now.domain.repository.AdventureRepository +import com.now.naaga.data.repository.DefaultAdventureRepository +import com.now.naaga.data.throwable.DataThrowable + +class BeginAdventureViewModel(private val adventureRepository: AdventureRepository) : ViewModel() { + private val _adventure = MutableLiveData() + val adventure: LiveData = _adventure + + private val _error = MutableLiveData() + val error: LiveData = _error + + private val _loading = MutableLiveData(false) + val loading: LiveData = _loading + + fun fetchAdventure(adventureStatus: AdventureStatus) { + _loading.value = true + adventureRepository.fetchAdventureByStatus(adventureStatus) { result -> + _loading.value = false + result + .onSuccess { + _adventure.value = it.firstOrNull() + } + .onFailure { + _error.value = it as DataThrowable + } + } + } + + companion object { + val Factory = BeginAdventureViewModelFactory(DefaultAdventureRepository()) + + class BeginAdventureViewModelFactory( + private val adventureRepository: AdventureRepository, + ) : ViewModelProvider.Factory { + override fun create(modelClass: Class): T { + return BeginAdventureViewModel(adventureRepository) as T + } + } + } +} diff --git a/android/app/src/main/res/anim/anim_skeleton.xml b/android/app/src/main/res/anim/anim_skeleton.xml new file mode 100644 index 000000000..9c1e401b5 --- /dev/null +++ b/android/app/src/main/res/anim/anim_skeleton.xml @@ -0,0 +1,12 @@ + + + + + + diff --git a/android/app/src/main/res/layout/activity_begin_adventure.xml b/android/app/src/main/res/layout/activity_begin_adventure.xml index 84b31e784..33b1008db 100644 --- a/android/app/src/main/res/layout/activity_begin_adventure.xml +++ b/android/app/src/main/res/layout/activity_begin_adventure.xml @@ -4,11 +4,28 @@ xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools"> + + + + + + + diff --git a/android/app/src/main/res/layout/skeleton_begin_adventure.xml b/android/app/src/main/res/layout/skeleton_begin_adventure.xml new file mode 100644 index 000000000..cc9e10f8b --- /dev/null +++ b/android/app/src/main/res/layout/skeleton_begin_adventure.xml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/raw/simple_loading.json b/android/app/src/main/res/raw/simple_loading.json new file mode 100644 index 000000000..225cb905d --- /dev/null +++ b/android/app/src/main/res/raw/simple_loading.json @@ -0,0 +1 @@ +{"v":"5.8.1","fr":30,"ip":0,"op":60,"w":300,"h":300,"nm":"loading_6","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 2","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":60,"s":[360]}],"ix":10},"p":{"a":0,"k":[150.00000000000003,150.00000000000003,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[30.000000000000004,30.000000000000004,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.22745098039215686,0.6627450980392157,0.8627450980392157,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":2,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"tm","s":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":10,"s":[0]},{"t":60,"s":[99]}],"ix":1},"e":{"a":1,"k":[{"i":{"x":[0.667],"y":[1]},"o":{"x":[0.333],"y":[0]},"t":0,"s":[1]},{"t":50,"s":[100]}],"ix":2},"o":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0]},{"t":60,"s":[3]}],"ix":3},"m":1,"ix":2,"nm":"Trim Paths 1","mn":"ADBE Vector Filter - Trim","hd":false}],"ip":0,"op":300,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"Shape Layer 1","sr":1,"ks":{"o":{"a":0,"k":30,"ix":11},"r":{"a":0,"k":0,"ix":10},"p":{"a":0,"k":[150.00000000000003,150.00000000000003,0],"ix":2,"l":2},"a":{"a":0,"k":[0,0,0],"ix":1,"l":2},"s":{"a":0,"k":[30.000000000000004,30.000000000000004,100],"ix":6,"l":2}},"ao":0,"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"a":0,"k":[300,300],"ix":2},"p":{"a":0,"k":[0,0],"ix":3},"nm":"Ellipse Path 1","mn":"ADBE Vector Shape - Ellipse","hd":false},{"ty":"st","c":{"a":0,"k":[0.6666666666666666,0.8431372549019608,0.9215686274509803,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":50,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"Stroke 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[0,0],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"Transform"}],"nm":"Ellipse 1","np":3,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":300,"st":0,"bm":0}],"markers":[]} \ No newline at end of file diff --git a/android/app/src/main/res/raw/animation_ll5gzgdu.json b/android/app/src/main/res/raw/walking_loading.json similarity index 100% rename from android/app/src/main/res/raw/animation_ll5gzgdu.json rename to android/app/src/main/res/raw/walking_loading.json diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 1e43db626..9778eacf8 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -7,6 +7,7 @@ 대략적인 위치 권한만 허용되었습니다 위치 권한 요청이 거절되었습니다 아직 준비되지 않은 기능입니다. + 모험 하기 이어 하기 diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index 12d9f8f05..9c48f80ce 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -9,4 +9,10 @@ @color/main_purple 6dp + +