Skip to content
Merged
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 @@ -57,7 +57,7 @@ class SplashViewModel
}

accountRepository
.renewTokens()
.createTokens()
.onSuccess {
_uiEffect.send(NavigateToMain)
}.onFailure {
Expand Down
1 change: 1 addition & 0 deletions core/database/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/build
20 changes: 20 additions & 0 deletions core/database/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import com.into.websoso.buildConfigs

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚫 [ktlint] standard:no-unused-imports reported by reviewdog 🐶
Unused import

import com.into.websoso.setNamespace

plugins {
id("websoso.android.library")
}

android {
setNamespace("core.database")
}

dependencies {
// 데이터 레이어 의존성
implementation(projects.data.library)

// 데이터베이스 관련 라이브러리
implementation(libs.room.ktx)
implementation(libs.room.runtime)
kapt(libs.room.compiler)
}
Empty file.
21 changes: 21 additions & 0 deletions core/database/proguard-rules.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html

# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
4 changes: 4 additions & 0 deletions core/database/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.into.websoso.core.database

import androidx.room.Database
import androidx.room.RoomDatabase
import com.into.websoso.core.database.datasource.library.NovelDao
import com.into.websoso.core.database.entity.NovelEntity

@Database(
entities = [NovelEntity::class],
version = 1,
exportSchema = false,
)
internal abstract class WebsosoDatabase : RoomDatabase() {
internal abstract fun novelDao(): NovelDao
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.into.websoso.core.database.datasource.library

import com.into.websoso.data.library.datasource.LibraryLocalDataSource
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import javax.inject.Inject
import javax.inject.Singleton

internal class DefaultLibraryDataSource
@Inject
constructor(
private val novelDao: NovelDao,
) : LibraryLocalDataSource {
override suspend fun selectAllNovels() {
TODO("Not yet implemented")
}
}
Comment on lines +11 to +19

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

미구현된 메서드 구현 필요

selectAllNovels() 메서드가 TODO로 남아있어 기능이 구현되지 않았습니다. novelDao를 활용하여 이 메서드를 완전히 구현해야 합니다.

다음과 같이 메서드를 구현하는 것을 권장합니다:

- override suspend fun selectAllNovels() {
-     TODO("Not yet implemented")
- }
+ override suspend fun selectAllNovels() = novelDao.selectAllNovels()

또한, LibraryLocalDataSource의 반환 타입에 따라 적절한 모델 변환이 필요할 수 있습니다. 만약 LibraryLocalDataSource 인터페이스의 메서드가 특정 반환 타입을 가지고 있다면 그에 맞게 수정해주세요.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
internal class DefaultLibraryDataSource
@Inject
constructor(
private val novelDao: NovelDao,
) : LibraryLocalDataSource {
override suspend fun selectAllNovels() {
TODO("Not yet implemented")
}
}
internal class DefaultLibraryDataSource
@Inject
constructor(
private val novelDao: NovelDao,
) : LibraryLocalDataSource {
override suspend fun selectAllNovels() = novelDao.selectAllNovels()
}
🤖 Prompt for AI Agents
In
core/database/src/main/java/com/into/websoso/core/database/datasource/library/DefaultLibraryDataSource.kt
around lines 11 to 19, the selectAllNovels() method is currently unimplemented
with a TODO. Implement this method by using novelDao to fetch all novels from
the database. Ensure the return type matches the LibraryLocalDataSource
interface's definition, and if necessary, convert the data from novelDao into
the appropriate model before returning it.


@Module
@InstallIn(SingletonComponent::class)
internal interface LibraryDataSourceModule {
@Binds
@Singleton
fun bindLibraryLocalDataSource(defaultLibraryDataSource: DefaultLibraryDataSource): LibraryLocalDataSource
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.into.websoso.core.database.datasource.library

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import com.into.websoso.core.database.WebsosoDatabase
import com.into.websoso.core.database.entity.NovelEntity
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.flow.Flow
import javax.inject.Singleton

@Dao
internal interface NovelDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun insertNovels(novels: List<NovelEntity>)

@Query(
value = """
SELECT * FROM novels
ORDER BY userNovelId
DESC
""",
)
fun selectAllNovels(): Flow<List<NovelEntity>>

@Query(
value = """
SELECT * FROM novels
WHERE userNovelId = :id
""",
)
suspend fun selectNovelById(id: Long): NovelEntity?

@Query(
value = """
DELETE FROM novels
""",
)
suspend fun deleteAllNovels()
}

@Module
@InstallIn(SingletonComponent::class)
internal object NovelDaoModule {
@Provides
@Singleton
internal fun provideNovelDao(database: WebsosoDatabase): NovelDao = database.novelDao()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.into.websoso.core.database.di

import android.content.Context
import androidx.room.Room
import com.into.websoso.core.database.WebsosoDatabase
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)
internal object DatabaseModule {
@Provides
@Singleton
internal fun provideDatabase(
@ApplicationContext context: Context,
): WebsosoDatabase =
Room
.databaseBuilder(
context,
WebsosoDatabase::class.java,
"websoso.db",
).build()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.into.websoso.core.database.entity

import androidx.room.Entity
import androidx.room.PrimaryKey

@Entity(tableName = "novels")
internal data class NovelEntity(
@PrimaryKey
val userNovelId: Long,
val novelId: Long,
val author: String,
val title: String,
val novelImage: String,
val novelRating: Float,
)
Original file line number Diff line number Diff line change
Expand Up @@ -20,31 +20,31 @@ internal class DefaultAccountDataSource
constructor(
@AccountDataStore private val accountDataStore: DataStore<Preferences>,
) : AccountLocalDataSource {
override suspend fun accessToken(): String =
override suspend fun selectAccessToken(): String =
accountDataStore.data
.map { preferences ->
preferences[ACCESS_TOKEN].orEmpty()
}.first()

override suspend fun refreshToken(): String =
override suspend fun selectRefreshToken(): String =
accountDataStore.data
.map { preferences ->
preferences[REFRESH_TOKEN].orEmpty()
}.first()

override suspend fun saveAccessToken(accessToken: String) {
override suspend fun updateAccessToken(accessToken: String) {
accountDataStore.edit { preferences ->
preferences[ACCESS_TOKEN] = accessToken
}
}

override suspend fun saveRefreshToken(refreshToken: String) {
override suspend fun updateRefreshToken(refreshToken: String) {
accountDataStore.edit { preferences ->
preferences[REFRESH_TOKEN] = refreshToken
}
}

override suspend fun clearTokens() {
override suspend fun deleteTokens() {
accountDataStore.edit { preferences ->
preferences.remove(ACCESS_TOKEN)
preferences.remove(REFRESH_TOKEN)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ internal class AuthorizationAuthenticator
}

private suspend fun renewToken(): String? =
accountRepository.get().renewTokens().fold(
accountRepository.get().createTokens().fold(
onSuccess = { accountRepository.get().accessToken() },
onFailure = {
sessionManager.onSessionExpired()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ class AccountRepository
var isRegisterUser: Boolean = false
private set

suspend fun accessToken(): String = accountLocalDataSource.accessToken()
suspend fun accessToken(): String = accountLocalDataSource.selectAccessToken()

suspend fun refreshToken(): String = accountLocalDataSource.refreshToken()
suspend fun refreshToken(): String = accountLocalDataSource.selectRefreshToken()

suspend fun saveTokens(
suspend fun createAccount(
platform: AuthPlatform,
authToken: AuthToken,
): Result<Unit> =
Expand All @@ -32,33 +32,33 @@ class AccountRepository
authToken = authToken,
)

accountLocalDataSource.saveAccessToken(account.token.accessToken)
accountLocalDataSource.saveRefreshToken(account.token.refreshToken)
accountLocalDataSource.updateAccessToken(account.token.accessToken)
accountLocalDataSource.updateRefreshToken(account.token.refreshToken)
isRegisterUser = account.isRegister
}

suspend fun deleteTokens(deviceIdentifier: String): Result<Unit> =
runCatching {
accountRemoteDataSource
.postLogout(
refreshToken = refreshToken(),
deviceIdentifier = deviceIdentifier,
)

accountLocalDataSource.clearTokens()
}

suspend fun deleteAccount(reason: String): Result<Unit> =
runCatching {
accountRemoteDataSource.postWithdraw(reason = reason)
accountLocalDataSource.clearTokens()
accountLocalDataSource.deleteTokens()
}

suspend fun renewTokens(): Result<Unit> =
suspend fun createTokens(): Result<Unit> =
runCatching {
val tokens = accountRemoteDataSource.postReissue(refreshToken = refreshToken())

accountLocalDataSource.saveAccessToken(tokens.accessToken)
accountLocalDataSource.saveRefreshToken(tokens.refreshToken)
accountLocalDataSource.updateAccessToken(tokens.accessToken)
accountLocalDataSource.updateRefreshToken(tokens.refreshToken)
}

suspend fun deleteTokens(deviceIdentifier: String): Result<Unit> =
runCatching {
accountRemoteDataSource
.postLogout(
refreshToken = refreshToken(),
deviceIdentifier = deviceIdentifier,
)

accountLocalDataSource.deleteTokens()
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
package com.into.websoso.data.account.datasource

interface AccountLocalDataSource {
suspend fun accessToken(): String
suspend fun selectAccessToken(): String

suspend fun refreshToken(): String
suspend fun selectRefreshToken(): String

suspend fun saveAccessToken(accessToken: String)
suspend fun updateAccessToken(accessToken: String)

suspend fun saveRefreshToken(refreshToken: String)
suspend fun updateRefreshToken(refreshToken: String)

suspend fun clearTokens()
suspend fun deleteTokens()
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package com.into.websoso.data.library.datasource

interface LibraryLocalDataSource {
suspend fun getFullLibrary()
suspend fun selectAllNovels()
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class SignInViewModel
) {
viewModelScope.launch {
accountRepository
.saveTokens(
.createAccount(
platform = platform,
authToken = authToken,
).onSuccess {
Expand Down
4 changes: 4 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ fragment-ktx = "1.6.1"
lifecycle-extensions = "2.2.0"
datastore-preferences = "1.1.1"
security-crypto = "1.1.0-alpha06"
room = "2.7.1"

# Testing Libraries
junit = "4.13.2"
Expand Down Expand Up @@ -94,6 +95,9 @@ fragment-ktx = { module = "androidx.fragment:fragment-ktx", version.ref = "fragm
lifecycle-extensions = { module = "androidx.lifecycle:lifecycle-extensions", version.ref = "lifecycle-extensions" }
datastore-preferences = { module = "androidx.datastore:datastore-preferences", version.ref = "datastore-preferences" }
security-crypto = { module = "androidx.security:security-crypto", version.ref = "security-crypto" }
room-runtime = { module = "androidx.room:room-runtime", version.ref = "room" }
room-ktx = { module = "androidx.room:room-ktx", version.ref = "room" }
room-compiler = { module = "androidx.room:room-compiler", version.ref = "room" }

# Testing Libraries
junit = { module = "junit:junit", version.ref = "junit" }
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ include(
":core:auth-kakao",
":core:network",
":core:datastore",
":core:database",
)

include(
Expand Down