Read picked import files through the fs plugin so Android content URIs work
On Android the open dialog returns a content:// URI, which std::fs can't open, so ManaBox/library and deck imports failed with "no such file or directory". Read them via tauri-plugin-fs, which resolves content URIs and falls through to plain paths on desktop. Closes #24
This commit is contained in:
@@ -16,6 +16,9 @@ tauri-build = { version = "2", features = [] }
|
||||
[dependencies]
|
||||
tauri = { version = "2", features = [] }
|
||||
tauri-plugin-dialog = "2"
|
||||
# Reads the files the dialog picks: on Android those are content:// URIs, which
|
||||
# std::fs can't open.
|
||||
tauri-plugin-fs = "2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
mtgc-core = { path = "../crates/mtgc-core" }
|
||||
|
||||
@@ -11,6 +11,7 @@ use mtgc_core::{
|
||||
};
|
||||
use serde::Serialize;
|
||||
use tauri::{AppHandle, Emitter, State};
|
||||
use tauri_plugin_fs::{FilePath, FsExt};
|
||||
|
||||
use crate::state::AppState;
|
||||
|
||||
@@ -416,10 +417,17 @@ pub fn export_deck(db: Db, deck_id: i64, path: String) -> Res<()> {
|
||||
std::fs::write(&path, text).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Read a text file the open dialog picked. On Android that's a content:// URI
|
||||
/// rather than a filesystem path, so it has to go through the fs plugin.
|
||||
fn read_picked_text(app: &AppHandle, path: &str) -> Res<String> {
|
||||
let path: FilePath = path.parse().unwrap();
|
||||
app.fs().read_to_string(path).map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn import_deck(db: Db, path: String, name: String) -> Res<DeckImportResult> {
|
||||
pub fn import_deck(app: AppHandle, db: Db, path: String, name: String) -> Res<DeckImportResult> {
|
||||
let text = read_picked_text(&app, &path)?;
|
||||
let s = db.lock().unwrap();
|
||||
let text = std::fs::read_to_string(&path).map_err(|e| e.to_string())?;
|
||||
let (deck, unresolved) = s.catalog()?.import_deck(&name, &text).map_err(|e| e.to_string())?;
|
||||
Ok(DeckImportResult { deck, unresolved })
|
||||
}
|
||||
@@ -452,7 +460,7 @@ pub async fn import_library_cards(
|
||||
location: Option<String>,
|
||||
) -> Res<LibraryImportResult> {
|
||||
crate::sync::blocking(move || {
|
||||
let text = std::fs::read_to_string(&path).map_err(|e| e.to_string())?;
|
||||
let text = read_picked_text(&app, &path)?;
|
||||
let s = crate::sync::lock(&app);
|
||||
// At most one event per percent, so a big file doesn't flood the UI.
|
||||
let mut last_percent = None;
|
||||
|
||||
@@ -37,6 +37,7 @@ pub(crate) fn logged<T>(what: &str, result: Result<T, String>) -> Result<T, Stri
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
let builder = tauri::Builder::default().plugin(tauri_plugin_dialog::init())
|
||||
.plugin(tauri_plugin_fs::init())
|
||||
.plugin(tauri_plugin_opener::init());
|
||||
// Android gets sync sign-ins back through the `mtgc://` scheme; desktop
|
||||
// uses a loopback port instead and needs no scheme registered.
|
||||
|
||||
Reference in New Issue
Block a user