diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 773cd401..af2bd525 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -70,5 +70,9 @@ android:name=".main.notification.NotificationCenterActivity" android:exported="false" /> + + \ No newline at end of file diff --git a/common-ui/src/main/res/drawable-hdpi/ic_info_gray_6.png b/common-ui/src/main/res/drawable-hdpi/ic_info_gray_6.png new file mode 100644 index 00000000..fd1bb5d9 Binary files /dev/null and b/common-ui/src/main/res/drawable-hdpi/ic_info_gray_6.png differ diff --git a/common-ui/src/main/res/drawable-mdpi/ic_info_gray_6.png b/common-ui/src/main/res/drawable-mdpi/ic_info_gray_6.png new file mode 100644 index 00000000..173c3153 Binary files /dev/null and b/common-ui/src/main/res/drawable-mdpi/ic_info_gray_6.png differ diff --git a/common-ui/src/main/res/drawable-xhdpi/ic_info_gray_6.png b/common-ui/src/main/res/drawable-xhdpi/ic_info_gray_6.png new file mode 100644 index 00000000..6d4e6a4a Binary files /dev/null and b/common-ui/src/main/res/drawable-xhdpi/ic_info_gray_6.png differ diff --git a/common-ui/src/main/res/drawable-xxhdpi/ic_info_gray_6.png b/common-ui/src/main/res/drawable-xxhdpi/ic_info_gray_6.png new file mode 100644 index 00000000..c171d2d4 Binary files /dev/null and b/common-ui/src/main/res/drawable-xxhdpi/ic_info_gray_6.png differ diff --git a/common-ui/src/main/res/drawable-xxxhdpi/ic_info_gray_6.png b/common-ui/src/main/res/drawable-xxxhdpi/ic_info_gray_6.png new file mode 100644 index 00000000..b0bfc31c Binary files /dev/null and b/common-ui/src/main/res/drawable-xxxhdpi/ic_info_gray_6.png differ diff --git a/common-ui/src/main/res/values/strings.xml b/common-ui/src/main/res/values/strings.xml index fe7986e1..6614c274 100644 --- a/common-ui/src/main/res/values/strings.xml +++ b/common-ui/src/main/res/values/strings.xml @@ -147,7 +147,7 @@ 참여한 미션은 취소가 불가능해요 미션에 참여하시겠어요? 미션을 삭제하시겠어요? - 이미 미션에 참여한 리뷰이가 있다면 미션 삭제가 불가능합니다. + 참여중인 리뷰어가 있다면 삭제가 불가능해요. 미션이 삭제되었습니다. @@ -191,4 +191,8 @@ 업데이트 최신 버전 + + 시스템 점검 안내 + + \ No newline at end of file diff --git a/data/src/main/java/com/lgtm/android/data/service/MissionService.kt b/data/src/main/java/com/lgtm/android/data/service/MissionService.kt index f25e16f9..e03bb9da 100644 --- a/data/src/main/java/com/lgtm/android/data/service/MissionService.kt +++ b/data/src/main/java/com/lgtm/android/data/service/MissionService.kt @@ -24,7 +24,7 @@ interface MissionService { @GET("v1/home") suspend fun getHomeMission(): Response> - @POST("v1/mission") + @POST("v2/mission") suspend fun postMission( @Body postMissionRequest: PostMissionRequestDTO ): Response> diff --git a/feature/auth/src/main/java/com/lgtm/android/auth/ui/SystemMaintenanceActivity.kt b/feature/auth/src/main/java/com/lgtm/android/auth/ui/SystemMaintenanceActivity.kt new file mode 100644 index 00000000..b23f8e3f --- /dev/null +++ b/feature/auth/src/main/java/com/lgtm/android/auth/ui/SystemMaintenanceActivity.kt @@ -0,0 +1,31 @@ +package com.lgtm.android.auth.ui + +import com.google.firebase.ktx.Firebase +import com.google.firebase.remoteconfig.FirebaseRemoteConfig +import com.google.firebase.remoteconfig.ktx.remoteConfig +import com.google.firebase.remoteconfig.ktx.remoteConfigSettings +import com.lgtm.android.auth.R +import com.lgtm.android.auth.databinding.ActivitySystemMaintenanceBinding +import com.lgtm.android.common_ui.base.BaseActivity + +class SystemMaintenanceActivity : + BaseActivity(R.layout.activity_system_maintenance) { + override fun initializeViewModel() { + viewModel = null + } + + override fun onResume() { + super.onResume() + + val remoteConfig: FirebaseRemoteConfig = Firebase.remoteConfig + val configSettings = remoteConfigSettings { + minimumFetchIntervalInSeconds = 10 + } + remoteConfig.setConfigSettingsAsync(configSettings) + remoteConfig.fetchAndActivate().addOnCompleteListener { + val isSystemMaintenance = remoteConfig.getString("systemUnderMaintenanceDescription") + .replace("\\n", "\n") + binding.tvDescription.text = isSystemMaintenance + } + } +} \ No newline at end of file diff --git a/feature/auth/src/main/java/com/lgtm/android/auth/ui/splash/SplashActivity.kt b/feature/auth/src/main/java/com/lgtm/android/auth/ui/splash/SplashActivity.kt index cfadef3e..bdd06d23 100644 --- a/feature/auth/src/main/java/com/lgtm/android/auth/ui/splash/SplashActivity.kt +++ b/feature/auth/src/main/java/com/lgtm/android/auth/ui/splash/SplashActivity.kt @@ -11,6 +11,7 @@ import com.lgtm.android.auth.R import com.lgtm.android.auth.constant.AutoLoginState import com.lgtm.android.auth.databinding.ActivitySplashBinding import com.lgtm.android.auth.ui.SignInActivity +import com.lgtm.android.auth.ui.SystemMaintenanceActivity import com.lgtm.android.common_ui.base.BaseActivity import dagger.hilt.android.AndroidEntryPoint @@ -31,6 +32,7 @@ class SplashActivity : BaseActivity(R.layout.activity_spl override fun onResume() { super.onResume() + splashViewModel.checkSystemMaintenance() splashViewModel.getAppVersionInfo() } @@ -55,24 +57,43 @@ class SplashActivity : BaseActivity(R.layout.activity_spl } private fun startNextActivity() { - if (autoLoginState == AutoLoginState.AUTO_LOGIN_SUCCESS) { - moveToMainActivity() - } else { - moveToAuthActivity() + splashViewModel.isDataAllSet.observe(this) { isReady -> + if (isReady == true) { + when { + isSystemMaintenance() -> navigateToSystemMaintenanceActivity() + isAutoLoginAvailable() -> moveToMainActivity() + isAutoLoginAvailable().not() -> moveToAuthActivity() + else -> throw IllegalStateException("Unhandled state") + } + } } } + private fun isSystemMaintenance() = splashViewModel.isSystemMaintenance.value == true + + private fun isAutoLoginAvailable() = autoLoginState == AutoLoginState.AUTO_LOGIN_SUCCESS + private fun moveToMainActivity() { lgtmNavigator.navigateToMain(this) finish() } + private fun navigateToSystemMaintenanceActivity() { + startActivity(Intent(this, SystemMaintenanceActivity::class.java)) + finish() + } + private fun moveToAuthActivity() { startActivity(Intent(this, SignInActivity::class.java)) overridePendingTransition(0, 0) finish() } + override fun onDestroy() { + splashViewModel.removeSourceOnIsDataAllSet() + super.onDestroy() + } + companion object { private const val SPLASH_DELAY: Long = 1000 } diff --git a/feature/auth/src/main/java/com/lgtm/android/auth/ui/splash/SplashViewModel.kt b/feature/auth/src/main/java/com/lgtm/android/auth/ui/splash/SplashViewModel.kt index e2869268..80bcf632 100644 --- a/feature/auth/src/main/java/com/lgtm/android/auth/ui/splash/SplashViewModel.kt +++ b/feature/auth/src/main/java/com/lgtm/android/auth/ui/splash/SplashViewModel.kt @@ -3,10 +3,14 @@ package com.lgtm.android.auth.ui.splash import android.content.ContentValues.TAG import android.util.Log import androidx.lifecycle.LiveData +import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData import androidx.lifecycle.viewModelScope import com.google.firebase.crashlytics.ktx.crashlytics import com.google.firebase.ktx.Firebase +import com.google.firebase.remoteconfig.FirebaseRemoteConfig +import com.google.firebase.remoteconfig.ktx.remoteConfig +import com.google.firebase.remoteconfig.ktx.remoteConfigSettings import com.lgtm.android.common_ui.base.BaseViewModel import com.lgtm.domain.repository.AuthRepository import com.lgtm.domain.repository.IntroRepository @@ -17,7 +21,7 @@ import javax.inject.Inject @HiltViewModel class SplashViewModel @Inject constructor( private val introRepository: IntroRepository, - private val authRepository: AuthRepository + private val authRepository: AuthRepository, ) : BaseViewModel() { private val _minVersion = MutableLiveData() val minVersion: LiveData = _minVersion @@ -38,7 +42,53 @@ class SplashViewModel @Inject constructor( } } + private val _isDataAllSet = MediatorLiveData().apply { value = false } + val isDataAllSet: LiveData = _isDataAllSet + + init { + addSourceOnIsDataAllSet() + } + + private fun addSourceOnIsDataAllSet() { + _isDataAllSet.addSource(minVersion) { + if (_isDataAllSet.value == true) return@addSource + fetchIsDataAllSetState() + } + _isDataAllSet.addSource(latestVersion) { + if (_isDataAllSet.value == true) return@addSource + fetchIsDataAllSetState() + } + } + + fun removeSourceOnIsDataAllSet() { + _isDataAllSet.removeSource(minVersion) + _isDataAllSet.removeSource(latestVersion) + } + + private fun fetchIsDataAllSetState() { + _isDataAllSet.value = _minVersion.value != null && _isSystemMaintenance.value != null + } + + private val _isSystemMaintenance = MutableLiveData() + val isSystemMaintenance: LiveData = _isSystemMaintenance + + fun checkSystemMaintenance() { + val remoteConfig: FirebaseRemoteConfig = Firebase.remoteConfig + val configSettings = remoteConfigSettings { + minimumFetchIntervalInSeconds = 10 + } + remoteConfig.setConfigSettingsAsync(configSettings) + remoteConfig.fetchAndActivate().addOnCompleteListener { + val isSystemMaintenance = remoteConfig.getBoolean(IS_SYSTEM_MAINTENANCE) + _isSystemMaintenance.postValue(isSystemMaintenance) + } + } + fun isAutoLoginAvailable(): Boolean { return authRepository.isAutoLoginAvailable() } + + companion object { + private const val IS_SYSTEM_MAINTENANCE = "isSystemUnderMaintenance" + } } \ No newline at end of file diff --git a/feature/auth/src/main/res/layout/activity_system_maintenance.xml b/feature/auth/src/main/res/layout/activity_system_maintenance.xml new file mode 100644 index 00000000..1713c56b --- /dev/null +++ b/feature/auth/src/main/res/layout/activity_system_maintenance.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/feature/auth/src/main/res/values/strings.xml b/feature/auth/src/main/res/values/strings.xml new file mode 100644 index 00000000..55344e51 --- /dev/null +++ b/feature/auth/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/feature/mission_detail/src/main/java/com/lgtm/android/mission_detail/MissionDetailActivity.kt b/feature/mission_detail/src/main/java/com/lgtm/android/mission_detail/MissionDetailActivity.kt index 7daa6536..5913e7b1 100644 --- a/feature/mission_detail/src/main/java/com/lgtm/android/mission_detail/MissionDetailActivity.kt +++ b/feature/mission_detail/src/main/java/com/lgtm/android/mission_detail/MissionDetailActivity.kt @@ -223,7 +223,7 @@ class MissionDetailActivity : title = title, description = description, doAfterConfirm = ::deleteMission, - confirmBtnBackground = LgtmConfirmationDialog.ConfirmButtonBackground.GREEN + confirmBtnBackground = LgtmConfirmationDialog.ConfirmButtonBackground.GRAY ) dialog.show(supportFragmentManager, this.javaClass.name) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 57dce658..069e71bf 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -3,8 +3,8 @@ compileSdk = "33" minSdk = "26" targetSdk = "33" -appVersion = "1.1.0" -versionCode = "110" +appVersion = "1.1.1" +versionCode = "111" # Kotlin and Serialization kotlin = "1.7.20" @@ -128,6 +128,7 @@ firebase = { module = "com.google.firebase:firebase-bom", version.ref = "firebas firebase-analytics = { module = "com.google.firebase:firebase-analytics-ktx" } firebase-crashlytics = { module = "com.google.firebase:firebase-crashlytics-ktx" } firebase-messaging = { module = "com.google.firebase:firebase-messaging-ktx" } +firebase-config = { module = "com.google.firebase:firebase-config-ktx" } kotlin-bom = { group = "org.jetbrains.kotlin", name = "kotlin-bom", version.ref = "kotlin-bom" } jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } @@ -138,7 +139,7 @@ androidx-ui-foundation = ["core-ktx", "appcompat", "lifecycle-viewmodel", "const okhttp = ["okhttp", "okhttp-logging-interceptor", "okhttp-bom"] retrofit = ["retrofit", "retrofit-kotlin-serialization-converter"] gson = ["gson", "gson-converter"] -firebase = ["firebase-analytics", "firebase-crashlytics", "firebase-messaging"] +firebase = ["firebase-analytics", "firebase-crashlytics", "firebase-messaging", "firebase-config"] accompanist = ["accompanist-systemuicontroller"] androidx-android-test = ["androidx-test-runner", "androidx-test-rules"] basic-test = ["junit", "androidx-test-junit", "androidx-test-espresso"]