From 8eaa4b31d984d7a8a43594e6d8c903c2b6ddd1b5 Mon Sep 17 00:00:00 2001 From: 2chang5 Date: Mon, 9 Oct 2023 21:15:50 +0900 Subject: [PATCH 01/39] =?UTF-8?q?[fix]=20sentry=20failure=20error=20body?= =?UTF-8?q?=20context=20=EC=9D=B4=EC=83=81=ED=95=98=EA=B2=8C=20=EC=88=98?= =?UTF-8?q?=EC=A7=91=EB=90=98=EB=8A=94=20=EB=B6=80=EB=B6=84=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#456)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/log/tripDrawLogUtil/TripDrawLogUtil.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/support/src/main/java/com/teamtripdraw/android/support/framework/presentation/log/tripDrawLogUtil/TripDrawLogUtil.kt b/android/support/src/main/java/com/teamtripdraw/android/support/framework/presentation/log/tripDrawLogUtil/TripDrawLogUtil.kt index 82a3ca0db..b095df0c9 100644 --- a/android/support/src/main/java/com/teamtripdraw/android/support/framework/presentation/log/tripDrawLogUtil/TripDrawLogUtil.kt +++ b/android/support/src/main/java/com/teamtripdraw/android/support/framework/presentation/log/tripDrawLogUtil/TripDrawLogUtil.kt @@ -64,7 +64,7 @@ class TripDrawLogUtil() : LogUtil { scope.setContexts(RESPONSE_STATE_FAILURE_CODE_KEY, code) scope.setContexts( RESPONSE_STATE_FAILURE_ERROR_BODY_KEY, - errorBody ?: NO_ERROR_BODY_MESSAGE, + errorBody?.string() ?: NO_ERROR_BODY_MESSAGE, ) } } From f7a4d80d0756f810885737ce6fe910ad62d69ba6 Mon Sep 17 00:00:00 2001 From: 2chang5 Date: Wed, 11 Oct 2023 17:46:07 +0900 Subject: [PATCH 02/39] =?UTF-8?q?[feat]=20=EB=8B=A4=EC=9D=B4=EC=96=BC?= =?UTF-8?q?=EB=A1=9C=EA=B7=B8=20=ED=83=9C=EB=B8=94=EB=A6=BF=20=EB=8C=80?= =?UTF-8?q?=EC=9D=91=20=EC=82=AC=EC=9D=B4=EC=A6=88=20=EC=A1=B0=EC=A0=95=20?= =?UTF-8?q?(#466)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/ui/common/dialog/DialogUtil.kt | 16 +----- .../dialog/ResponsiveUiDialogSizeAdjuster.kt | 53 +++++++++++++++++++ .../ui/common/dialog/SetTripTitleDialog.kt | 16 +----- 3 files changed, 55 insertions(+), 30 deletions(-) create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/common/dialog/ResponsiveUiDialogSizeAdjuster.kt diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/common/dialog/DialogUtil.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/common/dialog/DialogUtil.kt index 5d58a0d22..f9d3fe63e 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/common/dialog/DialogUtil.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/common/dialog/DialogUtil.kt @@ -31,7 +31,6 @@ class DialogUtil( super.onViewCreated(view, savedInstanceState) isCancelable = true - setLayout() setMessage() setConfirmText() setConfirmTextColor() @@ -41,19 +40,7 @@ class DialogUtil( override fun onStart() { super.onStart() - setLayout() - } - - private fun setLayout() { - requireNotNull(dialog).apply { - requireNotNull(window).apply { - setLayout( - (resources.displayMetrics.widthPixels * DIALOG_WINDOW_SIZE).toInt(), - ViewGroup.LayoutParams.WRAP_CONTENT, - ) - setBackgroundDrawableResource(R.color.td_white) - } - } + ResponsiveUiDialogSizeAdjuster().adjustSize(dialog, resources) } private fun setMessage() { @@ -106,7 +93,6 @@ class DialogUtil( } companion object { - private const val DIALOG_WINDOW_SIZE = 0.85 const val DELETE_CHECK = 0 const val SAVE_CHECK = 1 const val LOGOUT_CHECK = 2 diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/common/dialog/ResponsiveUiDialogSizeAdjuster.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/common/dialog/ResponsiveUiDialogSizeAdjuster.kt new file mode 100644 index 000000000..ac7e484bb --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/common/dialog/ResponsiveUiDialogSizeAdjuster.kt @@ -0,0 +1,53 @@ +package com.teamtripdraw.android.ui.common.dialog + +import android.app.Dialog +import android.content.res.Resources +import android.view.ViewGroup +import com.teamtripdraw.android.R +import kotlin.math.roundToInt + +class ResponsiveUiDialogSizeAdjuster { + + fun adjustSize(dialog: Dialog?, resources: Resources) { + dialog ?: return + when (isOverPhoneSize(resources)) { + true -> adjustTabletDialogSize(dialog, resources) + false -> adjustPhoneDialogSize(dialog, resources) + } + } + + private fun isOverPhoneSize(resources: Resources): Boolean = + getDeviceDPValue(resources) >= DEVICE_TYPE_BOUNDARY + + private fun getDeviceDPValue(resources: Resources): Int = + (resources.displayMetrics.widthPixels / resources.displayMetrics.density).roundToInt() + + private fun adjustPhoneDialogSize(dialog: Dialog, resources: Resources) { + dialog.window?.apply { + setLayout( + (resources.displayMetrics.widthPixels * PHONE_DIALOG_WIDTH_RATIO).toInt(), + ViewGroup.LayoutParams.WRAP_CONTENT, + ) + setBackgroundDrawableResource(R.color.td_white) + } + } + + private fun adjustTabletDialogSize(dialog: Dialog, resources: Resources) { + dialog.window?.apply { + setLayout( + dPToPixel(TABLET_DIALOG_WIDTH_DP, resources), + ViewGroup.LayoutParams.WRAP_CONTENT, + ) + setBackgroundDrawableResource(R.color.td_white) + } + } + + private fun dPToPixel(dp: Int, resources: Resources): Int = + (dp * resources.displayMetrics.density).roundToInt() + + companion object { + private const val PHONE_DIALOG_WIDTH_RATIO = 0.85 + private const val DEVICE_TYPE_BOUNDARY = 600 + private const val TABLET_DIALOG_WIDTH_DP = 400 + } +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/common/dialog/SetTripTitleDialog.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/common/dialog/SetTripTitleDialog.kt index 032533b1f..9a6097d32 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/common/dialog/SetTripTitleDialog.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/common/dialog/SetTripTitleDialog.kt @@ -7,7 +7,6 @@ import android.view.ViewGroup import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels -import com.teamtripdraw.android.R import com.teamtripdraw.android.databinding.FragmentTripTitleDialogBinding import com.teamtripdraw.android.support.framework.presentation.event.EventObserver import com.teamtripdraw.android.support.framework.presentation.getParcelableCompat @@ -54,19 +53,7 @@ class SetTripTitleDialog : DialogFragment() { override fun onStart() { super.onStart() - setLayout() - } - - private fun setLayout() { - requireNotNull(dialog).apply { - requireNotNull(window).apply { - setLayout( - (resources.displayMetrics.widthPixels * DIALOG_WINDOW_SIZE).toInt(), - ViewGroup.LayoutParams.WRAP_CONTENT, - ) - setBackgroundDrawableResource(R.color.td_white) - } - } + ResponsiveUiDialogSizeAdjuster().adjustSize(dialog, resources) } private fun initCompletedEventObserve() { @@ -106,7 +93,6 @@ class SetTripTitleDialog : DialogFragment() { } companion object { - private const val DIALOG_WINDOW_SIZE = 0.85 private const val TRIP_ID_KEY = "TRIP_ID_KEY" private const val SET_TITLE_SITUATION_KEY = "SET_TITLE_SITUATION_KEY" From 8255d79e98b2116a0307f7f496b3633f7afed568 Mon Sep 17 00:00:00 2001 From: otter Date: Thu, 12 Oct 2023 21:23:12 +0900 Subject: [PATCH 03/39] =?UTF-8?q?[feat]=20=EC=A0=95=EC=B1=85=20=EC=95=88?= =?UTF-8?q?=EB=82=B4=EC=82=AC=ED=95=AD=20=EC=9B=B9=20=EC=97=B0=EA=B2=B0=20?= =?UTF-8?q?(#309)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/build.gradle.kts | 18 ++++++++++++++++++ .../android/ui/login/LoginActivity.kt | 13 ++++++++++--- .../android/ui/login/LoginViewModel.kt | 5 +---- .../android/ui/myPage/MyPageFragment.kt | 14 ++++++++++---- .../app/src/main/res/layout/activity_login.xml | 2 +- 5 files changed, 40 insertions(+), 12 deletions(-) diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index b1599653f..8bfa7da61 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -73,6 +73,24 @@ android { localProperties.getProperty("ENCRYPTED_SHARED_PREFERENCE_MASTER_KEY_ALIAS"), ) + buildConfigField( + "String", + "OPEN_SOURCE_LICENSE_URL", + localProperties.getProperty("OPEN_SOURCE_LICENSE_URL"), + ) + + buildConfigField( + "String", + "PRIVACY_POLICY_URL", + localProperties.getProperty("PRIVACY_POLICY_URL"), + ) + + buildConfigField( + "String", + "TERMS_OF_SERVICE_URL", + localProperties.getProperty("TERMS_OF_SERVICE_URL"), + ) + manifestPlaceholders["NATIVE_APP_KEY"] = localProperties.getProperty("KAKAO_NATIVE_APP_KEY_NO_QUOTES") diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/login/LoginActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/login/LoginActivity.kt index 7428947f7..e4a20b7f6 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/login/LoginActivity.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/login/LoginActivity.kt @@ -2,11 +2,13 @@ package com.teamtripdraw.android.ui.login import android.content.Context import android.content.Intent +import android.net.Uri import android.os.Bundle import androidx.activity.viewModels import androidx.appcompat.app.AppCompatActivity import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.databinding.DataBindingUtil +import com.teamtripdraw.android.BuildConfig import com.teamtripdraw.android.R import com.teamtripdraw.android.databinding.ActivityLoginBinding import com.teamtripdraw.android.domain.model.auth.LoginInfo @@ -83,14 +85,19 @@ class LoginActivity : AppCompatActivity() { private fun initOpenPrivacyPolicyEventObserver() { loginViewModel.openPrivacyPolicyEvent.observe(this) { - if (it) startActivity(PrivacyPolicyActivity.getIntent(this)) - loginViewModel.resetTermsOfServiceEvent() + if (it.not()) return@observe + val browserIntent = + Intent(Intent.ACTION_VIEW, Uri.parse(BuildConfig.PRIVACY_POLICY_URL)) + startActivity(browserIntent) } } private fun initOpenTermsOfServiceEventObserver() { loginViewModel.openTermsOfServiceEvent.observe(this) { - if (it) startActivity(TermsOfServiceActivity.getIntent(this)) + if (it.not()) return@observe + val browserIntent = + Intent(Intent.ACTION_VIEW, Uri.parse(BuildConfig.TERMS_OF_SERVICE_URL)) + startActivity(browserIntent) } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/login/LoginViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/login/LoginViewModel.kt index b294010c0..eb1803cb7 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/login/LoginViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/login/LoginViewModel.kt @@ -53,11 +53,8 @@ class LoginViewModel @Inject constructor( _openPrivacyPolicyEvent.value = false } - fun startTermsOfServiceEvent() { + fun openTermsOfService() { _openTermsOfServiceEvent.value = true - } - - fun resetTermsOfServiceEvent() { _openTermsOfServiceEvent.value = false } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/myPage/MyPageFragment.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/myPage/MyPageFragment.kt index c2b7e8c60..3c306fea4 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/myPage/MyPageFragment.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/myPage/MyPageFragment.kt @@ -1,12 +1,14 @@ package com.teamtripdraw.android.ui.myPage import android.content.Intent +import android.net.Uri import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels +import com.teamtripdraw.android.BuildConfig import com.teamtripdraw.android.databinding.FragmentMyPageBinding import com.teamtripdraw.android.domain.model.trip.Trip import com.teamtripdraw.android.support.framework.presentation.event.EventObserver @@ -15,8 +17,6 @@ import com.teamtripdraw.android.ui.history.HistoryActivity import com.teamtripdraw.android.ui.home.recordingPoint.RecordingPointAlarmManager import com.teamtripdraw.android.ui.home.recordingPoint.RecordingPointService import com.teamtripdraw.android.ui.login.LoginActivity -import com.teamtripdraw.android.ui.policy.OpenSourceLicenseActivity -import com.teamtripdraw.android.ui.policy.PrivacyPolicyActivity import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -62,13 +62,19 @@ class MyPageFragment : Fragment() { private fun initOpenOpenSourceLicenseObserver() { viewModel.openOpenSourceLicenseEvent.observe(viewLifecycleOwner) { - if (it) startActivity(OpenSourceLicenseActivity.getIntent(requireContext())) + if (it.not()) return@observe + val browserIntent = + Intent(Intent.ACTION_VIEW, Uri.parse(BuildConfig.OPEN_SOURCE_LICENSE_URL)) + startActivity(browserIntent) } } private fun initOpenPrivacyPolicyObserver() { viewModel.openPrivacyPolicyEvent.observe(viewLifecycleOwner) { - if (it) startActivity(PrivacyPolicyActivity.getIntent(requireContext())) + if (it.not()) return@observe + val browserIntent = + Intent(Intent.ACTION_VIEW, Uri.parse(BuildConfig.PRIVACY_POLICY_URL)) + startActivity(browserIntent) } } diff --git a/android/app/src/main/res/layout/activity_login.xml b/android/app/src/main/res/layout/activity_login.xml index 7e226900b..c631dd58e 100644 --- a/android/app/src/main/res/layout/activity_login.xml +++ b/android/app/src/main/res/layout/activity_login.xml @@ -53,7 +53,7 @@ android:id="@+id/tv_login_sign_in_policy" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:onClick="@{()->loginViewModel.startTermsOfServiceEvent()}" + android:onClick="@{()->loginViewModel.openTermsOfService()}" android:text="@string/tv_login_sign_in_policy" android:textAppearance="@style/caption_1" android:textColor="@color/td_black" From 54dcf88cc99c0b4388825ae836353affc9389517 Mon Sep 17 00:00:00 2001 From: otter Date: Thu, 12 Oct 2023 21:28:04 +0900 Subject: [PATCH 04/39] =?UTF-8?q?[refactor]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=B4=EC=A7=84=20=EC=A0=95=EC=B1=85=20=EC=95=88=EB=82=B4?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EA=B4=80=EB=A0=A8=20=EC=BD=94=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0=20(#309)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/ui/login/LoginActivity.kt | 2 - .../ui/policy/OpenSourceLicenseActivity.kt | 32 --- .../ui/policy/PrivacyPolicyActivity.kt | 32 --- .../ui/policy/TermsOfServiceActivity.kt | 32 --- .../layout/activity_open_source_license.xml | 54 ----- .../res/layout/activity_privacy_policy.xml | 54 ----- .../res/layout/activity_terms_of_service.xml | 54 ----- android/app/src/main/res/values/strings.xml | 214 ------------------ 8 files changed, 474 deletions(-) delete mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/policy/OpenSourceLicenseActivity.kt delete mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/policy/PrivacyPolicyActivity.kt delete mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/policy/TermsOfServiceActivity.kt delete mode 100644 android/app/src/main/res/layout/activity_open_source_license.xml delete mode 100644 android/app/src/main/res/layout/activity_privacy_policy.xml delete mode 100644 android/app/src/main/res/layout/activity_terms_of_service.xml diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/login/LoginActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/login/LoginActivity.kt index e4a20b7f6..750ee0e35 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/login/LoginActivity.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/login/LoginActivity.kt @@ -18,8 +18,6 @@ import com.teamtripdraw.android.support.framework.presentation.loginManager.Kaka import com.teamtripdraw.android.support.framework.presentation.loginManager.SocialLoginManager import com.teamtripdraw.android.ui.main.MainActivity import com.teamtripdraw.android.ui.model.mapper.toPresentation -import com.teamtripdraw.android.ui.policy.PrivacyPolicyActivity -import com.teamtripdraw.android.ui.policy.TermsOfServiceActivity import com.teamtripdraw.android.ui.signUp.NicknameSetupActivity import dagger.hilt.android.AndroidEntryPoint diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/policy/OpenSourceLicenseActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/policy/OpenSourceLicenseActivity.kt deleted file mode 100644 index d314702ea..000000000 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/policy/OpenSourceLicenseActivity.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.teamtripdraw.android.ui.policy - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.teamtripdraw.android.databinding.ActivityOpenSourceLicenseBinding - -class OpenSourceLicenseActivity : AppCompatActivity() { - private lateinit var binding: ActivityOpenSourceLicenseBinding - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding = ActivityOpenSourceLicenseBinding.inflate(layoutInflater) - setContentView(binding.root) - - initBackClickEvent() - } - - private fun initBackClickEvent() { - binding.btnOpenSourceLicenseBack.setOnClickListener { - finish() - } - } - - companion object { - fun getIntent(context: Context): Intent { - val intent = Intent(context, OpenSourceLicenseActivity::class.java) - return intent - } - } -} diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/policy/PrivacyPolicyActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/policy/PrivacyPolicyActivity.kt deleted file mode 100644 index 3f82096b2..000000000 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/policy/PrivacyPolicyActivity.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.teamtripdraw.android.ui.policy - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.teamtripdraw.android.databinding.ActivityPrivacyPolicyBinding - -class PrivacyPolicyActivity : AppCompatActivity() { - private lateinit var binding: ActivityPrivacyPolicyBinding - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding = ActivityPrivacyPolicyBinding.inflate(layoutInflater) - setContentView(binding.root) - - initBackClickEvent() - } - - private fun initBackClickEvent() { - binding.btnPrivacyPolicyBack.setOnClickListener { - finish() - } - } - - companion object { - fun getIntent(context: Context): Intent { - val intent = Intent(context, PrivacyPolicyActivity::class.java) - return intent - } - } -} diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/policy/TermsOfServiceActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/policy/TermsOfServiceActivity.kt deleted file mode 100644 index 205761097..000000000 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/policy/TermsOfServiceActivity.kt +++ /dev/null @@ -1,32 +0,0 @@ -package com.teamtripdraw.android.ui.policy - -import android.content.Context -import android.content.Intent -import android.os.Bundle -import androidx.appcompat.app.AppCompatActivity -import com.teamtripdraw.android.databinding.ActivityTermsOfServiceBinding - -class TermsOfServiceActivity : AppCompatActivity() { - private lateinit var binding: ActivityTermsOfServiceBinding - - override fun onCreate(savedInstanceState: Bundle?) { - super.onCreate(savedInstanceState) - binding = ActivityTermsOfServiceBinding.inflate(layoutInflater) - setContentView(binding.root) - - initBackClickEvent() - } - - private fun initBackClickEvent() { - binding.btnTermsOfServiceBack.setOnClickListener { - finish() - } - } - - companion object { - fun getIntent(context: Context): Intent { - val intent = Intent(context, TermsOfServiceActivity::class.java) - return intent - } - } -} diff --git a/android/app/src/main/res/layout/activity_open_source_license.xml b/android/app/src/main/res/layout/activity_open_source_license.xml deleted file mode 100644 index fbad8fc1a..000000000 --- a/android/app/src/main/res/layout/activity_open_source_license.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/app/src/main/res/layout/activity_privacy_policy.xml b/android/app/src/main/res/layout/activity_privacy_policy.xml deleted file mode 100644 index e6407e6a5..000000000 --- a/android/app/src/main/res/layout/activity_privacy_policy.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/app/src/main/res/layout/activity_terms_of_service.xml b/android/app/src/main/res/layout/activity_terms_of_service.xml deleted file mode 100644 index cb45a3370..000000000 --- a/android/app/src/main/res/layout/activity_terms_of_service.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index a0005fecb..ee4da7b54 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -103,218 +103,4 @@ 검색된 감상이 없습니다. - - - 트립드로우는 사용자의 GPS 경로 및 위치, 사진, 동영상, 음성/문자 메모 등을 이용해 감상을 기록하고, 사용자의 여행 경로를 sns를 통해 손쉽게 공유할 수 있는 서비스를 제공합니다. 이 개인정보 처리방침은 트립드로우가 어떠한 개인정보들을 수집하고, 그 정보를 어떻게 사용하고 제공하는지 알려줍니다. \n\n\n개인정보 수집 항목 \n트립드로우는 서비스 제공을 위해 최소한의 개인정보를 수집하고 있습니다. 수집하는 개인정보는 사용자의 선택에 따라 달라질 수 있지만, 일반적으로 아래와 같은 정보들을 포함합니다. \n\n회원가입 시 \n타서비스 계정(카카오계정 등)을 이용하여 회원 가입을 할 경우 해당 계정의 유저아이디, 이름(닉네임)을 필수항목으로 수집합니다. \n\n서비스 이용 시\n단말기정보(모델명, OS정보, 언어 및 국가정보, 화면사이즈 등), IP주소, 쿠키, 방문일시, 위치정보, 부정이용기록, 서비스 이용 기록, 메타 데이터 등의 정보가 생성되어 수집될 수 있습니다. 메타 데이터에는 사용자가 콘텐츠에 추가한 키워드, 위치 정보, 기타 유사한 정보들이 포함될 수 있습니다. 구체적으로 서비스 이용 과정에서 이용자에 관한 정보를 자동화된 방법으로 생성하여 이를 수집하거나, 이용자 기기의 고유한 정보를 원래의 값을 확인하지 못하도록 안전하게 변환하여 수집합니다. 서비스 이용 과정에서 위치정보가 수집될 수 있으며, 트리플에서 제공하는 위치기반 서비스에 대해서는 ‘위치정보 이용약관’에서 자세하게 규정하고 있습니다. \n\n\n개인정보 수집 방법 \n개인정보를 수집하는 경우에는 반드시 사전에 사용자에게 해당 사실을 알리고 동의를 구하고 있습니다. 회원가입 및 서비스 이용 과정에서 개인정보 수집에 대해 동의를 하고 직접 정보를 입력하는 사용자에 한해 해당 개인정보를 수집합니다. \n\n\n개인정보 이용\n트립드로우는 회원관리, 서비스 개발·제공 및 향상, 안전한 인터넷 이용환경 구축 등의 목적으로만 개인정보를 이용합니다. 이용자 식별, 회원탈퇴 의사의 확인 등 회원관리를 위하여 개인정보를 이용합니다. 트립드로우는 아래와 같이 서비스 제공을 위해 필요한 최소한의 개인정보를 수집하고 있습니다. \n회원 식별/가입의사 확인, 본인/연령 확인, 부정이용 방지. \n신규 서비스 개발, 다양한 서비스 제공, 문의사항 또는 불만처리, 공지사항 전달 \n계정 도용 및 부정 이용 행위 등에 대한 방지 및 제재 \n서비스 이용 기록, 접속 빈도 및 서비스 이용에 대한 통계, 서비스 개선에 활용 \n\n\n개인정보 제공 \n트립드로우는 사용자의 별도의 동의가 있는 경우나 법령에 규정된 경우를 제외하고는 사용자의 개인정보를 제3자에게 제공하지 않습니다. 다만, 개인정보는 부정한 이용으로 인한 분쟁을 방지하기 위해 내부방침에 따라 보존한 다음 파기를 요청한 사용자에 한해 파기됩니다. \n\n\n사용자 및 법정대리인의 권리와 그 행사방법 \n사용자는 트립드로우에 대해 언제든지 다음 각 호의 개인정보 보호 관련 권리를 행사할 수 있습니다. \n개인정보 열람 요구 \n오류 등이 있을 경우 정정 요구 \n삭제 요구 \n처리 정지 요구 \n\n\n개인정보 보유 및 파기 \n트립드로우는 법령에 따른 개인정보 보유, 이용기간 또는 사용자로부터 개인정보를 수집 시에 동의받은 개인정보 보유, 이용기간 내에서 개인정보를 처리, 보유합니다. 개인정보 처리 및 보유 기간은 다음과 같습니다. \n회원 가입 및 관리 : 탈퇴 요청 시 까지 \n관계 법령 위반에 따른 수사, 조사 등이 진행 중인 경우에는 해당 수사, 조사 종료 시 까지 \n\n사용자의 개인정보는 원칙적으로 개인정보의 수집 및 이용목적이 달성되면 지체없이 파기하나, 사용자가 트립드로우의 회원 자격을 유지하고 있는 동안에는 제공받은 개인정보를 계속 보유합니다. 또한 아래와 같은 경우 그 즉시 개인정보를 파기합니다. \n사용자의 개인정보 파기 요청 \n일시적인 목적에 의해 수집한 개인정보의 경우, 그 이용 목적을 달성 시 \n서비스 탈퇴 요청 \n\n\n개인정보 보호책임자 \n트립드로우는 개인정보 처리에 관한 업무를 총괄해서 책임지고, 개인정보 처리와 관련한 정보주체의 불만처리 및 피해구제 등을 위하여 아래와 같이 개인정보 보호 책임자를 지정하고 있습니다. \n성명 : 김수연 \n직책 : 개인개발자 \n문의 : tripdrawaos@gmail.com \n\n\n트립드로우의 개인 정보 보호 정책을 변경하기로 결정하는 경우, 아래의 개인 정보 보호 정책의 수정 날짜를 업데이트합니다. 이 정책은 2023년 8월 12일에 마지막으로 수정되었습니다. - 개인정보 처리방침 - - - 오픈소스 라이선스 - Android Parcelable \nhttps://developer.android.com/reference/kotlin/android/os/Parcelable \n\n\nGlide \nhttps://github.com/bumptech/glide \n\n\nGoogle Firebase for Android \nhttps://firebase.google.com/docs/android/setup \n\n\nKotlin \nhttps://github.com/JetBrains/kotlin \n\n\nKotlinx.coroutine \nhttps://github.com/Kotlin/kotlinx.coroutines \n\n\nMaterial-BottomNavigation \nhttps://m2.material.io/components/bottom-navigation/android \n\n\nMockk \nhttps://mockk.io/ \n\n\nSquare Moshi \nhttps://github.com/square/moshi \n\n\nSquare OkHttp \nhttps://github.com/square/okhttp \n\n\nSquare Retrofit \nhttps://github.com/square/retrofit - - - 이용 약관 - ## 제 1조(목적) - ---- - -트립드로우 서비스에 오신 것을 환영합니다. - -본 약관은 사용자(본 약관에 동의한 자를 말합니다 이하 "회원"이라고 합니다.)가 트립드로우(이하 "회사"라고 합니다)가 제공하는 트립드로우(TripDraw) 서비스(이하 "서비스"라고 합니다)를 이용함에 있어 "회사"와 "회원"의 권리·의무 및 책임 사항을 규정함을 목적으로 합니다. - -## 제 2조 (이용약관의 효력 및 변경) - ---- - -1. "회사"는 본 약관의 내용을 "회원"이 알 수 있도록 "서비스"의 전용 앱에 게시함으로써 이를 알리고, 합리적인 사유가 발생될 경우에는 이 약관을 변경할 수 있으며, 약관을 변경할 경우에는 지체 없이 이를 사전에 공지합니다. -2. "회사"는 콘텐츠산업 진흥법, 정보통신망 이용촉진 및 정보보호 등에 관한 법률, 약관의 규제에 관한 법률, 소비자 기본법 등 관련 법령을 위배하지 않는 범위에서 본 약관을 개정할 수 있습니다. -3. "회사"가 약관을 개정할 경우에는 개정약관 및 개정약관의 시행일자와 개정사유를 명시하여 그 시행일자 7일(이용자에게 불리한 변경 또는 중대한 사항의 변경은 30일) 이전부터 시행일 이후 상당한 기간 동안 본 "서비스"의 이용약관 페이지에 게시합니다. -4. 기존 "회원"에게는 변경될 약관, 적용일자 및 변경사유(중요내용에 대한 변경인 경우 이에 대한 설명을 포함)를 이메일 또는 앱 푸시알림으로 발송하고, 개정된 약관은 그 시행일에 효력이 발생합니다. -5. "회사"가 개정약관 시행일까지 거부의사를 표시하지 않을 경우 이를 승인한 것으로 본다는 뜻을 고지하였음에도 불구하고 "회원"이 거부의사를 표하지 않는 경우, "회사"는 "회원"이 개정약관에 동의한 것으로 간주합니다. 개정약관에 동의하지 않는 "회원"은 제16조에 따라 이용계약을 해지할 수 있습니다. - -## 제 3조 (이용 계약의 체결 및 거절) - ---- - -1. “서비스”의 이용계약은 회원이 되고자 하는 자(이하 “가입신청자”)가 본 약관에 동의하고 가입을 신청한 다음 회사가 이를 수락함으로써 체결됩니다. -2. 가입신청자는 가입신청 시 진실한 정보를 기재하여야 하며, 허위의 정보를 기재한 경우 서비스 이용에 제한이 있을 수 있고, 나아가 그로 인한 불이익 및 법적 책임은 가입신청자에게 있습니다. -3. 가입신청자가 이전에 회원자격을 상실한 적이 있는 경우, 허위의 명의 또는 타인의 명의를 이용한 경우, 기타 승낙이 불가능한 사유가 있는 경우 이용계약의 승낙이 거부될 수 있습니다. -4. “회사”는 서비스 관련 설비의 여유 기타 기술상 또는 업무상의 이유로 이용계약의 승낙을 유보할 수 있으며, 그 결과를 가입신청자에게 알려드립니다. -5. “회사”는 다음 각 호에 해당하는 가입신청에 대하여는 승낙을 하지 않거나, 승낙 이후라도 이용의 제한 또는 이용계약의 해지 등의 조치를 취할 수 있습니다. - - ① “회사”가 정한 서비스 제공환경이 아니거나 기술상 서비스 제공이 불가능한 경우 - ② 가입신청자가 신청시 제공한 정보에 허위, 누락이나 오류가 있거나, “회사”가 요구하는 기준을 충족하지 못하는 경우 - ③ 신청 명의가 가입신청자 본인의 명의가 아닌 경우 - ④ 기타 가입신청자의 귀책사유로 인하여 승낙이 불가능하거나 해당 가입신청이 법령, 본 약관 및 기타 회사가 정한 제반 사항에 배치되는 경우 - “회사”의 해제, 해지 및 이용제한에 대하여 “회원”은 “회사”가 정한 절차에 따라 이의신청을 할 수 있습니다. 이 때 이의가 정당하다고 “회사”가 인정하는 경우, “회사”는 즉시 “서비스”의 이용을 재개합니다. - - -## 제 4조(개인정보의 관리 및 보호) - ---- - -1. "회사"는 "서비스"를 제공하기 위하여 "회원"으로부터 "서비스" 이용에 필요한 개인정보를 수집할 수 있습니다. -2. "회사"는 관계법령이 정하는 바에 따라 "회원"의 등록정보 및 개인정보를 보호하기 위해 노력하며, "회원"의 개인정보의 보호 및 사용에 대해서는 관련법령 및 "회사"의 개인정보 보호정책을 적용합니다. -3. “회원”이 회사와 체결한 서비스 이용계약은 처음 이용계약을 체결한 본인에 한해 적용됩니다. -4. “회원”의 모든 개인정보의 관리책임은 본인에게 있으므로, 타인에게 양도 및 대여할 수 없으며, 유출되지 않도록 관리해야 합니다. -5. "회사"의 공식 홈페이지 또는 "서비스" 전용 앱 이외의 사이트에서는 "회사"의 개인정보 보호정책이 적용되지 않습니다. 또한 "회사"는 이용자의 귀책사유로 인해 노출된 정보에 대해서 일체의 책임을 지지 않습니다. - -## 제 5조 (서비스 이용 계약의 종료) - ---- - -1. "회원"은 "서비스" 이용계약을 해지(이하"회원탈퇴")할 수 있으며, 서비스 내부에서 ‘회원 탈퇴’ 버튼을 눌러 "회원탈퇴" 신청할 수 있습니다. -2. "회원"이 "회원탈퇴"를 신청한 경우 "회사"는 해당 요청을 확인한 후 탈퇴를 처리합니다. -3. 탈퇴 완료 시 "회원"의 이용 정보(프로필 정보, 습관방 이용 내역, 인증 사진, 게시물 등)는 모두 삭제되어 복구 및 이용이 불가능합니다. -4. “회사”는 불가피한 사유로 더이상 서비스를 제공할 수 없을 경우, 회원의 동의 없이 회원자격을 박탈할 수 있습니다. - -## 제 6조 (회원의 계정) - ---- - -1. “회원”이 “서비스”를 이용하려면 서비스 계정(이하 “계정”이라고 합니다)을 개설하여야 하며, “계정” 개설 시 정확하고 완전한 정보를 제공하고, 정보에 변동이 있는 경우 이를 업데이트해야 합니다. -2. “회사”는 “회원”이 SNS 가입 연동 기능을 제공합니다. 계정 정보는 “서비스” 내 “회원” 본인을 제외한 타 회원에게 노출되지 않습니다. -3. “계정”에 대한 관리책임은 “회원” 본인에게 있으며, “회원”은 제3자에게 “계정”에 관한 정보를 알려주거나 이용하게 해서는 안됩니다. -4. “회원”이 자신의 “계정”을 도난당하거나 제3자가 사용하고 있음을 인지한 경우 즉시 “회사”에 통지하고 “회사”의 안내를 따라야합니다. “회사”에 통지하지 않거나, 안내에 따르지 않아 발생한 불이익에 대하여 “회사”는 책임지지 않습니다. -5. “회사”는 “계정”의 무단 도용으로 인하여 “회원”이 입은 손실에 대하여 책임을 지지 않습니다. 그러나 “회원”은 “계정”의 무단 도용으로 인해 “회사” 또는 타인이 입은 손해를 입게 된 경우 그 손해에 대해 책임을 질 수 있습니다. 단, “회원”에게 과실이 없는 때에는 그러하지 아니합니다. - -## 제 7조 (서비스의 제공) - ---- - -1. "회사"가 제공하는 "서비스"의 종류는 다음과 같습니다. - - 여행 경로 저장 서비스 - - 감상 저장 서비스 - - 기타 회사가 정하는 서비스 -2. 회사는 운영상, 기술상의 필요에 따라 제공하고 있는 서비스를 변경할 수 있습니다. -3. 회사는 이용자의 개인정보 및 서비스 이용 기록에 따라 서비스 이용에 차이를 둘 수 있습니다. - -## 제 8조 (서비스 이용시간) - ---- - -1. "서비스" 이용시간은 "회사"의 업무상 또는 기술상 불가능한 경우를 제외하고는 연중무휴 1일 24시간(00:00-24:00)으로 함을 원칙으로 합니다. -2. "회사"는 "서비스" 설비의 정기점검 등의 사유로 일정 기간 동안 "서비스" 제공을 일시 중지하거나 "서비스" 제공 시간을 제한할 수 있습니다. 이 경우 "회사"는 "회원"에게 그 사유를 사전에 알려야 하며, 사전 고지가 불가능한 긴급한 사유(시스템관리자의 고의, 과실없는 디스크장애, 시스템다운 등)가 있는 경우 사후에 통지할 수 있습니다. -3. "회사"는 "서비스"용 설비 점검·보수·공사 및 기간통신사업자의 전기통신 "서비스"의 중지, "서비스" 이용의 폭주나 국가비상사태 등을 사유로 "서비스" 제공에 장애가 발생한 경우 그 사유가 해소될 때까지 "서비스"를 일시 중지할 수 있습니다. -4. "회사"는 "서비스"를 특정 범위로 분할하여 각 범위 별로 이용가능시간을 별도로 지정할 수 있으며, 이 경우 합리적으로 가능한 방법을 통하여 그 내용을 사전 공지합니다. - -## 제 9조(게시물에 대한 저작권) - ---- - -1. "회사"가 "회원"에게 제공하는 상표, 로고, 서비스 및 광고 등 "회사"가 제작, 제공하는 것에 대한 지식재산권 등의 권리는 "회사"에 귀속합니다. -2. "회원"이 "서비스"를 이용하는 과정에서 작성한 게시물, 댓글, 카드 등(이하 “게시물 등”이라 합니다)에 대한 저작권을 포함한 일체의 권리는 각 "회원"에게 귀속됩니다. -3. "회원"은 자신이 "서비스"에 게시한 게시물 등을 "회사"가 국내·외에서 다음 각 호의 목적으로 사용하는 것을 허락합니다. -① "서비스"("서비스"가 제3자가 운영하는 사이트 또는 미디어의 일정 영역 내에 입점하는 형태로 제공되는 경우 포함) 내에서 게시물 등의 복제·전송·전시 및 우수 게시물을 "서비스" 화면에 노출하기 위하여 게시물의 내용 변경 없이 크기를 변환하거나 단순화하는 등의 방식으로 수정하는 것 -② "회사"가 운영하는 다른 "서비스"에서 게시물을 복제·전송 또는 전시하는 것. 다만 "회원"이 명시적으로 복제·전송 또는 전시에 동의하지 아니한 경우에는 그러하지 않음 -③ "회사"의 "서비스"를 홍보하기 위한 목적으로 미디어·통신사 등에 게시물의 전부 또는 일부를 보도·방영하게 하는 것. 이 경우 "회사"는 "회원"의 개별 동의 없이 미디어·통신사 등에게 "회원"의 정보를 제공하지 않음 -4. "회사"는 전항 이외의 방법으로 "회원"의 게시물 등을 이용하고자 하는 경우에는 사전에 "회원"의 동의를 얻습니다. -5. "회원"이 "서비스"에 게시물을 게재하는 것은 "회사"가 검색결과로 사용하는 것을 허락한 것으로 봅니다. -6. "회원"은 "서비스"를 이용하여 취득한 정보를 임의 가공, 판매하는 행위 등 "서비스"에 게재된 자료를 상업적으로 사용할 수 없습니다. - -## 제 10조(회원의 권리 및 의무) - ---- - -1. "회원" 은 "회사"가 서비스를 통해 제공하는 콘텐츠에 대하여 어떠한 권리도 취득하지 않습니다. -2. "회원" 은 "회사"의 동의 없이 콘텐츠를 서비스를 제공받는 용도 외로 이용하여서는 아니 되며, 특히 아래의 행위를 할 경우 그에 대한 모든 민형사상 책임을 지게 될 수 있습니다. -3. "회원"은 "서비스"의 서버와 네트워크 시스템에 허락되지 않은 방식으로 접근하는 일체의 행위(예를 들면 자동화 프로그램을 사용하여 서비스 서버와 네트워크에 접근하거나 콘텐츠 임의적 수집을 위해 서비스 시스템에 접근하는 행위) 또는 서비스의 제공을 방해하는 행위를 해서는 안됩니다. -4. "회원"은 다음과 같은 행위를 해서는 안됩니다. -① "회사"에 허위정보를 제공하거나 타인의 정보를 도용하는 행위 -② "회사"와 타인의 저작권 등 지식재산권에 대한 침해 행위 -③ 다른 "회원"의 개인정보를 수집하거나 명예를 훼손하는 행위 -④ "회사"의 사전승낙 없이 "서비스"를 이용한 영리활동을 하는 행위 -⑤ "서비스"의 기술적 보호조치를 무력화하거나 정상적인 운영을 방해할 목적으로 "회사"가 제공 또는 승인하지 아니한 컴퓨터 프로그램이나 기기 또는 장치를 이용하는 행위 -⑥ 다량의 정보를 전송하거나 동일한 또는 유사한 내용의 정보를 반복적으로 게시하여 "서비스"의 안정적인 운영을 방해하는 행위 -⑦ 정보통신설비의 오작동이나 정보 등의 파괴를 유발하는 컴퓨터 바이러스 등을 유포하는 행위 -⑧ "서비스" 내 버그를 악용하거나 비정상적인 방법으로 기록, UCD 등을 취득하는 행위 -⑨ 범죄와 관련이 있다고 판단되는 활동을 하는 행위 -⑩ 외설, 폭력적인 정보 등을 노출하는 행위 -⑪ 「정보통신망 이용촉진 및 정보보호 등에 관한 법률」 에서 금지하는 행위 등 기타 불법적이거나 부당한 행위 - -## 제 11조 (회사의 권리 및 의무) - ---- - -1. "회사"는 관련 법령을 준수하고, 본 약관이 정하는 권리의 행사와 의무의 이행을 신의에 따라 성실하게 합니다 -2. ”회사”는 회원이 안전하게 서비스를 이용할 수 있도록 개인정보 보호를 위해 보안시스템을 갖추어야 하며, 개인정보취급방침을 공시하고 준수합니다. -3. "회사"는 본 약관 및 개인정보취급방침에서 정한 경우를 제외하고는 "회원"의 개인정보가 제3자에게 공개 또는 제공되지 않도록 합니다. -4. "회사"는 "서비스" 이용과 관련한 "회원"의 의견이나 불만사항 등을 경청하며, 정당하다고 인정할 경우 이를 처리하여야 합니다. 처리한 결과는 “서비스” 화면 또는 E-mail을 통해 “회원”에게 통지합니다. -5. ”회사”는 서비스의 개선, 고객 만족도 향상 등의 목적으로 회원의 사전 동의 없이 회원 전체 또는 일부의 개인 정보에 관한 통계 자료를 작성하여 이를 사용할 수 있습니다. - -## 제 12조 (감상 사진) - ---- - -1. "감상 사진"는 "회원"이 서비스를 이용하면서 서비스 내에 업로드한 사진을 의미합니다. -2. "감상 사진"에는 아래의 내용이 포함되어서는 안됩니다. -① 타인(회사 및 콘텐츠의 출연자 포함)의 명예를 훼손하거나 근거 없이 비방하는 내용 -② 욕설, 음란/외설적 내용, 폭력적인 내용 등 미풍양속에 반하는 내용 -③ 저작권을 포함한 타인(회사 및 콘텐츠의 출연자 포함)의 지식재산권을 침해하는 내용 -④ 근거 없이 공포심이나 불안감을 지속적으로 유발하는 내용 -⑤ 선량한 풍속 기타 사회질서에 반하는 내용 -⑥ 민감한 개인정보를 포함한 내용 -3. 제2항의 위반 사유가 확인된 인증 콘텐츠에 대해서는 임시 삭제 조치가 취해질 수 있습니다. 단, 해당 콘텐츠를 작성한 회원은 자신의 콘텐츠가 제2항의 위반 사유에 해당하지 않음을 소명하여 해당 조치를 해제할 수 있습니다. -4. “회사”는 제2항의 위반 사유가 확인되었거나 일정 횟수 이상 신고를 받은 “회원”에 대하여 “서비스”의 이용을 제한할 수 있으며 "계정"을 중지시키고 이용계약을 해지할 수 있습니다. -5. "회사"는 “회원”의 "감상 사진"에 대해서는 적법성, 정확성, 진실성 등을 보증하지 않습니다. -6. "회사"는 서비스의 홍보 내지 개선을 위해 "감상 사진"을 사용할 수 있으며, 이러한 목적 범위 내에서 “감상 콘텐츠”에 대한 편집, 수정, 복제 등의 행위를 할 수 있습니다. - -## **제 13조 (경로)** - ---- - -1. “경로"는 "회원"이 서비스를 이용하면서 수집된 위치 정보를 의미합니다. -2. “회사”는 “회원”이 제공하는 위치 정보에 대하여 회사의 공지, 서비스 이용안내에서 정한 보관 기한에 따라 정보를 보관할 수 있습니다. -3. "회사"는 서비스의 홍보 내지 개선을 위해 "경로"를 사용할 수 있으며, 이러한 목적 범위 내에서 “경로”에 대한 편집, 수정, 복제 등의 행위를 할 수 있습니다. - -## **제 14조 (자료의 저장)** - ---- - -1. “회사”는 “회원”이 제공하는 정보, 자료에 대하여 회사의 공지, 서비스 이용안내에서 정한 바에 따라 일정한 게재/이용 기한 및 용량을 정할 수 있습니다. -2. 서비스의 사용을 통해 다운로드 및 동기화하거나 작성한 문서 및 자료는 회원의 재량 및 위험부담에 따르며, 그러한 사용으로 인해 발생하는 기기에 대한 피해나 데이터 손실에 대한 책임은 전적으로 회원에게 있습니다. -3. 회사는 콘텐츠 유실에 대해 책임지지 않습니다. 콘텐츠 유실은 다음을 포함하되 이에 국한되지 않습니다. - - ① 이용자 PC에서 다루는 제3자 제공 프로그램의 종료 및 오류로 인하여, 파일이 손상되었거나 Polaris Office에 업로드 도중 파일이 잘못 저장된 경우 - ② 이용자 PC 혹은 스마트폰에서 업로드 시 사용한 네트워크 연결상태 및 네트워크 환경상의 장애 및 오류 등으로 인하여, 정상적으로 파일이 업로드되지 않은 경우 - ③ 이용자 PC / 네트워크 등 환경 문제, ID / 비밀번호 분실 및 도용, 관리소홀 등 사용자 책임이 있는 경우 - ④ 천재지변, 국가비상사태 또는 이에 준하는 불가항력적인 사유로 인한 Polaris Office 파일 손실이 있는 경우 - - ⑤ 기타 위 사례를 포함하여, 회사의 책임이 없는 사유로 판단될 수 있는 경우 - - -## **제 15조 (데이터 및 기타 자료의 수집 및 사용 등)** - ---- - -1. “회사”는 본 클라이언트와 관련하여 사용자에게 제공되는 제품지원 서비스의 일환으로 회원의 디바이스의 데이터를 수집하고 사용할 수 있습니다. - -2. “회사”는 제1항의 자료를 본 클라이언트 또는 서비스를 개선하거나 이용자의 사용환경에 적합한 서비스 또는 기술을 제공하기 위한 목적으로만 사용하며 그 외의 다른 목적으로 사용하지 않습니다. - -3. “회사”는 본 클라이언트의 정상적인 이용을 위해 추가 구성 요소를 함께 설치할 수 있으며, 추가 구성 요소에 대하여는 본 클라이언트에 대한 본 약관의 규정을 같이 적용합니다. - -## 제 16조 (회사의 면책) - ---- - -1. “회사”는 전시, 사변, 천재지변, 비상사태, 현재의 기술로는 해결이 불가능한 기술적 결함 기타 불가항력적 사유로 서비스를 제공할 수 없는 경우에는 책임이 면제됩니다. -2. ”회사”는 인터넷 이용자 또는 “회원”의 귀책사유로 인한 서비스 이용의 장애에 대하여 책임을 지지 않습니다. -3. “회사”는 “회사”가 제공하는 거래서비스를 통하지 아니하고 이루어지는 개별 계약과 “회원” 본인이 제공한 신상등록정보의 오류, 미비 등으로 인하여 발생하는 손해에 대해서는 책임을 지지 않습니다. -4. “회사”는 “회원”이 다른 “회원”에 의해 게재된 정보, 자료, 사실의 정확성 등을 신뢰함으로써 입은 손해에 대하여 책임을 지지 않습니다. -5. "회사"는 "회원"의 모바일 네트워크 또는 모바일 디바이스 환경으로 인하여 발생하는 제반 문제 또는 "회사"의 고의 또는 중대한 과실이 없는 네트워크 환경으로 인하여 발생하는 문제에 대해서 책임이 면제됩니다. -6. “회사”는 “회원”이 “회사”가 제공하는 정보에 관하여 그 수신을 거부하여 발생하는 손해에 대해서는 책임을 지지 않습니다. - -## 제 17조(재판권 및 준거법) - -— - -1. "회사"와 "회원" 간에 제기된 법적 분쟁은 대한민국 법을 준거법으로 합니다. -2. "회사”와 회원간 발생한 분쟁에 관한 소송은 제소 당시의 회원의 주소에 의하고 주소가 없는 경우 “거소를 관할하는 지방법원의 전속관할로 합니다. 단 제소 당시 회원의 주소 또는 거소가 명확하지 아니한 경우의 관할법원은 민사소송법에 따라 정합니다. -3. 해외에 주소나 거소가 있는 회원의 경우 회사와 회원간 발생한 분쟁에 관한 소송은 전항에도 불구하고 대한민국 서울중앙지방법원을 관할 법원으로 합니다. - -## 부칙 - -— - -본 약관은 2023년 08월 14일부터 발효됩니다. From 56d40295059925e3937f1ff89d3412ad93ce8e7a Mon Sep 17 00:00:00 2001 From: otter Date: Thu, 12 Oct 2023 21:36:37 +0900 Subject: [PATCH 05/39] =?UTF-8?q?[feat]=20=EB=A7=88=EC=9D=B4=ED=8E=98?= =?UTF-8?q?=EC=9D=B4=EC=A7=80=20=EC=9D=B4=EC=9A=A9=EC=95=BD=EA=B4=80=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#309)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/ui/myPage/MyPageFragment.kt | 10 ++++++++ .../android/ui/myPage/MyPageViewModel.kt | 8 ++++++ .../src/main/res/layout/fragment_my_page.xml | 25 ++++++++++++++++++- android/app/src/main/res/values/strings.xml | 1 + 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/myPage/MyPageFragment.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/myPage/MyPageFragment.kt index 3c306fea4..acf9b7245 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/myPage/MyPageFragment.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/myPage/MyPageFragment.kt @@ -47,6 +47,7 @@ class MyPageFragment : Fragment() { private fun initObserver() { initOpenTripHistoryObserver() + initOpenTermsOfServiceObserver() initOpenOpenSourceLicenseObserver() initOpenPrivacyPolicyObserver() initLogOutEventObserver() @@ -60,6 +61,15 @@ class MyPageFragment : Fragment() { } } + private fun initOpenTermsOfServiceObserver() { + viewModel.openTermsOfService.observe(viewLifecycleOwner) { + if (it.not()) return@observe + val browserIntent = + Intent(Intent.ACTION_VIEW, Uri.parse(BuildConfig.TERMS_OF_SERVICE_URL)) + startActivity(browserIntent) + } + } + private fun initOpenOpenSourceLicenseObserver() { viewModel.openOpenSourceLicenseEvent.observe(viewLifecycleOwner) { if (it.not()) return@observe diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/myPage/MyPageViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/myPage/MyPageViewModel.kt index 7c59d72ae..a069a3618 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/myPage/MyPageViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/myPage/MyPageViewModel.kt @@ -27,6 +27,9 @@ class MyPageViewModel @Inject constructor( private val _openTripHistoryEvent: MutableLiveData = MutableLiveData() val openTripHistoryEvent: LiveData = _openTripHistoryEvent + private val _openTermsOfService: MutableLiveData = MutableLiveData(false) + val openTermsOfService: LiveData = _openTermsOfService + private val _openOpenSourceLicenseEvent: MutableLiveData = MutableLiveData(false) val openOpenSourceLicenseEvent: LiveData = _openOpenSourceLicenseEvent @@ -70,6 +73,11 @@ class MyPageViewModel @Inject constructor( _logoutEvent.value = false } + fun openTermsOfService() { + _openTermsOfService.value = true + _openTermsOfService.value = false + } + fun openOpenSourceLicense() { _openOpenSourceLicenseEvent.value = true _openOpenSourceLicenseEvent.value = false diff --git a/android/app/src/main/res/layout/fragment_my_page.xml b/android/app/src/main/res/layout/fragment_my_page.xml index ec35d8e3f..78a9e4cbe 100644 --- a/android/app/src/main/res/layout/fragment_my_page.xml +++ b/android/app/src/main/res/layout/fragment_my_page.xml @@ -103,7 +103,7 @@ app:layout_constraintTop_toBottomOf="@id/divider_nickname_layout" /> + + + + 닉네임 나의 여행 개인정보 처리방침 + 이용약관 오픈소스 라이선스 버전정보 로그아웃 From 87d19df25abd60c58b5d7e42eeafa29638c73a1d Mon Sep 17 00:00:00 2001 From: pingu244 Date: Fri, 13 Oct 2023 18:20:27 +0900 Subject: [PATCH 06/39] =?UTF-8?q?[refactor]=20Post=20dto=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#484)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../httpClient/dto/mapper/PostDtoMapper.kt | 2 ++ .../dto/response/GetTripPostListResponse.kt | 4 ++++ .../android/data/model/DataPost.kt | 2 ++ .../data/model/mapper/PostDataMapper.kt | 2 ++ .../android/ui/model/UiPostDetail.kt | 2 ++ .../android/ui/model/mapper/PostUiMapper.kt | 2 ++ .../android/domain/model/post/Post.kt | 18 ++---------------- 7 files changed, 16 insertions(+), 16 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PostDtoMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PostDtoMapper.kt index 98e31f8b7..fb42fbe2c 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PostDtoMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PostDtoMapper.kt @@ -65,6 +65,8 @@ fun GetTripPostResponse.toData(): DataPost { point = point.toData(), postImageUrl = postImageUrl, routeImageUrl = routeImageUrl, + isMine = isMine, + authorNickname = authorNickname, ) } diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetTripPostListResponse.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetTripPostListResponse.kt index 434a6c4f1..1bd6cc9d1 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetTripPostListResponse.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetTripPostListResponse.kt @@ -27,4 +27,8 @@ data class GetTripPostResponse( val tripId: Long, @Json(name = "writing") val writing: String, + @Json(name = "isMine") + val isMine: Boolean, + @Json(name = "authorNickname") + val authorNickname: String, ) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/model/DataPost.kt b/android/app/src/main/java/com/teamtripdraw/android/data/model/DataPost.kt index 537d08d1e..5ec91c0c5 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/model/DataPost.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/model/DataPost.kt @@ -9,4 +9,6 @@ data class DataPost( val point: DataPoint, val postImageUrl: String, val routeImageUrl: String, + val isMine: Boolean, + val authorNickname: String, ) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/PostDataMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/PostDataMapper.kt index 856a63f49..83c0d8d21 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/PostDataMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/PostDataMapper.kt @@ -38,6 +38,8 @@ fun DataPost.toDomain(): Post { point = point.toDomain(), postImageUrl = postImageUrl, routeImageUrl = routeImageUrl, + isMine = isMine, + authorNickname = authorNickname, ) } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPostDetail.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPostDetail.kt index 91894eda4..06ee35e1b 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPostDetail.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPostDetail.kt @@ -8,4 +8,6 @@ data class UiPostDetail( val recordedAt: String, val postImageUrl: String, val routeImageUrl: String, + val isMine: Boolean, + val authorNickname: String, ) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/PostUiMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/PostUiMapper.kt index 0abac2e4d..b22c7268f 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/PostUiMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/PostUiMapper.kt @@ -25,6 +25,8 @@ fun Post.toDetailPresentation() = UiPostDetail( recordedAt = this.point.recordedAt.formattedDateTime(), postImageUrl = this.postImageUrl, routeImageUrl = this.routeImageUrl, + isMine = this.isMine, + authorNickname = this.authorNickname, ) fun PostOfAll.toPresentation() = UiPostOfAll( diff --git a/android/domain/src/main/java/com/teamtripdraw/android/domain/model/post/Post.kt b/android/domain/src/main/java/com/teamtripdraw/android/domain/model/post/Post.kt index d02816b20..e93842ba8 100644 --- a/android/domain/src/main/java/com/teamtripdraw/android/domain/model/post/Post.kt +++ b/android/domain/src/main/java/com/teamtripdraw/android/domain/model/post/Post.kt @@ -11,25 +11,11 @@ data class Post( val point: Point, val postImageUrl: String, val routeImageUrl: String, + val isMine: Boolean, + val authorNickname: String, ) { companion object { const val NULL_SUBSTITUTE_ID = -1L - - fun getPrePost( - tripId: Long, - pointId: Long, - title: String, - writing: String, - address: String, - ): PrePost { - return PrePost( - tripId = tripId, - pointId = pointId, - title = title, - writing = writing, - address = address, - ) - } } } From f78f4c26ffb32132b9ad5cd99efff294ffdadde7 Mon Sep 17 00:00:00 2001 From: pingu244 Date: Fri, 13 Oct 2023 18:40:09 +0900 Subject: [PATCH 07/39] =?UTF-8?q?[refactor]=20PostOfAll=20dto=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#484)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/data/httpClient/dto/mapper/PostDtoMapper.kt | 2 ++ .../data/httpClient/dto/response/GetAllPostsResponse.kt | 4 ++++ .../java/com/teamtripdraw/android/data/model/DataPostOfAll.kt | 2 ++ .../teamtripdraw/android/data/model/mapper/PostDataMapper.kt | 2 ++ .../java/com/teamtripdraw/android/ui/model/UiPostOfAll.kt | 2 ++ .../com/teamtripdraw/android/ui/model/mapper/PostUiMapper.kt | 3 ++- .../com/teamtripdraw/android/domain/model/post/PostOfAll.kt | 2 ++ 7 files changed, 16 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PostDtoMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PostDtoMapper.kt index fb42fbe2c..4d04863b1 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PostDtoMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PostDtoMapper.kt @@ -84,6 +84,8 @@ fun GetAllPostsResponse.toData(): List { postImageUrl = it.postImageUrl, routeImageUrl = it.routeImageUrl, recordedAt = it.recordedAt, + isMine = it.isMine, + authorNickname = it.authorNickname, ) } return posts diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetAllPostsResponse.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetAllPostsResponse.kt index 0ce2e0fd9..ba7319374 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetAllPostsResponse.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetAllPostsResponse.kt @@ -29,4 +29,8 @@ data class Post( val tripId: Long, @Json(name = "writing") val writing: String, + @Json(name = "isMine") + val isMine: Boolean, + @Json(name = "authorNickname") + val authorNickname: String, ) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/model/DataPostOfAll.kt b/android/app/src/main/java/com/teamtripdraw/android/data/model/DataPostOfAll.kt index 438710ee2..0d1548952 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/model/DataPostOfAll.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/model/DataPostOfAll.kt @@ -9,4 +9,6 @@ data class DataPostOfAll( val postImageUrl: String, val routeImageUrl: String, val recordedAt: String, + val isMine: Boolean, + val authorNickname: String, ) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/PostDataMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/PostDataMapper.kt index 83c0d8d21..4be415f43 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/PostDataMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/PostDataMapper.kt @@ -53,5 +53,7 @@ fun DataPostOfAll.toDomain(): PostOfAll { postImageUrl = postImageUrl, routeImageUrl = routeImageUrl, recordedAt = LocalDateTime.parse(recordedAt), + isMine = isMine, + authorNickname = authorNickname, ) } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPostOfAll.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPostOfAll.kt index c7bcdb4cd..8014053a9 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPostOfAll.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPostOfAll.kt @@ -9,4 +9,6 @@ data class UiPostOfAll( val postImageUrl: String, val routeImageUrl: String, val recordedAt: String, + val isMine: Boolean, + val authorNickname: String, ) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/PostUiMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/PostUiMapper.kt index b22c7268f..07130d0e9 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/PostUiMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/PostUiMapper.kt @@ -38,7 +38,8 @@ fun PostOfAll.toPresentation() = UiPostOfAll( postImageUrl = this.postImageUrl, routeImageUrl = this.routeImageUrl, recordedAt = this.recordedAt.formattedDateTime(), - + isMine = this.isMine, + authorNickname = this.authorNickname, ) private fun LocalDateTime.formattedDateTime() = diff --git a/android/domain/src/main/java/com/teamtripdraw/android/domain/model/post/PostOfAll.kt b/android/domain/src/main/java/com/teamtripdraw/android/domain/model/post/PostOfAll.kt index 1becfa218..56998358a 100644 --- a/android/domain/src/main/java/com/teamtripdraw/android/domain/model/post/PostOfAll.kt +++ b/android/domain/src/main/java/com/teamtripdraw/android/domain/model/post/PostOfAll.kt @@ -11,4 +11,6 @@ data class PostOfAll( val postImageUrl: String, val routeImageUrl: String, val recordedAt: LocalDateTime, + val isMine: Boolean, + val authorNickname: String, ) From ad1eb189d2cb73036e7d26ec2b7773a2c5421752 Mon Sep 17 00:00:00 2001 From: pingu244 Date: Fri, 13 Oct 2023 19:04:17 +0900 Subject: [PATCH 08/39] =?UTF-8?q?[refactor]=20Trip=20dto=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#484)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/data/httpClient/dto/mapper/TripDtoMapper.kt | 2 ++ .../data/httpClient/dto/response/GetTripInfoResponse.kt | 4 ++++ .../main/java/com/teamtripdraw/android/data/model/DataTrip.kt | 2 ++ .../com/teamtripdraw/android/data/model/mapper/TripMapper.kt | 2 ++ .../java/com/teamtripdraw/android/domain/model/trip/Trip.kt | 2 ++ 5 files changed, 12 insertions(+) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/TripDtoMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/TripDtoMapper.kt index b1f2fcb3b..a665b737c 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/TripDtoMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/TripDtoMapper.kt @@ -20,6 +20,8 @@ fun GetTripInfoResponse.toData(): DataTrip = status = status, imageUrl = imageUrl, routeImageUrl = routeImageUrl, + isMine = isMine, + authorNickname = authorNickname, ) fun GetTripInfoPoint.toData(): DataPoint = diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetTripInfoResponse.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetTripInfoResponse.kt index d048fb0b4..57fe8e16a 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetTripInfoResponse.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetTripInfoResponse.kt @@ -17,6 +17,10 @@ data class GetTripInfoResponse( val imageUrl: String, @Json(name = "routeImageUrl") val routeImageUrl: String, + @Json(name = "isMine") + val isMine: Boolean, + @Json(name = "authorNickname") + val authorNickname: String, ) @JsonClass(generateAdapter = true) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/model/DataTrip.kt b/android/app/src/main/java/com/teamtripdraw/android/data/model/DataTrip.kt index 3284e0d43..073e00699 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/model/DataTrip.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/model/DataTrip.kt @@ -7,4 +7,6 @@ data class DataTrip( val status: String, val imageUrl: String, val routeImageUrl: String, + val isMine: Boolean, + val authorNickname: String, ) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/TripMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/TripMapper.kt index 6ea7d4ca9..9e8f5e99d 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/TripMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/TripMapper.kt @@ -22,6 +22,8 @@ fun DataTrip.toDomain(): Trip = status = status, imageUrl = imageUrl, routeImageUrl = routeImageUrl, + isMine = isMine, + authorNickname = authorNickname, ) fun PreSetTripTitle.toData(): DataPreSetTripTitle = diff --git a/android/domain/src/main/java/com/teamtripdraw/android/domain/model/trip/Trip.kt b/android/domain/src/main/java/com/teamtripdraw/android/domain/model/trip/Trip.kt index 37d4f02fd..9e449ec85 100644 --- a/android/domain/src/main/java/com/teamtripdraw/android/domain/model/trip/Trip.kt +++ b/android/domain/src/main/java/com/teamtripdraw/android/domain/model/trip/Trip.kt @@ -9,6 +9,8 @@ data class Trip( val status: String, val imageUrl: String, val routeImageUrl: String, + val isMine: Boolean, + val authorNickname: String, ) { companion object { const val NULL_SUBSTITUTE_ID = -1L From 77e080eeb1cf22ab65f31cb6fede06ccce655368 Mon Sep 17 00:00:00 2001 From: pingu244 Date: Fri, 13 Oct 2023 19:09:12 +0900 Subject: [PATCH 09/39] =?UTF-8?q?[refactor]=20TripOfAll=20dto=20=EC=88=98?= =?UTF-8?q?=EC=A0=95=20(#484)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/data/httpClient/dto/mapper/TripDtoMapper.kt | 2 ++ .../data/httpClient/dto/response/GetAllTripsResponse.kt | 4 ++++ .../com/teamtripdraw/android/data/model/DataTripOfAll.kt | 2 ++ .../teamtripdraw/android/data/model/mapper/TripMapper.kt | 2 ++ .../java/com/teamtripdraw/android/ui/model/UiTripOfAll.kt | 2 ++ .../teamtripdraw/android/ui/model/mapper/TripUiMapper.kt | 6 ++++-- .../com/teamtripdraw/android/domain/model/trip/TripOfAll.kt | 2 ++ 7 files changed, 18 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/TripDtoMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/TripDtoMapper.kt index a665b737c..1d31aa641 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/TripDtoMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/TripDtoMapper.kt @@ -56,6 +56,8 @@ fun GetAllTripsResponse.toData(): List { routeImageUrl = it.routeImageUrl, startTime = it.startTime, endTime = it.endTime, + isMine = it.isMine, + authorNickname = it.authorNickname, ) } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetAllTripsResponse.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetAllTripsResponse.kt index 9db1bdffe..088aa8781 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetAllTripsResponse.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetAllTripsResponse.kt @@ -25,4 +25,8 @@ data class Trip( val startTime: String, @Json(name = "tripId") val tripId: Long, + @Json(name = "isMine") + val isMine: Boolean, + @Json(name = "authorNickname") + val authorNickname: String, ) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/model/DataTripOfAll.kt b/android/app/src/main/java/com/teamtripdraw/android/data/model/DataTripOfAll.kt index 298febd43..a2b5ee12f 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/model/DataTripOfAll.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/model/DataTripOfAll.kt @@ -7,4 +7,6 @@ data class DataTripOfAll( val routeImageUrl: String, val startTime: String, val endTime: String, + val isMine: Boolean, + val authorNickname: String, ) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/TripMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/TripMapper.kt index 9e8f5e99d..0a7b07dbd 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/TripMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/model/mapper/TripMapper.kt @@ -40,4 +40,6 @@ fun DataTripOfAll.toDomain(): TripOfAll = routeImageUrl = routeImageUrl, startTime = LocalDateTime.parse(startTime), endTime = LocalDateTime.parse(endTime), + isMine = isMine, + authorNickname = authorNickname, ) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiTripOfAll.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiTripOfAll.kt index 2bd87bef8..055d3de86 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiTripOfAll.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiTripOfAll.kt @@ -7,4 +7,6 @@ data class UiTripOfAll( val routeImageUrl: String, val startTime: String, val endTime: String, + val isMine: Boolean, + val authorNickname: String, ) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/TripUiMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/TripUiMapper.kt index dbcfca5d5..63af1fe32 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/TripUiMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/TripUiMapper.kt @@ -28,8 +28,8 @@ fun Trip.toPreviewPresentation(): UiPreviewTrip = UiPreviewTrip( id = tripId, name = name, - imageUrl = imageUrl ?: "", - routeImageUrl = routeImageUrl ?: "", + imageUrl = imageUrl, + routeImageUrl = routeImageUrl, ) fun UiPreviewTrip.toDomain(): PreviewTrip = @@ -47,6 +47,8 @@ fun TripOfAll.toPresentation() = UiTripOfAll( routeImageUrl = routeImageUrl, startTime = startTime.formattedTripDate(), endTime = endTime.formattedTripDate(), + isMine = isMine, + authorNickname = authorNickname, ) private fun LocalDateTime.formattedTripDate() = diff --git a/android/domain/src/main/java/com/teamtripdraw/android/domain/model/trip/TripOfAll.kt b/android/domain/src/main/java/com/teamtripdraw/android/domain/model/trip/TripOfAll.kt index 9a2c1f276..5edbf1d2a 100644 --- a/android/domain/src/main/java/com/teamtripdraw/android/domain/model/trip/TripOfAll.kt +++ b/android/domain/src/main/java/com/teamtripdraw/android/domain/model/trip/TripOfAll.kt @@ -9,4 +9,6 @@ data class TripOfAll( val routeImageUrl: String, val startTime: LocalDateTime, val endTime: LocalDateTime, + val isMine: Boolean, + val authorNickname: String, ) From 4a29d5aaa58e85bda699ef171b795fe03e3d4751 Mon Sep 17 00:00:00 2001 From: pingu244 <69796976+pingu244@users.noreply.github.com> Date: Sat, 14 Oct 2023 23:36:21 +0900 Subject: [PATCH 10/39] =?UTF-8?q?[ui]=20=EC=A0=84=EC=B2=B4=20/=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=EC=9E=90=20=EB=8B=89=EB=84=A4=EC=9E=84=20=ED=8F=AC?= =?UTF-8?q?=ED=95=A8=EC=8B=9C=ED=82=A4=EA=B8=B0=20(#472)=20(#487)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [refactor] 전체 여행, 전체 감상 / memberNickname dto 추가 (#472) * [ui] 전체 감상 / 화면에 닉네임 추가 (#472) * [ui] 전체 감상 / 닉네임 추가 (#472) * [ui] 전체 여행 / 닉네임 추가 (#472) * [ui] 감상 상세 / 닉네임 추가 (#472) * [refactor] 불필요 코드 삭제 (#472) --- android/app/src/main/res/drawable/ic_user.xml | 10 ++++++ .../main/res/layout/activity_post_detail.xml | 32 ++++++++++++++--- .../src/main/res/layout/item_all_posts.xml | 34 ++++++++++++++---- .../src/main/res/layout/item_all_trips.xml | 36 +++++++++++++------ 4 files changed, 91 insertions(+), 21 deletions(-) create mode 100644 android/app/src/main/res/drawable/ic_user.xml diff --git a/android/app/src/main/res/drawable/ic_user.xml b/android/app/src/main/res/drawable/ic_user.xml new file mode 100644 index 000000000..a4dda7313 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_user.xml @@ -0,0 +1,10 @@ + + + diff --git a/android/app/src/main/res/layout/activity_post_detail.xml b/android/app/src/main/res/layout/activity_post_detail.xml index 6ece2ef23..3bf457e0b 100644 --- a/android/app/src/main/res/layout/activity_post_detail.xml +++ b/android/app/src/main/res/layout/activity_post_detail.xml @@ -103,6 +103,28 @@ app:layout_constraintTop_toBottomOf="@id/tv_post_detail_recorded_at" tools:text="우도의 바닷가" /> + + + + + app:layout_constraintStart_toStartOf="@id/iv_post_detail_user_icon" + app:layout_constraintTop_toBottomOf="@id/iv_post_detail_user_icon" /> @@ -150,11 +173,12 @@ + app:layout_constraintStart_toStartOf="@id/iv_item_all_posts_user_icon" + app:layout_constraintTop_toBottomOf="@id/iv_item_all_posts_user_icon" /> + + + + + + + + - - From 089d84f419e171fb94b3f3f4f9288940499e021a Mon Sep 17 00:00:00 2001 From: pingu244 <69796976+pingu244@users.noreply.github.com> Date: Sun, 15 Oct 2023 19:41:22 +0900 Subject: [PATCH 11/39] =?UTF-8?q?[refactor]=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EA=B0=90=EC=83=81=20/=20=EB=AC=B4=ED=95=9C=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A1=A4=20(#458)=20(#465)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [refactor] 전체 감상 / viewType 나누기 (#458) * [refactor] 필터 화면 / 코드 정리 (#438) * [refactor] 필터 화면 / 무한 스크롤 기능 추가 (#438) * [refactor] 필터 화면 / 로딩화면에 lottie 적용 (#438) * [refactor] 전체 감상 / lottie 색상 변경 (#458) * [refactor] 전체 감상 / 피드백 반영 (#458) * [refactor] 전체 감상 / 무한스크롤 로딩 아이템 생성 (#458) * [fix] 전체 감상 / 무한스크롤 작동하게 수정 (#458) * [refactor] 전체 감상 / 코드 리팩터링 (#458) - UiLoading 오브젝트로 수정 - 다음 아이템 로딩시 이전 아이템까지 다시 로딩되는 현상 수정 --- android/app/build.gradle.kts | 3 + .../android/ui/allPosts/AllPostsAdapter.kt | 67 +- .../android/ui/allPosts/AllPostsFragment.kt | 34 +- .../android/ui/allPosts/AllPostsViewHolder.kt | 10 +- .../android/ui/allPosts/AllPostsViewModel.kt | 57 +- .../bindingAdapter/CommonBindingAdapter.kt | 6 +- .../android/ui/model/UiAllPosts.kt | 6 - .../android/ui/model/allPosts/UiAllPosts.kt | 6 + .../android/ui/model/allPosts/UiItemView.kt | 3 + .../ui/model/allPosts/UiLoadingItem.kt | 3 + .../ui/model/{ => allPosts}/UiPostOfAll.kt | 4 +- .../android/ui/model/mapper/PostUiMapper.kt | 2 +- .../main/res/layout/activity_my_history.xml | 2 +- .../main/res/layout/activity_post_viewer.xml | 2 +- .../main/res/layout/fragment_all_posts.xml | 2 +- .../main/res/layout/fragment_all_trips.xml | 2 +- .../src/main/res/layout/item_all_posts.xml | 8 +- .../app/src/main/res/layout/item_loading.xml | 12 + android/app/src/main/res/raw/loading.json | 1094 +++++++++++++++++ android/gradle/libs.versions.toml | 6 + 20 files changed, 1283 insertions(+), 46 deletions(-) delete mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/model/UiAllPosts.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiAllPosts.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiItemView.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiLoadingItem.kt rename android/app/src/main/java/com/teamtripdraw/android/ui/model/{ => allPosts}/UiPostOfAll.kt (81%) create mode 100644 android/app/src/main/res/layout/item_loading.xml create mode 100644 android/app/src/main/res/raw/loading.json diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 8bfa7da61..b46a8a079 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -240,4 +240,7 @@ dependencies { // hilt implementation(libs.hilt) kapt(libs.hiltKapt) + + // lottie + implementation(libs.lottie) } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsAdapter.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsAdapter.kt index a73b31836..f8c27cd28 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsAdapter.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsAdapter.kt @@ -1,37 +1,76 @@ package com.teamtripdraw.android.ui.allPosts +import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter -import com.teamtripdraw.android.ui.model.UiPostOfAll +import androidx.recyclerview.widget.RecyclerView +import com.teamtripdraw.android.databinding.ItemLoadingBinding +import com.teamtripdraw.android.ui.model.allPosts.UiItemView +import com.teamtripdraw.android.ui.model.allPosts.UiLoadingItem +import com.teamtripdraw.android.ui.model.allPosts.UiPostOfAll class AllPostsAdapter( - private val viewModel: AllPostsViewModel, -) : ListAdapter(diffUtil) { + private val openPostEvent: (Long) -> Unit, +) : ListAdapter(diffUtil) { - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AllPostsViewHolder { - return AllPostsViewHolder.of(parent, viewModel) + override fun getItemViewType(position: Int): Int { + return if (getItem(position) is UiLoadingItem) { + LOADING_VIEW + } else { + POST_VIEW + } + } + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return when (viewType) { + LOADING_VIEW -> LoadingViewHolder.of(parent) + else -> AllPostsViewHolder.of(parent, openPostEvent) + } } - override fun onBindViewHolder(holder: AllPostsViewHolder, position: Int) { - holder.bind(getItem(position)) + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is AllPostsViewHolder) holder.bind(getItem(position) as UiPostOfAll) } companion object { - val diffUtil = object : DiffUtil.ItemCallback() { + private const val LOADING_VIEW = 1 + private const val POST_VIEW = 2 + + val diffUtil = object : DiffUtil.ItemCallback() { override fun areItemsTheSame( - oldItem: UiPostOfAll, - newItem: UiPostOfAll, + oldItem: UiItemView, + newItem: UiItemView, ): Boolean { - return oldItem.postId == newItem.postId + if (oldItem is UiPostOfAll && newItem is UiPostOfAll) { + return oldItem.postId == newItem.postId + } + return false } override fun areContentsTheSame( - oldItem: UiPostOfAll, - newItem: UiPostOfAll, + oldItem: UiItemView, + newItem: UiItemView, ): Boolean { - return oldItem == newItem + if (oldItem is UiPostOfAll && newItem is UiPostOfAll) { + return oldItem == newItem + } + return false } } } + + class LoadingViewHolder(val binding: ItemLoadingBinding) : + RecyclerView.ViewHolder(binding.root) { + companion object { + fun of(parent: ViewGroup): LoadingViewHolder = + LoadingViewHolder( + ItemLoadingBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false, + ), + ) + } + } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsFragment.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsFragment.kt index 302139ce4..5bcae63ea 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsFragment.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsFragment.kt @@ -6,6 +6,8 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import com.teamtripdraw.android.databinding.FragmentAllPostsBinding import com.teamtripdraw.android.support.framework.presentation.event.EventObserver import com.teamtripdraw.android.ui.post.detail.PostDetailActivity @@ -31,6 +33,7 @@ class AllPostsFragment : Fragment() { bindViewModel() initObserver() setAdapter() + addScrollListener() return binding.root } @@ -62,10 +65,34 @@ class AllPostsFragment : Fragment() { } private fun setAdapter() { - adapter = AllPostsAdapter(viewModel) + adapter = AllPostsAdapter(viewModel::openPostDetail) binding.rvAllPosts.adapter = adapter } + private fun addScrollListener() { + binding.rvAllPosts.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + val layoutManager = binding.rvAllPosts.layoutManager as LinearLayoutManager + val lastPosition = layoutManager.findLastCompletelyVisibleItemPosition() + checkFetchPostsCondition(layoutManager, lastPosition) + } + }) + } + + private fun checkFetchPostsCondition(layoutManager: LinearLayoutManager, lastPosition: Int) { + if (viewModel.hasNextPage && + viewModel.isAddLoading.not() && + checkLoadThreshold(layoutManager, lastPosition) && + binding.rvAllPosts.canScrollVertically(DOWNWARD_DIRECTION).not() + ) { + viewModel.fetchPosts() + } + } + + private fun checkLoadThreshold(layoutManager: LinearLayoutManager, lastPosition: Int) = + layoutManager.itemCount <= lastPosition + LOAD_THRESHOLD + override fun onResume() { super.onResume() fetchPosts() @@ -77,4 +104,9 @@ class AllPostsFragment : Fragment() { super.onDestroyView() _binding = null } + + companion object { + private const val LOAD_THRESHOLD = 3 + private const val DOWNWARD_DIRECTION = 1 + } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsViewHolder.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsViewHolder.kt index 31da266e8..754d7c368 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsViewHolder.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsViewHolder.kt @@ -4,15 +4,15 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.teamtripdraw.android.databinding.ItemAllPostsBinding -import com.teamtripdraw.android.ui.model.UiPostOfAll +import com.teamtripdraw.android.ui.model.allPosts.UiPostOfAll class AllPostsViewHolder( private val binding: ItemAllPostsBinding, - viewModel: AllPostsViewModel, + openPostEvent: (Long) -> Unit, ) : RecyclerView.ViewHolder(binding.root) { init { - binding.allPostsViewModel = viewModel + binding.openPostEvent = openPostEvent } fun bind(item: UiPostOfAll) { @@ -22,14 +22,14 @@ class AllPostsViewHolder( companion object { fun of( parent: ViewGroup, - viewModel: AllPostsViewModel, + openPostEvent: (Long) -> Unit, ): AllPostsViewHolder { val binding = ItemAllPostsBinding.inflate( LayoutInflater.from(parent.context), parent, false, ) - return AllPostsViewHolder(binding, viewModel) + return AllPostsViewHolder(binding, openPostEvent) } } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsViewModel.kt index 381a357f1..ba0a180c6 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsViewModel.kt @@ -9,7 +9,9 @@ import com.teamtripdraw.android.TripDrawApplication import com.teamtripdraw.android.domain.model.post.PostOfAll import com.teamtripdraw.android.domain.repository.PostRepository import com.teamtripdraw.android.support.framework.presentation.event.Event -import com.teamtripdraw.android.ui.model.UiAllPosts +import com.teamtripdraw.android.ui.model.allPosts.UiAllPosts +import com.teamtripdraw.android.ui.model.allPosts.UiItemView +import com.teamtripdraw.android.ui.model.allPosts.UiLoadingItem import com.teamtripdraw.android.ui.model.mapper.toPresentation import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch @@ -20,18 +22,40 @@ class AllPostsViewModel @Inject constructor( private val postRepository: PostRepository, ) : ViewModel() { - private val _posts: MutableLiveData> = MutableLiveData() - val posts: LiveData = - Transformations.map(_posts) { post -> UiAllPosts(post.map { it.toPresentation() }) } + private val _uiPosts: MutableLiveData> = MutableLiveData(listOf()) + val posts: LiveData = Transformations.map(_uiPosts) { post -> UiAllPosts(post) } private val _openPostDetailEvent = MutableLiveData>() val openPostDetailEvent: LiveData> = _openPostDetailEvent + private var lastId: Long? = null + + var hasNextPage = true + private set + + var isAddLoading = false + private set + fun fetchPosts() { + if (_uiPosts.value!!.isNotEmpty() && hasNextPage) { + isAddLoading = true + addLoadingItem() + } + getPosts() + } + + private fun addLoadingItem() { + _uiPosts.value = _uiPosts.value!!.toMutableList().apply { add(UiLoadingItem) } + } + + private fun getPosts() { viewModelScope.launch { - postRepository.getAllPosts() - .onSuccess { - _posts.value = it + postRepository.getAllPosts(lastViewedId = lastId, limit = PAGE_ITEM_SIZE) + .onSuccess { posts -> + setLastItemId(posts) + setHasNextPage(posts) + isAddLoading = false + fetchPosts(posts) } .onFailure { TripDrawApplication.logUtil.general.log(it) @@ -39,7 +63,26 @@ class AllPostsViewModel @Inject constructor( } } + private fun setLastItemId(posts: List) { + if (posts.isNotEmpty()) lastId = posts.last().postId + } + + private fun setHasNextPage(posts: List) { + if (posts.size < PAGE_ITEM_SIZE && lastId != null) hasNextPage = false + } + + private fun fetchPosts(posts: List) { + _uiPosts.value = _uiPosts.value!!.toMutableList().apply { + remove(UiLoadingItem) + addAll(posts.map { it.toPresentation() }) + } + } + fun openPostDetail(id: Long) { _openPostDetailEvent.value = Event(id) } + + companion object { + private const val PAGE_ITEM_SIZE = 20 + } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/CommonBindingAdapter.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/CommonBindingAdapter.kt index 0d894b321..5694ab5e5 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/CommonBindingAdapter.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/CommonBindingAdapter.kt @@ -5,10 +5,12 @@ import android.widget.ImageView import android.widget.TextView import androidx.databinding.BindingAdapter -@BindingAdapter("app:setMessageVisibility") -fun TextView.setMessageVisibility(isVisible: Boolean) { +@BindingAdapter("app:setNoItemsMessageVisibility") +fun TextView.setNoItemsMessageVisibility(isVisible: Boolean) { if (isVisible) { this.visibility = View.VISIBLE + } else { + this.visibility = View.GONE } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiAllPosts.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiAllPosts.kt deleted file mode 100644 index 97b1fc315..000000000 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiAllPosts.kt +++ /dev/null @@ -1,6 +0,0 @@ -package com.teamtripdraw.android.ui.model - -data class UiAllPosts( - val postItems: List, - val isEmpty: Boolean = postItems.isEmpty(), -) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiAllPosts.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiAllPosts.kt new file mode 100644 index 000000000..81a86c954 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiAllPosts.kt @@ -0,0 +1,6 @@ +package com.teamtripdraw.android.ui.model.allPosts + +data class UiAllPosts( + val postItems: List, + val isEmpty: Boolean = postItems.isEmpty(), +) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiItemView.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiItemView.kt new file mode 100644 index 000000000..971e0f33e --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiItemView.kt @@ -0,0 +1,3 @@ +package com.teamtripdraw.android.ui.model.allPosts + +interface UiItemView diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiLoadingItem.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiLoadingItem.kt new file mode 100644 index 000000000..5dac90a07 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiLoadingItem.kt @@ -0,0 +1,3 @@ +package com.teamtripdraw.android.ui.model.allPosts + +object UiLoadingItem : UiItemView diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPostOfAll.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiPostOfAll.kt similarity index 81% rename from android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPostOfAll.kt rename to android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiPostOfAll.kt index 8014053a9..bf0fc09cc 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPostOfAll.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allPosts/UiPostOfAll.kt @@ -1,4 +1,4 @@ -package com.teamtripdraw.android.ui.model +package com.teamtripdraw.android.ui.model.allPosts data class UiPostOfAll( val postId: Long, @@ -11,4 +11,4 @@ data class UiPostOfAll( val recordedAt: String, val isMine: Boolean, val authorNickname: String, -) +) : UiItemView diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/PostUiMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/PostUiMapper.kt index 07130d0e9..baa0056ba 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/PostUiMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/PostUiMapper.kt @@ -5,7 +5,7 @@ import com.teamtripdraw.android.domain.model.post.PostOfAll import com.teamtripdraw.android.support.framework.presentation.LocalDateTimeFormatter.displayDateTimeFormatter import com.teamtripdraw.android.ui.model.UiPostDetail import com.teamtripdraw.android.ui.model.UiPostItem -import com.teamtripdraw.android.ui.model.UiPostOfAll +import com.teamtripdraw.android.ui.model.allPosts.UiPostOfAll import java.time.LocalDateTime fun Post.toPresentation() = UiPostItem( diff --git a/android/app/src/main/res/layout/activity_my_history.xml b/android/app/src/main/res/layout/activity_my_history.xml index c31201d5f..29457550b 100644 --- a/android/app/src/main/res/layout/activity_my_history.xml +++ b/android/app/src/main/res/layout/activity_my_history.xml @@ -53,7 +53,7 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tb_history" - app:setMessageVisibility="@{historyViewModel.previewTrips.empty}" /> + app:setNoItemsMessageVisibility="@{historyViewModel.previewTrips.empty}" /> + app:setNoItemsMessageVisibility="@{postViewerViewModel.posts.empty}" /> + app:setNoItemsMessageVisibility="@{allPostsViewModel.posts.empty}" /> + app:setNoItemsMessageVisibility="@{allTripsViewModel.trips.empty}" /> + name="openPostEvent" + type="kotlin.jvm.functions.Function1" /> + type="com.teamtripdraw.android.ui.model.allPosts.UiPostOfAll" /> + android:onClick="@{(value)->openPostEvent.invoke(postItem.postId)}"> + diff --git a/android/app/src/main/res/raw/loading.json b/android/app/src/main/res/raw/loading.json new file mode 100644 index 000000000..48ed07ebc --- /dev/null +++ b/android/app/src/main/res/raw/loading.json @@ -0,0 +1,1094 @@ +{ + "v": "4.6.8", + "fr": 60, + "ip": 0, + "op": 106, + "w": 500, + "h": 500, + "nm": "Comp 1", + "ddd": 0, + "assets": [], + "layers": [ + { + "ddd": 0, + "ind": 2, + "ty": 4, + "nm": "Shape Layer 5", + "ks": { + "o": { + "a": 0, + "k": 100 + }, + "r": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.667 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p667_1_0p333_0" + ], + "t": 20, + "s": [ + 0 + ], + "e": [ + 360 + ] + }, + { + "t": 110 + } + ] + }, + "p": { + "a": 0, + "k": [ + 251, + 250, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ] + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { + "a": 0, + "k": [ + 10, + 10 + ] + }, + "p": { + "a": 0, + "k": [ + 0, + -100 + ] + }, + "nm": "Ellipse Path 1", + "mn": "ADBE Vector Shape - Ellipse" + }, + { + "ty": "st", + "c": { + "a": 0, + "k": [ + 0, + 0, + 0, + 1 + ] + }, + "o": { + "a": 0, + "k": 100 + }, + "w": { + "a": 0, + "k": 0 + }, + "lc": 1, + "lj": 1, + "ml": 4, + "nm": "Stroke 1", + "mn": "ADBE Vector Graphic - Stroke" + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0, + 0.7294118, + 1, + 1 + ] + }, + "o": { + "a": 0, + "k": 100 + }, + "r": 1, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill" + }, + { + "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, + "ix": 1, + "mn": "ADBE Vector Group" + } + ], + "ip": 20, + "op": 620, + "st": 20, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 3, + "ty": 4, + "nm": "Shape Layer 4", + "ks": { + "o": { + "a": 0, + "k": 100 + }, + "r": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.667 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p667_1_0p333_0" + ], + "t": 15, + "s": [ + 0 + ], + "e": [ + 360 + ] + }, + { + "t": 105 + } + ] + }, + "p": { + "a": 0, + "k": [ + 251, + 250, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ] + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { + "a": 0, + "k": [ + 20, + 20 + ] + }, + "p": { + "a": 0, + "k": [ + 0, + -100 + ] + }, + "nm": "Ellipse Path 1", + "mn": "ADBE Vector Shape - Ellipse" + }, + { + "ty": "st", + "c": { + "a": 0, + "k": [ + 0, + 0, + 0, + 1 + ] + }, + "o": { + "a": 0, + "k": 100 + }, + "w": { + "a": 0, + "k": 0 + }, + "lc": 1, + "lj": 1, + "ml": 4, + "nm": "Stroke 1", + "mn": "ADBE Vector Graphic - Stroke" + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0, + 0.7294118, + 1, + 1 + ] + }, + "o": { + "a": 0, + "k": 100 + }, + "r": 1, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill" + }, + { + "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, + "ix": 1, + "mn": "ADBE Vector Group" + } + ], + "ip": 15, + "op": 615, + "st": 15, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 4, + "ty": 4, + "nm": "Shape Layer 3", + "ks": { + "o": { + "a": 0, + "k": 100 + }, + "r": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.667 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p667_1_0p333_0" + ], + "t": 10, + "s": [ + 0 + ], + "e": [ + 360 + ] + }, + { + "t": 100 + } + ] + }, + "p": { + "a": 0, + "k": [ + 251, + 250, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ] + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { + "a": 0, + "k": [ + 30, + 30 + ] + }, + "p": { + "a": 0, + "k": [ + 0, + -100 + ] + }, + "nm": "Ellipse Path 1", + "mn": "ADBE Vector Shape - Ellipse" + }, + { + "ty": "st", + "c": { + "a": 0, + "k": [ + 0, + 0, + 0, + 1 + ] + }, + "o": { + "a": 0, + "k": 100 + }, + "w": { + "a": 0, + "k": 0 + }, + "lc": 1, + "lj": 1, + "ml": 4, + "nm": "Stroke 1", + "mn": "ADBE Vector Graphic - Stroke" + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0, + 0.7294118, + 1, + 1 + ] + }, + "o": { + "a": 0, + "k": 100 + }, + "r": 1, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill" + }, + { + "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, + "ix": 1, + "mn": "ADBE Vector Group" + } + ], + "ip": 10, + "op": 610, + "st": 10, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 5, + "ty": 4, + "nm": "Shape Layer 2", + "ks": { + "o": { + "a": 0, + "k": 100 + }, + "r": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.667 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p667_1_0p333_0" + ], + "t": 5, + "s": [ + 0 + ], + "e": [ + 360 + ] + }, + { + "t": 95 + } + ] + }, + "p": { + "a": 0, + "k": [ + 251, + 250, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ] + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { + "a": 0, + "k": [ + 40, + 40 + ] + }, + "p": { + "a": 0, + "k": [ + 0, + -100 + ] + }, + "nm": "Ellipse Path 1", + "mn": "ADBE Vector Shape - Ellipse" + }, + { + "ty": "st", + "c": { + "a": 0, + "k": [ + 0, + 0, + 0, + 1 + ] + }, + "o": { + "a": 0, + "k": 100 + }, + "w": { + "a": 0, + "k": 0 + }, + "lc": 1, + "lj": 1, + "ml": 4, + "nm": "Stroke 1", + "mn": "ADBE Vector Graphic - Stroke" + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0, + 0.7294118, + 1, + 1 + ] + }, + "o": { + "a": 0, + "k": 100 + }, + "r": 1, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill" + }, + { + "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, + "ix": 1, + "mn": "ADBE Vector Group" + } + ], + "ip": 5, + "op": 605, + "st": 5, + "bm": 0, + "sr": 1 + }, + { + "ddd": 0, + "ind": 6, + "ty": 4, + "nm": "Shape Layer 1", + "ks": { + "o": { + "a": 0, + "k": 100 + }, + "r": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.667 + ], + "y": [ + 1 + ] + }, + "o": { + "x": [ + 0.333 + ], + "y": [ + 0 + ] + }, + "n": [ + "0p667_1_0p333_0" + ], + "t": 0, + "s": [ + 0 + ], + "e": [ + 360 + ] + }, + { + "t": 90 + } + ] + }, + "p": { + "a": 0, + "k": [ + 250, + 250, + 0 + ] + }, + "a": { + "a": 0, + "k": [ + 0, + 0, + 0 + ] + }, + "s": { + "a": 0, + "k": [ + 100, + 100, + 100 + ] + } + }, + "ao": 0, + "shapes": [ + { + "ty": "gr", + "it": [ + { + "d": 1, + "ty": "el", + "s": { + "a": 1, + "k": [ + { + "i": { + "x": [ + 0.667, + 0.667 + ], + "y": [ + 1, + 1 + ] + }, + "o": { + "x": [ + 0.333, + 0.333 + ], + "y": [ + 0, + 0 + ] + }, + "n": [ + "0p667_1_0p333_0", + "0p667_1_0p333_0" + ], + "t": 0, + "s": [ + 50, + 50 + ], + "e": [ + 40, + 40 + ] + }, + { + "i": { + "x": [ + 0.667, + 0.667 + ], + "y": [ + 1, + 1 + ] + }, + "o": { + "x": [ + 0.333, + 0.333 + ], + "y": [ + 0, + 0 + ] + }, + "n": [ + "0p667_1_0p333_0", + "0p667_1_0p333_0" + ], + "t": 84, + "s": [ + 40, + 40 + ], + "e": [ + 50, + 50 + ] + }, + { + "t": 100 + } + ] + }, + "p": { + "a": 0, + "k": [ + 0, + -100 + ] + }, + "nm": "Ellipse Path 1", + "mn": "ADBE Vector Shape - Ellipse" + }, + { + "ty": "st", + "c": { + "a": 0, + "k": [ + 0, + 0, + 0, + 1 + ] + }, + "o": { + "a": 0, + "k": 100 + }, + "w": { + "a": 0, + "k": 0 + }, + "lc": 1, + "lj": 1, + "ml": 4, + "nm": "Stroke 1", + "mn": "ADBE Vector Graphic - Stroke" + }, + { + "ty": "fl", + "c": { + "a": 0, + "k": [ + 0, + 0.7294118, + 1, + 1 + ] + }, + "o": { + "a": 0, + "k": 100 + }, + "r": 1, + "nm": "Fill 1", + "mn": "ADBE Vector Graphic - Fill" + }, + { + "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, + "ix": 1, + "mn": "ADBE Vector Group" + } + ], + "ip": 0, + "op": 600, + "st": 0, + "bm": 0, + "sr": 1 + } + ] +} diff --git a/android/gradle/libs.versions.toml b/android/gradle/libs.versions.toml index b6cff9cc3..c391db2cb 100644 --- a/android/gradle/libs.versions.toml +++ b/android/gradle/libs.versions.toml @@ -98,6 +98,9 @@ timber = "5.0.1" # hilt hilt = "2.44" +# lottie +lottie = "6.1.0" + [libraries] # AndroidX Libraries coreKtx = { module = "androidx.core:core-ktx", version.ref = "coreKtx" } @@ -188,6 +191,9 @@ timber = { module = "com.jakewharton.timber:timber", version.ref = "timber" } hilt = { module = "com.google.dagger:hilt-android", version.ref = "hilt" } hiltKapt = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" } +# lottie +lottie = { module = "com.airbnb.android:lottie", version.ref = "lottie" } + [bundles] domainTest = ["junitJupiter", "assertjCore"] androidUnitTest = ["jupiterApi", "jupiterEngine", "parameterizedTest", "junit4", "junit4VintageEngine", "assertj", "mockk", "coroutineTest", "coreTest"] From acdae3d3389191d09457d742d0c1be93806fcbb8 Mon Sep 17 00:00:00 2001 From: otter Date: Wed, 4 Oct 2023 17:51:24 +0900 Subject: [PATCH 12/39] =?UTF-8?q?[fix]=20=EA=B0=90=EC=83=81=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20/=20=EC=A2=85=EB=A3=8C=EB=90=9C=20=EC=97=AC?= =?UTF-8?q?=ED=96=89=EC=97=90=20=EB=8C=80=ED=95=9C=20=EA=B0=90=EC=83=81=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=EC=9D=B4=20=EB=B6=88=EA=B0=80=EB=8A=A5?= =?UTF-8?q?=ED=95=9C=20=EB=AC=B8=EC=A0=9C=20=EC=88=98=EC=A0=95=20(#443)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/ui/home/HomeFragment.kt | 3 +- .../MarkerSelectedBottomSheet.kt | 3 +- .../ui/post/detail/PostDetailActivity.kt | 4 +-- .../ui/post/writing/PostWritingActivity.kt | 29 ++++++++++--------- .../ui/post/writing/PostWritingViewModel.kt | 22 +++++++------- .../android/ui/post/writing/WritingMode.kt | 8 +++++ .../post/writing/PostWritingViewModelTest.kt | 8 +++-- 7 files changed, 44 insertions(+), 33 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeFragment.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeFragment.kt index 077e43326..747ccf190 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeFragment.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeFragment.kt @@ -239,7 +239,8 @@ class HomeFragment : Fragment(), OnMapReadyCallback { } private fun navigateToPostWriting(pointId: Long) { - startActivity(PostWritingActivity.getIntent(requireContext(), pointId)) + val tripId = homeViewModel.tripId + startActivity(PostWritingActivity.getIntent(requireContext(), tripId, pointId)) } private fun observeUpdateTripId() { diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedBottomSheet.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedBottomSheet.kt index b9b4066f2..4d7a012d4 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedBottomSheet.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedBottomSheet.kt @@ -90,7 +90,8 @@ class MarkerSelectedBottomSheet : BottomSheetDialogFragment() { } private fun navigateToPostWriting(pointId: Long) { - startActivity(PostWritingActivity.getIntent(requireContext(), pointId)) + val tripId = initTripId() ?: throw IllegalArgumentException("trip을 가져올 수 없습니다.") + startActivity(PostWritingActivity.getIntent(requireContext(), tripId, pointId)) dismiss() } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/detail/PostDetailActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/detail/PostDetailActivity.kt index 3f7604ef3..4bc4adad6 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/detail/PostDetailActivity.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/detail/PostDetailActivity.kt @@ -12,7 +12,6 @@ import com.teamtripdraw.android.domain.model.post.Post import com.teamtripdraw.android.support.framework.presentation.event.EventObserver import com.teamtripdraw.android.ui.common.dialog.DialogUtil import com.teamtripdraw.android.ui.post.writing.PostWritingActivity -import com.teamtripdraw.android.ui.post.writing.WritingMode import dagger.hilt.android.AndroidEntryPoint @AndroidEntryPoint @@ -74,8 +73,7 @@ class PostDetailActivity : AppCompatActivity() { this, EventObserver { if (it) { - val intent = - PostWritingActivity.getIntent(this, viewModel.postId, WritingMode.EDIT) + val intent = PostWritingActivity.getIntent(this, viewModel.postId) startActivity(intent) } }, diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt index b134317bb..19d109995 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt @@ -4,6 +4,7 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle +import android.os.Parcelable import android.widget.Toast import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.contract.ActivityResultContracts @@ -14,8 +15,10 @@ import com.teamtripdraw.android.R import com.teamtripdraw.android.databinding.ActivityPostWritingBinding import com.teamtripdraw.android.domain.model.point.Point import com.teamtripdraw.android.domain.model.post.Post +import com.teamtripdraw.android.domain.model.trip.Trip import com.teamtripdraw.android.support.framework.presentation.event.EventObserver import com.teamtripdraw.android.support.framework.presentation.extensions.toResizedImageFile +import com.teamtripdraw.android.support.framework.presentation.getParcelableExtraCompat import com.teamtripdraw.android.support.framework.presentation.images.createImageUri import com.teamtripdraw.android.support.framework.presentation.permission.checkCameraPermission import com.teamtripdraw.android.support.framework.presentation.permission.requestCameraPermission @@ -67,16 +70,15 @@ class PostWritingActivity : AppCompatActivity() { } private fun initIntentData() { + val writingMode = + intent.getParcelableExtraCompat(INTENT_KEY_WRITING_MODE) + val tripId = intent.getLongExtra(INTENT_KEY_TRIP_ID, Trip.NULL_SUBSTITUTE_ID) val pointId = intent.getLongExtra(INTENT_KEY_POINT_ID, Point.NULL_SUBSTITUTE_ID) val postId = intent.getLongExtra(INTENT_KEY_POST_ID, Post.NULL_SUBSTITUTE_ID) - when { - pointId != Point.NULL_SUBSTITUTE_ID && postId == Post.NULL_SUBSTITUTE_ID -> { - viewModel.initWritingMode(WritingMode.NEW, pointId) - } - postId != Post.NULL_SUBSTITUTE_ID && pointId == Point.NULL_SUBSTITUTE_ID -> { - viewModel.initWritingMode(WritingMode.EDIT, postId) - } + when (writingMode) { + ParcelableWritingMode.NEW -> viewModel.initPostMetaData(tripId, pointId) + ParcelableWritingMode.EDIT -> viewModel.initPostMetaData(postId) else -> throw IllegalArgumentException(WRONG_INTENT_VALUE_MESSAGE) } } @@ -122,33 +124,32 @@ class PostWritingActivity : AppCompatActivity() { } companion object { + private const val INTENT_KEY_WRITING_MODE = "writingMode" + private const val INTENT_KEY_TRIP_ID = "tripId" private const val INTENT_KEY_POINT_ID = "pointId" private const val INTENT_KEY_POST_ID = "postId" private const val WRONG_INTENT_VALUE_MESSAGE = "인텐트 값이 잘못되었습니다. (PostWritingActivity)" /** * 새로운 글을 작성합니다. - * 기존의 글을 수정하고 싶다면 "WritingMode.Edit"를 설정해주세요. */ - fun getIntent(context: Context, pointId: Long): Intent { + fun getIntent(context: Context, tripId: Long, pointId: Long): Intent { val intent = Intent(context, PostWritingActivity::class.java) + intent.putExtra(INTENT_KEY_WRITING_MODE, ParcelableWritingMode.NEW as Parcelable) + intent.putExtra(INTENT_KEY_TRIP_ID, tripId) intent.putExtra(INTENT_KEY_POINT_ID, pointId) return intent } /** * 기존의 글을 수정합니다. - * 새로운 글을 작성하고 싶다면 글 작성 모드를 설정하지 마세요. */ fun getIntent( context: Context, postId: Long, - wringMode: WritingMode, ): Intent { - if (wringMode == WritingMode.NEW) { - throw IllegalArgumentException(WRONG_INTENT_VALUE_MESSAGE) - } val intent = Intent(context, PostWritingActivity::class.java) + intent.putExtra(INTENT_KEY_WRITING_MODE, ParcelableWritingMode.EDIT as Parcelable) intent.putExtra(INTENT_KEY_POST_ID, postId) return intent } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt index 8e3f0c232..b5d05eee6 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt @@ -99,19 +99,17 @@ class PostWritingViewModel @Inject constructor( _selectPhotoEvent.value = false } - fun initWritingMode(writingMode: WritingMode, id: Long) { + fun initPostMetaData(tripId: Long, pointId: Long, writingMode: WritingMode = WritingMode.NEW) { this.writingMode = writingMode - when (writingMode) { - WritingMode.NEW -> { - pointId = id - tripId = tripRepository.getCurrentTripId() - fetchPoint() - } - WritingMode.EDIT -> { - postId = id - fetchPost() - } - } + this.tripId = tripId + this.pointId = pointId + fetchPoint() + } + + fun initPostMetaData(postId: Long, writingMode: WritingMode = WritingMode.EDIT) { + this.writingMode = writingMode + this.postId = postId + fetchPost() } fun textChangedEvent() { diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt index f666dbeff..f486739a6 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt @@ -1,5 +1,13 @@ package com.teamtripdraw.android.ui.post.writing +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + enum class WritingMode { NEW, EDIT } + +@Parcelize +enum class ParcelableWritingMode : Parcelable { + NEW, EDIT +} diff --git a/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt b/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt index 1a0505db4..2bd99f941 100644 --- a/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt +++ b/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt @@ -3,6 +3,7 @@ package com.teamtripdraw.android.ui.post.writing import com.teamtripdraw.android.DefaultViewModelTest import com.teamtripdraw.android.domain.model.point.Point import com.teamtripdraw.android.domain.model.post.Post +import com.teamtripdraw.android.domain.repository.GeocodingRepository import com.teamtripdraw.android.domain.repository.PointRepository import com.teamtripdraw.android.domain.repository.PostRepository import com.teamtripdraw.android.domain.repository.TripRepository @@ -24,6 +25,7 @@ internal class PostWritingViewModelTest : DefaultViewModelTest() { private lateinit var postRepository: PostRepository private lateinit var pointRepository: PointRepository private lateinit var tripRepository: TripRepository + private lateinit var geocodingRepository: GeocodingRepository @OptIn(ExperimentalCoroutinesApi::class) override fun setUp() { @@ -32,11 +34,13 @@ internal class PostWritingViewModelTest : DefaultViewModelTest() { postRepository = mockk() pointRepository = mockk() tripRepository = mockk() + geocodingRepository = mockk() sut = PostWritingViewModel( postRepository = postRepository, pointRepository = pointRepository, tripRepository = tripRepository, + geocodingRepository = geocodingRepository, ) } @@ -58,7 +62,7 @@ internal class PostWritingViewModelTest : DefaultViewModelTest() { coEvery { pointRepository.getPoint(any(), any()) } returns getPointResult // when - sut.initWritingMode(WritingMode.NEW, pointId) + sut.initPostMetaData(pointId) val actualLat = sut.point.value?.latitude val actualLng = sut.point.value?.longitude @@ -87,7 +91,7 @@ internal class PostWritingViewModelTest : DefaultViewModelTest() { coEvery { postRepository.getPost(postId) } returns expectedGetPostSuccessResult // when - sut.initWritingMode(WritingMode.EDIT, postId) + sut.initPostMetaData(postId) val actualAddress = sut.address.value val actualTitle = sut.title.value val actualWriting = sut.writing.value From 864ae762f828e25e08df143f16f4959e3c50674b Mon Sep 17 00:00:00 2001 From: otter Date: Mon, 16 Oct 2023 15:12:05 +0900 Subject: [PATCH 13/39] =?UTF-8?q?[feat]=20point=EB=A5=BC=20=EC=9D=B4?= =?UTF-8?q?=EC=9A=A9=ED=95=9C=20post=20=EC=B6=94=EA=B0=80=20api=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(#443)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/dataSource/point/PointDataSource.kt | 2 ++ .../point/RemotePointDataSourceImpl.kt | 7 ++++++ .../httpClient/dto/mapper/PointDtoMapper.kt | 15 ++++++++++++ .../httpClient/dto/mapper/PostDtoMapper.kt | 1 + .../dto/response/GetPointPostResponse.kt | 24 +++++++++++++++++++ .../httpClient/service/GetPointPostService.kt | 13 ++++++++++ .../data/repository/PointRepositoryImpl.kt | 4 ++++ .../teamtripdraw/android/di/ServiceModule.kt | 6 +++++ .../domain/repository/PointRepository.kt | 2 ++ 9 files changed, 74 insertions(+) create mode 100644 android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetPointPostResponse.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/GetPointPostService.kt diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/PointDataSource.kt b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/PointDataSource.kt index 22d0b6463..5a13e598d 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/PointDataSource.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/PointDataSource.kt @@ -1,6 +1,7 @@ package com.teamtripdraw.android.data.dataSource.point import com.teamtripdraw.android.data.model.DataPoint +import com.teamtripdraw.android.data.model.DataPost import com.teamtripdraw.android.data.model.DataPrePoint interface PointDataSource { @@ -8,6 +9,7 @@ interface PointDataSource { interface Remote { suspend fun createRecordingPoint(dataPrePoint: DataPrePoint, tripId: Long): Result suspend fun getPoint(tripId: Long, pointId: Long): Result + suspend fun getPost(pointId: Long): Result suspend fun deletePoint(tripId: Long, pointId: Long): Result } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/RemotePointDataSourceImpl.kt b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/RemotePointDataSourceImpl.kt index 2cf7aa906..92da82f2a 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/RemotePointDataSourceImpl.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/RemotePointDataSourceImpl.kt @@ -4,14 +4,17 @@ import com.teamtripdraw.android.data.httpClient.dto.mapper.toData import com.teamtripdraw.android.data.httpClient.dto.mapper.toHttpRequest import com.teamtripdraw.android.data.httpClient.service.CreateRecordingPointService import com.teamtripdraw.android.data.httpClient.service.DeletePointService +import com.teamtripdraw.android.data.httpClient.service.GetPointPostService import com.teamtripdraw.android.data.httpClient.service.GetPointService import com.teamtripdraw.android.data.model.DataPoint +import com.teamtripdraw.android.data.model.DataPost import com.teamtripdraw.android.data.model.DataPrePoint import javax.inject.Inject class RemotePointDataSourceImpl @Inject constructor( private val createRecordingPointService: CreateRecordingPointService, private val getPointService: GetPointService, + private val getPointPostService: GetPointPostService, private val deletePointService: DeletePointService, ) : PointDataSource.Remote { @@ -26,6 +29,10 @@ class RemotePointDataSourceImpl @Inject constructor( getPointService.getPoint(tripId = tripId, pointId = pointId) .process { body, headers -> Result.success(body.toData()) } + override suspend fun getPost(pointId: Long): Result = + getPointPostService.getPost(pointId) + .process { body, headers -> Result.success(body.toData()) } + override suspend fun deletePoint(tripId: Long, pointId: Long): Result = deletePointService.deletePoint(pointId, tripId) .process { _, _ -> Result.success(Unit) } diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PointDtoMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PointDtoMapper.kt index c5d7d1466..16221a5d8 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PointDtoMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PointDtoMapper.kt @@ -1,6 +1,8 @@ package com.teamtripdraw.android.data.httpClient.dto.mapper import com.teamtripdraw.android.data.httpClient.dto.request.CreateRecordingPointRequest +import com.teamtripdraw.android.data.httpClient.dto.response.GetPointPostResponse +import com.teamtripdraw.android.data.model.DataPost import com.teamtripdraw.android.data.model.DataPrePoint fun DataPrePoint.toHttpRequest(tripId: Long): CreateRecordingPointRequest = @@ -10,3 +12,16 @@ fun DataPrePoint.toHttpRequest(tripId: Long): CreateRecordingPointRequest = longitude = longitude, recordedAt = recordedAt, ) + +fun GetPointPostResponse.toData(): DataPost { + return DataPost( + postId = postId, + tripId = tripId, + title = title, + writing = writing, + address = address, + point = point.toData(), + postImageUrl = postImageUrl, + routeImageUrl = routeImageUrl, + ) +} \ No newline at end of file diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PostDtoMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PostDtoMapper.kt index 4d04863b1..eb685bbd3 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PostDtoMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PostDtoMapper.kt @@ -4,6 +4,7 @@ import com.teamtripdraw.android.data.httpClient.dto.request.AddPostRequest import com.teamtripdraw.android.data.httpClient.dto.request.PatchPostRequest import com.teamtripdraw.android.data.httpClient.dto.response.AddPostResponse import com.teamtripdraw.android.data.httpClient.dto.response.GetAllPostsResponse +import com.teamtripdraw.android.data.httpClient.dto.response.GetPointPostResponse import com.teamtripdraw.android.data.httpClient.dto.response.GetPointResponse import com.teamtripdraw.android.data.httpClient.dto.response.GetPostPointResponse import com.teamtripdraw.android.data.httpClient.dto.response.GetTripPostListResponse diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetPointPostResponse.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetPointPostResponse.kt new file mode 100644 index 000000000..4b86ff8a4 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetPointPostResponse.kt @@ -0,0 +1,24 @@ +package com.teamtripdraw.android.data.httpClient.dto.response + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class GetPointPostResponse( + @Json(name = "address") + val address: String, + @Json(name = "pointResponse") + val point: GetPostPointResponse, + @Json(name = "postId") + val postId: Long, + @Json(name = "postImageUrl") + val postImageUrl: String, + @Json(name = "routeImageUrl") + val routeImageUrl: String, + @Json(name = "title") + val title: String, + @Json(name = "tripId") + val tripId: Long, + @Json(name = "writing") + val writing: String, +) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/GetPointPostService.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/GetPointPostService.kt new file mode 100644 index 000000000..4daed07ca --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/GetPointPostService.kt @@ -0,0 +1,13 @@ +package com.teamtripdraw.android.data.httpClient.service + +import com.teamtripdraw.android.data.httpClient.dto.response.GetPointPostResponse +import com.teamtripdraw.android.data.httpClient.retrofitAdapter.responseState.ResponseState +import retrofit2.http.GET +import retrofit2.http.Path + +interface GetPointPostService { + @GET("/points/{pointId}/post") + suspend fun getPost( + @Path("pointId") pointId: Long, + ): ResponseState +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/repository/PointRepositoryImpl.kt b/android/app/src/main/java/com/teamtripdraw/android/data/repository/PointRepositoryImpl.kt index f3de61078..c67f0ab24 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/repository/PointRepositoryImpl.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/repository/PointRepositoryImpl.kt @@ -6,6 +6,7 @@ import com.teamtripdraw.android.data.model.mapper.toData import com.teamtripdraw.android.data.model.mapper.toDomain import com.teamtripdraw.android.domain.model.point.Point import com.teamtripdraw.android.domain.model.point.PrePoint +import com.teamtripdraw.android.domain.model.post.Post import com.teamtripdraw.android.domain.repository.PointRepository import javax.inject.Inject @@ -22,6 +23,9 @@ class PointRepositoryImpl @Inject constructor( override suspend fun getPoint(pointId: Long, tripId: Long): Result = pointDataSource.getPoint(tripId = tripId, pointId = pointId).map { it.toDomain() } + override suspend fun getPost(pointId: Long): Result = + pointDataSource.getPost(pointId = pointId).map { it.toDomain() } + override suspend fun deletePoint(tripId: Long, pointId: Long): Result = pointDataSource.deletePoint(tripId = tripId, pointId = pointId) } diff --git a/android/app/src/main/java/com/teamtripdraw/android/di/ServiceModule.kt b/android/app/src/main/java/com/teamtripdraw/android/di/ServiceModule.kt index 73b505416..f81e4a063 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/di/ServiceModule.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/di/ServiceModule.kt @@ -5,6 +5,7 @@ import com.teamtripdraw.android.data.httpClient.service.CreateTripService import com.teamtripdraw.android.data.httpClient.service.DeletePointService import com.teamtripdraw.android.data.httpClient.service.DeleteTripService import com.teamtripdraw.android.data.httpClient.service.GetAllTripsService +import com.teamtripdraw.android.data.httpClient.service.GetPointPostService import com.teamtripdraw.android.data.httpClient.service.GetPointService import com.teamtripdraw.android.data.httpClient.service.GetTripInfoService import com.teamtripdraw.android.data.httpClient.service.GetUserInfoService @@ -51,6 +52,11 @@ object ServiceModule { fun providesCreateRecordingPointService(@TripDrawRetrofit retrofit: Retrofit): CreateRecordingPointService = retrofit.create(CreateRecordingPointService::class.java) + @Provides + @Singleton + fun providesGetPointPostService(@TripDrawRetrofit retrofit: Retrofit): GetPointPostService = + retrofit.create(GetPointPostService::class.java) + @Provides @Singleton fun providesGetTripInfoService(@TripDrawRetrofit retrofit: Retrofit): GetTripInfoService = diff --git a/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PointRepository.kt b/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PointRepository.kt index 95d030528..3a9b006ac 100644 --- a/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PointRepository.kt +++ b/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PointRepository.kt @@ -2,9 +2,11 @@ package com.teamtripdraw.android.domain.repository import com.teamtripdraw.android.domain.model.point.Point import com.teamtripdraw.android.domain.model.point.PrePoint +import com.teamtripdraw.android.domain.model.post.Post interface PointRepository { suspend fun createRecordingPoint(prePoint: PrePoint, tripId: Long? = null): Result suspend fun getPoint(pointId: Long, tripId: Long): Result + suspend fun getPost(pointId: Long): Result suspend fun deletePoint(tripId: Long, pointId: Long): Result } From fff08667e6f4a52644caa1d735611cccf8ecaa91 Mon Sep 17 00:00:00 2001 From: otter Date: Mon, 16 Oct 2023 16:07:55 +0900 Subject: [PATCH 14/39] =?UTF-8?q?[feat]=20=EA=B0=90=EC=83=81=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20/=20point=EC=9D=98=20=EA=B0=90=EC=83=81=20=EC=97=AC?= =?UTF-8?q?=EB=B6=80=EC=97=90=20=EB=94=B0=EB=A5=B8=20=EA=B8=80=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20=EB=AA=A8=EB=93=9C=20=EC=84=A4=EC=A0=95=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(#443)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/post/writing/PostWritingActivity.kt | 14 +---- .../ui/post/writing/PostWritingViewModel.kt | 63 ++++++++++++++----- .../android/ui/post/writing/WritingMode.kt | 8 --- .../post/writing/PostWritingViewModelTest.kt | 4 +- 4 files changed, 51 insertions(+), 38 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt index 19d109995..701f510d4 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt @@ -70,17 +70,11 @@ class PostWritingActivity : AppCompatActivity() { } private fun initIntentData() { - val writingMode = - intent.getParcelableExtraCompat(INTENT_KEY_WRITING_MODE) val tripId = intent.getLongExtra(INTENT_KEY_TRIP_ID, Trip.NULL_SUBSTITUTE_ID) val pointId = intent.getLongExtra(INTENT_KEY_POINT_ID, Point.NULL_SUBSTITUTE_ID) val postId = intent.getLongExtra(INTENT_KEY_POST_ID, Post.NULL_SUBSTITUTE_ID) - when (writingMode) { - ParcelableWritingMode.NEW -> viewModel.initPostMetaData(tripId, pointId) - ParcelableWritingMode.EDIT -> viewModel.initPostMetaData(postId) - else -> throw IllegalArgumentException(WRONG_INTENT_VALUE_MESSAGE) - } + viewModel.initPostData(tripId, pointId, postId) } private fun initObserve() { @@ -124,18 +118,17 @@ class PostWritingActivity : AppCompatActivity() { } companion object { - private const val INTENT_KEY_WRITING_MODE = "writingMode" private const val INTENT_KEY_TRIP_ID = "tripId" private const val INTENT_KEY_POINT_ID = "pointId" private const val INTENT_KEY_POST_ID = "postId" private const val WRONG_INTENT_VALUE_MESSAGE = "인텐트 값이 잘못되었습니다. (PostWritingActivity)" /** - * 새로운 글을 작성합니다. + * 지정된 위치에 대한 글을 작성합니다. + * 위치에 대한 감상 여부에 따라 자동으로 글 작성 모드가 설정됩니다. */ fun getIntent(context: Context, tripId: Long, pointId: Long): Intent { val intent = Intent(context, PostWritingActivity::class.java) - intent.putExtra(INTENT_KEY_WRITING_MODE, ParcelableWritingMode.NEW as Parcelable) intent.putExtra(INTENT_KEY_TRIP_ID, tripId) intent.putExtra(INTENT_KEY_POINT_ID, pointId) return intent @@ -149,7 +142,6 @@ class PostWritingActivity : AppCompatActivity() { postId: Long, ): Intent { val intent = Intent(context, PostWritingActivity::class.java) - intent.putExtra(INTENT_KEY_WRITING_MODE, ParcelableWritingMode.EDIT as Parcelable) intent.putExtra(INTENT_KEY_POST_ID, postId) return intent } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt index b5d05eee6..1cd50acec 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt @@ -5,6 +5,7 @@ import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import com.teamtripdraw.android.TripDrawApplication import com.teamtripdraw.android.domain.model.point.Point import com.teamtripdraw.android.domain.model.post.Post import com.teamtripdraw.android.domain.model.post.PostWritingValidState @@ -99,17 +100,22 @@ class PostWritingViewModel @Inject constructor( _selectPhotoEvent.value = false } - fun initPostMetaData(tripId: Long, pointId: Long, writingMode: WritingMode = WritingMode.NEW) { - this.writingMode = writingMode + fun initPostData( + tripId: Long = Trip.NULL_SUBSTITUTE_ID, + pointId: Long = Point.NULL_SUBSTITUTE_ID, + postId: Long = Post.NULL_SUBSTITUTE_ID, + ) { this.tripId = tripId this.pointId = pointId - fetchPoint() + this.postId = postId + setWritingMode(tripId, pointId, postId) + fetchPostData() } - fun initPostMetaData(postId: Long, writingMode: WritingMode = WritingMode.EDIT) { - this.writingMode = writingMode - this.postId = postId - fetchPost() + private fun setWritingMode(tripId: Long, pointId: Long, postId: Long) { + if (tripId != Trip.NULL_SUBSTITUTE_ID && pointId != Point.NULL_SUBSTITUTE_ID) { + writingMode = WritingMode.NEW + } else if (postId != Post.NULL_SUBSTITUTE_ID) writingMode = WritingMode.EDIT } fun textChangedEvent() { @@ -150,25 +156,25 @@ class PostWritingViewModel @Inject constructor( } } - private fun fetchPoint() { - viewModelScope.launch { - pointRepository.getPoint(pointId = pointId, tripId = tripId) - .onSuccess { + private fun fetchPostData() { + if (writingMode == WritingMode.NEW) { + viewModelScope.launch { + pointRepository.getPoint(pointId = pointId, tripId = tripId).onSuccess { _point.value = it fetchAddress() + fetchWritingMode() } + } + } else if (writingMode == WritingMode.EDIT) { + fetchPost() } } private fun fetchPost() { viewModelScope.launch { postRepository.getPost(postId = postId) - .onSuccess { - _address.value = it.address - title.value = it.title - writing.value = it.writing - _imageUri.value = it.postImageUrl - } + .onSuccess { setPostData(it) } + .onFailure { TripDrawApplication.logUtil.general.log(it) } } } @@ -180,4 +186,27 @@ class PostWritingViewModel @Inject constructor( } } } + + private fun fetchWritingMode() { + if (_point.value == null) throw IllegalArgumentException("") + if (_point.value == null || _point.value!!.hasPost.not()) { + writingMode = WritingMode.NEW + return + } + writingMode = WritingMode.EDIT + viewModelScope.launch { + pointRepository.getPost(pointId).onSuccess { + setPostData(it) + fetchPost() + }.onFailure { TripDrawApplication.logUtil.general.log(it) } + } + } + + private fun setPostData(post: Post) { + postId = post.postId + _address.value = post.address + title.value = post.title + writing.value = post.writing + _imageUri.value = post.postImageUrl + } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt index f486739a6..f666dbeff 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt @@ -1,13 +1,5 @@ package com.teamtripdraw.android.ui.post.writing -import android.os.Parcelable -import kotlinx.parcelize.Parcelize - enum class WritingMode { NEW, EDIT } - -@Parcelize -enum class ParcelableWritingMode : Parcelable { - NEW, EDIT -} diff --git a/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt b/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt index 2bd99f941..f82808e8f 100644 --- a/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt +++ b/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt @@ -62,7 +62,7 @@ internal class PostWritingViewModelTest : DefaultViewModelTest() { coEvery { pointRepository.getPoint(any(), any()) } returns getPointResult // when - sut.initPostMetaData(pointId) + sut.initPostData(pointId) val actualLat = sut.point.value?.latitude val actualLng = sut.point.value?.longitude @@ -91,7 +91,7 @@ internal class PostWritingViewModelTest : DefaultViewModelTest() { coEvery { postRepository.getPost(postId) } returns expectedGetPostSuccessResult // when - sut.initPostMetaData(postId) + sut.initPostData(postId) val actualAddress = sut.address.value val actualTitle = sut.title.value val actualWriting = sut.writing.value From c964df954ef34ab920c32b6f484551ac6aad14c8 Mon Sep 17 00:00:00 2001 From: otter Date: Mon, 16 Oct 2023 16:38:47 +0900 Subject: [PATCH 15/39] =?UTF-8?q?[refactor]=20=EA=B0=90=EC=83=81=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20/=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EB=B6=84=EB=A6=AC=20=EB=B0=8F=20=EB=B6=88=ED=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0=20(#443)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/post/writing/PostWritingViewModel.kt | 59 ++++++++++--------- 1 file changed, 32 insertions(+), 27 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt index 1cd50acec..e5f2f6b23 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt @@ -26,7 +26,6 @@ import javax.inject.Inject class PostWritingViewModel @Inject constructor( private val pointRepository: PointRepository, private val postRepository: PostRepository, - private val tripRepository: TripRepository, private val geocodingRepository: GeocodingRepository, ) : ViewModel() { @@ -126,32 +125,38 @@ class PostWritingViewModel @Inject constructor( } fun completeWritingEvent() { + when (writingMode) { + WritingMode.NEW -> writeNewPost() + WritingMode.EDIT -> writeEditedPost() + } + } + + private fun writeNewPost() { viewModelScope.launch { - when (writingMode) { - WritingMode.NEW -> { - val prePost = PrePost( - tripId = tripId, - pointId = pointId, - title = title.value ?: "", - writing = writing.value ?: "", - address = address.value ?: "", - imageFile = imageFile.value, - ) - postRepository.addPost(prePost).onSuccess { - _writingCompletedEvent.value = Event(true) - } - } - WritingMode.EDIT -> { - val prePatchPost = PrePatchPost( - postId = postId, - title = title.value ?: "", - writing = writing.value ?: "", - imageFile = imageFile.value, - ) - postRepository.patchPost(prePatchPost).onSuccess { - _writingCompletedEvent.value = Event(true) - } - } + val prePost = PrePost( + tripId = tripId, + pointId = pointId, + title = title.value ?: "", + writing = writing.value ?: "", + address = address.value ?: "", + imageFile = imageFile.value, + ) + postRepository.addPost(prePost).onSuccess { + _writingCompletedEvent.value = Event(true) + } + } + } + + private fun writeEditedPost() { + viewModelScope.launch { + val prePatchPost = PrePatchPost( + postId = postId, + title = title.value ?: "", + writing = writing.value ?: "", + imageFile = imageFile.value, + ) + postRepository.patchPost(prePatchPost).onSuccess { + _writingCompletedEvent.value = Event(true) } } } @@ -189,7 +194,7 @@ class PostWritingViewModel @Inject constructor( private fun fetchWritingMode() { if (_point.value == null) throw IllegalArgumentException("") - if (_point.value == null || _point.value!!.hasPost.not()) { + if (_point.value!!.hasPost.not()) { writingMode = WritingMode.NEW return } From 54e9e630015ebb49e5da15568f0211d25f29e5e8 Mon Sep 17 00:00:00 2001 From: otter Date: Tue, 17 Oct 2023 01:37:07 +0900 Subject: [PATCH 16/39] =?UTF-8?q?[refactor]=20=EA=B0=90=EC=83=81=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20/=20=EC=9D=B8=ED=85=90=ED=8A=B8=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD=20(#443)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teamtripdraw/android/ui/home/HomeFragment.kt | 2 +- .../MarkerSelectedBottomSheet.kt | 2 +- .../android/ui/post/detail/PostDetailActivity.kt | 2 +- .../android/ui/post/writing/PostWritingActivity.kt | 14 ++------------ 4 files changed, 5 insertions(+), 15 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeFragment.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeFragment.kt index 747ccf190..cc428bdba 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeFragment.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeFragment.kt @@ -240,7 +240,7 @@ class HomeFragment : Fragment(), OnMapReadyCallback { private fun navigateToPostWriting(pointId: Long) { val tripId = homeViewModel.tripId - startActivity(PostWritingActivity.getIntent(requireContext(), tripId, pointId)) + startActivity(PostWritingActivity.getIntentByPoint(requireContext(), tripId, pointId)) } private fun observeUpdateTripId() { diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedBottomSheet.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedBottomSheet.kt index 4d7a012d4..8f63ba12a 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedBottomSheet.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedBottomSheet.kt @@ -91,7 +91,7 @@ class MarkerSelectedBottomSheet : BottomSheetDialogFragment() { private fun navigateToPostWriting(pointId: Long) { val tripId = initTripId() ?: throw IllegalArgumentException("trip을 가져올 수 없습니다.") - startActivity(PostWritingActivity.getIntent(requireContext(), tripId, pointId)) + startActivity(PostWritingActivity.getIntentByPoint(requireContext(), tripId, pointId)) dismiss() } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/detail/PostDetailActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/detail/PostDetailActivity.kt index 4bc4adad6..428ea5db3 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/detail/PostDetailActivity.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/detail/PostDetailActivity.kt @@ -73,7 +73,7 @@ class PostDetailActivity : AppCompatActivity() { this, EventObserver { if (it) { - val intent = PostWritingActivity.getIntent(this, viewModel.postId) + val intent = PostWritingActivity.getIntentByPost(this, viewModel.postId) startActivity(intent) } }, diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt index 701f510d4..8e4e23af3 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt @@ -4,7 +4,6 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.os.Bundle -import android.os.Parcelable import android.widget.Toast import androidx.activity.result.PickVisualMediaRequest import androidx.activity.result.contract.ActivityResultContracts @@ -18,7 +17,6 @@ import com.teamtripdraw.android.domain.model.post.Post import com.teamtripdraw.android.domain.model.trip.Trip import com.teamtripdraw.android.support.framework.presentation.event.EventObserver import com.teamtripdraw.android.support.framework.presentation.extensions.toResizedImageFile -import com.teamtripdraw.android.support.framework.presentation.getParcelableExtraCompat import com.teamtripdraw.android.support.framework.presentation.images.createImageUri import com.teamtripdraw.android.support.framework.presentation.permission.checkCameraPermission import com.teamtripdraw.android.support.framework.presentation.permission.requestCameraPermission @@ -121,23 +119,15 @@ class PostWritingActivity : AppCompatActivity() { private const val INTENT_KEY_TRIP_ID = "tripId" private const val INTENT_KEY_POINT_ID = "pointId" private const val INTENT_KEY_POST_ID = "postId" - private const val WRONG_INTENT_VALUE_MESSAGE = "인텐트 값이 잘못되었습니다. (PostWritingActivity)" - /** - * 지정된 위치에 대한 글을 작성합니다. - * 위치에 대한 감상 여부에 따라 자동으로 글 작성 모드가 설정됩니다. - */ - fun getIntent(context: Context, tripId: Long, pointId: Long): Intent { + fun getIntentByPoint(context: Context, tripId: Long, pointId: Long): Intent { val intent = Intent(context, PostWritingActivity::class.java) intent.putExtra(INTENT_KEY_TRIP_ID, tripId) intent.putExtra(INTENT_KEY_POINT_ID, pointId) return intent } - /** - * 기존의 글을 수정합니다. - */ - fun getIntent( + fun getIntentByPost( context: Context, postId: Long, ): Intent { From 1798acf988c445cd5b66b638a58ee882d6bbf0c2 Mon Sep 17 00:00:00 2001 From: otter Date: Tue, 17 Oct 2023 09:07:34 +0900 Subject: [PATCH 17/39] =?UTF-8?q?[refactor]=20post=20repository=20?= =?UTF-8?q?=EB=A9=94=EC=84=9C=EB=93=9C=EB=AA=85=20=EB=B3=80=EA=B2=BD=20(#4?= =?UTF-8?q?43)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/data/dataSource/point/PointDataSource.kt | 2 -- .../data/dataSource/point/RemotePointDataSourceImpl.kt | 7 ------- .../android/data/dataSource/post/PostDataSource.kt | 4 +++- .../dataSource/post/remote/RemotePostDataSourceImpl.kt | 8 +++++++- .../android/data/repository/PointRepositoryImpl.kt | 3 --- .../android/data/repository/PostRepositoryImpl.kt | 7 +++++-- .../android/ui/post/detail/PostDetailViewModel.kt | 2 +- .../android/ui/post/writing/PostWritingViewModel.kt | 5 ++--- .../android/ui/post/detail/PostDetailViewModelTest.kt | 2 +- .../android/ui/post/writing/PostWritingViewModelTest.kt | 2 +- .../android/domain/repository/PointRepository.kt | 1 - .../android/domain/repository/PostRepository.kt | 4 +++- 12 files changed, 23 insertions(+), 24 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/PointDataSource.kt b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/PointDataSource.kt index 5a13e598d..22d0b6463 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/PointDataSource.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/PointDataSource.kt @@ -1,7 +1,6 @@ package com.teamtripdraw.android.data.dataSource.point import com.teamtripdraw.android.data.model.DataPoint -import com.teamtripdraw.android.data.model.DataPost import com.teamtripdraw.android.data.model.DataPrePoint interface PointDataSource { @@ -9,7 +8,6 @@ interface PointDataSource { interface Remote { suspend fun createRecordingPoint(dataPrePoint: DataPrePoint, tripId: Long): Result suspend fun getPoint(tripId: Long, pointId: Long): Result - suspend fun getPost(pointId: Long): Result suspend fun deletePoint(tripId: Long, pointId: Long): Result } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/RemotePointDataSourceImpl.kt b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/RemotePointDataSourceImpl.kt index 92da82f2a..2cf7aa906 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/RemotePointDataSourceImpl.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/point/RemotePointDataSourceImpl.kt @@ -4,17 +4,14 @@ import com.teamtripdraw.android.data.httpClient.dto.mapper.toData import com.teamtripdraw.android.data.httpClient.dto.mapper.toHttpRequest import com.teamtripdraw.android.data.httpClient.service.CreateRecordingPointService import com.teamtripdraw.android.data.httpClient.service.DeletePointService -import com.teamtripdraw.android.data.httpClient.service.GetPointPostService import com.teamtripdraw.android.data.httpClient.service.GetPointService import com.teamtripdraw.android.data.model.DataPoint -import com.teamtripdraw.android.data.model.DataPost import com.teamtripdraw.android.data.model.DataPrePoint import javax.inject.Inject class RemotePointDataSourceImpl @Inject constructor( private val createRecordingPointService: CreateRecordingPointService, private val getPointService: GetPointService, - private val getPointPostService: GetPointPostService, private val deletePointService: DeletePointService, ) : PointDataSource.Remote { @@ -29,10 +26,6 @@ class RemotePointDataSourceImpl @Inject constructor( getPointService.getPoint(tripId = tripId, pointId = pointId) .process { body, headers -> Result.success(body.toData()) } - override suspend fun getPost(pointId: Long): Result = - getPointPostService.getPost(pointId) - .process { body, headers -> Result.success(body.toData()) } - override suspend fun deletePoint(tripId: Long, pointId: Long): Result = deletePointService.deletePoint(pointId, tripId) .process { _, _ -> Result.success(Unit) } diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/PostDataSource.kt b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/PostDataSource.kt index 70dbcc787..da92a7b55 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/PostDataSource.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/PostDataSource.kt @@ -17,7 +17,9 @@ interface PostDataSource { imageFile: File?, ): Result - suspend fun getPost(postId: Long): Result + suspend fun getPostByPostId(postId: Long): Result + + suspend fun getPostByPointId(pointId: Long): Result suspend fun getTripPosts(tripId: Long): Result> diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/remote/RemotePostDataSourceImpl.kt b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/remote/RemotePostDataSourceImpl.kt index a2aff7e9d..ac795ddd6 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/remote/RemotePostDataSourceImpl.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/remote/RemotePostDataSourceImpl.kt @@ -6,6 +6,7 @@ import com.teamtripdraw.android.data.httpClient.dto.mapper.toData import com.teamtripdraw.android.data.httpClient.dto.mapper.toHttpRequest import com.teamtripdraw.android.data.httpClient.dto.request.AddPostRequest import com.teamtripdraw.android.data.httpClient.dto.request.PatchPostRequest +import com.teamtripdraw.android.data.httpClient.service.GetPointPostService import com.teamtripdraw.android.data.httpClient.service.PostService import com.teamtripdraw.android.data.model.DataPost import com.teamtripdraw.android.data.model.DataPostOfAll @@ -22,6 +23,7 @@ import javax.inject.Inject class RemotePostDataSourceImpl @Inject constructor( private val moshi: Moshi, private val postService: PostService, + private val getPointPostService: GetPointPostService, ) : PostDataSource.Remote { override suspend fun addPost( @@ -39,12 +41,16 @@ class RemotePostDataSourceImpl @Inject constructor( } } - override suspend fun getPost(postId: Long): Result { + override suspend fun getPostByPostId(postId: Long): Result { return postService.getPost(postId).process { body, headers -> Result.success(body.toData()) } } + override suspend fun getPostByPointId(pointId: Long): Result = + getPointPostService.getPost(pointId) + .process { body, headers -> Result.success(body.toData()) } + override suspend fun getTripPosts(tripId: Long): Result> { return postService.getTripPosts(tripId).process { body, headers -> Result.success(body.toData()) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/repository/PointRepositoryImpl.kt b/android/app/src/main/java/com/teamtripdraw/android/data/repository/PointRepositoryImpl.kt index c67f0ab24..7b4be177b 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/repository/PointRepositoryImpl.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/repository/PointRepositoryImpl.kt @@ -23,9 +23,6 @@ class PointRepositoryImpl @Inject constructor( override suspend fun getPoint(pointId: Long, tripId: Long): Result = pointDataSource.getPoint(tripId = tripId, pointId = pointId).map { it.toDomain() } - override suspend fun getPost(pointId: Long): Result = - pointDataSource.getPost(pointId = pointId).map { it.toDomain() } - override suspend fun deletePoint(tripId: Long, pointId: Long): Result = pointDataSource.deletePoint(tripId = tripId, pointId = pointId) } diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/repository/PostRepositoryImpl.kt b/android/app/src/main/java/com/teamtripdraw/android/data/repository/PostRepositoryImpl.kt index a75098ccf..18b4be8cd 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/repository/PostRepositoryImpl.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/repository/PostRepositoryImpl.kt @@ -23,10 +23,13 @@ class PostRepositoryImpl @Inject constructor( ) } - override suspend fun getPost(postId: Long): Result { - return remotePostDataSource.getPost(postId).map { it.toDomain() } + override suspend fun getPostByPostId(postId: Long): Result { + return remotePostDataSource.getPostByPostId(postId).map { it.toDomain() } } + override suspend fun getPostByPointId(pointId: Long): Result = + remotePostDataSource.getPostByPointId(pointId = pointId).map { it.toDomain() } + override suspend fun getTripPosts(tripId: Long): Result> { return remotePostDataSource.getTripPosts(tripId) .map { dataPosts -> dataPosts.map { it.toDomain() } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/detail/PostDetailViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/detail/PostDetailViewModel.kt index 3d2082d83..c3054e10b 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/detail/PostDetailViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/detail/PostDetailViewModel.kt @@ -40,7 +40,7 @@ class PostDetailViewModel @Inject constructor( fun fetchPost() { viewModelScope.launch { - repository.getPost(postId) + repository.getPostByPostId(postId) .onSuccess { _postDetail.value = it.toDetailPresentation() } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt index e5f2f6b23..abdf6c4e5 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt @@ -15,7 +15,6 @@ import com.teamtripdraw.android.domain.model.trip.Trip import com.teamtripdraw.android.domain.repository.GeocodingRepository import com.teamtripdraw.android.domain.repository.PointRepository import com.teamtripdraw.android.domain.repository.PostRepository -import com.teamtripdraw.android.domain.repository.TripRepository import com.teamtripdraw.android.support.framework.presentation.event.Event import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch @@ -177,7 +176,7 @@ class PostWritingViewModel @Inject constructor( private fun fetchPost() { viewModelScope.launch { - postRepository.getPost(postId = postId) + postRepository.getPostByPostId(postId = postId) .onSuccess { setPostData(it) } .onFailure { TripDrawApplication.logUtil.general.log(it) } } @@ -200,7 +199,7 @@ class PostWritingViewModel @Inject constructor( } writingMode = WritingMode.EDIT viewModelScope.launch { - pointRepository.getPost(pointId).onSuccess { + postRepository.getPostByPointId(pointId).onSuccess { setPostData(it) fetchPost() }.onFailure { TripDrawApplication.logUtil.general.log(it) } diff --git a/android/app/src/test/java/com/teamtripdraw/android/ui/post/detail/PostDetailViewModelTest.kt b/android/app/src/test/java/com/teamtripdraw/android/ui/post/detail/PostDetailViewModelTest.kt index 9df3be6c9..031eb54c2 100644 --- a/android/app/src/test/java/com/teamtripdraw/android/ui/post/detail/PostDetailViewModelTest.kt +++ b/android/app/src/test/java/com/teamtripdraw/android/ui/post/detail/PostDetailViewModelTest.kt @@ -40,7 +40,7 @@ class PostDetailViewModelTest : DefaultViewModelTest() { // given val post = getPost() val result: Result = Result.success(post) - coEvery { postRepository.getPost(any()) } returns result + coEvery { postRepository.getPostByPostId(any()) } returns result // when sut.fetchPost() diff --git a/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt b/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt index f82808e8f..7fbb20b5b 100644 --- a/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt +++ b/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt @@ -88,7 +88,7 @@ internal class PostWritingViewModelTest : DefaultViewModelTest() { postImageUrl = expectedImageUri, ) val expectedGetPostSuccessResult: Result = Result.success(expectedPost) - coEvery { postRepository.getPost(postId) } returns expectedGetPostSuccessResult + coEvery { postRepository.getPostByPostId(postId) } returns expectedGetPostSuccessResult // when sut.initPostData(postId) diff --git a/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PointRepository.kt b/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PointRepository.kt index 3a9b006ac..20dbe1015 100644 --- a/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PointRepository.kt +++ b/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PointRepository.kt @@ -7,6 +7,5 @@ import com.teamtripdraw.android.domain.model.post.Post interface PointRepository { suspend fun createRecordingPoint(prePoint: PrePoint, tripId: Long? = null): Result suspend fun getPoint(pointId: Long, tripId: Long): Result - suspend fun getPost(pointId: Long): Result suspend fun deletePoint(tripId: Long, pointId: Long): Result } diff --git a/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PostRepository.kt b/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PostRepository.kt index 00b1c6c74..fc379289f 100644 --- a/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PostRepository.kt +++ b/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PostRepository.kt @@ -9,7 +9,9 @@ interface PostRepository { suspend fun addPost(prePost: PrePost): Result - suspend fun getPost(postId: Long): Result + suspend fun getPostByPostId(postId: Long): Result + + suspend fun getPostByPointId(pointId: Long): Result suspend fun getTripPosts(tripId: Long): Result> From 2ee26886d1c47082de656c8b022300e9eb84f215 Mon Sep 17 00:00:00 2001 From: otter Date: Tue, 17 Oct 2023 10:33:56 +0900 Subject: [PATCH 18/39] =?UTF-8?q?[refactor]=20=EA=B0=90=EC=83=81=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20/=20=EB=A9=94=EC=84=9C=EB=93=9C=20?= =?UTF-8?q?=EC=88=9C=EC=84=9C=20=EC=A0=95=EB=A0=AC=20(#443)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/post/writing/PostWritingViewModel.kt | 92 +++++++++---------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt index abdf6c4e5..5d443a734 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt @@ -116,6 +116,52 @@ class PostWritingViewModel @Inject constructor( } else if (postId != Post.NULL_SUBSTITUTE_ID) writingMode = WritingMode.EDIT } + private fun fetchPostData() { + if (writingMode == WritingMode.NEW) { + viewModelScope.launch { + pointRepository.getPoint(pointId = pointId, tripId = tripId).onSuccess { + _point.value = it + fetchAddress() + fetchWritingMode() + } + } + } else if (writingMode == WritingMode.EDIT) { + fetchPost() + } + } + + private fun fetchAddress() { + _point.value?.let { point -> + viewModelScope.launch { + geocodingRepository.getAddress(point.latitude, point.longitude) + .onSuccess { _address.value = it } + } + } + } + + private fun fetchWritingMode() { + if (_point.value == null) throw IllegalArgumentException("") + if (_point.value!!.hasPost.not()) { + writingMode = WritingMode.NEW + return + } + writingMode = WritingMode.EDIT + viewModelScope.launch { + postRepository.getPostByPointId(pointId).onSuccess { + setPostData(it) + fetchPost() + }.onFailure { TripDrawApplication.logUtil.general.log(it) } + } + } + + private fun fetchPost() { + viewModelScope.launch { + postRepository.getPostByPostId(postId = postId) + .onSuccess { setPostData(it) } + .onFailure { TripDrawApplication.logUtil.general.log(it) } + } + } + fun textChangedEvent() { _postWritingValidState.value = PostWritingValidState.getValidState( requireNotNull(title.value), @@ -160,52 +206,6 @@ class PostWritingViewModel @Inject constructor( } } - private fun fetchPostData() { - if (writingMode == WritingMode.NEW) { - viewModelScope.launch { - pointRepository.getPoint(pointId = pointId, tripId = tripId).onSuccess { - _point.value = it - fetchAddress() - fetchWritingMode() - } - } - } else if (writingMode == WritingMode.EDIT) { - fetchPost() - } - } - - private fun fetchPost() { - viewModelScope.launch { - postRepository.getPostByPostId(postId = postId) - .onSuccess { setPostData(it) } - .onFailure { TripDrawApplication.logUtil.general.log(it) } - } - } - - private fun fetchAddress() { - _point.value?.let { point -> - viewModelScope.launch { - geocodingRepository.getAddress(point.latitude, point.longitude) - .onSuccess { _address.value = it } - } - } - } - - private fun fetchWritingMode() { - if (_point.value == null) throw IllegalArgumentException("") - if (_point.value!!.hasPost.not()) { - writingMode = WritingMode.NEW - return - } - writingMode = WritingMode.EDIT - viewModelScope.launch { - postRepository.getPostByPointId(pointId).onSuccess { - setPostData(it) - fetchPost() - }.onFailure { TripDrawApplication.logUtil.general.log(it) } - } - } - private fun setPostData(post: Post) { postId = post.postId _address.value = post.address From 2a38b9ce0292937ed82992ad43d035a241342b03 Mon Sep 17 00:00:00 2001 From: otter Date: Tue, 17 Oct 2023 18:03:26 +0900 Subject: [PATCH 19/39] =?UTF-8?q?[fix]=20GetPointPostResponse=20DTO=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#495)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/data/httpClient/dto/mapper/PointDtoMapper.kt | 4 +++- .../data/httpClient/dto/response/GetPointPostResponse.kt | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PointDtoMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PointDtoMapper.kt index 16221a5d8..6718a6de1 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PointDtoMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/mapper/PointDtoMapper.kt @@ -23,5 +23,7 @@ fun GetPointPostResponse.toData(): DataPost { point = point.toData(), postImageUrl = postImageUrl, routeImageUrl = routeImageUrl, + isMine = isMine, + authorNickname = authorNickname, ) -} \ No newline at end of file +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetPointPostResponse.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetPointPostResponse.kt index 4b86ff8a4..3be04ea26 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetPointPostResponse.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetPointPostResponse.kt @@ -21,4 +21,8 @@ data class GetPointPostResponse( val tripId: Long, @Json(name = "writing") val writing: String, + @Json(name = "isMine") + val isMine: Boolean, + @Json(name = "authorNickname") + val authorNickname: String ) From e32e26c2bb413214b6b22340a06018dfce29620c Mon Sep 17 00:00:00 2001 From: otter Date: Mon, 16 Oct 2023 21:29:53 +0900 Subject: [PATCH 20/39] =?UTF-8?q?[refactor]=20=EB=AA=A8=EB=91=90=EC=9D=98?= =?UTF-8?q?=20=EC=97=AC=ED=96=89=20/=20=ED=8C=A8=ED=82=A4=EC=A7=80=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD=20(#495)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teamtripdraw/android/ui/allTrips/AllTripsViewHolder.kt | 2 +- .../com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt | 4 ++-- .../android/ui/model/{ => allTrips}/UiAllTrips.kt | 2 +- .../android/ui/model/{ => allTrips}/UiTripOfAll.kt | 2 +- .../com/teamtripdraw/android/ui/model/mapper/TripUiMapper.kt | 2 +- android/app/src/main/res/layout/item_all_trips.xml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) rename android/app/src/main/java/com/teamtripdraw/android/ui/model/{ => allTrips}/UiAllTrips.kt (68%) rename android/app/src/main/java/com/teamtripdraw/android/ui/model/{ => allTrips}/UiTripOfAll.kt (82%) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewHolder.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewHolder.kt index 0728fd853..34a0bd833 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewHolder.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewHolder.kt @@ -4,7 +4,7 @@ import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.RecyclerView import com.teamtripdraw.android.databinding.ItemAllTripsBinding -import com.teamtripdraw.android.ui.model.UiTripOfAll +import com.teamtripdraw.android.ui.model.allTrips.UiTripOfAll class AllTripsViewHolder( private val binding: ItemAllTripsBinding, diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt index 6f863de42..9b9937ebf 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt @@ -8,9 +8,9 @@ import androidx.lifecycle.viewModelScope import com.teamtripdraw.android.TripDrawApplication import com.teamtripdraw.android.domain.model.trip.TripOfAll import com.teamtripdraw.android.domain.repository.TripRepository -import com.teamtripdraw.android.ui.model.UiAllTrips +import com.teamtripdraw.android.ui.model.allTrips.UiAllTrips import com.teamtripdraw.android.ui.model.UiPreviewTrip -import com.teamtripdraw.android.ui.model.UiTripOfAll +import com.teamtripdraw.android.ui.model.allTrips.UiTripOfAll import com.teamtripdraw.android.ui.model.mapper.toPresentation import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiAllTrips.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTrips.kt similarity index 68% rename from android/app/src/main/java/com/teamtripdraw/android/ui/model/UiAllTrips.kt rename to android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTrips.kt index 75b95090b..30eff3cb2 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiAllTrips.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTrips.kt @@ -1,4 +1,4 @@ -package com.teamtripdraw.android.ui.model +package com.teamtripdraw.android.ui.model.allTrips data class UiAllTrips( val tripItems: List, diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiTripOfAll.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiTripOfAll.kt similarity index 82% rename from android/app/src/main/java/com/teamtripdraw/android/ui/model/UiTripOfAll.kt rename to android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiTripOfAll.kt index 055d3de86..602d1ee2a 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiTripOfAll.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiTripOfAll.kt @@ -1,4 +1,4 @@ -package com.teamtripdraw.android.ui.model +package com.teamtripdraw.android.ui.model.allTrips data class UiTripOfAll( val tripId: Long, diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/TripUiMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/TripUiMapper.kt index 63af1fe32..5a94319c8 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/TripUiMapper.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/TripUiMapper.kt @@ -7,7 +7,7 @@ import com.teamtripdraw.android.domain.model.trip.TripOfAll import com.teamtripdraw.android.support.framework.presentation.LocalDateTimeFormatter import com.teamtripdraw.android.ui.model.UiPreviewTrip import com.teamtripdraw.android.ui.model.UiRoute -import com.teamtripdraw.android.ui.model.UiTripOfAll +import com.teamtripdraw.android.ui.model.allTrips.UiTripOfAll import java.time.LocalDateTime fun Route.toPresentation(): UiRoute = diff --git a/android/app/src/main/res/layout/item_all_trips.xml b/android/app/src/main/res/layout/item_all_trips.xml index a89ee50b8..dd07d7dee 100644 --- a/android/app/src/main/res/layout/item_all_trips.xml +++ b/android/app/src/main/res/layout/item_all_trips.xml @@ -11,7 +11,7 @@ + type="com.teamtripdraw.android.ui.model.allTrips.UiTripOfAll" /> Date: Mon, 16 Oct 2023 22:05:44 +0900 Subject: [PATCH 21/39] =?UTF-8?q?[feat]=20=EB=AA=A8=EB=91=90=EC=9D=98=20?= =?UTF-8?q?=EC=97=AC=ED=96=89=20/=20=EB=A1=9C=EB=94=A9=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=ED=85=9C=EA=B3=BC=20=EC=97=AC=ED=96=89=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=ED=85=9C=20=EA=B5=AC=EB=B6=84=EC=9D=84=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20UiAllTripItem=20interface=20=EC=B6=94=EA=B0=80=20(#?= =?UTF-8?q?495)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/ui/allTrips/AllTripsAdapter.kt | 28 +++++++++++++------ .../android/ui/allTrips/AllTripsViewModel.kt | 2 +- .../ui/model/allTrips/UiAllTripItem.kt | 3 ++ .../android/ui/model/allTrips/UiAllTrips.kt | 2 +- .../android/ui/model/allTrips/UiTripOfAll.kt | 2 +- 5 files changed, 26 insertions(+), 11 deletions(-) create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTripItem.kt diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsAdapter.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsAdapter.kt index c1c426bd8..aca55ef16 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsAdapter.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsAdapter.kt @@ -3,33 +3,45 @@ package com.teamtripdraw.android.ui.allTrips import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter -import com.teamtripdraw.android.ui.model.UiTripOfAll +import com.teamtripdraw.android.ui.model.allTrips.UiAllTripItem +import com.teamtripdraw.android.ui.model.allTrips.UiTripOfAll class AllTripsAdapter( private val viewModel: AllTripsViewModel, -) : ListAdapter(diffUtil) { +) : ListAdapter(diffUtil) { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AllTripsViewHolder { return AllTripsViewHolder.of(parent, viewModel) } override fun onBindViewHolder(holder: AllTripsViewHolder, position: Int) { - holder.bind(getItem(position)) + when (val item = getItem(position)) { + is UiTripOfAll -> holder.bind(item) + } + } + + override fun getItemViewType(position: Int): Int { + return ALL_TRIP_ITEM_VIEW } companion object { - val diffUtil = object : DiffUtil.ItemCallback() { + private const val LOADING_VIEW = 1 + private const val ALL_TRIP_ITEM_VIEW = 2 + + val diffUtil = object : DiffUtil.ItemCallback() { override fun areItemsTheSame( - oldItem: UiTripOfAll, - newItem: UiTripOfAll, + oldItem: UiAllTripItem, + newItem: UiAllTripItem, ): Boolean { + if (oldItem !is UiTripOfAll || newItem !is UiTripOfAll) return false return oldItem.tripId == newItem.tripId } override fun areContentsTheSame( - oldItem: UiTripOfAll, - newItem: UiTripOfAll, + oldItem: UiAllTripItem, + newItem: UiAllTripItem, ): Boolean { + if (oldItem !is UiTripOfAll || newItem !is UiTripOfAll) return false return oldItem == newItem } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt index 9b9937ebf..0e99f96a0 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt @@ -8,8 +8,8 @@ import androidx.lifecycle.viewModelScope import com.teamtripdraw.android.TripDrawApplication import com.teamtripdraw.android.domain.model.trip.TripOfAll import com.teamtripdraw.android.domain.repository.TripRepository -import com.teamtripdraw.android.ui.model.allTrips.UiAllTrips import com.teamtripdraw.android.ui.model.UiPreviewTrip +import com.teamtripdraw.android.ui.model.allTrips.UiAllTrips import com.teamtripdraw.android.ui.model.allTrips.UiTripOfAll import com.teamtripdraw.android.ui.model.mapper.toPresentation import dagger.hilt.android.lifecycle.HiltViewModel diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTripItem.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTripItem.kt new file mode 100644 index 000000000..cbba30bb3 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTripItem.kt @@ -0,0 +1,3 @@ +package com.teamtripdraw.android.ui.model.allTrips + +interface UiAllTripItem diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTrips.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTrips.kt index 30eff3cb2..2c9ff0976 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTrips.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTrips.kt @@ -1,6 +1,6 @@ package com.teamtripdraw.android.ui.model.allTrips data class UiAllTrips( - val tripItems: List, + val tripItems: List, val isEmpty: Boolean = tripItems.isEmpty(), ) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiTripOfAll.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiTripOfAll.kt index 602d1ee2a..4c089e546 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiTripOfAll.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiTripOfAll.kt @@ -9,4 +9,4 @@ data class UiTripOfAll( val endTime: String, val isMine: Boolean, val authorNickname: String, -) +) : UiAllTripItem From 871600cf86a0c291b80b82c24be2a5352769b101 Mon Sep 17 00:00:00 2001 From: otter Date: Tue, 17 Oct 2023 00:29:00 +0900 Subject: [PATCH 22/39] =?UTF-8?q?[feat]=20=EB=AA=A8=EB=91=90=EC=9D=98=20?= =?UTF-8?q?=EC=97=AC=ED=96=89=20/=20=EB=A1=9C=EB=94=A9=20=EC=95=84?= =?UTF-8?q?=EC=9D=B4=ED=85=9C=20=EC=B6=94=EA=B0=80=20(#495)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/ui/allTrips/AllTripsAdapter.kt | 37 +++++++++++++++---- .../ui/model/allTrips/UiAllTripLoadingItem.kt | 3 ++ 2 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTripLoadingItem.kt diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsAdapter.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsAdapter.kt index aca55ef16..604817b35 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsAdapter.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsAdapter.kt @@ -1,27 +1,34 @@ package com.teamtripdraw.android.ui.allTrips +import android.view.LayoutInflater import android.view.ViewGroup import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.ListAdapter +import androidx.recyclerview.widget.RecyclerView +import com.teamtripdraw.android.databinding.ItemLoadingBinding import com.teamtripdraw.android.ui.model.allTrips.UiAllTripItem import com.teamtripdraw.android.ui.model.allTrips.UiTripOfAll class AllTripsAdapter( private val viewModel: AllTripsViewModel, -) : ListAdapter(diffUtil) { +) : ListAdapter(diffUtil) { - override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AllTripsViewHolder { - return AllTripsViewHolder.of(parent, viewModel) + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder { + return when (viewType) { + ALL_TRIP_ITEM_VIEW -> AllTripsViewHolder.of(parent, viewModel) + else -> LoadingViewHolder.of(parent) + } } - override fun onBindViewHolder(holder: AllTripsViewHolder, position: Int) { - when (val item = getItem(position)) { - is UiTripOfAll -> holder.bind(item) - } + override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) { + if (holder is AllTripsViewHolder) holder.bind(getItem(position) as UiTripOfAll) } override fun getItemViewType(position: Int): Int { - return ALL_TRIP_ITEM_VIEW + return when (getItem(position)) { + is UiTripOfAll -> ALL_TRIP_ITEM_VIEW + else -> LOADING_VIEW + } } companion object { @@ -46,4 +53,18 @@ class AllTripsAdapter( } } } + + class LoadingViewHolder(val binding: ItemLoadingBinding) : + RecyclerView.ViewHolder(binding.root) { + companion object { + fun of(parent: ViewGroup): LoadingViewHolder = + LoadingViewHolder( + ItemLoadingBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false, + ), + ) + } + } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTripLoadingItem.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTripLoadingItem.kt new file mode 100644 index 000000000..d441d535f --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/allTrips/UiAllTripLoadingItem.kt @@ -0,0 +1,3 @@ +package com.teamtripdraw.android.ui.model.allTrips + +object UiAllTripLoadingItem : UiAllTripItem From 48040e4bcf84b9e39e8272700721a11f3815f955 Mon Sep 17 00:00:00 2001 From: otter Date: Tue, 17 Oct 2023 00:57:24 +0900 Subject: [PATCH 23/39] =?UTF-8?q?[refactor]=20=EB=AA=A8=EB=91=90=EC=9D=98?= =?UTF-8?q?=20=EC=97=AC=ED=96=89=20/=20=EC=97=AC=ED=96=89=EC=9D=84UiAllTri?= =?UTF-8?q?pItem=EC=9C=BC=EB=A1=9C=20=ED=83=80=EC=9E=85=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20(#495)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/ui/allTrips/AllTripsViewModel.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt index 0e99f96a0..37b35cb82 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt @@ -6,9 +6,9 @@ import androidx.lifecycle.Transformations import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.teamtripdraw.android.TripDrawApplication -import com.teamtripdraw.android.domain.model.trip.TripOfAll import com.teamtripdraw.android.domain.repository.TripRepository import com.teamtripdraw.android.ui.model.UiPreviewTrip +import com.teamtripdraw.android.ui.model.allTrips.UiAllTripItem import com.teamtripdraw.android.ui.model.allTrips.UiAllTrips import com.teamtripdraw.android.ui.model.allTrips.UiTripOfAll import com.teamtripdraw.android.ui.model.mapper.toPresentation @@ -20,9 +20,9 @@ import javax.inject.Inject class AllTripsViewModel @Inject constructor( private val tripRepository: TripRepository, ) : ViewModel() { - private val _trips: MutableLiveData> = MutableLiveData() - val trips: LiveData = - Transformations.map(_trips) { trip -> UiAllTrips(trip.map { it.toPresentation() }) } + + private val _trips: MutableLiveData> = MutableLiveData() + val trips: LiveData = Transformations.map(_trips) { trip -> UiAllTrips(trip) } private val _openHistoryDetailEvent = MutableLiveData() val openHistoryDetailEvent: LiveData = _openHistoryDetailEvent @@ -30,8 +30,8 @@ class AllTripsViewModel @Inject constructor( fun fetchTrips() { viewModelScope.launch { tripRepository.getAllTrips() - .onSuccess { - _trips.value = it + .onSuccess { it -> + _trips.value = it.map { it.toPresentation() } } .onFailure { TripDrawApplication.logUtil.general.log(it) From 80e3990cd2219bba09abf51937649f6717070c7e Mon Sep 17 00:00:00 2001 From: otter Date: Tue, 17 Oct 2023 14:46:19 +0900 Subject: [PATCH 24/39] =?UTF-8?q?[feat]=20=EB=AA=A8=EB=91=90=EC=9D=98=20?= =?UTF-8?q?=EC=97=AC=ED=96=89=20/=20=EB=AC=B4=ED=95=9C=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A1=A4=20=EC=A0=81=EC=9A=A9=20(#495)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/ui/allTrips/AllTripsFragment.kt | 29 +++++++++ .../android/ui/allTrips/AllTripsViewModel.kt | 61 ++++++++++++++++--- 2 files changed, 82 insertions(+), 8 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsFragment.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsFragment.kt index 7f2d3bfe2..180185185 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsFragment.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsFragment.kt @@ -6,6 +6,8 @@ import android.view.View import android.view.ViewGroup import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView import com.teamtripdraw.android.databinding.FragmentAllTripsBinding import com.teamtripdraw.android.ui.history.detail.HistoryDetailActivity import com.teamtripdraw.android.ui.model.UiPreviewTrip @@ -31,6 +33,7 @@ class AllTripsFragment : Fragment() { bindViewModel() initObserver() setAdapter() + addScrollListener() return binding.root } @@ -76,4 +79,30 @@ class AllTripsFragment : Fragment() { super.onDestroy() _binding = null } + + private fun addScrollListener() { + binding.rvAllTrips.addOnScrollListener(object : RecyclerView.OnScrollListener() { + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + super.onScrolled(recyclerView, dx, dy) + val layoutManager = binding.rvAllTrips.layoutManager as LinearLayoutManager + val lastPosition = layoutManager.findLastCompletelyVisibleItemPosition() + if (isMoreFetchTripsCondition(layoutManager, lastPosition)) viewModel.fetchTrips() + } + }) + } + + private fun isMoreFetchTripsCondition(layoutManager: LinearLayoutManager, lastPosition: Int): + Boolean = + viewModel.hasNextPage && + viewModel.isAddLoading.not() && + isLoadThreshold(layoutManager, lastPosition) && + binding.rvAllTrips.canScrollVertically(DOWNWARD_DIRECTION).not() + + private fun isLoadThreshold(layoutManager: LinearLayoutManager, lastPosition: Int): Boolean = + layoutManager.itemCount <= lastPosition + LOAD_THRESHOLD + + companion object { + private const val LOAD_THRESHOLD = 3 + private const val DOWNWARD_DIRECTION = 1 + } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt index 37b35cb82..61c1a6112 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt @@ -6,9 +6,11 @@ import androidx.lifecycle.Transformations import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.teamtripdraw.android.TripDrawApplication +import com.teamtripdraw.android.domain.model.trip.TripOfAll import com.teamtripdraw.android.domain.repository.TripRepository import com.teamtripdraw.android.ui.model.UiPreviewTrip import com.teamtripdraw.android.ui.model.allTrips.UiAllTripItem +import com.teamtripdraw.android.ui.model.allTrips.UiAllTripLoadingItem import com.teamtripdraw.android.ui.model.allTrips.UiAllTrips import com.teamtripdraw.android.ui.model.allTrips.UiTripOfAll import com.teamtripdraw.android.ui.model.mapper.toPresentation @@ -21,22 +23,61 @@ class AllTripsViewModel @Inject constructor( private val tripRepository: TripRepository, ) : ViewModel() { - private val _trips: MutableLiveData> = MutableLiveData() - val trips: LiveData = Transformations.map(_trips) { trip -> UiAllTrips(trip) } + private val _uiTripItems: MutableLiveData> = MutableLiveData(listOf()) + val trips: LiveData = Transformations.map(_uiTripItems) { trip -> UiAllTrips(trip) } private val _openHistoryDetailEvent = MutableLiveData() val openHistoryDetailEvent: LiveData = _openHistoryDetailEvent + private var lastId: Long? = null + + var hasNextPage = true + private set + + var isAddLoading = false + private set + fun fetchTrips() { + if (_uiTripItems.value!!.isNotEmpty() && hasNextPage) { + isAddLoading = true + addLoadingItem() + } + fetchMoreTrips() + } + + private fun fetchMoreTrips() { viewModelScope.launch { - tripRepository.getAllTrips() - .onSuccess { it -> - _trips.value = it.map { it.toPresentation() } - } - .onFailure { - TripDrawApplication.logUtil.general.log(it) + tripRepository.getAllTrips(lastViewedId = lastId).onSuccess { trips -> + setLastItemId(trips) + setHasNextPage(trips) + if (lastId == null) { + _uiTripItems.value = trips.map { it.toPresentation() } + } else { + setAddedItems(trips) } + }.onFailure { TripDrawApplication.logUtil.general.log(it) } + } + } + + private fun setAddedItems(trips: List) { + _uiTripItems.value = _uiTripItems.value!!.toMutableList().apply { + remove(UiAllTripLoadingItem) + addAll(trips.map { it.toPresentation() }) } + isAddLoading = false + } + + private fun addLoadingItem() { + _uiTripItems.value = + _uiTripItems.value!!.toMutableList().apply { add(UiAllTripLoadingItem) } + } + + private fun setLastItemId(trips: List) { + if (trips.isNotEmpty()) lastId = trips.last().tripId + } + + private fun setHasNextPage(trips: List) { + if (trips.size < PAGE_ITEM_SIZE && lastId != null) hasNextPage = false } fun openHistoryDetail(trip: UiTripOfAll) { @@ -48,4 +89,8 @@ class AllTripsViewModel @Inject constructor( ) _openHistoryDetailEvent.value = previewTrip } + + companion object { + private const val PAGE_ITEM_SIZE = 20 + } } From 1c327b3e8727a8ffdee430e3c2f9b44046d0b2b5 Mon Sep 17 00:00:00 2001 From: otter Date: Tue, 17 Oct 2023 22:15:08 +0900 Subject: [PATCH 25/39] =?UTF-8?q?[refactor]=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=EC=97=AC=ED=96=89=20/=20=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C?= =?UTF-8?q?=20=EB=B6=84=EA=B8=B0=EB=AC=B8=20=EC=A0=9C=EA=B1=B0=20=20(#495)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt index 61c1a6112..a98fa2f29 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt @@ -50,11 +50,7 @@ class AllTripsViewModel @Inject constructor( tripRepository.getAllTrips(lastViewedId = lastId).onSuccess { trips -> setLastItemId(trips) setHasNextPage(trips) - if (lastId == null) { - _uiTripItems.value = trips.map { it.toPresentation() } - } else { - setAddedItems(trips) - } + setAddedItems(trips) }.onFailure { TripDrawApplication.logUtil.general.log(it) } } } From 105104ffa70c10a734fa723bb8e3a63e5e63725f Mon Sep 17 00:00:00 2001 From: otter Date: Tue, 17 Oct 2023 22:33:47 +0900 Subject: [PATCH 26/39] =?UTF-8?q?[feat]=20=EA=B0=90=EC=83=81=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=20/=20=ED=83=9C=EB=B8=94=EB=A6=BF=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=EC=97=90=EC=84=9C=20=EC=9D=B4=EB=AF=B8=EC=A7=80=20?= =?UTF-8?q?=EB=AF=B8=EB=A6=AC=EB=B3=B4=EA=B8=B0=20=ED=81=AC=EA=B8=B0=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=88=20(#506)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/src/main/res/layout/activity_post_writing.xml | 8 ++++---- android/app/src/main/res/values-w600dp/dimens.xml | 8 ++++++++ android/app/src/main/res/values/dimens.xml | 4 ++++ 3 files changed, 16 insertions(+), 4 deletions(-) create mode 100644 android/app/src/main/res/values-w600dp/dimens.xml diff --git a/android/app/src/main/res/layout/activity_post_writing.xml b/android/app/src/main/res/layout/activity_post_writing.xml index e4e75515b..c84bfa4c3 100644 --- a/android/app/src/main/res/layout/activity_post_writing.xml +++ b/android/app/src/main/res/layout/activity_post_writing.xml @@ -135,8 +135,8 @@ + + + + 100dp + 24dp + + diff --git a/android/app/src/main/res/values/dimens.xml b/android/app/src/main/res/values/dimens.xml index aea7d93a8..fa12a9f37 100644 --- a/android/app/src/main/res/values/dimens.xml +++ b/android/app/src/main/res/values/dimens.xml @@ -4,4 +4,8 @@ 56dp 52dp + + 56dp + 16dp + From bfb01c9b3ce2d8699e4f4f0f4b12556bb3c197be Mon Sep 17 00:00:00 2001 From: 2chang5 Date: Thu, 19 Oct 2023 13:34:22 +0900 Subject: [PATCH 27/39] =?UTF-8?q?[feat]=20api=20=EB=B2=84=EC=A0=80?= =?UTF-8?q?=EB=8B=9D=20=EB=8C=80=EC=9D=91=ED=95=98=EC=97=AC=20api=20?= =?UTF-8?q?=EB=B2=84=EC=A0=84=20=EA=B4=80=EB=A0=A8=20=ED=97=A4=EB=8D=94=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20(#516)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- android/app/build.gradle.kts | 6 +++ .../teamtripdraw/android/di/RetrofitModule.kt | 39 ++++++++++++------- .../android/di/qualifier/Qualifiers.kt | 6 +++ 3 files changed, 38 insertions(+), 13 deletions(-) diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index b46a8a079..2b873de50 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -91,6 +91,12 @@ android { localProperties.getProperty("TERMS_OF_SERVICE_URL"), ) + buildConfigField( + "String", + "TRIP_DRAW_API_VERSION", + localProperties.getProperty("TRIP_DRAW_API_VERSION"), + ) + manifestPlaceholders["NATIVE_APP_KEY"] = localProperties.getProperty("KAKAO_NATIVE_APP_KEY_NO_QUOTES") diff --git a/android/app/src/main/java/com/teamtripdraw/android/di/RetrofitModule.kt b/android/app/src/main/java/com/teamtripdraw/android/di/RetrofitModule.kt index d9b5a7be7..51931106f 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/di/RetrofitModule.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/di/RetrofitModule.kt @@ -13,6 +13,8 @@ import com.teamtripdraw.android.data.httpClient.service.TokenRefreshService import com.teamtripdraw.android.di.qualifier.GeneralOKHttpClient import com.teamtripdraw.android.di.qualifier.NaverReverseGeocodingOkHttpClient import com.teamtripdraw.android.di.qualifier.NaverReverseGeocodingRetrofit +import com.teamtripdraw.android.di.qualifier.TripDrawApiVersionInterceptor +import com.teamtripdraw.android.di.qualifier.TripDrawAuthorizationInterceptor import com.teamtripdraw.android.di.qualifier.TripDrawOkHttpClient import com.teamtripdraw.android.di.qualifier.TripDrawRetrofit import dagger.Module @@ -35,20 +37,29 @@ object RetrofitModule { private const val AUTHORIZATION_INTERCEPTOR_VALUE_FORMAT = "Bearer %s" @Provides - @TripDrawOkHttpClient + @TripDrawAuthorizationInterceptor fun providesAuthorizationInterceptor(userIdentifyInfoDataSource: UserIdentifyInfoDataSource.Local): Interceptor = Interceptor { chain -> - with(chain) { - proceed( - request() - .newBuilder() - .addHeader( - "Authorization", - AUTHORIZATION_INTERCEPTOR_VALUE_FORMAT.format(userIdentifyInfoDataSource.getAccessToken()), - ) - .build(), - ) - } + val accessToken: String = + AUTHORIZATION_INTERCEPTOR_VALUE_FORMAT.format(userIdentifyInfoDataSource.getAccessToken()) + chain.proceed( + chain.request() + .newBuilder() + .addHeader("Authorization", accessToken) + .build(), + ) + } + + @Provides + @TripDrawApiVersionInterceptor + fun providesApiVersionInterceptor(): Interceptor = + Interceptor { chain -> + chain.proceed( + chain.request() + .newBuilder() + .addHeader("X-version", BuildConfig.TRIP_DRAW_API_VERSION) + .build(), + ) } @Provides @@ -79,10 +90,12 @@ object RetrofitModule { @TripDrawOkHttpClient fun providesTripDrawOkHttpClient( @GeneralOKHttpClient generalOKHttpClient: OkHttpClient, - @TripDrawOkHttpClient authorizationInterceptor: Interceptor, + @TripDrawAuthorizationInterceptor authorizationInterceptor: Interceptor, + @TripDrawApiVersionInterceptor apiVersionInterceptor: Interceptor, ): OkHttpClient = generalOKHttpClient.newBuilder() .addInterceptor(authorizationInterceptor) + .addInterceptor(apiVersionInterceptor) .build() @Provides diff --git a/android/app/src/main/java/com/teamtripdraw/android/di/qualifier/Qualifiers.kt b/android/app/src/main/java/com/teamtripdraw/android/di/qualifier/Qualifiers.kt index e395ef521..d16029972 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/di/qualifier/Qualifiers.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/di/qualifier/Qualifiers.kt @@ -8,6 +8,12 @@ annotation class GeneralOKHttpClient @Qualifier annotation class TripDrawOkHttpClient +@Qualifier +annotation class TripDrawAuthorizationInterceptor + +@Qualifier +annotation class TripDrawApiVersionInterceptor + @Qualifier annotation class NaverReverseGeocodingOkHttpClient From e1ed514929c1239a96358375fedd0f644dade156 Mon Sep 17 00:00:00 2001 From: pingu244 Date: Sun, 15 Oct 2023 22:34:47 +0900 Subject: [PATCH 28/39] =?UTF-8?q?[refactor]=20=EA=B0=90=EC=83=81=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20/=20=EC=9E=91=EC=84=B1=EC=9E=90=EB=94=B0?= =?UTF-8?q?=EB=9D=BC=20=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98=20=EC=95=88=EB=B3=B4=EC=9D=B4?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(#490)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/bindingAdapter/IconBindingAdapter.kt | 15 +++++++++++++++ .../src/main/res/layout/activity_post_detail.xml | 6 ++++-- 2 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/IconBindingAdapter.kt diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/IconBindingAdapter.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/IconBindingAdapter.kt new file mode 100644 index 000000000..4d3fc53e4 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/IconBindingAdapter.kt @@ -0,0 +1,15 @@ +package com.teamtripdraw.android.ui.common.bindingAdapter + +import android.view.View +import android.widget.ImageView +import androidx.databinding.BindingAdapter + +@BindingAdapter("app:setEditDeleteIconVisibility") +fun ImageView.setIconVisibility(isMine: Boolean?) { + if (isMine == null) return + if (isMine) { + this.visibility = View.VISIBLE + } else { + this.visibility = View.GONE + } +} diff --git a/android/app/src/main/res/layout/activity_post_detail.xml b/android/app/src/main/res/layout/activity_post_detail.xml index 3bf457e0b..78351301a 100644 --- a/android/app/src/main/res/layout/activity_post_detail.xml +++ b/android/app/src/main/res/layout/activity_post_detail.xml @@ -42,7 +42,8 @@ android:layout_marginEnd="@dimen/margin_default" android:contentDescription="@string/btn_delete_description" android:onClick="@{()->postDetailViewModel.openDeletionEvent()}" - android:src="@drawable/ic_delete" /> + android:src="@drawable/ic_delete" + app:setEditDeleteIconVisibility="@{postDetailViewModel.postDetail.isMine}" /> + android:src="@drawable/ic_edit" + app:setEditDeleteIconVisibility="@{postDetailViewModel.postDetail.isMine}" /> From feb8a4bce50e1e8bf1c6da3db99ae88ff826d323 Mon Sep 17 00:00:00 2001 From: pingu244 Date: Mon, 16 Oct 2023 00:13:36 +0900 Subject: [PATCH 29/39] =?UTF-8?q?[refactor]=20=EC=97=AC=ED=96=89=20?= =?UTF-8?q?=EC=83=81=EC=84=B8=20/=20=EC=9E=91=EC=84=B1=EC=9E=90=EB=94=B0?= =?UTF-8?q?=EB=9D=BC=20=EC=88=98=EC=A0=95,=20=EC=82=AD=EC=A0=9C=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98=20=EC=95=88=EB=B3=B4=EC=9D=B4?= =?UTF-8?q?=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20(#490)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt | 1 + .../java/com/teamtripdraw/android/ui/model/UiPreviewTrip.kt | 1 + android/app/src/main/res/layout/activity_history_detail.xml | 6 ++++-- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt index a98fa2f29..a7d8a39f8 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt @@ -82,6 +82,7 @@ class AllTripsViewModel @Inject constructor( name = trip.name, imageUrl = trip.imageUrl, routeImageUrl = trip.routeImageUrl, + isMine = trip.isMine, ) _openHistoryDetailEvent.value = previewTrip } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPreviewTrip.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPreviewTrip.kt index 2d4337a91..c308eb43f 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPreviewTrip.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiPreviewTrip.kt @@ -9,4 +9,5 @@ data class UiPreviewTrip( val name: String, val imageUrl: String, val routeImageUrl: String, + val isMine: Boolean = true, ) : Parcelable diff --git a/android/app/src/main/res/layout/activity_history_detail.xml b/android/app/src/main/res/layout/activity_history_detail.xml index 9afe3d63d..c4820185d 100644 --- a/android/app/src/main/res/layout/activity_history_detail.xml +++ b/android/app/src/main/res/layout/activity_history_detail.xml @@ -101,7 +101,8 @@ android:layout_marginEnd="@dimen/margin_default" android:contentDescription="@string/btn_delete_description" android:onClick="@{()->historyDetailViewModel.openDeleteDialog()}" - android:src="@drawable/ic_delete" /> + android:src="@drawable/ic_delete" + app:setEditDeleteIconVisibility="@{historyDetailViewModel.previewTrip.isMine}" /> + android:src="@drawable/ic_edit" + app:setEditDeleteIconVisibility="@{historyDetailViewModel.previewTrip.isMine}" /> From d4737f1f5c0f104bbbf5c65a5d8e28e21419e01b Mon Sep 17 00:00:00 2001 From: pingu244 Date: Mon, 16 Oct 2023 00:23:10 +0900 Subject: [PATCH 30/39] =?UTF-8?q?[refactor]=20=EB=B0=94=EC=9D=B8=EB=94=A9?= =?UTF-8?q?=EC=96=B4=EB=8C=91=ED=84=B0=20=ED=95=A8=EC=88=98=EB=AA=85=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=20(#490)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/ui/common/bindingAdapter/IconBindingAdapter.kt | 2 +- android/app/src/main/res/layout/activity_history_detail.xml | 4 ++-- android/app/src/main/res/layout/activity_post_detail.xml | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/IconBindingAdapter.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/IconBindingAdapter.kt index 4d3fc53e4..308e4d630 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/IconBindingAdapter.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/IconBindingAdapter.kt @@ -4,7 +4,7 @@ import android.view.View import android.widget.ImageView import androidx.databinding.BindingAdapter -@BindingAdapter("app:setEditDeleteIconVisibility") +@BindingAdapter("app:setIconVisibility") fun ImageView.setIconVisibility(isMine: Boolean?) { if (isMine == null) return if (isMine) { diff --git a/android/app/src/main/res/layout/activity_history_detail.xml b/android/app/src/main/res/layout/activity_history_detail.xml index c4820185d..40abe66ba 100644 --- a/android/app/src/main/res/layout/activity_history_detail.xml +++ b/android/app/src/main/res/layout/activity_history_detail.xml @@ -102,7 +102,7 @@ android:contentDescription="@string/btn_delete_description" android:onClick="@{()->historyDetailViewModel.openDeleteDialog()}" android:src="@drawable/ic_delete" - app:setEditDeleteIconVisibility="@{historyDetailViewModel.previewTrip.isMine}" /> + app:setIconVisibility="@{historyDetailViewModel.previewTrip.isMine}" /> + app:setIconVisibility="@{historyDetailViewModel.previewTrip.isMine}" /> diff --git a/android/app/src/main/res/layout/activity_post_detail.xml b/android/app/src/main/res/layout/activity_post_detail.xml index 78351301a..6a22955ab 100644 --- a/android/app/src/main/res/layout/activity_post_detail.xml +++ b/android/app/src/main/res/layout/activity_post_detail.xml @@ -43,7 +43,7 @@ android:contentDescription="@string/btn_delete_description" android:onClick="@{()->postDetailViewModel.openDeletionEvent()}" android:src="@drawable/ic_delete" - app:setEditDeleteIconVisibility="@{postDetailViewModel.postDetail.isMine}" /> + app:setIconVisibility="@{postDetailViewModel.postDetail.isMine}" /> + app:setIconVisibility="@{postDetailViewModel.postDetail.isMine}" /> From 944cab5b45e838adf9e07062c947400ea1b7dcea Mon Sep 17 00:00:00 2001 From: pingu244 Date: Mon, 16 Oct 2023 01:27:29 +0900 Subject: [PATCH 31/39] =?UTF-8?q?[refactor]=20=EC=A7=80=EB=8F=84=20?= =?UTF-8?q?=EB=B0=94=ED=85=80=EB=84=A4=EB=B9=84=EA=B2=8C=EC=9D=B4=EC=85=98?= =?UTF-8?q?=20/=20=EC=9E=91=EC=84=B1=EC=9E=90=EB=94=B0=EB=9D=BC=20?= =?UTF-8?q?=EA=B8=B0=EB=A1=9D=20=EC=9E=91=EC=84=B1,=20=EC=9C=84=EC=B9=98?= =?UTF-8?q?=20=EC=82=AD=EC=A0=9C=20=EB=B2=84=ED=8A=BC=20=EC=95=88=EB=B3=B4?= =?UTF-8?q?=EC=9D=B4=EB=8A=94=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(#490)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/common/bindingAdapter/IconBindingAdapter.kt | 3 +-- .../ui/history/tripDetail/TripDetailActivity.kt | 7 ++++--- .../ui/history/tripDetail/TripDetailViewModel.kt | 4 ++++ .../MarkerSelectedBottomSheet.kt | 14 ++++++++++++-- .../MarkerSelectedViewModel.kt | 7 +++++++ .../res/layout/bottom_sheet_marker_selected.xml | 10 ++++++---- 6 files changed, 34 insertions(+), 11 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/IconBindingAdapter.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/IconBindingAdapter.kt index 308e4d630..62bc3c278 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/IconBindingAdapter.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/IconBindingAdapter.kt @@ -1,11 +1,10 @@ package com.teamtripdraw.android.ui.common.bindingAdapter import android.view.View -import android.widget.ImageView import androidx.databinding.BindingAdapter @BindingAdapter("app:setIconVisibility") -fun ImageView.setIconVisibility(isMine: Boolean?) { +fun View.setIconVisibility(isMine: Boolean?) { if (isMine == null) return if (isMine) { this.visibility = View.VISIBLE diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/history/tripDetail/TripDetailActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/history/tripDetail/TripDetailActivity.kt index 2ea6ce831..20cf27ed2 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/history/tripDetail/TripDetailActivity.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/history/tripDetail/TripDetailActivity.kt @@ -130,9 +130,10 @@ class TripDetailActivity : AppCompatActivity(), OnMapReadyCallback { val markerSelectedBottomSheet = MarkerSelectedBottomSheet() markerSelectedBottomSheet.arguments = MarkerSelectedBottomSheet.getBundle( - pointId, - viewModel.tripId, - BottomSheetClickSituation.HISTORY, + pointId = pointId, + tripId = viewModel.tripId, + situation = BottomSheetClickSituation.HISTORY, + isMine = viewModel.isMine, ) markerSelectedBottomSheet.show(supportFragmentManager, this.javaClass.name) } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/history/tripDetail/TripDetailViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/history/tripDetail/TripDetailViewModel.kt index 75b64730f..b944351ef 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/history/tripDetail/TripDetailViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/history/tripDetail/TripDetailViewModel.kt @@ -26,6 +26,9 @@ class TripDetailViewModel @Inject constructor( val tripRoute: LiveData = Transformations.map(_tripRoute) { route -> route.toPresentation() } + var isMine: Boolean = true + private set + private val _tripTitle = MutableLiveData() val tripTitle: LiveData = _tripTitle @@ -59,6 +62,7 @@ class TripDetailViewModel @Inject constructor( .onSuccess { _tripRoute.value = it.route _tripTitle.value = it.name + isMine = it.isMine } .onFailure { TripDrawApplication.logUtil.general.log(it) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedBottomSheet.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedBottomSheet.kt index 8f63ba12a..2a9e1badd 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedBottomSheet.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedBottomSheet.kt @@ -56,6 +56,7 @@ class MarkerSelectedBottomSheet : BottomSheetDialogFragment() { private fun initMarkerSelectedViewModelData() { initPointData()?.let { pointId -> markerSelectedViewModel.updatePointId(pointId) } initTripId()?.let { tripId -> markerSelectedViewModel.updateTripId(tripId) } + initIsMine()?.let { isMine -> markerSelectedViewModel.updateIsMine(isMine) } markerSelectedViewModel.getPointInfo() } @@ -63,6 +64,8 @@ class MarkerSelectedBottomSheet : BottomSheetDialogFragment() { private fun initTripId(): Long? = arguments?.getLong(TRIP_ID) + private fun initIsMine(): Boolean? = arguments?.getBoolean(IS_MINE_KEY) + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -125,13 +128,20 @@ class MarkerSelectedBottomSheet : BottomSheetDialogFragment() { private const val POINT_ID = "POINT_ID" private const val TRIP_ID = "TRIP_ID" private const val BOTTOM_SHEET_CLICK_SITUATION_ID = "BOTTOM_SHEET_CLICK_SITUATION_ID" - - fun getBundle(pointId: Long, tripId: Long, situation: BottomSheetClickSituation): Bundle { + private const val IS_MINE_KEY = "IS_MINE_KEY" + + fun getBundle( + pointId: Long, + tripId: Long, + situation: BottomSheetClickSituation, + isMine: Boolean = true, + ): Bundle { val bundle = Bundle() bundle.apply { putLong(POINT_ID, pointId) putLong(TRIP_ID, tripId) putParcelable(BOTTOM_SHEET_CLICK_SITUATION_ID, situation) + putBoolean(IS_MINE_KEY, isMine) } return bundle } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedViewModel.kt index 71339f6bd..bfa870f5c 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/home/markerSelectedBottomSheet/MarkerSelectedViewModel.kt @@ -27,6 +27,9 @@ class MarkerSelectedViewModel @Inject constructor( private var tripId: Long = Trip.NULL_SUBSTITUTE_ID + var isMine: Boolean = true + private set + private val _selectedPoint = MutableLiveData() val selectedUiPoint: LiveData = Transformations.map(_selectedPoint) { point -> point.toPresentation() @@ -49,6 +52,10 @@ class MarkerSelectedViewModel @Inject constructor( this.tripId = tripId } + fun updateIsMine(isMine: Boolean) { + this.isMine = isMine + } + fun getPointInfo() { viewModelScope.launch { pointRepository.getPoint(pointId, tripId).onSuccess { diff --git a/android/app/src/main/res/layout/bottom_sheet_marker_selected.xml b/android/app/src/main/res/layout/bottom_sheet_marker_selected.xml index 0c7aaf0ee..c73e063fb 100644 --- a/android/app/src/main/res/layout/bottom_sheet_marker_selected.xml +++ b/android/app/src/main/res/layout/bottom_sheet_marker_selected.xml @@ -12,7 +12,8 @@ + android:layout_height="wrap_content" + android:paddingBottom="@dimen/margin_default"> + app:layout_constraintTop_toTopOf="@+id/btn_delete_point_marker_selected_bottom_sheet" + app:setIconVisibility="@{markerSelectedViewModel.isMine}" /> + app:layout_constraintTop_toBottomOf="@+id/iv_date_time_marker_selected_bottom_sheet" + app:setIconVisibility="@{markerSelectedViewModel.isMine}" /> From 33f2977603021d7aff39d4a363988ce95845d22a Mon Sep 17 00:00:00 2001 From: otter Date: Tue, 17 Oct 2023 20:47:04 +0900 Subject: [PATCH 32/39] =?UTF-8?q?[feat]=20=ED=98=84=EC=9E=AC=20=EC=A7=80?= =?UTF-8?q?=EC=A0=90=EC=97=90=20=EB=8C=80=ED=95=9C=20=EA=B0=90=EC=83=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20api=20=EC=97=B0=EB=8F=99=20(#370)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/dataSource/post/PostDataSource.kt | 12 +++++++ .../post/remote/RemotePostDataSourceImpl.kt | 35 +++++++++++++++++++ .../request/CreateCurrentPointPostRequest.kt | 22 ++++++++++++ .../CreateCurrentPointPostResponse.kt | 10 ++++++ .../service/CreateCurrentPointPostService.kt | 30 ++++++++++++++++ .../data/repository/PostRepositoryImpl.kt | 24 +++++++++++++ .../teamtripdraw/android/di/ServiceModule.kt | 6 ++++ .../domain/repository/PostRepository.kt | 13 +++++++ 8 files changed, 152 insertions(+) create mode 100644 android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/request/CreateCurrentPointPostRequest.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/CreateCurrentPointPostResponse.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/CreateCurrentPointPostService.kt diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/PostDataSource.kt b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/PostDataSource.kt index da92a7b55..9096dc9a0 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/PostDataSource.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/PostDataSource.kt @@ -5,6 +5,7 @@ import com.teamtripdraw.android.data.model.DataPostOfAll import com.teamtripdraw.android.data.model.DataPrePatchPost import com.teamtripdraw.android.data.model.DataPrePost import java.io.File +import java.time.LocalDateTime interface PostDataSource { @@ -17,6 +18,17 @@ interface PostDataSource { imageFile: File?, ): Result + suspend fun createCurrentPointPost( + tripId: Long, + title: String, + address: String, + writing: String, + latitude: Double, + longitude: Double, + recordedAt: LocalDateTime, + imageFile: File?, + ): Result + suspend fun getPostByPostId(postId: Long): Result suspend fun getPostByPointId(pointId: Long): Result diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/remote/RemotePostDataSourceImpl.kt b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/remote/RemotePostDataSourceImpl.kt index ac795ddd6..cb37191c9 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/remote/RemotePostDataSourceImpl.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/post/remote/RemotePostDataSourceImpl.kt @@ -5,7 +5,9 @@ import com.teamtripdraw.android.data.dataSource.post.PostDataSource import com.teamtripdraw.android.data.httpClient.dto.mapper.toData import com.teamtripdraw.android.data.httpClient.dto.mapper.toHttpRequest import com.teamtripdraw.android.data.httpClient.dto.request.AddPostRequest +import com.teamtripdraw.android.data.httpClient.dto.request.CreateCurrentPointPostRequest import com.teamtripdraw.android.data.httpClient.dto.request.PatchPostRequest +import com.teamtripdraw.android.data.httpClient.service.CreateCurrentPointPostService import com.teamtripdraw.android.data.httpClient.service.GetPointPostService import com.teamtripdraw.android.data.httpClient.service.PostService import com.teamtripdraw.android.data.model.DataPost @@ -13,17 +15,20 @@ import com.teamtripdraw.android.data.model.DataPostOfAll import com.teamtripdraw.android.data.model.DataPrePatchPost import com.teamtripdraw.android.data.model.DataPrePost import com.teamtripdraw.android.data.model.mapper.toData +import com.teamtripdraw.android.support.framework.presentation.LocalDateTimeFormatter.isoRemoveNanoSecondFormatter import okhttp3.MediaType.Companion.toMediaTypeOrNull import okhttp3.MultipartBody import okhttp3.RequestBody.Companion.asRequestBody import okhttp3.RequestBody.Companion.toRequestBody import java.io.File +import java.time.LocalDateTime import javax.inject.Inject class RemotePostDataSourceImpl @Inject constructor( private val moshi: Moshi, private val postService: PostService, private val getPointPostService: GetPointPostService, + private val createCurrentPointPostService: CreateCurrentPointPostService, ) : PostDataSource.Remote { override suspend fun addPost( @@ -41,6 +46,36 @@ class RemotePostDataSourceImpl @Inject constructor( } } + override suspend fun createCurrentPointPost( + tripId: Long, + title: String, + address: String, + writing: String, + latitude: Double, + longitude: Double, + recordedAt: LocalDateTime, + imageFile: File?, + ): Result { + val createCurrentPointPostRequest = CreateCurrentPointPostRequest( + address = address, + latitude = latitude, + longitude = longitude, + recordedAt = recordedAt.format(isoRemoveNanoSecondFormatter), + title = title, + tripId = tripId, + writing = writing, + ) + + val request = moshi.adapter(CreateCurrentPointPostRequest::class.java) + .toJson(createCurrentPointPostRequest) + val dto = request.toRequestBody("application/json".toMediaTypeOrNull()) + val imageBody = imageFile?.toMultipartRequestBody() + return createCurrentPointPostService.createCurrentPointPost(dto, imageBody) + .process { body, headers -> + Result.success(body.postId) + } + } + override suspend fun getPostByPostId(postId: Long): Result { return postService.getPost(postId).process { body, headers -> Result.success(body.toData()) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/request/CreateCurrentPointPostRequest.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/request/CreateCurrentPointPostRequest.kt new file mode 100644 index 000000000..02373725c --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/request/CreateCurrentPointPostRequest.kt @@ -0,0 +1,22 @@ +package com.teamtripdraw.android.data.httpClient.dto.request + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class CreateCurrentPointPostRequest( + @Json(name = "address") + val address: String, + @Json(name = "latitude") + val latitude: Double, + @Json(name = "longitude") + val longitude: Double, + @Json(name = "recordedAt") + val recordedAt: String, + @Json(name = "title") + val title: String, + @Json(name = "tripId") + val tripId: Long, + @Json(name = "writing") + val writing: String, +) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/CreateCurrentPointPostResponse.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/CreateCurrentPointPostResponse.kt new file mode 100644 index 000000000..5da2fc102 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/CreateCurrentPointPostResponse.kt @@ -0,0 +1,10 @@ +package com.teamtripdraw.android.data.httpClient.dto.response + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class CreateCurrentPointPostResponse( + @Json(name = "postId") + val postId: Long, +) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/CreateCurrentPointPostService.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/CreateCurrentPointPostService.kt new file mode 100644 index 000000000..bb6b4adf0 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/CreateCurrentPointPostService.kt @@ -0,0 +1,30 @@ +package com.teamtripdraw.android.data.httpClient.service + +import com.teamtripdraw.android.data.httpClient.dto.response.CreateCurrentPointPostResponse +import com.teamtripdraw.android.data.httpClient.retrofitAdapter.responseState.ResponseState +import okhttp3.MultipartBody +import okhttp3.RequestBody +import retrofit2.http.Multipart +import retrofit2.http.POST +import retrofit2.http.Part + +interface CreateCurrentPointPostService { + @Multipart + @POST("/posts/current-location") + suspend fun createCurrentPointPost( + @Part("dto") createCurrentPointPostRequest: RequestBody, + @Part imageFile: MultipartBody.Part?, + ): ResponseState +} + +// @Multipart +// @POST("/posts") +// suspend fun addPost( +// @Part("dto") addPostRequest: RequestBody, +// @Part imageFile: MultipartBody.Part?, +// ): ResponseState + +// @POST("/points") +// suspend fun createRecordingPoint( +// @Body body: CreateRecordingPointRequest, +// ): ResponseState diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/repository/PostRepositoryImpl.kt b/android/app/src/main/java/com/teamtripdraw/android/data/repository/PostRepositoryImpl.kt index 18b4be8cd..8fe083e79 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/repository/PostRepositoryImpl.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/repository/PostRepositoryImpl.kt @@ -8,6 +8,8 @@ import com.teamtripdraw.android.domain.model.post.PostOfAll import com.teamtripdraw.android.domain.model.post.PrePatchPost import com.teamtripdraw.android.domain.model.post.PrePost import com.teamtripdraw.android.domain.repository.PostRepository +import java.io.File +import java.time.LocalDateTime import javax.inject.Inject class PostRepositoryImpl @Inject constructor( @@ -23,6 +25,28 @@ class PostRepositoryImpl @Inject constructor( ) } + override suspend fun createCurrentPointPost( + tripId: Long, + title: String, + address: String, + writing: String, + latitude: Double, + longitude: Double, + recordedAt: LocalDateTime, + imageFile: File?, + ): Result { + return remotePostDataSource.createCurrentPointPost( + tripId = tripId, + title = title, + address = address, + writing = writing, + latitude = latitude, + longitude = longitude, + recordedAt = recordedAt, + imageFile = imageFile + ) + } + override suspend fun getPostByPostId(postId: Long): Result { return remotePostDataSource.getPostByPostId(postId).map { it.toDomain() } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/di/ServiceModule.kt b/android/app/src/main/java/com/teamtripdraw/android/di/ServiceModule.kt index f81e4a063..26657026c 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/di/ServiceModule.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/di/ServiceModule.kt @@ -1,5 +1,6 @@ package com.teamtripdraw.android.di +import com.teamtripdraw.android.data.httpClient.service.CreateCurrentPointPostService import com.teamtripdraw.android.data.httpClient.service.CreateRecordingPointService import com.teamtripdraw.android.data.httpClient.service.CreateTripService import com.teamtripdraw.android.data.httpClient.service.DeletePointService @@ -47,6 +48,11 @@ object ServiceModule { fun providesPostService(@TripDrawRetrofit retrofit: Retrofit): PostService = retrofit.create(PostService::class.java) + @Provides + @Singleton + fun providesCreateCurrentPointPostService(@TripDrawRetrofit retrofit: Retrofit): CreateCurrentPointPostService = + retrofit.create(CreateCurrentPointPostService::class.java) + @Provides @Singleton fun providesCreateRecordingPointService(@TripDrawRetrofit retrofit: Retrofit): CreateRecordingPointService = diff --git a/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PostRepository.kt b/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PostRepository.kt index fc379289f..ef344335e 100644 --- a/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PostRepository.kt +++ b/android/domain/src/main/java/com/teamtripdraw/android/domain/repository/PostRepository.kt @@ -4,11 +4,24 @@ import com.teamtripdraw.android.domain.model.post.Post import com.teamtripdraw.android.domain.model.post.PostOfAll import com.teamtripdraw.android.domain.model.post.PrePatchPost import com.teamtripdraw.android.domain.model.post.PrePost +import java.io.File +import java.time.LocalDateTime interface PostRepository { suspend fun addPost(prePost: PrePost): Result + suspend fun createCurrentPointPost( + tripId: Long, + title: String, + address: String, + writing: String, + latitude: Double, + longitude: Double, + recordedAt: LocalDateTime, + imageFile: File?, + ): Result + suspend fun getPostByPostId(postId: Long): Result suspend fun getPostByPointId(pointId: Long): Result From 6855681d91046f58551ff7e9986b009a33f7dcc3 Mon Sep 17 00:00:00 2001 From: otter Date: Tue, 17 Oct 2023 21:53:27 +0900 Subject: [PATCH 33/39] =?UTF-8?q?[feat]=20=ED=98=84=EC=9E=AC=20=EC=A7=80?= =?UTF-8?q?=EC=A0=90=EC=97=90=20=EB=8C=80=ED=95=9C=20=EA=B0=90=EC=83=81=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94=EA=B0=80=20?= =?UTF-8?q?(#370)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/post/writing/PostWritingActivity.kt | 27 +++++- .../ui/post/writing/PostWritingViewModel.kt | 83 +++++++++++++++---- .../android/ui/post/writing/WritingMode.kt | 4 +- .../post/writing/PostWritingViewModelTest.kt | 1 - .../android/domain/model/point/Point.kt | 2 + 5 files changed, 96 insertions(+), 21 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt index 8e4e23af3..7d705e563 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingActivity.kt @@ -71,8 +71,16 @@ class PostWritingActivity : AppCompatActivity() { val tripId = intent.getLongExtra(INTENT_KEY_TRIP_ID, Trip.NULL_SUBSTITUTE_ID) val pointId = intent.getLongExtra(INTENT_KEY_POINT_ID, Point.NULL_SUBSTITUTE_ID) val postId = intent.getLongExtra(INTENT_KEY_POST_ID, Post.NULL_SUBSTITUTE_ID) - - viewModel.initPostData(tripId, pointId, postId) + val latitude: Double = intent.getDoubleExtra(INTENT_KEY_LATITUDE, Point.NULL_LATITUDE) + val longitude: Double = intent.getDoubleExtra(INTENT_KEY_LONGITUDE, Point.NULL_LONGITUDE) + + viewModel.initPostData( + tripId = tripId, + pointId = pointId, + postId = postId, + latitude = latitude, + longitude = longitude, + ) } private fun initObserve() { @@ -119,6 +127,8 @@ class PostWritingActivity : AppCompatActivity() { private const val INTENT_KEY_TRIP_ID = "tripId" private const val INTENT_KEY_POINT_ID = "pointId" private const val INTENT_KEY_POST_ID = "postId" + private const val INTENT_KEY_LATITUDE = "latitude" + private const val INTENT_KEY_LONGITUDE = "longitude" fun getIntentByPoint(context: Context, tripId: Long, pointId: Long): Intent { val intent = Intent(context, PostWritingActivity::class.java) @@ -127,6 +137,19 @@ class PostWritingActivity : AppCompatActivity() { return intent } + fun getIntentByLatLng( + context: Context, + tripId: Long, + latitude: Double, + longitude: Double, + ): Intent { + val intent = Intent(context, PostWritingActivity::class.java) + intent.putExtra(INTENT_KEY_TRIP_ID, tripId) + intent.putExtra(INTENT_KEY_LATITUDE, latitude) + intent.putExtra(INTENT_KEY_LONGITUDE, longitude) + return intent + } + fun getIntentByPost( context: Context, postId: Long, diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt index 5d443a734..03df10368 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt @@ -19,6 +19,7 @@ import com.teamtripdraw.android.support.framework.presentation.event.Event import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch import java.io.File +import java.time.LocalDateTime import javax.inject.Inject @HiltViewModel @@ -34,6 +35,8 @@ class PostWritingViewModel @Inject constructor( private var tripId: Long = Trip.NULL_SUBSTITUTE_ID private var pointId: Long = Point.NULL_SUBSTITUTE_ID private var postId: Long = Post.NULL_SUBSTITUTE_ID + private var latitude: Double = Point.NULL_LATITUDE + private var longitude: Double = Point.NULL_LONGITUDE private lateinit var writingMode: WritingMode val title: MutableLiveData = MutableLiveData("") @@ -102,31 +105,60 @@ class PostWritingViewModel @Inject constructor( tripId: Long = Trip.NULL_SUBSTITUTE_ID, pointId: Long = Point.NULL_SUBSTITUTE_ID, postId: Long = Post.NULL_SUBSTITUTE_ID, + latitude: Double = Point.NULL_LATITUDE, + longitude: Double = Point.NULL_LONGITUDE, ) { this.tripId = tripId this.pointId = pointId this.postId = postId - setWritingMode(tripId, pointId, postId) + this.latitude = latitude + this.longitude = longitude + setWritingMode(tripId, pointId, postId, latitude, longitude) fetchPostData() } - private fun setWritingMode(tripId: Long, pointId: Long, postId: Long) { - if (tripId != Trip.NULL_SUBSTITUTE_ID && pointId != Point.NULL_SUBSTITUTE_ID) { - writingMode = WritingMode.NEW - } else if (postId != Post.NULL_SUBSTITUTE_ID) writingMode = WritingMode.EDIT + private fun setWritingMode( + tripId: Long, + pointId: Long, + postId: Long, + latitude: Double, + longitude: Double, + ) { + writingMode = + if (tripId != Trip.NULL_SUBSTITUTE_ID && pointId != Point.NULL_SUBSTITUTE_ID) { + WritingMode.NEW_RECORDED_POINT + } else if (postId != Post.NULL_SUBSTITUTE_ID) { + WritingMode.EDIT + } else if (latitude != Point.NULL_LATITUDE && longitude != Point.NULL_LONGITUDE) { + WritingMode.NEW_CURRENT_POINT + } else { + throw IllegalArgumentException("값이 잘못 설정되었습니다. (PostWritingViewModel)") + } } private fun fetchPostData() { - if (writingMode == WritingMode.NEW) { - viewModelScope.launch { - pointRepository.getPoint(pointId = pointId, tripId = tripId).onSuccess { - _point.value = it - fetchAddress() - fetchWritingMode() - } + when (writingMode) { + WritingMode.NEW_RECORDED_POINT -> fetchPostDataByPoint() + WritingMode.NEW_CURRENT_POINT -> fetchPostDataByLatLng() + WritingMode.EDIT -> fetchPost() + } + } + + private fun fetchPostDataByPoint() { + viewModelScope.launch { + pointRepository.getPoint(pointId = pointId, tripId = tripId).onSuccess { + _point.value = it + fetchAddress() + fetchWritingMode() + } + } + } + + private fun fetchPostDataByLatLng() { + viewModelScope.launch { + geocodingRepository.getAddress(latitude, longitude).onSuccess { + _address.value = it } - } else if (writingMode == WritingMode.EDIT) { - fetchPost() } } @@ -142,7 +174,7 @@ class PostWritingViewModel @Inject constructor( private fun fetchWritingMode() { if (_point.value == null) throw IllegalArgumentException("") if (_point.value!!.hasPost.not()) { - writingMode = WritingMode.NEW + writingMode = WritingMode.NEW_RECORDED_POINT return } writingMode = WritingMode.EDIT @@ -171,12 +203,29 @@ class PostWritingViewModel @Inject constructor( fun completeWritingEvent() { when (writingMode) { - WritingMode.NEW -> writeNewPost() + WritingMode.NEW_CURRENT_POINT -> writeNewCurrentPointPost() + WritingMode.NEW_RECORDED_POINT -> writeNewRecordedPointPost() WritingMode.EDIT -> writeEditedPost() } } - private fun writeNewPost() { + private fun writeNewCurrentPointPost() { + viewModelScope.launch { + postRepository.createCurrentPointPost( + tripId = tripId, + title = title.value ?: "", + address = address.value ?: "", + writing = writing.value ?: "", + latitude = latitude, + longitude = longitude, + recordedAt = LocalDateTime.now(), + imageFile = imageFile.value, + ).onSuccess { _writingCompletedEvent.value = Event(true) } + .onFailure { TripDrawApplication.logUtil.general.log(it) } + } + } + + private fun writeNewRecordedPointPost() { viewModelScope.launch { val prePost = PrePost( tripId = tripId, diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt index f666dbeff..64dbb2224 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt @@ -1,5 +1,7 @@ package com.teamtripdraw.android.ui.post.writing enum class WritingMode { - NEW, EDIT + NEW_RECORDED_POINT, + NEW_CURRENT_POINT, + EDIT, } diff --git a/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt b/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt index 7fbb20b5b..b7f327a9a 100644 --- a/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt +++ b/android/app/src/test/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModelTest.kt @@ -39,7 +39,6 @@ internal class PostWritingViewModelTest : DefaultViewModelTest() { sut = PostWritingViewModel( postRepository = postRepository, pointRepository = pointRepository, - tripRepository = tripRepository, geocodingRepository = geocodingRepository, ) } diff --git a/android/domain/src/main/java/com/teamtripdraw/android/domain/model/point/Point.kt b/android/domain/src/main/java/com/teamtripdraw/android/domain/model/point/Point.kt index 5e89ce62c..2d2052508 100644 --- a/android/domain/src/main/java/com/teamtripdraw/android/domain/model/point/Point.kt +++ b/android/domain/src/main/java/com/teamtripdraw/android/domain/model/point/Point.kt @@ -11,5 +11,7 @@ data class Point( ) { companion object { const val NULL_SUBSTITUTE_ID = -1L + const val NULL_LATITUDE = (-100).toDouble() // latitude는 -90 ~ 90 범위의 값을 가집니다. + const val NULL_LONGITUDE = (-200F).toDouble() // longitude는 -180 ~ 180 범위의 값을 가집니다. } } From bc55a92d6a0906db24d5ba02c384f7475e00f41d Mon Sep 17 00:00:00 2001 From: otter Date: Tue, 17 Oct 2023 22:07:15 +0900 Subject: [PATCH 34/39] =?UTF-8?q?[refactor]=20=EA=B0=90=EC=83=81=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20/=20writingMode=20=EA=B2=B0=EC=A0=95=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B6=84=EB=A6=AC=20=20(#370)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/post/writing/PostWritingViewModel.kt | 21 +--------------- .../android/ui/post/writing/WritingMode.kt | 25 +++++++++++++++++++ 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt index 03df10368..d8a93de0e 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/PostWritingViewModel.kt @@ -113,29 +113,10 @@ class PostWritingViewModel @Inject constructor( this.postId = postId this.latitude = latitude this.longitude = longitude - setWritingMode(tripId, pointId, postId, latitude, longitude) + writingMode = WritingMode.getWritingMode(tripId, pointId, postId, latitude, longitude) fetchPostData() } - private fun setWritingMode( - tripId: Long, - pointId: Long, - postId: Long, - latitude: Double, - longitude: Double, - ) { - writingMode = - if (tripId != Trip.NULL_SUBSTITUTE_ID && pointId != Point.NULL_SUBSTITUTE_ID) { - WritingMode.NEW_RECORDED_POINT - } else if (postId != Post.NULL_SUBSTITUTE_ID) { - WritingMode.EDIT - } else if (latitude != Point.NULL_LATITUDE && longitude != Point.NULL_LONGITUDE) { - WritingMode.NEW_CURRENT_POINT - } else { - throw IllegalArgumentException("값이 잘못 설정되었습니다. (PostWritingViewModel)") - } - } - private fun fetchPostData() { when (writingMode) { WritingMode.NEW_RECORDED_POINT -> fetchPostDataByPoint() diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt index 64dbb2224..86f74e791 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/post/writing/WritingMode.kt @@ -1,7 +1,32 @@ package com.teamtripdraw.android.ui.post.writing +import com.teamtripdraw.android.domain.model.point.Point +import com.teamtripdraw.android.domain.model.post.Post +import com.teamtripdraw.android.domain.model.trip.Trip + enum class WritingMode { NEW_RECORDED_POINT, NEW_CURRENT_POINT, EDIT, + ; + + companion object { + fun getWritingMode( + tripId: Long, + pointId: Long, + postId: Long, + latitude: Double, + longitude: Double, + ): WritingMode { + return if (tripId != Trip.NULL_SUBSTITUTE_ID && pointId != Point.NULL_SUBSTITUTE_ID) { + NEW_RECORDED_POINT + } else if (postId != Post.NULL_SUBSTITUTE_ID) { + EDIT + } else if (latitude != Point.NULL_LATITUDE && longitude != Point.NULL_LONGITUDE) { + NEW_CURRENT_POINT + } else { + throw IllegalArgumentException("WritingMode를 결정할 수 없습니다. 필요한 값을 모두 설정하였는지 확인해주세요") + } + } + } } From 21ce151c4d5ff3f1d2006e95ae8e2e0b24d5c1f8 Mon Sep 17 00:00:00 2001 From: otter Date: Thu, 19 Oct 2023 17:43:53 +0900 Subject: [PATCH 35/39] =?UTF-8?q?[refactor]=20=EA=B0=90=EC=83=81=20?= =?UTF-8?q?=EC=9E=91=EC=84=B1=20/=20=EB=B6=88=ED=95=84=EC=9A=94=20?= =?UTF-8?q?=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0=20(#370)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/CreateCurrentPointPostService.kt | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/CreateCurrentPointPostService.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/CreateCurrentPointPostService.kt index bb6b4adf0..a16e861f7 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/CreateCurrentPointPostService.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/CreateCurrentPointPostService.kt @@ -16,15 +16,3 @@ interface CreateCurrentPointPostService { @Part imageFile: MultipartBody.Part?, ): ResponseState } - -// @Multipart -// @POST("/posts") -// suspend fun addPost( -// @Part("dto") addPostRequest: RequestBody, -// @Part imageFile: MultipartBody.Part?, -// ): ResponseState - -// @POST("/points") -// suspend fun createRecordingPoint( -// @Body body: CreateRecordingPointRequest, -// ): ResponseState From 6acf438d9856e5c9c845c00ae5d27ff5684d9f65 Mon Sep 17 00:00:00 2001 From: otter Date: Thu, 19 Oct 2023 19:36:37 +0900 Subject: [PATCH 36/39] =?UTF-8?q?[refactor]=20=EB=84=A4=EC=9D=B4=EB=B2=84?= =?UTF-8?q?=20api=EB=A1=9C=EB=B6=80=ED=84=B0=20=ED=96=89=EC=A0=95=EB=8F=99?= =?UTF-8?q?=EB=A7=8C=20=EB=B0=9B=EC=95=84=EC=98=A4=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95=20(#525)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/data/httpClient/service/NaverGeocodingService.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/NaverGeocodingService.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/NaverGeocodingService.kt index f37c347aa..548f6d798 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/NaverGeocodingService.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/NaverGeocodingService.kt @@ -12,6 +12,6 @@ interface NaverGeocodingService { @Query("coords") coords: String, @Query("sourcecrs") sourcecrs: String = "epsg:4326", @Query("output") output: String = "json", - @Query("orders") orders: String = "legalcode,admcode", + @Query("orders") orders: String = "admcode", ): ResponseState } From d63166fd3e67a33e981d63c26860a6aac43489f3 Mon Sep 17 00:00:00 2001 From: 2chang5 Date: Thu, 19 Oct 2023 18:15:31 +0900 Subject: [PATCH 37/39] =?UTF-8?q?[feat]=20=ED=99=88,=EA=B0=90=EC=83=81=20?= =?UTF-8?q?=EA=B8=B0=EB=A1=9D=20/=20=EA=B0=90=EC=83=81=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1=EC=8B=9C=20=EC=9C=84=EC=B9=98=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=ED=95=98=EB=8A=94=20=EC=9A=94=EA=B5=AC=EC=82=AC=ED=95=AD?= =?UTF-8?q?=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20=EB=8C=80=EC=9D=91=20?= =?UTF-8?q?(#522)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/ui/home/HomeFragment.kt | 14 +++++++--- .../android/ui/home/HomeViewModel.kt | 27 +++---------------- 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeFragment.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeFragment.kt index cc428bdba..29a169c96 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeFragment.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeFragment.kt @@ -15,6 +15,7 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.lifecycle.LiveData import com.google.android.gms.location.FusedLocationProviderClient +import com.google.android.gms.location.LocationResult import com.google.android.gms.location.LocationServices import com.naver.maps.map.MapFragment import com.naver.maps.map.NaverMap @@ -223,7 +224,7 @@ class HomeFragment : Fragment(), OnMapReadyCallback { getUpdateLocation( getFusedLocationClient(), requireContext(), - homeViewModel::createPoint, + homeViewModel::openPostWriting, ) } } @@ -238,9 +239,16 @@ class HomeFragment : Fragment(), OnMapReadyCallback { ) } - private fun navigateToPostWriting(pointId: Long) { + private fun navigateToPostWriting(locationResult: LocationResult) { val tripId = homeViewModel.tripId - startActivity(PostWritingActivity.getIntentByPoint(requireContext(), tripId, pointId)) + startActivity( + PostWritingActivity.getIntentByLatLng( + context = requireContext(), + tripId = tripId, + latitude = locationResult.locations.first().latitude, + longitude = locationResult.locations.first().longitude, + ), + ) } private fun observeUpdateTripId() { diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeViewModel.kt index f4e6905df..697019698 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/home/HomeViewModel.kt @@ -6,8 +6,6 @@ import androidx.lifecycle.Transformations import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import com.google.android.gms.location.LocationResult -import com.teamtripdraw.android.TripDrawApplication.DependencyContainer.logUtil -import com.teamtripdraw.android.domain.model.point.PrePoint import com.teamtripdraw.android.domain.model.point.Route import com.teamtripdraw.android.domain.model.trip.Trip import com.teamtripdraw.android.domain.repository.PointRepository @@ -18,7 +16,6 @@ import com.teamtripdraw.android.ui.model.UiRoute import com.teamtripdraw.android.ui.model.mapper.toPresentation import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.launch -import java.time.LocalDateTime import javax.inject.Inject @HiltViewModel @@ -46,8 +43,8 @@ class HomeViewModel @Inject constructor( private val _openPostViewerEvent = MutableLiveData>() val openPostViewerEvent: LiveData> = _openPostViewerEvent - private val _openPostWritingEvent = MutableLiveData>() - val openPostWritingEvent: LiveData> = _openPostWritingEvent + private val _openPostWritingEvent = MutableLiveData>() + val openPostWritingEvent: LiveData> = _openPostWritingEvent private val _markerSelectEvent = MutableLiveData() val makerSelectedEvent: LiveData = _markerSelectEvent @@ -117,26 +114,10 @@ class HomeViewModel @Inject constructor( _openPostViewerEvent.value = Event(true) } - fun createPoint(locationResult: LocationResult) { - viewModelScope.launch { - pointRepository.createRecordingPoint( - getPrePoint(locationResult), - tripId, - ).onSuccess { - _openPostWritingEvent.value = Event(it) - }.onFailure { - logUtil.general.log(it) - } - } + fun openPostWriting(locationResult: LocationResult) { + _openPostWritingEvent.value = Event(locationResult) } - private fun getPrePoint(locationResult: LocationResult): PrePoint = - PrePoint( - locationResult.locations.first().latitude, - locationResult.locations.first().longitude, - LocalDateTime.now(), - ) - fun finishTripEvent() { _finishTripEvent.value = true } From 7b47f5111b549d4874b8e522266fa0d45a9749c7 Mon Sep 17 00:00:00 2001 From: pingu244 <69796976+pingu244@users.noreply.github.com> Date: Thu, 19 Oct 2023 22:15:50 +0900 Subject: [PATCH 38/39] =?UTF-8?q?[feat]=20=EC=97=AC=ED=96=89=20=EB=B0=8F?= =?UTF-8?q?=20=EA=B0=90=EC=83=81=20=ED=95=84=ED=84=B0=20=EC=98=B5=EC=85=98?= =?UTF-8?q?=20=EC=84=A0=ED=83=9D=20=EB=B7=B0=20(#438)=20(#455)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [feat] 필터 검색 / 옵션 추가 (#438) * [feat] 필터 검색 / 필터 화면 생성 (#438) * [refactor] 필터 검색 / bindingAdapter 적용 (#438) * [refactor] 필터 검색 / filterType에 따라 특정 option gone 하기 (#438) * [feat] 필터 검색 / 선택한 옵션값 viewModel에 저장 (#438) * [feat] 필터 검색 / 선택한 옵션값 초기화 기능 추가 (#438) * [refactor] 필터 검색 / 전체적인 리팩토링 (#438) - 커스텀뷰들을 List로 모아두기 - MVVM에 맞는 형태로 수정 - xml의 string 빼기 - 함수 분리 * [feat] 필터 검색 / 주소 검색 연결 (#438) * [refactor] 필터 검색 / 코드 정리 (#438) * [feat] 필터 검색 / 뒤로가기 버튼 기능 (#438) * [feat] 필터 검색 / 이전 선택대로 초기화하기 (#438) - 필터 선택 후 나왔다가 다시 들어가면 이전에 선택했던대로 초기화 * [fix] 필터 화면 / 실기기에서 선택 색상 바꾸기 (#438) * [refactor] 필터 화면 / Filter화면 inflate 방식 변경 (#438) * [fix] 머지하며 문제된 부분 해결 (#438) * [refactor] 전체 감상 / 필터 결과에 따라 검색해주기 (#438) * [refactor] 필터 화면 / 속성명 수정 (#438) * [refactor] 필터 화면 / Any를 제너릭으로 수정 (#438) * [refactor] 필터 화면 / bindingAdapter 내부 함수로 대체 (#438) * [refactor] 필터 화면 / 준비가 안된 기능 visibility 처리 (#438) * [refactor] 충돌 해결 (#438) * [refactor] 전체 여행 / 필터에 따라 검색 (#438) * [refactor] 필터 검색을 했을 때 recyclerView position을 0으로 이동 (#438) * [refactor] 코드 정리 (#438) * [refactor] 필터 화면 / 전체적인 코드 정리 (#438) - NumberPicker 관련 로직 MVVM에 맞게 수정 - 함수명 수정 - 로직 단순화 * [refactor] 필터 화면 / 메서드 순서 변경 (#438) * [refactor] 주소 필터 화면 / activity의 역할 분담을 위해 리사이클러뷰로 변경 (#438) * [refactor] 주소 필터 화면 / 색상 변경 적용 (#438) * [refactor] 주소 필터 화면 / 클릭시 색상 변경 로직 개선 (#438) * [feat] 주소 필터 화면 / api 연결 (#438) * [refactor] 필터 화면 / 제공하지 않는 기능에 대한 뷰 감추기 (#438) * [refactor] 필터 화면 / 코드 리팩터링 (#438) - 함수 위치 변화 - animator = null - fetch() 함수 위치 수정 --------- Co-authored-by: otter --- android/app/src/main/AndroidManifest.xml | 13 +- .../dataSource/address/AddressDataSource.kt | 7 + .../address/RemoteAddressDataSource.kt | 13 + .../dto/response/GetAddressesResponse.kt | 10 + .../httpClient/service/GetAddressesService.kt | 14 + .../data/repository/AddressRepositoryImpl.kt | 19 + .../android/di/RemoteDataSourceModule.kt | 6 + .../android/di/RepositoryModule.kt | 6 + .../teamtripdraw/android/di/ServiceModule.kt | 6 + .../android/ui/allPosts/AllPostsFragment.kt | 53 ++- .../android/ui/allPosts/AllPostsViewModel.kt | 67 +++- .../android/ui/allTrips/AllTripsFragment.kt | 61 +++- .../android/ui/allTrips/AllTripsViewModel.kt | 76 +++- .../FilterSelectionBindingAdapter.kt | 53 +++ .../android/ui/filter/FilterOptionsView.kt | 105 ++++++ .../ui/filter/FilterSelectionActivity.kt | 170 +++++++++ .../ui/filter/FilterSelectionViewModel.kt | 84 +++++ .../android/ui/filter/FilterType.kt | 9 + .../android/ui/filter/FilterView.kt | 5 + .../android/ui/filter/SelectedOptions.kt | 57 +++ .../address/AddressSelectionActivity.kt | 77 ++++ .../filter/address/AddressSelectionAdapter.kt | 37 ++ .../address/AddressSelectionViewHolder.kt | 36 ++ .../address/AddressSelectionViewModel.kt | 125 +++++++ .../ui/model/UiAddressSelectionItem.kt | 6 + .../ui/model/mapper/FilterOptionUiMapper.kt | 70 ++++ .../color/selector_filter_chip_bg_state.xml | 5 + .../res/color/selector_filter_text_state.xml | 5 + .../app/src/main/res/drawable/ic_refresh.xml | 9 + .../shape_td_light_blue_fill_0_rect.xml | 5 + .../shape_td_main_blue_fill_12_rect.xml | 6 + .../res/layout/activity_address_selection.xml | 135 +++++++ .../res/layout/activity_filter_selection.xml | 336 ++++++++++++++++++ .../main/res/layout/fragment_all_posts.xml | 3 +- .../main/res/layout/fragment_all_trips.xml | 1 + .../res/layout/item_filter_option_address.xml | 30 ++ .../main/res/layout/view_filter_options.xml | 36 ++ android/app/src/main/res/values/attrs.xml | 9 + android/app/src/main/res/values/strings.xml | 24 ++ android/app/src/main/res/values/themes.xml | 13 + .../domain/model/filterOption/FilterOption.kt | 6 + .../model/filterOption/OptionAgeRange.kt | 15 + .../model/filterOption/OptionDayOfWeek.kt | 13 + .../domain/model/filterOption/OptionGender.kt | 6 + .../domain/model/filterOption/OptionHour.kt | 45 +++ .../domain/model/filterOption/OptionMonth.kt | 18 + .../domain/model/filterOption/OptionYear.kt | 8 + .../domain/repository/AddressRepository.kt | 10 + 48 files changed, 1872 insertions(+), 51 deletions(-) create mode 100644 android/app/src/main/java/com/teamtripdraw/android/data/dataSource/address/AddressDataSource.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/data/dataSource/address/RemoteAddressDataSource.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetAddressesResponse.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/GetAddressesService.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/data/repository/AddressRepositoryImpl.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/FilterSelectionBindingAdapter.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterOptionsView.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterSelectionActivity.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterSelectionViewModel.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterType.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterView.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/filter/SelectedOptions.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionActivity.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionAdapter.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionViewHolder.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionViewModel.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/model/UiAddressSelectionItem.kt create mode 100644 android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/FilterOptionUiMapper.kt create mode 100644 android/app/src/main/res/color/selector_filter_chip_bg_state.xml create mode 100644 android/app/src/main/res/color/selector_filter_text_state.xml create mode 100644 android/app/src/main/res/drawable/ic_refresh.xml create mode 100644 android/app/src/main/res/drawable/shape_td_light_blue_fill_0_rect.xml create mode 100644 android/app/src/main/res/drawable/shape_td_main_blue_fill_12_rect.xml create mode 100644 android/app/src/main/res/layout/activity_address_selection.xml create mode 100644 android/app/src/main/res/layout/activity_filter_selection.xml create mode 100644 android/app/src/main/res/layout/item_filter_option_address.xml create mode 100644 android/app/src/main/res/layout/view_filter_options.xml create mode 100644 android/app/src/main/res/values/attrs.xml create mode 100644 android/domain/src/main/java/com/teamtripdraw/android/domain/model/filterOption/FilterOption.kt create mode 100644 android/domain/src/main/java/com/teamtripdraw/android/domain/model/filterOption/OptionAgeRange.kt create mode 100644 android/domain/src/main/java/com/teamtripdraw/android/domain/model/filterOption/OptionDayOfWeek.kt create mode 100644 android/domain/src/main/java/com/teamtripdraw/android/domain/model/filterOption/OptionGender.kt create mode 100644 android/domain/src/main/java/com/teamtripdraw/android/domain/model/filterOption/OptionHour.kt create mode 100644 android/domain/src/main/java/com/teamtripdraw/android/domain/model/filterOption/OptionMonth.kt create mode 100644 android/domain/src/main/java/com/teamtripdraw/android/domain/model/filterOption/OptionYear.kt create mode 100644 android/domain/src/main/java/com/teamtripdraw/android/domain/repository/AddressRepository.kt diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index d4073e33c..77bde3bc9 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -62,7 +62,7 @@ android:name=".ui.home.recordingPoint.RecordingPointService" android:description="@string/recording_point_service_description" android:exported="false" - android:foregroundServiceType="location"/> + android:foregroundServiceType="location" /> + + + + diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/address/AddressDataSource.kt b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/address/AddressDataSource.kt new file mode 100644 index 000000000..276afbb42 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/address/AddressDataSource.kt @@ -0,0 +1,7 @@ +package com.teamtripdraw.android.data.dataSource.address + +interface AddressDataSource { + interface Remote { + suspend fun getAddresses(siDo: String, siGunGu: String): Result> + } +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/address/RemoteAddressDataSource.kt b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/address/RemoteAddressDataSource.kt new file mode 100644 index 000000000..aa345672e --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/data/dataSource/address/RemoteAddressDataSource.kt @@ -0,0 +1,13 @@ +package com.teamtripdraw.android.data.dataSource.address + +import com.teamtripdraw.android.data.httpClient.service.GetAddressesService +import javax.inject.Inject + +class RemoteAddressDataSource @Inject constructor( + private val getAddressesService: GetAddressesService, +) : AddressDataSource.Remote { + + override suspend fun getAddresses(siDo: String, siGunGu: String): Result> = + getAddressesService.getAddresses(siDo, siGunGu) + .process { body, headers -> Result.success(body.areas) } +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetAddressesResponse.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetAddressesResponse.kt new file mode 100644 index 000000000..57125b0c2 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/dto/response/GetAddressesResponse.kt @@ -0,0 +1,10 @@ +package com.teamtripdraw.android.data.httpClient.dto.response + +import com.squareup.moshi.Json +import com.squareup.moshi.JsonClass + +@JsonClass(generateAdapter = true) +data class GetAddressesResponse( + @Json(name = "areas") + val areas: List, +) diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/GetAddressesService.kt b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/GetAddressesService.kt new file mode 100644 index 000000000..5e63de372 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/data/httpClient/service/GetAddressesService.kt @@ -0,0 +1,14 @@ +package com.teamtripdraw.android.data.httpClient.service + +import com.teamtripdraw.android.data.httpClient.dto.response.GetAddressesResponse +import com.teamtripdraw.android.data.httpClient.retrofitAdapter.responseState.ResponseState +import retrofit2.http.GET +import retrofit2.http.Query + +interface GetAddressesService { + @GET("/areas") + suspend fun getAddresses( + @Query("sido") siDo: String, + @Query("sigungu") siGunGu: String, + ): ResponseState +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/data/repository/AddressRepositoryImpl.kt b/android/app/src/main/java/com/teamtripdraw/android/data/repository/AddressRepositoryImpl.kt new file mode 100644 index 000000000..00d0900fa --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/data/repository/AddressRepositoryImpl.kt @@ -0,0 +1,19 @@ +package com.teamtripdraw.android.data.repository + +import com.teamtripdraw.android.data.dataSource.address.AddressDataSource +import com.teamtripdraw.android.domain.repository.AddressRepository +import javax.inject.Inject + +class AddressRepositoryImpl @Inject constructor( + private val remoteAddressDataSource: AddressDataSource.Remote, +) : AddressRepository { + + override suspend fun getSiDos(): Result> = + remoteAddressDataSource.getAddresses("", "") + + override suspend fun getSiGunGus(siDo: String): Result> = + remoteAddressDataSource.getAddresses(siDo, "") + + override suspend fun getEupMyeonDongs(siDo: String, siGunGu: String): Result> = + remoteAddressDataSource.getAddresses(siDo, siGunGu) +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/di/RemoteDataSourceModule.kt b/android/app/src/main/java/com/teamtripdraw/android/di/RemoteDataSourceModule.kt index b8c699b9b..ffae15001 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/di/RemoteDataSourceModule.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/di/RemoteDataSourceModule.kt @@ -1,5 +1,7 @@ package com.teamtripdraw.android.di +import com.teamtripdraw.android.data.dataSource.address.AddressDataSource +import com.teamtripdraw.android.data.dataSource.address.RemoteAddressDataSource import com.teamtripdraw.android.data.dataSource.auth.login.LoginDataSource import com.teamtripdraw.android.data.dataSource.auth.login.RemoteLoginDataSourceImpl import com.teamtripdraw.android.data.dataSource.auth.signUp.RemoteSignUpDataSourceImpl @@ -47,6 +49,10 @@ interface RemoteDataSourceModule { @Singleton fun bindsRemoteLoginDataSource(source: RemoteLoginDataSourceImpl): LoginDataSource.Remote + @Binds + @Singleton + fun bindsRemoteAddressDataSource(source: RemoteAddressDataSource): AddressDataSource.Remote + @Binds @Singleton fun bindsRemoteGeocodingDataSource(source: RemoteGeocodingDataSourceImpl): GeocodingDataSource.Remote diff --git a/android/app/src/main/java/com/teamtripdraw/android/di/RepositoryModule.kt b/android/app/src/main/java/com/teamtripdraw/android/di/RepositoryModule.kt index 499cca20f..282e4d1ad 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/di/RepositoryModule.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/di/RepositoryModule.kt @@ -1,10 +1,12 @@ package com.teamtripdraw.android.di +import com.teamtripdraw.android.data.repository.AddressRepositoryImpl import com.teamtripdraw.android.data.repository.AuthRepositoryImpl import com.teamtripdraw.android.data.repository.GeocodingRepositoryImpl import com.teamtripdraw.android.data.repository.PointRepositoryImpl import com.teamtripdraw.android.data.repository.PostRepositoryImpl import com.teamtripdraw.android.data.repository.TripRepositoryImpl +import com.teamtripdraw.android.domain.repository.AddressRepository import com.teamtripdraw.android.domain.repository.AuthRepository import com.teamtripdraw.android.domain.repository.GeocodingRepository import com.teamtripdraw.android.domain.repository.PointRepository @@ -39,4 +41,8 @@ interface RepositoryModule { @Binds @Singleton fun bindsGeocoding(repository: GeocodingRepositoryImpl): GeocodingRepository + + @Binds + @Singleton + fun bindsAddressRepository(repository: AddressRepositoryImpl): AddressRepository } diff --git a/android/app/src/main/java/com/teamtripdraw/android/di/ServiceModule.kt b/android/app/src/main/java/com/teamtripdraw/android/di/ServiceModule.kt index 26657026c..1c846b039 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/di/ServiceModule.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/di/ServiceModule.kt @@ -5,6 +5,7 @@ import com.teamtripdraw.android.data.httpClient.service.CreateRecordingPointServ import com.teamtripdraw.android.data.httpClient.service.CreateTripService import com.teamtripdraw.android.data.httpClient.service.DeletePointService import com.teamtripdraw.android.data.httpClient.service.DeleteTripService +import com.teamtripdraw.android.data.httpClient.service.GetAddressesService import com.teamtripdraw.android.data.httpClient.service.GetAllTripsService import com.teamtripdraw.android.data.httpClient.service.GetPointPostService import com.teamtripdraw.android.data.httpClient.service.GetPointService @@ -103,6 +104,11 @@ object ServiceModule { fun providesUnsubscribeService(@TripDrawRetrofit retrofit: Retrofit): UnsubscribeService = retrofit.create(UnsubscribeService::class.java) + @Provides + @Singleton + fun providesGetAddressesService(@TripDrawRetrofit retrofit: Retrofit): GetAddressesService = + retrofit.create(GetAddressesService::class.java) + @Provides @Singleton fun providesNaverReverseGeocodingService(@NaverReverseGeocodingRetrofit retrofit: Retrofit): NaverGeocodingService = diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsFragment.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsFragment.kt index 5bcae63ea..df6e269c6 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsFragment.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsFragment.kt @@ -1,15 +1,23 @@ package com.teamtripdraw.android.ui.allPosts +import android.app.Activity +import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.activity.result.contract.ActivityResultContracts import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.teamtripdraw.android.databinding.FragmentAllPostsBinding import com.teamtripdraw.android.support.framework.presentation.event.EventObserver +import com.teamtripdraw.android.support.framework.presentation.getParcelableExtraCompat +import com.teamtripdraw.android.ui.filter.FilterSelectionActivity +import com.teamtripdraw.android.ui.filter.FilterSelectionActivity.Companion.SELECTED_OPTIONS_INTENT_KEY +import com.teamtripdraw.android.ui.filter.FilterType +import com.teamtripdraw.android.ui.filter.SelectedOptions import com.teamtripdraw.android.ui.post.detail.PostDetailActivity import dagger.hilt.android.AndroidEntryPoint @@ -22,6 +30,17 @@ class AllPostsFragment : Fragment() { private lateinit var adapter: AllPostsAdapter private val viewModel: AllPostsViewModel by viewModels() + private val getFilterOptionsResult = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode != Activity.RESULT_OK) return@registerForActivityResult + val intent: Intent = result.data!! + val selectedOptions = + intent.getParcelableExtraCompat(SELECTED_OPTIONS_INTENT_KEY) + ?: throw java.lang.IllegalStateException() + viewModel.updateSelectedOptions(selectedOptions) + viewModel.fetchPosts() + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -34,6 +53,7 @@ class AllPostsFragment : Fragment() { initObserver() setAdapter() addScrollListener() + viewModel.fetchPosts() return binding.root } @@ -45,11 +65,14 @@ class AllPostsFragment : Fragment() { private fun initObserver() { initPostsObserve() initOpenPostDetailEventObserve() + initOpenFilterSelectionEventObserve() } private fun initPostsObserve() { viewModel.posts.observe(viewLifecycleOwner) { - adapter.submitList(it.postItems) + adapter.submitList(it.postItems) { + binding.rvAllPosts.smoothScrollToPosition(INITIAL_POSITION) + } } } @@ -64,9 +87,29 @@ class AllPostsFragment : Fragment() { startActivity(PostDetailActivity.getIntent(requireContext(), postId)) } + private fun initOpenFilterSelectionEventObserve() { + viewModel.openFilterSelectionEvent.observe( + viewLifecycleOwner, + this::onFilterSelectionClick, + ) + } + + private fun onFilterSelectionClick(isClicked: Boolean) { + if (isClicked) { + val intent = + FilterSelectionActivity.getIntent( + requireContext(), + FilterType.POST, + viewModel.selectedOptions, + ) + getFilterOptionsResult.launch(intent) + } + } + private fun setAdapter() { adapter = AllPostsAdapter(viewModel::openPostDetail) binding.rvAllPosts.adapter = adapter + binding.rvAllPosts.itemAnimator = null } private fun addScrollListener() { @@ -93,13 +136,6 @@ class AllPostsFragment : Fragment() { private fun checkLoadThreshold(layoutManager: LinearLayoutManager, lastPosition: Int) = layoutManager.itemCount <= lastPosition + LOAD_THRESHOLD - override fun onResume() { - super.onResume() - fetchPosts() - } - - private fun fetchPosts() = viewModel.fetchPosts() - override fun onDestroyView() { super.onDestroyView() _binding = null @@ -108,5 +144,6 @@ class AllPostsFragment : Fragment() { companion object { private const val LOAD_THRESHOLD = 3 private const val DOWNWARD_DIRECTION = 1 + private const val INITIAL_POSITION = 0 } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsViewModel.kt index ba0a180c6..b2af4c0b7 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allPosts/AllPostsViewModel.kt @@ -9,6 +9,7 @@ import com.teamtripdraw.android.TripDrawApplication import com.teamtripdraw.android.domain.model.post.PostOfAll import com.teamtripdraw.android.domain.repository.PostRepository import com.teamtripdraw.android.support.framework.presentation.event.Event +import com.teamtripdraw.android.ui.filter.SelectedOptions import com.teamtripdraw.android.ui.model.allPosts.UiAllPosts import com.teamtripdraw.android.ui.model.allPosts.UiItemView import com.teamtripdraw.android.ui.model.allPosts.UiLoadingItem @@ -25,9 +26,14 @@ class AllPostsViewModel @Inject constructor( private val _uiPosts: MutableLiveData> = MutableLiveData(listOf()) val posts: LiveData = Transformations.map(_uiPosts) { post -> UiAllPosts(post) } + var selectedOptions: SelectedOptions? = null + private val _openPostDetailEvent = MutableLiveData>() val openPostDetailEvent: LiveData> = _openPostDetailEvent + private val _openFilterSelectionEvent = MutableLiveData() + val openFilterSelectionEvent: LiveData = _openFilterSelectionEvent + private var lastId: Long? = null var hasNextPage = true @@ -37,29 +43,53 @@ class AllPostsViewModel @Inject constructor( private set fun fetchPosts() { - if (_uiPosts.value!!.isNotEmpty() && hasNextPage) { + reloadIfFiltered() + checkLoadOrNot() + getPosts() + } + + private fun reloadIfFiltered() { + if (_openFilterSelectionEvent.value == true) { + lastId = null + } + } + + private fun checkLoadOrNot() { + if (lastId != null && hasNextPage) { isAddLoading = true addLoadingItem() } - getPosts() } private fun addLoadingItem() { - _uiPosts.value = _uiPosts.value!!.toMutableList().apply { add(UiLoadingItem) } + _uiPosts.value = requireNotNull(_uiPosts.value).toMutableList().apply { add(UiLoadingItem) } } private fun getPosts() { viewModelScope.launch { - postRepository.getAllPosts(lastViewedId = lastId, limit = PAGE_ITEM_SIZE) - .onSuccess { posts -> - setLastItemId(posts) - setHasNextPage(posts) - isAddLoading = false + postRepository.getAllPosts( + lastViewedId = lastId, + limit = PAGE_ITEM_SIZE, + address = selectedOptions?.address ?: "", + years = selectedOptions?.years ?: listOf(), + months = selectedOptions?.months ?: listOf(), + daysOfWeek = selectedOptions?.daysOfWeek ?: listOf(), + hours = selectedOptions?.hours ?: listOf(), + ageRanges = selectedOptions?.ageRanges ?: listOf(), + genders = selectedOptions?.genders ?: listOf(), + ).onSuccess { posts -> + setLastItemId(posts) + setHasNextPage(posts) + isAddLoading = false + + if (_openFilterSelectionEvent.value == true) { + getSearchResult(posts) + } else { fetchPosts(posts) } - .onFailure { - TripDrawApplication.logUtil.general.log(it) - } + }.onFailure { + TripDrawApplication.logUtil.general.log(it) + } } } @@ -71,17 +101,30 @@ class AllPostsViewModel @Inject constructor( if (posts.size < PAGE_ITEM_SIZE && lastId != null) hasNextPage = false } + private fun getSearchResult(posts: List) { + _uiPosts.value = posts.map { it.toPresentation() } + _openFilterSelectionEvent.value = false + } + private fun fetchPosts(posts: List) { - _uiPosts.value = _uiPosts.value!!.toMutableList().apply { + _uiPosts.value = requireNotNull(_uiPosts.value).toMutableList().apply { remove(UiLoadingItem) addAll(posts.map { it.toPresentation() }) } } + fun updateSelectedOptions(options: SelectedOptions) { + selectedOptions = options + } + fun openPostDetail(id: Long) { _openPostDetailEvent.value = Event(id) } + fun openFilterSelection() { + _openFilterSelectionEvent.value = true + } + companion object { private const val PAGE_ITEM_SIZE = 20 } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsFragment.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsFragment.kt index 180185185..4603d0892 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsFragment.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsFragment.kt @@ -1,14 +1,22 @@ package com.teamtripdraw.android.ui.allTrips +import android.app.Activity.RESULT_OK +import android.content.Intent import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import androidx.activity.result.contract.ActivityResultContracts import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import com.teamtripdraw.android.databinding.FragmentAllTripsBinding +import com.teamtripdraw.android.support.framework.presentation.getParcelableExtraCompat +import com.teamtripdraw.android.ui.filter.FilterSelectionActivity +import com.teamtripdraw.android.ui.filter.FilterSelectionActivity.Companion.SELECTED_OPTIONS_INTENT_KEY +import com.teamtripdraw.android.ui.filter.FilterType +import com.teamtripdraw.android.ui.filter.SelectedOptions import com.teamtripdraw.android.ui.history.detail.HistoryDetailActivity import com.teamtripdraw.android.ui.model.UiPreviewTrip import dagger.hilt.android.AndroidEntryPoint @@ -22,6 +30,17 @@ class AllTripsFragment : Fragment() { private lateinit var adapter: AllTripsAdapter private val viewModel: AllTripsViewModel by viewModels() + private val getFilterOptionsResult = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode != RESULT_OK) return@registerForActivityResult + val intent: Intent = result.data!! + val selectedOptions = + intent.getParcelableExtraCompat(SELECTED_OPTIONS_INTENT_KEY) + ?: throw java.lang.IllegalStateException() + viewModel.updateSelectedOptions(selectedOptions) + viewModel.fetchTrips() + } + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, @@ -34,6 +53,7 @@ class AllTripsFragment : Fragment() { initObserver() setAdapter() addScrollListener() + viewModel.fetchTrips() return binding.root } @@ -45,11 +65,14 @@ class AllTripsFragment : Fragment() { private fun initObserver() { initTripsObserve() initOpenPostDetailEventObserve() + initOpenFilterSelectionEventObserve() } private fun initTripsObserve() { viewModel.trips.observe(viewLifecycleOwner) { - adapter.submitList(it.tripItems) + adapter.submitList(it.tripItems) { + binding.rvAllTrips.smoothScrollToPosition(INITIAL_POSITION) + } } } @@ -63,21 +86,29 @@ class AllTripsFragment : Fragment() { startActivity(HistoryDetailActivity.getIntent(requireContext(), trip)) } - private fun setAdapter() { - adapter = AllTripsAdapter(viewModel) - binding.rvAllTrips.adapter = adapter + private fun initOpenFilterSelectionEventObserve() { + viewModel.openFilterSelectionEvent.observe( + viewLifecycleOwner, + this::onFilterSelectionClick, + ) } - override fun onResume() { - super.onResume() - fetchTrips() + private fun onFilterSelectionClick(isClicked: Boolean) { + if (isClicked) { + val intent = + FilterSelectionActivity.getIntent( + requireContext(), + FilterType.TRIP, + viewModel.selectedOptions, + ) + getFilterOptionsResult.launch(intent) + } } - private fun fetchTrips() = viewModel.fetchTrips() - - override fun onDestroy() { - super.onDestroy() - _binding = null + private fun setAdapter() { + adapter = AllTripsAdapter(viewModel) + binding.rvAllTrips.adapter = adapter + binding.rvAllTrips.itemAnimator = null } private fun addScrollListener() { @@ -101,8 +132,14 @@ class AllTripsFragment : Fragment() { private fun isLoadThreshold(layoutManager: LinearLayoutManager, lastPosition: Int): Boolean = layoutManager.itemCount <= lastPosition + LOAD_THRESHOLD + override fun onDestroy() { + super.onDestroy() + _binding = null + } + companion object { private const val LOAD_THRESHOLD = 3 private const val DOWNWARD_DIRECTION = 1 + private const val INITIAL_POSITION = 0 } } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt index a7d8a39f8..34c1c97a9 100644 --- a/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/allTrips/AllTripsViewModel.kt @@ -8,6 +8,7 @@ import androidx.lifecycle.viewModelScope import com.teamtripdraw.android.TripDrawApplication import com.teamtripdraw.android.domain.model.trip.TripOfAll import com.teamtripdraw.android.domain.repository.TripRepository +import com.teamtripdraw.android.ui.filter.SelectedOptions import com.teamtripdraw.android.ui.model.UiPreviewTrip import com.teamtripdraw.android.ui.model.allTrips.UiAllTripItem import com.teamtripdraw.android.ui.model.allTrips.UiAllTripLoadingItem @@ -26,6 +27,8 @@ class AllTripsViewModel @Inject constructor( private val _uiTripItems: MutableLiveData> = MutableLiveData(listOf()) val trips: LiveData = Transformations.map(_uiTripItems) { trip -> UiAllTrips(trip) } + var selectedOptions: SelectedOptions? = null + private val _openHistoryDetailEvent = MutableLiveData() val openHistoryDetailEvent: LiveData = _openHistoryDetailEvent @@ -37,37 +40,55 @@ class AllTripsViewModel @Inject constructor( var isAddLoading = false private set + private val _openFilterSelectionEvent = MutableLiveData() + val openFilterSelectionEvent: LiveData = _openFilterSelectionEvent + fun fetchTrips() { - if (_uiTripItems.value!!.isNotEmpty() && hasNextPage) { + reloadIfFiltered() + checkLoadOrNot() + fetchMoreTrips() + } + + private fun reloadIfFiltered() { + if (_openFilterSelectionEvent.value == true) lastId = null + } + + private fun checkLoadOrNot() { + if (lastId != null && hasNextPage) { isAddLoading = true addLoadingItem() } - fetchMoreTrips() + } + + private fun addLoadingItem() { + _uiTripItems.value = + requireNotNull(_uiTripItems.value).toMutableList().apply { add(UiAllTripLoadingItem) } } private fun fetchMoreTrips() { viewModelScope.launch { - tripRepository.getAllTrips(lastViewedId = lastId).onSuccess { trips -> + tripRepository.getAllTrips( + lastViewedId = lastId, + limit = PAGE_ITEM_SIZE, + address = selectedOptions?.address ?: "", + years = selectedOptions?.years ?: listOf(), + months = selectedOptions?.months ?: listOf(), + daysOfWeek = selectedOptions?.daysOfWeek ?: listOf(), + ageRanges = selectedOptions?.ageRanges ?: listOf(), + genders = selectedOptions?.genders ?: listOf(), + ).onSuccess { trips -> setLastItemId(trips) setHasNextPage(trips) - setAddedItems(trips) + + if (_openFilterSelectionEvent.value == true) { + getSearchResult(trips) + } else { + addItems(trips) + } }.onFailure { TripDrawApplication.logUtil.general.log(it) } } } - private fun setAddedItems(trips: List) { - _uiTripItems.value = _uiTripItems.value!!.toMutableList().apply { - remove(UiAllTripLoadingItem) - addAll(trips.map { it.toPresentation() }) - } - isAddLoading = false - } - - private fun addLoadingItem() { - _uiTripItems.value = - _uiTripItems.value!!.toMutableList().apply { add(UiAllTripLoadingItem) } - } - private fun setLastItemId(trips: List) { if (trips.isNotEmpty()) lastId = trips.last().tripId } @@ -76,6 +97,23 @@ class AllTripsViewModel @Inject constructor( if (trips.size < PAGE_ITEM_SIZE && lastId != null) hasNextPage = false } + private fun getSearchResult(trips: List) { + _uiTripItems.value = trips.map { it.toPresentation() } + _openFilterSelectionEvent.value = false + } + + private fun addItems(trips: List) { + _uiTripItems.value = requireNotNull(_uiTripItems.value).toMutableList().apply { + remove(UiAllTripLoadingItem) + addAll(trips.map { it.toPresentation() }) + } + isAddLoading = false + } + + fun updateSelectedOptions(options: SelectedOptions) { + selectedOptions = options + } + fun openHistoryDetail(trip: UiTripOfAll) { val previewTrip = UiPreviewTrip( id = trip.tripId, @@ -87,6 +125,10 @@ class AllTripsViewModel @Inject constructor( _openHistoryDetailEvent.value = previewTrip } + fun openFilterSelection() { + _openFilterSelectionEvent.value = true + } + companion object { private const val PAGE_ITEM_SIZE = 20 } diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/FilterSelectionBindingAdapter.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/FilterSelectionBindingAdapter.kt new file mode 100644 index 000000000..84547f558 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/common/bindingAdapter/FilterSelectionBindingAdapter.kt @@ -0,0 +1,53 @@ +package com.teamtripdraw.android.ui.common.bindingAdapter + +import android.view.View +import android.widget.TextView +import androidx.appcompat.widget.AppCompatButton +import androidx.core.content.ContextCompat +import androidx.databinding.BindingAdapter +import com.teamtripdraw.android.R +import com.teamtripdraw.android.domain.model.filterOption.FilterOption +import com.teamtripdraw.android.ui.filter.FilterOptionsView +import com.teamtripdraw.android.ui.filter.FilterType +import com.teamtripdraw.android.ui.model.UiAddressSelectionItem + +@BindingAdapter("app:setupFilterOptions", "app:setupSelectedOptions") +fun FilterOptionsView.setupFilterOption( + options: List>, + selectedOptions: List? = null, +) { + setOptions(options, selectedOptions) +} + +@BindingAdapter("app:setVisibilityIfTrip") +fun View.setVisibilityIfTrip(filterType: FilterType?) { + if (filterType == FilterType.TRIP) { + visibility = View.GONE + } +} + +@BindingAdapter("app:setAddressText") +fun AppCompatButton.setAddressText(address: String?) { + if (address == null) return + if (address.isEmpty()) { + this.text = INITIAL_ADDRESS_BTN_TEXT + } else { + this.text = address + } +} + +@BindingAdapter("app:setAddressSelectionItemBackground") +fun TextView.testSetColor(uiAddressSelectionItem: UiAddressSelectionItem) { + val colorResId: Int = + if (uiAddressSelectionItem.isSelected) { + R.color.td_light_blue + } else { + R.color.td_white + } + + setBackgroundColor( + ContextCompat.getColor(this.context, colorResId), + ) +} + +private const val INITIAL_ADDRESS_BTN_TEXT = "+" diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterOptionsView.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterOptionsView.kt new file mode 100644 index 000000000..4541be624 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterOptionsView.kt @@ -0,0 +1,105 @@ +package com.teamtripdraw.android.ui.filter + +import android.content.Context +import android.content.res.TypedArray +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.ViewGroup +import android.widget.LinearLayout +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import com.google.android.material.chip.Chip +import com.google.android.material.chip.ChipDrawable +import com.google.android.material.chip.ChipGroup +import com.teamtripdraw.android.R +import com.teamtripdraw.android.domain.model.filterOption.FilterOption +import com.teamtripdraw.android.ui.model.mapper.toText + +class FilterOptionsView @JvmOverloads constructor(context: Context, attr: AttributeSet? = null) : + ConstraintLayout(context, attr) { + + private val chips: MutableList = mutableListOf() + + private lateinit var titleView: TextView + private lateinit var chipGroup: ChipGroup + + init { + initView(context) + attr?.let { + val filterOptionsTitle = + context.obtainStyledAttributes(it, R.styleable.FilterOptionsView) + setTitleAppearance(filterOptionsTitle) + filterOptionsTitle.recycle() + } + } + + private fun initView(context: Context) { + val inflateService = Context.LAYOUT_INFLATER_SERVICE + val layoutInflater = context.getSystemService(inflateService) as LayoutInflater + layoutInflater.inflate(R.layout.view_filter_options, this, true) + titleView = findViewById(R.id.tv_filter_options_title) + chipGroup = findViewById(R.id.chip_group_filter_options) + } + + private fun setTitleAppearance(filterOptionsTitle: TypedArray) { + when ( + filterOptionsTitle.getInt( + R.styleable.FilterOptionsView_filterOptionsTitleAppearance, + 1, + ) + ) { + TEXT_APPEARANCE_TITLE -> titleView.setTextAppearance(R.style.subtitle_1) + TEXT_APPEARANCE_SUBTITLE -> titleView.setTextAppearance(R.style.body_1) + } + } + + fun setOptions(options: List>, selectedOptions: List?) { + options.forEach { option -> createOptionChip(option) } + if (selectedOptions != null) checkSelectedOptions(selectedOptions) + } + + private fun createOptionChip(option: FilterOption) { + val chip = Chip(context) + chip.id = option.id + chip.layoutParams = LinearLayout.LayoutParams( + ViewGroup.LayoutParams.WRAP_CONTENT, + ViewGroup.LayoutParams.WRAP_CONTENT, + ) + settingChipStyle(chip) + chip.isCheckable = true + chip.text = option.toText() + chips.add(chip) + chipGroup.addView(chip) + } + + private fun settingChipStyle(chip: Chip) { + chip.setChipDrawable( + ChipDrawable.createFromAttributes( + context, + null, + 0, + R.style.filterChip, + ), + ) + chip.setTextAppearance(R.style.chipTextAppearance) + } + + private fun checkSelectedOptions(selectedOptions: List) { + chips.forEach { + if (selectedOptions.contains(it.id)) it.isChecked = true + } + } + + fun setTitle(title: String) { + titleView.text = title + } + + fun getCheckedChipIds(): List = chipGroup.checkedChipIds + + fun clearCheck() = chipGroup.clearCheck() + + companion object { + private const val TEXT_APPEARANCE_TITLE = 1 + private const val TEXT_APPEARANCE_SUBTITLE = 2 + } +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterSelectionActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterSelectionActivity.kt new file mode 100644 index 000000000..562f5fab6 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterSelectionActivity.kt @@ -0,0 +1,170 @@ +package com.teamtripdraw.android.ui.filter + +import android.app.Activity +import android.content.Context +import android.content.Intent +import android.os.Bundle +import android.os.Parcelable +import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import androidx.databinding.DataBindingUtil +import com.teamtripdraw.android.R +import com.teamtripdraw.android.databinding.ActivityFilterSelectionBinding +import com.teamtripdraw.android.domain.model.filterOption.OptionAgeRange +import com.teamtripdraw.android.domain.model.filterOption.OptionDayOfWeek +import com.teamtripdraw.android.domain.model.filterOption.OptionGender +import com.teamtripdraw.android.domain.model.filterOption.OptionHour +import com.teamtripdraw.android.domain.model.filterOption.OptionMonth +import com.teamtripdraw.android.domain.model.filterOption.OptionYear +import com.teamtripdraw.android.support.framework.presentation.event.EventObserver +import com.teamtripdraw.android.support.framework.presentation.getParcelableExtraCompat +import com.teamtripdraw.android.ui.filter.address.AddressSelectionActivity +import dagger.hilt.android.AndroidEntryPoint +import kotlin.reflect.typeOf + +@AndroidEntryPoint +class FilterSelectionActivity : AppCompatActivity() { + + lateinit var binding: ActivityFilterSelectionBinding + private val viewModel: FilterSelectionViewModel by viewModels() + private lateinit var filterViews: List + private val getSelectedAddress = + registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> + if (result.resultCode != RESULT_OK) return@registerForActivityResult + val intent: Intent = result.data!! + val address = intent.getStringExtra(AddressSelectionActivity.INTENT_KEY_ADDRESS) ?: "" + viewModel.setAddress(address) + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = DataBindingUtil.setContentView(this, R.layout.activity_filter_selection) + bindViewModel() + + viewModel.setupFilterType(initFilterType()) + setupFilterViews() + initViewBySelectedOptions() + initObserver() + } + + private fun bindViewModel() { + binding.lifecycleOwner = this + binding.filterSelectionViewModel = viewModel + } + + private fun initFilterType(): FilterType = + intent.getParcelableExtraCompat(FILTER_TYPE_ID) ?: throw IllegalStateException() + + private fun initViewBySelectedOptions() { + val selectedOptions = + intent.getParcelableExtraCompat(SELECTED_OPTIONS_HISTORY_KEY) ?: return + viewModel.setSelectedOption(selectedOptions) + viewModel.setAddress(selectedOptions.address) + } + + private fun setupFilterViews() { + filterViews = listOf( + FilterView(typeOf(), binding.filterOptionsYear), + FilterView(typeOf(), binding.filterOptionsMonth), + FilterView(typeOf(), binding.filterOptionsDayOfWeek), + FilterView(typeOf(), binding.filterOptionsAgeRange), + FilterView(typeOf(), binding.filterOptionsGender), + ) + } + + private fun initObserver() { + initOpenAddressSelectionEventObserve() + initOpenSearchResultEventObserve() + initRefreshEventObserve() + initBackPageObserve() + } + + private fun initOpenAddressSelectionEventObserve() { + viewModel.openAddressSelectionEvent.observe( + this, + this::onAddressSelectionClick, + ) + } + + private fun onAddressSelectionClick(isClicked: Boolean) { + if (isClicked) { + val intent = Intent(this, AddressSelectionActivity::class.java) + getSelectedAddress.launch(intent) + } + } + + private fun initOpenSearchResultEventObserve() { + viewModel.openSearchResultEvent.observe( + this, + this::onSearchClick, + ) + } + + private fun onSearchClick(isClicked: Boolean) { + if (isClicked) { + val resultIntent = Intent() + resultIntent.putExtra(SELECTED_OPTIONS_INTENT_KEY, getSelectedOptions()) + setResult(Activity.RESULT_OK, resultIntent) + finish() + } + } + + private fun initRefreshEventObserve() { + viewModel.refreshEvent.observe( + this, + this::onRefreshClick, + ) + } + + private fun onRefreshClick(isClicked: Boolean) { + if (isClicked) { + viewModel.setAddress() + filterViews.forEach { it.view.clearCheck() } + } + } + + private fun getSelectedOptions(): SelectedOptions { + val selectedOptions = SelectedOptionsBuilder() + filterViews.forEach { + selectedOptions.setSelectedOptions(it, it.view.getCheckedChipIds()) + } + selectedOptions.setAddress(viewModel.address.value ?: "").setHours(getHour()) + return selectedOptions.build() + } + + private fun getHour(): List? = + if (viewModel.filterType.value == FilterType.POST) { + OptionHour.getSelectedHourIds( + fromValue = binding.filterOptionsHourFrom.value, + toValue = binding.filterOptionsHourTo.value, + ) + } else { + null + } + + private fun initBackPageObserve() { + viewModel.backPageEvent.observe( + this, + EventObserver { if (it) finish() }, + ) + } + + companion object { + private const val FILTER_TYPE_ID = "FILTER_TYPE_ID" + private const val SELECTED_OPTIONS_HISTORY_KEY = "SELECTED_OPTIONS_HISTORY_KEY" + const val SELECTED_OPTIONS_INTENT_KEY = "SELECTED_OPTIONS_INTENT_KEY" + + fun getIntent( + context: Context, + type: FilterType, + selectedOptions: SelectedOptions?, + ): Intent { + val intent = Intent(context, FilterSelectionActivity::class.java) + intent.putExtra(FILTER_TYPE_ID, type as Parcelable) + intent.putExtra(SELECTED_OPTIONS_HISTORY_KEY, selectedOptions) + return intent + } + } +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterSelectionViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterSelectionViewModel.kt new file mode 100644 index 000000000..ced1bfe4d --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterSelectionViewModel.kt @@ -0,0 +1,84 @@ +package com.teamtripdraw.android.ui.filter + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.teamtripdraw.android.domain.model.filterOption.OptionAgeRange +import com.teamtripdraw.android.domain.model.filterOption.OptionDayOfWeek +import com.teamtripdraw.android.domain.model.filterOption.OptionGender +import com.teamtripdraw.android.domain.model.filterOption.OptionHour +import com.teamtripdraw.android.domain.model.filterOption.OptionMonth +import com.teamtripdraw.android.domain.model.filterOption.OptionYear +import com.teamtripdraw.android.support.framework.presentation.event.Event +import dagger.hilt.android.lifecycle.HiltViewModel +import javax.inject.Inject + +@HiltViewModel +class FilterSelectionViewModel @Inject constructor() : ViewModel() { + + private val _filterType = MutableLiveData() + val filterType: LiveData = _filterType + + val years = OptionYear.values().toList() + val months = OptionMonth.values().toList() + val dayOfWeek = OptionDayOfWeek.values().toList() + val minHour = OptionHour.minHour + val maxHour = OptionHour.maxHour + val ageRange = OptionAgeRange.values().toList() + val gender = OptionGender.values().toList() + + private val _selectedOption = MutableLiveData() + val selectedOption: LiveData = _selectedOption + + private val _selectedHourFrom = MutableLiveData(OptionHour.minHour.value) + val selectedHourFrom: LiveData = _selectedHourFrom + private val _selectedHourTo = MutableLiveData(OptionHour.maxHour.value) + val selectedHourTo: LiveData = _selectedHourTo + + private val _address = MutableLiveData("") + val address: LiveData = _address + + private val _openAddressSelectionEvent = MutableLiveData() + val openAddressSelectionEvent: LiveData = _openAddressSelectionEvent + + private val _openSearchResultEvent = MutableLiveData() + val openSearchResultEvent: LiveData = _openSearchResultEvent + + private val _refreshEvent = MutableLiveData() + val refreshEvent: LiveData = _refreshEvent + + private val _backPageEvent: MutableLiveData> = MutableLiveData(Event(false)) + val backPageEvent: LiveData> = _backPageEvent + + fun setupFilterType(type: FilterType) { + _filterType.value = type + } + + fun setSelectedOption(options: SelectedOptions) { + _selectedOption.value = options + _selectedHourFrom.value = options.hours?.first() + _selectedHourTo.value = options.hours?.last() + } + + fun setAddress(address: String = "") { + _address.value = address + } + + fun openAddressSelection() { + _openAddressSelectionEvent.value = true + } + + fun openSearchResult() { + _openSearchResultEvent.value = true + } + + fun refresh() { + _refreshEvent.value = true + _selectedHourFrom.value = OptionHour.minHour.value + _selectedHourTo.value = OptionHour.maxHour.value + } + + fun backPage() { + _backPageEvent.value = Event(true) + } +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterType.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterType.kt new file mode 100644 index 000000000..585037e95 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterType.kt @@ -0,0 +1,9 @@ +package com.teamtripdraw.android.ui.filter + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize + +@Parcelize +enum class FilterType : Parcelable { + TRIP, POST +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterView.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterView.kt new file mode 100644 index 000000000..51be3605e --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/FilterView.kt @@ -0,0 +1,5 @@ +package com.teamtripdraw.android.ui.filter + +import kotlin.reflect.KType + +data class FilterView(val type: KType, val view: FilterOptionsView) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/filter/SelectedOptions.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/SelectedOptions.kt new file mode 100644 index 000000000..2089f0ca3 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/SelectedOptions.kt @@ -0,0 +1,57 @@ +package com.teamtripdraw.android.ui.filter + +import android.os.Parcelable +import com.teamtripdraw.android.domain.model.filterOption.OptionAgeRange +import com.teamtripdraw.android.domain.model.filterOption.OptionDayOfWeek +import com.teamtripdraw.android.domain.model.filterOption.OptionGender +import com.teamtripdraw.android.domain.model.filterOption.OptionMonth +import com.teamtripdraw.android.domain.model.filterOption.OptionYear +import kotlinx.parcelize.Parcelize +import kotlin.reflect.typeOf + +@Parcelize +data class SelectedOptions( + val years: List, + val months: List, + val daysOfWeek: List, + val ageRanges: List, + val genders: List, + val address: String, + val hours: List?, +) : Parcelable + +class SelectedOptionsBuilder { + private val years = mutableListOf() + private val months = mutableListOf() + private val daysOfWeek = mutableListOf() + private val ageRanges = mutableListOf() + private val genders = mutableListOf() + private var address = "" + private var hours: List? = null + + fun build(): SelectedOptions = + SelectedOptions(years, months, daysOfWeek, ageRanges, genders, address, hours) + + fun setSelectedOptions( + type: FilterView, + options: List, + ) { + when (type.type) { + typeOf() -> years.addAll(options) + typeOf() -> months.addAll(options) + typeOf() -> daysOfWeek.addAll(options) + typeOf() -> ageRanges.addAll(options) + typeOf() -> genders.addAll(options) + } + } + + fun setAddress(address: String): SelectedOptionsBuilder { + this.address = address + return this + } + + fun setHours(hour: List?): SelectedOptionsBuilder { + hours = hour + return this + } +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionActivity.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionActivity.kt new file mode 100644 index 000000000..6617e299d --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionActivity.kt @@ -0,0 +1,77 @@ +package com.teamtripdraw.android.ui.filter.address + +import android.app.Activity +import android.content.Intent +import android.os.Bundle +import androidx.activity.viewModels +import androidx.appcompat.app.AppCompatActivity +import androidx.databinding.DataBindingUtil +import com.teamtripdraw.android.R +import com.teamtripdraw.android.databinding.ActivityAddressSelectionBinding +import dagger.hilt.android.AndroidEntryPoint + +@AndroidEntryPoint +class AddressSelectionActivity : AppCompatActivity() { + + private lateinit var binding: ActivityAddressSelectionBinding + private val viewModel: AddressSelectionViewModel by viewModels() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + binding = DataBindingUtil.setContentView(this, R.layout.activity_address_selection) + binding.lifecycleOwner = this + binding.addressSelectionViewModel = viewModel + + initSiDoListView() + initSiGunGuListView() + initEupMyeonDongListView() + initSelectedCompleteView() + } + + private fun initSiDoListView() { + val siDoAdapter = AddressSelectionAdapter { viewModel.selectSiDo(it) } + binding.rvAddressSelectionSiDo.adapter = siDoAdapter + binding.rvAddressSelectionSiDo.itemAnimator = null + + viewModel.siDos.observe(this) { siDos -> + siDoAdapter.submitList(siDos.toList()) + } + } + + private fun initSiGunGuListView() { + val siGunGuAdapter = AddressSelectionAdapter { viewModel.selectSiGunGu(it) } + binding.rvAddressSelectionSiGunGu.adapter = siGunGuAdapter + binding.rvAddressSelectionSiGunGu.itemAnimator = null + + viewModel.siGunGus.observe(this) { siGunGus -> + siGunGuAdapter.submitList(siGunGus) + } + } + + private fun initEupMyeonDongListView() { + val eupMyeonDongAdapter = AddressSelectionAdapter { viewModel.selectEupMyeonDong(it) } + binding.rvAddressSelectionEupMyeonDong.adapter = eupMyeonDongAdapter + binding.rvAddressSelectionEupMyeonDong.itemAnimator = null + + viewModel.eupMyeonDongs.observe(this) { eupMyeonDongs -> + eupMyeonDongAdapter.submitList(eupMyeonDongs) + } + } + + private fun initSelectedCompleteView() { + viewModel.selectingCompletedEvent.observe(this) { + if (it.content) returnBeforeActivity() + } + } + + private fun returnBeforeActivity() { + val resultIntent = Intent() + resultIntent.putExtra(INTENT_KEY_ADDRESS, viewModel.address) + setResult(Activity.RESULT_OK, resultIntent) + finish() + } + + companion object { + const val INTENT_KEY_ADDRESS = "INTENT_KEY_ADDRESS" + } +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionAdapter.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionAdapter.kt new file mode 100644 index 000000000..8cf779cf9 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionAdapter.kt @@ -0,0 +1,37 @@ +package com.teamtripdraw.android.ui.filter.address + +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.ListAdapter +import com.teamtripdraw.android.ui.model.UiAddressSelectionItem + +class AddressSelectionAdapter( + private val selectEvent: (address: UiAddressSelectionItem) -> Unit, +) : ListAdapter(diffUtil) { + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): AddressSelectionViewHolder { + return AddressSelectionViewHolder.of(parent, selectEvent) + } + + override fun onBindViewHolder(holder: AddressSelectionViewHolder, position: Int) { + holder.bind(getItem(position)) + } + + companion object { + val diffUtil = object : DiffUtil.ItemCallback() { + + override fun areItemsTheSame( + oldItem: UiAddressSelectionItem, + newItem: UiAddressSelectionItem, + ): Boolean = + oldItem == newItem + + override fun areContentsTheSame( + oldItem: UiAddressSelectionItem, + newItem: UiAddressSelectionItem, + ): Boolean = + oldItem.isSelected == newItem.isSelected && + oldItem.addressName == newItem.addressName + } + } +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionViewHolder.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionViewHolder.kt new file mode 100644 index 000000000..31d79a496 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionViewHolder.kt @@ -0,0 +1,36 @@ +package com.teamtripdraw.android.ui.filter.address + +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.RecyclerView +import com.teamtripdraw.android.databinding.ItemFilterOptionAddressBinding +import com.teamtripdraw.android.ui.model.UiAddressSelectionItem + +class AddressSelectionViewHolder( + val binding: ItemFilterOptionAddressBinding, + selectEvent: (addressName: UiAddressSelectionItem) -> Unit, +) : RecyclerView.ViewHolder(binding.root) { + + init { + binding.selectEvent = selectEvent + } + + fun bind(address: UiAddressSelectionItem) { + binding.addressItem = address + binding.tvFilterOptionAddressName.text = address.addressName + } + + companion object { + fun of( + parent: ViewGroup, + selectEvent: (addressName: UiAddressSelectionItem) -> Unit, + ): AddressSelectionViewHolder { + val binding = ItemFilterOptionAddressBinding.inflate( + LayoutInflater.from(parent.context), + parent, + false, + ) + return AddressSelectionViewHolder(binding, selectEvent) + } + } +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionViewModel.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionViewModel.kt new file mode 100644 index 000000000..80b9d3379 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/filter/address/AddressSelectionViewModel.kt @@ -0,0 +1,125 @@ +package com.teamtripdraw.android.ui.filter.address + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.teamtripdraw.android.TripDrawApplication +import com.teamtripdraw.android.domain.repository.AddressRepository +import com.teamtripdraw.android.support.framework.presentation.event.Event +import com.teamtripdraw.android.ui.model.UiAddressSelectionItem +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class AddressSelectionViewModel @Inject constructor( + private val addressRepository: AddressRepository, +) : ViewModel() { + + private val selectedSiDo: MutableLiveData = MutableLiveData("") + val selectedSiGunGu: MutableLiveData = MutableLiveData("") + private val selectedEupMyeonDong: MutableLiveData = MutableLiveData("") + val address: String get() = "${selectedSiDo.value} ${selectedSiGunGu.value} ${selectedEupMyeonDong.value}" + + private val _siDos: MutableLiveData> = MutableLiveData(listOf()) + val siDos: LiveData> = _siDos + + private val _siGunGus: MutableLiveData> = MutableLiveData(listOf()) + val siGunGus: LiveData> = _siGunGus + + private val _eupMyeonDongs: MutableLiveData> = + MutableLiveData(listOf()) + val eupMyeonDongs: LiveData> = _eupMyeonDongs + + private val _selectingCompletedEvent: MutableLiveData> = + MutableLiveData(Event(false)) + val selectingCompletedEvent: LiveData> = _selectingCompletedEvent + + init { + fetchSiDos() + } + + fun selectSiDo(selectedSiDoItem: UiAddressSelectionItem) { + _siDos.value?.let { siDoItems -> + _siDos.value = siDoItems.toMutableList().map { item -> + val isSelected = item.addressName == selectedSiDoItem.addressName + UiAddressSelectionItem(item.addressName, isSelected) + } + } + + this.selectedSiDo.value = selectedSiDoItem.addressName + selectedSiGunGu.value = "" + selectedEupMyeonDong.value = "" + + _siGunGus.value = listOf() + _eupMyeonDongs.value = listOf() + + fetchSiGunGu() + } + + fun selectSiGunGu(selectedSiGunGuItem: UiAddressSelectionItem) { + _siGunGus.value?.let { siGunGuItems -> + _siGunGus.value = siGunGuItems.toMutableList().map { item -> + val isSelected = item.addressName == selectedSiGunGuItem.addressName + UiAddressSelectionItem(item.addressName, isSelected) + } + } + + selectedSiGunGu.value = selectedSiGunGuItem.addressName + selectedEupMyeonDong.value = "" + + _eupMyeonDongs.value = listOf() + + fetchEupMyeonDong() + } + + fun selectEupMyeonDong(selectedEupMyeonDongItem: UiAddressSelectionItem) { + _eupMyeonDongs.value?.let { eupMyeonDongs -> + _eupMyeonDongs.value = eupMyeonDongs.toMutableList().map { item -> + val isSelected = item.addressName == selectedEupMyeonDongItem.addressName + UiAddressSelectionItem(item.addressName, isSelected) + } + } + + selectedEupMyeonDong.value = selectedEupMyeonDongItem.addressName + } + + private fun fetchSiDos() { + viewModelScope.launch { + addressRepository.getSiDos() + .onSuccess { getSiDos -> + _siDos.value = getSiDos.map { UiAddressSelectionItem(it) } + }.onFailure { TripDrawApplication.logUtil.general.log(it) } + } + } + + private fun fetchSiGunGu() { + viewModelScope.launch { + addressRepository.getSiGunGus(selectedSiDo.value!!) + .onSuccess { getGunGus -> + _siGunGus.value = getGunGus.map { UiAddressSelectionItem(it) } + }.onFailure { TripDrawApplication.logUtil.general.log(it) } + } + } + + private fun fetchEupMyeonDong() { + viewModelScope.launch { + addressRepository.getEupMyeonDongs(selectedSiDo.value!!, selectedSiGunGu.value!!) + .onSuccess { getEupMyeonDongs -> + _eupMyeonDongs.value = getEupMyeonDongs.map { UiAddressSelectionItem(it) } + }.onFailure { TripDrawApplication.logUtil.general.log(it) } + } + } + + fun completeSelecting() { + if (selectedEupMyeonDong.value!!.isEmpty() || + selectedSiGunGu.value!!.isEmpty() || + selectedSiDo.value!!.isEmpty() + ) { + return + } + + _selectingCompletedEvent.value = Event(true) + } +} diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiAddressSelectionItem.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiAddressSelectionItem.kt new file mode 100644 index 000000000..7c21b2ce0 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/UiAddressSelectionItem.kt @@ -0,0 +1,6 @@ +package com.teamtripdraw.android.ui.model + +data class UiAddressSelectionItem( + val addressName: String, + var isSelected: Boolean = false, +) diff --git a/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/FilterOptionUiMapper.kt b/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/FilterOptionUiMapper.kt new file mode 100644 index 000000000..181ee0e86 --- /dev/null +++ b/android/app/src/main/java/com/teamtripdraw/android/ui/model/mapper/FilterOptionUiMapper.kt @@ -0,0 +1,70 @@ +package com.teamtripdraw.android.ui.model.mapper + +import com.teamtripdraw.android.domain.model.filterOption.FilterOption +import com.teamtripdraw.android.domain.model.filterOption.OptionAgeRange +import com.teamtripdraw.android.domain.model.filterOption.OptionDayOfWeek +import com.teamtripdraw.android.domain.model.filterOption.OptionGender +import com.teamtripdraw.android.domain.model.filterOption.OptionHour +import com.teamtripdraw.android.domain.model.filterOption.OptionMonth +import com.teamtripdraw.android.domain.model.filterOption.OptionYear + +fun FilterOption.toText(): String { + return when (this) { + is OptionYear -> this.toText() + is OptionMonth -> this.toText() + is OptionDayOfWeek -> this.toText() + is OptionHour -> this.value.toString() + is OptionAgeRange -> this.toText() + is OptionGender -> this.toText() + } +} + +private fun OptionYear.toText(): String = this.value.toString() + +private fun OptionMonth.toText(): String = + when (this) { + OptionMonth.JANUARY -> "1월" + OptionMonth.FEBRUARY -> "2월" + OptionMonth.MARCH -> "3월" + OptionMonth.APRIL -> "4월" + OptionMonth.MAY -> "5월" + OptionMonth.JUNE -> "6월" + OptionMonth.JULY -> "7월" + OptionMonth.AUGUST -> "8월" + OptionMonth.SEPTEMBER -> "9월" + OptionMonth.OCTOBER -> "10월" + OptionMonth.NOVEMBER -> "11월" + OptionMonth.DECEMBER -> "12월" + } + +private fun OptionDayOfWeek.toText(): String = + when (this) { + OptionDayOfWeek.SUNDAY -> "일" + OptionDayOfWeek.MONDAY -> "월" + OptionDayOfWeek.TUESDAY -> "화" + OptionDayOfWeek.WEDNESDAY -> "수" + OptionDayOfWeek.THURSDAY -> "목" + OptionDayOfWeek.FRIDAY -> "금" + OptionDayOfWeek.SATURDAY -> "토" + } + +private fun OptionAgeRange.toText(): String = + when (this) { + OptionAgeRange.AGE_1_TO_9 -> "1~9세" + OptionAgeRange.AGE_10_TO_14 -> "10~14세" + OptionAgeRange.AGE_15_TO_19 -> "15~19세" + OptionAgeRange.AGE_20_TO_29 -> "20~29세" + OptionAgeRange.AGE_30_TO_39 -> "30~39세" + OptionAgeRange.AGE_40_TO_49 -> "40~49세" + OptionAgeRange.AGE_50_TO_59 -> "50~59세" + OptionAgeRange.AGE_60_TO_69 -> "60~69세" + OptionAgeRange.AGE_70_TO_79 -> "70~79세" + OptionAgeRange.AGE_80_TO_89 -> "80~89세" + OptionAgeRange.AGE_OVER_90 -> "90세~" + } + +private fun OptionGender.toText(): String = + when (this) { + OptionGender.FEMALE -> "여성" + OptionGender.MALE -> "남성" + } diff --git a/android/app/src/main/res/color/selector_filter_chip_bg_state.xml b/android/app/src/main/res/color/selector_filter_chip_bg_state.xml new file mode 100644 index 000000000..b0e19ca6c --- /dev/null +++ b/android/app/src/main/res/color/selector_filter_chip_bg_state.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android/app/src/main/res/color/selector_filter_text_state.xml b/android/app/src/main/res/color/selector_filter_text_state.xml new file mode 100644 index 000000000..5d9fe35a9 --- /dev/null +++ b/android/app/src/main/res/color/selector_filter_text_state.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android/app/src/main/res/drawable/ic_refresh.xml b/android/app/src/main/res/drawable/ic_refresh.xml new file mode 100644 index 000000000..6112847b2 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_refresh.xml @@ -0,0 +1,9 @@ + + + diff --git a/android/app/src/main/res/drawable/shape_td_light_blue_fill_0_rect.xml b/android/app/src/main/res/drawable/shape_td_light_blue_fill_0_rect.xml new file mode 100644 index 000000000..b1dd44e5b --- /dev/null +++ b/android/app/src/main/res/drawable/shape_td_light_blue_fill_0_rect.xml @@ -0,0 +1,5 @@ + + + + diff --git a/android/app/src/main/res/drawable/shape_td_main_blue_fill_12_rect.xml b/android/app/src/main/res/drawable/shape_td_main_blue_fill_12_rect.xml new file mode 100644 index 000000000..22bac316d --- /dev/null +++ b/android/app/src/main/res/drawable/shape_td_main_blue_fill_12_rect.xml @@ -0,0 +1,6 @@ + + + + + diff --git a/android/app/src/main/res/layout/activity_address_selection.xml b/android/app/src/main/res/layout/activity_address_selection.xml new file mode 100644 index 000000000..dbab1d400 --- /dev/null +++ b/android/app/src/main/res/layout/activity_address_selection.xml @@ -0,0 +1,135 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/layout/activity_filter_selection.xml b/android/app/src/main/res/layout/activity_filter_selection.xml new file mode 100644 index 000000000..c5c5b2364 --- /dev/null +++ b/android/app/src/main/res/layout/activity_filter_selection.xml @@ -0,0 +1,336 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/layout/fragment_all_posts.xml b/android/app/src/main/res/layout/fragment_all_posts.xml index d6d24e455..ccf884f5a 100644 --- a/android/app/src/main/res/layout/fragment_all_posts.xml +++ b/android/app/src/main/res/layout/fragment_all_posts.xml @@ -36,6 +36,7 @@ android:layout_height="24dp" android:layout_gravity="end" android:layout_marginEnd="@dimen/margin_default" + android:onClick="@{()->allPostsViewModel.openFilterSelection()}" android:src="@drawable/ic_search" /> @@ -53,7 +54,7 @@ app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/tb_all_posts" - app:setNoItemsMessageVisibility="@{allPostsViewModel.posts.empty}" /> + app:setNoItemsMessageVisibility="@{allPostsViewModel.posts.isEmpty}" /> diff --git a/android/app/src/main/res/layout/item_filter_option_address.xml b/android/app/src/main/res/layout/item_filter_option_address.xml new file mode 100644 index 000000000..141deafd1 --- /dev/null +++ b/android/app/src/main/res/layout/item_filter_option_address.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/android/app/src/main/res/layout/view_filter_options.xml b/android/app/src/main/res/layout/view_filter_options.xml new file mode 100644 index 000000000..33a9ed2f5 --- /dev/null +++ b/android/app/src/main/res/layout/view_filter_options.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/values/attrs.xml b/android/app/src/main/res/values/attrs.xml new file mode 100644 index 000000000..ee0b16b7d --- /dev/null +++ b/android/app/src/main/res/values/attrs.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/android/app/src/main/res/values/strings.xml b/android/app/src/main/res/values/strings.xml index 596793579..2d827a9dd 100644 --- a/android/app/src/main/res/values/strings.xml +++ b/android/app/src/main/res/values/strings.xml @@ -104,4 +104,28 @@ 검색된 감상이 없습니다. + + + 연도 + + 요일 + 나이대 + 성별 + 검색어를 입력해주세요 + 지역 검색 + 현재 위치 + 날짜 + 시간대 + : 00 + ~ + : 59 + 초기화 + 검색 + + + 시 / 도 + 시 / 군 / 구 + 읍 / 면 / 동 + 선택 완료 + diff --git a/android/app/src/main/res/values/themes.xml b/android/app/src/main/res/values/themes.xml index 8a03d1d29..3a16a1ee3 100644 --- a/android/app/src/main/res/values/themes.xml +++ b/android/app/src/main/res/values/themes.xml @@ -22,6 +22,19 @@ @style/Theme.TripDraw + + + + +