mod commands; mod libraries; mod news; mod state; mod sync; use std::sync::Mutex; use tauri::Manager; use state::AppState; /// Write a line to the platform log. /// /// On Android this reaches `adb logcat` under the tag `RustStdoutStderr`: tao's /// Android glue `dup2`s stdout/stderr into a pipe and forwards each line to the /// system log, so a plain `eprintln!` is all that's needed and no logging /// dependency is warranted. On desktop it's just stderr. /// /// This matters because Tauri command failures are *returned* to the WebView as /// values, not raised — so without logging them explicitly they never appear in /// logcat at all, and the UI only ever shows a truncated version. #[macro_export] macro_rules! mlog { ($($arg:tt)*) => { eprintln!("[mtgc] {}", format_args!($($arg)*)) }; } /// Log a command failure (with its full, untruncated message) and pass the /// result through unchanged. pub(crate) fn logged(what: &str, result: Result) -> Result { if let Err(e) = &result { crate::mlog!("{what} failed: {e}"); } result } #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { let builder = tauri::Builder::default().plugin(tauri_plugin_dialog::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. #[cfg(target_os = "android")] let builder = builder.plugin(tauri_plugin_deep_link::init()); builder .setup(|app| { let data_dir = app .path() .app_data_dir() .expect("resolve app data dir"); std::fs::create_dir_all(&data_dir).ok(); mlog!("data dir: {}", data_dir.display()); app.manage(Mutex::new(AppState::new(data_dir))); #[cfg(target_os = "android")] { use tauri_plugin_deep_link::DeepLinkExt; app.deep_link().on_open_url(|event| { for url in event.urls() { sync::deliver_callback(url.as_str()); } }); } Ok(()) }) .invoke_handler(tauri::generate_handler![ commands::get_status, commands::update_card_data, commands::cancel_update_card_data, commands::import_reference_db, sync::sync_status, sync::sync_sign_in, sync::sync_cancel_sign_in, sync::sync_sign_out, sync::sync_now, sync::sync_connect, sync::sync_devices, sync::sync_revoke_device, sync::import_library_file, libraries::list_libraries, libraries::create_library, libraries::switch_library, libraries::rename_library, libraries::delete_library, libraries::set_library_sync, sync::export_library_document, news::get_news, news::get_set_cards, commands::search_cards, commands::add_owned, commands::set_owned, commands::set_location, commands::search_library, commands::search_reference, commands::get_library_stats, commands::get_library_facets, commands::get_reference_facets, commands::list_decks, commands::create_deck, commands::delete_deck, commands::rename_deck, commands::duplicate_deck, commands::set_deck_format, commands::set_deck_commander, commands::set_deck_card, commands::deck_contents, commands::suggest_cards, commands::card_decks, commands::list_printings, commands::list_library_copies, commands::set_library_copy, commands::set_deck_card_printing, commands::export_deck, commands::import_deck, commands::export_library_cards, commands::import_library_cards, ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); }