dioxus-std icon indicating copy to clipboard operation
dioxus-std copied to clipboard

Custom storage encoding support and example

Open Craig-Macomber opened this issue 8 months ago • 8 comments

An implementation of the proposed feature from https://github.com/DioxusLabs/sdk/issues/82 .

Included is an example which stores pretty printed JSON in the local storage instead of the current compressed binary format (which ironically in this example takes up much more space.

I attempted to integrated the idea in https://github.com/DioxusLabs/sdk/issues/82#issuecomment-2930743753 and decouple the API/format from serde, but I ran into complications which can be seen in https://github.com/Craig-Macomber/Dioxus-sdk/commit/7bda9ab576eb2454bf00bec8699276a752f4342b . The extra type parameter introduced to constrain the encodable types leaked out to a lot of places where it caused issues, like StorageBacking.

Due to those issues, this PR contains the addition of support for custom encoding format of serde compatible types, and does not make the coupling to serde opt in.

I'd like some guidance on the preferred way for me to proceed with this work. I'm thinking I should do one of:

  1. Cleanup this PR (mostly improve documentation) for merging roughly as is. This may or may not be followed up a second change to decouple this from serde.
  2. Continue attempts to decouple this from serde before trying to merge this PR (In this case I'd like suggestions for what approach to take as my initial attempt didn't go very well).

Additionally I'd like clarity on how error handling should be done. For example if the storage is filled with some invalid value (possibly from a different version of the app, or collision with some other storage in a different format), I think the default behavior should probably not be to destroy that existing data, nor to panic, but instead produce an app facing error which the app can handle as desired (for example by asking the user if they want to overwrite the data or exit, or attempting to parse the data with a legacy format handler).

Craig-Macomber avatar Jun 16 '25 19:06 Craig-Macomber

Thanks for working on this! The bounds are somewhat infectious, but you can get it working without serde if you just follow the errors:

https://github.com/DioxusLabs/sdk/compare/main...ealmloff:dioxus-std:decouple-serde

I think some of the bounds on the current implementation are unnecessary. For example, the S: StorageBacking is only ever used in a PhantomData, so it shouldn't require the Clone bound. I wonder if this would be simpler if we removed StorageBacking and LayeredStorage and just used the new traits directly?

For error handling, it might be easier to handle some of the errors in the StorageEncoder rather than every time you read or write to the signal. If we can make it easy enough to implement StorageEncoder in userland and we allow state on the StorageEncoder, it could potentially handle fallback for deserialization failures and error reporting

ealmloff avatar Jun 17 '25 21:06 ealmloff

I finally got around to debugging an issue and getting it working on desktop: the fact that the subscriptions send the unencoded data through the channels tripped me up and I had a bug where I was sending encoded data. Still a lot of cleanup to do, but at least its working. I will continue to make progress on this.

I wonder if this would be simpler if we removed StorageBacking and LayeredStorage and just used the new traits directly?

I kept the existing stuff in place to avoid making major API breaking changes, and to limit the scope of the change. I suppose nearly all users will just be using the storage hooks with the existing storage types, so adjusting the traits wouldn't be too disruptive. I'll consider such options as I iterate on this. Reworking this might make it easier to layer the encoding better to avoid issues like the StoragePersistence.store needing the unencoded value.

Craig-Macomber avatar Aug 24 '25 01:08 Craig-Macomber

I think everything is working as expected now, both on web and desktop.

I still need to to do a self code review, add more documentation and add some unit tests.

Craig-Macomber avatar Aug 30 '25 20:08 Craig-Macomber

I think this change is ready for initial review.

I ended up pivoting a bit on the design, reworking the StorageBacking trait so its easier to implement and just serves the role of composing together the encoder and persistence.

Craig-Macomber avatar Aug 30 '25 23:08 Craig-Macomber

I would like to try out this reworked dioxus SDK storage, straight from the PR/fork. Currently I am using https://github.com/everaccountable/easy_prefs, for desktop, mobile and web. But this one integrates much nicer with dioxus, obviously. Is there an updated example anywhere already on how to use it ? Otherwise I assume it is just like using signals (but with persistence) and for fs-based persistence I need to set the directory first.

rsaccon avatar Sep 11 '25 22:09 rsaccon

Is there an updated example anywhere already on how to use it ?

This Repository contains an example of how to use the storage APIs and this PR updates it to show off the new options it adds.

Craig-Macomber avatar Sep 11 '25 23:09 Craig-Macomber

Uups, sorry, now I'm on the right branch. I see, the example has also been updated.

rsaccon avatar Sep 11 '25 23:09 rsaccon

Looks much better overall. Let me know what you think about the associated error type. I can take some time to explore that approach

I'm experimenting with some ways to do error handling and storage clearing. I think I might be onto something nice. I'm going to mark this as draft again until I'm done exploring the options there.

Craig-Macomber avatar Sep 13 '25 19:09 Craig-Macomber