Files
mtgc/src-tauri/src/lib.rs
Garrett Mills bfad4c1f27 Partner commanders: Partner, Partner—<variant>, Partner with, Background, Doctor
A Commander/Brawl deck can now have two commanders when their abilities
allow it. Partner abilities are parsed from oracle text (Scryfall's keyword
list files every "Partner—Survivors"-style variant under plain "Partner"),
and a second search box offers only cards that can pair with the commander.
The legality check accepts a valid pair and checks color identity against
both; suggestions and decklist import/export handle both commanders.

Closes #4
2026-10-23 22:29:56 -05:00

124 lines
4.3 KiB
Rust

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<T>(what: &str, result: Result<T, String>) -> Result<T, String> {
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_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.
#[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_commanders,
commands::search_partners,
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");
}