diff --git a/app/build.gradle b/app/build.gradle
index 6dfab455..5fd94e45 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -5,7 +5,7 @@ plugins {
id 'dagger.hilt.android.plugin'
id 'kotlin-parcelize'
id "org.jlleitschuh.gradle.ktlint" version "10.3.0"
- id 'org.jetbrains.kotlin.plugin.serialization' version '1.7.20'
+ id 'org.jetbrains.kotlin.plugin.serialization' version '1.9.0'
id 'com.google.gms.google-services'
}
@@ -59,10 +59,6 @@ android {
dependencies {
- // glide
- implementation 'com.github.bumptech.glide:glide:4.13.2'
- kapt 'com.github.bumptech.glide:compiler:4.13.2'
-
// hilt
implementation 'com.google.dagger:hilt-android:2.48.1'
kapt 'com.google.dagger:hilt-compiler:2.48.1'
@@ -84,8 +80,7 @@ dependencies {
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3'
// network
- implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0'
- implementation(platform('com.squareup.okhttp3:okhttp-bom:4.11.0'))
+ implementation 'com.squareup.okhttp3:logging-interceptor:4.12.0'
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.jakewharton.retrofit:retrofit2-kotlinx-serialization-converter:1.0.0'
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index a521b84d..e19982d0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -4,13 +4,15 @@
+ android:required="true" />
-
-
-
+ android:screenOrientation="portrait" />
=
kotlin.runCatching { authDataSource.postLogin(socialPlatform) }.map { response ->
@@ -28,15 +27,10 @@ class AuthRepositoryImpl @Inject constructor(
localTokenDataSource.refreshToken = refreshToken
}
- override fun setSplashState(splashState: SplashState) {
- localSplashDataSource.splashState = splashState.toString()
- }
-
- override fun getSplashState(): SplashState {
- return SplashState.valueOf(localSplashDataSource.splashState)
- }
+ override fun clearLocalPref() = localPrefDataSource.clearLocalPref()
- override fun clearLocalPref() {
- localPrefDataSource.clearLocalPref()
+ override fun getSignedUp(): Boolean = localSignedUpDataSource.isSignedUp
+ override fun setSignedUp() {
+ localSignedUpDataSource.isSignedUp = true
}
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/data/repository/ForceUpdateRepositoryImpl.kt b/app/src/main/java/com/sopt/peekabookaos/data/repository/ForceUpdateRepositoryImpl.kt
deleted file mode 100644
index cb5989cd..00000000
--- a/app/src/main/java/com/sopt/peekabookaos/data/repository/ForceUpdateRepositoryImpl.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.sopt.peekabookaos.data.repository
-
-import com.sopt.peekabookaos.data.source.remote.ForceUpdateDataSource
-import com.sopt.peekabookaos.domain.entity.Version
-import com.sopt.peekabookaos.domain.repository.ForceUpdateRepository
-import javax.inject.Inject
-
-class ForceUpdateRepositoryImpl @Inject constructor(
- private val forceUpdateDataSource: ForceUpdateDataSource
-) : ForceUpdateRepository {
- override suspend fun getVersion(): Result =
- kotlin.runCatching { forceUpdateDataSource.getVersion() }.map { response ->
- requireNotNull(response.data).toVersion()
- }
-}
diff --git a/app/src/main/java/com/sopt/peekabookaos/data/repository/ForcedUpdateRepositoryImpl.kt b/app/src/main/java/com/sopt/peekabookaos/data/repository/ForcedUpdateRepositoryImpl.kt
new file mode 100644
index 00000000..f55f7e76
--- /dev/null
+++ b/app/src/main/java/com/sopt/peekabookaos/data/repository/ForcedUpdateRepositoryImpl.kt
@@ -0,0 +1,25 @@
+package com.sopt.peekabookaos.data.repository
+
+import com.sopt.peekabookaos.data.source.remote.ForcedUpdateDataSource
+import com.sopt.peekabookaos.domain.entity.ForcedUpdate
+import com.sopt.peekabookaos.domain.entity.UpdateInformation
+import com.sopt.peekabookaos.domain.entity.Version
+import com.sopt.peekabookaos.domain.repository.ForcedUpdateRepository
+import javax.inject.Inject
+
+class ForcedUpdateRepositoryImpl @Inject constructor(
+ private val forcedUpdateDataSource: ForcedUpdateDataSource
+) : ForcedUpdateRepository {
+ override suspend fun hasForceUpdateVersion(
+ currentVersion: String
+ ): Result = kotlin.runCatching {
+ forcedUpdateDataSource.getForcedUpdateVersion()
+ }.map { response ->
+ val (imageUrl, androidForceVersion, text) = requireNotNull(response.data)
+ if (Version.of(androidForceVersion).greaterThan(Version.of(currentVersion))) {
+ return@map ForcedUpdate.Need(UpdateInformation(imageUrl, text))
+ } else {
+ return@map ForcedUpdate.None
+ }
+ }
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/data/service/ForceUpdateService.kt b/app/src/main/java/com/sopt/peekabookaos/data/service/ForceUpdateService.kt
deleted file mode 100644
index 13b32c72..00000000
--- a/app/src/main/java/com/sopt/peekabookaos/data/service/ForceUpdateService.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.sopt.peekabookaos.data.service
-
-import com.sopt.peekabookaos.data.entity.BaseResponse
-import com.sopt.peekabookaos.data.entity.response.VersionResponse
-import retrofit2.http.GET
-
-interface ForceUpdateService {
- @GET("user/v1/version")
- suspend fun getVersion(): BaseResponse
-}
diff --git a/app/src/main/java/com/sopt/peekabookaos/data/service/ForcedUpdateService.kt b/app/src/main/java/com/sopt/peekabookaos/data/service/ForcedUpdateService.kt
new file mode 100644
index 00000000..96850d71
--- /dev/null
+++ b/app/src/main/java/com/sopt/peekabookaos/data/service/ForcedUpdateService.kt
@@ -0,0 +1,10 @@
+package com.sopt.peekabookaos.data.service
+
+import com.sopt.peekabookaos.data.entity.BaseResponse
+import com.sopt.peekabookaos.data.entity.response.ForcedUpdateResponse
+import retrofit2.http.GET
+
+interface ForcedUpdateService {
+ @GET("user/v1/version")
+ suspend fun getVersion(): BaseResponse
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/data/source/local/LocalSignedUpDataSource.kt b/app/src/main/java/com/sopt/peekabookaos/data/source/local/LocalSignedUpDataSource.kt
new file mode 100644
index 00000000..a11da331
--- /dev/null
+++ b/app/src/main/java/com/sopt/peekabookaos/data/source/local/LocalSignedUpDataSource.kt
@@ -0,0 +1,17 @@
+package com.sopt.peekabookaos.data.source.local
+
+import android.content.SharedPreferences
+import androidx.core.content.edit
+import javax.inject.Inject
+
+class LocalSignedUpDataSource @Inject constructor(
+ private val prefs: SharedPreferences
+) {
+ var isSignedUp: Boolean
+ set(value) = prefs.edit { putBoolean(SIGNED_UP, value) }
+ get() = prefs.getBoolean(SIGNED_UP, false)
+
+ companion object {
+ private const val SIGNED_UP = "signed up"
+ }
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/data/source/local/LocalSplashDataSource.kt b/app/src/main/java/com/sopt/peekabookaos/data/source/local/LocalSplashDataSource.kt
deleted file mode 100644
index c5511091..00000000
--- a/app/src/main/java/com/sopt/peekabookaos/data/source/local/LocalSplashDataSource.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package com.sopt.peekabookaos.data.source.local
-
-import android.content.SharedPreferences
-import androidx.core.content.edit
-import javax.inject.Inject
-
-class LocalSplashDataSource @Inject constructor(
- private val prefs: SharedPreferences
-) {
- var splashState: String
- set(value) = prefs.edit { putString(SPLASH_STATE, value) }
- get() = prefs.getString(SPLASH_STATE, DEFAULT_STATE) ?: DEFAULT_STATE
-
- companion object {
- private const val SPLASH_STATE = "splash_state"
- private const val DEFAULT_STATE = "ONBOARDING"
- }
-}
diff --git a/app/src/main/java/com/sopt/peekabookaos/data/source/remote/ForceUpdateDataSource.kt b/app/src/main/java/com/sopt/peekabookaos/data/source/remote/ForceUpdateDataSource.kt
deleted file mode 100644
index c21ee921..00000000
--- a/app/src/main/java/com/sopt/peekabookaos/data/source/remote/ForceUpdateDataSource.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.sopt.peekabookaos.data.source.remote
-
-import com.sopt.peekabookaos.data.entity.BaseResponse
-import com.sopt.peekabookaos.data.entity.response.VersionResponse
-import com.sopt.peekabookaos.data.service.ForceUpdateService
-import javax.inject.Inject
-
-class ForceUpdateDataSource @Inject constructor(
- private val forceUpdateService: ForceUpdateService
-) {
- suspend fun getVersion(): BaseResponse =
- forceUpdateService.getVersion()
-}
diff --git a/app/src/main/java/com/sopt/peekabookaos/data/source/remote/ForcedUpdateDataSource.kt b/app/src/main/java/com/sopt/peekabookaos/data/source/remote/ForcedUpdateDataSource.kt
new file mode 100644
index 00000000..37c49e76
--- /dev/null
+++ b/app/src/main/java/com/sopt/peekabookaos/data/source/remote/ForcedUpdateDataSource.kt
@@ -0,0 +1,13 @@
+package com.sopt.peekabookaos.data.source.remote
+
+import com.sopt.peekabookaos.data.entity.BaseResponse
+import com.sopt.peekabookaos.data.entity.response.ForcedUpdateResponse
+import com.sopt.peekabookaos.data.service.ForcedUpdateService
+import javax.inject.Inject
+
+class ForcedUpdateDataSource @Inject constructor(
+ private val forcedUpdateService: ForcedUpdateService
+) {
+ suspend fun getForcedUpdateVersion(): BaseResponse =
+ forcedUpdateService.getVersion()
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/di/RepositoryModule.kt b/app/src/main/java/com/sopt/peekabookaos/di/RepositoryModule.kt
index 0b8c200f..676e504b 100644
--- a/app/src/main/java/com/sopt/peekabookaos/di/RepositoryModule.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/di/RepositoryModule.kt
@@ -4,7 +4,7 @@ import com.sopt.peekabookaos.data.repository.AuthRepositoryImpl
import com.sopt.peekabookaos.data.repository.BlockRepositoryImpl
import com.sopt.peekabookaos.data.repository.BookRepositoryImpl
import com.sopt.peekabookaos.data.repository.DetailRepositoryImpl
-import com.sopt.peekabookaos.data.repository.ForceUpdateRepositoryImpl
+import com.sopt.peekabookaos.data.repository.ForcedUpdateRepositoryImpl
import com.sopt.peekabookaos.data.repository.MyPageRepositoryImpl
import com.sopt.peekabookaos.data.repository.NaverRepositoryImpl
import com.sopt.peekabookaos.data.repository.NotificationRepositoryImpl
@@ -18,7 +18,7 @@ import com.sopt.peekabookaos.domain.repository.AuthRepository
import com.sopt.peekabookaos.domain.repository.BlockRepository
import com.sopt.peekabookaos.domain.repository.BookRepository
import com.sopt.peekabookaos.domain.repository.DetailRepository
-import com.sopt.peekabookaos.domain.repository.ForceUpdateRepository
+import com.sopt.peekabookaos.domain.repository.ForcedUpdateRepository
import com.sopt.peekabookaos.domain.repository.MyPageRepository
import com.sopt.peekabookaos.domain.repository.NaverRepository
import com.sopt.peekabookaos.domain.repository.NotificationRepository
@@ -118,6 +118,6 @@ abstract class RepositoryModule {
@Binds
@Singleton
abstract fun bindToForceUpdateRepository(
- forceUpdateRepositoryImpl: ForceUpdateRepositoryImpl
- ): ForceUpdateRepository
+ forceUpdateRepositoryImpl: ForcedUpdateRepositoryImpl
+ ): ForcedUpdateRepository
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/di/RetrofitServiceModule.kt b/app/src/main/java/com/sopt/peekabookaos/di/RetrofitServiceModule.kt
index 22f4b3fc..9814775b 100644
--- a/app/src/main/java/com/sopt/peekabookaos/di/RetrofitServiceModule.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/di/RetrofitServiceModule.kt
@@ -4,7 +4,7 @@ import com.sopt.peekabookaos.data.service.AuthService
import com.sopt.peekabookaos.data.service.BlockService
import com.sopt.peekabookaos.data.service.BookService
import com.sopt.peekabookaos.data.service.DetailService
-import com.sopt.peekabookaos.data.service.ForceUpdateService
+import com.sopt.peekabookaos.data.service.ForcedUpdateService
import com.sopt.peekabookaos.data.service.MyPageService
import com.sopt.peekabookaos.data.service.NaverService
import com.sopt.peekabookaos.data.service.NotificationService
@@ -22,7 +22,6 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import retrofit2.Retrofit
-import retrofit2.create
@Module
@InstallIn(SingletonComponent::class)
@@ -80,6 +79,6 @@ object RetrofitServiceModule {
retrofit.create(ReportService::class.java)
@Provides
- fun providesForceUpdateService(@PeekaType retrofit: Retrofit): ForceUpdateService =
- retrofit.create(ForceUpdateService::class.java)
+ fun providesForceUpdateService(@PeekaType retrofit: Retrofit): ForcedUpdateService =
+ retrofit.create(ForcedUpdateService::class.java)
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/entity/ForcedUpdate.kt b/app/src/main/java/com/sopt/peekabookaos/domain/entity/ForcedUpdate.kt
new file mode 100644
index 00000000..797d8052
--- /dev/null
+++ b/app/src/main/java/com/sopt/peekabookaos/domain/entity/ForcedUpdate.kt
@@ -0,0 +1,6 @@
+package com.sopt.peekabookaos.domain.entity
+
+sealed class ForcedUpdate {
+ data object None : ForcedUpdate()
+ data class Need(val updateInformation: UpdateInformation) : ForcedUpdate()
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/entity/SplashState.kt b/app/src/main/java/com/sopt/peekabookaos/domain/entity/SplashState.kt
deleted file mode 100644
index 790865d4..00000000
--- a/app/src/main/java/com/sopt/peekabookaos/domain/entity/SplashState.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.sopt.peekabookaos.domain.entity
-
-enum class SplashState {
- ONBOARDING, MAIN
-}
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/entity/SplashUiState.kt b/app/src/main/java/com/sopt/peekabookaos/domain/entity/SplashUiState.kt
new file mode 100644
index 00000000..91ad4105
--- /dev/null
+++ b/app/src/main/java/com/sopt/peekabookaos/domain/entity/SplashUiState.kt
@@ -0,0 +1,10 @@
+package com.sopt.peekabookaos.domain.entity
+
+sealed class SplashUiState {
+ data object Idle : SplashUiState()
+ data object Error : SplashUiState()
+ data object ShowSplash : SplashUiState()
+ data object CanStartOnboarding : SplashUiState()
+ data object CanStartMain : SplashUiState()
+ data class ForceUpdate(val data: UpdateInformation) : SplashUiState()
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/entity/UpdateInformation.kt b/app/src/main/java/com/sopt/peekabookaos/domain/entity/UpdateInformation.kt
new file mode 100644
index 00000000..1f9f2bcc
--- /dev/null
+++ b/app/src/main/java/com/sopt/peekabookaos/domain/entity/UpdateInformation.kt
@@ -0,0 +1,10 @@
+package com.sopt.peekabookaos.domain.entity
+
+import android.os.Parcelable
+import kotlinx.parcelize.Parcelize
+
+@Parcelize
+data class UpdateInformation(
+ val imageUrl: String = "",
+ val text: String = ""
+) : Parcelable
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/entity/Version.kt b/app/src/main/java/com/sopt/peekabookaos/domain/entity/Version.kt
index c998453d..d0185321 100644
--- a/app/src/main/java/com/sopt/peekabookaos/domain/entity/Version.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/domain/entity/Version.kt
@@ -1,11 +1,20 @@
package com.sopt.peekabookaos.domain.entity
-import android.os.Parcelable
-import kotlinx.parcelize.Parcelize
+class Version private constructor(
+ private val major: Int,
+ private val minor: Int
+) {
-@Parcelize
-data class Version(
- val imageUrl: String = "",
- val androidForceVersion: String = "",
- val versionText: String = ""
-) : Parcelable
+ fun greaterThan(other: Version): Boolean = other.major < major || other.minor < minor
+
+ companion object {
+ private const val VERSION_SPLIT_SIGN = "."
+ private const val MAJOR_POSITION = 0
+ private const val MINOR_POSITION = 1
+ fun of(version: String) = version.split(VERSION_SPLIT_SIGN).map {
+ it.toInt()
+ }.let {
+ Version(it[MAJOR_POSITION], it[MINOR_POSITION])
+ }
+ }
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/entity/VersionDetail.kt b/app/src/main/java/com/sopt/peekabookaos/domain/entity/VersionDetail.kt
deleted file mode 100644
index b904357a..00000000
--- a/app/src/main/java/com/sopt/peekabookaos/domain/entity/VersionDetail.kt
+++ /dev/null
@@ -1,6 +0,0 @@
-package com.sopt.peekabookaos.domain.entity
-
-data class VersionDetail(
- val major: String,
- val minor: String
-)
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/entity/VersionState.kt b/app/src/main/java/com/sopt/peekabookaos/domain/entity/VersionState.kt
deleted file mode 100644
index 8bb1ca7b..00000000
--- a/app/src/main/java/com/sopt/peekabookaos/domain/entity/VersionState.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.sopt.peekabookaos.domain.entity
-
-enum class VersionState {
- LATEST, OUTDATED
-}
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/repository/AuthRepository.kt b/app/src/main/java/com/sopt/peekabookaos/domain/repository/AuthRepository.kt
index 2a60edcf..0a7d8c9e 100644
--- a/app/src/main/java/com/sopt/peekabookaos/domain/repository/AuthRepository.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/domain/repository/AuthRepository.kt
@@ -1,6 +1,5 @@
package com.sopt.peekabookaos.domain.repository
-import com.sopt.peekabookaos.domain.entity.SplashState
import com.sopt.peekabookaos.domain.entity.Token
interface AuthRepository {
@@ -10,9 +9,9 @@ interface AuthRepository {
fun initToken(accessToken: String, refreshToken: String)
- fun setSplashState(splashState: SplashState)
+ fun clearLocalPref()
- fun getSplashState(): SplashState
+ fun getSignedUp(): Boolean
- fun clearLocalPref()
+ fun setSignedUp()
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/repository/ForceUpdateRepository.kt b/app/src/main/java/com/sopt/peekabookaos/domain/repository/ForceUpdateRepository.kt
deleted file mode 100644
index 6050968a..00000000
--- a/app/src/main/java/com/sopt/peekabookaos/domain/repository/ForceUpdateRepository.kt
+++ /dev/null
@@ -1,7 +0,0 @@
-package com.sopt.peekabookaos.domain.repository
-
-import com.sopt.peekabookaos.domain.entity.Version
-
-interface ForceUpdateRepository {
- suspend fun getVersion(): Result
-}
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/repository/ForcedUpdateRepository.kt b/app/src/main/java/com/sopt/peekabookaos/domain/repository/ForcedUpdateRepository.kt
new file mode 100644
index 00000000..90d569ac
--- /dev/null
+++ b/app/src/main/java/com/sopt/peekabookaos/domain/repository/ForcedUpdateRepository.kt
@@ -0,0 +1,9 @@
+package com.sopt.peekabookaos.domain.repository
+
+import com.sopt.peekabookaos.domain.entity.ForcedUpdate
+
+interface ForcedUpdateRepository {
+ suspend fun hasForceUpdateVersion(
+ currentVersion: String
+ ): Result
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/usecase/GetSplashStateUseCase.kt b/app/src/main/java/com/sopt/peekabookaos/domain/usecase/GetSignedUpUseCase.kt
similarity index 63%
rename from app/src/main/java/com/sopt/peekabookaos/domain/usecase/GetSplashStateUseCase.kt
rename to app/src/main/java/com/sopt/peekabookaos/domain/usecase/GetSignedUpUseCase.kt
index bc51c746..a00b306d 100644
--- a/app/src/main/java/com/sopt/peekabookaos/domain/usecase/GetSplashStateUseCase.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/domain/usecase/GetSignedUpUseCase.kt
@@ -3,8 +3,8 @@ package com.sopt.peekabookaos.domain.usecase
import com.sopt.peekabookaos.domain.repository.AuthRepository
import javax.inject.Inject
-class GetSplashStateUseCase @Inject constructor(
+class GetSignedUpUseCase @Inject constructor(
private val authRepository: AuthRepository
) {
- operator fun invoke() = authRepository.getSplashState()
+ operator fun invoke() = authRepository.getSignedUp()
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/usecase/GetVersionUseCase.kt b/app/src/main/java/com/sopt/peekabookaos/domain/usecase/GetVersionUseCase.kt
deleted file mode 100644
index e4884600..00000000
--- a/app/src/main/java/com/sopt/peekabookaos/domain/usecase/GetVersionUseCase.kt
+++ /dev/null
@@ -1,10 +0,0 @@
-package com.sopt.peekabookaos.domain.usecase
-
-import com.sopt.peekabookaos.domain.repository.ForceUpdateRepository
-import javax.inject.Inject
-
-class GetVersionUseCase @Inject constructor(
- private val forceUpdateRepository: ForceUpdateRepository
-) {
- suspend operator fun invoke() = forceUpdateRepository.getVersion()
-}
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/usecase/HasUpdateVersionCheckUseCase.kt b/app/src/main/java/com/sopt/peekabookaos/domain/usecase/HasUpdateVersionCheckUseCase.kt
new file mode 100644
index 00000000..ca3c7b3e
--- /dev/null
+++ b/app/src/main/java/com/sopt/peekabookaos/domain/usecase/HasUpdateVersionCheckUseCase.kt
@@ -0,0 +1,12 @@
+package com.sopt.peekabookaos.domain.usecase
+
+import com.sopt.peekabookaos.domain.repository.ForcedUpdateRepository
+import javax.inject.Inject
+
+class HasUpdateVersionCheckUseCase @Inject constructor(
+ private val forcedUpdateRepository: ForcedUpdateRepository
+) {
+ suspend operator fun invoke(
+ currentVersion: String
+ ) = forcedUpdateRepository.hasForceUpdateVersion(currentVersion)
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/usecase/SetAccessToMainUseCase.kt b/app/src/main/java/com/sopt/peekabookaos/domain/usecase/SetAccessToMainUseCase.kt
new file mode 100644
index 00000000..0301685b
--- /dev/null
+++ b/app/src/main/java/com/sopt/peekabookaos/domain/usecase/SetAccessToMainUseCase.kt
@@ -0,0 +1,10 @@
+package com.sopt.peekabookaos.domain.usecase
+
+import com.sopt.peekabookaos.domain.repository.AuthRepository
+import javax.inject.Inject
+
+class SetAccessToMainUseCase @Inject constructor(
+ private val authRepository: AuthRepository
+) {
+ operator fun invoke() = authRepository.setSignedUp()
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/domain/usecase/SetSplashStateUseCase.kt b/app/src/main/java/com/sopt/peekabookaos/domain/usecase/SetSplashStateUseCase.kt
deleted file mode 100644
index 91608884..00000000
--- a/app/src/main/java/com/sopt/peekabookaos/domain/usecase/SetSplashStateUseCase.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package com.sopt.peekabookaos.domain.usecase
-
-import com.sopt.peekabookaos.domain.entity.SplashState
-import com.sopt.peekabookaos.domain.repository.AuthRepository
-import javax.inject.Inject
-
-class SetSplashStateUseCase @Inject constructor(
- private val authRepository: AuthRepository
-) {
- operator fun invoke(splashState: SplashState) {
- authRepository.setSplashState(splashState)
- }
-}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/barcodeScanner/BarcodeAnalyser.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/barcodeScanner/BarcodeAnalyzer.kt
similarity index 88%
rename from app/src/main/java/com/sopt/peekabookaos/presentation/barcodeScanner/BarcodeAnalyser.kt
rename to app/src/main/java/com/sopt/peekabookaos/presentation/barcodeScanner/BarcodeAnalyzer.kt
index e19b8545..29a4c6f5 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/barcodeScanner/BarcodeAnalyser.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/barcodeScanner/BarcodeAnalyzer.kt
@@ -1,6 +1,7 @@
package com.sopt.peekabookaos.presentation.barcodeScanner
-import android.annotation.SuppressLint
+import androidx.annotation.OptIn
+import androidx.camera.core.ExperimentalGetImage
import androidx.camera.core.ImageAnalysis
import androidx.camera.core.ImageProxy
import com.google.mlkit.vision.barcode.BarcodeScannerOptions
@@ -8,7 +9,7 @@ import com.google.mlkit.vision.barcode.BarcodeScanning
import com.google.mlkit.vision.barcode.common.Barcode
import com.google.mlkit.vision.common.InputImage
-class BarcodeAnalyser(private val barcodeListener: BarcodeAnalyzerListener) :
+class BarcodeAnalyzer(private val barcodeListener: BarcodeAnalyzerListener) :
ImageAnalysis.Analyzer {
private val options = BarcodeScannerOptions.Builder().setBarcodeFormats(
Barcode.FORMAT_CODE_39,
@@ -24,7 +25,7 @@ class BarcodeAnalyser(private val barcodeListener: BarcodeAnalyzerListener) :
private val scanner by lazy { BarcodeScanning.getClient(options) }
- @SuppressLint("UnsafeOptInUsageError")
+ @OptIn(ExperimentalGetImage::class)
override fun analyze(imageProxy: ImageProxy) {
val mediaImage = imageProxy.image
if (mediaImage != null) {
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/barcodeScanner/BarcodeScannerFragment.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/barcodeScanner/BarcodeScannerFragment.kt
index c1339de6..4e8fb809 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/barcodeScanner/BarcodeScannerFragment.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/barcodeScanner/BarcodeScannerFragment.kt
@@ -3,7 +3,6 @@ package com.sopt.peekabookaos.presentation.barcodeScanner
import android.Manifest
import android.content.pm.PackageManager
import android.os.Bundle
-import android.util.DisplayMetrics
import android.view.View
import androidx.activity.OnBackPressedCallback
import androidx.camera.core.AspectRatio
@@ -25,6 +24,7 @@ import com.sopt.peekabookaos.presentation.book.BookActivity.Companion.CREATE
import com.sopt.peekabookaos.presentation.book.BookActivity.Companion.LOCATION
import com.sopt.peekabookaos.util.ToastMessageUtil
import com.sopt.peekabookaos.util.binding.BindingFragment
+import com.sopt.peekabookaos.util.extensions.getScreenSize
import com.sopt.peekabookaos.util.extensions.repeatOnStarted
import com.sopt.peekabookaos.util.extensions.setSingleOnClickListener
import dagger.hilt.android.AndroidEntryPoint
@@ -34,7 +34,7 @@ import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min
-private val REQUIRED_PERMISSIONS = arrayOf(Manifest.permission.CAMERA)
+private val requiredPermissions = arrayOf(Manifest.permission.CAMERA)
private const val RATIO_4_3_VALUE = 4.0 / 3.0
private const val RATIO_16_9_VALUE = 16.0 / 9.0
typealias BarcodeAnalyzerListener = (barcode: MutableList) -> Unit
@@ -77,10 +77,8 @@ class BarcodeScannerFragment :
}
private fun startCamera() {
- @Suppress("DEPRECATION")
- val metrics =
- DisplayMetrics().also { binding.pvBarcode.display.getRealMetrics(it) }
- val screenAspectRatio = aspectRatio(metrics.widthPixels, metrics.heightPixels)
+ val screenSize = requireContext().getScreenSize()
+ val screenAspectRatio = aspectRatio(screenSize.first, screenSize.second)
val rotation = binding.pvBarcode.display.rotation
val cameraSelector =
@@ -90,8 +88,7 @@ class BarcodeScannerFragment :
{
val cameraProvider: ProcessCameraProvider = cameraProviderFuture.get()
- val preview = Preview.Builder().setTargetAspectRatio(screenAspectRatio)
- .setTargetRotation(rotation).build()
+ val preview = Preview.Builder().setTargetRotation(rotation).build()
preview.setSurfaceProvider(binding.pvBarcode.surfaceProvider)
@@ -116,7 +113,7 @@ class BarcodeScannerFragment :
)
}
- private fun allPermissionsGranted() = REQUIRED_PERMISSIONS.all {
+ private fun allPermissionsGranted() = requiredPermissions.all {
ContextCompat.checkSelfPermission(requireContext(), it) == PackageManager.PERMISSION_GRANTED
}
@@ -129,12 +126,12 @@ class BarcodeScannerFragment :
}
private fun initAnalyzer(screenAspectRatio: Int, rotation: Int): UseCase {
- return ImageAnalysis.Builder().setTargetAspectRatio(screenAspectRatio)
+ return ImageAnalysis.Builder().setTargetRotation(screenAspectRatio)
.setBackpressureStrategy(ImageAnalysis.STRATEGY_KEEP_ONLY_LATEST)
.setTargetRotation(rotation).build().also {
it.setAnalyzer(
executor,
- BarcodeAnalyser { barcode ->
+ BarcodeAnalyzer { barcode ->
if (processingBarcode.compareAndSet(false, false)) {
onBarcodeDetected(barcode)
}
@@ -177,9 +174,11 @@ class BarcodeScannerFragment :
}
)
}
+
BarcodeState.ERROR -> {
BarcodeErrorDialog().show(childFragmentManager, BarcodeErrorDialog.TAG)
}
+
BarcodeState.IDLE -> {
return@collect
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/book/BookActivity.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/book/BookActivity.kt
index ff92e08d..bca4df5f 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/book/BookActivity.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/book/BookActivity.kt
@@ -1,12 +1,12 @@
package com.sopt.peekabookaos.presentation.book
-import android.app.Activity
import android.os.Bundle
import androidx.navigation.fragment.NavHostFragment
import com.sopt.peekabookaos.R
import com.sopt.peekabookaos.databinding.ActivityBookBinding
import com.sopt.peekabookaos.util.binding.BindingActivity
-import com.sopt.peekabookaos.util.extensions.activityTransition
+import com.sopt.peekabookaos.util.extensions.activityCloseTransition
+import com.sopt.peekabookaos.util.extensions.activityOpenTransition
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
@@ -24,31 +24,19 @@ class BookActivity : BindingActivity(R.layout.activity_book
when (intent.getStringExtra(LOCATION) ?: CREATE) {
RECOMMEND -> {
navController.navigate(R.id.action_barcodeScannerFragment_to_searchBookFragment)
- activityTransition(
- Activity.OVERRIDE_TRANSITION_OPEN,
- R.animator.anim_from_right,
- R.animator.anim_to_left
- )
+ activityOpenTransition(R.animator.anim_from_right, R.animator.anim_to_left)
}
else -> {
navController.navigate(R.id.barcodeScannerFragment)
- activityTransition(
- Activity.OVERRIDE_TRANSITION_OPEN,
- R.animator.anim_from_bottom,
- R.animator.anim_to_top
- )
+ activityOpenTransition(R.animator.anim_from_bottom, R.animator.anim_to_top)
}
}
}
override fun finish() {
super.finish()
- activityTransition(
- Activity.OVERRIDE_TRANSITION_CLOSE,
- R.animator.anim_from_left,
- R.animator.anim_to_right
- )
+ activityCloseTransition(R.animator.anim_from_left, R.animator.anim_to_right)
}
companion object {
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/bookshelf/BlockDialog.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/bookshelf/BlockDialog.kt
index 25c56543..e2cc8b12 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/bookshelf/BlockDialog.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/bookshelf/BlockDialog.kt
@@ -10,6 +10,7 @@ import com.sopt.peekabookaos.R
import com.sopt.peekabookaos.databinding.DialogBlockBinding
import com.sopt.peekabookaos.util.dialog.ConfirmClickListener
import com.sopt.peekabookaos.util.dialog.WarningDialogFragment
+import com.sopt.peekabookaos.util.extensions.getParcelableCompat
import timber.log.Timber
class BlockDialog : DialogFragment() {
@@ -49,7 +50,7 @@ class BlockDialog : DialogFragment() {
private fun initConfirmBtnClickListener() {
binding.btnBlockDialogConfirm.setOnClickListener {
- arguments?.getParcelable(WarningDialogFragment.CONFIRM_ACTION)
+ arguments?.getParcelableCompat(WarningDialogFragment.CONFIRM_ACTION)
?.onConfirmClick()
?: Timber.e(getString(R.string.null_point_exception_warning_dialog_argument))
dismiss()
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/createBook/CreateBookFragment.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/createBook/CreateBookFragment.kt
index 1fb6e731..314d970a 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/createBook/CreateBookFragment.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/createBook/CreateBookFragment.kt
@@ -50,7 +50,7 @@ class CreateBookFragment :
private fun initBookInfo() {
createBookViewModel.initBookInfo(
- arguments?.getParcelableCompat(BOOK_INFO, Book::class.java) ?: Book()
+ arguments?.getParcelableCompat(BOOK_INFO) ?: Book()
)
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/forceUpdate/ForceUpdateActivity.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/forceUpdate/ForceUpdateActivity.kt
deleted file mode 100644
index c9e3eae1..00000000
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/forceUpdate/ForceUpdateActivity.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-package com.sopt.peekabookaos.presentation.forceUpdate
-
-import android.content.Intent
-import android.net.Uri
-import android.os.Bundle
-import androidx.activity.viewModels
-import com.sopt.peekabookaos.R
-import com.sopt.peekabookaos.databinding.ActivityForceUpdateBinding
-import com.sopt.peekabookaos.domain.entity.Version
-import com.sopt.peekabookaos.presentation.splash.SplashActivity.Companion.LATEST_VERSION
-import com.sopt.peekabookaos.util.binding.BindingActivity
-import com.sopt.peekabookaos.util.extensions.getParcelable
-
-class ForceUpdateActivity :
- BindingActivity(R.layout.activity_force_update) {
- private lateinit var intentToPlayStore: Intent
- private val viewModel by viewModels()
-
- override fun onCreate(savedInstanceState: Bundle?) {
- super.onCreate(savedInstanceState)
- binding.viewModel = viewModel
- getLatestVersion()
- initUpdateBtnClickListener()
- }
-
- private fun initUpdateBtnClickListener() {
- binding.btnForceUpdate.setOnClickListener {
- intentToPlayStore = Intent(
- Intent.ACTION_VIEW,
- Uri.parse(getString(R.string.force_update_store_link))
- )
- startActivity(intentToPlayStore)
- }
- }
-
- private fun getLatestVersion() {
- intent.getParcelable(LATEST_VERSION, Version::class.java)
- ?.let { viewModel.getLatestVersion(it) }
- }
-}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/forceUpdate/ForceUpdateViewModel.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/forceUpdate/ForceUpdateViewModel.kt
deleted file mode 100644
index 992bb827..00000000
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/forceUpdate/ForceUpdateViewModel.kt
+++ /dev/null
@@ -1,15 +0,0 @@
-package com.sopt.peekabookaos.presentation.forceUpdate
-
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MutableLiveData
-import androidx.lifecycle.ViewModel
-import com.sopt.peekabookaos.domain.entity.Version
-
-class ForceUpdateViewModel : ViewModel() {
- private val _latestVersion: MutableLiveData = MutableLiveData()
- val latestVersion: LiveData = _latestVersion
-
- fun getLatestVersion(version: Version) {
- _latestVersion.value = version
- }
-}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/forceUpdate/ForcedUpdateActivity.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/forceUpdate/ForcedUpdateActivity.kt
new file mode 100644
index 00000000..ad5acfad
--- /dev/null
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/forceUpdate/ForcedUpdateActivity.kt
@@ -0,0 +1,42 @@
+package com.sopt.peekabookaos.presentation.forceUpdate
+
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import androidx.activity.viewModels
+import com.sopt.peekabookaos.R
+import com.sopt.peekabookaos.databinding.ActivityForcedUpdateBinding
+import com.sopt.peekabookaos.domain.entity.UpdateInformation
+import com.sopt.peekabookaos.presentation.splash.SplashActivity.Companion.UPDATE_INFORMATION
+import com.sopt.peekabookaos.util.binding.BindingActivity
+import com.sopt.peekabookaos.util.extensions.getParcelable
+import com.sopt.peekabookaos.util.extensions.initBackPressedCallback
+import com.sopt.peekabookaos.util.extensions.setSingleOnClickListener
+
+class ForcedUpdateActivity :
+ BindingActivity(R.layout.activity_forced_update) {
+ private val viewModel by viewModels()
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ binding.viewModel = viewModel
+ initBackPressedCallback()
+ getUpdateInformation()
+ initUpdateBtnClickListener()
+ }
+
+ private fun initUpdateBtnClickListener() {
+ binding.btnForceUpdate.setSingleOnClickListener {
+ val intentToPlayStore = Intent(
+ Intent.ACTION_VIEW,
+ Uri.parse(getString(R.string.force_update_store_link))
+ )
+ startActivity(intentToPlayStore)
+ }
+ }
+
+ private fun getUpdateInformation() {
+ intent.getParcelable(UPDATE_INFORMATION, UpdateInformation::class.java)
+ ?.let { viewModel.setUpdateInformation(it) }
+ }
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/forceUpdate/ForcedUpdateViewModel.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/forceUpdate/ForcedUpdateViewModel.kt
new file mode 100644
index 00000000..23f17cfc
--- /dev/null
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/forceUpdate/ForcedUpdateViewModel.kt
@@ -0,0 +1,15 @@
+package com.sopt.peekabookaos.presentation.forceUpdate
+
+import androidx.lifecycle.ViewModel
+import com.sopt.peekabookaos.domain.entity.UpdateInformation
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.flow.update
+
+class ForcedUpdateViewModel : ViewModel() {
+ private val _updateInformation = MutableStateFlow(UpdateInformation())
+ val updateInformation = _updateInformation.asStateFlow()
+
+ fun setUpdateInformation(updateInformation: UpdateInformation) =
+ _updateInformation.update { updateInformation }
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/main/MainActivity.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/main/MainActivity.kt
index 219418a2..689b8ebc 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/main/MainActivity.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/main/MainActivity.kt
@@ -9,21 +9,20 @@ import androidx.navigation.fragment.NavHostFragment
import androidx.navigation.ui.setupWithNavController
import com.sopt.peekabookaos.R
import com.sopt.peekabookaos.databinding.ActivityMainBinding
-import com.sopt.peekabookaos.util.ToastMessageUtil
import com.sopt.peekabookaos.util.binding.BindingActivity
+import com.sopt.peekabookaos.util.extensions.initBackPressedCallback
import dagger.hilt.android.AndroidEntryPoint
import timber.log.Timber
-import kotlin.system.exitProcess
@AndroidEntryPoint
class MainActivity : BindingActivity(R.layout.activity_main) {
private val mainViewModel: MainViewModel by viewModels()
- private var onBackPressedTime = 0L
+
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding.vm = mainViewModel
initBottomNavigationView()
- initBackPressedCallback()
+ clickBackPressedButton()
}
private fun initBottomNavigationView() {
@@ -37,30 +36,14 @@ class MainActivity : BindingActivity(R.layout.activity_main
return navHostFragment.navController
}
- private fun initBackPressedCallback() {
+ private fun clickBackPressedButton() {
onBackPressedDispatcher.addCallback {
val fragmentId: Int? = findNavController(R.id.fcv_main).currentDestination?.id
fragmentId?.also { id ->
if (id == R.id.bookshelfFragment) {
- val curTime = System.currentTimeMillis()
- val gap = curTime - onBackPressedTime
- if (gap > WAITING_DEADLINE) {
- onBackPressedTime = curTime
- ToastMessageUtil.showToast(
- this@MainActivity,
- getString(R.string.finish_app_toast_msg)
- )
- return@addCallback
- }
- finishAffinity()
- System.runFinalization()
- exitProcess(0)
+ initBackPressedCallback()
}
} ?: Timber.e(getString(R.string.null_point_exception))
}
}
-
- companion object {
- private const val WAITING_DEADLINE = 2000L
- }
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/main/MainViewModel.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/main/MainViewModel.kt
index a9cc701b..b5366404 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/main/MainViewModel.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/main/MainViewModel.kt
@@ -1,16 +1,15 @@
package com.sopt.peekabookaos.presentation.main
import androidx.lifecycle.ViewModel
-import com.sopt.peekabookaos.domain.entity.SplashState
-import com.sopt.peekabookaos.domain.usecase.SetSplashStateUseCase
+import com.sopt.peekabookaos.domain.usecase.SetAccessToMainUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class MainViewModel @Inject constructor(
- setSplashStateUseCase: SetSplashStateUseCase
+ setAccessToMainUseCase: SetAccessToMainUseCase
) : ViewModel() {
init {
- setSplashStateUseCase(SplashState.MAIN)
+ setAccessToMainUseCase()
}
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/networkError/NetworkErrorActivity.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/networkError/NetworkErrorActivity.kt
index 99f452fc..d159084e 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/networkError/NetworkErrorActivity.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/networkError/NetworkErrorActivity.kt
@@ -2,24 +2,19 @@ package com.sopt.peekabookaos.presentation.networkError
import android.content.Intent
import android.os.Bundle
-import androidx.activity.addCallback
-import androidx.activity.viewModels
import com.sopt.peekabookaos.R
import com.sopt.peekabookaos.databinding.ActivityNetworkErrorBinding
-import com.sopt.peekabookaos.domain.entity.SplashState
-import com.sopt.peekabookaos.presentation.main.MainActivity
-import com.sopt.peekabookaos.presentation.onboarding.OnboardingActivity
+import com.sopt.peekabookaos.presentation.splash.SplashActivity
import com.sopt.peekabookaos.util.ToastMessageUtil
import com.sopt.peekabookaos.util.binding.BindingActivity
+import com.sopt.peekabookaos.util.extensions.activityOpenTransition
+import com.sopt.peekabookaos.util.extensions.initBackPressedCallback
import com.sopt.peekabookaos.util.extensions.isNetworkConnected
import dagger.hilt.android.AndroidEntryPoint
-import kotlin.system.exitProcess
@AndroidEntryPoint
class NetworkErrorActivity :
BindingActivity(R.layout.activity_network_error) {
- private val networkErrorViewModel: NetworkErrorViewModel by viewModels()
- private var onBackPressedTime = 0L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -27,33 +22,15 @@ class NetworkErrorActivity :
initBackPressedCallback()
}
- private fun initBackPressedCallback() {
- onBackPressedDispatcher.addCallback {
- if (System.currentTimeMillis() - onBackPressedTime >= WAITING_DEADLINE) {
- onBackPressedTime = System.currentTimeMillis()
- ToastMessageUtil.showToast(
- this@NetworkErrorActivity,
- getString(R.string.finish_app_toast_msg)
- )
- } else {
- finishAffinity()
- System.runFinalization()
- exitProcess(0)
- }
- }
- }
-
private fun checkNetworkConnect() {
binding.btnNetworkErrorRetry.setOnClickListener {
if (isNetworkConnected()) {
- when (networkErrorViewModel.getSplashState()) {
- SplashState.ONBOARDING -> startActivity(
- Intent(this, OnboardingActivity::class.java)
- )
- SplashState.MAIN -> startActivity(Intent(this, MainActivity::class.java))
- }
- overridePendingTransition(0, 0)
- finish()
+ startActivity(
+ Intent(this, SplashActivity::class.java)
+ .putExtra(LOCATION, NETWORK_ERROR)
+ )
+ activityOpenTransition(0, 0)
+ finishAffinity()
} else {
ToastMessageUtil.showToast(
this@NetworkErrorActivity,
@@ -64,6 +41,7 @@ class NetworkErrorActivity :
}
companion object {
- private const val WAITING_DEADLINE = 2000L
+ const val LOCATION = "location"
+ const val NETWORK_ERROR = "network error"
}
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/networkError/NetworkErrorViewModel.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/networkError/NetworkErrorViewModel.kt
deleted file mode 100644
index 94163f7d..00000000
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/networkError/NetworkErrorViewModel.kt
+++ /dev/null
@@ -1,14 +0,0 @@
-package com.sopt.peekabookaos.presentation.networkError
-
-import androidx.lifecycle.ViewModel
-import com.sopt.peekabookaos.domain.entity.SplashState
-import com.sopt.peekabookaos.domain.usecase.GetSplashStateUseCase
-import dagger.hilt.android.lifecycle.HiltViewModel
-import javax.inject.Inject
-
-@HiltViewModel
-class NetworkErrorViewModel @Inject constructor(
- private val getSplashStateUseCase: GetSplashStateUseCase
-) : ViewModel() {
- fun getSplashState(): SplashState = getSplashStateUseCase()
-}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/onboarding/OnboardingActivity.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/onboarding/OnboardingActivity.kt
index ca134360..8a2625b9 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/onboarding/OnboardingActivity.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/onboarding/OnboardingActivity.kt
@@ -2,22 +2,19 @@ package com.sopt.peekabookaos.presentation.onboarding
import android.content.Intent
import android.os.Bundle
-import androidx.activity.addCallback
import com.google.android.material.tabs.TabLayoutMediator
import com.sopt.peekabookaos.R
import com.sopt.peekabookaos.databinding.ActivityOnboardingBinding
import com.sopt.peekabookaos.domain.entity.Onboarding
import com.sopt.peekabookaos.presentation.login.LoginActivity
-import com.sopt.peekabookaos.util.ToastMessageUtil
import com.sopt.peekabookaos.util.binding.BindingActivity
+import com.sopt.peekabookaos.util.extensions.initBackPressedCallback
import com.sopt.peekabookaos.util.extensions.setSingleOnClickListener
-import kotlin.system.exitProcess
class OnboardingActivity :
BindingActivity(R.layout.activity_onboarding) {
private val onboardingAdapter: OnboardingAdapter?
get() = binding.vpOnboarding.adapter as? OnboardingAdapter
- private var onBackPressedTime = 0L
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -45,22 +42,6 @@ class OnboardingActivity :
}
}
- private fun initBackPressedCallback() {
- onBackPressedDispatcher.addCallback {
- if (System.currentTimeMillis() - onBackPressedTime >= WAITING_DEADLINE) {
- onBackPressedTime = System.currentTimeMillis()
- ToastMessageUtil.showToast(
- this@OnboardingActivity,
- getString(R.string.finish_app_toast_msg)
- )
- } else {
- finishAffinity()
- System.runFinalization()
- exitProcess(0)
- }
- }
- }
-
companion object {
private val onboardingList = listOf(
Onboarding(R.drawable.ic_onboarding_1, R.drawable.ic_onboarding_content_1),
@@ -68,6 +49,5 @@ class OnboardingActivity :
Onboarding(R.drawable.ic_onboarding_3, R.drawable.ic_onboarding_content_3),
Onboarding(R.drawable.ic_onboarding_4, R.drawable.ic_onboarding_content_4)
)
- private const val WAITING_DEADLINE = 2000L
}
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/pickModify/PickModifyViewModel.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/pickModify/PickModifyViewModel.kt
index 8958f1b5..04687acc 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/pickModify/PickModifyViewModel.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/pickModify/PickModifyViewModel.kt
@@ -30,7 +30,7 @@ class PickModifyViewModel @Inject constructor(
private val _overListState: MutableLiveData = MutableLiveData()
val overListState: LiveData = _overListState
- var preListState = _overListState.value
+ private var preListState = _overListState.value
private val _isGetPickServerStatus = MutableLiveData()
val isGetPickServerStatus: LiveData = _isGetPickServerStatus
@@ -38,7 +38,7 @@ class PickModifyViewModel @Inject constructor(
private val _isPatchPickServerStatus = MutableLiveData()
val isPatchPickServerStatus: LiveData = _isPatchPickServerStatus
- var selectItemIdList = arrayOfNulls(3)
+ private var selectItemIdList = arrayOfNulls(3)
init {
getPick()
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/recommendation/RecommendationFragment.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/recommendation/RecommendationFragment.kt
index 4b2e2564..7677891c 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/recommendation/RecommendationFragment.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/recommendation/RecommendationFragment.kt
@@ -51,16 +51,10 @@ class RecommendationFragment :
private fun initView() {
recommendationViewModel.initRecommendData(
requireNotNull(
- arguments?.getParcelableCompat(
- BookActivity.BOOK_INFO,
- Book::class.java
- )
+ arguments?.getParcelableCompat(BookActivity.BOOK_INFO) ?: Book()
),
requireNotNull(
- arguments?.getParcelableCompat(
- BookActivity.FRIEND_INFO,
- User::class.java
- )
+ arguments?.getParcelableCompat(BookActivity.FRIEND_INFO) ?: User()
)
)
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/search/user/SearchUserActivity.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/search/user/SearchUserActivity.kt
index a84fbe0d..2381296e 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/search/user/SearchUserActivity.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/search/user/SearchUserActivity.kt
@@ -26,7 +26,7 @@ class SearchUserActivity :
initEditTextClearFocus()
initKeyboardDoneClickListener()
initCloseBtnClickListener()
- collectSearchState()
+ collectUiEvent()
}
private fun initSearchFocus() {
@@ -65,7 +65,7 @@ class SearchUserActivity :
}
}
- private fun collectSearchState() {
+ private fun collectUiEvent() {
repeatOnStarted {
searchUserViewModel.uiEvent.collect { uiEvent ->
when (uiEvent) {
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/socialLogin/SocialLoginFragment.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/socialLogin/SocialLoginFragment.kt
index 27a51162..dc2d72f2 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/socialLogin/SocialLoginFragment.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/socialLogin/SocialLoginFragment.kt
@@ -5,29 +5,25 @@ import android.content.Intent.ACTION_VIEW
import android.net.Uri
import android.os.Bundle
import android.view.View
-import androidx.activity.OnBackPressedCallback
-import androidx.core.app.ActivityCompat.finishAffinity
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import com.sopt.peekabookaos.R
import com.sopt.peekabookaos.data.service.KakaoLoginService
import com.sopt.peekabookaos.databinding.FragmentSocialLoginBinding
import com.sopt.peekabookaos.presentation.main.MainActivity
-import com.sopt.peekabookaos.util.ToastMessageUtil
import com.sopt.peekabookaos.util.binding.BindingFragment
+import com.sopt.peekabookaos.util.extensions.initBackPressedCallback
import com.sopt.peekabookaos.util.extensions.repeatOnStarted
import com.sopt.peekabookaos.util.extensions.setSingleOnClickListener
import dagger.hilt.android.AndroidEntryPoint
import timber.log.Timber
import javax.inject.Inject
-import kotlin.system.exitProcess
@AndroidEntryPoint
class SocialLoginFragment :
BindingFragment(R.layout.fragment_social_login) {
@Inject
lateinit var kakaoLoginService: KakaoLoginService
- private var onBackPressedTime = 0L
private val socialLoginViewModel: SocialLoginViewModel by viewModels()
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@@ -40,29 +36,6 @@ class SocialLoginFragment :
collectIsSignedUp()
}
- private fun initBackPressedCallback() {
- requireActivity().onBackPressedDispatcher.addCallback(
- viewLifecycleOwner,
- object : OnBackPressedCallback(true) {
- override fun handleOnBackPressed() {
- val curTime = System.currentTimeMillis()
- val gap = curTime - onBackPressedTime
- if (gap > WAITING_DEADLINE) {
- onBackPressedTime = curTime
- ToastMessageUtil.showToast(
- requireContext(),
- getString(R.string.finish_app_toast_msg)
- )
- return
- }
- finishAffinity(requireActivity())
- System.runFinalization()
- exitProcess(0)
- }
- }
- )
- }
-
private fun initKakaoLoginBtnClickListener() {
binding.btnSocialLoginKakao.setSingleOnClickListener {
startKakaoLogin()
@@ -119,8 +92,4 @@ class SocialLoginFragment :
}
}
}
-
- companion object {
- private const val WAITING_DEADLINE = 2000L
- }
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/splash/SplashActivity.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/splash/SplashActivity.kt
index e28ccd88..3d3b7706 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/splash/SplashActivity.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/splash/SplashActivity.kt
@@ -2,20 +2,22 @@ package com.sopt.peekabookaos.presentation.splash
import android.annotation.SuppressLint
import android.content.Intent
-import android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK
-import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import androidx.activity.viewModels
import com.sopt.peekabookaos.R
import com.sopt.peekabookaos.databinding.ActivitySplashBinding
-import com.sopt.peekabookaos.domain.entity.SplashState
-import com.sopt.peekabookaos.domain.entity.VersionState
-import com.sopt.peekabookaos.presentation.forceUpdate.ForceUpdateActivity
+import com.sopt.peekabookaos.domain.entity.SplashUiState
+import com.sopt.peekabookaos.domain.entity.UpdateInformation
+import com.sopt.peekabookaos.presentation.forceUpdate.ForcedUpdateActivity
import com.sopt.peekabookaos.presentation.main.MainActivity
+import com.sopt.peekabookaos.presentation.networkError.NetworkErrorActivity.Companion.LOCATION
+import com.sopt.peekabookaos.presentation.networkError.NetworkErrorActivity.Companion.NETWORK_ERROR
import com.sopt.peekabookaos.presentation.onboarding.OnboardingActivity
import com.sopt.peekabookaos.util.binding.BindingActivity
+import com.sopt.peekabookaos.util.extensions.activityOpenTransition
+import com.sopt.peekabookaos.util.extensions.repeatOnStarted
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
@@ -25,42 +27,63 @@ class SplashActivity : BindingActivity(R.layout.activity_
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
- binding.lottieSplash.playAnimation()
- Handler(Looper.getMainLooper()).postDelayed({ initIsForceUpdateObserver() }, DURATION)
+ checkLocation()
}
- private fun initIsForceUpdateObserver() {
- splashViewModel.latestVersion.observe(this) {
- splashViewModel.checkUpdateVersion()
- checkVersionUpdate()
+ private fun checkLocation() {
+ when (intent.getStringExtra(LOCATION)) {
+ NETWORK_ERROR -> {
+ collectUiState()
+ }
+
+ else -> {
+ binding.lottieSplash.playAnimation()
+ Handler(Looper.getMainLooper()).postDelayed({ collectUiState() }, DURATION)
+ }
}
}
- private fun checkVersionUpdate() {
- when (splashViewModel.checkUpdateVersion()) {
- VersionState.LATEST -> checkSplashState()
- VersionState.OUTDATED -> {
- val intentToForceUpdate = Intent(this, ForceUpdateActivity::class.java).apply {
- putExtra(LATEST_VERSION, splashViewModel.latestVersion.value)
- addFlags(FLAG_ACTIVITY_CLEAR_TASK or FLAG_ACTIVITY_NEW_TASK)
+ private fun collectUiState() {
+ repeatOnStarted {
+ splashViewModel.uiState.collect { uiState ->
+ when (uiState) {
+ is SplashUiState.Idle -> {}
+ is SplashUiState.Error -> {}
+ is SplashUiState.ShowSplash -> {}
+ is SplashUiState.CanStartOnboarding -> startOnboardingActivity()
+ is SplashUiState.CanStartMain -> startMainActivity()
+ is SplashUiState.ForceUpdate -> {
+ startForcedUpdateActivity(uiState.data)
+ }
}
- startActivity(Intent(intentToForceUpdate))
- finish()
}
}
}
- private fun checkSplashState() {
- when (splashViewModel.getSplashState()) {
- SplashState.ONBOARDING -> startActivity(Intent(this, OnboardingActivity::class.java))
- SplashState.MAIN -> startActivity(Intent(this, MainActivity::class.java))
+ private fun startForcedUpdateActivity(updateInformation: UpdateInformation) {
+ Intent(this, ForcedUpdateActivity::class.java).apply {
+ putExtra(UPDATE_INFORMATION, updateInformation)
+ }.also {
+ startActivityWithAnimation(it)
}
- overridePendingTransition(0, 0)
- finish()
+ }
+
+ private fun startOnboardingActivity() {
+ Intent(this, OnboardingActivity::class.java).also { startActivityWithAnimation(it) }
+ }
+
+ private fun startMainActivity() {
+ Intent(this, MainActivity::class.java).also { startActivityWithAnimation(it) }
+ }
+
+ private fun startActivityWithAnimation(intent: Intent) {
+ startActivity(intent)
+ activityOpenTransition(0, 0)
+ finishAffinity()
}
companion object {
- private const val DURATION: Long = 2000
- const val LATEST_VERSION = "latest version"
+ private const val DURATION: Long = 2000L
+ const val UPDATE_INFORMATION = "update information"
}
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/splash/SplashViewModel.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/splash/SplashViewModel.kt
index 268ae523..c7a86a13 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/splash/SplashViewModel.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/splash/SplashViewModel.kt
@@ -1,65 +1,53 @@
package com.sopt.peekabookaos.presentation.splash
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.sopt.peekabookaos.BuildConfig
-import com.sopt.peekabookaos.domain.entity.SplashState
-import com.sopt.peekabookaos.domain.entity.Version
-import com.sopt.peekabookaos.domain.entity.VersionDetail
-import com.sopt.peekabookaos.domain.entity.VersionState
-import com.sopt.peekabookaos.domain.usecase.GetSplashStateUseCase
-import com.sopt.peekabookaos.domain.usecase.GetVersionUseCase
+import com.sopt.peekabookaos.domain.entity.ForcedUpdate
+import com.sopt.peekabookaos.domain.entity.SplashUiState
+import com.sopt.peekabookaos.domain.usecase.GetSignedUpUseCase
+import com.sopt.peekabookaos.domain.usecase.HasUpdateVersionCheckUseCase
import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import timber.log.Timber
import javax.inject.Inject
@HiltViewModel
class SplashViewModel @Inject constructor(
- private val getSplashStateUseCase: GetSplashStateUseCase,
- private val getVersionUseCase: GetVersionUseCase
+ private val hasUpdateVersionCheckUseCase: HasUpdateVersionCheckUseCase,
+ private val getSignedUpUseCase: GetSignedUpUseCase
) : ViewModel() {
- private val _latestVersion: MutableLiveData = MutableLiveData()
- val latestVersion: LiveData = _latestVersion
- private lateinit var latestVersionDetail: VersionDetail
- private lateinit var appVersionDetail: VersionDetail
+ private val _uiState = MutableStateFlow(SplashUiState.Idle)
+ val uiState = _uiState.asSharedFlow()
init {
- getVersion()
+ checkHasUpdate()
}
- fun getSplashState(): SplashState = getSplashStateUseCase()
+ private fun isSignedUp(): Boolean = getSignedUpUseCase()
- fun checkUpdateVersion(): VersionState {
- latestVersionDetail =
- spiltVersionToMajorMinor(requireNotNull(latestVersion.value?.androidForceVersion) { "version is null" })
- appVersionDetail = spiltVersionToMajorMinor(BuildConfig.VERSION_NAME)
- return if (appVersionDetail.major != latestVersionDetail.major || appVersionDetail.minor != latestVersionDetail.minor) VersionState.OUTDATED
- else VersionState.LATEST
- }
-
- private fun spiltVersionToMajorMinor(versionName: String): VersionDetail {
- val versionSpiltList = versionName.split(".")
- val major = versionSpiltList[0]
- val minor = versionSpiltList[1]
- return VersionDetail(major, minor)
- }
+ private fun checkHasUpdate() = viewModelScope.launch {
+ _uiState.emit(SplashUiState.Idle)
+ hasUpdateVersionCheckUseCase(BuildConfig.VERSION_NAME)
+ .onSuccess { update ->
+ when (update) {
+ is ForcedUpdate.None -> {
+ if (isSignedUp()) {
+ _uiState.emit(SplashUiState.CanStartMain)
+ } else {
+ _uiState.emit(SplashUiState.CanStartOnboarding)
+ }
+ }
- private fun getVersion() {
- viewModelScope.launch {
- getVersionUseCase()
- .onSuccess { response ->
- _latestVersion.value = Version(
- response.imageUrl,
- response.androidForceVersion,
- response.versionText
- )
- }
- .onFailure { throwable ->
- Timber.e("$throwable")
+ is ForcedUpdate.Need -> {
+ _uiState.emit(SplashUiState.ForceUpdate(update.updateInformation))
+ }
}
- }
+ }.onFailure { throwable ->
+ _uiState.emit(SplashUiState.Error)
+ Timber.e("$throwable")
+ }
}
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/userInput/UserInputViewModel.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/userInput/UserInputViewModel.kt
index a61ddd68..ea446ca5 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/userInput/UserInputViewModel.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/userInput/UserInputViewModel.kt
@@ -68,13 +68,14 @@ class UserInputViewModel @Inject constructor(
fun getNickNameState() {
viewModelScope.launch {
- postDuplicateUseCase(requireNotNull(nickname.value)).onSuccess { check ->
- _isNickname.value = (check == 1)
- updateNicknameMessage(true)
- updateDuplicateButtonState(requireNotNull(_isNickname.value))
- }.onFailure { throwable ->
- Timber.e("$throwable")
- }
+ postDuplicateUseCase(requireNotNull(nickname.value))
+ .onSuccess { check ->
+ _isNickname.value = (check == 1)
+ updateNicknameMessage(true)
+ updateDuplicateButtonState(requireNotNull(_isNickname.value))
+ }.onFailure { throwable ->
+ Timber.e("$throwable")
+ }
}
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/presentation/withdraw/WithdrawViewModel.kt b/app/src/main/java/com/sopt/peekabookaos/presentation/withdraw/WithdrawViewModel.kt
index 6397e0de..46c4cc96 100644
--- a/app/src/main/java/com/sopt/peekabookaos/presentation/withdraw/WithdrawViewModel.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/presentation/withdraw/WithdrawViewModel.kt
@@ -2,10 +2,8 @@ package com.sopt.peekabookaos.presentation.withdraw
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import com.sopt.peekabookaos.domain.entity.SplashState
import com.sopt.peekabookaos.domain.usecase.ClearLocalPrefUseCase
import com.sopt.peekabookaos.domain.usecase.DeleteUserUseCase
-import com.sopt.peekabookaos.domain.usecase.SetSplashStateUseCase
import com.sopt.peekabookaos.util.UiEvent
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableSharedFlow
@@ -17,8 +15,7 @@ import javax.inject.Inject
@HiltViewModel
class WithdrawViewModel @Inject constructor(
private val deleteUserUseCase: DeleteUserUseCase,
- private val clearLocalPrefUseCase: ClearLocalPrefUseCase,
- private val setSplashStateUseCase: SetSplashStateUseCase
+ private val clearLocalPrefUseCase: ClearLocalPrefUseCase
) : ViewModel() {
private val _uiEvent = MutableSharedFlow()
val uiEvent = _uiEvent.asSharedFlow()
@@ -30,7 +27,6 @@ class WithdrawViewModel @Inject constructor(
.onSuccess {
_uiEvent.emit(UiEvent.SUCCESS)
clearLocalPrefUseCase()
- setSplashStateUseCase(SplashState.ONBOARDING)
}.onFailure { throwable ->
_uiEvent.emit(UiEvent.ERROR)
Timber.e("$throwable")
diff --git a/app/src/main/java/com/sopt/peekabookaos/util/ImageUtil.kt b/app/src/main/java/com/sopt/peekabookaos/util/ImageUtil.kt
index 6359f8df..9eaf5dc2 100644
--- a/app/src/main/java/com/sopt/peekabookaos/util/ImageUtil.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/util/ImageUtil.kt
@@ -7,9 +7,7 @@ import android.graphics.BitmapFactory
import android.graphics.Matrix
import android.media.ExifInterface
import android.net.Uri
-import android.os.Build
import android.provider.MediaStore
-import androidx.annotation.RequiresApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.ByteArrayOutputStream
@@ -38,7 +36,6 @@ object ImageUtil {
return Uri.parse(path)
}
- @RequiresApi(Build.VERSION_CODES.N)
fun getOrientationOfImage(uri: Uri, bitmap: Bitmap, cr: ContentResolver): Bitmap {
val inputStream = cr.openInputStream(uri)
val matrix = Matrix()
diff --git a/app/src/main/java/com/sopt/peekabookaos/util/binding/BindingAdapter.kt b/app/src/main/java/com/sopt/peekabookaos/util/binding/BindingAdapter.kt
index 5e4d672e..828c0001 100644
--- a/app/src/main/java/com/sopt/peekabookaos/util/binding/BindingAdapter.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/util/binding/BindingAdapter.kt
@@ -4,7 +4,9 @@ import android.widget.ImageView
import android.widget.TextView
import androidx.core.content.ContextCompat
import androidx.databinding.BindingAdapter
-import com.bumptech.glide.Glide
+import coil.imageLoader
+import coil.request.ImageRequest
+import coil.transform.CircleCropTransformation
import com.sopt.peekabookaos.R
object BindingAdapter {
@@ -12,9 +14,11 @@ object BindingAdapter {
@BindingAdapter("setImage")
fun ImageView.setImage(imgUrl: String?) {
this.let {
- Glide.with(context)
- .load(imgUrl)
- .into(this)
+ val request = ImageRequest.Builder(context)
+ .data(imgUrl)
+ .target(this)
+ .build()
+ context.imageLoader.enqueue(request)
}
}
@@ -22,15 +26,13 @@ object BindingAdapter {
@BindingAdapter("setCircleImage")
fun ImageView.setCircleImage(imgUrl: String?) {
this.let {
- Glide.with(context)
- .load(imgUrl)
- .apply {
- if (imgUrl == null) {
- placeholder(R.drawable.ic_profile_default)
- }
- }
- .circleCrop()
- .into(this)
+ val request = ImageRequest.Builder(context)
+ .data(imgUrl)
+ .target(this)
+ .transformations(CircleCropTransformation())
+ .fallback(R.drawable.ic_profile_default)
+ .build()
+ context.imageLoader.enqueue(request)
}
}
@@ -66,8 +68,8 @@ object BindingAdapter {
}
@JvmStatic
- @BindingAdapter("setImageResource")
- fun ImageView.setImageResource(resId: Int) {
+ @BindingAdapter("imageResource")
+ fun ImageView.setAppImageResource(resId: Int) {
setImageResource(resId)
}
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/util/dialog/WarningDialogFragment.kt b/app/src/main/java/com/sopt/peekabookaos/util/dialog/WarningDialogFragment.kt
index 0e58c2d9..f86e107b 100644
--- a/app/src/main/java/com/sopt/peekabookaos/util/dialog/WarningDialogFragment.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/util/dialog/WarningDialogFragment.kt
@@ -7,6 +7,8 @@ import android.view.ViewGroup
import androidx.fragment.app.DialogFragment
import com.sopt.peekabookaos.R
import com.sopt.peekabookaos.databinding.DialogWarningBinding
+import com.sopt.peekabookaos.util.extensions.getParcelableCompat
+import com.sopt.peekabookaos.util.extensions.getSerializableCompat
import com.sopt.peekabookaos.util.extensions.initLayout
import com.sopt.peekabookaos.util.extensions.setSingleOnClickListener
import timber.log.Timber
@@ -34,17 +36,20 @@ class WarningDialogFragment : DialogFragment() {
}
private fun initWarningDialogContent() {
- val warningType = arguments?.get(WARNING_TYPE)
+ val warningType = arguments?.getSerializableCompat(WARNING_TYPE) as? WarningType
?: Timber.e(getString(R.string.null_point_exception_warning_dialog_argument))
val follower = arguments?.getString(FOLLOWER) ?: DEFAULT
with(binding) {
warning = when (warningType as WarningType) {
WarningType.WARNING_RECOMMEND ->
WarningDialogContent().getWarningRecommendBook(requireContext(), follower)
+
WarningType.WARNING_DELETE_BOOK ->
WarningDialogContent().getWarningDeleteBook(requireContext())
+
WarningType.WARNING_DELETE_FOLLOWER ->
WarningDialogContent().getWarningDeleteFollow(requireContext(), follower)
+
WarningType.WARNING_UNFOLLOW ->
WarningDialogContent().getWarningUnfollow(requireContext(), follower)
}
@@ -59,7 +64,7 @@ class WarningDialogFragment : DialogFragment() {
private fun initConfirmClickListener() {
binding.btnWarningDialogConfirm.setSingleOnClickListener {
- arguments?.getParcelable(CONFIRM_ACTION)
+ arguments?.getParcelableCompat(CONFIRM_ACTION)
?.onConfirmClick()
?: Timber.e(getString(R.string.null_point_exception_warning_dialog_argument))
dismiss()
diff --git a/app/src/main/java/com/sopt/peekabookaos/util/extensions/ActivityExt.kt b/app/src/main/java/com/sopt/peekabookaos/util/extensions/ActivityExt.kt
index 8e44f653..058c43f1 100644
--- a/app/src/main/java/com/sopt/peekabookaos/util/extensions/ActivityExt.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/util/extensions/ActivityExt.kt
@@ -1,12 +1,44 @@
package com.sopt.peekabookaos.util.extensions
import android.app.Activity
+import android.app.Activity.OVERRIDE_TRANSITION_CLOSE
+import android.app.Activity.OVERRIDE_TRANSITION_OPEN
import android.os.Build
+import androidx.activity.addCallback
+import androidx.appcompat.app.AppCompatActivity
+import com.sopt.peekabookaos.R
+import com.sopt.peekabookaos.util.ToastMessageUtil.showToast
+import kotlin.system.exitProcess
-fun Activity.activityTransition(transitionType: Int, enterAnim: Int, exitAnim: Int) {
+fun Activity.activityOpenTransition(enterAnim: Int, exitAnim: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
- overrideActivityTransition(transitionType, enterAnim, exitAnim)
+ overrideActivityTransition(OVERRIDE_TRANSITION_OPEN, enterAnim, exitAnim)
} else {
+ @Suppress("DEPRECATION")
overridePendingTransition(enterAnim, exitAnim)
}
}
+
+fun Activity.activityCloseTransition(enterAnim: Int, exitAnim: Int) {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
+ overrideActivityTransition(OVERRIDE_TRANSITION_CLOSE, enterAnim, exitAnim)
+ } else {
+ @Suppress("DEPRECATION")
+ overridePendingTransition(enterAnim, exitAnim)
+ }
+}
+
+fun AppCompatActivity.initBackPressedCallback() {
+ var onBackPressedTime = 0L
+ val deadline = 2000L
+ onBackPressedDispatcher.addCallback(this) {
+ if (System.currentTimeMillis() - onBackPressedTime >= deadline) {
+ onBackPressedTime = System.currentTimeMillis()
+ showToast(this@initBackPressedCallback, getString(R.string.finish_app_toast_msg))
+ } else {
+ this@initBackPressedCallback.finishAffinity()
+ System.runFinalization()
+ exitProcess(0)
+ }
+ }
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/util/extensions/BundleExt.kt b/app/src/main/java/com/sopt/peekabookaos/util/extensions/BundleExt.kt
index 68ef973b..e827ca5c 100644
--- a/app/src/main/java/com/sopt/peekabookaos/util/extensions/BundleExt.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/util/extensions/BundleExt.kt
@@ -2,11 +2,23 @@ package com.sopt.peekabookaos.util.extensions
import android.os.Build
import android.os.Bundle
+import android.os.Parcelable
+import java.io.Serializable
-fun Bundle.getParcelableCompat(name: String, clazz: Class): T? {
+inline fun Bundle.getParcelableCompat(key: String): T? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- getParcelable(name, clazz)
+ getParcelable(key, T::class.java)
} else {
- getParcelable(name)
+ @Suppress("DEPRECATION")
+ getParcelable(key) as? T
+ }
+}
+
+inline fun Bundle.getSerializableCompat(key: String): T? {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ getSerializable(key, T::class.java)
+ } else {
+ @Suppress("DEPRECATION")
+ getSerializable(key) as? T
}
}
diff --git a/app/src/main/java/com/sopt/peekabookaos/util/extensions/ContextExt.kt b/app/src/main/java/com/sopt/peekabookaos/util/extensions/ContextExt.kt
index 916bfc52..7acaa065 100644
--- a/app/src/main/java/com/sopt/peekabookaos/util/extensions/ContextExt.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/util/extensions/ContextExt.kt
@@ -3,7 +3,12 @@ package com.sopt.peekabookaos.util.extensions
import android.content.Context
import android.net.ConnectivityManager
import android.net.NetworkCapabilities
+import android.os.Build
+import android.util.DisplayMetrics
+import android.util.Size
import android.view.View
+import android.view.WindowInsets
+import android.view.WindowManager
import com.sopt.peekabookaos.util.OnSingleClickListener
fun View.setSingleOnClickListener(onSingleClick: (View) -> Unit) {
@@ -15,10 +20,39 @@ fun Context.isNetworkConnected(): Boolean {
val cm = this.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val capabilities = cm.getNetworkCapabilities(cm.activeNetwork)
if (capabilities != null) {
- isConnected =
- capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI) || capabilities.hasTransport(
- NetworkCapabilities.TRANSPORT_CELLULAR
- )
+ isConnected = isConnectedToWiFi(capabilities) || isConnectedToCellular(capabilities)
}
return isConnected
}
+
+private fun isConnectedToWiFi(capabilities: NetworkCapabilities): Boolean {
+ return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
+}
+
+private fun isConnectedToCellular(capabilities: NetworkCapabilities): Boolean {
+ return capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)
+}
+
+fun Context.getScreenSize(): Pair {
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
+ val metrics = this.getSystemService(WindowManager::class.java).currentWindowMetrics
+ val windowInsets = metrics.windowInsets
+
+ val insets = windowInsets.getInsetsIgnoringVisibility(
+ WindowInsets.Type.systemBars() or WindowInsets.Type.displayCutout()
+ )
+ val insetsWidth = insets.right + insets.left
+ val insetsHeight = insets.top + insets.bottom
+
+ val legacySize = Size(
+ metrics.bounds.width() - insetsWidth,
+ metrics.bounds.height() - insetsHeight
+ )
+ Pair(legacySize.width, legacySize.height)
+ } else {
+ val metrics = DisplayMetrics()
+ @Suppress("DEPRECATION")
+ this.getSystemService(WindowManager::class.java).defaultDisplay.getRealMetrics(metrics)
+ Pair(metrics.widthPixels, metrics.heightPixels)
+ }
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/util/extensions/FragmentExt.kt b/app/src/main/java/com/sopt/peekabookaos/util/extensions/FragmentExt.kt
index bac732bb..ac182e69 100644
--- a/app/src/main/java/com/sopt/peekabookaos/util/extensions/FragmentExt.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/util/extensions/FragmentExt.kt
@@ -1,10 +1,39 @@
package com.sopt.peekabookaos.util.extensions
import android.os.Bundle
+import androidx.activity.OnBackPressedCallback
import androidx.fragment.app.Fragment
+import com.sopt.peekabookaos.R
+import com.sopt.peekabookaos.util.ToastMessageUtil
+import kotlin.system.exitProcess
inline fun T.withArgs(argsBuilder: Bundle.() -> Unit): T {
return this.apply {
arguments = Bundle().apply(argsBuilder)
}
}
+
+fun Fragment.initBackPressedCallback() {
+ var onBackPressedTime = 0L
+ val deadline = 2000L
+ requireActivity().onBackPressedDispatcher.addCallback(
+ viewLifecycleOwner,
+ object : OnBackPressedCallback(true) {
+ override fun handleOnBackPressed() {
+ val curTime = System.currentTimeMillis()
+ val gap = curTime - onBackPressedTime
+ if (gap > deadline) {
+ onBackPressedTime = curTime
+ ToastMessageUtil.showToast(
+ requireContext(),
+ getString(R.string.finish_app_toast_msg)
+ )
+ } else {
+ requireActivity().finishAffinity()
+ System.runFinalization()
+ exitProcess(0)
+ }
+ }
+ }
+ )
+}
diff --git a/app/src/main/java/com/sopt/peekabookaos/util/extensions/IntentExt.kt b/app/src/main/java/com/sopt/peekabookaos/util/extensions/IntentExt.kt
index ea7e0232..ec9bbbe9 100644
--- a/app/src/main/java/com/sopt/peekabookaos/util/extensions/IntentExt.kt
+++ b/app/src/main/java/com/sopt/peekabookaos/util/extensions/IntentExt.kt
@@ -7,6 +7,7 @@ fun Intent.getParcelable(name: String, clazz: Class): T? {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
getParcelableExtra(name, clazz)
} else {
+ @Suppress("DEPRECATION")
getParcelableExtra(name)
}
}
diff --git a/app/src/main/res/layout/activity_force_update.xml b/app/src/main/res/layout/activity_forced_update.xml
similarity index 95%
rename from app/src/main/res/layout/activity_force_update.xml
rename to app/src/main/res/layout/activity_forced_update.xml
index 666f325e..baead1c9 100644
--- a/app/src/main/res/layout/activity_force_update.xml
+++ b/app/src/main/res/layout/activity_forced_update.xml
@@ -7,14 +7,14 @@
+ type="com.sopt.peekabookaos.presentation.forceUpdate.ForcedUpdateViewModel" />
+ tools:context=".presentation.forceUpdate.ForcedUpdateActivity">