fix: muse-action board emits fallback image event even if Rust download fails
Browse files- src-tauri/src/lib.rs +39 -10
src-tauri/src/lib.rs
CHANGED
|
@@ -34,9 +34,44 @@ pub fn run() {
|
|
| 34 |
let query = uri.split('?').nth(1).unwrap_or("");
|
| 35 |
let params: std::collections::HashMap<String, String> = query.split('&').filter_map(|pair| { let (k, v) = pair.split_once('=')?; Some((percent_decode(k), percent_decode(v))) }).collect();
|
| 36 |
match action.as_str() {
|
| 37 |
-
"library" => {
|
| 38 |
-
|
| 39 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 40 |
_ => {}
|
| 41 |
}
|
| 42 |
tauri::http::Response::builder().status(200).header("Access-Control-Allow-Origin", "*").body(Vec::new()).unwrap()
|
|
@@ -76,11 +111,5 @@ pub fn run() {
|
|
| 76 |
.expect("error while running Refstudio");
|
| 77 |
}
|
| 78 |
|
| 79 |
-
fn migrations() -> Vec<Migration> {
|
| 80 |
-
vec![
|
| 81 |
-
Migration { version: 1, description: "phase0_init", sql: include_str!("../migrations/001_phase0_init.sql"), kind: MigrationKind::Up },
|
| 82 |
-
Migration { version: 2, description: "phase3_tables", sql: include_str!("../migrations/002_phase3_tables.sql"), kind: MigrationKind::Up },
|
| 83 |
-
]
|
| 84 |
-
}
|
| 85 |
-
|
| 86 |
fn percent_decode(s: &str) -> String { let bytes = s.as_bytes(); let mut out = Vec::with_capacity(bytes.len()); let mut i = 0; while i < bytes.len() { if bytes[i] == b'%' && i + 2 < bytes.len() { if let Ok(hex) = std::str::from_utf8(&bytes[i+1..i+3]) { if let Ok(v) = u8::from_str_radix(hex, 16) { out.push(v); i += 3; continue; } } } out.push(if bytes[i] == b'+' { b' ' } else { bytes[i] }); i += 1; } String::from_utf8_lossy(&out).to_string() }
|
|
|
|
| 34 |
let query = uri.split('?').nth(1).unwrap_or("");
|
| 35 |
let params: std::collections::HashMap<String, String> = query.split('&').filter_map(|pair| { let (k, v) = pair.split_once('=')?; Some((percent_decode(k), percent_decode(v))) }).collect();
|
| 36 |
match action.as_str() {
|
| 37 |
+
"library" => {
|
| 38 |
+
let url = params.get("url").cloned().unwrap_or_default();
|
| 39 |
+
if !url.is_empty() {
|
| 40 |
+
let source = params.get("source").cloned();
|
| 41 |
+
let title = params.get("title").cloned();
|
| 42 |
+
tauri::async_runtime::spawn(async move { let _ = crate::library::library_add_item(app, url, source, title).await; });
|
| 43 |
+
}
|
| 44 |
+
}
|
| 45 |
+
"board" => {
|
| 46 |
+
let url = params.get("url").cloned().unwrap_or_default();
|
| 47 |
+
if !url.is_empty() {
|
| 48 |
+
let source = params.get("source").cloned().unwrap_or_default();
|
| 49 |
+
let title = params.get("title").cloned().unwrap_or_else(|| "Web Reference".to_string());
|
| 50 |
+
let w = params.get("w").and_then(|s| s.parse::<u32>().ok()).unwrap_or(300);
|
| 51 |
+
let h = params.get("h").and_then(|s| s.parse::<u32>().ok()).unwrap_or(200);
|
| 52 |
+
tauri::async_runtime::spawn(async move {
|
| 53 |
+
match crate::library::library_add_item(app.clone(), url.clone(), Some(source.clone()), Some(title.clone())).await {
|
| 54 |
+
Ok(item) => {
|
| 55 |
+
let _ = crate::board::board_add_image(app.clone(), Some(item.id.clone()), item.data_url.clone(), 120.0, 120.0, 300.0, 200.0);
|
| 56 |
+
let _ = app.emit("board://image_added", serde_json::json!({"libraryId": item.id, "dataUrl": item.data_url, "url": item.url, "sourceUrl": item.source_url, "title": item.title, "width": item.width, "height": item.height, "colors": item.colors}));
|
| 57 |
+
}
|
| 58 |
+
Err(e) => {
|
| 59 |
+
// Fallback: still add visible remote image to the canvas.
|
| 60 |
+
// This mirrors snip/webclip behavior: user action must produce a board item.
|
| 61 |
+
let _ = app.emit("board://image_added", serde_json::json!({"url": url, "dataUrl": url, "sourceUrl": source, "title": title, "width": w, "height": h, "colors": [], "downloadError": e}));
|
| 62 |
+
}
|
| 63 |
+
}
|
| 64 |
+
});
|
| 65 |
+
}
|
| 66 |
+
}
|
| 67 |
+
"vault" => {
|
| 68 |
+
let va = params.get("action").cloned().unwrap_or_default();
|
| 69 |
+
match va.as_str() {
|
| 70 |
+
"save-prompt" => { let _ = app.emit("vault://save-prompt", serde_json::json!({"origin": params.get("origin").cloned().unwrap_or_default(), "username": params.get("username").cloned().unwrap_or_default(), "password": params.get("password").cloned().unwrap_or_default()})); }
|
| 71 |
+
"has-login-form" => { let _ = app.emit("vault://login-detected", serde_json::json!({"origin": params.get("origin").cloned().unwrap_or_default(), "fields": params.get("fields").cloned().unwrap_or_default()})); }
|
| 72 |
+
_ => {}
|
| 73 |
+
}
|
| 74 |
+
}
|
| 75 |
_ => {}
|
| 76 |
}
|
| 77 |
tauri::http::Response::builder().status(200).header("Access-Control-Allow-Origin", "*").body(Vec::new()).unwrap()
|
|
|
|
| 111 |
.expect("error while running Refstudio");
|
| 112 |
}
|
| 113 |
|
| 114 |
+
fn migrations() -> Vec<Migration> { vec![ Migration { version: 1, description: "phase0_init", sql: include_str!("../migrations/001_phase0_init.sql"), kind: MigrationKind::Up }, Migration { version: 2, description: "phase3_tables", sql: include_str!("../migrations/002_phase3_tables.sql"), kind: MigrationKind::Up } ] }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 115 |
fn percent_decode(s: &str) -> String { let bytes = s.as_bytes(); let mut out = Vec::with_capacity(bytes.len()); let mut i = 0; while i < bytes.len() { if bytes[i] == b'%' && i + 2 < bytes.len() { if let Ok(hex) = std::str::from_utf8(&bytes[i+1..i+3]) { if let Ok(v) = u8::from_str_radix(hex, 16) { out.push(v); i += 3; continue; } } } out.push(if bytes[i] == b'+' { b' ' } else { bytes[i] }); i += 1; } String::from_utf8_lossy(&out).to_string() }
|