From 0098c2093ba843bc026729eb887f2148fbcd7ef5 Mon Sep 17 00:00:00 2001 From: hoyahozz <85336456+hoyahozz@users.noreply.github.com> Date: Sun, 21 Apr 2024 22:30:37 +0900 Subject: [PATCH 1/4] =?UTF-8?q?feat=20:=20=EA=B6=8C=ED=95=9C=20=EB=8B=A4?= =?UTF-8?q?=EC=9D=B4=EC=96=BC=EB=A1=9C=EA=B7=B8=20=EB=82=B4=20=EC=B7=A8?= =?UTF-8?q?=EC=86=8C=20=EB=A6=AC=EC=8A=A4=EB=84=88=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/view/setting/PermissionDialog.kt | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/PermissionDialog.kt b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/PermissionDialog.kt index dc0dc142..d3b07322 100644 --- a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/PermissionDialog.kt +++ b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/PermissionDialog.kt @@ -12,11 +12,20 @@ import android.view.ViewGroup import androidx.fragment.app.DialogFragment import com.dongyang.android.youdongknowme.databinding.DialogPermissionBinding -class PermissionDialog(val title: String, val content: String, val pacakageName: String) : DialogFragment() { +class PermissionDialog( + val title: String, + val content: String, + val pacakageName: String, + val cancelListener: (() -> Unit)? = null, +) : DialogFragment() { private var _binding: DialogPermissionBinding? = null private val binding get() = _binding!! - override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle?, + ): View { _binding = DialogPermissionBinding.inflate(inflater, container, false) val view = binding.root @@ -29,8 +38,10 @@ class PermissionDialog(val title: String, val content: String, val pacakageName: // 취소 버튼 binding.customTvBtn1.setOnClickListener { + cancelListener?.invoke() dismiss() } + // 확인 버튼 binding.customTvBtn2.setOnClickListener { val intent = @@ -46,4 +57,4 @@ class PermissionDialog(val title: String, val content: String, val pacakageName: super.onDestroyView() _binding = null } -} \ No newline at end of file +} From 67a6dd819b91ecce00b49a92d300c9d8a2920052 Mon Sep 17 00:00:00 2001 From: hoyahozz <85336456+hoyahozz@users.noreply.github.com> Date: Sun, 21 Apr 2024 22:31:12 +0900 Subject: [PATCH 2/4] =?UTF-8?q?fix=20:=20=EC=84=A4=EC=A0=95=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EB=82=B4=20=EC=8A=A4=EC=9C=84=EC=B9=98=20UI=20?= =?UTF-8?q?=EC=83=81=ED=83=9C=EC=99=80=20=EC=8B=A4=EC=A0=9C=20=EB=8D=B0?= =?UTF-8?q?=EC=9D=B4=ED=84=B0=20=EC=83=81=ED=83=9C=EA=B0=80=20=EC=9D=BC?= =?UTF-8?q?=EC=B9=98=ED=95=98=EC=A7=80=20=EC=95=8A=EB=8D=98=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/view/main/MainActivity.kt | 6 +- .../ui/view/setting/SettingFragment.kt | 155 +++++++++--------- .../ui/view/setting/SettingViewModel.kt | 86 ++++++---- app/src/main/res/layout/fragment_setting.xml | 28 +++- 4 files changed, 155 insertions(+), 120 deletions(-) diff --git a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/main/MainActivity.kt b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/main/MainActivity.kt index a25da2a4..b7c9a821 100644 --- a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/main/MainActivity.kt +++ b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/main/MainActivity.kt @@ -12,7 +12,6 @@ import com.dongyang.android.youdongknowme.standard.base.BaseActivity import com.dongyang.android.youdongknowme.ui.view.util.KeepStateNavigator import com.google.firebase.messaging.FirebaseMessaging import org.koin.androidx.viewmodel.ext.android.viewModel -import timber.log.Timber /* 메인 액티비티 */ class MainActivity : BaseActivity() { @@ -50,14 +49,11 @@ class MainActivity : BaseActivity() { FirebaseMessaging.getInstance().token.addOnCompleteListener { task -> if (task.isSuccessful) { viewModel.setFCMToken(task.result).run { viewModel.setInitToken() } - Timber.d("first ${task.result}") } else { return@addOnCompleteListener } val token = task.result SharedPreference.setFcmToken(token) - - Timber.d("token : ${token}") } } @@ -66,4 +62,4 @@ class MainActivity : BaseActivity() { return Intent(context, MainActivity::class.java) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/SettingFragment.kt b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/SettingFragment.kt index db6cc300..06512fd8 100644 --- a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/SettingFragment.kt +++ b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/SettingFragment.kt @@ -1,17 +1,11 @@ package com.dongyang.android.youdongknowme.ui.view.setting -import android.app.Activity import android.Manifest import android.content.Intent import android.content.pm.PackageManager -import android.content.res.ColorStateList import android.net.Uri -import androidx.activity.result.ActivityResultLauncher -import androidx.activity.result.contract.ActivityResultContracts import android.os.Build -import android.view.View -import android.widget.Switch -import androidx.appcompat.widget.SwitchCompat +import androidx.activity.result.contract.ActivityResultContracts.StartActivityForResult import androidx.core.content.ContextCompat import com.dongyang.android.youdongknowme.R import com.dongyang.android.youdongknowme.databinding.FragmentSettingBinding @@ -27,29 +21,21 @@ class SettingFragment : BaseFragment() override val layoutResourceId: Int = R.layout.fragment_setting override val viewModel: SettingViewModel by viewModel() - private lateinit var resultLauncherKeyword: ActivityResultLauncher - private lateinit var resultResultDepartment: ActivityResultLauncher - - private var topics: List = emptyList() - private var department: String = "" + private val departmentActivityResultLauncher = + registerForActivityResult(StartActivityForResult()) { _ -> + // 학과 선택 화면 이동 후 재진입 시 학과 재조회 처리 + viewModel.getUserDepartment() + } override fun initStartView() { binding.tvSettingAppVersion.text = getAppVersion() - setResultKeyword() - setResultDepartment() + initAlarmSwitchStateByNotificationPermission() } override fun initDataBinding() { viewModel.myDepartment.observe(viewLifecycleOwner) { myDepartment -> binding.tvSettingDepartment.text = myDepartment - department = myDepartment - viewModel.updateUserDepartment(department) - } - - viewModel.myTopics.observe(viewLifecycleOwner) { myTopics -> - topics = myTopics - viewModel.updateUserTopic(topics) } viewModel.isAccessUniversityAlarm.observe(viewLifecycleOwner) { isChecked -> @@ -59,44 +45,60 @@ class SettingFragment : BaseFragment() viewModel.isAccessDepartAlarm.observe(viewLifecycleOwner) { isChecked -> binding.switchSettingDepartmentAlarm.isChecked = isChecked } + + viewModel.isLoading.observe(viewLifecycleOwner) { isLoading -> + if (isLoading) + showLoading() + else + dismissLoading() + } } override fun initAfterBinding() { + /** TODO 스위치 클릭을 억제하기 위한 임시 뷰, 후에 삭제 필요 */ + binding.viewSettingUniversityAlarm.setOnClickListener { + if (viewModel.isAccessUniversityAlarm.value == false) { + if (checkNotificationPermission().not()) { + showPermissionDialog() + return@setOnClickListener + } - viewModel.checkAccessAlarm() - viewModel.getUserDepartment() - viewModel.getUserTopic() + if (viewModel.myDepartment.value.isNullOrBlank()) + return@setOnClickListener - binding.switchSettingUniversityAlarm.setOnCheckedChangeListener { compoundButton, _ -> - checkPermission(binding.switchSettingUniversityAlarm) - if (compoundButton.isChecked) { - if (topics.isNotEmpty()) { - viewModel.updateUserTopic(topics) - } - } else { - viewModel.removeUserTopic() + viewModel.updateUserTopic() + return@setOnClickListener } + + viewModel.removeUserTopic() } - binding.switchSettingDepartmentAlarm.setOnCheckedChangeListener { compoundButton, _ -> - checkPermission(binding.switchSettingDepartmentAlarm) - if (compoundButton.isChecked) { - if (department.isNotEmpty()) { - viewModel.updateUserDepartment(department) + /** TODO 스위치 클릭을 억제하기 위한 임시 뷰, 후에 삭제 필요 */ + binding.viewSettingDepartmentAlarm.setOnClickListener { + if (viewModel.isAccessDepartAlarm.value == false) { + if (checkNotificationPermission().not()) { + showPermissionDialog() + return@setOnClickListener } - } else { - viewModel.removeUserDepartment() + + if (viewModel.myDepartment.value.isNullOrBlank()) + return@setOnClickListener + + viewModel.updateUserDepartment() + return@setOnClickListener } + + viewModel.removeUserDepartment() } binding.btnSettingEditKeyword.setOnClickListener { val intent = Intent(requireActivity(), KeywordActivity::class.java) - resultLauncherKeyword.launch(intent) + startActivity(intent) } binding.btnSettingEditDepartment.setOnClickListener { val intent = Intent(requireActivity(), DepartActivity::class.java) - resultResultDepartment.launch(intent) + departmentActivityResultLauncher.launch(intent) } binding.btnSettingAppHelp.setOnClickListener { @@ -121,51 +123,44 @@ class SettingFragment : BaseFragment() } } - private fun checkPermission(switch: SwitchCompat){ - return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - if (PackageManager.PERMISSION_DENIED == ContextCompat.checkSelfPermission( - requireContext(), Manifest.permission.POST_NOTIFICATIONS - ) - ) { - // 알림 권한 설정 미허용 - viewModel.setIsAccessDepartAlarm(false) - viewModel.setIsAccessUniversityAlarm(false) - binding.switchSettingUniversityAlarm.isChecked = false - binding.switchSettingDepartmentAlarm.isChecked = false - - val dialog = PermissionDialog(getString(R.string.dialog_permission_title), getString(R.string.dialog_permission_content), requireContext().packageName) - dialog.show(parentFragmentManager, "CustomDialog") - } else { - switch.isChecked = !switch.isChecked - } - } else { - switch.isChecked = !switch.isChecked - } - } - private fun getAppVersion(): String { val packageManager = requireContext().packageManager.getPackageInfo(requireContext().packageName, 0) return packageManager.versionName } - private fun setResultKeyword() { - resultLauncherKeyword = - registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - if (result.resultCode == Activity.RESULT_OK) { - viewModel.getUserTopic().run { viewModel.updateUserTopic(topics) } - binding.switchSettingUniversityAlarm.isChecked = true - } - } + private fun initAlarmSwitchStateByNotificationPermission() { + if (!checkNotificationPermission()) { + viewModel.setIsAccessDepartAlarm(false) + viewModel.setIsAccessUniversityAlarm(false) + } } - private fun setResultDepartment() { - resultResultDepartment = - registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -> - if (result.resultCode == Activity.RESULT_OK) { - viewModel.getUserDepartment() - binding.switchSettingDepartmentAlarm.isChecked = true - } - } + private fun showPermissionDialog() { + val dialog = PermissionDialog( + title = getString(R.string.dialog_permission_title), + content = getString(R.string.dialog_permission_content), + pacakageName = requireContext().packageName, + cancelListener = { + viewModel.setIsAccessDepartAlarm(false) + viewModel.setIsAccessUniversityAlarm(false) + }) + + dialog.show(parentFragmentManager, null) + } + + private fun checkNotificationPermission(): Boolean { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) + return true + + if (PackageManager.PERMISSION_DENIED == ContextCompat.checkSelfPermission( + requireContext(), + Manifest.permission.POST_NOTIFICATIONS + ) + ) { + return false + } + + return true } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/SettingViewModel.kt b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/SettingViewModel.kt index 85779b9e..e78048cb 100644 --- a/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/SettingViewModel.kt +++ b/app/src/main/java/com/dongyang/android/youdongknowme/ui/view/setting/SettingViewModel.kt @@ -24,10 +24,10 @@ class SettingViewModel(private val settingRepository: SettingRepository) : BaseV private val _isError: MutableLiveData = MutableLiveData() val isError: LiveData = _isError - private val _isAccessUniversityAlarm: MutableLiveData = MutableLiveData(false) + private val _isAccessUniversityAlarm: MutableLiveData = MutableLiveData() val isAccessUniversityAlarm: LiveData get() = _isAccessUniversityAlarm - private val _isAccessDepartAlarm: MutableLiveData = MutableLiveData(false) + private val _isAccessDepartAlarm: MutableLiveData = MutableLiveData() val isAccessDepartAlarm: LiveData get() = _isAccessDepartAlarm private val _myDepartment: MutableLiveData = MutableLiveData() @@ -36,35 +36,37 @@ class SettingViewModel(private val settingRepository: SettingRepository) : BaseV private val _myTopics: MutableLiveData> = MutableLiveData() val myTopics: LiveData> get() = _myTopics - private val _FCMToken: MutableLiveData = MutableLiveData() - val FCMToken: LiveData get() = _FCMToken + private var FCMToken: String = "" init { + checkAccessAlarm() getUserFCMToken() + getUserTopic() getUserDepartment() } fun checkAccessAlarm() { val isAccessUniversityAlarm = settingRepository.getIsAccessUniversityAlarm() _isAccessUniversityAlarm.postValue(isAccessUniversityAlarm) - val isAccessDepartAlarm = settingRepository.getIsAccessDepartAlarm() _isAccessDepartAlarm.postValue(isAccessDepartAlarm) } fun setIsAccessUniversityAlarm(isAccessSchoolAlarm: Boolean) { settingRepository.setIsAccessSchoolAlarm(isAccessSchoolAlarm) + checkAccessAlarm() } fun setIsAccessDepartAlarm(isAccessDepartAlarm: Boolean) { settingRepository.setIsAccessDepartAlarm(isAccessDepartAlarm) + checkAccessAlarm() } fun getUserDepartment() { _myDepartment.value = settingRepository.getUserDepartment() } - fun getUserTopic() { + private fun getUserTopic() { viewModelScope.launch { val keyword = settingRepository.getUserTopic() _myTopics.value = keyword @@ -72,27 +74,30 @@ class SettingViewModel(private val settingRepository: SettingRepository) : BaseV } private fun getUserFCMToken() { - _FCMToken.value = settingRepository.getUserFCMToken() + FCMToken = settingRepository.getUserFCMToken() } - fun updateUserDepartment(department: String) { + fun updateUserTopic() { _isLoading.postValue(true) viewModelScope.launch { - when (val result = settingRepository.updateUserDepartment( - UpdateDepartment( - token = FCMToken.value.toString(), - department = department + val result = settingRepository.updateUserTopic( + UpdateTopic( + token = FCMToken, + topics = myTopics.value ?: emptyList() ) - )) { + ) + + when (result) { is NetworkResult.Success -> { - setIsAccessDepartAlarm(true) + setIsAccessUniversityAlarm(true) _isLoading.postValue(false) _isError.postValue(false) } is NetworkResult.Error -> { handleError(result, _errorState) + setIsAccessUniversityAlarm(false) _isLoading.postValue(false) _isError.postValue(true) } @@ -100,23 +105,25 @@ class SettingViewModel(private val settingRepository: SettingRepository) : BaseV } } - fun removeUserDepartment() { + fun removeUserTopic() { _isLoading.postValue(true) viewModelScope.launch { - when (val result = - settingRepository.removeUserDepartment( - RemoveToken(token = FCMToken.value.toString()) + val result = + settingRepository.removeUserTopic( + RemoveToken(token = FCMToken) ) - ) { + + when (result) { is NetworkResult.Success -> { - setIsAccessDepartAlarm(false) + setIsAccessUniversityAlarm(false) _isLoading.postValue(false) _isError.postValue(false) } is NetworkResult.Error -> { handleError(result, _errorState) + setIsAccessUniversityAlarm(false) _isLoading.postValue(false) _isError.postValue(true) } @@ -124,24 +131,33 @@ class SettingViewModel(private val settingRepository: SettingRepository) : BaseV } } - fun updateUserTopic(topic: List) { + fun updateUserDepartment() { + val department = _myDepartment.value ?: run { + _isError.postValue(true) + setIsAccessDepartAlarm(false) + return + } + _isLoading.postValue(true) viewModelScope.launch { - when (val result = settingRepository.updateUserTopic( - UpdateTopic( - token = FCMToken.value.toString(), - topics = topic + val result = settingRepository.updateUserDepartment( + UpdateDepartment( + token = FCMToken, + department = department ) - )) { + ) + + when (result) { is NetworkResult.Success -> { - setIsAccessUniversityAlarm(true) + setIsAccessDepartAlarm(true) _isLoading.postValue(false) _isError.postValue(false) } is NetworkResult.Error -> { handleError(result, _errorState) + setIsAccessDepartAlarm(false) _isLoading.postValue(false) _isError.postValue(true) } @@ -149,26 +165,28 @@ class SettingViewModel(private val settingRepository: SettingRepository) : BaseV } } - fun removeUserTopic() { + fun removeUserDepartment() { _isLoading.postValue(true) viewModelScope.launch { - when (val result = - settingRepository.removeUserTopic( - RemoveToken(token = FCMToken.value.toString()) - )) { + val result = settingRepository.removeUserDepartment( + RemoveToken(token = FCMToken) + ) + + when (result) { is NetworkResult.Success -> { - setIsAccessUniversityAlarm(false) + setIsAccessDepartAlarm(false) _isLoading.postValue(false) _isError.postValue(false) } is NetworkResult.Error -> { handleError(result, _errorState) + setIsAccessDepartAlarm(false) _isLoading.postValue(false) _isError.postValue(true) } } } } -} \ No newline at end of file +} diff --git a/app/src/main/res/layout/fragment_setting.xml b/app/src/main/res/layout/fragment_setting.xml index 32e29f7c..16c32c32 100644 --- a/app/src/main/res/layout/fragment_setting.xml +++ b/app/src/main/res/layout/fragment_setting.xml @@ -47,6 +47,8 @@ android:id="@+id/switch_setting_university_alarm" style="@style/PretendardMedium18" android:layout_width="0dp" + android:clickable="false" + android:focusable="false" android:layout_height="wrap_content" android:foreground="?attr/selectableItemBackground" android:minHeight="0dp" @@ -58,6 +60,17 @@ app:layout_constraintTop_toBottomOf="@id/tv_setting_university_title" tools:ignore="RtlSymmetry" /> + + + + - \ No newline at end of file + From 47ab1850e6285b7088f8357e422e89197b231a20 Mon Sep 17 00:00:00 2001 From: hoyahozz <85336456+hoyahozz@users.noreply.github.com> Date: Sun, 21 Apr 2024 22:53:15 +0900 Subject: [PATCH 3/4] =?UTF-8?q?fix=20:=20=ED=82=A4=EC=9B=8C=EB=93=9C=20?= =?UTF-8?q?=ED=99=94=EB=A9=B4=20=EB=82=B4=20=ED=8C=A8=EB=94=A9=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/layout/activity_keyword.xml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/src/main/res/layout/activity_keyword.xml b/app/src/main/res/layout/activity_keyword.xml index 5416bb52..305fccb1 100644 --- a/app/src/main/res/layout/activity_keyword.xml +++ b/app/src/main/res/layout/activity_keyword.xml @@ -34,7 +34,8 @@ + android:layout_height="wrap_content" + android:paddingBottom="20dp"> - \ No newline at end of file + From 674c8b4d4a56f52df54d51ba9bf00474ec32ff1e Mon Sep 17 00:00:00 2001 From: hoyahozz <85336456+hoyahozz@users.noreply.github.com> Date: Sun, 21 Apr 2024 22:58:10 +0900 Subject: [PATCH 4/4] =?UTF-8?q?fix=20:=20=EC=8B=9D=EB=8B=A8=20=ED=99=94?= =?UTF-8?q?=EB=A9=B4=20=EB=82=B4=20=EB=A6=AC=EC=82=AC=EC=9D=B4=ED=81=B4?= =?UTF-8?q?=EB=9F=AC=EB=B7=B0=20=EC=98=A4=EB=B2=84=20=EC=8A=A4=ED=81=AC?= =?UTF-8?q?=EB=A1=A4=20=EC=9D=B4=ED=8E=99=ED=8A=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/res/layout/fragment_cafeteria.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/layout/fragment_cafeteria.xml b/app/src/main/res/layout/fragment_cafeteria.xml index 620669b6..5982cd6a 100644 --- a/app/src/main/res/layout/fragment_cafeteria.xml +++ b/app/src/main/res/layout/fragment_cafeteria.xml @@ -19,8 +19,8 @@ android:id="@+id/nsv_cafeteria_content" android:layout_width="0dp" android:layout_height="0dp" - android:fillViewport="true" android:layout_marginBottom="20dp" + android:fillViewport="true" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -147,6 +147,7 @@ android:layout_height="wrap_content" android:layout_marginVertical="8dp" android:layout_marginStart="8dp" + android:overScrollMode="never" tools:listitem="@layout/item_cafeteria_menu" /> @@ -187,6 +188,7 @@ android:layout_height="wrap_content" android:layout_marginVertical="8dp" android:layout_marginStart="8dp" + android:overScrollMode="never" tools:listitem="@layout/item_cafeteria_menu" />