diff --git a/README/README_seminar_7.md b/README/README_seminar_7.md
new file mode 100644
index 0000000..d08f14d
--- /dev/null
+++ b/README/README_seminar_7.md
@@ -0,0 +1 @@
+7주차 README입니다 - https://velog.io/@gxstxdgxs/THE-SOPT-Android-7차-세미나-과제
diff --git a/app/build.gradle b/app/build.gradle
index 60d9245..632d224 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -47,10 +47,10 @@ android {
}
dependencies {
- implementation 'androidx.core:core-ktx:1.7.0'
- implementation 'androidx.appcompat:appcompat:1.4.1'
- implementation 'com.google.android.material:material:1.6.0'
- implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
+ implementation 'androidx.core:core-ktx:1.8.0'
+ implementation 'androidx.appcompat:appcompat:1.4.2'
+ implementation 'com.google.android.material:material:1.6.1'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
@@ -61,8 +61,8 @@ dependencies {
kapt 'androidx.room:room-compiler:2.4.2'
// Hilt
- implementation "com.google.dagger:hilt-android:2.40"
- kapt "com.google.dagger:hilt-android-compiler:2.40"
+ implementation "com.google.dagger:hilt-android:2.41"
+ kapt "com.google.dagger:hilt-android-compiler:2.41"
// ktx
implementation 'androidx.activity:activity-ktx:1.4.0'
@@ -90,5 +90,11 @@ dependencies {
// OkHttp3
implementation 'com.squareup.okhttp3:okhttp:5.0.0-alpha.2'
- implementation 'com.squareup.okhttp3:logging-interceptor:4.9.1'
+ implementation 'com.squareup.okhttp3:logging-interceptor:4.9.3'
+
+ // Coroutines
+ implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.0'
+
+ // lifecycle
+ implementation 'androidx.lifecycle:lifecycle-runtime-ktx:2.4.1'
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8fe9acb..d6784ce 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -14,6 +14,15 @@
android:supportsRtl="true"
android:theme="@style/Theme.SOPT_Seminar_30th"
android:usesCleartextTraffic="true">
+
+
+
+
+
+
+
@@ -27,13 +36,7 @@
-
-
-
-
-
-
+ android:windowSoftInputMode="adjustResize" />
\ No newline at end of file
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/data/database/AppDatabase.kt b/app/src/main/java/co/kr/sopt_seminar_30th/data/database/AppDatabase.kt
index 91003b3..41007c5 100644
--- a/app/src/main/java/co/kr/sopt_seminar_30th/data/database/AppDatabase.kt
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/data/database/AppDatabase.kt
@@ -4,18 +4,21 @@ import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
+import co.kr.sopt_seminar_30th.data.datasource.local.AuthorizationDao
import co.kr.sopt_seminar_30th.data.datasource.local.FollowerDao
import co.kr.sopt_seminar_30th.data.datasource.local.RepositoryDao
import co.kr.sopt_seminar_30th.data.datasource.local.UserDao
+import co.kr.sopt_seminar_30th.data.model.dto.AuthorizationDto
import co.kr.sopt_seminar_30th.data.model.dto.FollowerDto
import co.kr.sopt_seminar_30th.data.model.dto.RepositoryDto
import co.kr.sopt_seminar_30th.data.model.dto.UserDto
-@Database(entities = [UserDto::class, FollowerDto::class, RepositoryDto::class], version = 1)
+@Database(entities = [UserDto::class, FollowerDto::class, RepositoryDto::class, AuthorizationDto::class], version = 1)
abstract class AppDatabase : RoomDatabase() {
abstract fun userDao(): UserDao
abstract fun followerDao(): FollowerDao
abstract fun repositoryDao(): RepositoryDao
+ abstract fun authorizationDao(): AuthorizationDao
companion object {
fun getInstance(context: Context): AppDatabase = Room
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/data/datasource/local/AuthorizationDao.kt b/app/src/main/java/co/kr/sopt_seminar_30th/data/datasource/local/AuthorizationDao.kt
new file mode 100644
index 0000000..b4ca3ea
--- /dev/null
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/data/datasource/local/AuthorizationDao.kt
@@ -0,0 +1,16 @@
+package co.kr.sopt_seminar_30th.data.datasource.local
+
+import androidx.room.*
+import co.kr.sopt_seminar_30th.data.model.dto.AuthorizationDto
+
+@Dao
+interface AuthorizationDao {
+ @Insert
+ suspend fun insertAuthorization(authorizationDto: AuthorizationDto)
+
+ @Delete
+ suspend fun deleteAuthorization(authorizationDto: AuthorizationDto)
+
+ @Query("SELECT * FROM Authorization WHERE userId = :id")
+ suspend fun getAuthorization(id: String): AuthorizationDto
+}
\ No newline at end of file
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/data/datasource/local/SopthubDataStore.kt b/app/src/main/java/co/kr/sopt_seminar_30th/data/datasource/local/SopthubDataStore.kt
index 98a6abe..31633ba 100644
--- a/app/src/main/java/co/kr/sopt_seminar_30th/data/datasource/local/SopthubDataStore.kt
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/data/datasource/local/SopthubDataStore.kt
@@ -33,4 +33,8 @@ class SopthubDataStore @Inject constructor(
var autoLogin: Boolean
set(value) = dataStore.edit { putBoolean("AUTO_LOGIN", value) }
get() = dataStore.getBoolean("AUTO_LOGIN", false)
+
+ var onBoardingEnabled: Boolean
+ set(value) = dataStore.edit { putBoolean("ON_BOARDING_ENABLED", value) }
+ get() = dataStore.getBoolean("ON_BOARDING_ENABLED", false)
}
\ No newline at end of file
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/data/model/dto/AuthorizationDto.kt b/app/src/main/java/co/kr/sopt_seminar_30th/data/model/dto/AuthorizationDto.kt
new file mode 100644
index 0000000..cd85811
--- /dev/null
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/data/model/dto/AuthorizationDto.kt
@@ -0,0 +1,11 @@
+package co.kr.sopt_seminar_30th.data.model.dto
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "Authorization")
+data class AuthorizationDto(
+ @PrimaryKey val userId: String,
+ @ColumnInfo(name = "autoLogin") val autoLogin: Boolean
+)
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/data/repositoryimpl/local/AuthorizationRepositoryImpl.kt b/app/src/main/java/co/kr/sopt_seminar_30th/data/repositoryimpl/local/AuthorizationRepositoryImpl.kt
new file mode 100644
index 0000000..d074cf8
--- /dev/null
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/data/repositoryimpl/local/AuthorizationRepositoryImpl.kt
@@ -0,0 +1,28 @@
+package co.kr.sopt_seminar_30th.data.repositoryimpl.local
+
+import co.kr.sopt_seminar_30th.data.datasource.local.AuthorizationDao
+import co.kr.sopt_seminar_30th.data.model.dto.AuthorizationDto
+import co.kr.sopt_seminar_30th.domain.repository.local.AuthorizationRepository
+import kotlinx.coroutines.CoroutineDispatcher
+import kotlinx.coroutines.withContext
+import javax.inject.Inject
+
+class AuthorizationRepositoryImpl @Inject constructor(
+ private val dao: AuthorizationDao,
+ private val coroutineDispatcher: CoroutineDispatcher
+) : AuthorizationRepository {
+ override suspend fun insertAuthorization(userId: String, autoLogin: Boolean) =
+ withContext(coroutineDispatcher) {
+ dao.insertAuthorization(AuthorizationDto(userId, autoLogin))
+ }
+
+ override suspend fun deleteAuthorization(userId: String, autoLogin: Boolean) =
+ withContext(coroutineDispatcher) {
+ dao.deleteAuthorization(AuthorizationDto(userId, autoLogin))
+ }
+
+ override suspend fun getAuthorization(userId: String): Boolean =
+ withContext(coroutineDispatcher) {
+ dao.getAuthorization(userId).autoLogin
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/di/DbModule.kt b/app/src/main/java/co/kr/sopt_seminar_30th/di/DbModule.kt
index 419c58c..c213d61 100644
--- a/app/src/main/java/co/kr/sopt_seminar_30th/di/DbModule.kt
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/di/DbModule.kt
@@ -2,6 +2,7 @@ package co.kr.sopt_seminar_30th.di
import android.content.Context
import co.kr.sopt_seminar_30th.data.database.AppDatabase
+import co.kr.sopt_seminar_30th.data.datasource.local.AuthorizationDao
import co.kr.sopt_seminar_30th.data.datasource.local.FollowerDao
import co.kr.sopt_seminar_30th.data.datasource.local.RepositoryDao
import co.kr.sopt_seminar_30th.data.datasource.local.UserDao
@@ -33,4 +34,8 @@ object DbModule {
@Singleton
@Provides
fun provideRepositoryDao(appDatabase: AppDatabase): RepositoryDao = appDatabase.repositoryDao()
+
+ @Singleton
+ @Provides
+ fun provideAuthorizationDao(appDatabase: AppDatabase): AuthorizationDao = appDatabase.authorizationDao()
}
\ No newline at end of file
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/di/RepositoryModule.kt b/app/src/main/java/co/kr/sopt_seminar_30th/di/RepositoryModule.kt
index 73c621f..7a17bdd 100644
--- a/app/src/main/java/co/kr/sopt_seminar_30th/di/RepositoryModule.kt
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/di/RepositoryModule.kt
@@ -1,9 +1,7 @@
package co.kr.sopt_seminar_30th.di
-import co.kr.sopt_seminar_30th.data.datasource.local.FollowerDao
-import co.kr.sopt_seminar_30th.data.datasource.local.RepositoryDao
-import co.kr.sopt_seminar_30th.data.datasource.local.SopthubDataStore
-import co.kr.sopt_seminar_30th.data.datasource.local.UserDao
+import co.kr.sopt_seminar_30th.data.datasource.local.*
+import co.kr.sopt_seminar_30th.data.repositoryimpl.local.AuthorizationRepositoryImpl
import co.kr.sopt_seminar_30th.data.repositoryimpl.local.FollowerRepositoryImpl
import co.kr.sopt_seminar_30th.data.repositoryimpl.local.RepositoryRepositoryImpl
import co.kr.sopt_seminar_30th.data.repositoryimpl.local.UserRepositoryImpl
@@ -13,6 +11,7 @@ import co.kr.sopt_seminar_30th.data.repositoryimpl.remote.SignUpRepositoryImpl
import co.kr.sopt_seminar_30th.data.service.auth.SignInService
import co.kr.sopt_seminar_30th.data.service.auth.SignUpService
import co.kr.sopt_seminar_30th.data.service.home.HomeService
+import co.kr.sopt_seminar_30th.domain.repository.local.AuthorizationRepository
import co.kr.sopt_seminar_30th.domain.repository.local.FollowerRepository
import co.kr.sopt_seminar_30th.domain.repository.local.RepositoryRepository
import co.kr.sopt_seminar_30th.domain.repository.local.UserRepository
@@ -68,4 +67,12 @@ object RepositoryModule {
homeService: HomeService,
@IoDispatcher coroutineDispatcher: CoroutineDispatcher
): HomeRepository = HomeRepositoryImpl(homeService, coroutineDispatcher)
+
+ @Singleton
+ @Provides
+ fun provideAuthorizationRepository(
+ authorizationDao: AuthorizationDao,
+ @IoDispatcher coroutineDispatcher: CoroutineDispatcher
+ ): AuthorizationRepository =
+ AuthorizationRepositoryImpl(authorizationDao, coroutineDispatcher)
}
\ No newline at end of file
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/domain/repository/local/AuthorizationRepository.kt b/app/src/main/java/co/kr/sopt_seminar_30th/domain/repository/local/AuthorizationRepository.kt
new file mode 100644
index 0000000..5f7cdb8
--- /dev/null
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/domain/repository/local/AuthorizationRepository.kt
@@ -0,0 +1,7 @@
+package co.kr.sopt_seminar_30th.domain.repository.local
+
+interface AuthorizationRepository {
+ suspend fun insertAuthorization(userId: String, autoLogin: Boolean)
+ suspend fun deleteAuthorization(userId: String, autoLogin: Boolean)
+ suspend fun getAuthorization(userId: String): Boolean
+}
\ No newline at end of file
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/auth/SignInActivity.kt b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/auth/SignInActivity.kt
index 85d8243..8bb59a7 100644
--- a/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/auth/SignInActivity.kt
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/auth/SignInActivity.kt
@@ -5,12 +5,18 @@ import android.os.Bundle
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
import co.kr.sopt_seminar_30th.R
+import co.kr.sopt_seminar_30th.data.datasource.local.SopthubDataStore
import co.kr.sopt_seminar_30th.databinding.ActivitySignInBinding
import co.kr.sopt_seminar_30th.presentation.ui.base.BaseActivity
import co.kr.sopt_seminar_30th.presentation.ui.home.HomeActivity
import co.kr.sopt_seminar_30th.presentation.viewmodel.SignInViewModel
import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import javax.inject.Inject
@AndroidEntryPoint
class SignInActivity : BaseActivity() {
@@ -19,6 +25,9 @@ class SignInActivity : BaseActivity() {
private val signInViewModel by viewModels()
+ @Inject
+ lateinit var dataStore: SopthubDataStore
+
private val activityResultLauncher =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
if (it.resultCode == RESULT_OK) {
@@ -34,11 +43,18 @@ class SignInActivity : BaseActivity() {
binding.viewmodel = signInViewModel
binding.lifecycleOwner = this
+ loginWithAutoLogin()
signUp()
login()
observeLogin()
}
+ private fun loginWithAutoLogin() {
+ if (dataStore.autoLogin) {
+ signInViewModel.checkAuthorization(dataStore.userId)
+ }
+ }
+
private fun signUp() {
binding.btnSignUp.setOnClickListener {
val intent = Intent(this, SignUpActivity::class.java)
@@ -65,34 +81,30 @@ class SignInActivity : BaseActivity() {
}
}
}
-
signInViewModel.isEmailIncorrect.observe(this) {
- if(it) {
+ if (it) {
Toast.makeText(this, "존재하지 않는 계정입니다", Toast.LENGTH_SHORT).show()
binding.etUserPassword.text.clear()
}
}
-
signInViewModel.isPasswordIncorrect.observe(this) {
- if(it) {
+ if (it) {
Toast.makeText(this, "비밀번호가 일치하지 않습니다", Toast.LENGTH_SHORT).show()
binding.etUserPassword.text.clear()
}
}
-
signInViewModel.isEmpty.observe(this) {
if (it) {
Toast.makeText(this, "아이디/비밀번호를 확인해주세요", Toast.LENGTH_SHORT).show()
}
}
-
- signInViewModel.autoLogin.observe(this) {
- if (it) {
- Toast.makeText(this, "자동로그인 성공", Toast.LENGTH_SHORT).show()
- val intent = Intent(this, HomeActivity::class.java)
- startActivity(intent)
- finish()
- }
- }
+ signInViewModel.autoLoginState
+ .flowWithLifecycle(this.lifecycle)
+ .onEach {
+ if(it) {
+ startActivity(Intent(this, HomeActivity::class.java))
+ finish()
+ }
+ }.launchIn(this.lifecycleScope)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/onboarding/OnBoardingActivity.kt b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/onboarding/OnBoardingActivity.kt
new file mode 100644
index 0000000..e687c28
--- /dev/null
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/onboarding/OnBoardingActivity.kt
@@ -0,0 +1,62 @@
+package co.kr.sopt_seminar_30th.presentation.ui.onboarding
+
+import android.content.Intent
+import android.os.Bundle
+import androidx.activity.viewModels
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import co.kr.sopt_seminar_30th.R
+import co.kr.sopt_seminar_30th.data.datasource.local.SopthubDataStore
+import co.kr.sopt_seminar_30th.databinding.ActivityOnBoardingBinding
+import co.kr.sopt_seminar_30th.presentation.ui.auth.SignInActivity
+import co.kr.sopt_seminar_30th.presentation.ui.base.BaseActivity
+import co.kr.sopt_seminar_30th.presentation.ui.home.HomeActivity
+import co.kr.sopt_seminar_30th.presentation.viewmodel.OnBoardingViewModel
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class OnBoardingActivity : BaseActivity() {
+ override val layoutRes: Int
+ get() = R.layout.activity_on_boarding
+
+ private val viewModel by viewModels()
+
+ @Inject
+ lateinit var dataStore: SopthubDataStore
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ checkAutoLoginEnabled()
+ checkOnBoardingEnabled()
+ observeData()
+ }
+
+ private fun checkAutoLoginEnabled() {
+ if (dataStore.autoLogin) {
+ viewModel.checkAuthorization(dataStore.userId)
+ }
+ }
+
+ private fun checkOnBoardingEnabled() {
+ if (dataStore.onBoardingEnabled) {
+ if (!isFinishing) {
+ startActivity(Intent(this, SignInActivity::class.java))
+ finish()
+ }
+ }
+ }
+
+ private fun observeData() {
+ viewModel.autoLoginState
+ .flowWithLifecycle(this.lifecycle)
+ .onEach {
+ if (it) {
+ startActivity(Intent(this, HomeActivity::class.java))
+ finish()
+ }
+ }.launchIn(this.lifecycleScope)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/onboarding/OnBoardingFirstFragment.kt b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/onboarding/OnBoardingFirstFragment.kt
new file mode 100644
index 0000000..6b63384
--- /dev/null
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/onboarding/OnBoardingFirstFragment.kt
@@ -0,0 +1,30 @@
+package co.kr.sopt_seminar_30th.presentation.ui.onboarding
+
+import android.os.Bundle
+import android.view.View
+import androidx.navigation.fragment.findNavController
+import co.kr.sopt_seminar_30th.R
+import co.kr.sopt_seminar_30th.data.datasource.local.SopthubDataStore
+import co.kr.sopt_seminar_30th.databinding.FragmentOnBoardingFirstBinding
+import co.kr.sopt_seminar_30th.presentation.ui.base.BaseFragment
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class OnBoardingFirstFragment : BaseFragment() {
+ override val TAG: String
+ get() = OnBoardingFirstFragment::class.java.simpleName
+ override val layoutRes: Int
+ get() = R.layout.fragment_on_boarding_first
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setOnBtnNextClickListener()
+ }
+
+ private fun setOnBtnNextClickListener() {
+ binding.btnOnBoardingNext.setOnClickListener {
+ findNavController().navigate(R.id.action_fragment_on_boarding_first_to_fragment_on_boarding_second)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/onboarding/OnBoardingSecondFragment.kt b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/onboarding/OnBoardingSecondFragment.kt
new file mode 100644
index 0000000..97d3f48
--- /dev/null
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/onboarding/OnBoardingSecondFragment.kt
@@ -0,0 +1,28 @@
+package co.kr.sopt_seminar_30th.presentation.ui.onboarding
+
+import android.os.Bundle
+import android.view.View
+import androidx.navigation.fragment.findNavController
+import co.kr.sopt_seminar_30th.R
+import co.kr.sopt_seminar_30th.databinding.FragmentOnBoardingSecondBinding
+import co.kr.sopt_seminar_30th.presentation.ui.base.BaseFragment
+import dagger.hilt.android.AndroidEntryPoint
+
+@AndroidEntryPoint
+class OnBoardingSecondFragment : BaseFragment() {
+ override val TAG: String
+ get() = OnBoardingSecondFragment::class.java.simpleName
+ override val layoutRes: Int
+ get() = R.layout.fragment_on_boarding_second
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setOnBtnNextClickListener()
+ }
+
+ private fun setOnBtnNextClickListener() {
+ binding.btnOnBoardingNext.setOnClickListener {
+ findNavController().navigate(R.id.action_fragment_on_boarding_second_to_fragment_on_boarding_third)
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/onboarding/OnBoardingThirdFragment.kt b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/onboarding/OnBoardingThirdFragment.kt
new file mode 100644
index 0000000..7587d06
--- /dev/null
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/ui/onboarding/OnBoardingThirdFragment.kt
@@ -0,0 +1,35 @@
+package co.kr.sopt_seminar_30th.presentation.ui.onboarding
+
+import android.os.Bundle
+import android.view.View
+import androidx.navigation.fragment.findNavController
+import co.kr.sopt_seminar_30th.R
+import co.kr.sopt_seminar_30th.data.datasource.local.SopthubDataStore
+import co.kr.sopt_seminar_30th.databinding.FragmentOnBoardingThirdBinding
+import co.kr.sopt_seminar_30th.presentation.ui.base.BaseFragment
+import dagger.hilt.android.AndroidEntryPoint
+import javax.inject.Inject
+
+@AndroidEntryPoint
+class OnBoardingThirdFragment : BaseFragment() {
+ override val TAG: String
+ get() = OnBoardingThirdFragment::class.java.simpleName
+ override val layoutRes: Int
+ get() = R.layout.fragment_on_boarding_third
+
+ @Inject
+ lateinit var dataStore: SopthubDataStore
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ setOnBtnStartClickListener()
+ }
+
+ private fun setOnBtnStartClickListener() {
+ binding.btnOnBoardingStart.setOnClickListener {
+ dataStore.onBoardingEnabled = true
+ findNavController().navigate(R.id.action_fragment_on_boarding_third_to_activity_sign_in)
+ requireActivity().finish()
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/presentation/viewmodel/HomeViewModel.kt b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/viewmodel/HomeViewModel.kt
index ad20b95..8d35734 100644
--- a/app/src/main/java/co/kr/sopt_seminar_30th/presentation/viewmodel/HomeViewModel.kt
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/viewmodel/HomeViewModel.kt
@@ -9,6 +9,7 @@ import androidx.lifecycle.viewModelScope
import co.kr.sopt_seminar_30th.domain.entity.home.UserFollow
import co.kr.sopt_seminar_30th.domain.entity.home.UserProfile
import co.kr.sopt_seminar_30th.domain.entity.home.UserRepository
+import co.kr.sopt_seminar_30th.domain.repository.local.AuthorizationRepository
import co.kr.sopt_seminar_30th.domain.repository.remote.HomeRepository
import co.kr.sopt_seminar_30th.domain.usecase.user.GetUserIdUseCase
import co.kr.sopt_seminar_30th.domain.usecase.user.TurnOffAutoLoginUseCase
@@ -23,7 +24,8 @@ import javax.inject.Inject
class HomeViewModel @Inject constructor(
private val getUserIdUseCase: GetUserIdUseCase,
private val turnOffAutoLoginUseCase: TurnOffAutoLoginUseCase,
- private val homeRepository: HomeRepository
+ private val homeRepository: HomeRepository,
+ private val authorizationRepository: AuthorizationRepository
) : ViewModel() {
private var id: String = ""
@@ -216,10 +218,14 @@ class HomeViewModel @Inject constructor(
fun turnOffAutoLogin() {
viewModelScope.launch {
- kotlin.runCatching {
+ runCatching {
turnOffAutoLoginUseCase()
}.onSuccess {
- _turnOffSuccess.value = true
+ runCatching {
+ authorizationRepository.deleteAuthorization(id, true)
+ }.onSuccess {
+ _turnOffSuccess.value = true
+ }
}
}
}
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/presentation/viewmodel/OnBoardingViewModel.kt b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/viewmodel/OnBoardingViewModel.kt
new file mode 100644
index 0000000..644a37e
--- /dev/null
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/viewmodel/OnBoardingViewModel.kt
@@ -0,0 +1,32 @@
+package co.kr.sopt_seminar_30th.presentation.viewmodel
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import co.kr.sopt_seminar_30th.domain.repository.local.AuthorizationRepository
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
+import kotlinx.coroutines.launch
+import timber.log.Timber
+import javax.inject.Inject
+
+@HiltViewModel
+class OnBoardingViewModel @Inject constructor(
+ private val authorizationRepository: AuthorizationRepository
+): ViewModel() {
+ private val _autoLoginState = MutableStateFlow(false)
+ val autoLoginState = _autoLoginState.asStateFlow()
+
+ fun checkAuthorization(userId: String) {
+ viewModelScope.launch {
+ runCatching {
+ authorizationRepository.getAuthorization(userId)
+ }.onSuccess {
+ _autoLoginState.emit(true)
+ }.onFailure {
+ _autoLoginState.emit(false)
+ Timber.e(it)
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/co/kr/sopt_seminar_30th/presentation/viewmodel/SignInViewModel.kt b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/viewmodel/SignInViewModel.kt
index f2a03b6..6684f1f 100644
--- a/app/src/main/java/co/kr/sopt_seminar_30th/presentation/viewmodel/SignInViewModel.kt
+++ b/app/src/main/java/co/kr/sopt_seminar_30th/presentation/viewmodel/SignInViewModel.kt
@@ -5,12 +5,15 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
+import co.kr.sopt_seminar_30th.domain.repository.local.AuthorizationRepository
import co.kr.sopt_seminar_30th.domain.repository.remote.SignInRepository
import co.kr.sopt_seminar_30th.domain.usecase.user.GetAutoLoginUseCase
import co.kr.sopt_seminar_30th.domain.usecase.user.GetUserIdUseCase
import co.kr.sopt_seminar_30th.domain.usecase.user.LoginUseCase
import co.kr.sopt_seminar_30th.util.SingleLiveEvent
import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import retrofit2.HttpException
import timber.log.Timber
@@ -22,25 +25,21 @@ class SignInViewModel @Inject constructor(
private val getUserIdUseCase: GetUserIdUseCase,
private val loginUseCase: LoginUseCase,
private val getAutoLoginUseCase: GetAutoLoginUseCase,
- private val signInRepository: SignInRepository
+ private val signInRepository: SignInRepository,
+ private val authorizationRepository: AuthorizationRepository
) : ViewModel() {
var userId = MutableLiveData()
var userPassword = MutableLiveData()
-
- private var _autoLogin = MutableLiveData(false)
- val autoLogin: LiveData get() = _autoLogin
-
private var _isSuccess = SingleLiveEvent()
val isSuccess: LiveData get() = _isSuccess
-
private var _isEmpty = SingleLiveEvent()
val isEmpty: LiveData get() = _isEmpty
-
private var _isEmailIncorrect = SingleLiveEvent()
val isEmailIncorrect: LiveData get() = _isEmailIncorrect
-
private var _isPasswordIncorrect = SingleLiveEvent()
val isPasswordIncorrect: LiveData get() = _isPasswordIncorrect
+ private val _autoLoginState = MutableStateFlow(false)
+ val autoLoginState = _autoLoginState.asStateFlow()
fun login() {
if (!userId.value.isNullOrBlank() && !userPassword.value.isNullOrBlank()) {
@@ -53,6 +52,9 @@ class SignInViewModel @Inject constructor(
.onSuccess {
_isSuccess.value = true
loginUseCase(email, password)
+ runCatching {
+ authorizationRepository.insertAuthorization(email, true)
+ }.onFailure { Timber.e(it) }
}
.onFailure { exception ->
when ((exception as HttpException).code()) {
@@ -67,4 +69,17 @@ class SignInViewModel @Inject constructor(
_isEmpty.value = true
}
}
+
+ fun checkAuthorization(userId: String) {
+ viewModelScope.launch {
+ runCatching {
+ authorizationRepository.getAuthorization(userId)
+ }.onSuccess {
+ _autoLoginState.emit(true)
+ }.onFailure {
+ _autoLoginState.emit(false)
+ Timber.e(it)
+ }
+ }
+ }
}
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_on_boarding.xml b/app/src/main/res/layout/activity_on_boarding.xml
new file mode 100644
index 0000000..d282c90
--- /dev/null
+++ b/app/src/main/res/layout/activity_on_boarding.xml
@@ -0,0 +1,41 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_on_boarding_first.xml b/app/src/main/res/layout/fragment_on_boarding_first.xml
new file mode 100644
index 0000000..2c175fa
--- /dev/null
+++ b/app/src/main/res/layout/fragment_on_boarding_first.xml
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_on_boarding_second.xml b/app/src/main/res/layout/fragment_on_boarding_second.xml
new file mode 100644
index 0000000..03be5e9
--- /dev/null
+++ b/app/src/main/res/layout/fragment_on_boarding_second.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_on_boarding_third.xml b/app/src/main/res/layout/fragment_on_boarding_third.xml
new file mode 100644
index 0000000..fadf897
--- /dev/null
+++ b/app/src/main/res/layout/fragment_on_boarding_third.xml
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/navigation/nav_graph_on_boarding.xml b/app/src/main/res/navigation/nav_graph_on_boarding.xml
new file mode 100644
index 0000000..2cee0e1
--- /dev/null
+++ b/app/src/main/res/navigation/nav_graph_on_boarding.xml
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index cb267ca..267efca 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -28,4 +28,10 @@
프로필
홈
더보기
+ WELCOME
+ 온
+ next
+ 보
+ 딩
+ start
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index a542095..e92578d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -8,7 +8,7 @@ buildscript {
plugins {
id 'com.android.application' version '7.1.2' apply false
id 'com.android.library' version '7.1.2' apply false
- id 'org.jetbrains.kotlin.android' version '1.6.10' apply false
+ id 'org.jetbrains.kotlin.android' version '1.6.21' apply false
}
task clean(type: Delete) {