Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change CoroutineScope of preferences datastore, instead of redispatching #325

Merged
merged 3 commits into from
Jan 20, 2025
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 @@ -23,7 +23,7 @@ import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.SupervisorJob
import soup.movie.common.ApplicationScope
import soup.movie.common.MainImmediateDispatcher
import soup.movie.common.DefaultDispatcher
import javax.inject.Singleton

@Module
Expand All @@ -34,6 +34,6 @@ object CoroutineScopesModule {
@Provides
@ApplicationScope
fun providesCoroutineScope(
@MainImmediateDispatcher dispatcher: CoroutineDispatcher,
@DefaultDispatcher dispatcher: CoroutineDispatcher,
): CoroutineScope = CoroutineScope(SupervisorJob() + dispatcher)
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,17 @@
*/
package soup.movie.data.settings.impl

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.SharedPreferencesMigration
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.preferencesDataStore
import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import soup.movie.common.ApplicationScope
import soup.movie.common.IoDispatcher
import soup.movie.data.settings.AppSettings
import soup.movie.model.settings.AgeFilter
import soup.movie.model.settings.TheaterFilter
Expand All @@ -41,21 +34,10 @@ import javax.inject.Singleton

@Singleton
class AppSettingsImpl @Inject constructor(
@ApplicationContext private val context: Context,
@IoDispatcher private val ioDispatcher: CoroutineDispatcher,
private val preferences: DataStore<Preferences>,
@ApplicationScope private val coroutineScope: CoroutineScope,
) : AppSettings {

private val Context.preferencesName: String
get() = packageName + "_preferences"

private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(
name = context.preferencesName,
produceMigrations = { context ->
listOf(SharedPreferencesMigration(context, context.preferencesName))
},
)

private val theaterFilterKey = intPreferencesKey("theater_filter")

init {
Expand All @@ -65,13 +47,13 @@ class AppSettingsImpl @Inject constructor(
}

override suspend fun setTheaterFilter(theaterFilter: TheaterFilter) {
context.dataStore.edit { settings ->
preferences.edit { settings ->
settings[theaterFilterKey] = theaterFilter.toFlags()
}
}

override fun getTheaterFilterFlow(): Flow<TheaterFilter> {
return context.dataStore.data.map { preferences ->
return preferences.data.map { preferences ->
TheaterFilter(
preferences[theaterFilterKey]
?: TheaterFilter.FLAG_THEATER_ALL,
Expand All @@ -82,13 +64,13 @@ class AppSettingsImpl @Inject constructor(
private val ageFilterKey = intPreferencesKey("age_filter")

override suspend fun setAgeFilter(ageFilter: AgeFilter) {
context.dataStore.edit { settings ->
preferences.edit { settings ->
settings[ageFilterKey] = ageFilter.toFlags()
}
}

override fun getAgeFilterFlow(): Flow<AgeFilter> {
return context.dataStore.data.map { preferences ->
return preferences.data.map { preferences ->
AgeFilter(
preferences[ageFilterKey] ?: AgeFilter.FLAG_AGE_DEFAULT,
)
Expand All @@ -98,10 +80,8 @@ class AppSettingsImpl @Inject constructor(
private val themeOptionKey = stringPreferencesKey("theme_option")

override suspend fun setThemeOption(themeOption: String) {
withContext(ioDispatcher) {
context.dataStore.edit { settings ->
settings[themeOptionKey] = themeOption
}
preferences.edit { settings ->
settings[themeOptionKey] = themeOption
}
}

Expand All @@ -110,17 +90,15 @@ class AppSettingsImpl @Inject constructor(
}

override fun getThemeOptionFlow(): Flow<String> {
return context.dataStore.data.map { preferences ->
return preferences.data.map { preferences ->
preferences[themeOptionKey].orEmpty()
}
}

private suspend fun clearStaleData() {
withContext(ioDispatcher) {
context.dataStore.edit { settings ->
settings.remove(stringPreferencesKey("favorite_theaters"))
settings.remove(stringPreferencesKey("favorite_genre"))
}
preferences.edit { settings ->
settings.remove(stringPreferencesKey("favorite_theaters"))
settings.remove(stringPreferencesKey("favorite_genre"))
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* Copyright 2025 SOUP
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package soup.movie.data.settings.impl.di

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.SharedPreferencesMigration
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStoreFile
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
import soup.movie.common.ApplicationScope
import soup.movie.common.IoDispatcher
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
object DataStoreModule {

@Provides
@Singleton
fun providesPreferencesDataStore(
@ApplicationContext context: Context,
@IoDispatcher ioDispatcher: CoroutineDispatcher,
@ApplicationScope scope: CoroutineScope,
): DataStore<Preferences> {
val name = context.packageName + "_preferences"
return PreferenceDataStoreFactory.create(
scope = CoroutineScope(scope.coroutineContext + ioDispatcher),
migrations = listOf(
SharedPreferencesMigration(context = context, sharedPreferencesName = name),
),
) {
context.preferencesDataStoreFile(name)
}
}
}
Loading