mirror of
https://github.com/tauri-apps/plugins-workspace.git
synced 2026-06-10 14:13:55 +02:00
feat(store): load override defaults (#2857)
* feat(store): load override defaults * Update docs * Update example * Allow setting defaults from js * Tweak resolve * Merge remote-tracking branch 'upstream/v2' into store-load-override-defaults * Merge branch 'v2' of https://github.com/tauri-apps/plugins-workspace into store-load-override-defaults * Merge branch 'v2' into store-load-override-defaults * Rename to ignore defaults * Merge remote-tracking branch 'upstream/v2' into store-load-override-defaults
This commit is contained in:
+43
-23
@@ -53,17 +53,36 @@ enum AutoSave {
|
||||
Bool(bool),
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
struct LoadStoreOptions {
|
||||
defaults: Option<HashMap<String, JsonValue>>,
|
||||
auto_save: Option<AutoSave>,
|
||||
serialize_fn_name: Option<String>,
|
||||
deserialize_fn_name: Option<String>,
|
||||
#[serde(default)]
|
||||
create_new: bool,
|
||||
#[serde(default)]
|
||||
override_defaults: bool,
|
||||
}
|
||||
|
||||
fn builder<R: Runtime>(
|
||||
app: AppHandle<R>,
|
||||
store_state: State<'_, StoreState>,
|
||||
path: PathBuf,
|
||||
auto_save: Option<AutoSave>,
|
||||
serialize_fn_name: Option<String>,
|
||||
deserialize_fn_name: Option<String>,
|
||||
create_new: bool,
|
||||
options: Option<LoadStoreOptions>,
|
||||
) -> Result<StoreBuilder<R>> {
|
||||
let mut builder = app.store_builder(path);
|
||||
if let Some(auto_save) = auto_save {
|
||||
|
||||
let Some(options) = options else {
|
||||
return Ok(builder);
|
||||
};
|
||||
|
||||
if let Some(defaults) = options.defaults {
|
||||
builder = builder.defaults(defaults);
|
||||
}
|
||||
|
||||
if let Some(auto_save) = options.auto_save {
|
||||
match auto_save {
|
||||
AutoSave::DebounceDuration(duration) => {
|
||||
builder = builder.auto_save(Duration::from_millis(duration));
|
||||
@@ -75,7 +94,7 @@ fn builder<R: Runtime>(
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(serialize_fn_name) = serialize_fn_name {
|
||||
if let Some(serialize_fn_name) = options.serialize_fn_name {
|
||||
let serialize_fn = store_state
|
||||
.serialize_fns
|
||||
.get(&serialize_fn_name)
|
||||
@@ -83,7 +102,7 @@ fn builder<R: Runtime>(
|
||||
builder = builder.serialize(*serialize_fn);
|
||||
}
|
||||
|
||||
if let Some(deserialize_fn_name) = deserialize_fn_name {
|
||||
if let Some(deserialize_fn_name) = options.deserialize_fn_name {
|
||||
let deserialize_fn = store_state
|
||||
.deserialize_fns
|
||||
.get(&deserialize_fn_name)
|
||||
@@ -91,10 +110,14 @@ fn builder<R: Runtime>(
|
||||
builder = builder.deserialize(*deserialize_fn);
|
||||
}
|
||||
|
||||
if create_new {
|
||||
if options.create_new {
|
||||
builder = builder.create_new();
|
||||
}
|
||||
|
||||
if options.override_defaults {
|
||||
builder = builder.override_defaults();
|
||||
}
|
||||
|
||||
Ok(builder)
|
||||
}
|
||||
|
||||
@@ -103,20 +126,9 @@ async fn load<R: Runtime>(
|
||||
app: AppHandle<R>,
|
||||
store_state: State<'_, StoreState>,
|
||||
path: PathBuf,
|
||||
auto_save: Option<AutoSave>,
|
||||
serialize_fn_name: Option<String>,
|
||||
deserialize_fn_name: Option<String>,
|
||||
create_new: Option<bool>,
|
||||
options: Option<LoadStoreOptions>,
|
||||
) -> Result<ResourceId> {
|
||||
let builder = builder(
|
||||
app,
|
||||
store_state,
|
||||
path,
|
||||
auto_save,
|
||||
serialize_fn_name,
|
||||
deserialize_fn_name,
|
||||
create_new.unwrap_or_default(),
|
||||
)?;
|
||||
let builder = builder(app, store_state, path, options)?;
|
||||
let (_, rid) = builder.build_inner()?;
|
||||
Ok(rid)
|
||||
}
|
||||
@@ -209,9 +221,17 @@ async fn length<R: Runtime>(app: AppHandle<R>, rid: ResourceId) -> Result<usize>
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn reload<R: Runtime>(app: AppHandle<R>, rid: ResourceId) -> Result<()> {
|
||||
async fn reload<R: Runtime>(
|
||||
app: AppHandle<R>,
|
||||
rid: ResourceId,
|
||||
ignore_defaults: Option<bool>,
|
||||
) -> Result<()> {
|
||||
let store = app.resources_table().get::<Store<R>>(rid)?;
|
||||
store.reload()
|
||||
if ignore_defaults.unwrap_or_default() {
|
||||
store.reload_ignore_defaults()
|
||||
} else {
|
||||
store.reload()
|
||||
}
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
|
||||
@@ -39,6 +39,7 @@ pub struct StoreBuilder<R: Runtime> {
|
||||
deserialize_fn: DeserializeFn,
|
||||
auto_save: Option<Duration>,
|
||||
create_new: bool,
|
||||
override_defaults: bool,
|
||||
}
|
||||
|
||||
impl<R: Runtime> StoreBuilder<R> {
|
||||
@@ -66,6 +67,7 @@ impl<R: Runtime> StoreBuilder<R> {
|
||||
deserialize_fn,
|
||||
auto_save: Some(Duration::from_millis(100)),
|
||||
create_new: false,
|
||||
override_defaults: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,6 +180,12 @@ impl<R: Runtime> StoreBuilder<R> {
|
||||
self
|
||||
}
|
||||
|
||||
/// Override the store values when creating the store, ignoring defaults.
|
||||
pub fn override_defaults(mut self) -> Self {
|
||||
self.override_defaults = true;
|
||||
self
|
||||
}
|
||||
|
||||
pub(crate) fn build_inner(mut self) -> crate::Result<(Arc<Store<R>>, ResourceId)> {
|
||||
let stores = self.app.state::<StoreState>().stores.clone();
|
||||
let mut stores = stores.lock().unwrap();
|
||||
@@ -205,7 +213,11 @@ impl<R: Runtime> StoreBuilder<R> {
|
||||
);
|
||||
|
||||
if !self.create_new {
|
||||
let _ = store_inner.load();
|
||||
if self.override_defaults {
|
||||
let _ = store_inner.load_ignore_defaults();
|
||||
} else {
|
||||
let _ = store_inner.load();
|
||||
}
|
||||
}
|
||||
|
||||
let store = Store {
|
||||
@@ -284,6 +296,8 @@ impl<R: Runtime> StoreInner<R> {
|
||||
}
|
||||
|
||||
/// Update the store from the on-disk state
|
||||
///
|
||||
/// Note: This method loads the data and merges it with the current store
|
||||
pub fn load(&mut self) -> crate::Result<()> {
|
||||
let bytes = fs::read(&self.path)?;
|
||||
|
||||
@@ -293,6 +307,13 @@ impl<R: Runtime> StoreInner<R> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Load the store from the on-disk state, ignoring defaults
|
||||
pub fn load_ignore_defaults(&mut self) -> crate::Result<()> {
|
||||
let bytes = fs::read(&self.path)?;
|
||||
self.cache = (self.deserialize_fn)(&bytes).map_err(crate::Error::Deserialize)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Inserts a key-value pair into the store.
|
||||
pub fn set(&mut self, key: impl Into<String>, value: impl Into<JsonValue>) {
|
||||
let key = key.into();
|
||||
@@ -499,10 +520,24 @@ impl<R: Runtime> Store<R> {
|
||||
}
|
||||
|
||||
/// Update the store from the on-disk state
|
||||
///
|
||||
/// Note:
|
||||
/// - This method loads the data and merges it with the current store,
|
||||
/// this behavior will be changed to resetting to default first and then merging with the on-disk state in v3,
|
||||
/// to fully match the store with the on-disk state,
|
||||
/// use [`reload_override_defaults`](Self::reload_override_defaults) instead
|
||||
/// - This method does not emit change events
|
||||
pub fn reload(&self) -> crate::Result<()> {
|
||||
self.store.lock().unwrap().load()
|
||||
}
|
||||
|
||||
/// Load the store from the on-disk state, ignoring defaults
|
||||
///
|
||||
/// Note: This method does not emit change events
|
||||
pub fn reload_ignore_defaults(&self) -> crate::Result<()> {
|
||||
self.store.lock().unwrap().load_ignore_defaults()
|
||||
}
|
||||
|
||||
/// Saves the store to disk at the store's `path`.
|
||||
pub fn save(&self) -> crate::Result<()> {
|
||||
if let Some(sender) = self.auto_save_debounce_sender.lock().unwrap().take() {
|
||||
|
||||
Reference in New Issue
Block a user