1use directories::ProjectDirs;
2use std::{
3 error::Error,
4 fmt,
5 fs::create_dir_all,
6 io::{Read, Write},
7 sync::Mutex,
8};
9use tauri::{plugin::TauriPlugin, Manager, Runtime};
10
11pub fn init<R: Runtime>() -> TauriPlugin<R> {
12 tauri::plugin::Builder::new("tauri-elm")
13 .invoke_handler(tauri::generate_handler![
14 http_request,
15 read_file,
16 write_file,
17 ])
18 .setup(|app_handler| {
19 if let Some(proj_dir) = ProjectDirs::from("com", "tauri-elm", "test-app") {
20 if let Err(err) = create_dir_all(proj_dir.data_dir()) {
21 Err(Box::new(SetupError(format!(
22 "Could not create data dir: {}",
23 err
24 ))))
25 } else {
26 app_handler.manage(default_state(proj_dir));
27 Ok(())
28 }
29 } else {
30 Err(Box::new(SetupError("Could not setup plugin".into())))
31 }
32 })
33 .build()
34}
35
36#[derive(Debug)]
37struct SetupError(String);
38
39impl fmt::Display for SetupError {
40 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
41 write!(f, "There is an error: {}", self.0)
42 }
43}
44
45impl Error for SetupError {}
46
47#[derive(serde::Serialize)]
48struct Response {
49 status: u16,
50 body: String,
51}
52
53#[derive(serde::Deserialize)]
54struct Request {
55 url: String,
56}
57
58#[tauri::command(async)]
59async fn http_request(request: Request) -> Result<Response, String> {
60 let resp = reqwest::get(request.url).await;
61 match resp {
62 Ok(r) => {
63 let status_code = r.status().as_u16();
64 match r.text().await {
65 Ok(b) => Ok(Response {
66 body: b,
67 status: status_code,
68 }),
69 Err(err) => Err(format!("Could not get text from response: {}", err)),
70 }
71 }
72 Err(err) => Err(format!("Could not make request: {}", err)),
73 }
74}
75
76#[tauri::command]
77fn read_file(state: tauri::State<AppState>, name: String) -> Result<String, String> {
78 let app_state = state.0.lock().unwrap();
79 let path = app_state.proj_dir.data_dir().join(name);
80
81 let file = std::fs::OpenOptions::new()
82 .write(true)
83 .read(true)
84 .create(true)
85 .open(&path);
86
87 match file {
88 Ok(mut f) => {
89 let mut buf = String::new();
90 match f.read_to_string(&mut buf) {
91 Ok(_) => Ok(buf),
92 Err(err) => Err(format!("--- {}", err)),
93 }
94 }
95 Err(err) => Err(format!("<<< {} {}", path.display().to_string(), err)),
96 }
97}
98
99#[tauri::command]
100fn write_file(state: tauri::State<AppState>, name: String, data: String) -> Result<(), String> {
101 let app_state = state.0.lock().unwrap();
102 let path = app_state.proj_dir.data_dir().join(name);
103
104 let file = std::fs::OpenOptions::new()
105 .write(true)
106 .create(true)
107 .open(&path);
108
109 println!("saving the data: {}", data);
110
111 match file {
112 Ok(mut f) => match f.write_all(&data.as_bytes()) {
113 Ok(()) => Ok(()),
114 Err(err) => Err(err.to_string()),
115 },
116 Err(err) => Err(format!("{} {}", path.display().to_string(), err)),
117 }
118}
119
120struct AppState(Mutex<App>);
121
122struct App {
123 proj_dir: ProjectDirs,
126}
127
128fn default_state(proj_dir: ProjectDirs) -> AppState {
129 AppState(Mutex::new(App {
130 proj_dir,
133 }))
134}