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
124 lines
4.3 KiB
Rust
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");
|
|
}
|