mobiler 0.11.0

Build mobile apps in Rust — one core, native UI on Android, iOS, and the web (CLI)
package {{PACKAGE}}

import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKey
import org.json.JSONObject

// Secure key/value storage (free, bundled). Backed by EncryptedSharedPreferences (AES-256,
// keys held in the Android Keystore). For secrets — auth tokens, API keys — NOT bulk data.
// `input` is JSON:
//   set:    {"key": "...", "value": "..."}  → ok:true
//   get:    {"key": "..."}                  → ok:true, output = value ("" if absent)
//   delete: {"key": "..."}                  → ok:true
// Pair with the `biometric` plugin (gate a get behind an authenticate in your Rust core).
class SecureStorePlugin(private val application: android.app.Application) : MobilerPlugin {
    private val prefs by lazy {
        val masterKey = MasterKey.Builder(application)
            .setKeyScheme(MasterKey.KeyScheme.AES256_GCM)
            .build()
        EncryptedSharedPreferences.create(
            application,
            "mobiler_secure",
            masterKey,
            EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
            EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM,
        )
    }

    override suspend fun handle(op: String, input: String): PluginResponse {
        val obj = runCatching { JSONObject(input) }.getOrNull()
            ?: return PluginResponse(false, "invalid input JSON")
        val key = obj.optString("key")
        if (key.isEmpty()) return PluginResponse(false, "missing key")
        return when (op) {
            "set" -> {
                prefs.edit().putString(key, obj.optString("value")).apply()
                PluginResponse(true, "")
            }
            "get" -> PluginResponse(true, prefs.getString(key, "") ?: "")
            "delete" -> {
                prefs.edit().remove(key).apply()
                PluginResponse(true, "")
            }
            else -> PluginResponse(false, "unknown op '$op'")
        }
    }
}