russhwolf / multiplatform-settings

A Kotlin Multiplatform library for saving simple key-value data
Apache License 2.0
1.6k stars 67 forks source link

Add a wrapper to convert `Settings` to `ObservableSettings` by manually invoking callbacks #155

Closed russhwolf closed 4 weeks ago

russhwolf commented 1 year ago

It would be pretty straightforward to create a class that manually wires in update listeners in Kotlin for platforms that don't natively have them.

class ObservableSettingsWrapper(val delegate: Settings): ObservableSettings {
    private val listeners = mutableListOf<() -> Unit>()

    fun addIntListener(key: String, callback: (Int) -> Unit): SettingsListener {
        var prev = getIntOrNull(key)
        listeners.add {
            val current = getIntOrNull(key)
            if (prev != current) {
                block()
                prev = current
            }
        }
        // ...
    }

    fun setInt(key: String, value: Int) {
        delegate.setInt(key, value)
        listeners.forEach { it.invoke() }
    }

    // ...
}

The reason I've never added this to the library previously is, the interop story can get confusing here. For example, if you have platform code in JS interacting with localStorage directly, then making changes there would not trigger your listeners. Indeed even if you had multiple Settings instances reading from the same storage, they wouldn't trigger each other's listeners in the implementation above.

As KMP matures, there's a growing number of users for whom the interop story is less important than having an API that does everything they need in common code. So I'm reconsidering adding an API like this, and want to hear what others in the community think about it.

Some details I'm considering

psuzn commented 1 year ago

This would certainly be useful. I’ve created a simpler version of this and would be happy to contribute if you decide to include it in the pipeline.

russhwolf commented 1 year ago

I don't want to think too much about this until after getting 1.1 out the door, but would certainly welcome contributions. Is the version you've used available publicly anywhere?

psuzn commented 1 year ago

It is not available publicly yet. I'm working on a simple multiplatform app that will eventually be public.

psuzn commented 1 year ago

I finally published my app and here is the link to my implementation.

Besides this, I also ended up adding some extensions to support stateflow.

I can contribute these back if you think it adds some value to this project.

russhwolf commented 8 months ago

Hi @psuzn,

Sorry it's taken me a while to get back on this. I'd like to add something like this, and would welcome the contribution if you'd like to make a PR with your implementation.

Some notes:

ChristianKatzmann commented 7 months ago

@psuzn Hey there! Are you by any chance about to create the aforementioned PR? Don't want to stress, though.

psuzn commented 7 months ago

Hey, @ChristianKatzmann I started to work on it a while ago, but something came up and I forgot. Will continue with it over the weekends and hopefully will push something soon.

psuzn commented 5 months ago

Since #184 has been merged, let's also close this.

russhwolf commented 5 months ago

Will close once I get it released (which I'm admittedly way late on)

psuzn commented 5 months ago

makes sense, what are other things in the pipeline if there is anything I can help with?

russhwolf commented 4 weeks ago

This is now released in 1.2