Skip to content

Commit

Permalink
Merge pull request droidknights#245 from l2hyunwoo/feature/droidknigh…
Browse files Browse the repository at this point in the history
…ts#202

[feature/droidknights#202] 앱이 종료된 이후에도 북마크 세션들을 유지한다
  • Loading branch information
laco-dev authored Aug 31, 2023
2 parents 2355550 + 034b3bc commit 6fa292c
Show file tree
Hide file tree
Showing 11 changed files with 92 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import com.droidknights.app2023.core.data.repository.DefaultSponsorRepository
import com.droidknights.app2023.core.data.repository.SessionRepository
import com.droidknights.app2023.core.data.repository.SettingsRepository
import com.droidknights.app2023.core.data.repository.SponsorRepository
import com.droidknights.app2023.core.datastore.datasource.DefaultSessionPreferencesDataSource
import com.droidknights.app2023.core.datastore.datasource.SessionPreferencesDataSource
import dagger.Binds
import dagger.Module
import dagger.Provides
Expand All @@ -33,6 +35,11 @@ internal abstract class DataModule {
repository: DefaultSettingsRepository,
): SettingsRepository

@Binds
abstract fun bindSessionLocalDataSource(
dataSource: DefaultSessionPreferencesDataSource,
): SessionPreferencesDataSource

@InstallIn(SingletonComponent::class)
@Module
internal object FakeModule {
Expand All @@ -47,7 +54,8 @@ internal abstract class DataModule {
@Singleton
fun provideSessionRepository(
githubRawApi: GithubRawApi,
): SessionRepository = DefaultSessionRepository(githubRawApi)
sessionDataSource: SessionPreferencesDataSource,
): SessionRepository = DefaultSessionRepository(githubRawApi, sessionDataSource)

@Provides
@Singleton
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
package com.droidknights.app2023.core.data.repository

import com.droidknights.app2023.core.data.api.GithubRawApi
import com.droidknights.app2023.core.datastore.datasource.SessionPreferencesDataSource
import com.droidknights.app2023.core.data.mapper.toData
import com.droidknights.app2023.core.model.Session
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.filterNotNull
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.flow.first
import javax.inject.Inject

internal class DefaultSessionRepository @Inject constructor(
private val githubRawApi: GithubRawApi,
private val sessionDataSource: SessionPreferencesDataSource
) : SessionRepository {
private var cachedSessions: List<Session> = emptyList()

/**
* TODO : 북마크 아이디가 앱이 종료된 이후에도 유지되도록 한다
*/
private val bookmarkIds: MutableStateFlow<Set<String>> = MutableStateFlow(emptySet())
private val bookmarkIds: Flow<Set<String>> = sessionDataSource.bookmarkedSession

override suspend fun getSessions(): List<Session> {
return githubRawApi.getSessions()
Expand All @@ -40,12 +38,13 @@ internal class DefaultSessionRepository @Inject constructor(
}

override suspend fun bookmarkSession(sessionId: String, bookmark: Boolean) {
bookmarkIds.update { ids ->
val currentBookmarkedSessionIds = bookmarkIds.first()
sessionDataSource.updateBookmarkedSession(
if (bookmark) {
ids + sessionId
currentBookmarkedSessionIds + sessionId
} else {
ids - sessionId
currentBookmarkedSessionIds - sessionId
}
}
)
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.droidknights.app2023.core.data.repository

import com.droidknights.app2023.core.datastore.SettingsPreferencesDataSource
import com.droidknights.app2023.core.datastore.datasource.SettingsPreferencesDataSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.map
import javax.inject.Inject
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package com.droidknights.app2023.core.data.datastore.fake

import com.droidknights.app2023.core.datastore.datasource.SessionPreferencesDataSource
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.filterNotNull

class FakeSessionPreferencesDataSource : SessionPreferencesDataSource {
private val _bookmarkedSession = MutableStateFlow(emptySet<String>())
override val bookmarkedSession: Flow<Set<String>> = _bookmarkedSession.filterNotNull()

override suspend fun updateBookmarkedSession(bookmarkedSession: Set<String>) {
_bookmarkedSession.value = bookmarkedSession.toSet()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.droidknights.app2023.core.data.repository

import app.cash.turbine.test
import com.droidknights.app2023.core.data.api.fake.FakeGithubRawApi
import com.droidknights.app2023.core.data.datastore.fake.FakeSessionPreferencesDataSource
import com.droidknights.app2023.core.model.Level
import com.droidknights.app2023.core.model.Room
import com.droidknights.app2023.core.model.Session
Expand All @@ -13,7 +14,8 @@ internal class DefaultSessionRepositoryTest : StringSpec() {

init {
val repository: SessionRepository = DefaultSessionRepository(
githubRawApi = FakeGithubRawApi()
githubRawApi = FakeGithubRawApi(),
sessionDataSource = FakeSessionPreferencesDataSource()
)
"역직렬화 테스트" {
val expected = Session(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.droidknights.app2023.core.datastore.datasource

import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.stringSetPreferencesKey
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import javax.inject.Named

class DefaultSessionPreferencesDataSource @Inject constructor(
@Named("session") private val dataStore: DataStore<Preferences>
) : SessionPreferencesDataSource {
object PreferencesKey {
val BOOKMARKED_SESSION = stringSetPreferencesKey("BOOKMARKED_SESSION")
}

override val bookmarkedSession = dataStore.data.map { preferences ->
preferences[PreferencesKey.BOOKMARKED_SESSION] ?: emptySet()
}

override suspend fun updateBookmarkedSession(bookmarkedSession: Set<String>) {
dataStore.edit { preferences ->
preferences[PreferencesKey.BOOKMARKED_SESSION] = bookmarkedSession
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.droidknights.app2023.core.datastore.datasource

import kotlinx.coroutines.flow.Flow

interface SessionPreferencesDataSource {
val bookmarkedSession: Flow<Set<String>>
suspend fun updateBookmarkedSession(bookmarkedSession: Set<String>)
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.droidknights.app2023.core.datastore
package com.droidknights.app2023.core.datastore.datasource

import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
Expand All @@ -7,9 +7,10 @@ import androidx.datastore.preferences.core.edit
import com.droidknights.app2023.core.datastore.model.SettingsData
import kotlinx.coroutines.flow.map
import javax.inject.Inject
import javax.inject.Named

class SettingsPreferencesDataSource @Inject constructor(
private val dataStore: DataStore<Preferences>
@Named("setting") private val dataStore: DataStore<Preferences>
) {
object PreferencesKey {
val IS_DARK_THEME = booleanPreferencesKey("IS_DARK_THEME")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,28 @@ import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Named
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object DataStoreModule {
private const val DATASTORE_NAME = "SETTINGS_PREFERENCES"
private val Context.dataStore by preferencesDataStore(DATASTORE_NAME)
private const val SETTING_DATASTORE_NAME = "SETTINGS_PREFERENCES"
private const val SESSION_DATASTORE_NAME = "SESSION_PREFERENCES"
private val Context.settingDataStore by preferencesDataStore(SETTING_DATASTORE_NAME)
private val Context.sessionDataStore by preferencesDataStore(SESSION_DATASTORE_NAME)

@Provides
@Singleton
@Named("setting")
fun provideSettingsDataStore(
@ApplicationContext context: Context
): DataStore<Preferences> = context.dataStore
): DataStore<Preferences> = context.settingDataStore

@Provides
@Singleton
@Named("session")
fun provideSessionDataStore(
@ApplicationContext context: Context
): DataStore<Preferences> = context.sessionDataStore
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.droidknights.app2023.core.datastore

import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import com.droidknights.app2023.core.datastore.datasource.SettingsPreferencesDataSource
import io.kotest.core.spec.style.StringSpec
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.first
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package com.droidknights.app2023.core.domain.usecase

import com.droidknights.app2023.core.model.Session
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.zip
import javax.inject.Inject

class GetBookmarkedSessionsUseCase @Inject constructor(
Expand All @@ -14,7 +14,7 @@ class GetBookmarkedSessionsUseCase @Inject constructor(
suspend operator fun invoke(): Flow<List<Session>> {
return flow {
emit(getSessionsUseCase())
}.zip(getBookmarkedSessionIdsUseCase()) { allSession, bookmarkedSessions ->
}.combine(getBookmarkedSessionIdsUseCase()) { allSession, bookmarkedSessions ->
allSession
.filter { session -> bookmarkedSessions.contains(session.id) }
.sortedBy { it.startTime }
Expand Down

0 comments on commit 6fa292c

Please sign in to comment.