Rework library sync around a JSON document; add card filters
Sync
The previous design put the merge inside SQL: timestamp-stamping triggers,
a tombstone table, per-device SQLite snapshots, a device id in the database,
and row merges written as correlated-subquery UPDATEs. All of that schema
was inherited by desktop, and the merge was very hard to verify.
Replace it with a single JSON document plus a three-way merge in plain Rust.
Storing the last-read remote document as the merge base makes "who changed
what" and "what was deleted" derivable, which removes the tombstone table,
the updated_at columns and all eight triggers. It also makes a single shared
file safe: if a publish is lost the remote is unchanged, so the next merge
re-detects the local edits and republishes rather than reading their absence
as a deletion. That removes the need for per-device files and for device
identity entirely. Schema impact drops to one column, decks.uuid.
Conflicts resolve to "theirs", which is required for convergence rather than
chosen for taste — preferring ours has each device re-asserting its own value
forever. Every such choice is reported to the user.
SQLite becomes invisible: the working copy lives in the app data dir and the
user only ever names a .json file. There is always a document, defaulting to
private storage, so edits are never stranded with nowhere to be saved.
Pointing at a file that doesn't exist yet moves the current library there;
pointing at one that does adopts it. A converter brings a pre-document
library.db across.
Android reaches the folder through the Storage Access Framework rather than
MANAGE_EXTERNAL_STORAGE, so no storage permission is declared at all.
Filters
Track card origin in reference.db: Universes Beyond, digital-only and
Un-set cards, plus numeric power/toughness. Each origin flag is derived as
"every printing", not "any printing" — ordinary cards get reprinted into
those sets, and Lightning Bolt appearing in Marvel Commander must not hide
it. Non-numeric power ("*", "1+*") stays NULL so it drops out of range
filters instead of being compared as zero.
Also wire up filters over data already present: price range, format legality
(restricted counts as legal) and "can be a commander". All of these degrade
silently against an older reference.db rather than failing every query.
The shared criteria live in one component used by both filter panels, as a
compact row of icon toggles.
Card Search gains the Library tab's bulk selection: checkboxes in both views,
select-all, and a bulk add-to-deck with a single undo for the whole batch.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
mod commands;
|
||||
mod state;
|
||||
mod sync;
|
||||
|
||||
use std::sync::Mutex;
|
||||
|
||||
@@ -31,10 +32,27 @@ pub(crate) fn logged<T>(what: &str, result: Result<T, String>) -> Result<T, Stri
|
||||
result
|
||||
}
|
||||
|
||||
/// Register the Kotlin-side `SyncPlugin` and stash its handle in app state, so
|
||||
/// the sync commands can call across to SAF. See `sync.rs` for why library sync
|
||||
/// goes through a Java plugin rather than plain `std::fs`.
|
||||
#[cfg(target_os = "android")]
|
||||
fn sync_plugin() -> tauri::plugin::TauriPlugin<tauri::Wry> {
|
||||
tauri::plugin::Builder::new("mtgc-sync")
|
||||
.setup(|app, api| {
|
||||
let handle = api.register_android_plugin("com.garrettmills.mtgc", "SyncPlugin")?;
|
||||
app.manage(sync::SyncBridge(handle));
|
||||
Ok(())
|
||||
})
|
||||
.build()
|
||||
}
|
||||
|
||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||
pub fn run() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_dialog::init())
|
||||
let builder = tauri::Builder::default().plugin(tauri_plugin_dialog::init());
|
||||
#[cfg(target_os = "android")]
|
||||
let builder = builder.plugin(sync_plugin());
|
||||
|
||||
builder
|
||||
.setup(|app| {
|
||||
let data_dir = app
|
||||
.path()
|
||||
@@ -47,10 +65,15 @@ pub fn run() {
|
||||
})
|
||||
.invoke_handler(tauri::generate_handler![
|
||||
commands::get_status,
|
||||
commands::set_library_path,
|
||||
commands::update_card_data,
|
||||
commands::cancel_update_card_data,
|
||||
commands::import_reference_db,
|
||||
sync::sync_status,
|
||||
sync::sync_pick_folder,
|
||||
sync::sync_set_document,
|
||||
sync::sync_forget_document,
|
||||
sync::sync_now,
|
||||
sync::convert_legacy_library,
|
||||
commands::search_cards,
|
||||
commands::add_owned,
|
||||
commands::set_owned,
|
||||
|
||||
Reference in New Issue
Block a user