From edb5cda772ced5b9a62b3daac5468f082f3ab957 Mon Sep 17 00:00:00 2001 From: b5 Date: Mon, 25 Mar 2024 20:56:00 -0400 Subject: [PATCH 1/5] chore: upgrade iroh to v0.13.0 --- Cargo.lock | 186 ++++++++++++++++++++++++++++++++------------------- Cargo.toml | 7 +- src/main.rs | 37 +++++----- tests/cli.rs | 2 +- 4 files changed, 142 insertions(+), 90 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 98ed742..cb151ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -232,12 +232,13 @@ dependencies = [ [[package]] name = "bao-tree" -version = "0.9.1" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "155e7e0c896695a9049badd7bf2b915d29230e24dc82a7c7ef065eded072404f" +checksum = "bdae307defb220bd2698a42495e226ff89e3173f024abfc2182129603e74b5c7" dependencies = [ "bytes", "futures", + "genawaiter", "iroh-blake3", "iroh-io", "positioned-io", @@ -435,6 +436,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "concurrent-queue" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "console" version = "0.15.7" @@ -912,9 +922,14 @@ dependencies = [ [[package]] name = "event-listener" -version = "2.5.3" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +checksum = "67b215c49b2b248c855fb73579eb1f4f26c38ffdc12973e20e07b91d78d5646e" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] [[package]] name = "fallible-iterator" @@ -986,6 +1001,17 @@ dependencies = [ "futures-util", ] +[[package]] +name = "futures-buffered" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "de8419e65098e54c06f5ae8a130a79e8ba2e391ff995d260ca5d77ea72ab2fe3" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", +] + [[package]] name = "futures-channel" version = "0.3.29" @@ -1209,6 +1235,51 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hickory-proto" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "091a6fbccf4860009355e3efc52ff4acf37a63489aad7435372d44ceeb6fbbcf" +dependencies = [ + "async-trait", + "cfg-if", + "data-encoding", + "enum-as-inner", + "futures-channel", + "futures-io", + "futures-util", + "idna 0.4.0", + "ipnet", + "once_cell", + "rand", + "thiserror", + "tinyvec", + "tokio", + "tracing", + "url", +] + +[[package]] +name = "hickory-resolver" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35b8f021164e6a984c9030023544c57789c51760065cd510572fedcfb04164e8" +dependencies = [ + "cfg-if", + "futures-util", + "hickory-proto", + "ipconfig", + "lru-cache", + "once_cell", + "parking_lot", + "rand", + "resolv-conf", + "smallvec", + "thiserror", + "tokio", + "tracing", +] + [[package]] name = "hmac" version = "0.12.1" @@ -1524,19 +1595,31 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "iroh-base" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b42ef43639a86a49132998f066810b702798818993e34565dd4eea835f626e" +checksum = "5892623f5c5b2cf00c29c248338e0dd228c76bbe8d64bfa9f30630377e4c4c06" dependencies = [ + "aead", "anyhow", "bao-tree", + "crypto_box", "data-encoding", + "derive_more", + "ed25519-dalek", "hex", "multibase", + "once_cell", "postcard", + "rand", + "rand_core", + "redb", "serde", "serde-error", + "ssh-key", "thiserror", + "ttl_cache", + "url", + "zeroize", ] [[package]] @@ -1554,9 +1637,9 @@ dependencies = [ [[package]] name = "iroh-bytes" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38213865ec542f82fc4d8a9748b5cdae92da1707c134428e9f60b1cd46ccbe39" +checksum = "e8fb3c7d9b7ccedd459ea3425c4bdc75961d95e009eec817f0126e1658f07f08" dependencies = [ "anyhow", "bao-tree", @@ -1566,6 +1649,7 @@ dependencies = [ "derive_more", "flume", "futures", + "futures-buffered", "genawaiter", "hex", "iroh-base", @@ -1576,6 +1660,7 @@ dependencies = [ "quinn", "rand", "range-collections", + "redb", "reflink-copy", "self_cell", "serde", @@ -1590,9 +1675,9 @@ dependencies = [ [[package]] name = "iroh-io" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ace4f69567bfeb726672bab901d3e81be0c01119d860b2a10b7efb1553b880" +checksum = "1fd67e386f948a6f09e71057b48fff51b6414f0080997495b5bdf2d1bdcdbe46" dependencies = [ "bytes", "futures", @@ -1603,9 +1688,9 @@ dependencies = [ [[package]] name = "iroh-metrics" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92a3271df85ec2a18a358d36723039eeacb464d8764531c8fd9f822dac39410d" +checksum = "e4b29ecbd3a1581e5b73c59cdff20225690f5eed32f293728563a0d06c2c91fe" dependencies = [ "anyhow", "erased_set", @@ -1624,26 +1709,25 @@ dependencies = [ [[package]] name = "iroh-net" -version = "0.12.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0477847a7fe225f71fbdff7b0baccea8fc9c9b33e7755f4b28e19f075bd64499" +checksum = "77d4ef2660b04e61525a140fe9f12cdfdcfc483d0b28cb81022df4f203947d4b" dependencies = [ "aead", "anyhow", "backoff", "bytes", - "crypto_box", "curve25519-dalek", "data-encoding", "default-net", "der", "derive_more", "duct", - "ed25519-dalek", "flume", "futures", "governor", "hex", + "hickory-resolver", "hostname", "http 1.0.0", "http-body-util", @@ -1676,7 +1760,6 @@ dependencies = [ "serdect", "smallvec", "socket2", - "ssh-key", "strum", "stun-rs", "surge-ping", @@ -1687,15 +1770,12 @@ dependencies = [ "tokio-rustls-acme", "tokio-util", "tracing", - "trust-dns-resolver", - "ttl_cache", "url", "watchable", "webpki-roots", "windows 0.51.1", "wmi", "x509-parser", - "zeroize", ] [[package]] @@ -2176,6 +2256,12 @@ dependencies = [ "sha2", ] +[[package]] +name = "parking" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb813b8af86854136c6922af0598d719255ecb2179515e6e7730d468f05c9cae" + [[package]] name = "parking_lot" version = "0.12.1" @@ -2718,6 +2804,15 @@ dependencies = [ "yasna", ] +[[package]] +name = "redb" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd7f82ecd6ba647a39dd1a7172b8a1cd9453c0adee6da20cb553d83a9a460fa5" +dependencies = [ + "libc", +] + [[package]] name = "redox_syscall" version = "0.4.1" @@ -3139,6 +3234,7 @@ dependencies = [ "futures", "hex", "indicatif", + "iroh-base", "iroh-bytes", "iroh-io", "iroh-net", @@ -3806,52 +3902,6 @@ dependencies = [ "tracing-log", ] -[[package]] -name = "trust-dns-proto" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3119112651c157f4488931a01e586aa459736e9d6046d3bd9105ffb69352d374" -dependencies = [ - "async-trait", - "cfg-if", - "data-encoding", - "enum-as-inner", - "futures-channel", - "futures-io", - "futures-util", - "idna 0.4.0", - "ipnet", - "once_cell", - "rand", - "smallvec", - "thiserror", - "tinyvec", - "tokio", - "tracing", - "url", -] - -[[package]] -name = "trust-dns-resolver" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a3e6c3aff1718b3c73e395d1f35202ba2ffa847c6a62eea0db8fb4cfe30be6" -dependencies = [ - "cfg-if", - "futures-util", - "ipconfig", - "lru-cache", - "once_cell", - "parking_lot", - "rand", - "resolv-conf", - "smallvec", - "thiserror", - "tokio", - "tracing", - "trust-dns-proto", -] - [[package]] name = "try-lock" version = "0.2.5" @@ -4066,9 +4116,9 @@ checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" [[package]] name = "watchable" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff90d0baafb3c0abbeebec1a8a305b4211c356de1d953a0dd77aab006baa8a62" +checksum = "45b42a2f611916b5965120a9cde2b60f2db4454826dd9ad5e6f47c24a5b3b259" dependencies = [ "event-listener", "futures-util", diff --git a/Cargo.toml b/Cargo.toml index 7d493ce..450ce6d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,9 +19,10 @@ flume = "0.11.0" futures = "0.3.29" hex = "0.4.3" indicatif = "0.17.7" -iroh-bytes = "0.12" -iroh-io = "0.3.0" -iroh-net = "0.12" +iroh-base="0.13" +iroh-bytes = "0.13" +iroh-io = "0.4.0" +iroh-net = "0.13" num_cpus = "1.16.0" rand = "0.8.5" tokio = { version = "1.34.0", features = ["full"] } diff --git a/src/main.rs b/src/main.rs index 1ddadee..3c03603 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,6 +9,7 @@ use futures::{future, FutureExt, Stream, StreamExt}; use indicatif::{ HumanBytes, HumanDuration, MultiProgress, ProgressBar, ProgressDrawTarget, ProgressStyle, }; +use iroh_base::ticket::BlobTicket; use iroh_bytes::{ format::collection::Collection, get::{ @@ -20,7 +21,7 @@ use iroh_bytes::{ store::{ExportMode, ImportMode, ImportProgress}, BlobFormat, Hash, HashAndFormat, TempTag, }; -use iroh_net::{key::SecretKey, ticket::BlobTicket, MagicEndpoint}; +use iroh_net::{key::SecretKey, MagicEndpoint}; use rand::Rng; use std::{ collections::BTreeMap, @@ -342,8 +343,13 @@ async fn export(db: impl iroh_bytes::store::Store, collection: Collection) -> an eprintln!("You can remove the file or directory and try again. The download will not be repeated."); anyhow::bail!("target {} already exists", target.display()); } - db.export(*hash, target, ExportMode::TryReference, |_position| Ok(())) - .await?; + db.export( + *hash, + target, + ExportMode::TryReference, + Box::new(move |_position| Ok(())), + ) + .await?; } Ok(()) } @@ -455,14 +461,14 @@ async fn send(args: SendArgs) -> anyhow::Result<()> { anyhow::Ok(()) }); std::fs::create_dir_all(&iroh_data_dir)?; - let db = iroh_bytes::store::flat::Store::load(&iroh_data_dir).await?; + let db = iroh_bytes::store::fs::Store::load(&iroh_data_dir).await?; let path = args.path; let (temp_tag, size, collection) = import(path.clone(), db.clone()).await?; let hash = *temp_tag.hash(); // wait for the endpoint to be ready let endpoint = endpoint_fut.await?; // wait for the endpoint to figure out its address before making a ticket - while endpoint.my_derp().is_none() { + while endpoint.my_relay().is_none() { tokio::time::sleep(std::time::Duration::from_millis(100)).await; } // make a ticket @@ -546,20 +552,14 @@ pub async fn show_download_progress( DownloadProgress::Done { id } => { total_done += sizes.remove(&id).unwrap_or_default(); } - DownloadProgress::NetworkDone { - bytes_read, - elapsed, - .. - } => { + DownloadProgress::AllDone(stats) => { op.finish_and_clear(); eprintln!( "Transferred {} in {}, {}/s", - HumanBytes(bytes_read), - HumanDuration(elapsed), - HumanBytes((bytes_read as f64 / elapsed.as_secs_f64()) as u64) + HumanBytes(stats.bytes_read), + HumanDuration(stats.elapsed), + HumanBytes((stats.bytes_read as f64 / stats.elapsed.as_secs_f64()) as u64) ); - } - DownloadProgress::AllDone => { break; } DownloadProgress::Abort(e) => { @@ -628,7 +628,7 @@ async fn get(args: ReceiveArgs) -> anyhow::Result<()> { .await?; let dir_name = format!(".sendme-get-{}", ticket.hash().to_hex()); let iroh_data_dir = std::env::current_dir()?.join(dir_name); - let db = iroh_bytes::store::flat::Store::load(&iroh_data_dir).await?; + let db = iroh_bytes::store::fs::Store::load(&iroh_data_dir).await?; let mp = MultiProgress::new(); let connect_progress = mp.add(ProgressBar::hidden()); connect_progress.set_draw_target(ProgressDrawTarget::stderr()); @@ -664,9 +664,10 @@ async fn get(args: ReceiveArgs) -> anyhow::Result<()> { ); } let _task = tokio::spawn(show_download_progress(recv.into_stream(), total_size)); - let stats = iroh_bytes::get::db::get_to_db(&db, connection, &hash_and_format, progress) + let get_conn = || async move { Ok(connection) }; + let stats = iroh_bytes::get::db::get_to_db(&db, get_conn, &hash_and_format, progress) .await - .map_err(show_get_error)?; + .map_err(|e| show_get_error(anyhow::anyhow!(e)))?; let collection = Collection::load(&db, &hash_and_format.hash).await?; if args.common.verbose > 0 { for (name, hash) in collection.iter() { diff --git a/tests/cli.rs b/tests/cli.rs index 7994ff4..8cc9d38 100644 --- a/tests/cli.rs +++ b/tests/cli.rs @@ -4,7 +4,7 @@ use std::{ str::FromStr, }; -use iroh_net::ticket::BlobTicket; +use iroh_base::ticket::BlobTicket; // binary path fn sendme_bin() -> &'static str { From f08d722d2202c72e9e0b2fb6c315cdbcfba843ae Mon Sep 17 00:00:00 2001 From: b5 Date: Mon, 25 Mar 2024 21:05:16 -0400 Subject: [PATCH 2/5] chore(deps): update deps, bump dev deps --- Cargo.lock | 901 +++++++++++++++++++++++++++-------------------------- Cargo.toml | 2 +- 2 files changed, 460 insertions(+), 443 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb151ed..bfb722b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "once_cell", @@ -42,9 +42,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -72,9 +72,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.5" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ "anstyle", "anstyle-parse", @@ -86,9 +86,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" @@ -120,9 +120,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.76" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59d2a3357dde987206219e78ecfbbb6e8dad06cbb65292758d3270e6254f7355" +checksum = "0952808a6c2afd1aa8947271f3a60f1a6763c7b912d210184c5149b5cf147247" [[package]] name = "arrayref" @@ -177,13 +177,13 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.75" +version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdf6721fb0140e4f897002dd086c06f6c27775df19cfe1fccb21181a48fd2c98" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] @@ -192,7 +192,7 @@ version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fdb8867f378f33f78a811a8eb9bf108ad99430d7aad43315dd9319c827ef6247" dependencies = [ - "http 0.2.11", + "http 0.2.12", "log", "url", "wildmatch", @@ -200,9 +200,9 @@ dependencies = [ [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "backoff" @@ -217,9 +217,9 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -268,9 +268,15 @@ checksum = "23ce669cd6c8588f79e15cf450314f9638f967fc5770ff1c7c1deb0925ea7cfa" [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" [[package]] name = "base64ct" @@ -292,9 +298,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" [[package]] name = "block-buffer" @@ -313,9 +319,9 @@ checksum = "78a6932c88f1d2c29533a3b8a5f5a2f84cc19c3339b431677c3160c5c2e6ca85" [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "byteorder" @@ -325,21 +331,18 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" dependencies = [ "serde", ] [[package]] name = "cc" -version = "1.0.83" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" [[package]] name = "cfg-if" @@ -347,6 +350,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chacha20" version = "0.9.1" @@ -360,9 +369,9 @@ dependencies = [ [[package]] name = "chrono" -version = "0.4.31" +version = "0.4.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" dependencies = [ "android-tzdata", "iana-time-zone", @@ -370,7 +379,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.48.5", + "windows-targets 0.52.4", ] [[package]] @@ -386,9 +395,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.11" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -396,9 +405,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.11" +version = "4.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4" dependencies = [ "anstream", "anstyle", @@ -408,21 +417,21 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ - "heck", + "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce" [[package]] name = "cobs" @@ -447,15 +456,15 @@ dependencies = [ [[package]] name = "console" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" dependencies = [ "encode_unicode", "lazy_static", "libc", "unicode-width", - "windows-sys 0.45.0", + "windows-sys 0.52.0", ] [[package]] @@ -508,9 +517,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -532,12 +541,9 @@ checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" [[package]] name = "crossbeam-utils" -version = "0.8.17" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d96137f14f244c37f989d9fff8f95e6c18b918e71f36638f8c49112e4c78f" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crypto-bigint" @@ -596,9 +602,9 @@ dependencies = [ [[package]] name = "curve25519-dalek" -version = "4.1.1" +version = "4.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c" +checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348" dependencies = [ "cfg-if", "cpufeatures", @@ -619,7 +625,7 @@ checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] @@ -711,14 +717,14 @@ checksum = "5fe87ce4529967e0ba1dcf8450bab64d97dfd5010a6256187ffe2e43e6f0e049" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] name = "deranged" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eb30d70a07a3b04884d2677f06bec33509dc67ca60d92949e5535352d3191dc" +checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" dependencies = [ "powerfmt", "serde", @@ -741,7 +747,7 @@ checksum = "2bba3e9872d7c58ce7ef0fcf1844fcc3e23ef2a58377b50df35dd98e42a5726e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", "unicode-xid", ] @@ -765,7 +771,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] @@ -787,9 +793,9 @@ checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" [[package]] name = "duct" -version = "0.13.6" +version = "0.13.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ae3fc31835f74c2a7ceda3aeede378b0ae2e74c8f1c36559fcc9ae2a4e7d3e" +checksum = "e4ab5718d1224b63252cd0c6f74f6480f9ffeb117438a2e0f5cf6d9a4798929c" dependencies = [ "libc", "once_cell", @@ -824,9 +830,9 @@ dependencies = [ [[package]] name = "ed25519-dalek" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0" +checksum = "4a3daa8e81a3963a60642bcc1f90a670680bd4a77535faa384e9d1c79d620871" dependencies = [ "curve25519-dalek", "ed25519", @@ -883,10 +889,30 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", +] + +[[package]] +name = "enumflags2" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3278c9d5fb675e0a51dabcf4c0d355f692b064171535ba72361be1528a9d8e8d" +dependencies = [ + "enumflags2_derive", +] + +[[package]] +name = "enumflags2_derive" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c785274071b1b420972453b306eeca06acf4633829db4223b58a2a8c5953bc4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", ] [[package]] @@ -939,9 +965,9 @@ checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "ff" @@ -955,9 +981,9 @@ dependencies = [ [[package]] name = "fiat-crypto" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7" +checksum = "c007b1ae3abe1cb6f85a16305acd418b7ca6343b953633fee2b76d8f108b830f" [[package]] name = "flume" @@ -988,9 +1014,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -1014,9 +1040,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -1024,15 +1050,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -1041,44 +1067,44 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] name = "futures-sink" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-timer" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e64b03909df88034c26dc1547e8970b91f98bdb65165d6a4e9110d94263dbb2c" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" [[package]] name = "futures-util" -version = "0.3.29" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -1136,9 +1162,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "js-sys", @@ -1161,9 +1187,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "governor" -version = "0.6.0" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "821239e5672ff23e2a7060901fa622950bbd80b649cdaadd78d1c1767ed14eb4" +checksum = "68a7f542ee6b35af73b06abc0dad1c1bae89964e4e253bc4b587b91c9637867b" dependencies = [ "cfg-if", "dashmap", @@ -1172,9 +1198,11 @@ dependencies = [ "no-std-compat", "nonzero_ext", "parking_lot", + "portable-atomic", "quanta", "rand", "smallvec", + "spinning_top", ] [[package]] @@ -1190,16 +1218,16 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.22" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d6250322ef6e60f93f9a2162799302cd6f68f79f6e5d85c8c16f14d1d958178" +checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" dependencies = [ "bytes", "fnv", "futures-core", "futures-sink", "futures-util", - "http 0.2.11", + "http 0.2.12", "indexmap", "slab", "tokio", @@ -1223,11 +1251,17 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "hex" @@ -1291,10 +1325,11 @@ dependencies = [ [[package]] name = "hmac-sha1" -version = "0.1.3" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1333fad8d94b82cab989da428b0b36a3435db3870d85e971a1d6dc0a8576722" +checksum = "6b05da5b9e5d4720bfb691eebb2b9d42da3570745da71eac8a1f5bb7e59aab88" dependencies = [ + "hmac", "sha1", ] @@ -1323,9 +1358,9 @@ checksum = "f558a64ac9af88b5ba400d99b579451af0d39c6d360980045b91aac966d705e2" [[package]] name = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -1334,9 +1369,9 @@ dependencies = [ [[package]] name = "http" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ "bytes", "fnv", @@ -1350,7 +1385,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", - "http 0.2.11", + "http 0.2.12", "pin-project-lite", ] @@ -1361,18 +1396,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" dependencies = [ "bytes", - "http 1.0.0", + "http 1.1.0", ] [[package]] name = "http-body-util" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cb79eb393015dadd30fc252023adb0b2400a0caee0fa2a077e6e21a551e840" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" dependencies = [ "bytes", - "futures-util", - "http 1.0.0", + "futures-core", + "http 1.1.0", "http-body 1.0.0", "pin-project-lite", ] @@ -1400,7 +1435,7 @@ dependencies = [ "futures-core", "futures-util", "h2", - "http 0.2.11", + "http 0.2.12", "http-body 0.4.6", "httparse", "httpdate", @@ -1415,19 +1450,20 @@ dependencies = [ [[package]] name = "hyper" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75" +checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a" dependencies = [ "bytes", "futures-channel", "futures-util", - "http 1.0.0", + "http 1.1.0", "http-body 1.0.0", "httparse", "httpdate", "itoa", "pin-project-lite", + "smallvec", "tokio", "want", ] @@ -1439,7 +1475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", - "http 0.2.11", + "http 0.2.12", "hyper 0.14.28", "rustls", "tokio", @@ -1448,34 +1484,32 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdea9aac0dbe5a9240d68cfd9501e2db94222c6dc06843e06640b9e07f0fdc67" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" dependencies = [ "bytes", - "futures-channel", "futures-util", - "http 1.0.0", + "http 1.1.0", "http-body 1.0.0", - "hyper 1.1.0", + "hyper 1.2.0", "pin-project-lite", "socket2", "tokio", - "tracing", ] [[package]] name = "iana-time-zone" -version = "0.1.58" +version = "0.1.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core 0.51.1", + "windows-core 0.52.0", ] [[package]] @@ -1516,7 +1550,7 @@ dependencies = [ "attohttpc", "bytes", "futures", - "http 0.2.11", + "http 0.2.12", "hyper 0.14.28", "log", "rand", @@ -1527,9 +1561,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown", @@ -1537,9 +1571,9 @@ dependencies = [ [[package]] name = "indicatif" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25" +checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3" dependencies = [ "console", "instant", @@ -1695,7 +1729,7 @@ dependencies = [ "anyhow", "erased_set", "http-body-util", - "hyper 1.1.0", + "hyper 1.2.0", "hyper-util", "once_cell", "prometheus-client", @@ -1729,9 +1763,9 @@ dependencies = [ "hex", "hickory-resolver", "hostname", - "http 1.0.0", + "http 1.1.0", "http-body-util", - "hyper 1.1.0", + "hyper 1.2.0", "hyper-util", "igd", "iroh-base", @@ -1751,7 +1785,7 @@ dependencies = [ "rand_core", "rcgen", "reqwest", - "ring 0.17.7", + "ring 0.17.8", "rtnetlink", "rustls", "rustls-webpki", @@ -1786,9 +1820,9 @@ checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1804,9 +1838,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.151" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libm" @@ -1822,9 +1856,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -1838,9 +1872,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "lru-cache" @@ -1851,15 +1885,6 @@ dependencies = [ "linked-hash-map", ] -[[package]] -name = "mach2" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19b955cdeb2a02b9117f121ce63aa52d08ade45de53e48fe6a38b39c10f6f709" -dependencies = [ - "libc", -] - [[package]] name = "match_cfg" version = "0.1.0" @@ -1889,9 +1914,9 @@ checksum = "df39d232f5c40b0891c10216992c2f250c054105cb1e56f0fc9032db6203ecc1" [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "mime" @@ -1907,18 +1932,18 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -1984,9 +2009,9 @@ dependencies = [ [[package]] name = "netlink-proto" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "842c6770fc4bb33dd902f41829c61ef872b8e38de1405aa0b938b27b8fba12c3" +checksum = "86b33524dc0968bfad349684447bfce6db937a9ac3332a1fe60c0c5a5ce63f21" dependencies = [ "bytes", "futures", @@ -2023,12 +2048,13 @@ dependencies = [ [[package]] name = "nix" -version = "0.27.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053" +checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "cfg-if", + "cfg_aliases", "libc", ] @@ -2098,21 +2124,26 @@ dependencies = [ "zeroize", ] +[[package]] +name = "num-conv" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" + [[package]] name = "num-integer" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" dependencies = [ - "autocfg", "num-traits", ] [[package]] name = "num-iter" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252" +checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9" dependencies = [ "autocfg", "num-integer", @@ -2121,9 +2152,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", "libm", @@ -2141,23 +2172,23 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] @@ -2168,9 +2199,9 @@ checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] @@ -2192,9 +2223,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "opaque-debug" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" [[package]] name = "openssl-probe" @@ -2204,12 +2235,12 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "os_pipe" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ae859aa07428ca9a929b936690f8b12dc5f11dd8c6992a18ca93919f28bc177" +checksum = "57119c3b893986491ec9aa85056780d3a0f3cf4da7cc09dd3650dbd6c6738fb9" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2297,7 +2328,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b13fe415cdf3c8e44518e18a7c95a13431d9bdf6d15367d82b23c377fdd441a" dependencies = [ - "base64", + "base64 0.21.7", "serde", ] @@ -2307,7 +2338,7 @@ version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b8fcc794035347fb64beda2d3b462595dd2753e3f268d89c5aae77e8cf2c310" dependencies = [ - "base64", + "base64 0.21.7", "serde", ] @@ -2328,9 +2359,9 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.5" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae9cee2a55a544be8b89dc6848072af97a20f2422603c10865be2a42b580fff5" +checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" dependencies = [ "memchr", "thiserror", @@ -2339,9 +2370,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.5" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81d78524685f5ef2a3b3bd1cafbc9fcabb036253d9b1463e726a91cd16e2dfc2" +checksum = "b0d24f72393fd16ab6ac5738bc33cdb6a9aa73f8b902e8fe29cf4e67d7dd1026" dependencies = [ "pest", "pest_generator", @@ -2349,22 +2380,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.5" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68bd1206e71118b5356dae5ddc61c8b11e28b09ef6a31acbd15ea48a28e0c227" +checksum = "fdc17e2a6c7d0a492f0158d7a4bd66cc17280308bbaff78d5bef566dca35ab80" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] name = "pest_meta" -version = "2.7.5" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c747191d4ad9e4a4ab9c8798f1e82a39affe7ef9648390b7e5548d18e099de6" +checksum = "934cd7631c050f4674352a6e835d5f6711ffbfb9345c2fc0107155ac495ae293" dependencies = [ "once_cell", "pest", @@ -2373,22 +2404,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.3" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] @@ -2426,45 +2457,45 @@ dependencies = [ [[package]] name = "platforms" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14e6ab3f592e6fb464fc9712d8d6e6912de6473954635fd76a589d832cffcbb0" +checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c" [[package]] name = "pnet_base" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "872e46346144ebf35219ccaa64b1dffacd9c6f188cd7d012bd6977a2a838f42e" +checksum = "fe4cf6fb3ab38b68d01ab2aea03ed3d1132b4868fa4e06285f29f16da01c5f4c" dependencies = [ "no-std-net", ] [[package]] name = "pnet_macros" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a780e80005c2e463ec25a6e9f928630049a10b43945fea83207207d4a7606f4" +checksum = "688b17499eee04a0408aca0aa5cba5fc86401d7216de8a63fdf7a4c227871804" dependencies = [ "proc-macro2", "quote", "regex", - "syn 1.0.109", + "syn 2.0.55", ] [[package]] name = "pnet_macros_support" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d932134f32efd7834eb8b16d42418dac87086347d1bc7d142370ef078582bc" +checksum = "eea925b72f4bd37f8eab0f221bbe4c78b63498350c983ffa9dd4bcde7e030f56" dependencies = [ "pnet_base", ] [[package]] name = "pnet_packet" -version = "0.33.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bde678bbd85cb1c2d99dc9fc596e57f03aa725f84f3168b0eaf33eeccb41706" +checksum = "a9a005825396b7fe7a38a8e288dbc342d5034dac80c15212436424fef8ea90ba" dependencies = [ "glob", "pnet_base", @@ -2580,11 +2611,10 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.1" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97dc5fea232fc28d2f597b37c4876b348a40e33f3b02cc975c8d006d78d94b1a" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_datetime", "toml_edit", ] @@ -2622,18 +2652,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.70" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39278fbbf5fb4f646ce651690877f89d1c5811a3d4acb27700c1cb3cdb78fd3b" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] [[package]] name = "prometheus-client" -version = "0.22.0" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "510c4f1c9d81d556458f94c98f857748130ea9737bbd6053da497503b26ea63c" +checksum = "c1ca959da22a332509f2a73ae9e5f23f9dcfc31fd3a54d71f159495bd5909baa" dependencies = [ "dtoa", "itoa", @@ -2649,18 +2679,17 @@ checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] name = "quanta" -version = "0.11.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17e662a7a8291a865152364c20c7abc5e60486ab2001e8ec10b24862de0b9ab" +checksum = "9ca0b7bac0b97248c40bb77288fc52029cf1459c0461ea1b05ee32ccf011de2c" dependencies = [ "crossbeam-utils", "libc", - "mach2", "once_cell", "raw-cpuid", "wasi", @@ -2724,9 +2753,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -2785,11 +2814,11 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "10.7.0" +version = "11.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c297679cb867470fa8c9f67dbba74a78d78e3e98d7cf2b08d6d71540f797332" +checksum = "9d86a7c4638d42c44551f4791a20e687dbb4c3de1f33c43dd71e355cd429def1" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", ] [[package]] @@ -2824,44 +2853,44 @@ dependencies = [ [[package]] name = "ref-cast" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53313ec9f12686aeeffb43462c3ac77aa25f590a5f630eb2cde0de59417b29c7" +checksum = "c4846d4c50d1721b1a3bef8af76924eef20d5e723647333798c1b519b3a9473f" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2566c4bf6845f2c2e83b27043c3f5dfcd5ba8f2937d6c00dc009bfb51a079dc4" +checksum = "5fddb4f8d99b0a2ebafc65a87a69a7b9875e4b1ae1f00db265d300ef7f28bccc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] name = "reflink-copy" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "767be24c0da52e7448d495b8d162506a9aa125426651d547d545d6c2b4b65b62" +checksum = "52b1349400e2ffd64a9fb5ed9008e33c0b8ef86bd5bae8f73080839c7082f1d5" dependencies = [ "cfg-if", "rustix", - "windows 0.52.0", + "windows 0.54.0", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.3", + "regex-automata 0.4.6", "regex-syntax 0.8.2", ] @@ -2876,9 +2905,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -2905,17 +2934,17 @@ checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.23" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37b1ae8d9ac08420c66222fb9096fc5de435c3c48542bc5336c51892cffafb41" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", "futures-util", "h2", - "http 0.2.11", + "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", "hyper-rustls", @@ -2931,6 +2960,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-rustls", @@ -2980,16 +3010,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if", "getrandom", "libc", "spin 0.9.8", "untrusted 0.9.0", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3063,11 +3094,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.28" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -3081,7 +3112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" dependencies = [ "log", - "ring 0.17.7", + "ring 0.17.8", "rustls-webpki", "sct", ] @@ -3104,7 +3135,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64", + "base64 0.21.7", ] [[package]] @@ -3113,7 +3144,7 @@ version = "0.101.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" dependencies = [ - "ring 0.17.7", + "ring 0.17.8", "untrusted 0.9.0", ] @@ -3125,9 +3156,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "salsa20" @@ -3149,11 +3180,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3168,7 +3199,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.17.7", + "ring 0.17.8", "untrusted 0.9.0", ] @@ -3217,9 +3248,9 @@ checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba" [[package]] name = "semver" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "sendme" @@ -3238,7 +3269,7 @@ dependencies = [ "iroh-bytes", "iroh-io", "iroh-net", - "nix 0.27.1", + "nix 0.28.0", "num_cpus", "rand", "serde_json", @@ -3252,9 +3283,9 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] @@ -3270,29 +3301,29 @@ dependencies = [ [[package]] name = "serde_bytes" -version = "0.11.12" +version = "0.11.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab33ec92f677585af6d88c65593ae2375adde54efdbf16d597f2cbc7a6d368ff" +checksum = "8b8497c313fd43ab992087548117643f6fcd935cbf36f176ffda0aacf9591734" dependencies = [ "serde", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -3323,9 +3354,14 @@ dependencies = [ [[package]] name = "sha1" -version = "0.2.0" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] [[package]] name = "sha2" @@ -3387,21 +3423,21 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" dependencies = [ "serde", ] [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3419,6 +3455,15 @@ dependencies = [ "lock_api", ] +[[package]] +name = "spinning_top" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d96d2d1d716fb500937168cc09353ffdc7a012be8475ac7308e1bdf0e3923300" +dependencies = [ + "lock_api", +] + [[package]] name = "spki" version = "0.7.3" @@ -3452,9 +3497,9 @@ dependencies = [ [[package]] name = "ssh-key" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51901eb883a5b442b506a1f8fa483d143f3bab513fe721e398ec56c77624feb" +checksum = "3b71299a724c8d84956caaf8fc3b3ea57c3587fe2d0b800cd0dc1f3599905d7e" dependencies = [ "ed25519-dalek", "p256", @@ -3473,9 +3518,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01" [[package]] name = "struct_iterable" @@ -3497,7 +3542,7 @@ dependencies = [ "proc-macro2", "quote", "struct_iterable_internal", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] @@ -3521,22 +3566,24 @@ version = "0.25.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23dc1fa9ac9c169a78ba62f0b841814b7abae11bdd047b9c58f893439e309ea0" dependencies = [ - "heck", + "heck 0.4.1", "proc-macro2", "quote", "rustversion", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] name = "stun-rs" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78517bf347f802eba0204cdecf5ff10fb7056c914a3b2d9f2011f231cb1438b5" +checksum = "0adebf9fb8fba5c39ee34092b0383f247e4d1255b98fcffec94b4b797b85b677" dependencies = [ + "base64 0.22.0", "bounded-integer", "byteorder", "crc", + "enumflags2", "fallible-iterator", "hmac-sha1", "hmac-sha256", @@ -3558,9 +3605,9 @@ checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" [[package]] name = "surge-ping" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af341b2be485d647b5dc4cfb2da99efac35b5c95748a08fb7233480fedc5ead3" +checksum = "efbf95ce4c7c5b311d2ce3f088af2b93edef0f09727fa50fbe03c7a979afce77" dependencies = [ "hex", "parking_lot", @@ -3585,9 +3632,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.42" +version = "2.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b7d0a2c048d661a1a59fcd7355baa232f7ed34e0ee4df2eef3c1c1c0d3852d8" +checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" dependencies = [ "proc-macro2", "quote", @@ -3605,6 +3652,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "synstructure" version = "0.12.6" @@ -3640,42 +3693,41 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", - "redox_syscall", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "thiserror" -version = "1.0.51" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f11c217e1416d6f036b870f14e0413d480dbf28edbee1f877abaf0206af43bb7" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.51" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01742297787513b79cf8e29d1056ede1313e2420b7b3b15d0a768b4921f549df" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if", "once_cell", @@ -3683,12 +3735,13 @@ dependencies = [ [[package]] name = "time" -version = "0.3.31" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e" +checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749" dependencies = [ "deranged", "itoa", + "num-conv", "powerfmt", "serde", "time-core", @@ -3703,10 +3756,11 @@ checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f" +checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774" dependencies = [ + "num-conv", "time-core", ] @@ -3727,9 +3781,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.35.1" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", @@ -3752,7 +3806,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] @@ -3772,7 +3826,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dfb6f50b5523d014ba161512c37457acb16fd8218c883c7152e0a67ab763f2d4" dependencies = [ "async-trait", - "base64", + "base64 0.21.7", "chrono", "futures", "log", @@ -3809,15 +3863,15 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" [[package]] name = "toml_edit" -version = "0.20.2" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap", "toml_datetime", @@ -3850,7 +3904,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] @@ -3925,9 +3979,9 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-parse" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212c59636157b18c2f57eed2799e6606c52fc49c6a11685ffb0d08f06e55f428" +checksum = "c06ff81122fcbf4df4c1660b15f7e3336058e7aec14437c9f85c6b31a0f279b9" dependencies = [ "regex-lite", ] @@ -3940,9 +3994,9 @@ checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "unicode-bidi" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f2528f27a9eb2b21e69c95319b30bd0efd85d09c379741b0f78ea1d86be2416" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -3952,9 +4006,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -4025,9 +4079,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -4050,9 +4104,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -4060,24 +4114,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -4087,9 +4141,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -4097,22 +4151,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "watchable" @@ -4128,9 +4182,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -4138,9 +4192,9 @@ dependencies = [ [[package]] name = "webpki-roots" -version = "0.25.3" +version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1778a42e8b3b90bff8d0f5032bf22250792889a5cdc752aa0020c84abe3aaf10" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "widestring" @@ -4191,8 +4245,6 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-implement", - "windows-interface", "windows-targets 0.48.5", ] @@ -4213,7 +4265,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ "windows-core 0.52.0", - "windows-targets 0.52.0", + "windows-implement", + "windows-interface", + "windows-targets 0.52.4", +] + +[[package]] +name = "windows" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +dependencies = [ + "windows-core 0.54.0", + "windows-targets 0.52.4", ] [[package]] @@ -4231,38 +4295,48 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.4", +] + +[[package]] +name = "windows-core" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +dependencies = [ + "windows-result", + "windows-targets 0.52.4", ] [[package]] name = "windows-implement" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e2ee588991b9e7e6c8338edf3333fbe4da35dc72092643958ebb43f0ab2c49c" +checksum = "12168c33176773b86799be25e2a2ba07c7aab9968b37541f1094dbd7a60c8946" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.55", ] [[package]] name = "windows-interface" -version = "0.48.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6fb8df20c9bcaa8ad6ab513f7b40104840c8867d5751126e4df3b08388d0cc7" +checksum = "9d8dc32e0095a7eeccebd0e3f09e9509365ecb3fc6ac4d6f5f14a3f6392942d1" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.55", ] [[package]] -name = "windows-sys" -version = "0.45.0" +name = "windows-result" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "cd19df78e5168dfb0aedc343d1d1b8d422ab2db6756d2dc3fef75035402a3f64" dependencies = [ - "windows-targets 0.42.2", + "windows-targets 0.52.4", ] [[package]] @@ -4280,22 +4354,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets 0.52.4", ] [[package]] @@ -4315,25 +4374,19 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.5" @@ -4342,15 +4395,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -4360,15 +4407,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -4378,15 +4419,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -4396,15 +4431,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -4414,15 +4443,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -4432,15 +4455,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -4450,15 +4467,15 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" [[package]] name = "winnow" -version = "0.5.30" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ "memchr", ] @@ -4475,16 +4492,16 @@ dependencies = [ [[package]] name = "wmi" -version = "0.13.1" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ced703d10188571ce53582c2932ce640ed3c413cff7ee6e2d961f9abdb6a63d1" +checksum = "fc2f0a4062ca522aad4705a2948fd4061b3857537990202a8ddd5af21607f79a" dependencies = [ "chrono", "futures", "log", "serde", "thiserror", - "windows 0.48.0", + "windows 0.52.0", ] [[package]] @@ -4545,7 +4562,7 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.42", + "syn 2.0.55", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 450ce6d..bd2e48c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,7 @@ walkdir = "2.4.0" [dev-dependencies] duct = "0.13.6" -nix = { version = "0.27", features = ["signal", "process"] } +nix = { version = "0.28", features = ["signal", "process"] } rand = "0.8.5" serde_json = "1.0.108" tempfile = "3.8.1" From e40a7b50243104a4d51964fcd717ca2fb81034e6 Mon Sep 17 00:00:00 2001 From: b5 Date: Wed, 27 Mar 2024 00:17:42 -0400 Subject: [PATCH 3/5] feat: ios sendme POC --- .../sendme/sendme.xcodeproj/project.pbxproj | 674 ++++++++++++++++++ .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../xcshareddata/swiftpm/Package.resolved | 15 + .../UserInterfaceState.xcuserstate | Bin 0 -> 41051 bytes .../xcschemes/xcschememanagement.plist | 14 + .../AccentColor.colorset/Contents.json | 11 + .../AppIcon.appiconset/Contents.json | 13 + .../sendme/Assets.xcassets/Contents.json | 6 + ui/ios/sendme/sendme/ContentView.swift | 31 + ui/ios/sendme/sendme/DocumentPicker.swift | 41 ++ ui/ios/sendme/sendme/Node.swift | 174 +++++ .../Preview Assets.xcassets/Contents.json | 6 + ui/ios/sendme/sendme/Receive.swift | 118 +++ ui/ios/sendme/sendme/Send.swift | 73 ++ ui/ios/sendme/sendme/ShareSheet.swift | 28 + ui/ios/sendme/sendme/sendmeApp.swift | 22 + ui/ios/sendme/sendmeTests/sendmeTests.swift | 36 + .../sendme/sendmeUITests/sendmeUITests.swift | 41 ++ .../sendmeUITestsLaunchTests.swift | 32 + 20 files changed, 1350 insertions(+) create mode 100644 ui/ios/sendme/sendme.xcodeproj/project.pbxproj create mode 100644 ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/contents.xcworkspacedata create mode 100644 ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved create mode 100644 ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcuserdata/b5.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 ui/ios/sendme/sendme.xcodeproj/xcuserdata/b5.xcuserdatad/xcschemes/xcschememanagement.plist create mode 100644 ui/ios/sendme/sendme/Assets.xcassets/AccentColor.colorset/Contents.json create mode 100644 ui/ios/sendme/sendme/Assets.xcassets/AppIcon.appiconset/Contents.json create mode 100644 ui/ios/sendme/sendme/Assets.xcassets/Contents.json create mode 100644 ui/ios/sendme/sendme/ContentView.swift create mode 100644 ui/ios/sendme/sendme/DocumentPicker.swift create mode 100644 ui/ios/sendme/sendme/Node.swift create mode 100644 ui/ios/sendme/sendme/Preview Content/Preview Assets.xcassets/Contents.json create mode 100644 ui/ios/sendme/sendme/Receive.swift create mode 100644 ui/ios/sendme/sendme/Send.swift create mode 100644 ui/ios/sendme/sendme/ShareSheet.swift create mode 100644 ui/ios/sendme/sendme/sendmeApp.swift create mode 100644 ui/ios/sendme/sendmeTests/sendmeTests.swift create mode 100644 ui/ios/sendme/sendmeUITests/sendmeUITests.swift create mode 100644 ui/ios/sendme/sendmeUITests/sendmeUITestsLaunchTests.swift diff --git a/ui/ios/sendme/sendme.xcodeproj/project.pbxproj b/ui/ios/sendme/sendme.xcodeproj/project.pbxproj new file mode 100644 index 0000000..fce3465 --- /dev/null +++ b/ui/ios/sendme/sendme.xcodeproj/project.pbxproj @@ -0,0 +1,674 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 60; + objects = { + +/* Begin PBXBuildFile section */ + 4235A9C32BB306190013D818 /* sendmeApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4235A9C22BB306190013D818 /* sendmeApp.swift */; }; + 4235A9C52BB306190013D818 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4235A9C42BB306190013D818 /* ContentView.swift */; }; + 4235A9C72BB3061A0013D818 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4235A9C62BB3061A0013D818 /* Assets.xcassets */; }; + 4235A9CA2BB3061A0013D818 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4235A9C92BB3061A0013D818 /* Preview Assets.xcassets */; }; + 4235A9D42BB3061A0013D818 /* sendmeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4235A9D32BB3061A0013D818 /* sendmeTests.swift */; }; + 4235A9DE2BB3061A0013D818 /* sendmeUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4235A9DD2BB3061A0013D818 /* sendmeUITests.swift */; }; + 4235A9E02BB3061A0013D818 /* sendmeUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4235A9DF2BB3061A0013D818 /* sendmeUITestsLaunchTests.swift */; }; + 4235A9EF2BB307250013D818 /* SystemConfiguration.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4235A9EE2BB307250013D818 /* SystemConfiguration.framework */; }; + 42C61F5F2BB307EC00762786 /* IrohLib in Frameworks */ = {isa = PBXBuildFile; productRef = 42C61F5E2BB307EC00762786 /* IrohLib */; }; + 42C61F612BB3084300762786 /* Node.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C61F602BB3084300762786 /* Node.swift */; }; + 42C61F662BB3A82A00762786 /* Receive.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C61F652BB3A82A00762786 /* Receive.swift */; }; + 42C61F682BB3A8A400762786 /* CodeScanner in Frameworks */ = {isa = PBXBuildFile; productRef = 42C61F672BB3A8A400762786 /* CodeScanner */; }; + 42C61F6A2BB3BB2400762786 /* Send.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C61F692BB3BB2400762786 /* Send.swift */; }; + 42C61F6C2BB3BEC200762786 /* DocumentPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C61F6B2BB3BEC200762786 /* DocumentPicker.swift */; }; + 42C61F6E2BB3CEC500762786 /* ShareSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C61F6D2BB3CEC500762786 /* ShareSheet.swift */; }; +/* End PBXBuildFile section */ + +/* Begin PBXContainerItemProxy section */ + 4235A9D02BB3061A0013D818 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4235A9B72BB306190013D818 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4235A9BE2BB306190013D818; + remoteInfo = sendme; + }; + 4235A9DA2BB3061A0013D818 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 4235A9B72BB306190013D818 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 4235A9BE2BB306190013D818; + remoteInfo = sendme; + }; +/* End PBXContainerItemProxy section */ + +/* Begin PBXFileReference section */ + 4235A9BF2BB306190013D818 /* sendme.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = sendme.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 4235A9C22BB306190013D818 /* sendmeApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = sendmeApp.swift; sourceTree = ""; }; + 4235A9C42BB306190013D818 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; }; + 4235A9C62BB3061A0013D818 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; + 4235A9C92BB3061A0013D818 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; }; + 4235A9CF2BB3061A0013D818 /* sendmeTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = sendmeTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 4235A9D32BB3061A0013D818 /* sendmeTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = sendmeTests.swift; sourceTree = ""; }; + 4235A9D92BB3061A0013D818 /* sendmeUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = sendmeUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 4235A9DD2BB3061A0013D818 /* sendmeUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = sendmeUITests.swift; sourceTree = ""; }; + 4235A9DF2BB3061A0013D818 /* sendmeUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = sendmeUITestsLaunchTests.swift; sourceTree = ""; }; + 4235A9EE2BB307250013D818 /* SystemConfiguration.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SystemConfiguration.framework; path = System/Library/Frameworks/SystemConfiguration.framework; sourceTree = SDKROOT; }; + 42C61F602BB3084300762786 /* Node.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Node.swift; sourceTree = ""; }; + 42C61F652BB3A82A00762786 /* Receive.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Receive.swift; sourceTree = ""; }; + 42C61F692BB3BB2400762786 /* Send.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Send.swift; sourceTree = ""; }; + 42C61F6B2BB3BEC200762786 /* DocumentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPicker.swift; sourceTree = ""; }; + 42C61F6D2BB3CEC500762786 /* ShareSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareSheet.swift; sourceTree = ""; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 4235A9BC2BB306190013D818 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 42C61F5F2BB307EC00762786 /* IrohLib in Frameworks */, + 4235A9EF2BB307250013D818 /* SystemConfiguration.framework in Frameworks */, + 42C61F682BB3A8A400762786 /* CodeScanner in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4235A9CC2BB3061A0013D818 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4235A9D62BB3061A0013D818 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 4235A9B62BB306190013D818 = { + isa = PBXGroup; + children = ( + 4235A9C12BB306190013D818 /* sendme */, + 4235A9D22BB3061A0013D818 /* sendmeTests */, + 4235A9DC2BB3061A0013D818 /* sendmeUITests */, + 4235A9C02BB306190013D818 /* Products */, + 4235A9ED2BB307250013D818 /* Frameworks */, + ); + sourceTree = ""; + }; + 4235A9C02BB306190013D818 /* Products */ = { + isa = PBXGroup; + children = ( + 4235A9BF2BB306190013D818 /* sendme.app */, + 4235A9CF2BB3061A0013D818 /* sendmeTests.xctest */, + 4235A9D92BB3061A0013D818 /* sendmeUITests.xctest */, + ); + name = Products; + sourceTree = ""; + }; + 4235A9C12BB306190013D818 /* sendme */ = { + isa = PBXGroup; + children = ( + 4235A9C22BB306190013D818 /* sendmeApp.swift */, + 4235A9C42BB306190013D818 /* ContentView.swift */, + 42C61F692BB3BB2400762786 /* Send.swift */, + 4235A9C62BB3061A0013D818 /* Assets.xcassets */, + 4235A9C82BB3061A0013D818 /* Preview Content */, + 42C61F602BB3084300762786 /* Node.swift */, + 42C61F652BB3A82A00762786 /* Receive.swift */, + 42C61F6B2BB3BEC200762786 /* DocumentPicker.swift */, + 42C61F6D2BB3CEC500762786 /* ShareSheet.swift */, + ); + path = sendme; + sourceTree = ""; + }; + 4235A9C82BB3061A0013D818 /* Preview Content */ = { + isa = PBXGroup; + children = ( + 4235A9C92BB3061A0013D818 /* Preview Assets.xcassets */, + ); + path = "Preview Content"; + sourceTree = ""; + }; + 4235A9D22BB3061A0013D818 /* sendmeTests */ = { + isa = PBXGroup; + children = ( + 4235A9D32BB3061A0013D818 /* sendmeTests.swift */, + ); + path = sendmeTests; + sourceTree = ""; + }; + 4235A9DC2BB3061A0013D818 /* sendmeUITests */ = { + isa = PBXGroup; + children = ( + 4235A9DD2BB3061A0013D818 /* sendmeUITests.swift */, + 4235A9DF2BB3061A0013D818 /* sendmeUITestsLaunchTests.swift */, + ); + path = sendmeUITests; + sourceTree = ""; + }; + 4235A9ED2BB307250013D818 /* Frameworks */ = { + isa = PBXGroup; + children = ( + 4235A9EE2BB307250013D818 /* SystemConfiguration.framework */, + ); + name = Frameworks; + sourceTree = ""; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 4235A9BE2BB306190013D818 /* sendme */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4235A9E32BB3061A0013D818 /* Build configuration list for PBXNativeTarget "sendme" */; + buildPhases = ( + 4235A9BB2BB306190013D818 /* Sources */, + 4235A9BC2BB306190013D818 /* Frameworks */, + 4235A9BD2BB306190013D818 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = sendme; + packageProductDependencies = ( + 42C61F5E2BB307EC00762786 /* IrohLib */, + 42C61F672BB3A8A400762786 /* CodeScanner */, + ); + productName = sendme; + productReference = 4235A9BF2BB306190013D818 /* sendme.app */; + productType = "com.apple.product-type.application"; + }; + 4235A9CE2BB3061A0013D818 /* sendmeTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4235A9E62BB3061A0013D818 /* Build configuration list for PBXNativeTarget "sendmeTests" */; + buildPhases = ( + 4235A9CB2BB3061A0013D818 /* Sources */, + 4235A9CC2BB3061A0013D818 /* Frameworks */, + 4235A9CD2BB3061A0013D818 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4235A9D12BB3061A0013D818 /* PBXTargetDependency */, + ); + name = sendmeTests; + productName = sendmeTests; + productReference = 4235A9CF2BB3061A0013D818 /* sendmeTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; + 4235A9D82BB3061A0013D818 /* sendmeUITests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 4235A9E92BB3061A0013D818 /* Build configuration list for PBXNativeTarget "sendmeUITests" */; + buildPhases = ( + 4235A9D52BB3061A0013D818 /* Sources */, + 4235A9D62BB3061A0013D818 /* Frameworks */, + 4235A9D72BB3061A0013D818 /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 4235A9DB2BB3061A0013D818 /* PBXTargetDependency */, + ); + name = sendmeUITests; + productName = sendmeUITests; + productReference = 4235A9D92BB3061A0013D818 /* sendmeUITests.xctest */; + productType = "com.apple.product-type.bundle.ui-testing"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 4235A9B72BB306190013D818 /* Project object */ = { + isa = PBXProject; + attributes = { + BuildIndependentTargetsInParallel = 1; + LastSwiftUpdateCheck = 1530; + LastUpgradeCheck = 1530; + TargetAttributes = { + 4235A9BE2BB306190013D818 = { + CreatedOnToolsVersion = 15.3; + }; + 4235A9CE2BB3061A0013D818 = { + CreatedOnToolsVersion = 15.3; + TestTargetID = 4235A9BE2BB306190013D818; + }; + 4235A9D82BB3061A0013D818 = { + CreatedOnToolsVersion = 15.3; + TestTargetID = 4235A9BE2BB306190013D818; + }; + }; + }; + buildConfigurationList = 4235A9BA2BB306190013D818 /* Build configuration list for PBXProject "sendme" */; + compatibilityVersion = "Xcode 14.0"; + developmentRegion = en; + hasScannedForEncodings = 0; + knownRegions = ( + en, + Base, + ); + mainGroup = 4235A9B62BB306190013D818; + packageReferences = ( + 4235A9EC2BB307170013D818 /* XCLocalSwiftPackageReference "../../../../iroh-ffi/IrohLib" */, + 42C61F642BB3A7AA00762786 /* XCRemoteSwiftPackageReference "CodeScanner" */, + ); + productRefGroup = 4235A9C02BB306190013D818 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 4235A9BE2BB306190013D818 /* sendme */, + 4235A9CE2BB3061A0013D818 /* sendmeTests */, + 4235A9D82BB3061A0013D818 /* sendmeUITests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 4235A9BD2BB306190013D818 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4235A9CA2BB3061A0013D818 /* Preview Assets.xcassets in Resources */, + 4235A9C72BB3061A0013D818 /* Assets.xcassets in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4235A9CD2BB3061A0013D818 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4235A9D72BB3061A0013D818 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 4235A9BB2BB306190013D818 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 42C61F612BB3084300762786 /* Node.swift in Sources */, + 42C61F6A2BB3BB2400762786 /* Send.swift in Sources */, + 4235A9C52BB306190013D818 /* ContentView.swift in Sources */, + 42C61F662BB3A82A00762786 /* Receive.swift in Sources */, + 4235A9C32BB306190013D818 /* sendmeApp.swift in Sources */, + 42C61F6C2BB3BEC200762786 /* DocumentPicker.swift in Sources */, + 42C61F6E2BB3CEC500762786 /* ShareSheet.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4235A9CB2BB3061A0013D818 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4235A9D42BB3061A0013D818 /* sendmeTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + 4235A9D52BB3061A0013D818 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 4235A9E02BB3061A0013D818 /* sendmeUITestsLaunchTests.swift in Sources */, + 4235A9DE2BB3061A0013D818 /* sendmeUITests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin PBXTargetDependency section */ + 4235A9D12BB3061A0013D818 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4235A9BE2BB306190013D818 /* sendme */; + targetProxy = 4235A9D02BB3061A0013D818 /* PBXContainerItemProxy */; + }; + 4235A9DB2BB3061A0013D818 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 4235A9BE2BB306190013D818 /* sendme */; + targetProxy = 4235A9DA2BB3061A0013D818 /* PBXContainerItemProxy */; + }; +/* End PBXTargetDependency section */ + +/* Begin XCBuildConfiguration section */ + 4235A9E12BB3061A0013D818 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = dwarf; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_DYNAMIC_NO_PIC = NO; + GCC_NO_COMMON_BLOCKS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; + MTL_FAST_MATH = YES; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; + SWIFT_OPTIMIZATION_LEVEL = "-Onone"; + }; + name = Debug; + }; + 4235A9E22BB3061A0013D818 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_NONNULL = YES; + CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; + CLANG_ENABLE_MODULES = YES; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_ENABLE_OBJC_WEAK = YES; + CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_COMMA = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_DOCUMENTATION_COMMENTS = YES; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; + CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; + CLANG_WARN_STRICT_PROTOTYPES = YES; + CLANG_WARN_SUSPICIOUS_MOVE = YES; + CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; + CLANG_WARN_UNREACHABLE_CODE = YES; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; + GCC_C_LANGUAGE_STANDARD = gnu17; + GCC_NO_COMMON_BLOCKS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; + LOCALIZATION_PREFERS_STRING_CATALOGS = YES; + MTL_ENABLE_DEBUG_INFO = NO; + MTL_FAST_MATH = YES; + SDKROOT = iphoneos; + SWIFT_COMPILATION_MODE = wholemodule; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + 4235A9E42BB3061A0013D818 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"sendme/Preview Content\""; + DEVELOPMENT_TEAM = 7K8LD2955M; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSCameraUsageDescription = "Used to scan QR codes!"; + INFOPLIST_KEY_NSDocumentsFolderUsageDescription = "for sending files"; + INFOPLIST_KEY_NSFileProviderDomainUsageDescription = wat; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "computer.iroh.sendme-ui.sendme"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Debug; + }; + 4235A9E52BB3061A0013D818 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_ASSET_PATHS = "\"sendme/Preview Content\""; + DEVELOPMENT_TEAM = 7K8LD2955M; + ENABLE_PREVIEWS = YES; + GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_NSCameraUsageDescription = "Used to scan QR codes!"; + INFOPLIST_KEY_NSDocumentsFolderUsageDescription = "for sending files"; + INFOPLIST_KEY_NSFileProviderDomainUsageDescription = wat; + INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES; + INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES; + INFOPLIST_KEY_UILaunchScreen_Generation = YES; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/Frameworks", + ); + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "computer.iroh.sendme-ui.sendme"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = YES; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + }; + name = Release; + }; + 4235A9E72BB3061A0013D818 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 7K8LD2955M; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "computer.iroh.sendme-ui.sendmeTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/sendme.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/sendme"; + }; + name = Debug; + }; + 4235A9E82BB3061A0013D818 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + BUNDLE_LOADER = "$(TEST_HOST)"; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 7K8LD2955M; + GENERATE_INFOPLIST_FILE = YES; + IPHONEOS_DEPLOYMENT_TARGET = 17.4; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "computer.iroh.sendme-ui.sendmeTests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_HOST = "$(BUILT_PRODUCTS_DIR)/sendme.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/sendme"; + }; + name = Release; + }; + 4235A9EA2BB3061A0013D818 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 7K8LD2955M; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "computer.iroh.sendme-ui.sendmeUITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = sendme; + }; + name = Debug; + }; + 4235A9EB2BB3061A0013D818 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; + CODE_SIGN_STYLE = Automatic; + CURRENT_PROJECT_VERSION = 1; + DEVELOPMENT_TEAM = 7K8LD2955M; + GENERATE_INFOPLIST_FILE = YES; + MARKETING_VERSION = 1.0; + PRODUCT_BUNDLE_IDENTIFIER = "computer.iroh.sendme-ui.sendmeUITests"; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_EMIT_LOC_STRINGS = NO; + SWIFT_VERSION = 5.0; + TARGETED_DEVICE_FAMILY = "1,2"; + TEST_TARGET_NAME = sendme; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 4235A9BA2BB306190013D818 /* Build configuration list for PBXProject "sendme" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4235A9E12BB3061A0013D818 /* Debug */, + 4235A9E22BB3061A0013D818 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4235A9E32BB3061A0013D818 /* Build configuration list for PBXNativeTarget "sendme" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4235A9E42BB3061A0013D818 /* Debug */, + 4235A9E52BB3061A0013D818 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4235A9E62BB3061A0013D818 /* Build configuration list for PBXNativeTarget "sendmeTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4235A9E72BB3061A0013D818 /* Debug */, + 4235A9E82BB3061A0013D818 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + 4235A9E92BB3061A0013D818 /* Build configuration list for PBXNativeTarget "sendmeUITests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 4235A9EA2BB3061A0013D818 /* Debug */, + 4235A9EB2BB3061A0013D818 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + +/* Begin XCLocalSwiftPackageReference section */ + 4235A9EC2BB307170013D818 /* XCLocalSwiftPackageReference "../../../../iroh-ffi/IrohLib" */ = { + isa = XCLocalSwiftPackageReference; + relativePath = "../../../../iroh-ffi/IrohLib"; + }; +/* End XCLocalSwiftPackageReference section */ + +/* Begin XCRemoteSwiftPackageReference section */ + 42C61F642BB3A7AA00762786 /* XCRemoteSwiftPackageReference "CodeScanner" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/twostraws/CodeScanner"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 2.4.0; + }; + }; +/* End XCRemoteSwiftPackageReference section */ + +/* Begin XCSwiftPackageProductDependency section */ + 42C61F5E2BB307EC00762786 /* IrohLib */ = { + isa = XCSwiftPackageProductDependency; + package = 4235A9EC2BB307170013D818 /* XCLocalSwiftPackageReference "../../../../iroh-ffi/IrohLib" */; + productName = IrohLib; + }; + 42C61F672BB3A8A400762786 /* CodeScanner */ = { + isa = XCSwiftPackageProductDependency; + package = 42C61F642BB3A7AA00762786 /* XCRemoteSwiftPackageReference "CodeScanner" */; + productName = CodeScanner; + }; +/* End XCSwiftPackageProductDependency section */ + }; + rootObject = 4235A9B72BB306190013D818 /* Project object */; +} diff --git a/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved new file mode 100644 index 0000000..d6a1552 --- /dev/null +++ b/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -0,0 +1,15 @@ +{ + "originHash" : "19143d4db0ea9e94de64cd39414304eb87f8b90781d40db6519be71a4bdf0418", + "pins" : [ + { + "identity" : "codescanner", + "kind" : "remoteSourceControl", + "location" : "https://github.com/twostraws/CodeScanner", + "state" : { + "revision" : "303bd5adbb61d068c3bcbb839857340c3e6ff8b0", + "version" : "2.4.0" + } + } + ], + "version" : 3 +} diff --git a/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcuserdata/b5.xcuserdatad/UserInterfaceState.xcuserstate b/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcuserdata/b5.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..b2723066a7a2649342c39df48caddd3498628c44 GIT binary patch literal 41051 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

A}k%U9<#~N=);%rS)oKRz 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 NuAb*g^gME${{g{PPeK3y literal 0 HcmV?d00001 diff --git a/ui/ios/sendme/sendme.xcodeproj/xcuserdata/b5.xcuserdatad/xcschemes/xcschememanagement.plist b/ui/ios/sendme/sendme.xcodeproj/xcuserdata/b5.xcuserdatad/xcschemes/xcschememanagement.plist new file mode 100644 index 0000000..201aeb1 --- /dev/null +++ b/ui/ios/sendme/sendme.xcodeproj/xcuserdata/b5.xcuserdatad/xcschemes/xcschememanagement.plist @@ -0,0 +1,14 @@ + + + + + SchemeUserState + + sendme.xcscheme_^#shared#^_ + + orderHint + 0 + + + + diff --git a/ui/ios/sendme/sendme/Assets.xcassets/AccentColor.colorset/Contents.json b/ui/ios/sendme/sendme/Assets.xcassets/AccentColor.colorset/Contents.json new file mode 100644 index 0000000..eb87897 --- /dev/null +++ b/ui/ios/sendme/sendme/Assets.xcassets/AccentColor.colorset/Contents.json @@ -0,0 +1,11 @@ +{ + "colors" : [ + { + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ui/ios/sendme/sendme/Assets.xcassets/AppIcon.appiconset/Contents.json b/ui/ios/sendme/sendme/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 0000000..13613e3 --- /dev/null +++ b/ui/ios/sendme/sendme/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,13 @@ +{ + "images" : [ + { + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ui/ios/sendme/sendme/Assets.xcassets/Contents.json b/ui/ios/sendme/sendme/Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/ui/ios/sendme/sendme/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ui/ios/sendme/sendme/ContentView.swift b/ui/ios/sendme/sendme/ContentView.swift new file mode 100644 index 0000000..a544a1d --- /dev/null +++ b/ui/ios/sendme/sendme/ContentView.swift @@ -0,0 +1,31 @@ +// +// ContentView.swift +// sendme +// +// Created by Brendan O'Brien on 3/26/24. +// + +import SwiftUI + +struct ContentView: View { + var body: some View { + TabView { + Send() + .tabItem { + Label("Send", systemImage: "terminal") + } + Receive() + .tabItem { + Label("Receive", systemImage: "macpro.gen2.fill") + } + } + } +} + +#Preview { + ContentView() + .environmentObject(IrohNodeManager.shared) + .onAppear() { + IrohNodeManager.shared.start() + } +} diff --git a/ui/ios/sendme/sendme/DocumentPicker.swift b/ui/ios/sendme/sendme/DocumentPicker.swift new file mode 100644 index 0000000..da26698 --- /dev/null +++ b/ui/ios/sendme/sendme/DocumentPicker.swift @@ -0,0 +1,41 @@ +// +// DocumentPicker.swift +// sendme +// +// Created by Brendan O'Brien on 3/26/24. +// + +import UniformTypeIdentifiers +import SwiftUI +import UIKit + +struct DocumentPicker: UIViewControllerRepresentable { + var onPick: ([URL]) -> Void + + func makeUIViewController(context: Context) -> UIDocumentPickerViewController { + let picker = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.text, UTType.image, UTType.pdf, UTType.zip], asCopy: true) + picker.allowsMultipleSelection = false + picker.delegate = context.coordinator + return picker + } + + func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) { + // Update logic if needed + } + + func makeCoordinator() -> Coordinator { + Coordinator(self) + } + + class Coordinator: NSObject, UIDocumentPickerDelegate { + var parent: DocumentPicker + + init(_ documentPicker: DocumentPicker) { + self.parent = documentPicker + } + + func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { + parent.onPick(urls) + } + } +} diff --git a/ui/ios/sendme/sendme/Node.swift b/ui/ios/sendme/sendme/Node.swift new file mode 100644 index 0000000..7eaecc4 --- /dev/null +++ b/ui/ios/sendme/sendme/Node.swift @@ -0,0 +1,174 @@ +// +// IrohNodeManager.swift +// iroh +// +// Created by Brendan O'Brien on 8/8/23. +// + +import SwiftUI +import IrohLib +import Foundation + +class IrohNodeManager: ObservableObject { + static let shared = IrohNodeManager() + + @Published var node: IrohNode? + @Published var nodeID: String = "" + @Published var author: AuthorId? + @Published var nodeStats: [String : CounterStats]? + @Published var connections: [ConnectionInfoIdentifiable]? + @Published var connectionHistories: [String: [ConnHistory]] = [:] + + + private var timer: Timer? + + func start() { +// IrohLib.setLogLevel(level: .debug) + do { + try IrohLib.startMetricsCollection() + let path = self.irohPath() + print(path.absoluteString) + self.node = try IrohNode(path: path.path) + nodeID = node?.nodeId() ?? "" + startConnectionMonitoring() + startStatsMonitoring() + initAuthor() + print("created iroh node with node Id \(nodeID)") + } catch { + print("error creating iroh node \(error)") + } + } + + // TODO: using a single author for now. At some point we should add support for author selection + private func initAuthor() { + do { + self.author = try self.node?.authorCreate() + } catch { + print("couldn't create author \(error)") + return + } + } + + + private func startConnectionMonitoring() { + updateConnections() + DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { + self.startConnectionMonitoring() + } + } + + private func updateConnections() { + guard let node = node else { + print("Error: no node") + return + } + + do { + let connections = try node.connections() + + DispatchQueue.global(qos: .userInteractive).async { + let mapped = connections.map { (conn) -> ConnectionInfoIdentifiable in + let nodeId = conn.nodeId.toString() + let item = ConnHistory( + id: .now, + latency: conn.latency != nil ? conn.latency! * 1000 : 0, + connType: conn.connType) + + DispatchQueue.main.async { + if self.connectionHistories[nodeId] != nil { + self.connectionHistories[nodeId]?.append(item) + } else { + self.connectionHistories[nodeId] = [item] + } + + if self.connectionHistories[nodeId]?.count ?? 0 >= 300 { + let _ = self.connectionHistories[nodeId]!.popLast() + } + } + + return ConnectionInfoIdentifiable( + id: nodeId, + latency: conn.latency != nil ? conn.latency! * 1000 : nil, + connType: conn.connType) + } + + DispatchQueue.main.async { + self.connections = mapped + } + } + } catch { + print("error fetching connections") + } + } + + private func startStatsMonitoring() { + timer = Timer.scheduledTimer(withTimeInterval: 3, repeats: true) { _ in + do { + if let latest = try self.node?.stats() { + + DispatchQueue.main.async { + self.nodeStats = latest + } + + } + } catch (let error) { + print("error \(error)") + self.timer?.invalidate() + self.timer = nil + } + } + } + + private func irohPath() -> URL { + let paths = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask) + let irohPath = paths[0].appendingPathComponent("iroh") + mkdirP(path: irohPath.path) + return irohPath + } +} + +struct IrohNodeManagerEnvironmentKey: EnvironmentKey { + static var defaultValue: IrohNodeManager = IrohNodeManager.shared +} + +extension EnvironmentValues { + var irohNodeManager: IrohNodeManager { + get { self[IrohNodeManagerEnvironmentKey.self] } + set { self[IrohNodeManagerEnvironmentKey.self] = newValue } + } +} + +struct ConnectionInfoIdentifiable: Identifiable, Equatable { + var id: String + var latency: Double? + var connType: ConnectionType + + static func == (lhs: ConnectionInfoIdentifiable, rhs: ConnectionInfoIdentifiable) -> Bool { + lhs.id == rhs.id + } + + func latencyString() -> String { + if let latency = latency { + return String(format:"%.1f", latency) + } + return "?" + } +} + +struct ConnHistory: Identifiable { + var id: Date + var latency: Double + var connType: ConnectionType +} + +func mkdirP(path: String) { + let fileManager = FileManager.default + + do { + try fileManager.createDirectory(atPath: path, + withIntermediateDirectories: true, + attributes: nil) + } catch { + print("Error creating directory: \(error)") + } +} diff --git a/ui/ios/sendme/sendme/Preview Content/Preview Assets.xcassets/Contents.json b/ui/ios/sendme/sendme/Preview Content/Preview Assets.xcassets/Contents.json new file mode 100644 index 0000000..73c0059 --- /dev/null +++ b/ui/ios/sendme/sendme/Preview Content/Preview Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/ui/ios/sendme/sendme/Receive.swift b/ui/ios/sendme/sendme/Receive.swift new file mode 100644 index 0000000..d26df81 --- /dev/null +++ b/ui/ios/sendme/sendme/Receive.swift @@ -0,0 +1,118 @@ +// +// Receive.swift +// sendme +// +// Created by Brendan O'Brien on 3/26/24. +// + +import Foundation +import SwiftUI +import IrohLib +import CodeScanner + +struct Receive: View { + @EnvironmentObject var nodeManager: IrohNodeManager + @State private var ticketString: String = "" + @State private var showingQRScanner: Bool = false + + var scannerSheet: some View { + CodeScannerView( + codeTypes: [.qr], + completion: { result in + if case let .success(code) = result { + self.ticketString = code.string + self.showingQRScanner = false + } + }) + } + + var body: some View { + VStack(spacing: 5) { + VStack { + Text("Receive") + .font(Font.custom("Space Mono", size: 32)) + .foregroundColor(.primary) + .frame(maxWidth: .infinity, alignment: .leading) + Text("choose a document to get started") + .font(Font.custom("Space Mono", size: 14)) + .foregroundColor(.secondary) + .frame(maxWidth: .infinity, alignment: .leading) + }.padding(EdgeInsets(top: 0, leading: 20, bottom: 10, trailing: 20)) + + + HStack{ + TextField("Paste Ticket", text: $ticketString, axis: .vertical) + .textFieldStyle(.roundedBorder) + .padding() + + Button("Download") { + do { + let node = self.nodeManager.node! + let cb = DownloadProgressManager() + try node.blobsDownloadTicket(ticket: ticketString, cb: cb) + } catch { + print("unknown error occurred") + } + } + + Button { + showingQRScanner = true + } label: { + Image(systemName: "qrcode.viewfinder") + } + .sheet(isPresented: $showingQRScanner) { + self.scannerSheet + } + } + } + } +} + +class DownloadProgressManager: DownloadCallback { + func progress(progress: DownloadProgress) throws { + print("progress: \(progress)") +// switch p.type() { +// case .foundLocal: +// <#code#> +// case .connected: +// <#code#> +// case .found: +// <#code#> +// case .foundHashSeq: +// <#code#> +// case .progress: +// <#code#> +// case .done: +// <#code#> +// case .allDone: +// <#code#> +// case .abort: +// <#code#> +// } + } +} + +func saveFileToDocumentsDirectory(fileName: String, data: Data) { + // Get the URL for the document directory + let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + + // Create the full file URL + let fileURL = documentsDirectoryURL.appendingPathComponent(fileName) + + do { + // Write the data to the file + try data.write(to: fileURL) + print("File saved: \(fileURL.absoluteString)") + } catch { + // Handle any errors + print("Error saving file: \(error)") + } +} + +#Preview { + Receive() + .environmentObject(IrohNodeManager.shared) + .onAppear() { + IrohNodeManager.shared.start() + } +} diff --git a/ui/ios/sendme/sendme/Send.swift b/ui/ios/sendme/sendme/Send.swift new file mode 100644 index 0000000..36f6e0c --- /dev/null +++ b/ui/ios/sendme/sendme/Send.swift @@ -0,0 +1,73 @@ +// +// Send.swift +// sendme +// +// Created by Brendan O'Brien on 3/26/24. +// + +import Foundation +import SwiftUI + +struct Send: View { + @EnvironmentObject var nodeManager: IrohNodeManager + @State private var documentURLs: [URL] = [] + @State private var ticket: String = "" + @State private var showingDocumentPicker: Bool = false + @State private var showingShareSheet: Bool = false + + var body: some View { + VStack { + Button("Pick a Document") { + showingDocumentPicker = true + } + } + .sheet(isPresented: $showingDocumentPicker) { + DocumentPicker { urls in + self.documentURLs = urls + + do { + let node = self.nodeManager.node! + let bytes = readFileContents(at: documentURLs.first!) + + node.blobs + let res = try node.blobsAddBytes(bytes: bytes!) + ticket = try node.blobsShare(hash: res.hash, blobFormat: res.format) + print("generated blob ticket: \(ticket)") + self.showingDocumentPicker = false + + // Delay the presentation of the share sheet to let self.ticket change propagate + DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) { + self.showingShareSheet = true + } + } catch { + print("sharing blob failed") + } + } + } + .sheet(isPresented: $showingShareSheet) { + ShareSheet(items: [self.ticket]) + } + .padding() + } +} + +func readFileContents(at url: URL) -> Data? { + do { + // Attempt to read the file contents into a Data object + let data = try Data(contentsOf: url) + return data + } catch { + // If an error occurs, print it and return nil + print("Error reading file: \(error)") + return nil + } +} + + +#Preview { + Send() + .environmentObject(IrohNodeManager.shared) + .onAppear() { + IrohNodeManager.shared.start() + } +} diff --git a/ui/ios/sendme/sendme/ShareSheet.swift b/ui/ios/sendme/sendme/ShareSheet.swift new file mode 100644 index 0000000..6b2de5d --- /dev/null +++ b/ui/ios/sendme/sendme/ShareSheet.swift @@ -0,0 +1,28 @@ +// +// ShareSheet.swift +// sendme +// +// Created by Brendan O'Brien on 3/26/24. +// + +import SwiftUI +import UIKit + +struct ShareSheet: UIViewControllerRepresentable { + var items: [Any] + + func makeUIViewController(context: Context) -> UIActivityViewController { + print("sharing items \(items)") + let activityViewController = UIActivityViewController(activityItems: items, applicationActivities: nil) + return activityViewController + } + + func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) { + // No need to update the view controller in this case. + } +} + +#Preview { + ShareSheet(items: ["Hello, World!"]) +} + diff --git a/ui/ios/sendme/sendme/sendmeApp.swift b/ui/ios/sendme/sendme/sendmeApp.swift new file mode 100644 index 0000000..f27d285 --- /dev/null +++ b/ui/ios/sendme/sendme/sendmeApp.swift @@ -0,0 +1,22 @@ +// +// sendmeApp.swift +// sendme +// +// Created by Brendan O'Brien on 3/26/24. +// + +import SwiftUI + +@main +struct sendmeApp: App { + @StateObject private var irohNodeManager = IrohNodeManager.shared + var body: some Scene { + WindowGroup { + ContentView() + .environmentObject(irohNodeManager) + .onAppear() { + irohNodeManager.start() + } + } + } +} diff --git a/ui/ios/sendme/sendmeTests/sendmeTests.swift b/ui/ios/sendme/sendmeTests/sendmeTests.swift new file mode 100644 index 0000000..fd964e0 --- /dev/null +++ b/ui/ios/sendme/sendmeTests/sendmeTests.swift @@ -0,0 +1,36 @@ +// +// sendmeTests.swift +// sendmeTests +// +// Created by Brendan O'Brien on 3/26/24. +// + +import XCTest +@testable import sendme + +final class sendmeTests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // This is an example of a functional test case. + // Use XCTAssert and related functions to verify your tests produce the correct results. + // Any test you write for XCTest can be annotated as throws and async. + // Mark your test throws to produce an unexpected failure when your test encounters an uncaught error. + // Mark your test async to allow awaiting for asynchronous code to complete. Check the results with assertions afterwards. + } + + func testPerformanceExample() throws { + // This is an example of a performance test case. + self.measure { + // Put the code you want to measure the time of here. + } + } + +} diff --git a/ui/ios/sendme/sendmeUITests/sendmeUITests.swift b/ui/ios/sendme/sendmeUITests/sendmeUITests.swift new file mode 100644 index 0000000..8f4853d --- /dev/null +++ b/ui/ios/sendme/sendmeUITests/sendmeUITests.swift @@ -0,0 +1,41 @@ +// +// sendmeUITests.swift +// sendmeUITests +// +// Created by Brendan O'Brien on 3/26/24. +// + +import XCTest + +final class sendmeUITests: XCTestCase { + + override func setUpWithError() throws { + // Put setup code here. This method is called before the invocation of each test method in the class. + + // In UI tests it is usually best to stop immediately when a failure occurs. + continueAfterFailure = false + + // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. + } + + override func tearDownWithError() throws { + // Put teardown code here. This method is called after the invocation of each test method in the class. + } + + func testExample() throws { + // UI tests must launch the application that they test. + let app = XCUIApplication() + app.launch() + + // Use XCTAssert and related functions to verify your tests produce the correct results. + } + + func testLaunchPerformance() throws { + if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { + // This measures how long it takes to launch your application. + measure(metrics: [XCTApplicationLaunchMetric()]) { + XCUIApplication().launch() + } + } + } +} diff --git a/ui/ios/sendme/sendmeUITests/sendmeUITestsLaunchTests.swift b/ui/ios/sendme/sendmeUITests/sendmeUITestsLaunchTests.swift new file mode 100644 index 0000000..60dba41 --- /dev/null +++ b/ui/ios/sendme/sendmeUITests/sendmeUITestsLaunchTests.swift @@ -0,0 +1,32 @@ +// +// sendmeUITestsLaunchTests.swift +// sendmeUITests +// +// Created by Brendan O'Brien on 3/26/24. +// + +import XCTest + +final class sendmeUITestsLaunchTests: XCTestCase { + + override class var runsForEachTargetApplicationUIConfiguration: Bool { + true + } + + override func setUpWithError() throws { + continueAfterFailure = false + } + + func testLaunch() throws { + let app = XCUIApplication() + app.launch() + + // Insert steps here to perform after app launch but before taking a screenshot, + // such as logging into a test account or navigating somewhere in the app + + let attachment = XCTAttachment(screenshot: app.screenshot()) + attachment.name = "Launch Screen" + attachment.lifetime = .keepAlways + add(attachment) + } +} From 21ee9677e37bfe7d0a103a49fb69ee76c27eeeb4 Mon Sep 17 00:00:00 2001 From: b5 Date: Wed, 27 Mar 2024 16:44:43 -0400 Subject: [PATCH 4/5] feat: basic send and receive working on iOS --- .gitignore | 90 ++++++++++++ .../sendme/sendme.xcodeproj/project.pbxproj | 6 + .../UserInterfaceState.xcuserstate | Bin 41051 -> 51271 bytes ui/ios/sendme/sendme/AppError.swift | 38 +++++ ui/ios/sendme/sendme/ContentView.swift | 8 +- ui/ios/sendme/sendme/DocumentPicker.swift | 2 +- ui/ios/sendme/sendme/Node.swift | 41 ++++-- ui/ios/sendme/sendme/Receive.swift | 139 ++++++++++++------ ui/ios/sendme/sendme/Send.swift | 35 ++++- ui/ios/sendme/sendme/sendmeApp.swift | 2 +- 10 files changed, 294 insertions(+), 67 deletions(-) create mode 100644 ui/ios/sendme/sendme/AppError.swift diff --git a/.gitignore b/.gitignore index 2bc7d63..a859c04 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,93 @@ /target tmp/* .sendme-* + + +# Xcode + +## Build generated +build/ +DerivedData/ + +## Various settings +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +xcuserdata/ +*.xccheckout +*.moved-aside +*.xcscmblueprint + +## Obj-C/Swift specific +*.hmap +*.ipa +*.dSYM.zip +*.dSYM + +## Playgrounds +timeline +playground.xcworkspace + +# Swift Package Manager +.build/ + +# CocoaPods +## Reference: https://www.gitignore.io/api/cocoapods +# CocoaPods - Objective-C/Swift dependency manager +# +# We recommend against adding the Pods directory to your .gitignore. However +# you should judge for yourself, the pros and cons are mentioned at: +# https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# +# Pods/ + +# Carthage +Carthage/Build + +# fastlane +## It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the +## screenshots whenever they are needed. +## For more information about the recommended setup visit: +## https://docs.fastlane.tools/best-practices/source-control/ +# +# fastlane/report.xml +# fastlane/Preview.html +# fastlane/screenshots +# fastlane/test_output + +# Code Injection +injectionforxcode/ + +# User Interface State +*.userstate + +# Apple Watch +*.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk diff --git a/ui/ios/sendme/sendme.xcodeproj/project.pbxproj b/ui/ios/sendme/sendme.xcodeproj/project.pbxproj index fce3465..7dedeb6 100644 --- a/ui/ios/sendme/sendme.xcodeproj/project.pbxproj +++ b/ui/ios/sendme/sendme.xcodeproj/project.pbxproj @@ -22,6 +22,7 @@ 42C61F6A2BB3BB2400762786 /* Send.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C61F692BB3BB2400762786 /* Send.swift */; }; 42C61F6C2BB3BEC200762786 /* DocumentPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C61F6B2BB3BEC200762786 /* DocumentPicker.swift */; }; 42C61F6E2BB3CEC500762786 /* ShareSheet.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C61F6D2BB3CEC500762786 /* ShareSheet.swift */; }; + 42C808FA2BB4948300114DC5 /* AppError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 42C808F92BB4948300114DC5 /* AppError.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -58,6 +59,7 @@ 42C61F692BB3BB2400762786 /* Send.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Send.swift; sourceTree = ""; }; 42C61F6B2BB3BEC200762786 /* DocumentPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DocumentPicker.swift; sourceTree = ""; }; 42C61F6D2BB3CEC500762786 /* ShareSheet.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShareSheet.swift; sourceTree = ""; }; + 42C808F92BB4948300114DC5 /* AppError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppError.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -121,6 +123,7 @@ 42C61F652BB3A82A00762786 /* Receive.swift */, 42C61F6B2BB3BEC200762786 /* DocumentPicker.swift */, 42C61F6D2BB3CEC500762786 /* ShareSheet.swift */, + 42C808F92BB4948300114DC5 /* AppError.swift */, ); path = sendme; sourceTree = ""; @@ -300,6 +303,7 @@ 42C61F6A2BB3BB2400762786 /* Send.swift in Sources */, 4235A9C52BB306190013D818 /* ContentView.swift in Sources */, 42C61F662BB3A82A00762786 /* Receive.swift in Sources */, + 42C808FA2BB4948300114DC5 /* AppError.swift in Sources */, 4235A9C32BB306190013D818 /* sendmeApp.swift in Sources */, 42C61F6C2BB3BEC200762786 /* DocumentPicker.swift in Sources */, 42C61F6E2BB3CEC500762786 /* ShareSheet.swift in Sources */, @@ -477,6 +481,7 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportsDocumentBrowser = YES; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -509,6 +514,7 @@ INFOPLIST_KEY_UILaunchScreen_Generation = YES; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight"; + INFOPLIST_KEY_UISupportsDocumentBrowser = YES; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcuserdata/b5.xcuserdatad/UserInterfaceState.xcuserstate b/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcuserdata/b5.xcuserdatad/UserInterfaceState.xcuserstate index b2723066a7a2649342c39df48caddd3498628c44..22375300b13334d10fc7b8443f8e751dca712237 100644 GIT binary patch literal 51271 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�Bv{e2@a925CTAkP);Av>D_8xj?^zZh>xt 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 literal 41051 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

A}k%U9<#~N=);%rS)oKRz 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 NuAb*g^gME${{g{PPeK3y diff --git a/ui/ios/sendme/sendme/AppError.swift b/ui/ios/sendme/sendme/AppError.swift new file mode 100644 index 0000000..2fa0168 --- /dev/null +++ b/ui/ios/sendme/sendme/AppError.swift @@ -0,0 +1,38 @@ +// +// AppError.swift +// sendme +// +// Created by Brendan O'Brien on 3/27/24. +// + +import Foundation + + +enum AppError: Error, Identifiable { + var id: String { localizedDescription } + + case invalidTicket(String) + case downloadFailed(String) +} + +extension AppError: LocalizedError { + var errorDescription: String? { + switch self { + case .invalidTicket(let error): + return NSLocalizedString(error, comment: "") + case .downloadFailed(let error): + return NSLocalizedString(error, comment: "") + } + } +} + +extension AppError { + var title: String { + switch self { + case .invalidTicket(_): + return NSLocalizedString("Invalid Ticket", comment: "") + case .downloadFailed(_): + return NSLocalizedString("Download Failed", comment: "") + } + } +} diff --git a/ui/ios/sendme/sendme/ContentView.swift b/ui/ios/sendme/sendme/ContentView.swift index a544a1d..de6844f 100644 --- a/ui/ios/sendme/sendme/ContentView.swift +++ b/ui/ios/sendme/sendme/ContentView.swift @@ -10,14 +10,14 @@ import SwiftUI struct ContentView: View { var body: some View { TabView { - Send() - .tabItem { - Label("Send", systemImage: "terminal") - } Receive() .tabItem { Label("Receive", systemImage: "macpro.gen2.fill") } + Send() + .tabItem { + Label("Send", systemImage: "terminal") + } } } } diff --git a/ui/ios/sendme/sendme/DocumentPicker.swift b/ui/ios/sendme/sendme/DocumentPicker.swift index da26698..a70300a 100644 --- a/ui/ios/sendme/sendme/DocumentPicker.swift +++ b/ui/ios/sendme/sendme/DocumentPicker.swift @@ -14,7 +14,7 @@ struct DocumentPicker: UIViewControllerRepresentable { func makeUIViewController(context: Context) -> UIDocumentPickerViewController { let picker = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.text, UTType.image, UTType.pdf, UTType.zip], asCopy: true) - picker.allowsMultipleSelection = false + picker.allowsMultipleSelection = true picker.delegate = context.coordinator return picker } diff --git a/ui/ios/sendme/sendme/Node.swift b/ui/ios/sendme/sendme/Node.swift index 7eaecc4..ffdb20d 100644 --- a/ui/ios/sendme/sendme/Node.swift +++ b/ui/ios/sendme/sendme/Node.swift @@ -13,7 +13,6 @@ class IrohNodeManager: ObservableObject { static let shared = IrohNodeManager() @Published var node: IrohNode? - @Published var nodeID: String = "" @Published var author: AuthorId? @Published var nodeStats: [String : CounterStats]? @Published var connections: [ConnectionInfoIdentifiable]? @@ -23,19 +22,33 @@ class IrohNodeManager: ObservableObject { private var timer: Timer? func start() { -// IrohLib.setLogLevel(level: .debug) - do { - try IrohLib.startMetricsCollection() - let path = self.irohPath() - print(path.absoluteString) - self.node = try IrohNode(path: path.path) - nodeID = node?.nodeId() ?? "" - startConnectionMonitoring() - startStatsMonitoring() - initAuthor() - print("created iroh node with node Id \(nodeID)") - } catch { - print("error creating iroh node \(error)") + Task { + let newNode = await self.startInner() + await MainActor.run { + self.node = newNode + startConnectionMonitoring() + startStatsMonitoring() + initAuthor() + } + } + } + + func startInner() async -> IrohNode? { + await withCheckedContinuation { continuation in + DispatchQueue.global(qos: .background).async { + // IrohLib.setLogLevel(level: .debug) + var node: IrohNode? + do { + try IrohLib.startMetricsCollection() + let path = self.irohPath() + print(path.absoluteString) + node = try IrohNode(path: path.path) + print("created iroh node with node Id \(node!.nodeId())") + } catch { + print("error creating iroh node \(error)") + } + continuation.resume(returning: node) + } } } diff --git a/ui/ios/sendme/sendme/Receive.swift b/ui/ios/sendme/sendme/Receive.swift index d26df81..37135a8 100644 --- a/ui/ios/sendme/sendme/Receive.swift +++ b/ui/ios/sendme/sendme/Receive.swift @@ -10,85 +10,142 @@ import SwiftUI import IrohLib import CodeScanner +enum ReceiveStep { + case configuring + case downloading + case finished +} + struct Receive: View { @EnvironmentObject var nodeManager: IrohNodeManager + @State private var step: ReceiveStep = .configuring + @State private var currentError: AppError? @State private var ticketString: String = "" @State private var showingQRScanner: Bool = false + private var progressManager: DownloadProgressManager = DownloadProgressManager() - var scannerSheet: some View { - CodeScannerView( - codeTypes: [.qr], - completion: { result in - if case let .success(code) = result { - self.ticketString = code.string - self.showingQRScanner = false - } - }) + var body: some View { + stepView } - var body: some View { - VStack(spacing: 5) { + private var stepView: some View { + switch step { + case .configuring: + return AnyView(self.configure()) + case .downloading: + return AnyView(self.downloading()) + case .finished: + return AnyView(self.finished()) + } + } + + private func configure() -> any View { + return AnyView(VStack(spacing: 5) { VStack { Text("Receive") .font(Font.custom("Space Mono", size: 32)) .foregroundColor(.primary) .frame(maxWidth: .infinity, alignment: .leading) - Text("choose a document to get started") + Text("download to your device") .font(Font.custom("Space Mono", size: 14)) .foregroundColor(.secondary) .frame(maxWidth: .infinity, alignment: .leading) }.padding(EdgeInsets(top: 0, leading: 20, bottom: 10, trailing: 20)) - - HStack{ + + VStack{ TextField("Paste Ticket", text: $ticketString, axis: .vertical) .textFieldStyle(.roundedBorder) .padding() - + Button("Download") { - do { - let node = self.nodeManager.node! - let cb = DownloadProgressManager() - try node.blobsDownloadTicket(ticket: ticketString, cb: cb) - } catch { - print("unknown error occurred") + step = .downloading + DispatchQueue.global(qos: .userInteractive).async { + defer { + step = .finished + } + + do { + let node = self.nodeManager.node! + + let ticket = try BlobTicket(ticket: ticketString) + if ticket.format() == BlobFormat.raw { + currentError = .invalidTicket("this is a 'raw' file ticket that links to data without a filename. sendme needs 'collection'-type tickets") + return + } + + try node.blobsDownload(req: ticket.asDownloadRequest(), cb: progressManager) + let blobs = try node.blobsGetCollection(hash: ticket.hash()).blobs() + for blob in blobs { + let data = try node.blobsReadToBytes(hash: blob.link) + saveFileToDocumentsDirectory(fileName: blob.name, data: data) + } + } catch let error { + currentError = .downloadFailed(error.localizedDescription) + } } } - + Button { showingQRScanner = true } label: { Image(systemName: "qrcode.viewfinder") } .sheet(isPresented: $showingQRScanner) { - self.scannerSheet + CodeScannerView( + codeTypes: [.qr], + completion: { result in + if case let .success(code) = result { + self.ticketString = code.string + self.showingQRScanner = false + } + }) + } + .alert(item: $currentError) { error in + Alert(title: Text(error.title), message: Text(error.localizedDescription), dismissButton: .default(Text("OK"))) } } - } + }) + } + + private func downloading() -> any View { + return AnyView(VStack { + Text("Downloading") + }.padding()) + } + + private func finished() -> any View { + return AnyView(VStack{ + Text("Done!") + Button("ok") { + self.ticketString = "" + step = .configuring + } + }.padding()) } } class DownloadProgressManager: DownloadCallback { + func progress(progress: DownloadProgress) throws { - print("progress: \(progress)") -// switch p.type() { + switch progress.type() { // case .foundLocal: -// <#code#> -// case .connected: -// <#code#> -// case .found: -// <#code#> +// debugPrint("found local: \(progress.asFound())") + case .found: + debugPrint("found: \(progress.asFound())") // case .foundHashSeq: -// <#code#> -// case .progress: -// <#code#> -// case .done: -// <#code#> -// case .allDone: -// <#code#> -// case .abort: -// <#code#> -// } +// debugPrint("found HashSeq: \(progress.asFound())") + case .progress: + debugPrint("progress: \(progress.asProgress())") + case .done: + debugPrint("found done: \(progress.asDone())") + case .allDone: + debugPrint("allDone: \(progress)") + case .abort: + debugPrint("abort: \(progress.asAbort())") + default: + debugPrint("unknown progress event: \(progress)") + } } } diff --git a/ui/ios/sendme/sendme/Send.swift b/ui/ios/sendme/sendme/Send.swift index 36f6e0c..6e91a86 100644 --- a/ui/ios/sendme/sendme/Send.swift +++ b/ui/ios/sendme/sendme/Send.swift @@ -7,6 +7,7 @@ import Foundation import SwiftUI +import IrohLib struct Send: View { @EnvironmentObject var nodeManager: IrohNodeManager @@ -16,7 +17,17 @@ struct Send: View { @State private var showingShareSheet: Bool = false var body: some View { - VStack { + VStack(spacing: 5) { + VStack { + Text("Send") + .font(Font.custom("Space Mono", size: 32)) + .foregroundColor(.primary) + .frame(maxWidth: .infinity, alignment: .leading) + Text("share file(s)") + .font(Font.custom("Space Mono", size: 14)) + .foregroundColor(.secondary) + .frame(maxWidth: .infinity, alignment: .leading) + }.padding(EdgeInsets(top: 0, leading: 20, bottom: 10, trailing: 20)) Button("Pick a Document") { showingDocumentPicker = true } @@ -27,12 +38,24 @@ struct Send: View { do { let node = self.nodeManager.node! - let bytes = readFileContents(at: documentURLs.first!) - node.blobs - let res = try node.blobsAddBytes(bytes: bytes!) - ticket = try node.blobsShare(hash: res.hash, blobFormat: res.format) - print("generated blob ticket: \(ticket)") + let collection = Collection() + var tagsToDelete: [String] = [] + for url in urls { + let bytes = readFileContents(at: documentURLs.first!) + let res = try node.blobsAddBytes(bytes: bytes!) + + try collection.push(name: url.lastPathComponent, hash: res.hash) + + if let tag = String(data: res.tag, encoding: .utf8) { + tagsToDelete.append(tag) + } + } + print("created collection \(collection)") + + let res = try node.blobsCreateCollection(collection: collection, tag: SetTagOption.auto(), tagsToDelete: tagsToDelete) + ticket = try node.blobsShare(hash: res.hash, blobFormat: BlobFormat.hashSeq) + print("generated collection ticket: \(ticket)") self.showingDocumentPicker = false // Delay the presentation of the share sheet to let self.ticket change propagate diff --git a/ui/ios/sendme/sendme/sendmeApp.swift b/ui/ios/sendme/sendme/sendmeApp.swift index f27d285..0160011 100644 --- a/ui/ios/sendme/sendme/sendmeApp.swift +++ b/ui/ios/sendme/sendme/sendmeApp.swift @@ -15,7 +15,7 @@ struct sendmeApp: App { ContentView() .environmentObject(irohNodeManager) .onAppear() { - irohNodeManager.start() + irohNodeManager.start() } } } From 4edcfc4e96f75b0160fceb5449e63deb2c25feef Mon Sep 17 00:00:00 2001 From: b5 Date: Wed, 27 Mar 2024 21:25:54 -0400 Subject: [PATCH 5/5] feat(ios): 'take me to files' after successful downlaod --- .../sendme/sendme.xcodeproj/project.pbxproj | 2 + .../UserInterfaceState.xcuserstate | Bin 51271 -> 39185 bytes ui/ios/sendme/sendme/Receive.swift | 50 ++++++++++++------ 3 files changed, 37 insertions(+), 15 deletions(-) diff --git a/ui/ios/sendme/sendme.xcodeproj/project.pbxproj b/ui/ios/sendme/sendme.xcodeproj/project.pbxproj index 7dedeb6..7c78237 100644 --- a/ui/ios/sendme/sendme.xcodeproj/project.pbxproj +++ b/ui/ios/sendme/sendme.xcodeproj/project.pbxproj @@ -473,6 +473,7 @@ DEVELOPMENT_TEAM = 7K8LD2955M; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES; INFOPLIST_KEY_NSCameraUsageDescription = "Used to scan QR codes!"; INFOPLIST_KEY_NSDocumentsFolderUsageDescription = "for sending files"; INFOPLIST_KEY_NSFileProviderDomainUsageDescription = wat; @@ -506,6 +507,7 @@ DEVELOPMENT_TEAM = 7K8LD2955M; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; + INFOPLIST_KEY_LSSupportsOpeningDocumentsInPlace = YES; INFOPLIST_KEY_NSCameraUsageDescription = "Used to scan QR codes!"; INFOPLIST_KEY_NSDocumentsFolderUsageDescription = "for sending files"; INFOPLIST_KEY_NSFileProviderDomainUsageDescription = wat; diff --git a/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcuserdata/b5.xcuserdatad/UserInterfaceState.xcuserstate b/ui/ios/sendme/sendme.xcodeproj/project.xcworkspace/xcuserdata/b5.xcuserdatad/UserInterfaceState.xcuserstate index 22375300b13334d10fc7b8443f8e751dca712237..b83356feb4f5d2b5081d345a8eb79f83b79f797e 100644 GIT binary patch delta 18243 zcmb8VcU)A*_ddQew_i|}x>PAkvCy$A9RcaRBW;)7I|%L_jJ><|4p=ev-Zi$E*fknk zY%!V`qtQfDEWf$CV9Yz8?;k(*b?+`SbLXD(Jm;J_Q%=t&=4^+vvmxO)$TK^{;5CCCQ_pb(US zDp0KgHJ}zWg2`YCm0kz!31)%CU;VVB5pWco1?RvO za0A=~x4>QS5IhD?z%SrAcm>{oKfpT(U@zDk>Om>ghgPr;w1zg&7TUw1a2Om8N5GNL z8~Q+B=m&$LDg;KrB$y0SU@A<5=}-ytVF4_J<*)+Q!f{Xq1vnK>gVW(`xEXGNTj4gi z9qxcT;V!rv?ty#ZKDZwqfM3G%@B+LHufgl^7Q7Ab!SCTC_#^xY{sN!FSMWFZ2mBMh zgYOAlq8HJd&?BUTK4GRJtcX5@9pOm05}t$?F@zXOL=cfg6cJ6t5V1rY5l}F;yiJa_>QUSsb$nE zs-0Rxt);rCjnr}K1a*=+MV+R;q|Q)ZQD0MMsdLmN>Rajtb)R}bJ*1veKU2@C7t~+W z-_%>`9SvxTrs>|a9_>W;rTfwS=>fDe?LxcKZnQh?K@Xxw(%$qaI+zZjqv;qrmQJTL z=uCPHolEDd=mNTsuB5BzDfCo&8aUT(X;6}^jum^FQiw{Yw30LdU`v(gWgH+ zqW95<=#%s*`ZRrkzDPfzf24n+pVB|m&*)$1=kyEuSNbLWntn&WXK03DSVqd|GX{($ zW5x7gtQk4u#PntQF&>O36UKxyst6{MiDIIe7$%m9W8#?vCWXmj3YbEsh^b*}nL4JP zX=cVT6PZcOWM(!qhuOe%F&mlBnN7@QW(%{G*~V;Vb})OG!^|n>H1j2MnYqGTWxio< zFn5?o%n!_C<~j3%Wm%5pSshlF?Zx(H^;jvZ&l<2MD%Oha!#c7~Y+u%$^^N4%PGTpsQ&=@SkDbphV3)8f z*tP6Bc0Id+?P9mHJJ_$;v+OzcJbQt?$X;SEvsc)w>^JNU_8xnm{gM5NRXt^2vA?mu zvmZDK2RO*l9M2hWhTH(onRDS>IXBLo^WZ!=FK!?=h#SWFasJ$BE{qH361gNUnM>g^ zxNNSFE8>c|YOaQx#!csDa5K4C+-z zo#ws_;LdQDxXawP+zsv~_Z{~=_k?@Nz2bi3e&_z?KJbudd0k%0oAVaDC2z&s@N(Xf z_u+kcKi;1Y-~;&}^_(iB;e0e7$B*H&_-sCh&*k%Y1+U~w_&UCxZ{QpGCVo8s89#xa z!q4EB^DFq3{3^a3l<*z=8nr3s4TbaS6t3RPQDQH#mGqa`3%!Kif*$_#5_ANq&`bT8 zOV=|S9W*Mrs9aIekWf)knyZfC7pnt!Gb=VrYT@Ex<8I?I$ivfS*dTZO^W#5iJDtd0 z*+Pz>5R^gz?yp$gqH~`K5>kaU!BxG*#7y0)tE+ycYp?dfzgOwT?vVBB1jBn7n3!AI z*g5vU%&?qpLS;^EVJd#NvN5!%ytaeaNvctnE6SAV+OGsK=7T<)zW)mPgX8mW6r z4eWE&jf?f965N5IaR+adsco7#TH6?2mYJG;Y^;wPFB^!PTIjd)m#z9(f2=XUHM1_` z8e9Dip1&-&clcQ4gsT?Lz*SEDI(fctmQ*jMT3KJDY_JKeD6dtP*Gh@Y1DsuSdnD?e zqfR;f%FF-c&2dJ*x<667N*&?Uz3L?Cun~f!O)^QcM6yA$U9wZMPjXQ5mE^4ClH_~I zE6G~`00CHF0r~?kJg|-cejpwXrX`>fkDU{Dd?lR*DbEFlYAjLD)KDD_`WLVqChd}of`7Z@vJjvtwcsw}zOPBguaeiIN-r@sze#=ga~VTD9?*cvh>DM_tIf$RRmLl8J8=ms znV1+AkN-*a7~+|muN>s=ep$p2=m6bSLZbG;-av26#|QnZt8pg$yB67_(ZUkYs>9l6346 zeS|E*NO1!2lsoea+O_)=eXy+^!y&0Km92i_9r4s1Rng+if7J;p3DCkVtyoHv3|AQ*&zP%s*Vfp8E3 zB0&_07D|Ltp-d=)mK?`{~s7Q~BA1!)+42}aGpi(mN(}J|tzaBb39Z67K_v(R657@R1lquOe4l{h-*|!f zOqhrrZD>|*b26R?YMM@=CeCXs$ZT{UsNF4^XOV-SyWD$C{m4x zc2H4XEq0=u>L&Fp8_P&RqWR3yzH=|wmnAjAJ~v8HR9jIUT2zDYO=1@vV83MI|D#U( z>_KoyJty3Z1cxOP@efn=sc=J6a149_j$_GAfRo@9I1Ro8XTVpIN9ugrVx48eJYl8K zA*eBGw`_;Rfb(EwC%6DEf=j}DVX?48n05tR1>fMuuYv2}+qBUN97v1uiA= z!a`wDW}GrlSyZodt!XIAua(kTac+Y<>dAK2L-@)rNaUhGYtu87r5ZZ-RS<->(OG*9JN9B6P z;7{;ZI_@^Os8lJMc_;WAyj6cMcOb!g@Il?n-UUe1BkWyO+Q1GWWN!ht)lTYf6MNzcvXEOQ~^11%;YlX%RV16?L_d6$)%4#$vp! zEG^R11Sxat3jC{;Io)0Z4WLYXjUhCG#?VCAAQ*KC8->qT<3RohnoAsU5Kj^|sV`Uv zgP0B7h#LARoEtM7j_6cg+}M#C84fN)Sa)CuDx z_Ao&>jAc5aK5IET2WG(R|1`>xIKn*P7#NF9iQa@Esz03(OQm*dW4o$B-x`NQDQ%$}V^a z9)?HYQFsh~0guBI@FYAX+!5{x4}|Z9N5W&_N8zdPOn8nB2A+}V!LPs$cov?+!>DU+ zPK^==c-LxWDfX;-B@S12h3~SY{u)>GlpEV$gqQG8ofsF<0WV4>e%iq|n#T9Dq$9<~ zHc{BbwL#+3MmIH$9%e}cH9g*QHFWwY0(h#aT>feMhnk`vvZNz$dk^fcyy2(SPc+p} z)H8>UGWysLe5NV=saq2D5pUg3Dqm_Uf6kHyXe2lkU|{^ulW#PYzhvnXP!58#ZS0z~L`q$JbYXfs?b4n`;)GHF2)RhUY1G~+LFd&R^)<76y^8OH> zcMv9oO!!Oq8{64GtPz$PiT=bA4OVYS)Jq_&37daeBOxd3|6Slj;5?>-=u7ky-U%N% zhyeta3Xi_V|L)mC)AM^R_g?DorP6l?j0nJChZs(bAVw12 zgb(3M_!0gHKm-T`NCYSZXapDpSOmEBL?97Fj3R=G5F(TqO@tx9BcOwTE&{y}=#79L z0)_|}shyWCGb9oLu}X;349`T0=C}IRGIu$VNsRfodO1WMjuS*K0@8Lufq=f+b-9@d zQAiZ6Lcl;fT(Lw+hnRG#V^=t+h;pLh-(6G_WB-3C(n7QndkVJG4YjGMybP}tHH3(QEV1s~dC$WxLPi#QI4uSp%3{Wo-re_jc zaMna@ML;f0yGrc9;C&$w&m6y`>aF6`^ zi9@1+9Uu-O;D~@z2XR=mfxbel`ZLs*Bu)~i)LW4)O`Ima#2jozHtILXiX^@wzE+#I z*^DAC5LfZYM_hy_iOa+l1YCq?2)H5Ov6}dXxJFzjzD2+bfn)?45LobUv%RCWOxGRb z+Wv$FA6=Jtpe=XbF=c`$@k#k(ZMo-;bCdssO5!KtcZqWs@s#+Pct-p}JSScdzY;Hr zSHy1!3`AfM0)r74g1}G&h9NKvY|n5HocQVLeCCiO`Jd>J9&hX8gRd=C(&>Bodhb){3f z@g>bkD~U-5X+c^d5QM;}4zdr4DGf#-Onq$h=wi~IbP^jlkXV8c1VTHYIoVIxgurOQ zDZR9)T&c`%J&BaEyr8zwKw|oZd(TVUNH07NlJ2Aj>4`u%0ucyAc9H|hK_o^X z3V|2|V%2j-saSHPM33|)eboJD+1Mfwt#L8ZkMze`c4Fe_pbpXx=hb8&ZWV-EeVAzz zfLqD^6st4?uiVd7^DWVj@#%Sa7#S%l5KiKkCL)mZsRD`l6{U(AwST3Fl1w18Fk56I znM5X&DP$^{My8V)WF|QVffNK%5lBNI9f1r4G7-RqSqNk!kkdtGYuO?dq>{{+*pr1K zTe&@K6(CT9K&{ADotCY7ku7X(c|B}3i)@W0Tktgw0UT$PntMKGtG9(zDmClTquyty{mAESHT*-5Sy-?^H^g;m%FI>>bp2cc@5E)wc~ z7UULkyB6PV8hqSof`^f#|0rDVuh&)UlA&-*B$S)9RM4$zCviJWI1D&x*LV_24=Q;aOag25Ow&N{T7+OahT!ac3rF%TB@t17N4_UNATSewSqRMTqyPm))G-lr zyHOuVaS}a>Cw=g$g=<}1ks`OLR#_7*l@5LUO0KvXw07QSQ{1YSUTYHxp?cxAy)hw& z7udLpR(|A#*0{UnrVJ=!4e}IractT1MdV+L$WIrMS5g*~BSxOGq^zhulr?2T*;00t zoU*5|8VeCvgur41mLRYcfn^9RM_>g4D-l@LMLB7arv^~Yl#9fkaubnn??HYI0+{RV zBJ?{j^a&t=^2XRxJ_vMlV^8^G?5O~Mv2Zzg;Ur$ z*CMd4gNmY}5m=A#Bv~|QDuGJD&{Bz15|xYq9$&f;*w{&>QfVTzpCf?P)rJl#2g8+% z;WAxf6RW{bi3{@oi}i3S|H!+u!4qZ;ubiCFrwTLPW9w8ARVs>8EE2s%B$_G{iQbBd zp0uQ&1yx5iY7xiYixJ<65vR&T#J7rwtEh3*RJ;-czn}yPQEfPPK7upm<2ZvpN=*?S zBd{BRy$I~b3G@S;Hvfpz=RY?9!2o>zXmI6iNI;{s6AQIU`-yiGRfqhEQ?yH9h>kfL5QaIZIbMh z+SS_H16fkM5^lGz)=K_A%I=|I07dSIElb11WqIHWf!%#+sF=5heY?Lj*3QhrpL(6 zB5*_N-ZwQi7E9qZhIZ-#0$=sm*k#eb?@?F9OXJ*MYwy^OD5e5C1hu$syCDGv)QwHI{zRLx0P$-!pG%BnxT1(ozk4f zPH%N9MT%N!VgoIu@hWB)txp@!hO`lFOqZFtD6ftgKnts>D4S~tRFlXbiQ8>mX zLxX!BE>Qdz_sAva(cl$PgC{p7yT8lz!|sXm4m&OKQmRMpB3g_fWH^n-Ui{)eKaoou z4e4sSRm8o9uBGefdb)vbq?_nwdMw?7z~2bGMc^F*?-BTbpaemHAViQrknEzzb>rTq z9S!M;7$1#V{K%JRuVL^XM;|&ZE%dbQ% zq0uMx7)vYq5`A05@-lsezDj>XU!$+n-_keeoAfP&XWWsNxb99jX!q#{^h0c{c+Ubs zn;y{Q2)ZHYj*S(1Xi$rxUx}#whM;W^YHu)V^dFK(;)S4{xMG5Dco<_A_UQ3}fmlvP z!eF}W5p?Ka2!=!uzp0-le_%L9SEDGSqfyieE5h^^7455*DXknCLq>+7WsDeO#stCs z2o6Bdxsx$v%tUBi5X8g3c93IiBzlZ3hVq_Li!Ec13mkBPPQHzY#w0DZCaKS~cFV`~ zXIwNmGR_(tJwJK9Xp@W=9zEh~Q|AT{6W?xd>hfQ_7Sf7=+*`1cN)7 z3UV-0gFDNXt;kPmkNKy6j(bW`o-Hn z>>Odf5ZO7(978Yz!ORZkICBEQF$gL|cKR}Bm~$dKUol@ZXA#UoFdM;~PUbvwK{Rd5 zX&xpBZ${1@F;IPBrjuGP%~o}pxrV{N{(peK=bLo&XS7rM^o03iXD-M2CMN18ZhPy$ zZDUvV8ydbO^v1l7_)~X%f`@!U)OXB%Em8M0L@7nUA8Lro7l~5WdCDxACyZuN5YFHc z4MSS^Nh2*QzcOz{R$el%nBSP+nb*u4<`3pi<}U`XrWPYuf?z3v*dogjtU$05L2QlH z2-b8l@3gG2K+6hCiLBrWqWD1&rt=tjFW6 z_KpWo<8G^Btyw#)Bx}RkBG`yvQwJ+&ad2uzuvH97mTW)PS%U&QK!d_qtRRcy3^vym zb?hjMzN{BJ1XITjWCyXBs&NRa5EMGuq2yo|#{g{P*y`Fe)Wxf#Yx}EMKZzde|6eAW zzmojkZ&P^I4z=aeflg1vsmx_I2)7;e-?p0_YfGBu1)X1MSY>he>8Snxu*Qb6nh`&o z#Unl@_iDzp>T51uT(?d&x zNJ}HzBwh&4#eXJ*L2Mg>^ATLo!G6Y0KyV>~%QXRwoyyJ>ai7Lc zXR&aL5L}Gll1_FOJ6m*_r3fzT9t~9NLX6^~|Dx!8!0*zQN#V+Eorks_ZhhgRK^)Kb zSv=qW-rz9K8)ZkHyuofo|bOc1@O zdsfHc$v`_d1i`c2v~a^QE!+t9ws;|UPNYS1$Fz*?riBaOMqw?uKrRTu3kY89;DWgj z1aa)Tt{HZ?2rdSr&P8%j93CMrBX|YDtDWRvE{==WK>iJa*D&h-bLDEcG4ASfGyAK! zRE%cYf6)w>@zYnSF@dFB^Cq|)U?i;>V;M%#>B1;`yCxSmA__Tvt!>vW| zX9QnrA|1Dp+aj{`Ik$=1jNmf_e?jnhC%2W`CPum!2;zC0Ht*&3V!Zd^G`A#8oA+`D zals*6uprIG;S-dPa>unO<0S`-@++L{awo-9`!_r#R=OrSlc%1k?0HXV`9YJGUQ-ml>v0bOm&o&zo1kK8j6grB&l97g6nf*%l}FX`ld;hu9Z5CITDB7#v5 zTscj}z2^SFy#jm?s-6225fJyvy~Xc;$GsPKTx*NUl;RFbjyf)JB_asT>Nzjr0bV^1 z!Y4>NcnRKS)h^ud1dlfxwSDn4A}CQpJ)YxvUMCgzRiioHfCxHEI((GB$H3sB0cw}_ zfvMuTE4~-s8*g2IJV2#Iq!SnGNhYS?!&jPTdtRi^N!@ln**Dl`we{7;?Qq1{21m{VOgcpyHb@;{XxLtF5tzDQlvIW3gW2fCen0bj@$A)-Gb+z>JFpZ-hvN|Ew1zMQW>!~leMg$b8V%9*d` z@jl8nM7ZMa#a!pW=bQO)|Hm`DiWhi<2zNwa&O8NIxo`I>c%H<@0ZMEx z^AoXAOyVc+px2m^D#A-^^i%n1nIG*F+kQ?bKb4;@nW*)Io^vt$OnyE-O@;-X&ClU0 zcr`yyBkmwX48{^8VhAFJuH_f-3;9L-VtikSh+&8rj))P67^(R&TvWrZ2ORbC4a$Z;3Xy*Z36QXSQ0!VHrPmv~A%)FoY(D*85Fl6X$PVIW=}=#39}8!$4)jIqE+ zyn~o@d~&;q8OyZdNhM;&GZXN+?J0Q5w~SfAtYSKt)y!IEJwCzxIdg)!!V);y55>o; zH?pVL)9fRhqP)TDoqC-HohF?&of$d{bUJm`>ul3G zt8+u8b6e*-o%=cubsp(TbU9r|-M+g0d!Orlt@j5#TF*^yp5Ai39eVrqPU~INyR3Ir z@0#AXdiV7n>OInXtoNhdQz?|1NZq7iQl+$7S|@FgHcMNiw~?<=s8N_vgi(}Hj8U9XvC(X!6Go4Welhyh=#|m$MsJNN zV*_I|m9e#PKVwg0FXKVRKE{#83C0=5V~iV(n~hf)Z!+F(yw`ZY@j>Im#;1+X7=LYi z&iI1yCF9p7<|Y9qN|VVZb4*s4w3~FAtTkD0(q(eqt{C7 z%*V{nY_wUTS(;hCS(RChS)JK9Gh{a2Y=YTbvz2D;W}Rkh%+{H0FxzOh*KEJpL9@eV zN6o%4JE1Z=Wp>Hzk=ftooVl_2AoC&SLFVD+k>=6nvF0h}Y33Q`W6ZP7>&z#cFEQ^l zUu(YJyvuxx`8M|Se00nSyfn7Sv6Ws zu$p7F)M~laN~?COhgLuLfqj@hR(%}%c=Yk=GpJ8#pSnJ%&*VPy`mF7E88--22O`%P(O{q<} zO{Gn>O|4D6&1##gw!qfiHr;lb?IGKrZU3}=Yx~{~*b#Or%FfKr&d$lMpWOgE7rWth z{&sVq;_MRalI#?ARd%1*&9GZw*J;;f_qp9>yRCM6?Dp9musdXT#O{pU zWxL0AzuCR9`_t~N-Fvx2ZX~yo+sW zlK(D$BmYzWx4ntIslB(LpThx%Lk>qAjyb4~JDhYl?Qq87n!|SvKRNvD z@QcF>$AOOCj)9J$j){)Rj;W66j!PWZIc{*==(x%8m6OB?I+0GalcAHblg!D?DcMQk zl&Gy94g420R?_%YYXHUJm$uz#jwt9`Me2sB@n4a_5^ayo=1m(xs1!jf;be zlS@CB0WL#bhP#Y(@o{N!nc_0lWtz(jmnAMsU6#45aM|dx)n&WOPM3Wy2VIW19CJDE za?$0o%T-rXR|i)o*M6?fuG3u?yLP#5a^32>!*#doKG%b;M_j*fz2d66=6b{Rw(DKj z2dEZ3+>k;7*?Gfvd;F0W+>XGkJ=27WU<5BO?>LGZH_n7E0*<+8# zcb>gGO+3v!Ej{~qx_J)s9O>!n>F*ij8R?nkndO=5sq`%NEc2}JtnzI1RH;1YdM@=m z;Q58;1J6IaC@v{!^zv{#&0f>(}Lo|n?AaB$Y( z(!u3}D+kvM>m0Uq*!E#NhwT};VdU(z8St*zPY|dzNNkuzSX|9zRP_t_`dM{(~tHu^Rx7G@N@Q4dH4j5e)Iem_$~9>=(pGJoZm&iD}LAfZus5yyX*JB z?~&gVzo-5Zf5M;gXZ$&TU4K1)1AilbnZKF8h5u0hWdE`L%l(h}KMv3d=pQgTAU~iY zpgN!~pdmmAm=Z8OU{=7~fcXIn1D2=)mIbT`*ch-iU`N32fCB-C1C9k85BMRF2$TlO z0?h-h0&N1F0{aKL1iA-$2Brtj2;3aFC-6kz^}w5f4+CEW5kYj2VUTH%MNpq0d5~jJ z-=O|M!-9N*LW07Al7ljWvVwAh3WAD)N`uOST7#wrtqkf2S`)NBXk*akplv}rgH(Hh z_6Hpbx*YUP(Dk4jLAQdw3%VclFz8Xxlc1l1ejde*>N_f8RQag6qxO!vJ?igZ^WY)D ze!+pk!NH-yvB7D=rv=Xpo)fGN-Wq%*_+Id% z;3vUPgI@%{3jRI#O$Z&rg_wj`h1i71LmX8hE+OtAULk`+hKA&Xs6%#!918g=Pq3!M-; zIdpmGs?d(m)uC%cH-vs3x+Qd5=+4mHp?gEW3H@!f>FD93$Bh1L^!m}KNB%P8xl4wEI2GYEGjHEEGaBCEF)}87z$evwlQpb*sid> zVF$v#2s;_}W!TqY=fYlx_YEH%9v7Y!UL9T+J}!J(_=@oM@Xg^n!gq)73qKrwEc|%* z$?&V;H^Lu;KMH>t{wDmd@OKd~f{b7yxCqk-hlr7?2%iZ5h@gm&h|v+@5s?wm5wQ{R z5lInc5tR`&5%m#G5iJp_h_;9c5tAdPMa+zt9kD!OWkh?#>WF6%e?`2FcpnKO!y{87 z(;_n>vm)0LqB5hhqH?10 zqVl7PqEsbOWl@z;)ls!kbE39JU5$DjZ656xt%x2U-4T5x`pf9Aqt8cQjJ^^5Ao@}C zljx_>zeK-?ei{8ChKyli_!zwygBar&SLril_OU$&Gc`@^2 z7RD@zSr@Z8W?Rh8m_0FvV~)j~h&df|Cgx?VVeF{bC{=8FYfqE7sXnRxsllnCso|-SsTrw7 zspC>n>Sw8wQm3ZQNS&RkPF;|?ICWX-w$z=eyHoe3?oU0GdNlQT>dDkEQ@=_*oBCrK zo93Jrl~$d$DD7a{t+c<=W$8BQ@^r`azUdz6!_&RfebWQdgH-9k>7&z=($mw&r01mP zrx&G{rkAHrOW&M+ApL0i@$^&aU#Fi-znFeG{eJon>95lNN`IFj$sjWLj9wYi48siL z44;h3j5!%gGS+46&p4EED&tDV4;epZyv+DL6J|1*d}gmqgG{4LS*BTL-^@XoVVRMc zF`4n1Ntvmc8JSs`s@zOvW?^P)rjXf|`B~<~%qf}EGiPSb&Qxd4&s>16fJ($6x?vdMDD>YFtn%RS30YjD=k ztn{qLtO;4uvu0(@&6=OJENf*}N7kCGby*j)e$AF=J7*8ej>wMAPElnmvm3L=W>3zZ zkv%(GoxLb~Y4(cjRoPpzw`U*8K9PMo`>X5=*_X4w$-bWbL-wm2Hb*C?caDCJQI0If zJjW`>CP$v*m@^{BC&w=*ASWm%BquBck%&CffWcQ@}z-tP)lp`$QT*eV7phA4s*qZJW~Xhnh|S&^p5 zP?RXj6=M~GV!UFaVwz&6Vva(s=um7?oKT!re5E+2xTv_IxTd(FxUEv$RXk9PC4YPV&iqUHzZHN2x_~RtEzmD8Dv%YJ74$6_P%yN> zw;-TkR6%G#bU|E!DzPA?Agy3}!KQ+11$PU6F8ELg3v~)j3kMXs7LF+ND-0|QE(|Y> zDvT|RFU&2hDEzE&QsLCX8HKY8)rAWR7Z)xoTv^yrxTkP`;laYgg+~jI7oI9SQ}}h^ z`NE5ZmkXa4^)B)(N+@b9T2b^x(fwjcu~o5Salc~cV%Op!#eT(ss^Z|{(ZvzPQN=OE zam881isFLe;^K

f*ZMhT(-# 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�Bv{e2@a925CTAkP);Av>D_8xj?^zZh>xt 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 diff --git a/ui/ios/sendme/sendme/Receive.swift b/ui/ios/sendme/sendme/Receive.swift index 37135a8..070b697 100644 --- a/ui/ios/sendme/sendme/Receive.swift +++ b/ui/ios/sendme/sendme/Receive.swift @@ -7,6 +7,7 @@ import Foundation import SwiftUI +import UIKit import IrohLib import CodeScanner @@ -25,7 +26,12 @@ struct Receive: View { private var progressManager: DownloadProgressManager = DownloadProgressManager() var body: some View { - stepView + VStack { + stepView + } + .alert(item: $currentError) { error in + Alert(title: Text(error.title), message: Text(error.localizedDescription), dismissButton: .default(Text("OK"))) + } } private var stepView: some View { @@ -74,12 +80,18 @@ struct Receive: View { return } - try node.blobsDownload(req: ticket.asDownloadRequest(), cb: progressManager) - let blobs = try node.blobsGetCollection(hash: ticket.hash()).blobs() - for blob in blobs { - let data = try node.blobsReadToBytes(hash: blob.link) - saveFileToDocumentsDirectory(fileName: blob.name, data: data) - } + try node.blobsDownload( + req: ticket.asDownloadRequest(), + cb: progressManager + ) + let documentsDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! + print("exporting to: \(documentsDirectoryURL.relativePath)") + try node.blobsExport( + hash: ticket.hash(), + destination: documentsDirectoryURL.relativePath, + format: BlobExportFormat.collection, + mode: BlobExportMode.tryReference + ) } catch let error { currentError = .downloadFailed(error.localizedDescription) } @@ -101,15 +113,15 @@ struct Receive: View { } }) } - .alert(item: $currentError) { error in - Alert(title: Text(error.title), message: Text(error.localizedDescription), dismissButton: .default(Text("OK"))) - } } }) } private func downloading() -> any View { - return AnyView(VStack { + return AnyView(VStack(spacing: 5) { + ProgressView() + .progressViewStyle(CircularProgressViewStyle()) + .scaleEffect(1.5) Text("Downloading") }.padding()) } @@ -121,6 +133,14 @@ struct Receive: View { self.ticketString = "" step = .configuring } + Button("Show in Files App") { + if let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first { + // Switch URL scheme to this psudo-documents "shareddocuments": + let url = URL(string: "shareddocuments://" + url.path())! + print("opening \(url)") + UIApplication.shared.open(url) + } + } }.padding()) } } @@ -129,12 +149,12 @@ class DownloadProgressManager: DownloadCallback { func progress(progress: DownloadProgress) throws { switch progress.type() { -// case .foundLocal: -// debugPrint("found local: \(progress.asFound())") + case .foundLocal: + debugPrint("found local: \(progress.asFoundLocal())") case .found: debugPrint("found: \(progress.asFound())") -// case .foundHashSeq: -// debugPrint("found HashSeq: \(progress.asFound())") + case .foundHashSeq: + debugPrint("found HashSeq: \(progress.asFoundHashSeq())") case .progress: debugPrint("progress: \(progress.asProgress())") case .done: