From 7e6952868cb5a10420b827699dbc2700c8d85821 Mon Sep 17 00:00:00 2001 From: chanu Date: Sat, 17 Aug 2024 00:17:59 +0900 Subject: [PATCH 01/12] =?UTF-8?q?#22=20[setting]=20:=20datastore=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=83=9D=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/datastore/.gitignore | 1 + core/datastore/build.gradle.kts | 12 ++++++++++++ core/datastore/src/main/AndroidManifest.xml | 4 ++++ settings.gradle.kts | 1 + 4 files changed, 18 insertions(+) create mode 100644 core/datastore/.gitignore create mode 100644 core/datastore/build.gradle.kts create mode 100644 core/datastore/src/main/AndroidManifest.xml diff --git a/core/datastore/.gitignore b/core/datastore/.gitignore new file mode 100644 index 00000000..42afabfd --- /dev/null +++ b/core/datastore/.gitignore @@ -0,0 +1 @@ +/build \ No newline at end of file diff --git a/core/datastore/build.gradle.kts b/core/datastore/build.gradle.kts new file mode 100644 index 00000000..64025462 --- /dev/null +++ b/core/datastore/build.gradle.kts @@ -0,0 +1,12 @@ +plugins { + alias(libs.plugins.android.library) + id("com.teamwable.wable.kotlin") + id("com.teamwable.wable.hilt") +} + +android { + namespace = "com.teamwable.datastore" +} + +dependencies { +} diff --git a/core/datastore/src/main/AndroidManifest.xml b/core/datastore/src/main/AndroidManifest.xml new file mode 100644 index 00000000..e1000761 --- /dev/null +++ b/core/datastore/src/main/AndroidManifest.xml @@ -0,0 +1,4 @@ + + + + diff --git a/settings.gradle.kts b/settings.gradle.kts index e1350c6f..22fb3afd 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -37,3 +37,4 @@ include(":feature:profile") include(":feature:auth") include(":feature:main-compose") include(":core:designsystem") +include(":core:datastore") From 33800fbaddd29cd268e57a2a48a60a645918979c Mon Sep 17 00:00:00 2001 From: chanu Date: Sat, 17 Aug 2024 00:18:13 +0900 Subject: [PATCH 02/12] =?UTF-8?q?#22=20[setting]=20:=20datastore=20?= =?UTF-8?q?=EC=9D=98=EC=A1=B4=20=EA=B7=B8=EB=9E=98=ED=94=84=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- core/data/build.gradle.kts | 3 ++- core/network/build.gradle.kts | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/core/data/build.gradle.kts b/core/data/build.gradle.kts index 2588b378..5c615df1 100644 --- a/core/data/build.gradle.kts +++ b/core/data/build.gradle.kts @@ -11,4 +11,5 @@ android { dependencies { implementation(project(":core:network")) implementation(project(":core:model")) -} \ No newline at end of file + implementation(project(":core:datastore")) +} diff --git a/core/network/build.gradle.kts b/core/network/build.gradle.kts index a1c87a44..e1e0117e 100644 --- a/core/network/build.gradle.kts +++ b/core/network/build.gradle.kts @@ -27,9 +27,9 @@ android { buildFeatures.apply { buildConfig = true } - } dependencies { implementation(project(":core:model")) + implementation(project(":core:datastore")) } From c2e55e8b73a471288b2f6f340047d9452bcf2eae Mon Sep 17 00:00:00 2001 From: chanu Date: Sat, 17 Aug 2024 00:24:40 +0900 Subject: [PATCH 03/12] =?UTF-8?q?#22=20[setting]=20:=20datastore=20?= =?UTF-8?q?=EB=AA=A8=EB=93=88=20=EC=9D=98=EC=A1=B4=EC=84=B1=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 --- core/datastore/build.gradle.kts | 1 + gradle/libs.versions.toml | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/core/datastore/build.gradle.kts b/core/datastore/build.gradle.kts index 64025462..957ec1a9 100644 --- a/core/datastore/build.gradle.kts +++ b/core/datastore/build.gradle.kts @@ -9,4 +9,5 @@ android { } dependencies { + implementation(libs.bundles.datastore) } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d105b81e..9926065a 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -23,6 +23,7 @@ paging = "3.3.1" constraintlayout = "2.1.4" navigationFragmentKtx = "2.7.7" navigationUiKtx = "2.7.7" +androidx-datastore = "1.1.1" # material + google material = "1.12.0" @@ -152,6 +153,10 @@ androidx-lifecycle-viewModelCompose = { group = "androidx.lifecycle", name = "li androidx-activity-compose = { group = "androidx.activity", name = "activity-compose", version.ref = "activity" } androidx-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "hiltNavigationComposeVersion" } +# datastore +androidx-datastore-core = { group = "androidx.datastore", name = "datastore", version.ref = "androidx-datastore" } +androidx-datastore-preferences = { group = "androidx.datastore", name = "datastore-preferences", version.ref = "androidx-datastore" } + [plugins] android-application = { id = "com.android.application", version.ref = "agp" } kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" } @@ -167,3 +172,4 @@ jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "jetbrai lifecycle = ["lifecycle", "lifecycle-viewmodel", "lifecycle-livedata"] retrofit = ["retrofit", "retrofit-kotlin-serialization-converter", "okhttp", "okhttp-logging-interceptor"] androidx-android-test = ["androidx-junit", "androidx-espresso-core"] +datastore = ["androidx-datastore-core", "androidx-datastore-preferences"] From 06a9d7ad5c1788c3b33ec07c47b0e842c7469cfd Mon Sep 17 00:00:00 2001 From: chanu Date: Sat, 17 Aug 2024 02:42:23 +0900 Subject: [PATCH 04/12] =?UTF-8?q?#22=20[setting]=20:=20wable=20preference?= =?UTF-8?q?=20datasource=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datasource/WablePreferencesDataSource.kt | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 core/datastore/src/main/java/com/teamwable/datastore/datasource/WablePreferencesDataSource.kt diff --git a/core/datastore/src/main/java/com/teamwable/datastore/datasource/WablePreferencesDataSource.kt b/core/datastore/src/main/java/com/teamwable/datastore/datasource/WablePreferencesDataSource.kt new file mode 100644 index 00000000..26f77e5e --- /dev/null +++ b/core/datastore/src/main/java/com/teamwable/datastore/datasource/WablePreferencesDataSource.kt @@ -0,0 +1,34 @@ +package com.teamwable.datastore.datasource + +import kotlinx.coroutines.flow.Flow + +interface WablePreferencesDataSource { + val accessToken: Flow + val refreshToken: Flow + val autoLogin: Flow + val nickname: Flow + val memberId: Flow + val memberProfileUrl: Flow + val isNewUser: Flow + val isPushAlarmAllowed: Flow + + suspend fun updateAccessToken(accessToken: String) + + suspend fun updateRefreshToken(refreshToken: String) + + suspend fun updateAutoLogin(autoLogin: Boolean) + + suspend fun updateNickname(name: String) + + suspend fun updateMemberId(memberId: Int) + + suspend fun updateMemberProfileUrl(memberUrl: String) + + suspend fun updateIsNewUser(isNewUser: Boolean) + + suspend fun updateIsPushAlarmAllowed(isPushAlarmAllowed: Boolean) + + suspend fun clear() + + suspend fun clearForRefreshToken() +} From 07804f2da675e2507e8df06f173082d32a165047 Mon Sep 17 00:00:00 2001 From: chanu Date: Sat, 17 Aug 2024 02:43:09 +0900 Subject: [PATCH 05/12] =?UTF-8?q?#22=20[setting]=20:=20default=20datastore?= =?UTF-8?q?=20preference=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DefaultWablePreferenceDatasource.kt | 145 ++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 core/datastore/src/main/java/com/teamwable/datastore/datasource/DefaultWablePreferenceDatasource.kt diff --git a/core/datastore/src/main/java/com/teamwable/datastore/datasource/DefaultWablePreferenceDatasource.kt b/core/datastore/src/main/java/com/teamwable/datastore/datasource/DefaultWablePreferenceDatasource.kt new file mode 100644 index 00000000..bd3b69c8 --- /dev/null +++ b/core/datastore/src/main/java/com/teamwable/datastore/datasource/DefaultWablePreferenceDatasource.kt @@ -0,0 +1,145 @@ +package com.teamwable.datastore.datasource + +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.core.booleanPreferencesKey +import androidx.datastore.preferences.core.edit +import androidx.datastore.preferences.core.emptyPreferences +import androidx.datastore.preferences.core.intPreferencesKey +import androidx.datastore.preferences.core.stringPreferencesKey +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.FlowCollector +import kotlinx.coroutines.flow.catch +import kotlinx.coroutines.flow.map +import java.io.IOException +import javax.inject.Inject + +class DefaultWablePreferenceDatasource @Inject constructor( + private val dataStore: DataStore, +) : WablePreferencesDataSource { + private object PreferencesKeys { + val AccessToken = stringPreferencesKey("accessToken") + val RefreshToken = stringPreferencesKey("refreshToken") + val Nickname = stringPreferencesKey("nickname") + val AutoLogin = booleanPreferencesKey("autoLogin") + val MemberId = intPreferencesKey("memberId") + val MemberProfileUrl = stringPreferencesKey("memberProfileUrl") + val IsNewUser = booleanPreferencesKey("isNewUser") + val IsPushAlarmAllowed = booleanPreferencesKey("isPushAlarmAllowed") + } + + override val accessToken: Flow = dataStore.data + .catch { handleError(it) } + .map { preferences -> + preferences[PreferencesKeys.AccessToken].orEmpty() + } + + override val refreshToken: Flow = dataStore.data + .catch { handleError(it) } + .map { preferences -> + preferences[PreferencesKeys.RefreshToken].orEmpty() + } + + override val autoLogin: Flow = dataStore.data + .catch { handleError(it) } + .map { preferences -> + preferences[PreferencesKeys.AutoLogin] ?: false + } + + override val nickname: Flow = dataStore.data + .catch { handleError(it) } + .map { preferences -> + preferences[PreferencesKeys.Nickname].orEmpty() + } + + override val memberId: Flow = dataStore.data + .catch { handleError(it) } + .map { preferences -> + preferences[PreferencesKeys.MemberId] ?: -1 + } + + override var memberProfileUrl: Flow = dataStore.data + .catch { handleError(it) } + .map { preferences -> + preferences[PreferencesKeys.MemberProfileUrl].orEmpty() + } + + override var isNewUser: Flow = dataStore.data + .catch { handleError(it) } + .map { preferences -> + preferences[PreferencesKeys.IsNewUser] ?: false + } + + override var isPushAlarmAllowed: Flow = dataStore.data + .catch { handleError(it) } + .map { preferences -> + preferences[PreferencesKeys.IsPushAlarmAllowed] ?: false + } + + override suspend fun updateAccessToken(accessToken: String) { + dataStore.edit { preferences -> + preferences[PreferencesKeys.AccessToken] = accessToken + } + } + + override suspend fun updateRefreshToken(refreshToken: String) { + dataStore.edit { preferences -> + preferences[PreferencesKeys.RefreshToken] = refreshToken + } + } + + override suspend fun updateAutoLogin(autoLogin: Boolean) { + dataStore.edit { preferences -> + preferences[PreferencesKeys.AutoLogin] = autoLogin + } + } + + override suspend fun updateNickname(name: String) { + dataStore.edit { preferences -> + preferences[PreferencesKeys.Nickname] = name + } + } + + override suspend fun updateMemberId(memberId: Int) { + dataStore.edit { preferences -> + preferences[PreferencesKeys.MemberId] = memberId + } + } + + override suspend fun updateMemberProfileUrl(memberUrl: String) { + dataStore.edit { preferences -> + preferences[PreferencesKeys.MemberProfileUrl] = memberUrl + } + } + + override suspend fun updateIsNewUser(isNewUser: Boolean) { + dataStore.edit { preferences -> + preferences[PreferencesKeys.IsNewUser] = isNewUser + } + } + + override suspend fun updateIsPushAlarmAllowed(isPushAlarmAllowed: Boolean) { + dataStore.edit { preferences -> + preferences[PreferencesKeys.IsPushAlarmAllowed] = isPushAlarmAllowed + } + } + + override suspend fun clear() { + dataStore.edit { preferences -> + preferences.clear() + } + } + + override suspend fun clearForRefreshToken() { + dataStore.edit { preferences -> + preferences.remove(PreferencesKeys.AccessToken) + preferences.remove(PreferencesKeys.RefreshToken) + preferences.remove(PreferencesKeys.AutoLogin) + } + } +} + +private suspend fun FlowCollector.handleError(it: Throwable) { + if (it is IOException) emit(emptyPreferences()) + else throw it +} From 0f2aa004552d4f29d28b800a8ba04dce9177effa Mon Sep 17 00:00:00 2001 From: chanu Date: Sat, 17 Aug 2024 02:43:29 +0900 Subject: [PATCH 06/12] #22 [setting] : datastore module di setting --- .../teamwable/datastore/di/DataStoreModule.kt | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 core/datastore/src/main/java/com/teamwable/datastore/di/DataStoreModule.kt diff --git a/core/datastore/src/main/java/com/teamwable/datastore/di/DataStoreModule.kt b/core/datastore/src/main/java/com/teamwable/datastore/di/DataStoreModule.kt new file mode 100644 index 00000000..985e71bd --- /dev/null +++ b/core/datastore/src/main/java/com/teamwable/datastore/di/DataStoreModule.kt @@ -0,0 +1,25 @@ +package com.teamwable.datastore.di + +import android.content.Context +import androidx.datastore.core.DataStore +import androidx.datastore.preferences.core.Preferences +import androidx.datastore.preferences.preferencesDataStore +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.android.qualifiers.ApplicationContext +import dagger.hilt.components.SingletonComponent +import javax.inject.Singleton + +@Module +@InstallIn(SingletonComponent::class) +object DataStoreModule { + private val Context.dataStore by preferencesDataStore(name = "wable_data_store") + + @Singleton + @Provides + fun provideDataStore( + @ApplicationContext context: Context, + ): DataStore = + context.dataStore +} From 408b84d68f30d80fcabd0e5f8b91a703a6e04dcb Mon Sep 17 00:00:00 2001 From: chanu Date: Sat, 17 Aug 2024 02:43:51 +0900 Subject: [PATCH 07/12] #22 [setting] : UserInfoRepository setting --- .../data/repository/UserInfoRepository.kt | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 core/data/src/main/java/com/teamwable/data/repository/UserInfoRepository.kt diff --git a/core/data/src/main/java/com/teamwable/data/repository/UserInfoRepository.kt b/core/data/src/main/java/com/teamwable/data/repository/UserInfoRepository.kt new file mode 100644 index 00000000..5824c659 --- /dev/null +++ b/core/data/src/main/java/com/teamwable/data/repository/UserInfoRepository.kt @@ -0,0 +1,41 @@ +package com.teamwable.data.repository + +import kotlinx.coroutines.flow.Flow + +interface UserInfoRepository { + fun getAccessToken(): Flow + + fun getRefreshToken(): Flow + + fun getAutoLogin(): Flow + + fun getNickname(): Flow + + fun getMemberId(): Flow + + fun getMemberProfileUrl(): Flow + + fun getIsNewUser(): Flow + + fun getIsPushAlarmAllowed(): Flow + + suspend fun saveAccessToken(accessToken: String) + + suspend fun saveRefreshToken(refreshToken: String) + + suspend fun saveAutoLogin(autoLogin: Boolean) + + suspend fun saveNickname(name: String) + + suspend fun saveMemberId(memberId: Int) + + suspend fun saveMemberProfileUrl(memberUrl: String) + + suspend fun saveIsNewUser(isNewUser: Boolean) + + suspend fun saveIsPushAlarmAllowed(isPushAlarmAllowed: Boolean) + + suspend fun clearAll() + + suspend fun clearForRefreshToken() +} From 0e043337a829425c3a05d6125a24c6f43e3928d8 Mon Sep 17 00:00:00 2001 From: chanu Date: Sat, 17 Aug 2024 02:45:31 +0900 Subject: [PATCH 08/12] =?UTF-8?q?#22=20[setting]=20:=20UserInfoRepositoryi?= =?UTF-8?q?mpl=20=EA=B5=AC=ED=98=84=EC=B2=B4=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../DefaultUserInfoRepository.kt | 74 +++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 core/data/src/main/java/com/teamwable/data/repositoryimpl/DefaultUserInfoRepository.kt diff --git a/core/data/src/main/java/com/teamwable/data/repositoryimpl/DefaultUserInfoRepository.kt b/core/data/src/main/java/com/teamwable/data/repositoryimpl/DefaultUserInfoRepository.kt new file mode 100644 index 00000000..de507ccc --- /dev/null +++ b/core/data/src/main/java/com/teamwable/data/repositoryimpl/DefaultUserInfoRepository.kt @@ -0,0 +1,74 @@ +package com.teamwable.data.repositoryimpl + +import com.teamwable.data.repository.UserInfoRepository +import com.teamwable.datastore.datasource.WablePreferencesDataSource +import kotlinx.coroutines.flow.Flow +import javax.inject.Inject + +internal class DefaultUserInfoRepository @Inject constructor( + private val wablePreferencesDataSource: WablePreferencesDataSource, +) : UserInfoRepository { + override fun getAccessToken(): Flow = + wablePreferencesDataSource.accessToken + + override fun getRefreshToken(): Flow = + wablePreferencesDataSource.refreshToken + + override fun getAutoLogin(): Flow = + wablePreferencesDataSource.autoLogin + + override fun getNickname(): Flow = + wablePreferencesDataSource.nickname + + override fun getMemberId(): Flow = + wablePreferencesDataSource.memberId + + override fun getMemberProfileUrl(): Flow = + wablePreferencesDataSource.memberProfileUrl + + override fun getIsNewUser(): Flow = + wablePreferencesDataSource.isNewUser + + override fun getIsPushAlarmAllowed(): Flow = + wablePreferencesDataSource.isPushAlarmAllowed + + override suspend fun saveAccessToken(accessToken: String) { + wablePreferencesDataSource.updateAccessToken(accessToken) + } + + override suspend fun saveRefreshToken(refreshToken: String) { + wablePreferencesDataSource.updateRefreshToken(refreshToken) + } + + override suspend fun saveAutoLogin(autoLogin: Boolean) { + wablePreferencesDataSource.updateAutoLogin(autoLogin) + } + + override suspend fun saveNickname(name: String) { + wablePreferencesDataSource.updateNickname(name) + } + + override suspend fun saveMemberId(memberId: Int) { + wablePreferencesDataSource.updateMemberId(memberId) + } + + override suspend fun saveMemberProfileUrl(memberUrl: String) { + wablePreferencesDataSource.updateMemberProfileUrl(memberUrl) + } + + override suspend fun saveIsNewUser(isNewUser: Boolean) { + wablePreferencesDataSource.updateIsNewUser(isNewUser) + } + + override suspend fun saveIsPushAlarmAllowed(isPushAlarmAllowed: Boolean) { + wablePreferencesDataSource.updateIsPushAlarmAllowed(isPushAlarmAllowed) + } + + override suspend fun clearAll() { + wablePreferencesDataSource.clear() + } + + override suspend fun clearForRefreshToken() { + wablePreferencesDataSource.clearForRefreshToken() + } +} From c87887d2e6e310efaf858718fa80ad02d1d76d48 Mon Sep 17 00:00:00 2001 From: chanu Date: Sat, 17 Aug 2024 02:46:04 +0900 Subject: [PATCH 09/12] #22 [setting] : userInfoRepository, wable local datasource di setting --- .../com/teamwable/data/di/RepositoryModule.kt | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/core/data/src/main/java/com/teamwable/data/di/RepositoryModule.kt b/core/data/src/main/java/com/teamwable/data/di/RepositoryModule.kt index 4d4f11f9..83048a17 100644 --- a/core/data/src/main/java/com/teamwable/data/di/RepositoryModule.kt +++ b/core/data/src/main/java/com/teamwable/data/di/RepositoryModule.kt @@ -1,7 +1,11 @@ package com.teamwable.data.di import com.teamwable.data.repository.DummyRepository +import com.teamwable.data.repository.UserInfoRepository import com.teamwable.data.repositoryimpl.DefaultDummyRepository +import com.teamwable.data.repositoryimpl.DefaultUserInfoRepository +import com.teamwable.datastore.datasource.DefaultWablePreferenceDatasource +import com.teamwable.datastore.datasource.WablePreferencesDataSource import dagger.Binds import dagger.Module import dagger.hilt.InstallIn @@ -14,4 +18,16 @@ internal abstract class RepositoryModule { @Binds @Singleton abstract fun bindsHomeRepository(repositoryImpl: DefaultDummyRepository): DummyRepository + + @Binds + @Singleton + abstract fun bindsWableLocalDataSource( + dataSourceImpl: DefaultWablePreferenceDatasource, + ): WablePreferencesDataSource + + @Binds + @Singleton + abstract fun bindsUserInfoRepository( + repositoryImpl: DefaultUserInfoRepository, + ): UserInfoRepository } From 5529b44949b8f347509c2c1162c1e80a4348e0ef Mon Sep 17 00:00:00 2001 From: chanu Date: Sat, 17 Aug 2024 03:15:46 +0900 Subject: [PATCH 10/12] =?UTF-8?q?#22=20[feat]=20:=20=EC=95=BD=EC=8B=9D=20?= =?UTF-8?q?=EC=9E=90=EB=8F=99=EB=A1=9C=EA=B7=B8=EC=9D=B8=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84,=20datastore=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/teamwable/auth/LoginScreen.kt | 33 +++++++++++++++- .../java/com/teamwable/auth/LoginViewModel.kt | 38 +++++++++++++++++++ .../teamwable/auth/model/LoginSideEffect.kt | 9 +++++ 3 files changed, 78 insertions(+), 2 deletions(-) create mode 100644 feature/auth/src/main/java/com/teamwable/auth/LoginViewModel.kt create mode 100644 feature/auth/src/main/java/com/teamwable/auth/model/LoginSideEffect.kt diff --git a/feature/auth/src/main/java/com/teamwable/auth/LoginScreen.kt b/feature/auth/src/main/java/com/teamwable/auth/LoginScreen.kt index 07a0aba3..d9dc1a4c 100644 --- a/feature/auth/src/main/java/com/teamwable/auth/LoginScreen.kt +++ b/feature/auth/src/main/java/com/teamwable/auth/LoginScreen.kt @@ -1,5 +1,6 @@ package com.teamwable.auth +import android.content.Context import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -13,6 +14,7 @@ import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Button import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext @@ -22,26 +24,53 @@ import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import androidx.core.content.ContextCompat.startActivity +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.LocalLifecycleOwner +import androidx.lifecycle.flowWithLifecycle +import com.teamwable.auth.model.LoginSideEffect import com.teamwable.common.intentprovider.IntentProvider import com.teamwable.designsystem.theme.WableTheme @Composable fun LoginRoute( + viewModel: LoginViewModel = hiltViewModel(), navigateToOnBoarding: () -> Unit, navigateToHome: () -> Unit, onShowErrorSnackBar: (throwable: Throwable?) -> Unit, intentProvider: IntentProvider, ) { + val lifecycleOwner = LocalLifecycleOwner.current val context = LocalContext.current + LaunchedEffect(Unit) { + viewModel.observeAutoLogin() + } + + LaunchedEffect(lifecycleOwner) { + viewModel.loginSideEffect.flowWithLifecycle(lifecycleOwner.lifecycle) + .collect { sideEffect -> + when (sideEffect) { + is LoginSideEffect.NavigateToMain -> navigateToMain(intentProvider, context) + else -> Unit + } + } + } + LoginScreen( onLoginBtnClick = { - val intent = intentProvider.getIntent() - startActivity(context, intent, null) + viewModel.saveIsAutoLogin(true) }, ) } +private fun navigateToMain( + intentProvider: IntentProvider, + context: Context, +) { + val intent = intentProvider.getIntent() + startActivity(context, intent, null) +} + @Composable fun LoginScreen( onLoginBtnClick: () -> Unit, diff --git a/feature/auth/src/main/java/com/teamwable/auth/LoginViewModel.kt b/feature/auth/src/main/java/com/teamwable/auth/LoginViewModel.kt new file mode 100644 index 00000000..c3e79002 --- /dev/null +++ b/feature/auth/src/main/java/com/teamwable/auth/LoginViewModel.kt @@ -0,0 +1,38 @@ +package com.teamwable.auth + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.teamwable.auth.model.LoginSideEffect +import com.teamwable.data.repository.UserInfoRepository +import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.flow.MutableSharedFlow +import kotlinx.coroutines.flow.SharedFlow +import kotlinx.coroutines.flow.asSharedFlow +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch +import javax.inject.Inject + +@HiltViewModel +class LoginViewModel @Inject constructor( + private val userInfoRepository: UserInfoRepository, +) : ViewModel() { + private val _loginSideEffect: MutableSharedFlow = MutableSharedFlow() + val loginSideEffect: SharedFlow + get() = _loginSideEffect.asSharedFlow() + + fun observeAutoLogin() { + viewModelScope.launch { + userInfoRepository.getAutoLogin().collectLatest { isAutoLogin -> + if (isAutoLogin) { + _loginSideEffect.emit(LoginSideEffect.NavigateToMain) + } + } + } + } + + fun saveIsAutoLogin(input: Boolean) { + viewModelScope.launch { + userInfoRepository.saveAutoLogin(input) + } + } +} diff --git a/feature/auth/src/main/java/com/teamwable/auth/model/LoginSideEffect.kt b/feature/auth/src/main/java/com/teamwable/auth/model/LoginSideEffect.kt new file mode 100644 index 00000000..3eda9a0c --- /dev/null +++ b/feature/auth/src/main/java/com/teamwable/auth/model/LoginSideEffect.kt @@ -0,0 +1,9 @@ +package com.teamwable.auth.model + +sealed interface LoginSideEffect { + data object NavigateToMain : LoginSideEffect + + data object NavigateToOnBoarding : LoginSideEffect + + data class ShowSnackBar(val message: String) : LoginSideEffect +} From 8679fc35c23eee4dc8acbe820a2ad83d81c337ca Mon Sep 17 00:00:00 2001 From: chanu Date: Sat, 17 Aug 2024 03:31:22 +0900 Subject: [PATCH 11/12] =?UTF-8?q?#22=20[fix]=20:=20=EB=B6=88=ED=95=84?= =?UTF-8?q?=EC=9A=94=ED=95=9C=20intent=20provider=20props=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/com/teamwable/auth/LoginScreen.kt | 14 +------------- .../teamwable/auth/naviagation/AuthNavigation.kt | 3 --- .../java/com/teamwable/main_compose/MainScreen.kt | 1 - 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/feature/auth/src/main/java/com/teamwable/auth/LoginScreen.kt b/feature/auth/src/main/java/com/teamwable/auth/LoginScreen.kt index d9dc1a4c..149fd654 100644 --- a/feature/auth/src/main/java/com/teamwable/auth/LoginScreen.kt +++ b/feature/auth/src/main/java/com/teamwable/auth/LoginScreen.kt @@ -1,6 +1,5 @@ package com.teamwable.auth -import android.content.Context import androidx.compose.foundation.Image import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -23,12 +22,10 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp -import androidx.core.content.ContextCompat.startActivity import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.LocalLifecycleOwner import androidx.lifecycle.flowWithLifecycle import com.teamwable.auth.model.LoginSideEffect -import com.teamwable.common.intentprovider.IntentProvider import com.teamwable.designsystem.theme.WableTheme @Composable @@ -37,7 +34,6 @@ fun LoginRoute( navigateToOnBoarding: () -> Unit, navigateToHome: () -> Unit, onShowErrorSnackBar: (throwable: Throwable?) -> Unit, - intentProvider: IntentProvider, ) { val lifecycleOwner = LocalLifecycleOwner.current val context = LocalContext.current @@ -50,7 +46,7 @@ fun LoginRoute( viewModel.loginSideEffect.flowWithLifecycle(lifecycleOwner.lifecycle) .collect { sideEffect -> when (sideEffect) { - is LoginSideEffect.NavigateToMain -> navigateToMain(intentProvider, context) + is LoginSideEffect.NavigateToMain -> navigateToHome() else -> Unit } } @@ -63,14 +59,6 @@ fun LoginRoute( ) } -private fun navigateToMain( - intentProvider: IntentProvider, - context: Context, -) { - val intent = intentProvider.getIntent() - startActivity(context, intent, null) -} - @Composable fun LoginScreen( onLoginBtnClick: () -> Unit, diff --git a/feature/auth/src/main/java/com/teamwable/auth/naviagation/AuthNavigation.kt b/feature/auth/src/main/java/com/teamwable/auth/naviagation/AuthNavigation.kt index 4d55383b..4a977a59 100644 --- a/feature/auth/src/main/java/com/teamwable/auth/naviagation/AuthNavigation.kt +++ b/feature/auth/src/main/java/com/teamwable/auth/naviagation/AuthNavigation.kt @@ -5,7 +5,6 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable import com.teamwable.auth.LoginRoute -import com.teamwable.common.intentprovider.IntentProvider import com.teamwable.navigation.Route fun NavController.navigateLogin(navOptions: NavOptions) { @@ -16,14 +15,12 @@ fun NavGraphBuilder.loginNavGraph( navigateToOnBoarding: () -> Unit, navigateToHome: () -> Unit, onShowErrorSnackBar: (throwable: Throwable?) -> Unit, - intentProvider: IntentProvider, ) { composable { LoginRoute( navigateToHome = navigateToHome, navigateToOnBoarding = navigateToOnBoarding, onShowErrorSnackBar = onShowErrorSnackBar, - intentProvider = intentProvider, ) } } diff --git a/feature/main-compose/src/main/java/com/teamwable/main_compose/MainScreen.kt b/feature/main-compose/src/main/java/com/teamwable/main_compose/MainScreen.kt index 5f3f1ea5..96d6eabd 100644 --- a/feature/main-compose/src/main/java/com/teamwable/main_compose/MainScreen.kt +++ b/feature/main-compose/src/main/java/com/teamwable/main_compose/MainScreen.kt @@ -74,7 +74,6 @@ internal fun MainScreen( navigateToOnBoarding = {}, navigateToHome = { startActivity(localContext, intent, null) }, onShowErrorSnackBar = onShowErrorSnackBar, - intentProvider = intentProvider, ) } } From 02d73e1bf4f1027ca47b670038b6eafed7c336f2 Mon Sep 17 00:00:00 2001 From: chanu Date: Sat, 17 Aug 2024 21:49:02 +0900 Subject: [PATCH 12/12] =?UTF-8?q?#22=20[delete]=20:=20isNewUser=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../teamwable/data/repository/UserInfoRepository.kt | 4 ---- .../repositoryimpl/DefaultUserInfoRepository.kt | 7 ------- .../datasource/DefaultWablePreferenceDatasource.kt | 13 ------------- .../datasource/WablePreferencesDataSource.kt | 3 --- 4 files changed, 27 deletions(-) diff --git a/core/data/src/main/java/com/teamwable/data/repository/UserInfoRepository.kt b/core/data/src/main/java/com/teamwable/data/repository/UserInfoRepository.kt index 5824c659..4bbfdb2e 100644 --- a/core/data/src/main/java/com/teamwable/data/repository/UserInfoRepository.kt +++ b/core/data/src/main/java/com/teamwable/data/repository/UserInfoRepository.kt @@ -15,8 +15,6 @@ interface UserInfoRepository { fun getMemberProfileUrl(): Flow - fun getIsNewUser(): Flow - fun getIsPushAlarmAllowed(): Flow suspend fun saveAccessToken(accessToken: String) @@ -31,8 +29,6 @@ interface UserInfoRepository { suspend fun saveMemberProfileUrl(memberUrl: String) - suspend fun saveIsNewUser(isNewUser: Boolean) - suspend fun saveIsPushAlarmAllowed(isPushAlarmAllowed: Boolean) suspend fun clearAll() diff --git a/core/data/src/main/java/com/teamwable/data/repositoryimpl/DefaultUserInfoRepository.kt b/core/data/src/main/java/com/teamwable/data/repositoryimpl/DefaultUserInfoRepository.kt index de507ccc..9c14d267 100644 --- a/core/data/src/main/java/com/teamwable/data/repositoryimpl/DefaultUserInfoRepository.kt +++ b/core/data/src/main/java/com/teamwable/data/repositoryimpl/DefaultUserInfoRepository.kt @@ -26,9 +26,6 @@ internal class DefaultUserInfoRepository @Inject constructor( override fun getMemberProfileUrl(): Flow = wablePreferencesDataSource.memberProfileUrl - override fun getIsNewUser(): Flow = - wablePreferencesDataSource.isNewUser - override fun getIsPushAlarmAllowed(): Flow = wablePreferencesDataSource.isPushAlarmAllowed @@ -56,10 +53,6 @@ internal class DefaultUserInfoRepository @Inject constructor( wablePreferencesDataSource.updateMemberProfileUrl(memberUrl) } - override suspend fun saveIsNewUser(isNewUser: Boolean) { - wablePreferencesDataSource.updateIsNewUser(isNewUser) - } - override suspend fun saveIsPushAlarmAllowed(isPushAlarmAllowed: Boolean) { wablePreferencesDataSource.updateIsPushAlarmAllowed(isPushAlarmAllowed) } diff --git a/core/datastore/src/main/java/com/teamwable/datastore/datasource/DefaultWablePreferenceDatasource.kt b/core/datastore/src/main/java/com/teamwable/datastore/datasource/DefaultWablePreferenceDatasource.kt index bd3b69c8..f603ec5c 100644 --- a/core/datastore/src/main/java/com/teamwable/datastore/datasource/DefaultWablePreferenceDatasource.kt +++ b/core/datastore/src/main/java/com/teamwable/datastore/datasource/DefaultWablePreferenceDatasource.kt @@ -24,7 +24,6 @@ class DefaultWablePreferenceDatasource @Inject constructor( val AutoLogin = booleanPreferencesKey("autoLogin") val MemberId = intPreferencesKey("memberId") val MemberProfileUrl = stringPreferencesKey("memberProfileUrl") - val IsNewUser = booleanPreferencesKey("isNewUser") val IsPushAlarmAllowed = booleanPreferencesKey("isPushAlarmAllowed") } @@ -64,12 +63,6 @@ class DefaultWablePreferenceDatasource @Inject constructor( preferences[PreferencesKeys.MemberProfileUrl].orEmpty() } - override var isNewUser: Flow = dataStore.data - .catch { handleError(it) } - .map { preferences -> - preferences[PreferencesKeys.IsNewUser] ?: false - } - override var isPushAlarmAllowed: Flow = dataStore.data .catch { handleError(it) } .map { preferences -> @@ -112,12 +105,6 @@ class DefaultWablePreferenceDatasource @Inject constructor( } } - override suspend fun updateIsNewUser(isNewUser: Boolean) { - dataStore.edit { preferences -> - preferences[PreferencesKeys.IsNewUser] = isNewUser - } - } - override suspend fun updateIsPushAlarmAllowed(isPushAlarmAllowed: Boolean) { dataStore.edit { preferences -> preferences[PreferencesKeys.IsPushAlarmAllowed] = isPushAlarmAllowed diff --git a/core/datastore/src/main/java/com/teamwable/datastore/datasource/WablePreferencesDataSource.kt b/core/datastore/src/main/java/com/teamwable/datastore/datasource/WablePreferencesDataSource.kt index 26f77e5e..b4c1ca84 100644 --- a/core/datastore/src/main/java/com/teamwable/datastore/datasource/WablePreferencesDataSource.kt +++ b/core/datastore/src/main/java/com/teamwable/datastore/datasource/WablePreferencesDataSource.kt @@ -9,7 +9,6 @@ interface WablePreferencesDataSource { val nickname: Flow val memberId: Flow val memberProfileUrl: Flow - val isNewUser: Flow val isPushAlarmAllowed: Flow suspend fun updateAccessToken(accessToken: String) @@ -24,8 +23,6 @@ interface WablePreferencesDataSource { suspend fun updateMemberProfileUrl(memberUrl: String) - suspend fun updateIsNewUser(isNewUser: Boolean) - suspend fun updateIsPushAlarmAllowed(isPushAlarmAllowed: Boolean) suspend fun clear()