Access Tauri's plugin variable from Yew frontend

142 Views Asked by At

I have a project that contains Tauri backend and Yew frontend. I'm trying to save a form variable to file with tauri_plugin_store library. But the documentation is horrible and I'm not sure how to call store variable from my frontend or just from save_to_file function to be able to save data there. This is how my Tauri main.rs looks like


// Prevents additional console window on Windows in release, DO NOT REMOVE!!
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]

use tauri::Error;
use tauri_plugin_store::StoreBuilder;
use serde_json::json;

// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
#[tauri::command]
fn greets(name: &str) -> String {
    format!("Hello, {}! You've been greeted from Rust!", name)
}

#[tauri::command]
fn save_to_file(day: &str, text: &str, parent: &str) -> Result<(), Error>{
    println!(">>>>{}", text);
    return Ok(())
}

fn main() {
    tauri::Builder::default()
        .invoke_handler(tauri::generate_handler![greets, save_to_file])
        .plugin(tauri_plugin_store::Builder::default().build())
        .setup(|app| {
            let mut store = StoreBuilder::new(app.handle(), "/Users/a/Desktop/tauri_project/store.bin".parse()?).build();
            Ok(store.insert("a".to_string(), json!("b"))?)
        })
        .run(tauri::generate_context!())
        .expect("error while running tauri application");
}

As you can see I have save_to_file() to saving my data. I'm invoking this function from my form.rs inside of Yew app. I'm able to call it and pass the data, but no save it, because store is defined in main as local variable


fn execute_effect(user_record: Record) {
    spawn_local(async move {
        if user_record.day == "" || user_record.text == "" || user_record.parent == "" {
            return;
        } else {
            let args = to_value(&Record {
                day: user_record.day.clone(),
                text: user_record.text.clone(),
                parent: user_record.parent.clone(),
            })
            .unwrap();

            let new_msg = invoke("save_to_file", args).await.as_string();
            log!("{:#?}", new_msg);
        }
    });
}

Is there some workaround this?

I saw this example at the github page


//As you may have noticed, the Store crated above isn't accessible to the frontend. To interoperate with stores created by JS use the exported with_store method:

use tauri::Wry;
use tauri_plugin_store::with_store;

let stores = app.state::<StoreCollection<Wry>>();
let path = PathBuf::from("path/to/the/storefile");

with_store(app_handle, stores, path, |store| store.insert("a".to_string(), json!("b")))

But this really says nothing... what is StoreCollection? How can I import tauri from inside the Yew? Wtf is app??

2

There are 2 best solutions below

0
interstellarfrog On BEST ANSWER

This question was asked 4 months ago so you probably won't care, and there is probably a better way to do this, but here is my answer for others who may have came across something like this.

Note: I am using tauri 2.0.0-alpha.13 so some syntax may be different

Inside of my project I need to access variables and information inside of the setup function at runtime from the frontend, the way I do this is using tauri commands, but as you can see there is no visible way to store this information globally or pass this data to the frontend without the data going out of scope.

One way you can handle this is by using once_cell and mutex, to create a static value that can be initialized lazily at runtime and safely used between threads using locking mechanisms, this allows you to

  1. Get the data at runtime
  2. Save the data
  3. Then access the cloned data and functions even after the initial variable has gone out of scope.

And since you are using the app handle which is cloneable (at least in my version) then you should be able to save it and create the tauri Store inside of the tauri command functions using it or you may be able to save the tauri Store inside of the lazy static so you don't have to create a new one every time you want to save or get information.

Here is my current setup

use lazy_static::lazy_static;
use once_cell::sync::OnceCell;
use spin::lock_api::Mutex;

lazy_static! {
    static ref INFORMATION: OnceCell<Mutex<Information>> = OnceCell::new();
}

#[tauri::command]
fn get_config() -> Config {
    INFORMATION
        .get()
        .expect("MAJOR ERROR: Application Global Information Struct Not Initialized")
        .lock()
        .config
        .to_owned()
}


// Inside of my main function
tauri::Builder::default()
        .setup(|app| {
            // useful info
            let app_handle = app.app_handle();
            let app_config = app.config();

            INFORMATION.get_or_init(|| {
                let information = Information {
                    config: app_config.to_owned(),
                    app_handle: app_handle.to_owned(),
                };

                Mutex::new(information)
            });

            Ok(())
        })


0
Tom Cheung On

Try another store crate in rust layer. tauri_plugin_store just use rust std::File, not the best.