Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.umc.edison.data.model.bubble.BubbleEntity
interface BubbleLocalDataSource {
// CREATE
suspend fun addBubbles(bubbles: List<BubbleEntity>)
suspend fun addBubble(bubble: BubbleEntity) : BubbleEntity
suspend fun addBubble(bubble: BubbleEntity, userEmail: String? = null) : BubbleEntity

// READ
suspend fun getAllActiveBubbles(): List<BubbleEntity>
Expand All @@ -24,6 +24,7 @@ interface BubbleLocalDataSource {
suspend fun trashBubbles(bubbles: List<BubbleEntity>)
suspend fun markAsSynced(bubble: BubbleEntity)
suspend fun syncBubbles(bubbles: List<BubbleEntity>)
suspend fun linkGuestBubblesToUser(userEmail: String)

// DELETE
suspend fun deleteBubbles(bubbles: List<BubbleEntity>)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package com.umc.edison.data.repository

import android.util.Log
import com.umc.edison.data.bound.FlowBoundResourceFactory
import com.umc.edison.data.datasources.BubbleLocalDataSource
import com.umc.edison.data.datasources.BubbleRemoteDataSource
import com.umc.edison.data.model.bubble.ClusteredBubbleEntity
import com.umc.edison.data.model.bubble.KeywordBubbleEntity
import com.umc.edison.data.model.bubble.toData
import com.umc.edison.common.logging.AppLogger
import com.umc.edison.data.token.TokenManager
import com.umc.edison.domain.DataResource
import com.umc.edison.domain.model.bubble.Bubble
import com.umc.edison.domain.model.bubble.ClusteredBubble
Expand All @@ -19,7 +21,7 @@ import javax.inject.Inject
class BubbleRepositoryImpl @Inject constructor(
private val bubbleLocalDataSource: BubbleLocalDataSource,
private val bubbleRemoteDataSource: BubbleRemoteDataSource,
private val resourceFactory: FlowBoundResourceFactory
private val resourceFactory: FlowBoundResourceFactory,
) : BubbleRepository {
// CREATE
override fun addBubbles(bubbles: List<Bubble>): Flow<DataResource<Unit>> =
Expand All @@ -41,7 +43,9 @@ class BubbleRepositoryImpl @Inject constructor(

override fun addBubble(bubble: Bubble): Flow<DataResource<Bubble>> =
resourceFactory.sync(
localAction = { bubbleLocalDataSource.addBubble(bubble.toData()) },
localAction = {
bubbleLocalDataSource.addBubble(bubble.toData())
Comment thread
ally010314 marked this conversation as resolved.
},
Comment thread
ally010314 marked this conversation as resolved.
remoteSync = {
val newBubble = bubbleLocalDataSource.getActiveBubble(bubble.id)
bubbleRemoteDataSource.syncBubble(newBubble)
Expand Down Expand Up @@ -193,6 +197,10 @@ class BubbleRepositoryImpl @Inject constructor(
}
)

override suspend fun linkGuestBubblesToUser(userEmail: String) {
bubbleLocalDataSource.linkGuestBubblesToUser(userEmail)
}

// DELETE
override fun deleteBubbles(bubbles: List<Bubble>): Flow<DataResource<Unit>> =
resourceFactory.sync(
Expand All @@ -212,7 +220,8 @@ class BubbleRepositoryImpl @Inject constructor(
}
},
onRemoteSuccess = { deletedBubbles ->
val localBubbles = deletedBubbles.map { remote -> bubbleLocalDataSource.getRawBubble(remote.id) }
val localBubbles =
deletedBubbles.map { remote -> bubbleLocalDataSource.getRawBubble(remote.id) }
bubbleLocalDataSource.deleteBubbles(localBubbles)
}
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import com.umc.edison.data.token.TokenManager
import com.umc.edison.domain.DataResource
import com.umc.edison.domain.model.identity.Identity
import com.umc.edison.domain.model.user.User
import com.umc.edison.domain.repository.BubbleRepository
import com.umc.edison.domain.repository.UserRepository
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
Expand All @@ -18,11 +19,12 @@ class UserRepositoryImpl @Inject constructor(
private val resourceFactory: FlowBoundResourceFactory,
private val tokenManager: TokenManager,
) : UserRepository {
// CREATE

override fun googleLogin(idToken: String): Flow<DataResource<User>> = resourceFactory.remote(
dataAction = {
val userWithToken: UserWithTokenEntity = userRemoteDataSource.googleLogin(idToken)
tokenManager.setToken(userWithToken.accessToken, userWithToken.refreshToken)
tokenManager.saveUserEmail(userWithToken.user.email)
userWithToken
}
)
Expand All @@ -33,23 +35,21 @@ class UserRepositoryImpl @Inject constructor(
identity: List<Identity>
): Flow<DataResource<User>> = resourceFactory.remote(
dataAction = {
val userWithToken: UserWithTokenEntity =
userRemoteDataSource.googleSignup(
idToken = idToken,
nickname = nickname,
identity = identity.map { it.toData() }
)
val userWithToken: UserWithTokenEntity = userRemoteDataSource.googleSignup(
idToken = idToken,
nickname = nickname,
identity = identity.map { it.toData() }
)
tokenManager.setToken(userWithToken.accessToken, userWithToken.refreshToken)
tokenManager.saveUserEmail(userWithToken.user.email)
userWithToken
}
)



// READ
override fun getLogInState(): Flow<DataResource<Boolean>> = resourceFactory.local(
dataAction = {
tokenManager.loadAccessToken()?.isNotEmpty()
tokenManager.loadAccessToken()?.isNotEmpty() == true
}
)

Expand Down
32 changes: 27 additions & 5 deletions app/src/main/java/com/umc/edison/data/token/TokenManager.kt
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
package com.umc.edison.data.token

import com.umc.edison.data.datasources.PrefDataSource
import com.umc.edison.data.di.ApplicationScope
import javax.inject.Inject
import javax.inject.Singleton
import com.umc.edison.data.datasources.PrefDataSource
import com.umc.edison.data.di.ApplicationScope
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
Expand All @@ -17,19 +17,27 @@ class TokenManager @Inject constructor(

private val mutex = Mutex()

private var cachedAccessToken: String? = null
private var cachedRefreshToken: String? = null

init {
applicationScope.launch {
preloadTokens()
loadUserEmail()
}
}

private var cachedAccessToken: String? = null
private var cachedRefreshToken: String? = null
private var cachedUserEmail: String? = null


override fun getAccessToken(): String? = cachedAccessToken

override fun getRefreshToken(): String? = cachedRefreshToken

suspend fun getUserEmail(): String? {
if (cachedUserEmail != null) return cachedUserEmail
return loadUserEmail()
}

override suspend fun clearCachedTokens() {
mutex.withLock {
cachedAccessToken = null
Expand Down Expand Up @@ -60,6 +68,17 @@ class TokenManager @Inject constructor(
}
}

suspend fun loadUserEmail(): String? {
val email = prefDataSource.get(USER_EMAIL_KEY, "")
cachedUserEmail = email.ifEmpty { null }
return cachedUserEmail
}

suspend fun saveUserEmail(userEmail: String) {
cachedUserEmail = userEmail
prefDataSource.set(USER_EMAIL_KEY, userEmail)
}

suspend fun setToken(accessToken: String, refreshToken: String? = null) {
mutex.withLock {
cachedAccessToken = accessToken
Expand All @@ -75,8 +94,10 @@ class TokenManager @Inject constructor(
mutex.withLock {
cachedAccessToken = null
cachedRefreshToken = null
cachedUserEmail = null
prefDataSource.remove(ACCESS_TOKEN_KEY)
prefDataSource.remove(REFRESH_TOKEN_KEY)
prefDataSource.remove(USER_EMAIL_KEY)
}
}

Expand All @@ -90,5 +111,6 @@ class TokenManager @Inject constructor(
companion object {
private const val ACCESS_TOKEN_KEY = "access_token"
private const val REFRESH_TOKEN_KEY = "refresh_token"
private const val USER_EMAIL_KEY = "user_email"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ interface BubbleRepository {
fun recoverBubbles(bubbles: List<Bubble>): Flow<DataResource<Unit>>
fun updateBubbles(bubbles: List<Bubble>): Flow<DataResource<Unit>>
fun updateBubble(bubble: Bubble): Flow<DataResource<Bubble>>
suspend fun linkGuestBubblesToUser(userEmail: String)

// DELETE
fun deleteBubbles(bubbles: List<Bubble>): Flow<DataResource<Unit>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,21 @@ package com.umc.edison.domain.usecase.user

import com.umc.edison.domain.DataResource
import com.umc.edison.domain.model.user.User
import com.umc.edison.domain.repository.BubbleRepository
import com.umc.edison.domain.repository.UserRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onEach
import javax.inject.Inject

class GoogleLoginUseCase @Inject constructor(
private val userRepository: UserRepository
private val userRepository: UserRepository,
private val bubbleRepository: BubbleRepository
) {
operator fun invoke(idToken: String): Flow<DataResource<User>> =
userRepository.googleLogin(idToken)
}
userRepository.googleLogin(idToken).onEach { resource ->
if (resource is DataResource.Success) {
val userEmail = resource.data.email
bubbleRepository.linkGuestBubblesToUser(userEmail)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,25 @@ package com.umc.edison.domain.usecase.user
import com.umc.edison.domain.DataResource
import com.umc.edison.domain.model.identity.Identity
import com.umc.edison.domain.model.user.User
import com.umc.edison.domain.repository.BubbleRepository
import com.umc.edison.domain.repository.UserRepository
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.onEach
import javax.inject.Inject

class GoogleSignUpUseCase @Inject constructor(
private val userRepository: UserRepository
private val userRepository: UserRepository,
private val bubbleRepository: BubbleRepository
) {
operator fun invoke(
idToken: String,
nickname: String,
identities: List<Identity>
): Flow<DataResource<User>> =
userRepository.googleSignUp(idToken, nickname, identities)
userRepository.googleSignUp(idToken, nickname, identities).onEach { resource ->
if (resource is DataResource.Success) {
val userEmail = resource.data.email
bubbleRepository.linkGuestBubblesToUser(userEmail)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ open class BaseLocalDataSourceImpl<T : BaseSyncLocal>(

// UPDATE
suspend fun update(entity: T, tableName: String, isSynced: Boolean = false) {
val query = SimpleSQLiteQuery("SELECT * FROM $tableName WHERE id = '${entity.uuid}'")
val query = SimpleSQLiteQuery(
"SELECT * FROM $tableName WHERE id = ?",
arrayOf(entity.uuid)
)
baseDao.getById(query)?.let {
entity.createdAt = it.createdAt
entity.updatedAt = Date()
Expand All @@ -36,7 +39,10 @@ open class BaseLocalDataSourceImpl<T : BaseSyncLocal>(

suspend fun markAsSynced(tableName: String, id: String) {
val date = Date()
val query = SimpleSQLiteQuery("UPDATE $tableName SET is_synced = 1, updated_at = '$date' WHERE id = '$id'")
val query = SimpleSQLiteQuery(
"UPDATE $tableName SET is_synced = 1, updated_at = ? WHERE id = ?",
arrayOf(date.time, id)
)
baseDao.markAsSynced(query)
}
}
Loading