Skip to content

Commit

Permalink
Merge pull request #75 from russhwolf/datastore-update
Browse files Browse the repository at this point in the history
Update DataStore version to 1.0.0-alpha06
  • Loading branch information
russhwolf authored Jan 18, 2021
2 parents 74df5b7 + f719175 commit 6af7bb8
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 33 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
# Changelog #

## v0.7.1 *(2021-01-17)* ##

- Update `multiplatform-settings-datastore` to use DataStore version 1.0.0-alpha06

## v0.7 *(2020-12-26)* ##

- Kotlin 1.4.21 and other dependency updates
- New typed update listeners
- `addIntListener { int: Int -> ... }` in addition to `addListener { ... }`
Expand Down
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ Then, simply add the dependency to your common source-set dependencies
commonMain {
dependencies {
// ...
implementation("com.russhwolf:multiplatform-settings:0.7")
implementation("com.russhwolf:multiplatform-settings:0.7.1")
}
}
```
Expand Down Expand Up @@ -144,7 +144,7 @@ val factory: Settings.Factory = AppleSettings.Factory()
To create a `Settings` instance from common without needing to pass platform-specific dependencies, add the `multiplatform-settings-no-arg` gradle dependency. This exports `multiplatform-settings` as an API dependency, so you can use it as a replacement for that default dependency.

```kotlin
implementation("com.russhwolf:multiplatform-settings-no-arg:0.7")
implementation("com.russhwolf:multiplatform-settings-no-arg:0.7.1")
```

Then from common code, you can write
Expand Down Expand Up @@ -238,7 +238,7 @@ Note that for the `AppleSettings` implementation, some entries are unremovable a
A testing dependency is available to aid in testing code that interacts with this library.

```kotlin
implementation("com.russhwolf:multiplatform-settings-test:0.7")
implementation("com.russhwolf:multiplatform-settings-test:0.7.1")
```

This includes a `MockSettings` implementation of the `Settings` interface, which is backed by an in-memory `MutableMap` on all platforms.
Expand Down Expand Up @@ -309,7 +309,7 @@ On Apple platforms, the `AppleSettings` listeners are designed to work within th
A `kotlinx-serialization` integration exists so it's easier to save non-primitive data

```kotlin
implementation("com.russhwolf:multiplatform-settings-serialization:0.7")
implementation("com.russhwolf:multiplatform-settings-serialization:0.7.1")
```

This essentially uses the `Settings` store as a serialization format. Thus for a serializable class
Expand Down Expand Up @@ -346,10 +346,10 @@ Usage requires accepting both the `@ExperimentalSettingsApi` and `@ExperimentalS
A separate `multiplatform-settings-coroutines` dependency includes various coroutine APIs.

```kotlin
implementation("com.russhwolf:multiplatform-settings-coroutines:0.7")
implementation("com.russhwolf:multiplatform-settings-coroutines:0.7.1")

// Or, if you use native-mt coroutines release
implementation("com.russhwolf:multiplatform-settings-coroutines-native-mt:0.7")
implementation("com.russhwolf:multiplatform-settings-coroutines-native-mt:0.7.1")
```

This adds flow extensions for all types which use the listener APIs internally.
Expand Down Expand Up @@ -389,7 +389,7 @@ val blockingSettings: Settings = suspendSettings.toBlockingSettings()
An implementation of `FlowSettings` on the Android exists in the `multiplatform-settings-datastore` dependency, based on [Jetpack DataStore](https://developer.android.com/jetpack/androidx/releases/datastore)

```kotlin
implementation("com.russhwolf:multiplatform-settings-coroutines:0.7")
implementation("com.russhwolf:multiplatform-settings-coroutines:0.7.1")
```

This provides a `DataStoreSettings` class
Expand Down
4 changes: 2 additions & 2 deletions buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@
@file:Suppress("KDocMissingDocumentation")

object Versions {
const val multiplatformSettings = "0.7"
const val multiplatformSettings = "0.7.1"

const val minSdk = 15
const val compileSdk = 30

const val androidxDatastore = "1.0.0-alpha05"
const val androidxDatastore = "1.0.0-alpha06"
const val androidxPreference = "1.1.1"
const val androidxStartup = "1.0.0"
const val androidxTest = "1.3.0"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,14 @@ package com.russhwolf.settings.datastore

import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.doublePreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.preferencesKey
import androidx.datastore.preferences.core.remove
import androidx.datastore.preferences.core.floatPreferencesKey
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import androidx.datastore.preferences.core.stringSetPreferencesKey
import com.russhwolf.settings.ExperimentalSettingsApi
import com.russhwolf.settings.ExperimentalSettingsImplementation
import com.russhwolf.settings.coroutines.FlowSettings
Expand All @@ -39,64 +44,69 @@ public class DataStoreSettings(private val datastore: DataStore<Preferences>) :
public override suspend fun clear(): Unit = keys().forEach { remove(it) }

public override suspend fun remove(key: String) {
datastore.edit { it.remove(preferencesKey<String>(key)) }
datastore.edit { it.remove(stringSetPreferencesKey(key)) }
}

public override suspend fun hasKey(key: String): Boolean =
datastore.data.first().contains(preferencesKey<String>(key))
datastore.data.first().contains(stringSetPreferencesKey(key))

public override suspend fun putInt(key: String, value: Int) {
datastore.edit { it[preferencesKey(key)] = value }
datastore.edit { it[intPreferencesKey(key)] = value }
}

public override fun getIntFlow(key: String, defaultValue: Int): Flow<Int> =
datastore.data.map { it[preferencesKey(key)] ?: defaultValue }
datastore.data.map { it[intPreferencesKey(key)] ?: defaultValue }

public override fun getIntOrNullFlow(key: String): Flow<Int?> = datastore.data.map { it[preferencesKey(key)] }
public override fun getIntOrNullFlow(key: String): Flow<Int?> =
datastore.data.map { it[intPreferencesKey(key)] }

public override suspend fun putLong(key: String, value: Long) {
datastore.edit { it[preferencesKey(key)] = value }
datastore.edit { it[longPreferencesKey(key)] = value }
}

public override fun getLongFlow(key: String, defaultValue: Long): Flow<Long> =
datastore.data.map { it[preferencesKey(key)] ?: defaultValue }
datastore.data.map { it[longPreferencesKey(key)] ?: defaultValue }

public override fun getLongOrNullFlow(key: String): Flow<Long?> = datastore.data.map { it[preferencesKey(key)] }
public override fun getLongOrNullFlow(key: String): Flow<Long?> =
datastore.data.map { it[longPreferencesKey(key)] }

public override suspend fun putString(key: String, value: String) {
datastore.edit { it[preferencesKey(key)] = value }
datastore.edit { it[stringPreferencesKey(key)] = value }
}

public override fun getStringFlow(key: String, defaultValue: String): Flow<String> =
datastore.data.map { it[preferencesKey(key)] ?: defaultValue }
datastore.data.map { it[stringPreferencesKey(key)] ?: defaultValue }

public override fun getStringOrNullFlow(key: String): Flow<String?> = datastore.data.map { it[preferencesKey(key)] }
public override fun getStringOrNullFlow(key: String): Flow<String?> =
datastore.data.map { it[stringPreferencesKey(key)] }

public override suspend fun putFloat(key: String, value: Float) {
datastore.edit { it[preferencesKey(key)] = value }
datastore.edit { it[floatPreferencesKey(key)] = value }
}

public override fun getFloatFlow(key: String, defaultValue: Float): Flow<Float> =
datastore.data.map { it[preferencesKey(key)] ?: defaultValue }
datastore.data.map { it[floatPreferencesKey(key)] ?: defaultValue }

public override fun getFloatOrNullFlow(key: String): Flow<Float?> = datastore.data.map { it[preferencesKey(key)] }
public override fun getFloatOrNullFlow(key: String): Flow<Float?> =
datastore.data.map { it[floatPreferencesKey(key)] }

public override suspend fun putDouble(key: String, value: Double) {
datastore.edit { it[preferencesKey(key)] = value }
datastore.edit { it[doublePreferencesKey(key)] = value }
}

public override fun getDoubleFlow(key: String, defaultValue: Double): Flow<Double> =
datastore.data.map { it[preferencesKey(key)] ?: defaultValue }
datastore.data.map { it[doublePreferencesKey(key)] ?: defaultValue }

public override fun getDoubleOrNullFlow(key: String): Flow<Double?> = datastore.data.map { it[preferencesKey(key)] }
public override fun getDoubleOrNullFlow(key: String): Flow<Double?> =
datastore.data.map { it[doublePreferencesKey(key)] }

public override suspend fun putBoolean(key: String, value: Boolean) {
datastore.edit { it[preferencesKey(key)] = value }
datastore.edit { it[booleanPreferencesKey(key)] = value }
}

public override fun getBooleanFlow(key: String, defaultValue: Boolean): Flow<Boolean> =
datastore.data.map { it[preferencesKey(key)] ?: defaultValue }
datastore.data.map { it[booleanPreferencesKey(key)] ?: defaultValue }

public override fun getBooleanOrNullFlow(key: String): Flow<Boolean?> =
datastore.data.map { it[preferencesKey(key)] }
datastore.data.map { it[booleanPreferencesKey(key)] }
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,13 @@ package com.russhwolf.settings.datastore
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.PreferenceDataStoreFactory
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.core.booleanPreferencesKey
import androidx.datastore.preferences.core.doublePreferencesKey
import androidx.datastore.preferences.core.edit
import androidx.datastore.preferences.core.preferencesKey
import androidx.datastore.preferences.core.floatPreferencesKey
import androidx.datastore.preferences.core.intPreferencesKey
import androidx.datastore.preferences.core.longPreferencesKey
import androidx.datastore.preferences.core.stringPreferencesKey
import com.russhwolf.settings.BaseSettingsTest
import com.russhwolf.settings.ExperimentalSettingsApi
import com.russhwolf.settings.ExperimentalSettingsImplementation
Expand Down Expand Up @@ -52,6 +57,7 @@ import org.junit.Test
import org.junit.rules.TemporaryFolder
import java.io.File
import kotlin.test.assertEquals
import kotlin.test.fail

private val temporaryFolder = TemporaryFolder()
private val testScope = TestCoroutineScope()
Expand Down Expand Up @@ -79,7 +85,7 @@ class DataStoreSettingsTest : BaseSettingsTest(
val dataStore = PreferenceDataStoreFactory.create { File(temporaryFolder.root, "settings.preferences_pb") }
val settings = DataStoreSettings(dataStore)

dataStore.edit { it[preferencesKey("a")] = 3 }
dataStore.edit { it[intPreferencesKey("a")] = 3 }
assertEquals(3, settings.getInt("a"))
}

Expand Down Expand Up @@ -110,6 +116,19 @@ private class BlockingDataStoreSettings(
private inline fun <reified T : Any> flowOrNull(): Flow<T?> =
dataStore.data.map { it[preferencesKey<T>(key)] }.catch {}

private inline fun <reified T> preferencesKey(key: String): Preferences.Key<T> {
@Suppress("UNCHECKED_CAST")
return when (T::class) {
Int::class -> intPreferencesKey(key)
Long::class -> longPreferencesKey(key)
String::class -> stringPreferencesKey(key)
Float::class -> floatPreferencesKey(key)
Double::class -> doublePreferencesKey(key)
Int::class -> booleanPreferencesKey(key)
else -> fail("invalid type")
} as Preferences.Key<T>
}

private val scope = CoroutineScope(testScope.coroutineContext + SupervisorJob(testScope.coroutineContext[Job]))

init {
Expand Down

0 comments on commit 6af7bb8

Please sign in to comment.