diff --git a/.gitignore b/.gitignore
index f71b497..ed84d2d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,10 +6,12 @@
/files/build/
/local-storage/build/
/shared-preferences/build/
+/bundle/build/
/json/build/
/json/json-files/build/
/json/json-local-storage/build/
-/json/json-shared-preferences/build
+/json/json-shared-preferences/build/
+/json/json-bundle/
/.gradle/
/buildSrc/.gradle/
diff --git a/README.md b/README.md
index 9447235..1e115d5 100644
--- a/README.md
+++ b/README.md
@@ -48,6 +48,32 @@ fun main() {
}
```
+### Android Bundle State
+You can also store android app state with the library
+```kotlin
+class MainActivity : Activity() {
+ private val state = object : KBundleDataStorage() {
+ var score by int { 0 } // This will be automatically saved and restored
+ }
+
+ override fun onCreate(bundle: Bundle?) = state.fillState(bundle) {
+ super.onCreate(bundle)
+ }
+ // OR
+ override fun onCreate(bundle: Bundle?) {
+ super.onCreate(bundle)
+ state.restoreInstanceState(bundle)
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ state.saveInstanceState(outState)
+ }
+}
+```
+`property` are also allowed there with serialization to string followed by `bundle.putString`
+
+
### Mutate Example
There is also an API to use mutable objects
```kotlin
@@ -60,15 +86,15 @@ object MainStorage : ... {
}
// Launches an asynchronous commit after block()
-fun addItem() = MainStorage.mutate {
+fun editItem() = MainStorage.mutate {
item.foo = ...
}
// Suspends until commit
-suspend fun addItem() = MainStorage.mutateCommit {
+suspend fun editItem() = MainStorage.mutateCommit {
item.foo = ...
}
// Blocking mutation
-fun addItem() = MainStorage.mutateBlocking {
+fun editItem() = MainStorage.mutateBlocking {
item.foo = ...
}
@@ -127,7 +153,14 @@ All `kds` packages are located at repository [maven.kotlingang.fun](https://mave
**Platforms**: ![android][badge-android]
**Dependency**: `fun.kotlingang.kds:json-shared-preferences:$version`
-**Example**: Github [repo](https://github.com/kotlingang/kds-android-example)
+**Example**: GitHub [repo](https://github.com/kotlingang/kds-android-example)
+
+### KBundleDataStorage
+> KDataStorage sync [implementation](json/json-bundle) with android `Bundle`
+
+**Platforms**: ![android][badge-android]
+**Dependency**: `fun.kotlingang.kds:json-bundle:$version`
+**Example**: GitHub [repo](https://github.com/kotlingang/kds-android-example)
### Custom
There **are** plans for other implementations (bundle, ns-user-default, etc.), but if you want to create your implementation, take a look at the following dependencies
diff --git a/buildSrc/src/main/kotlin/AppInfo.kt b/buildSrc/src/main/kotlin/AppInfo.kt
index 1d80030..dfc4e5f 100644
--- a/buildSrc/src/main/kotlin/AppInfo.kt
+++ b/buildSrc/src/main/kotlin/AppInfo.kt
@@ -1,6 +1,6 @@
object AppInfo {
const val PACKAGE = "fun.kotlingang.kds"
- const val VERSION = "5.3.0"
+ const val VERSION = "1.0.0"
const val NAME = "Kotlin Data Storage"
const val DESCRIPTION = "Multiplatform Coroutine-Based Kotlin Library for storing data via kotlinx.serialization"
}
diff --git a/buildSrc/src/main/kotlin/Modules.kt b/buildSrc/src/main/kotlin/Modules.kt
index 6cba355..4956f38 100644
--- a/buildSrc/src/main/kotlin/Modules.kt
+++ b/buildSrc/src/main/kotlin/Modules.kt
@@ -14,3 +14,4 @@ val DependencyHandler.json get() = project(":json")
val DependencyHandler.core get() = project(":core")
val DependencyHandler.`shared-preferences` get() = project(":shared-preferences")
val DependencyHandler.`android-app-provider` get() = project(":android-app-provider")
+val DependencyHandler.bundle get() = project(":bundle")
diff --git a/bundle/build.gradle.kts b/bundle/build.gradle.kts
new file mode 100644
index 0000000..9569f9c
--- /dev/null
+++ b/bundle/build.gradle.kts
@@ -0,0 +1,31 @@
+import `fun`.kotlingang.deploy.DeployEntity
+
+plugins {
+ id(plugin.androidLibrary)
+ kotlin(plugin.android)
+}
+
+configure {
+ componentName = "release"
+}
+
+android {
+ // Workaround since explicitApi() does not work for android
+ kotlinOptions.freeCompilerArgs += "-Xexplicit-api=strict"
+ kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
+
+ compileSdk = Version.COMPILE_SDK
+
+ defaultConfig {
+ targetSdk = Version.COMPILE_SDK
+ minSdk = Version.MIN_SDK
+ }
+
+ buildFeatures {
+ buildConfig = false
+ }
+}
+
+dependencies {
+ api(core)
+}
diff --git a/bundle/src/main/AndroidManifest.xml b/bundle/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..1ffd87f
--- /dev/null
+++ b/bundle/src/main/AndroidManifest.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/bundle/src/main/java/fun/kotlingang/kds/InstanceStateManager.kt b/bundle/src/main/java/fun/kotlingang/kds/InstanceStateManager.kt
new file mode 100644
index 0000000..afb08fb
--- /dev/null
+++ b/bundle/src/main/java/fun/kotlingang/kds/InstanceStateManager.kt
@@ -0,0 +1,9 @@
+package `fun`.kotlingang.kds
+
+import android.os.Bundle
+
+
+public interface InstanceStateManager {
+ public fun restoreInstanceState(bundle: Bundle?)
+ public fun saveInstanceState(bundle: Bundle)
+}
diff --git a/bundle/src/main/java/fun/kotlingang/kds/KPrimitiveBundleDataStorage.kt b/bundle/src/main/java/fun/kotlingang/kds/KPrimitiveBundleDataStorage.kt
new file mode 100644
index 0000000..5b2dcc4
--- /dev/null
+++ b/bundle/src/main/java/fun/kotlingang/kds/KPrimitiveBundleDataStorage.kt
@@ -0,0 +1,91 @@
+package `fun`.kotlingang.kds
+
+import `fun`.kotlingang.kds.annotation.RawSetterGetter
+import `fun`.kotlingang.kds.extensions.bundle.contains
+import `fun`.kotlingang.kds.storage.PrimitiveDataStorage
+import android.os.Bundle
+
+
+public open class KPrimitiveBundleDataStorage : PrimitiveDataStorage, InstanceStateManager {
+ private val bundle = Bundle()
+
+ override fun restoreInstanceState(bundle: Bundle?) {
+ if(bundle != null)
+ this.bundle.putAll(bundle)
+ }
+ override fun saveInstanceState(bundle: Bundle) {
+ bundle.putAll(this.bundle)
+ }
+
+ @RawSetterGetter
+ final override fun putString(key: String, value: String) {
+ bundle.putString(key, value)
+ }
+
+ @RawSetterGetter
+ final override fun putInt(key: String, value: Int) {
+ bundle.putInt(key, value)
+ }
+
+ @RawSetterGetter
+ final override fun putLong(key: String, value: Long) {
+ bundle.putLong(key, value)
+ }
+
+ @RawSetterGetter
+ final override fun putFloat(key: String, value: Float) {
+ bundle.putFloat(key, value)
+ }
+
+ @RawSetterGetter
+ final override fun putDouble(key: String, value: Double) {
+ bundle.putDouble(key, value)
+ }
+
+ @RawSetterGetter
+ final override fun putBoolean(key: String, value: Boolean) {
+ bundle.putBoolean(key, value)
+ }
+
+ @RawSetterGetter
+ final override fun getString(key: String): String? =
+ if(key in bundle)
+ bundle.getString(key)
+ else
+ null
+
+ @RawSetterGetter
+ final override fun getInt(key: String): Int? =
+ if(key in bundle)
+ bundle.getInt(key)
+ else
+ null
+
+ @RawSetterGetter
+ final override fun getLong(key: String): Long? =
+ if(key in bundle)
+ bundle.getLong(key)
+ else
+ null
+
+ @RawSetterGetter
+ final override fun getFloat(key: String): Float? =
+ if(key in bundle)
+ bundle.getFloat(key)
+ else
+ null
+
+ @RawSetterGetter
+ final override fun getDouble(key: String): Double? =
+ if(key in bundle)
+ bundle.getDouble(key)
+ else
+ null
+
+ @RawSetterGetter
+ final override fun getBoolean(key: String): Boolean? =
+ if(key in bundle)
+ bundle.getBoolean(key)
+ else
+ null
+}
diff --git a/bundle/src/main/java/fun/kotlingang/kds/extensions/bundle/in.kt b/bundle/src/main/java/fun/kotlingang/kds/extensions/bundle/in.kt
new file mode 100644
index 0000000..3987e13
--- /dev/null
+++ b/bundle/src/main/java/fun/kotlingang/kds/extensions/bundle/in.kt
@@ -0,0 +1,6 @@
+package `fun`.kotlingang.kds.extensions.bundle
+
+import android.os.Bundle
+
+
+internal operator fun Bundle.contains(key: String) = containsKey(key)
diff --git a/bundle/src/main/java/fun/kotlingang/kds/extensions/instance_state_manager/fillState.kt b/bundle/src/main/java/fun/kotlingang/kds/extensions/instance_state_manager/fillState.kt
new file mode 100644
index 0000000..babfba8
--- /dev/null
+++ b/bundle/src/main/java/fun/kotlingang/kds/extensions/instance_state_manager/fillState.kt
@@ -0,0 +1,10 @@
+package `fun`.kotlingang.kds.extensions.instance_state_manager
+
+import `fun`.kotlingang.kds.InstanceStateManager
+import android.os.Bundle
+
+
+public inline fun InstanceStateManager.fillState(bundle: Bundle?, block: () -> Unit) {
+ restoreInstanceState(bundle)
+ block()
+}
diff --git a/json/json-bundle/build.gradle.kts b/json/json-bundle/build.gradle.kts
new file mode 100644
index 0000000..1d13296
--- /dev/null
+++ b/json/json-bundle/build.gradle.kts
@@ -0,0 +1,32 @@
+import `fun`.kotlingang.deploy.DeployEntity
+
+plugins {
+ id(plugin.androidLibrary)
+ kotlin(plugin.android)
+}
+
+configure {
+ componentName = "release"
+}
+
+android {
+ // Workaround since explicitApi() does not work for android
+ kotlinOptions.freeCompilerArgs += "-Xexplicit-api=strict"
+ kotlinOptions.freeCompilerArgs += "-Xopt-in=kotlin.RequiresOptIn"
+
+ compileSdk = Version.COMPILE_SDK
+
+ defaultConfig {
+ targetSdk = Version.COMPILE_SDK
+ minSdk = Version.MIN_SDK
+ }
+
+ buildFeatures {
+ buildConfig = false
+ }
+}
+
+dependencies {
+ api(json)
+ api(bundle)
+}
diff --git a/json/json-bundle/src/main/AndroidManifest.xml b/json/json-bundle/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..1ffd87f
--- /dev/null
+++ b/json/json-bundle/src/main/AndroidManifest.xml
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/json/json-bundle/src/main/java/fun/kotlingang/kds/KBundleDataStorage.kt b/json/json-bundle/src/main/java/fun/kotlingang/kds/KBundleDataStorage.kt
new file mode 100644
index 0000000..5e28765
--- /dev/null
+++ b/json/json-bundle/src/main/java/fun/kotlingang/kds/KBundleDataStorage.kt
@@ -0,0 +1,95 @@
+package `fun`.kotlingang.kds
+
+import `fun`.kotlingang.kds.annotation.DelicateKDSApi
+import `fun`.kotlingang.kds.annotation.RawSetterGetter
+import `fun`.kotlingang.kds.storage.PrimitiveDataStorage
+import android.os.Bundle
+import kotlinx.serialization.json.Json
+
+
+public open class KBundleDataStorage private constructor (
+ json: Json,
+ private val storage: KJsonElementDataStorage
+): KJsonDataStorage(json, storage), PrimitiveDataStorage, InstanceStateManager {
+ public constructor (
+ json: Json = Json
+ ) : this(json, KJsonElementDataStorage(json))
+
+ final override fun restoreInstanceState(bundle: Bundle?) {
+ storage.restoreInstanceState(bundle)
+ }
+ final override fun saveInstanceState(bundle: Bundle) {
+ storage.saveInstanceState(bundle)
+ }
+
+ @RawSetterGetter
+ final override fun putString(key: String, value: String) {
+ storage.putString(key, value)
+ }
+
+ @RawSetterGetter
+ final override fun putInt(key: String, value: Int) {
+ storage.putInt(key, value)
+ }
+
+ @RawSetterGetter
+ final override fun putLong(key: String, value: Long) {
+ storage.putLong(key, value)
+ }
+
+ @RawSetterGetter
+ final override fun putFloat(key: String, value: Float) {
+ storage.putFloat(key, value)
+ }
+
+ @RawSetterGetter
+ final override fun putDouble(key: String, value: Double) {
+ storage.putDouble(key, value)
+ }
+
+ @RawSetterGetter
+ final override fun putBoolean(key: String, value: Boolean) {
+ storage.putBoolean(key, value)
+ }
+
+ @RawSetterGetter
+ final override fun getString(key: String): String? {
+ return storage.getString(key)
+ }
+
+ @RawSetterGetter
+ final override fun getInt(key: String): Int? {
+ return storage.getInt(key)
+ }
+
+ @RawSetterGetter
+ final override fun getLong(key: String): Long? {
+ return storage.getLong(key)
+ }
+
+ @RawSetterGetter
+ final override fun getFloat(key: String): Float? {
+ return storage.getFloat(key)
+ }
+
+ @RawSetterGetter
+ final override fun getDouble(key: String): Double? {
+ return storage.getDouble(key)
+ }
+
+ @RawSetterGetter
+ final override fun getBoolean(key: String): Boolean? {
+ return storage.getBoolean(key)
+ }
+
+ @OptIn(DelicateKDSApi::class, RawSetterGetter::class)
+ override fun commitBlocking() {
+ encodeReferences().forEach { (k, v) ->
+ storage.putJsonElement(k, v)
+ }
+ }
+
+ final override fun setupBlocking() {
+ super.setupBlocking()
+ }
+}
diff --git a/json/json-bundle/src/main/java/fun/kotlingang/kds/KJsonElementDataStorage.kt b/json/json-bundle/src/main/java/fun/kotlingang/kds/KJsonElementDataStorage.kt
new file mode 100644
index 0000000..169aab9
--- /dev/null
+++ b/json/json-bundle/src/main/java/fun/kotlingang/kds/KJsonElementDataStorage.kt
@@ -0,0 +1,23 @@
+package `fun`.kotlingang.kds
+
+import `fun`.kotlingang.kds.annotation.RawSetterGetter
+import `fun`.kotlingang.kds.storage.JsonElementDataStorage
+import kotlinx.serialization.decodeFromString
+import kotlinx.serialization.encodeToString
+import kotlinx.serialization.json.Json
+import kotlinx.serialization.json.JsonElement
+
+
+internal class KJsonElementDataStorage (
+ private val json: Json
+) : KPrimitiveBundleDataStorage(), JsonElementDataStorage {
+ @RawSetterGetter
+ override fun putJsonElement(key: String, value: JsonElement) {
+ putString(key, json.encodeToString(value))
+ }
+
+ @RawSetterGetter
+ override fun getJsonElement(key: String): JsonElement? {
+ return json.decodeFromString(string = getString(key) ?: return null)
+ }
+}
diff --git a/json/json-local-storage/src/main/kotlin/fun/kotlingang/kds/KLocalDataStorage.kt b/json/json-local-storage/src/main/kotlin/fun/kotlingang/kds/KLocalDataStorage.kt
index e8473f5..48cfd74 100644
--- a/json/json-local-storage/src/main/kotlin/fun/kotlingang/kds/KLocalDataStorage.kt
+++ b/json/json-local-storage/src/main/kotlin/fun/kotlingang/kds/KLocalDataStorage.kt
@@ -9,7 +9,7 @@ import kotlinx.serialization.json.Json
public open class KLocalDataStorage (
json: Json = Json
-) : KJsonDataStorage(json, JsonElementLocalDataStorage(json)), CommittableStorage {
+) : KJsonDataStorage(json, JsonElementLocalDataStorage(json)) {
@OptIn(DelicateKDSApi::class, RawSetterGetter::class)
final override fun commitBlocking(): Unit = encodeReferences()
.forEach { (k, v) -> KStringLocalDataStorage.putString(k, json.encodeToString(v)) }
diff --git a/json/src/commonMain/kotlin/fun/kotlingang/kds/KJsonDataStorage.kt b/json/src/commonMain/kotlin/fun/kotlingang/kds/KJsonDataStorage.kt
index ce53ddc..62e3f0a 100644
--- a/json/src/commonMain/kotlin/fun/kotlingang/kds/KJsonDataStorage.kt
+++ b/json/src/commonMain/kotlin/fun/kotlingang/kds/KJsonDataStorage.kt
@@ -8,6 +8,7 @@ import `fun`.kotlingang.kds.storage.JsonElementDataStorage
import `fun`.kotlingang.kds.storage.SerializableDataStorage
import `fun`.kotlingang.kds.sync.platformSynchronized
import `fun`.kotlingang.kds.optional.Optional
+import `fun`.kotlingang.kds.storage.CommittableStorage
import kotlinx.serialization.KSerializer
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
@@ -15,10 +16,10 @@ import kotlinx.serialization.serializer
import kotlin.reflect.KType
-public open class KJsonDataStorage (
+public abstract class KJsonDataStorage (
final override val json: Json,
private val storage: JsonElementDataStorage
-) : SerializableDataStorage {
+) : SerializableDataStorage, CommittableStorage {
/**
* Any mutation/iteration/etc should be wrapped with synchronization
diff --git a/settings.gradle.kts b/settings.gradle.kts
index ffe634c..fdf6781 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -8,9 +8,11 @@ include (
"files",
"local-storage",
"shared-preferences",
+ "bundle",
"json",
"json:json-files",
"json:json-local-storage",
- "json:json-shared-preferences"
+ "json:json-shared-preferences",
+ "json:json-bundle"
)