Skip to content

Commit

Permalink
Merge pull request #80 from Hyesung82/feature/location
Browse files Browse the repository at this point in the history
[develop] 위치 선택 화면 코드 보완
  • Loading branch information
Hyesung82 authored Mar 17, 2024
2 parents a17af5f + 8b93e70 commit 4eab078
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 103 deletions.
1 change: 1 addition & 0 deletions presentation/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ plugins {
id 'com.google.android.libraries.mapsplatform.secrets-gradle-plugin'
id 'dagger.hilt.android.plugin'
id 'androidx.navigation.safeargs.kotlin'
id 'kotlin-parcelize'
}

Properties properties = new Properties()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package com.cheocharm.presentation.model

import android.net.Uri
import android.os.Parcelable
import com.google.android.gms.maps.model.LatLng
import kotlinx.parcelize.IgnoredOnParcel
import kotlinx.parcelize.Parcelize

data class Picture(val uri: Uri, val latLng: LatLng?) {
@Parcelize
data class Picture(val uri: Uri, val latLng: LatLng?): Parcelable {
@IgnoredOnParcel
var address: String? = null
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ import android.widget.Toast
import androidx.core.content.ContextCompat
import androidx.core.view.MenuHost
import androidx.core.view.MenuProvider
import androidx.hilt.navigation.fragment.hiltNavGraphViewModels
import androidx.lifecycle.Lifecycle
import androidx.navigation.fragment.findNavController
import androidx.navigation.navGraphViewModels
import com.cheocharm.presentation.R
import com.cheocharm.presentation.base.BaseFragment
import com.cheocharm.presentation.common.DEFAULT_ZOOM_LEVEL
Expand All @@ -38,14 +38,12 @@ import com.google.android.gms.maps.model.LatLng
import com.google.android.gms.maps.model.Marker
import com.google.android.gms.maps.model.MarkerOptions
import dagger.hilt.android.AndroidEntryPoint
import kotlinx.coroutines.Dispatchers
import java.io.File

@AndroidEntryPoint
class LocationFragment : BaseFragment<FragmentLocationBinding>(R.layout.fragment_location),
MenuProvider {
private val locationViewModel by navGraphViewModels<LocationViewModel>(R.id.write) { defaultViewModelProviderFactory }
private val writeViewModel by navGraphViewModels<WriteViewModel>(R.id.write) { defaultViewModelProviderFactory }
private val locationViewModel: LocationViewModel by hiltNavGraphViewModels(R.id.write)
private val writeViewModel: WriteViewModel by hiltNavGraphViewModels(R.id.write)

private lateinit var map: GoogleMap
private lateinit var geocodeUtil: GeocodeUtil
Expand All @@ -56,14 +54,11 @@ class LocationFragment : BaseFragment<FragmentLocationBinding>(R.layout.fragment
private var draggableMarker: Marker? = null
private var address: String? = null
private var location: LatLng? = null
private var file: File? = null

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

geocodeUtil = GeocodeUtil(requireContext(), Dispatchers.IO)

setHasOptionsMenu(true)
geocodeUtil = GeocodeUtil(requireContext())
}

override fun onCreateView(
Expand Down Expand Up @@ -92,32 +87,40 @@ class LocationFragment : BaseFragment<FragmentLocationBinding>(R.layout.fragment
mainActivity.setSupportActionBar(this)
setNavigationIcon(R.drawable.ic_back)
setNavigationOnClickListener {
mainActivity.onBackPressed()
mainActivity.onBackPressedDispatcher.onBackPressed()
}
}

if (savedInstanceState != null) {
with(savedInstanceState) {
val uri = getString(KEY_URI)
val lat = getString(KEY_LAT)?.toDoubleOrNull()
val lng = getString(KEY_LNG)?.toDoubleOrNull()
val isDefaultLocation = getBoolean(KEY_IS_DEFAULT_LOCATION)

if (uri != null) {
val latLng = if (lat != null && lng != null) LatLng(lat, lng) else null
val picture = Picture(Uri.parse(uri), latLng)

locationViewModel.loadPicture(listOf(picture), geocodeUtil)
}

if (isDefaultLocation) {
val typeDefault = LatLngSelectionType.DEFAULT
initialType = typeDefault
locationViewModel.setSelectedLatLng(defaultLatLng.toDoubleArray(), typeDefault)
}
locationViewModel.isDefaultLocationLiveData.observe(viewLifecycleOwner) {
if (it) {
val typeDefault = LatLngSelectionType.DEFAULT
initialType = typeDefault
locationViewModel.setSelectedLatLng(defaultLatLng.toDoubleArray(), typeDefault)
}
}

// if (savedInstanceState != null) {
// with(savedInstanceState) {
// val uri = getString(KEY_URI)
// val lat = getString(KEY_LAT)?.toDoubleOrNull()
// val lng = getString(KEY_LNG)?.toDoubleOrNull()
// val isDefaultLocation = getBoolean(KEY_IS_DEFAULT_LOCATION)
//
// if (uri != null) {
// val latLng = if (lat != null && lng != null) LatLng(lat, lng) else null
// val picture = Picture(Uri.parse(uri), latLng)
//
// locationViewModel.loadPicture(listOf(picture), geocodeUtil)
// }
//
// if (isDefaultLocation) {
// val typeDefault = LatLngSelectionType.DEFAULT
// initialType = typeDefault
// locationViewModel.setSelectedLatLng(defaultLatLng.toDoubleArray(), typeDefault)
// }
// }
// }

setupMap(mainActivity, picturesAdapter)
setupToast()
setupNavigation()
Expand Down Expand Up @@ -275,16 +278,12 @@ class LocationFragment : BaseFragment<FragmentLocationBinding>(R.layout.fragment
override fun onMenuItemSelected(menuItem: MenuItem): Boolean {
return when (menuItem.itemId) {
R.id.menu_base_confirm -> {
// TODO: file을 여기서 초기화하면 전역변수로 두지 않아도 될듯
file?.let {
locationViewModel.uploadImages(
TEST_GROUP_ID,
address,
location?.latitude,
location?.longitude,
listOf(it)
)
}
locationViewModel.confirmLocation(
TEST_GROUP_ID,
address,
location?.latitude,
location?.longitude
)

true
}
Expand All @@ -293,24 +292,10 @@ class LocationFragment : BaseFragment<FragmentLocationBinding>(R.layout.fragment
}

override fun onSaveInstanceState(outState: Bundle) {
// TODO: savedStateHandle 사용
val pictures = locationViewModel.pictures.value
val picture = pictures?.get(0)

if (picture != null) {
with(outState) {
putString(KEY_URI, picture.uri.toString())

if (picture.latLng != null) {
putString(KEY_LAT, picture.latLng.latitude.toString())
putString(KEY_LNG, picture.latLng.longitude.toString())
}
val latLng = map.cameraPosition.target
val isDefaultLocation = distanceBetween(defaultLatLng, latLng) <= 1

val latLng = map.cameraPosition.target
val isDefaultLocation = distanceBetween(defaultLatLng, latLng) <= 1
putBoolean(KEY_IS_DEFAULT_LOCATION, isDefaultLocation)
}
}
locationViewModel.saveIsDefaultLocation(isDefaultLocation)

super.onSaveInstanceState(outState)
}
Expand All @@ -326,11 +311,6 @@ class LocationFragment : BaseFragment<FragmentLocationBinding>(R.layout.fragment

companion object {
private val defaultLatLng = LatLng(SOUTH_KOREA_LAT, SOUTH_KOREA_LNG)

private const val KEY_URI = "uri"
private const val KEY_LAT = "lat"
private const val KEY_LNG = "lng"
private const val KEY_IS_DEFAULT_LOCATION = "isDefaultLocation"
private const val TEST_GROUP_ID = 1L
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ package com.cheocharm.presentation.ui.write.location
import android.os.Build
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.cheocharm.domain.model.TempDiary
import com.cheocharm.domain.model.WriteImageRequest
import com.cheocharm.domain.usecase.write.RequestWriteImagesUseCase
import com.cheocharm.presentation.common.Event
import com.cheocharm.presentation.common.TestValues
Expand All @@ -15,14 +15,23 @@ import com.cheocharm.presentation.model.Picture
import com.cheocharm.presentation.model.Sticker
import com.cheocharm.presentation.util.GeocodeUtil
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.File
import javax.inject.Inject

@HiltViewModel
class LocationViewModel @Inject constructor(
private val handle: SavedStateHandle,
private val requestWriteImagesUseCase: RequestWriteImagesUseCase
) : ViewModel() {
private var isDefaultLocation = handle.get<Boolean>(KEY_IS_DEFAULT_LOCATION) ?: false
set(value) {
handle[KEY_IS_DEFAULT_LOCATION] = value
field = value
}
val isDefaultLocationLiveData: LiveData<Boolean> = handle.getLiveData(KEY_IS_DEFAULT_LOCATION, false)

private val _toastText = MutableLiveData<Event<String>>()
val toastText: LiveData<Event<String>> = _toastText

Expand All @@ -32,33 +41,27 @@ class LocationViewModel @Inject constructor(
var stickers: List<Sticker> = TestValues.testStickers
private set

private val _pictures = MutableLiveData<List<Picture>>()
private val _pictures: MutableLiveData<List<Picture>> = handle.getLiveData(KEY_PICTURES)
val pictures: LiveData<List<Picture>> = _pictures

private val _locationString = MutableLiveData<String>()
val locationString: LiveData<String> = _locationString

fun saveIsDefaultLocation(boolean: Boolean) {
isDefaultLocation = boolean
}

fun loadPicture(pictures: List<Picture>, geocodeUtil: GeocodeUtil) {
_pictures.value = pictures
handle[KEY_PICTURES] = pictures

// TODO: 모든 사진에 대해 지오코딩
val pic = pictures[0]

if (pic.address == null) {
viewModelScope.launch {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
geocodeUtil.execute(pic) {
_pictures.value?.get(0)?.address = it[0].getAddressLine(0)
}
} else {
geocodeUtil.execute(pic)
}
}
viewModelScope.launch(Dispatchers.IO) {
geocodeUtil.execute(pictures[0])
}
}

fun geocode(geocodeUtil: GeocodeUtil, latLng: DoubleArray, type: LatLngSelectionType) {
viewModelScope.launch {
viewModelScope.launch(Dispatchers.IO) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
geocodeUtil.execute(latLng, type, ::setSelectedLatLng) {
_locationString.postValue(
Expand Down Expand Up @@ -93,35 +96,45 @@ class LocationViewModel @Inject constructor(
return "($lat, $lng)"
}

fun uploadImages(
fun confirmLocation(
groupId: Long,
address: String?,
lat: Double?,
lng: Double?,
images: List<File>
lng: Double?
) {
viewModelScope.launch {
// 테스트
// _toastText.value = Event("TEST: 이미지 업로드 실패")
// _locationSelectedEvent.value = Event(TempDiary(38, TestValues.testImages))

requestWriteImagesUseCase.invoke(
WriteImageRequest(
groupId,
address ?: TEST_ADDRESS,
lat ?: TEST_LAT,
lng ?: TEST_LNG,
images
)
).onSuccess {
_locationSelectedEvent.value = Event(it)
}.onFailure {
_toastText.value = Event(it.message ?: "")
}
viewModelScope.launch(Dispatchers.IO) {
val images = getFiles() ?: return@launch

// requestWriteImagesUseCase.invoke(
// WriteImageRequest(
// groupId,
// address ?: TEST_ADDRESS,
// lat ?: TEST_LAT,
// lng ?: TEST_LNG,
// images
// )
// ).onSuccess {
// _locationSelectedEvent.postValue(Event(it))
// }.onFailure {
// _toastText.postValue(Event(it.message ?: ""))
// }

_locationSelectedEvent.postValue(Event(TempDiary(0, listOf())))
}
}

private fun getFiles(): List<File> ?{
val pictures = pictures.value

return pictures?.map {
File(it.uri.toString())
}
}

companion object {
private const val KEY_PICTURES = "pictures"
private const val KEY_IS_DEFAULT_LOCATION = "isDefaultLocation"

// TODO: 기본 위치 설정
private const val TEST_LAT = 0.0
private const val TEST_LNG = 0.0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ import com.cheocharm.presentation.ui.MainActivity
import com.cheocharm.presentation.util.GeocodeUtil
import com.google.android.gms.maps.model.LatLng
import com.google.android.material.snackbar.Snackbar
import kotlinx.coroutines.Dispatchers

class PictureFragment : BaseFragment<FragmentPictureBinding>(R.layout.fragment_picture) {
private val locationViewModel: LocationViewModel by hiltNavGraphViewModels(R.id.write)
Expand All @@ -52,7 +51,7 @@ class PictureFragment : BaseFragment<FragmentPictureBinding>(R.layout.fragment_p
if (it.resultCode == Activity.RESULT_OK) {
val pictures = mutableListOf<Picture>()
val clipData = it?.data?.clipData
val geocodeUtil = GeocodeUtil(requireContext(), Dispatchers.IO)
val geocodeUtil = GeocodeUtil(requireContext())

if (clipData == null) {
val uri = it?.data?.data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ import com.cheocharm.presentation.model.Picture
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.util.*
import java.util.Locale

class GeocodeUtil(
context: Context,
private val coroutineDispatcher: CoroutineDispatcher
private val coroutineDispatcher: CoroutineDispatcher = Dispatchers.IO
) {
private val geocoder = Geocoder(context, Locale.KOREAN)

Expand Down

0 comments on commit 4eab078

Please sign in to comment.