Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
0bab7a3
#211 [chore] ResponseReverseGeocodingDto 추가
unam98 Sep 2, 2023
5b9d210
#211 [UI] 출발지 설정 카드뷰 생성
unam98 Sep 2, 2023
1aea96d
#211 [chore] ReverseGeocodingService 생성
unam98 Sep 6, 2023
8a198e6
#211 [chore] ServiceModule 추가
unam98 Sep 6, 2023
fc479ee
#211 [chore] DataSource 추가
unam98 Sep 6, 2023
fbe0e35
#211 [chore] RepositoryModule 추가
unam98 Sep 7, 2023
a37f3dd
#211 [chore] data class에 현위치, 지도에서 출발을 구분하기 위한 식별자 추가
unam98 Sep 7, 2023
2c8aab1
#211 [chore] 좌표로 response 받아온 것을 custom하게 활용하기 위한 data class 추가
unam98 Sep 7, 2023
a238bf9
#211 [chore] DrawViewModel에 좌표로 주소값 요청하는 통신 logic 추가
unam98 Sep 7, 2023
0b1f050
#211 [UI] xml에 직접 출발지 설정 마커 추가
unam98 Sep 7, 2023
6e87132
#211 [fix] 소셜 로그인 버튼 dp -> sp 수정
unam98 Sep 7, 2023
57a8642
#211 [feat] SearchActivity에 '현위치 출발', '직접 설정'에 대한 ClickListener 추가
unam98 Sep 7, 2023
347c3a1
#211 [chore] 출발지 검색 EditText hint 문구 수정
unam98 Sep 7, 2023
a69e2a9
#211 [feat] 출발지를 설정하는 3개 mode에 대한 코드 setting (코루틴 적용 전)
unam98 Sep 7, 2023
8cf9bfc
#211 [feat] 직접 출발지 설정 기능 구현 완료
unam98 Sep 7, 2023
973c9e8
#211 [chore] buildingName empty 시 대체 문구 설정 ("내가 설정한 출발지")
unam98 Sep 16, 2023
f33f2e6
#211 [ui] 코스 이름 입력 받는 BottomSheet 생성
unam98 Sep 20, 2023
da75492
#211 [chore] reverseGeoCoding 관련 함수 및 변수명 수정
unam98 Sep 20, 2023
baf7e2f
#211 [feat] 커스텀 출발지 설정 data 연결 완료
unam98 Sep 20, 2023
927a1e7
#211 [MOD] 마커 앵커 PointF(0.5f, 0.7f) -> PoinF(0.5f, 0.5f))
unam98 Sep 24, 2023
1ad5a21
#211 [ADD] InfoWindow drawble 추가, layout 생성
unam98 Sep 24, 2023
e7aee9b
#211 [UI] xml에 InfoWindow imageView 추가
unam98 Sep 24, 2023
6904b7d
#211 [FEAT] 사용자 지정 출발지에서 코스 그리기 구현
unam98 Sep 24, 2023
876f3e8
#211 [MOD] 출발지 설정(현위치, 장소 검색) 코스 생성 전
unam98 Sep 25, 2023
169e2e5
#211 [MOD] 출발지 설정 3개 mode 구현 완료
unam98 Sep 25, 2023
1fe80ab
#211 [CHORE] 코드 간결화 (함수명 변경, 중복 코드 제거 등)
unam98 Sep 26, 2023
bcc473e
#211 [MOD] 현위치 출발 순서 맞추기
unam98 Sep 28, 2023
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
12 changes: 12 additions & 0 deletions app/src/debug/res/drawable/draw_require_coure_name_border.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<corners
android:radius="10dp">
</corners>
<solid
android:color="@color/W1">
</solid>
<stroke
android:color="@color/M1"
android:width="1dp" />
</shape>
16 changes: 16 additions & 0 deletions app/src/debug/res/drawable/ic_current_location.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M8,8m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
android:fillColor="#C1C1C1"/>
<group>
<clip-path
android:pathData="M3.2,3.2h9.6v9.6h-9.6z"/>
<path
android:pathData="M8.668,12H8.644C8.556,11.995 8.472,11.961 8.406,11.903C8.339,11.845 8.294,11.767 8.276,11.68L7.66,8.652C7.644,8.575 7.607,8.505 7.551,8.449C7.496,8.394 7.425,8.356 7.348,8.34L4.32,7.724C4.234,7.707 4.155,7.662 4.097,7.595C4.039,7.529 4.004,7.445 3.999,7.357C3.993,7.269 4.017,7.181 4.067,7.108C4.116,7.035 4.188,6.98 4.272,6.952L10.672,4.82C10.744,4.791 10.823,4.783 10.899,4.797C10.976,4.812 11.046,4.848 11.102,4.902C11.158,4.956 11.197,5.025 11.215,5.1C11.232,5.176 11.227,5.255 11.2,5.328L9.068,11.728C9.04,11.811 8.986,11.882 8.914,11.932C8.842,11.981 8.755,12.005 8.668,12Z"
android:fillColor="#ffffff"/>
</group>
</vector>
12 changes: 12 additions & 0 deletions app/src/debug/res/drawable/ic_custom_location.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="16dp"
android:height="16dp"
android:viewportWidth="16"
android:viewportHeight="16">
<path
android:pathData="M8,8m-8,0a8,8 0,1 1,16 0a8,8 0,1 1,-16 0"
android:fillColor="#C1C1C1"/>
<path
android:pathData="M9.2,11.6L6.8,10.76L4.94,11.48C4.807,11.534 4.684,11.519 4.57,11.435C4.457,11.352 4.4,11.24 4.4,11.1V5.5C4.4,5.414 4.425,5.337 4.476,5.27C4.526,5.204 4.594,5.154 4.68,5.12L6.8,4.4L9.2,5.24L11.06,4.52C11.194,4.467 11.317,4.482 11.43,4.566C11.544,4.649 11.6,4.761 11.6,4.9V10.5C11.6,10.587 11.575,10.664 11.525,10.73C11.475,10.797 11.407,10.847 11.32,10.88L9.2,11.6ZM8.8,10.62V5.94L7.2,5.38V10.06L8.8,10.62Z"
android:fillColor="#ffffff"/>
</vector>
12 changes: 12 additions & 0 deletions app/src/debug/res/drawable/ic_drag.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="46dp"
android:height="4dp"
android:viewportWidth="46"
android:viewportHeight="4">
<path
android:pathData="M2,2H43.5"
android:strokeWidth="4"
android:fillColor="#00000000"
android:strokeColor="#ECECEC"
android:strokeLineCap="round"/>
</vector>
15 changes: 15 additions & 0 deletions app/src/debug/res/drawable/ic_info_window.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="52dp"
android:height="30dp"
android:viewportWidth="52"
android:viewportHeight="30">
<path
android:pathData="M26,30L21.521,22.323L30.48,22.323L26,30Z"
android:fillColor="#593EEC"/>
<path
android:pathData="M5.231,0.876L46.769,0.876A4.279,4.279 0,0 1,51.048 5.155L51.048,19.021A4.279,4.279 0,0 1,46.769 23.3L5.231,23.3A4.279,4.279 0,0 1,0.952 19.021L0.952,5.155A4.279,4.279 0,0 1,5.231 0.876z"
android:fillColor="#593EEC"/>
<path
android:pathData="M25.649,11.557V12.645H21.554V13.312H24.491V15.909H18.559V16.494H24.771V17.594H17.096V14.903H23.017V14.377H17.085V13.312H20.068V12.645H15.985V11.557H25.649ZM16.359,10.165C18.489,10.071 19.571,9.562 19.881,8.948H16.897V7.848H20.068V7.006H21.542V7.848H24.736V8.948H21.724C22.028,9.562 23.116,10.071 25.263,10.165L24.83,11.264C22.853,11.165 21.478,10.668 20.805,9.866C20.132,10.668 18.764,11.165 16.769,11.264L16.359,10.165ZM28.118,7.497V8.761H30.294V7.497H31.792V12.142H26.632V7.497H28.118ZM27.697,13.991V12.832H34.763V15.722H29.182V16.412H35.068V17.594H27.72V14.657H33.277V13.991H27.697ZM28.118,10.972H30.294V9.884H28.118V10.972ZM33.266,12.434V7.017H34.763V9.088H36.202V10.293H34.763V12.434H33.266Z"
android:fillColor="#ffffff"/>
</vector>
11 changes: 11 additions & 0 deletions app/src/main/java/com/runnect/runnect/data/dto/LocationData.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.runnect.runnect.data.dto


import android.os.Parcelable
import kotlinx.android.parcel.Parcelize

@Parcelize
data class LocationData(
val buildingName: String,
val fullAddress: String,
) : Parcelable
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@ import kotlinx.android.parcel.Parcelize
data class SearchResultEntity(
val fullAddress: String,
val name: String,
val locationLatLng: LatLng,
val locationLatLng: LatLng?,
val mode: String
) : Parcelable
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package com.runnect.runnect.data.dto.tmap.geocoding


import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class ResponseReverseGeocodingDto(
@SerialName("addressInfo")
val addressInfo: AddressInfo
) {
@Serializable
data class AddressInfo(
@SerialName("addressKey")
val addressKey: String? = null,
@SerialName("addressType")
val addressType: String,
@SerialName("adminDong")
val adminDong: String,
@SerialName("adminDongCode")
val adminDongCode: String,
@SerialName("adminDongCoord")
val adminDongCoord: AdminDongCoord? = null,
@SerialName("buildingIndex")
val buildingIndex: String,
@SerialName("buildingName")
val buildingName: String,
@SerialName("bunji")
val bunji: String,
@SerialName("city_do")
val cityDo: String,
@SerialName("eup_myun")
val eupMyun: String,
@SerialName("fullAddress")
val fullAddress: String,
@SerialName("gu_gun")
val guGun: String,
@SerialName("legalDong")
val legalDong: String,
@SerialName("legalDongCode")
val legalDongCode: String,
@SerialName("legalDongCoord")
val legalDongCoord: LegalDongCoord? = null,
@SerialName("mappingDistance")
val mappingDistance: String,
@SerialName("ri")
val ri: String,
@SerialName("roadAddressKey")
val roadAddressKey: String? = null,
@SerialName("roadCode")
val roadCode: String,
@SerialName("roadCoord")
val roadCoord: RoadCoord? = null,
@SerialName("roadName")
val roadName: String
) {

@Serializable
data class AdminDongCoord(
@SerialName("lat")
val lat: String,
@SerialName("latEntr")
val latEntr: String,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

latEntr 속성이 무엇인지 알 수 있을까요?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

주소의 입구에 해당하는 위도 좌표입니다.

다른 attribute에 대한 설명은 아래 링크에 있습니다!
https://openapi.sk.com/products/detail?linkMenuSeq=23

@SerialName("lon")
val lon: String,
@SerialName("lonEntr")
val lonEntr: String
)

@Serializable
data class RoadCoord(
@SerialName("lat")
val lat: String,
@SerialName("latEntr")
val latEntr: String,
@SerialName("lon")
val lon: String,
@SerialName("lonEntr")
val lonEntr: String
)

@Serializable
data class LegalDongCoord(
@SerialName("lat")
val lat: String,
@SerialName("latEntr")
val latEntr: String,
@SerialName("lon")
val lon: String,
@SerialName("lonEntr")
val lonEntr: String
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ class DepartureSearchRepositoryImpl @Inject constructor(private val departureSou
SearchResultEntity(
fullAddress = makeMainAdress(it),
name = it.name ?: "",
locationLatLng = LatLng(it.noorLat.toDouble(), it.noorLon.toDouble())
locationLatLng = LatLng(it.noorLat.toDouble(), it.noorLon.toDouble()),
mode = "searchLocation" //현위치, 지도에서 출발과 구분하기 위한 식별자
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

문자열은 하드코딩 하지 않고 const 로 상수화 시키는 것이 어떨까요??

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

아래 코드에 리뷰를 추가했는데, 문자열 대신 enum class를 활용하는 것도 좋을 거 같아요 :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

좋아요!! 매직 리터럴을 지양하는 방향이 좋다고 생각하고 기존의 코드들도 리팩토링 해오고 있었습니다!

)
}
return changedData
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.runnect.runnect.data.repository

import com.runnect.runnect.data.dto.LocationData
import com.runnect.runnect.data.source.remote.RemoteReverseGeocodingDataSource
import com.runnect.runnect.domain.ReverseGeocodingRepository
import javax.inject.Inject

class ReverseGeocodingRepositoryImpl @Inject constructor(private val reverseGeocodingDataSource: RemoteReverseGeocodingDataSource) :
ReverseGeocodingRepository {
override suspend fun getLocationInfoUsingLatLng(
lat: Double,
lon: Double
): LocationData {
val response =
reverseGeocodingDataSource.getLocationInfoUsingLatLng(lat = lat, lon = lon).body()
return LocationData(
buildingName = response?.addressInfo?.buildingName ?: "buildingName fail",
fullAddress = response?.addressInfo?.fullAddress ?: "fullAddress fail"
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

응답값 response 가 널이어도 LocationData에는 "buildingName fail" 같은 문자열이 들어가네요!
이 함수를 뷰모델에서 사용하고 있는데, "buildingName fail" 과 같은 상황에 대한 별도의 예외 처리는 없는 것으로 보였습니다..! 혹시 모를 예외 상황을 위해, 널에 대한 처리를 좀 더 분명하게 하면 좋을 거 같습니다 :)

interface ReverseGeocodingRepository {
    suspend fun getLocationInfoUsingLatLng(lat: Double, lon: Double): LocationData?
}
override suspend fun getLocationInfoUsingLatLng(
        lat: Double,
        lon: Double
    ): LocationData? {
        val response = reverseGeocodingDataSource
            .getLocationInfoUsingLatLng(lat = lat, lon = lon)
            .body()

        return if (response != null) {
            LocationData(
                buildingName = response.addressInfo.buildingName,
                fullAddress = response.addressInfo.fullAddress
            )
        } else null
    }
    fun getLocationInfoUsingLatLng(lat: Double, lon: Double) {
        viewModelScope.launch {
            runCatching {
                reverseGeocodingRepository.getLocationInfoUsingLatLng(lat = lat, lon = lon)
            }.onSuccess { response ->
                if(response == null) {
                    Timber.e("getLocationInfoUsingLatLng response is null")
                    return@launch
                }

                Timber.tag(ContentValues.TAG).d("통신success")
                reverseGeocodingResult.value = response
            }.onFailure {
                Timber.tag(ContentValues.TAG).d("통신failure : ${it}")
                errorMessage.value = it.message
            }
        }
    }

이런 식으로 널 처리하는 걸 생각해봤는데, 더 나은 방식이 있다면 적극 추천해주세요!!

Copy link
Collaborator Author

@unam98 unam98 Sep 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

response 자체가 null이 오는 건 생각 못했는데 좋다!! 날카로워서 베일 뻔..

내가 짜놓은 코드는 하은이 네 말처럼 response부터 null이 오는 경우도 "buildingName fail"을 주기 때문에 적절한 null 처리라는 생각이 안 드네.

api에서 buildingName, fullAddress 값으로 보내줄 게 없을 때 빈문자열("")로 보내주거든. 그래서 (api 측에 문제가 생기지 않는 이상) 사실 buildingName에 null이 뜰 가능성은 없어서 하은이 네가 짜준 코드처럼 그냥 크게 response의 null 여부만 체크하는 게 간단할 것 같아!! (만약 response는 null이 아닌데 이후 attribute 값들이 null을 가진다면 더 세부적인 처리가 필요하겠지만)

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.runnect.runnect.data.service

import com.runnect.runnect.BuildConfig
import com.runnect.runnect.data.dto.tmap.SearchResponseTmapDto
import com.runnect.runnect.data.dto.tmap.geocoding.ResponseReverseGeocodingDto
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Header
import retrofit2.http.Query

interface ReverseGeocodingService {

@GET("/tmap/geo/reversegeocoding?")
suspend fun getLocationUsingLatLng(
@Header("appKey") appKey: String = BuildConfig.TMAP_API_KEY,
@Query("version") version: Int = 1,
@Query("callback") callback: String? = null,
@Query("lat") lat: Double,
@Query("lon") lon: Double,
@Query("coordType") coordType: String? = "WGS84GEO",
@Query("addressType") addresstType: String? = "A04",
): Response<ResponseReverseGeocodingDto>
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 문서 를 통해 각 속성이 어떤 것인지 알 수 있었어요!

Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.runnect.runnect.data.source.remote

import com.runnect.runnect.data.dto.tmap.geocoding.ResponseReverseGeocodingDto
import com.runnect.runnect.data.service.ReverseGeocodingService
import retrofit2.Response
import javax.inject.Inject

class RemoteReverseGeocodingDataSource @Inject constructor(private val reverseGeocodingService: ReverseGeocodingService) {
suspend fun getLocationInfoUsingLatLng(
lat: Double,
lon: Double
): Response<ResponseReverseGeocodingDto> =
reverseGeocodingService.getLocationUsingLatLng(lat = lat, lon = lon)
}
7 changes: 5 additions & 2 deletions app/src/main/java/com/runnect/runnect/di/RepositoryModule.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
package com.runnect.runnect.di

import com.runnect.runnect.data.service.*
import com.runnect.runnect.data.repository.*
import com.runnect.runnect.data.service.*
import com.runnect.runnect.data.source.remote.*
import com.runnect.runnect.domain.*
import dagger.Binds
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton
Expand Down Expand Up @@ -34,6 +33,10 @@ interface RepositoryModule {
@Binds
fun bindLoginRepository(loginRepositoryImpl: LoginRepositoryImpl): LoginRepository

@Singleton
@Binds
fun bindReverseGeocodingRepository(reverseGeocodingRepositoryImpl: ReverseGeocodingRepositoryImpl): ReverseGeocodingRepository

@Singleton
@Binds
fun bindBannerRepository(bannerRepositoryImpl: BannerRepositoryImpl): BannerRepository
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/java/com/runnect/runnect/di/ServiceModule.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@ object ServiceModule {
fun provideKSearchService(@RetrofitModule.Tmap tmapRetrofit: Retrofit) =
tmapRetrofit.create(SearchService::class.java)

@Singleton
@Provides
fun provideReverseGeocodingService(@RetrofitModule.Tmap tmapRetrofit: Retrofit) =
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Runnect, Tmap 이라는 한정자는 qualifier 라는 패키지로 별도 분리하여 정의하는 것이 더 좋을 거 같습니다 :)
그러면 앞에 일일이 RetrofitModule 클래스명을 적어주지 않아도 되니까요!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

그렇게 해본 적이 없어서 어떻게 해볼 수 있을지 모르겠는데 코어 타임 때 여쭤보겠습니다!

tmapRetrofit.create(ReverseGeocodingService::class.java)

@Singleton
@Provides
fun provideBannerService() = Firebase.firestore
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.runnect.runnect.domain

import com.runnect.runnect.data.dto.LocationData

interface ReverseGeocodingRepository {
suspend fun getLocationInfoUsingLatLng(lat: Double, lon: Double): LocationData
}
Loading