From 4bbd830c7f9f2160e59ae169d3280c8825bf8501 Mon Sep 17 00:00:00 2001 From: matthiasdebernardini Date: Sat, 7 Mar 2026 21:09:39 -0600 Subject: [PATCH 1/3] add nostr-lib, carpet-ui crates and phoenixd infrastructure - nostr-lib: marketplace Nostr layer with NostrService, filters, zap, profile (nostr-sdk 0.44) - carpet-ui: Dioxus 0.7.3 UI with routes, components, and state management - Fix Dioxus.toml legacy fields and simplify main.rs for dx serve compatibility - Add workspace default-members excluding carpet-ui (needs platform features) - Add phoenixd Docker compose and justfile for Lightning node management - Add QR scan utility script Co-Authored-By: Claude Opus 4.6 (1M context) --- Cargo.lock | 5408 +++++++++++++++-- Cargo.toml | 9 + crates/carpet-ui/Cargo.toml | 24 + crates/carpet-ui/Dioxus.toml | 16 + crates/carpet-ui/src/app.rs | 17 + crates/carpet-ui/src/components/layout.rs | 42 + crates/carpet-ui/src/components/list_card.rs | 41 + .../carpet-ui/src/components/list_detail.rs | 28 + crates/carpet-ui/src/components/mod.rs | 3 + crates/carpet-ui/src/main.rs | 10 + crates/carpet-ui/src/routes.rs | 95 + crates/carpet-ui/src/state/marketplace.rs | 7 + crates/carpet-ui/src/state/mod.rs | 3 + crates/carpet-ui/src/state/nostr.rs | 8 + crates/carpet-ui/src/state/wallet.rs | 7 + crates/nostr-lib/Cargo.toml | 14 + crates/nostr-lib/src/error.rs | 31 + crates/nostr-lib/src/filters.rs | 60 + crates/nostr-lib/src/lib.rs | 10 + crates/nostr-lib/src/profile.rs | 71 + crates/nostr-lib/src/service.rs | 275 + crates/nostr-lib/src/types.rs | 72 + crates/nostr-lib/src/zap.rs | 119 + docker-compose.phoenixd.yml | 13 + phoenixd.justfile | 156 + scripts/scan_qr.py | 35 + 26 files changed, 5962 insertions(+), 612 deletions(-) create mode 100644 crates/carpet-ui/Cargo.toml create mode 100644 crates/carpet-ui/Dioxus.toml create mode 100644 crates/carpet-ui/src/app.rs create mode 100644 crates/carpet-ui/src/components/layout.rs create mode 100644 crates/carpet-ui/src/components/list_card.rs create mode 100644 crates/carpet-ui/src/components/list_detail.rs create mode 100644 crates/carpet-ui/src/components/mod.rs create mode 100644 crates/carpet-ui/src/main.rs create mode 100644 crates/carpet-ui/src/routes.rs create mode 100644 crates/carpet-ui/src/state/marketplace.rs create mode 100644 crates/carpet-ui/src/state/mod.rs create mode 100644 crates/carpet-ui/src/state/nostr.rs create mode 100644 crates/carpet-ui/src/state/wallet.rs create mode 100644 crates/nostr-lib/Cargo.toml create mode 100644 crates/nostr-lib/src/error.rs create mode 100644 crates/nostr-lib/src/filters.rs create mode 100644 crates/nostr-lib/src/lib.rs create mode 100644 crates/nostr-lib/src/profile.rs create mode 100644 crates/nostr-lib/src/service.rs create mode 100644 crates/nostr-lib/src/types.rs create mode 100644 crates/nostr-lib/src/zap.rs create mode 100644 docker-compose.phoenixd.yml create mode 100644 phoenixd.justfile create mode 100755 scripts/scan_qr.py diff --git a/Cargo.lock b/Cargo.lock index 1cc24a9..e297b7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,33 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + +[[package]] +name = "aead" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0" +dependencies = [ + "crypto-common", + "generic-array", +] + +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "agcli" version = "0.7.0" @@ -33,6 +60,21 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" version = "1.0.102" @@ -51,6 +93,12 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0f477b951e452a0b6b4a10b53ccd569042d1d01729b519e02074a9c0958a063" +[[package]] +name = "askama_escape" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3df27b8d5ddb458c5fb1bbc1ce172d4a38c614a97d550b0ac89003897fb01de4" + [[package]] name = "async-stream" version = "0.3.6" @@ -70,7 +118,7 @@ checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -81,9 +129,85 @@ checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", +] + +[[package]] +name = "async-tungstenite" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee88b4c88ac8c9ea446ad43498955750a4bbe64c4392f21ccfe5d952865e318f" +dependencies = [ + "atomic-waker", + "futures-core", + "futures-io", + "futures-task", + "futures-util", + "log", + "pin-project-lite", + "tungstenite 0.27.0", +] + +[[package]] +name = "async-utility" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34a3b57207a7a1007832416c3e4862378c8451b4e8e093e436f48c2d3d2c151" +dependencies = [ + "futures-util", + "gloo-timers", + "tokio", + "wasm-bindgen-futures", +] + +[[package]] +name = "async-wsocket" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c92385c7c8b3eb2de1b78aeca225212e4c9a69a78b802832759b108681a5069" +dependencies = [ + "async-utility", + "futures", + "futures-util", + "js-sys", + "tokio", + "tokio-rustls", + "tokio-socks", + "tokio-tungstenite 0.26.2", + "url", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "atk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" +dependencies = [ + "atk-sys", + "glib", + "libc", +] + +[[package]] +name = "atk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", ] +[[package]] +name = "atomic-destructor" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef49f5882e4b6afaac09ad239a4f8c70a24b8f2b0897edb1f706008efd109cf4" + [[package]] name = "atomic-waker" version = "1.1.2" @@ -118,6 +242,103 @@ dependencies = [ "fs_extra", ] +[[package]] +name = "axum" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b52af3cb4058c895d37317bb27508dccc8e5f2d39454016b297bf4a400597b8" +dependencies = [ + "axum-core", + "axum-macros", + "base64 0.22.1", + "bytes", + "form_urlencoded", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "multer", + "percent-encoding", + "pin-project-lite", + "serde_core", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sha1", + "sync_wrapper", + "tokio", + "tokio-tungstenite 0.28.0", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-extra" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9963ff19f40c6102c76756ef0a46004c0d58957d87259fc9208ff8441c12ab96" +dependencies = [ + "axum", + "axum-core", + "bytes", + "futures-util", + "headers", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "serde_core", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-macros" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604fde5e028fea851ce1d8570bbdc034bec850d157f7569d10f347d06808c05c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "base16" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d27c3610c36aee21ce8ac510e6224498de4228ad772a171ed65643a24693a5a8" + [[package]] name = "base58ck" version = "0.1.0" @@ -140,6 +361,12 @@ version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64ct" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" + [[package]] name = "bdk-agcli" version = "0.1.0" @@ -310,11 +537,53 @@ dependencies = [ "serde", ] +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + [[package]] name = "bitflags" version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +dependencies = [ + "serde_core", +] + +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block-padding" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93" +dependencies = [ + "generic-array", +] + +[[package]] +name = "block2" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +dependencies = [ + "objc2", +] [[package]] name = "bumpalo" @@ -322,11 +591,45 @@ version = "3.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d20789868f4b01b2f2caec9f5c4e0213b41e3e5702a50157d699ae31ced2fcb" +[[package]] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + [[package]] name = "bytes" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +dependencies = [ + "serde", +] + +[[package]] +name = "cairo-rs" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" +dependencies = [ + "bitflags 2.11.0", + "cairo-sys-rs", + "glib", + "libc", + "once_cell", + "thiserror 1.0.69", +] + +[[package]] +name = "cairo-sys-rs" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] [[package]] name = "carpet-agent" @@ -344,6 +647,31 @@ dependencies = [ "tracing-subscriber", ] +[[package]] +name = "carpet-ui" +version = "0.1.0" +dependencies = [ + "axum", + "bdk-lib", + "dcosl-core", + "dioxus", + "nostr-lib", + "phoenixd-lib", + "serde", + "serde_json", + "tokio", + "tracing", +] + +[[package]] +name = "cbc" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6" +dependencies = [ + "cipher", +] + [[package]] name = "cc" version = "1.2.56" @@ -362,6 +690,27 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cfb" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" +dependencies = [ + "byteorder", + "fnv", + "uuid", +] + +[[package]] +name = "cfg-expr" +version = "0.15.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" +dependencies = [ + "smallvec", + "target-lexicon", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -375,963 +724,3343 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] -name = "cmake" -version = "0.1.57" +name = "chacha20" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +checksum = "c3613f74bd2eac03dad61bd53dbe620703d4371614fe0bc3b9f04dd36fe4e818" dependencies = [ - "cc", + "cfg-if", + "cipher", + "cpufeatures", ] [[package]] -name = "combine" -version = "4.6.7" +name = "chacha20poly1305" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +checksum = "10cd79432192d1c0f4e1a0fef9527696cc039165d729fb41b3f4f4f354c2dc35" dependencies = [ - "bytes", - "memchr", + "aead", + "chacha20", + "cipher", + "poly1305", + "zeroize", ] [[package]] -name = "convert_case" -version = "0.10.0" +name = "charset" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +checksum = "f1f927b07c74ba84c7e5fe4db2baeb3e996ab2688992e39ac68ce3220a677c7e" dependencies = [ - "unicode-segmentation", + "base64 0.22.1", + "encoding_rs", ] [[package]] -name = "core-foundation" -version = "0.9.4" +name = "chrono" +version = "0.4.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0" dependencies = [ - "core-foundation-sys", - "libc", + "iana-time-zone", + "js-sys", + "num-traits", + "wasm-bindgen", + "windows-link 0.2.1", ] [[package]] -name = "core-foundation" -version = "0.10.1" +name = "ciborium" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ - "core-foundation-sys", - "libc", + "ciborium-io", + "ciborium-ll", + "serde", ] [[package]] -name = "core-foundation-sys" -version = "0.8.7" +name = "ciborium-io" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] -name = "deluxe" -version = "0.5.0" +name = "ciborium-ll" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed332aaf752b459088acf3dd4eca323e3ef4b83c70a84ca48fb0ec5305f1488" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ - "deluxe-core", - "deluxe-macros", - "once_cell", - "proc-macro2", - "syn", + "ciborium-io", + "half", ] [[package]] -name = "deluxe-core" -version = "0.5.0" +name = "cipher" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddada51c8576df9d6a8450c351ff63042b092c9458b8ac7d20f89cbd0ffd313" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "arrayvec", - "proc-macro2", - "quote", - "strsim", - "syn", + "crypto-common", + "inout", + "zeroize", ] [[package]] -name = "deluxe-macros" -version = "0.5.0" +name = "cmake" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f87546d9c837f0b7557e47b8bd6eae52c3c223141b76aa233c345c9ab41d9117" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" dependencies = [ - "deluxe-core", - "heck 0.4.1", - "if_chain", - "proc-macro-crate", - "proc-macro2", - "quote", - "syn", + "cc", ] [[package]] -name = "dirs" -version = "6.0.0" +name = "cocoa" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +checksum = "ad36507aeb7e16159dfe68db81ccc27571c3ccd4b76fb2fb72fc59e7a4b1b64c" dependencies = [ - "dirs-sys", + "bitflags 2.11.0", + "block", + "cocoa-foundation", + "core-foundation 0.10.1", + "core-graphics 0.24.0", + "foreign-types 0.5.0", + "libc", + "objc", ] [[package]] -name = "dirs-sys" -version = "0.5.0" +name = "cocoa-foundation" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +checksum = "81411967c50ee9a1fc11365f8c585f863a22a9697c89239c452292c40ba79b0d" dependencies = [ - "libc", - "option-ext", - "redox_users", - "windows-sys 0.61.2", + "bitflags 2.11.0", + "block", + "core-foundation 0.10.1", + "core-graphics-types", + "objc", ] [[package]] -name = "displaydoc" -version = "0.2.5" +name = "combine" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ - "proc-macro2", - "quote", - "syn", + "bytes", + "memchr", ] [[package]] -name = "dunce" -version = "1.0.5" +name = "const-serialize" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" +checksum = "ad7154afa56de2f290e3c82c2c6dc4f5b282b6870903f56ef3509aba95866edc" +dependencies = [ + "const-serialize-macro 0.7.2", +] [[package]] -name = "dyn-clone" -version = "1.0.20" +name = "const-serialize" +version = "0.8.0-alpha.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" +checksum = "9e42cd5aabba86f128b3763da1fec1491c0f728ce99245062cd49b6f9e6d235b" +dependencies = [ + "const-serialize 0.7.2", + "const-serialize-macro 0.8.0-alpha.0", + "serde", +] [[package]] -name = "encoding_rs" -version = "0.8.35" +name = "const-serialize-macro" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +checksum = "4f160aad86b4343e8d4e261fee9965c3005b2fd6bc117d172ab65948779e4acf" dependencies = [ - "cfg-if", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "equivalent" -version = "1.0.2" +name = "const-serialize-macro" +version = "0.8.0-alpha.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "42571ed01eb46d2e1adcf99c8ca576f081e46f2623d13500eba70d1d99a4c439" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] -name = "errno" -version = "0.3.14" +name = "const-str" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +checksum = "b0664d2867b4a32697dfe655557f5c3b187e9b605b38612a748e5ec99811d160" + +[[package]] +name = "const_format" +version = "0.2.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7faa7469a93a566e9ccc1c73fe783b4a65c274c5ace346038dca9c39fe0030ad" dependencies = [ - "libc", - "windows-sys 0.61.2", + "const_format_proc_macros", ] [[package]] -name = "esplora-client" -version = "0.12.3" +name = "const_format_proc_macros" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f19e3ea99dbfbef0c1ec26d83e69de0c579f6aa6aaac4f44597805fcc27e97af" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" dependencies = [ - "bitcoin", - "hex-conservative", - "log", - "minreq", - "reqwest 0.12.28", - "serde", - "serde_json", - "tokio", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] -name = "eventsource-stream" -version = "0.2.3" +name = "content_disposition" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74fef4569247a5f429d9156b9d0a2599914385dd189c539334c625d8099d90ab" +checksum = "ebc14a88e1463ddd193906285abe5c360c7e8564e05ccc5d501755f7fbc9ca9c" dependencies = [ - "futures-core", - "nom", - "pin-project-lite", + "charset", ] [[package]] -name = "fastrand" -version = "2.3.0" +name = "convert_case" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" [[package]] -name = "find-msvc-tools" -version = "0.1.9" +name = "convert_case" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" +dependencies = [ + "unicode-segmentation", +] [[package]] -name = "fnv" -version = "1.0.7" +name = "convert_case" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +dependencies = [ + "unicode-segmentation", +] [[package]] -name = "foldhash" -version = "0.1.5" +name = "cookie" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747" +dependencies = [ + "percent-encoding", + "time", + "version_check", +] [[package]] -name = "foreign-types" -version = "0.3.2" +name = "cookie_store" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +checksum = "15b2c103cf610ec6cae3da84a766285b42fd16aad564758459e6ecf128c75206" dependencies = [ - "foreign-types-shared", + "cookie", + "document-features", + "idna", + "log", + "publicsuffix", + "serde", + "serde_derive", + "serde_json", + "time", + "url", ] [[package]] -name = "foreign-types-shared" -version = "0.1.1" +name = "core-foundation" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] [[package]] -name = "form_urlencoded" -version = "1.2.2" +name = "core-foundation" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ - "percent-encoding", + "core-foundation-sys", + "libc", ] [[package]] -name = "fs_extra" -version = "1.3.0" +name = "core-foundation-sys" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] -name = "futures" -version = "0.3.32" +name = "core-graphics" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ - "futures-channel", - "futures-core", - "futures-executor", - "futures-io", - "futures-sink", - "futures-task", - "futures-util", + "bitflags 2.11.0", + "core-foundation 0.10.1", + "core-graphics-types", + "foreign-types 0.5.0", + "libc", ] [[package]] -name = "futures-channel" -version = "0.3.32" +name = "core-graphics" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ - "futures-core", - "futures-sink", + "bitflags 2.11.0", + "core-foundation 0.10.1", + "core-graphics-types", + "foreign-types 0.5.0", + "libc", ] [[package]] -name = "futures-core" -version = "0.3.32" +name = "core-graphics-types" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.11.0", + "core-foundation 0.10.1", + "libc", +] [[package]] -name = "futures-executor" -version = "0.3.32" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" dependencies = [ - "futures-core", - "futures-task", - "futures-util", + "libc", ] [[package]] -name = "futures-io" -version = "0.3.32" +name = "crc32fast" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] [[package]] -name = "futures-macro" -version = "0.3.32" +name = "crossbeam-channel" +version = "0.5.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +checksum = "82b8f8f868b36967f9606790d1903570de9ceaf870a7bf9fbbd3016d636a2cb2" dependencies = [ - "proc-macro2", - "quote", - "syn", + "crossbeam-utils", ] [[package]] -name = "futures-sink" -version = "0.3.32" +name = "crossbeam-utils" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" [[package]] -name = "futures-task" -version = "0.3.32" +name = "crunchy" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] -name = "futures-timer" -version = "3.0.3" +name = "crypto-common" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +dependencies = [ + "generic-array", + "rand_core 0.6.4", + "typenum", +] [[package]] -name = "futures-util" -version = "0.3.32" +name = "cssparser" +version = "0.29.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" dependencies = [ - "futures-channel", - "futures-core", - "futures-io", - "futures-macro", - "futures-sink", - "futures-task", - "memchr", - "pin-project-lite", - "slab", + "cssparser-macros", + "dtoa-short", + "itoa", + "matches", + "phf 0.10.1", + "proc-macro2", + "quote", + "smallvec", + "syn 1.0.109", ] [[package]] -name = "getrandom" -version = "0.2.17" +name = "cssparser-macros" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ - "cfg-if", - "js-sys", - "libc", - "wasi", - "wasm-bindgen", + "quote", + "syn 2.0.117", ] [[package]] -name = "getrandom" -version = "0.3.4" +name = "darling" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" dependencies = [ - "cfg-if", - "js-sys", - "libc", - "r-efi 5.3.0", - "wasip2", - "wasm-bindgen", + "darling_core", + "darling_macro", ] [[package]] -name = "getrandom" -version = "0.4.2" +name = "darling_core" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ - "cfg-if", - "libc", - "r-efi 6.0.0", - "wasip2", - "wasip3", + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "glob" -version = "0.3.3" +name = "darling_macro" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" +dependencies = [ + "darling_core", + "quote", + "syn 2.0.117", +] [[package]] -name = "h2" -version = "0.4.13" +name = "dashmap" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http", - "indexmap", - "slab", - "tokio", - "tokio-util", - "tracing", + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", ] [[package]] -name = "hashbrown" -version = "0.14.5" +name = "data-encoding" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "d7a1e2f27636f116493b8b860f5546edb47c8d8f8ea73e1d2a20be88e28d1fea" + +[[package]] +name = "dcosl-core" +version = "0.1.0" dependencies = [ - "ahash", - "serde", + "nostr", + "serde_json", + "thiserror 2.0.18", ] [[package]] -name = "hashbrown" -version = "0.15.5" +name = "deluxe" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "8ed332aaf752b459088acf3dd4eca323e3ef4b83c70a84ca48fb0ec5305f1488" dependencies = [ - "foldhash", + "deluxe-core", + "deluxe-macros", + "once_cell", + "proc-macro2", + "syn 2.0.117", ] [[package]] -name = "hashbrown" -version = "0.16.1" +name = "deluxe-core" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "eddada51c8576df9d6a8450c351ff63042b092c9458b8ac7d20f89cbd0ffd313" +dependencies = [ + "arrayvec", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.117", +] [[package]] -name = "heck" -version = "0.4.1" +name = "deluxe-macros" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "f87546d9c837f0b7557e47b8bd6eae52c3c223141b76aa233c345c9ab41d9117" +dependencies = [ + "deluxe-core", + "heck 0.4.1", + "if_chain", + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] -name = "heck" -version = "0.5.0" +name = "deranged" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" +dependencies = [ + "powerfmt", +] [[package]] -name = "hex-conservative" -version = "0.2.2" +name = "derive_more" +version = "0.99.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ - "arrayvec", + "convert_case 0.4.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", ] [[package]] -name = "hex_lit" -version = "0.1.1" +name = "derive_more" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] [[package]] -name = "http" -version = "1.4.0" +name = "derive_more-impl" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" dependencies = [ - "bytes", - "itoa", + "convert_case 0.10.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.117", + "unicode-xid", ] [[package]] -name = "http-body" -version = "1.0.1" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "bytes", - "http", + "block-buffer", + "crypto-common", + "subtle", ] [[package]] -name = "http-body-util" -version = "0.1.3" +name = "dioxus" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "92b583b48ac77158495e6678fe3a2b5954fc8866fc04cb9695dd146e88bc329d" dependencies = [ - "bytes", - "futures-core", + "dioxus-asset-resolver", + "dioxus-cli-config", + "dioxus-config-macro", + "dioxus-config-macros", + "dioxus-core", + "dioxus-core-macro", + "dioxus-desktop", + "dioxus-devtools", + "dioxus-document", + "dioxus-fullstack", + "dioxus-fullstack-macro", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-liveview", + "dioxus-logger", + "dioxus-router", + "dioxus-server", + "dioxus-signals", + "dioxus-ssr", + "dioxus-stores", + "dioxus-web", + "manganis", + "subsecond", + "warnings", +] + +[[package]] +name = "dioxus-asset-resolver" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0161af1d3cfc8ff31503ff1b7ee0068c97771fc38d0cc6566e23483142ddf4f" +dependencies = [ + "dioxus-cli-config", "http", - "http-body", - "pin-project-lite", + "infer", + "jni", + "js-sys", + "ndk", + "ndk-context", + "ndk-sys", + "percent-encoding", + "thiserror 2.0.18", + "tokio", + "wasm-bindgen-futures", + "web-sys", ] [[package]] -name = "httparse" -version = "1.10.1" +name = "dioxus-cli-config" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" +checksum = "ccd67ab405e1915a47df9769cd5408545d1b559d5c01ce7a0f442caef520d1f3" +dependencies = [ + "wasm-bindgen", +] [[package]] -name = "hyper" -version = "1.8.1" +name = "dioxus-config-macro" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +checksum = "f040ec7c41aa5428283f56bb0670afba9631bfe3ffd885f4814807f12c8c9d91" dependencies = [ - "atomic-waker", - "bytes", - "futures-channel", - "futures-core", - "h2", - "http", - "http-body", - "httparse", - "itoa", - "pin-project-lite", - "pin-utils", - "smallvec", - "tokio", - "want", + "proc-macro2", + "quote", ] [[package]] -name = "hyper-rustls" -version = "0.27.7" +name = "dioxus-config-macros" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +checksum = "10c41b47b55a433b61f7c12327c85ba650572bacbcc42c342ba2e87a57975264" + +[[package]] +name = "dioxus-core" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b389b0e3cc01c7da292ad9b884b088835fdd1671d45fbd2f737506152b22eef0" dependencies = [ - "http", - "hyper", - "hyper-util", - "rustls 0.23.37", - "rustls-pki-types", - "tokio", - "tokio-rustls", - "tower-service", + "anyhow", + "const_format", + "dioxus-core-types", + "futures-channel", + "futures-util", + "generational-box", + "longest-increasing-subsequence", + "rustc-hash 2.1.1", + "rustversion", + "serde", + "slab", + "slotmap", + "subsecond", + "tracing", ] [[package]] -name = "hyper-tls" -version = "0.6.0" +name = "dioxus-core-macro" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +checksum = "6a82d65f0024fc86f01911a16156d280eea583be5a82a3bed85e7e8e4194302d" dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", + "convert_case 0.8.0", + "dioxus-rsx", + "proc-macro2", + "quote", + "syn 2.0.117", ] [[package]] -name = "hyper-util" -version = "0.1.20" +name = "dioxus-core-types" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +checksum = "bfc4b8cdc440a55c17355542fc2089d97949bba674255d84cac77805e1db8c9f" + +[[package]] +name = "dioxus-desktop" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e6ec66749d1556636c5b4f661495565c155a7f78a46d4d007d7478c6bdc288c" dependencies = [ + "async-trait", "base64 0.22.1", "bytes", + "cocoa", + "core-foundation 0.10.1", + "dioxus-asset-resolver", + "dioxus-cli-config", + "dioxus-core", + "dioxus-devtools", + "dioxus-document", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-interpreter-js", + "dioxus-signals", + "dunce", "futures-channel", "futures-util", - "http", - "http-body", - "hyper", - "ipnet", + "generational-box", + "global-hotkey", + "infer", + "jni", + "lazy-js-bundle", "libc", + "muda", + "ndk", + "ndk-context", + "ndk-sys", + "objc", + "objc_id", "percent-encoding", - "pin-project-lite", - "socket2", - "system-configuration", + "rand 0.9.2", + "rfd", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "signal-hook", + "slab", + "subtle", + "tao", + "thiserror 2.0.18", "tokio", - "tower-service", "tracing", - "windows-registry", + "tray-icon", + "tungstenite 0.27.0", + "webbrowser", + "wry", ] [[package]] -name = "icu_collections" -version = "2.1.1" +name = "dioxus-devtools" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +checksum = "dcf89488bad8fb0f18b9086ee2db01f95f709801c10c68be42691a36378a0f2d" dependencies = [ - "displaydoc", - "potential_utf", - "yoke", - "zerofrom", - "zerovec", + "dioxus-cli-config", + "dioxus-core", + "dioxus-devtools-types", + "dioxus-signals", + "futures-channel", + "futures-util", + "serde", + "serde_json", + "subsecond", + "thiserror 2.0.18", + "tracing", + "tungstenite 0.27.0", ] [[package]] -name = "icu_locale_core" +name = "dioxus-devtools-types" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e7381d9d7d0a0f66b9d5082d584853c3d53be21d34007073daca98ddf26fc4d" +dependencies = [ + "dioxus-core", + "serde", + "subsecond-types", +] + +[[package]] +name = "dioxus-document" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ba0aeeff26d9d06441f59fd8d7f4f76098ba30ca9728e047c94486161185ceb" +dependencies = [ + "dioxus-core", + "dioxus-core-macro", + "dioxus-core-types", + "dioxus-html", + "futures-channel", + "futures-util", + "generational-box", + "lazy-js-bundle", + "serde", + "serde_json", + "tracing", +] + +[[package]] +name = "dioxus-fullstack" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7db1f8b70338072ec408b48d09c96559cf071f87847465d8161294197504c498" +dependencies = [ + "anyhow", + "async-stream", + "async-tungstenite", + "axum", + "axum-core", + "axum-extra", + "base64 0.22.1", + "bytes", + "ciborium", + "const-str", + "const_format", + "content_disposition", + "derive_more 2.1.1", + "dioxus-asset-resolver", + "dioxus-cli-config", + "dioxus-core", + "dioxus-fullstack-core", + "dioxus-fullstack-macro", + "dioxus-hooks", + "dioxus-html", + "dioxus-signals", + "form_urlencoded", + "futures", + "futures-channel", + "futures-util", + "gloo-net", + "headers", + "http", + "http-body", + "http-body-util", + "inventory", + "js-sys", + "mime", + "pin-project", + "reqwest 0.12.28", + "rustversion", + "send_wrapper", + "serde", + "serde_json", + "serde_qs", + "serde_urlencoded", + "thiserror 2.0.18", + "tokio", + "tokio-stream", + "tokio-tungstenite 0.27.0", + "tokio-util", + "tower", + "tower-http", + "tower-layer", + "tracing", + "tungstenite 0.27.0", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.4.2", + "web-sys", + "xxhash-rust", +] + +[[package]] +name = "dioxus-fullstack-core" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda8b152e85121243741b9d5f2a3d8cb3c47a7b2299e902f98b6a7719915b0a2" +dependencies = [ + "anyhow", + "axum-core", + "base64 0.22.1", + "ciborium", + "dioxus-core", + "dioxus-document", + "dioxus-history", + "dioxus-hooks", + "dioxus-signals", + "futures-channel", + "futures-util", + "generational-box", + "http", + "inventory", + "parking_lot", + "serde", + "serde_json", + "thiserror 2.0.18", + "tokio", + "tracing", +] + +[[package]] +name = "dioxus-fullstack-macro" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "255104d4a4f278f1a8482fa30536c91d22260c561c954b753e72987df8d65b2e" +dependencies = [ + "const_format", + "convert_case 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.117", + "xxhash-rust", +] + +[[package]] +name = "dioxus-history" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d00ba43bfe6e5ca226fef6128f240ca970bea73cac0462416188026360ccdcf" +dependencies = [ + "dioxus-core", + "tracing", +] + +[[package]] +name = "dioxus-hooks" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab2da4f038c33cb38caa37ffc3f5d6dfbc018f05da35b238210a533bb075823" +dependencies = [ + "dioxus-core", + "dioxus-signals", + "futures-channel", + "futures-util", + "generational-box", + "rustversion", + "slab", + "tracing", +] + +[[package]] +name = "dioxus-html" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eded5fa6d2e677b7442a93f4228bf3c0ad2597a8bd3292cae50c869d015f3a99" +dependencies = [ + "async-trait", + "bytes", + "dioxus-core", + "dioxus-core-macro", + "dioxus-core-types", + "dioxus-hooks", + "dioxus-html-internal-macro", + "enumset", + "euclid", + "futures-channel", + "futures-util", + "generational-box", + "keyboard-types", + "lazy-js-bundle", + "rustversion", + "serde", + "serde_json", + "serde_repr", + "tracing", +] + +[[package]] +name = "dioxus-html-internal-macro" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45462ab85fe059a36841508d40545109fd0e25855012d22583a61908eb5cd02a" +dependencies = [ + "convert_case 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-interpreter-js" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a42a7f73ad32a5054bd8c1014f4ac78cca3b7f6889210ee2b57ea31b33b6d32f" +dependencies = [ + "dioxus-core", + "dioxus-core-types", + "dioxus-html", + "js-sys", + "lazy-js-bundle", + "rustc-hash 2.1.1", + "serde", + "sledgehammer_bindgen", + "sledgehammer_utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "dioxus-liveview" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3f7a1cfe6f8e9f2e303607c8ae564d11932fd80714c8a8c97e3860d55538997" +dependencies = [ + "axum", + "dioxus-cli-config", + "dioxus-core", + "dioxus-devtools", + "dioxus-document", + "dioxus-history", + "dioxus-html", + "dioxus-interpreter-js", + "futures-channel", + "futures-util", + "generational-box", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "slab", + "thiserror 2.0.18", + "tokio", + "tokio-stream", + "tokio-util", + "tracing", +] + +[[package]] +name = "dioxus-logger" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1eeab114cb009d9e6b85ea10639a18cfc54bb342f3b837770b004c4daeb89c2" +dependencies = [ + "dioxus-cli-config", + "tracing", + "tracing-subscriber", + "tracing-wasm", +] + +[[package]] +name = "dioxus-router" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d5b31f9e27231389bf5a117b7074d22d8c58358b484a2558e56fbab20e64ca4" +dependencies = [ + "dioxus-cli-config", + "dioxus-core", + "dioxus-core-macro", + "dioxus-fullstack-core", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-router-macro", + "dioxus-signals", + "percent-encoding", + "rustversion", + "tracing", + "url", +] + +[[package]] +name = "dioxus-router-macro" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "838b9b441a95da62b39cae4defd240b5ebb0ec9f2daea1126099e00a838dc86f" +dependencies = [ + "base16", + "digest", + "proc-macro2", + "quote", + "sha2", + "slab", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-rsx" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53128858f0ccca9de54292a4d48409fda1df75fd5012c6243f664042f0225d68" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "rustversion", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-server" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8adb2d4e0f0f3a157bda6af2d90f22bac40070e509a66e3ea58abf3b35f904c" +dependencies = [ + "anyhow", + "async-trait", + "axum", + "base64 0.22.1", + "bytes", + "chrono", + "ciborium", + "dashmap", + "dioxus-cli-config", + "dioxus-core", + "dioxus-core-macro", + "dioxus-devtools", + "dioxus-document", + "dioxus-fullstack-core", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-interpreter-js", + "dioxus-logger", + "dioxus-router", + "dioxus-signals", + "dioxus-ssr", + "enumset", + "futures", + "futures-channel", + "futures-util", + "generational-box", + "http", + "http-body-util", + "hyper", + "hyper-util", + "inventory", + "lru", + "parking_lot", + "pin-project", + "rustc-hash 2.1.1", + "serde", + "serde_json", + "serde_qs", + "subsecond", + "thiserror 2.0.18", + "tokio", + "tokio-tungstenite 0.27.0", + "tokio-util", + "tower", + "tower-http", + "tracing", + "tracing-futures", + "url", + "walkdir", +] + +[[package]] +name = "dioxus-signals" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f48020bc23bc9766e7cce986c0fd6de9af0b8cbfd432652ec6b1094439c1ec6" +dependencies = [ + "dioxus-core", + "futures-channel", + "futures-util", + "generational-box", + "parking_lot", + "rustc-hash 2.1.1", + "tracing", + "warnings", +] + +[[package]] +name = "dioxus-ssr" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44cf9294a21fcd1098e02ad7a3ba61b99be8310ad3395fecf8210387c83f26b9" +dependencies = [ + "askama_escape", + "dioxus-core", + "dioxus-core-types", + "rustc-hash 2.1.1", +] + +[[package]] +name = "dioxus-stores" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77aaa9ac56d781bb506cf3c0d23bea96b768064b89fe50d3b4d4659cc6bd8058" +dependencies = [ + "dioxus-core", + "dioxus-signals", + "dioxus-stores-macro", + "generational-box", +] + +[[package]] +name = "dioxus-stores-macro" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b1a728622e7b63db45774f75e71504335dd4e6115b235bbcff272980499493a" +dependencies = [ + "convert_case 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dioxus-web" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b33fe739fed4e8143dac222a9153593f8e2451662ce8fc4c9d167a9d6ec0923" +dependencies = [ + "dioxus-cli-config", + "dioxus-core", + "dioxus-core-types", + "dioxus-devtools", + "dioxus-document", + "dioxus-history", + "dioxus-html", + "dioxus-interpreter-js", + "dioxus-signals", + "futures-channel", + "futures-util", + "generational-box", + "gloo-timers", + "js-sys", + "lazy-js-bundle", + "rustc-hash 2.1.1", + "send_wrapper", + "serde", + "serde-wasm-bindgen", + "serde_json", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.4.2", + "web-sys", +] + +[[package]] +name = "dirs" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] + +[[package]] +name = "dispatch2" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" +dependencies = [ + "bitflags 2.11.0", + "block2", + "libc", + "objc2", +] + +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "dlopen2" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4" +dependencies = [ + "dlopen2_derive", + "libc", + "once_cell", + "winapi", +] + +[[package]] +name = "dlopen2_derive" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "document-features" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] + +[[package]] +name = "dpi" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" + +[[package]] +name = "dtoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" + +[[package]] +name = "dtoa-short" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" +dependencies = [ + "dtoa", +] + +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + +[[package]] +name = "dyn-clone" +version = "1.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + +[[package]] +name = "encoding_rs" +version = "0.8.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "enumset" +version = "1.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b07a8dfbbbfc0064c0a6bdf9edcf966de6b1c33ce344bdeca3b41615452634" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43e744e4ea338060faee68ed933e46e722fb7f3617e722a5772d7e856d8b3ce" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "esplora-client" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f19e3ea99dbfbef0c1ec26d83e69de0c579f6aa6aaac4f44597805fcc27e97af" +dependencies = [ + "bitcoin", + "hex-conservative", + "log", + "minreq", + "reqwest 0.12.28", + "serde", + "serde_json", + "tokio", +] + +[[package]] +name = "euclid" +version = "0.22.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df61bf483e837f88d5c2291dcf55c67be7e676b3a51acc48db3a7b163b91ed63" +dependencies = [ + "num-traits", + "serde", +] + +[[package]] +name = "eventsource-stream" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74fef4569247a5f429d9156b9d0a2599914385dd189c539334c625d8099d90ab" +dependencies = [ + "futures-core", + "nom", + "pin-project-lite", +] + +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + +[[package]] +name = "find-msvc-tools" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide", +] + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared 0.1.1", +] + +[[package]] +name = "foreign-types" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +dependencies = [ + "foreign-types-macros", + "foreign-types-shared 0.3.1", +] + +[[package]] +name = "foreign-types-macros" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[package]] +name = "foreign-types-shared" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + +[[package]] +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b147ee9d1f6d097cef9ce628cd2ee62288d963e16fb287bd9286455b241382d" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" + +[[package]] +name = "futures-executor" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf29c38818342a3b26b5b923639e7b1f4a61fc5e76102d4b1981c6dc7a7579d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" + +[[package]] +name = "futures-macro" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e835b70203e41293343137df5c0664546da5745f82ec9b84d40be8336958447b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "futures-sink" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" + +[[package]] +name = "futures-task" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "slab", +] + +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "gdk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", + "once_cell", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkwayland-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "140071d506d223f7572b9f09b5e155afbd77428cd5cc7af8f2694c41d98dfe69" +dependencies = [ + "gdk-sys", + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkx11-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e7445fe01ac26f11601db260dd8608fe172514eb63b3b5e261ea6b0f4428d" +dependencies = [ + "gdk-sys", + "glib-sys", + "libc", + "system-deps", + "x11", +] + +[[package]] +name = "generational-box" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4ed190b9de8e734d47a70be59b1e7588b9e8e0d0036e332f4c014e8aed1bc5" +dependencies = [ + "parking_lot", + "tracing", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gethostname" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" +dependencies = [ + "rustix", + "windows-link 0.2.1", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 5.3.0", + "wasip2", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0de51e6874e94e7bf76d726fc5d13ba782deca734ff60d5bb2fb2607c7406555" +dependencies = [ + "cfg-if", + "libc", + "r-efi 6.0.0", + "wasip2", + "wasip3", +] + +[[package]] +name = "gio" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "glib" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +dependencies = [ + "bitflags 2.11.0", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "once_cell", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "glib-macros" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" +dependencies = [ + "heck 0.4.1", + "proc-macro-crate 2.0.2", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "glib-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "glob" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" + +[[package]] +name = "global-hotkey" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9247516746aa8e53411a0db9b62b0e24efbcf6a76e0ba73e5a91b512ddabed7" +dependencies = [ + "crossbeam-channel", + "keyboard-types", + "objc2", + "objc2-app-kit", + "once_cell", + "thiserror 2.0.18", + "windows-sys 0.59.0", + "x11rb", + "xkeysym", +] + +[[package]] +name = "gloo-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06f627b1a58ca3d42b45d6104bf1e1a03799df472df00988b6ba21accc10580" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "http", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror 1.0.69", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-timers" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb143cf96099802033e0d4f4963b19fd2e0b728bcf076cd9cf7f6634f092994" +dependencies = [ + "futures-channel", + "futures-core", + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "gobject-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" +dependencies = [ + "glib-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gtk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" +dependencies = [ + "atk", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk3-macros" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "h2" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "serde", +] + +[[package]] +name = "hashbrown" +version = "0.15.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +dependencies = [ + "foldhash 0.1.5", +] + +[[package]] +name = "hashbrown" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash 0.2.0", +] + +[[package]] +name = "headers" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3314d5adb5d94bcdf56771f2e50dbbc80bb4bdf88967526706205ac9eff24eb" +dependencies = [ + "base64 0.22.1", + "bytes", + "headers-core", + "http", + "httpdate", + "mime", + "sha1", +] + +[[package]] +name = "headers-core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54b4a22553d4242c49fddb9ba998a99962b5cc6f22cb5a3482bec22522403ce4" +dependencies = [ + "http", +] + +[[package]] +name = "heck" +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 = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" + +[[package]] +name = "hex-conservative" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fda06d18ac606267c40c04e41b9947729bf8b9efe74bd4e82b61a5f26a510b9f" +dependencies = [ + "arrayvec", +] + +[[package]] +name = "hex_lit" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3011d1213f159867b13cfd6ac92d2cd5f1345762c63be3554e84092d85a50bbd" + +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + +[[package]] +name = "html5ever" +version = "0.29.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" +dependencies = [ + "log", + "mac", + "markup5ever", + "match_token", +] + +[[package]] +name = "http" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" +dependencies = [ + "bytes", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "http-range-header" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c" + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls 0.23.37", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots 1.0.6", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" +dependencies = [ + "base64 0.22.1", + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "system-configuration", + "tokio", + "tower-layer", + "tower-service", + "tracing", + "windows-registry", +] + +[[package]] +name = "iana-time-zone" +version = "0.1.65" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "log", + "wasm-bindgen", + "windows-core 0.62.2", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "id-arena" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "if_chain" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd62e6b5e86ea8eeeb8db1de02880a6abc01a397b2ebb64b5d74ac255318f5cb" + +[[package]] +name = "indexmap" +version = "2.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +dependencies = [ + "equivalent", + "hashbrown 0.16.1", + "serde", + "serde_core", +] + +[[package]] +name = "indoc" +version = "2.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +dependencies = [ + "rustversion", +] + +[[package]] +name = "infer" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" +dependencies = [ + "cfb", +] + +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "block-padding", + "generic-array", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "inventory" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "009ae045c87e7082cb72dab0ccd01ae075dd00141ddc108f43a0ea150a9e7227" +dependencies = [ + "rustversion", +] + +[[package]] +name = "ipnet" +version = "2.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" + +[[package]] +name = "iri-string" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +dependencies = [ + "memchr", + "serde", +] + +[[package]] +name = "itoa" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" + +[[package]] +name = "javascriptcore-rs" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" +dependencies = [ + "bitflags 1.3.2", + "glib", + "javascriptcore-rs-sys", +] + +[[package]] +name = "javascriptcore-rs-sys" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + +[[package]] +name = "js-sys" +version = "0.3.91" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +dependencies = [ + "once_cell", + "wasm-bindgen", +] + +[[package]] +name = "keyboard-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +dependencies = [ + "bitflags 2.11.0", + "serde", + "unicode-segmentation", +] + +[[package]] +name = "kuchikiki" +version = "0.8.8-speedreader" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2" +dependencies = [ + "cssparser", + "html5ever", + "indexmap", + "selectors", +] + +[[package]] +name = "lazy-js-bundle" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7b88b715ab1496c6e6b8f5e927be961c4235196121b6ae59bcb51077a21dd36" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leb128fmt" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" + +[[package]] +name = "libappindicator" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a" +dependencies = [ + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", +] + +[[package]] +name = "libappindicator-sys" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" +dependencies = [ + "gtk-sys", + "libloading 0.7.4", + "once_cell", +] + +[[package]] +name = "libc" +version = "0.2.182" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" + +[[package]] +name = "libloading" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" +dependencies = [ + "cfg-if", + "winapi", +] + +[[package]] +name = "libloading" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" +dependencies = [ + "cfg-if", + "windows-link 0.2.1", +] + +[[package]] +name = "libredox" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" +dependencies = [ + "libc", +] + +[[package]] +name = "libxdo" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00333b8756a3d28e78def82067a377de7fa61b24909000aeaa2b446a948d14db" +dependencies = [ + "libxdo-sys", +] + +[[package]] +name = "libxdo-sys" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db23b9e7e2b7831bbd8aac0bbeeeb7b68cbebc162b227e7052e8e55829a09212" +dependencies = [ + "libc", + "x11", +] + +[[package]] +name = "linux-raw-sys" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" + +[[package]] +name = "litemap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" + +[[package]] +name = "litrs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" + +[[package]] +name = "longest-increasing-subsequence" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" + +[[package]] +name = "lru" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1dc47f592c06f33f8e3aea9591776ec7c9f9e4124778ff8a3c3b87159f7e593" +dependencies = [ + "hashbrown 0.16.1", +] + +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + +[[package]] +name = "manganis" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cce7d688848bf9d034168513b9a2ffbfe5f61df2ff14ae15e6cfc866efdd344" +dependencies = [ + "const-serialize 0.7.2", + "const-serialize 0.8.0-alpha.0", + "manganis-core", + "manganis-macro", +] + +[[package]] +name = "manganis-core" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "84ce917b978268fe8a7db49e216343ec7c8f471f7e686feb70940d67293f19d4" +dependencies = [ + "const-serialize 0.7.2", + "const-serialize 0.8.0-alpha.0", + "dioxus-cli-config", + "dioxus-core-types", + "serde", + "winnow 0.7.15", +] + +[[package]] +name = "manganis-macro" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad513e990f7c0bca86aa68659a7a3dc4c705572ed4c22fd6af32ccf261334cc2" +dependencies = [ + "dunce", + "macro-string", + "manganis-core", + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "markup5ever" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18" +dependencies = [ + "log", + "phf 0.11.3", + "phf_codegen 0.11.3", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "match_token" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "matchers" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +dependencies = [ + "regex-automata", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + +[[package]] +name = "memchr" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" + +[[package]] +name = "memfd" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" +dependencies = [ + "rustix", +] + +[[package]] +name = "memmap2" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" +dependencies = [ + "libc", ] [[package]] -name = "icu_normalizer" -version = "2.1.1" +name = "memoffset" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" dependencies = [ - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "zerovec", + "autocfg", ] [[package]] -name = "icu_normalizer_data" -version = "2.1.1" +name = "mime" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] -name = "icu_properties" -version = "2.1.2" +name = "mime_guess" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ - "icu_collections", - "icu_locale_core", - "icu_properties_data", - "icu_provider", - "zerotrie", - "zerovec", + "mime", + "unicase", ] [[package]] -name = "icu_properties_data" -version = "2.1.2" +name = "minimal-lexical" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] -name = "icu_provider" -version = "2.1.1" +name = "miniscript" +version = "12.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +checksum = "487906208f38448e186e3deb02f2b8ef046a9078b0de00bdb28bf4fb9b76951c" dependencies = [ - "displaydoc", - "icu_locale_core", - "writeable", - "yoke", - "zerofrom", - "zerotrie", - "zerovec", + "bech32", + "bitcoin", + "serde", ] [[package]] -name = "id-arena" -version = "2.3.0" +name = "miniz_oxide" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] [[package]] -name = "idna" -version = "1.1.0" +name = "minreq" +version = "2.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +checksum = "05015102dad0f7d61691ca347e9d9d9006685a64aefb3d79eecf62665de2153d" dependencies = [ - "idna_adapter", - "smallvec", - "utf8_iter", + "base64 0.22.1", + "rustls 0.21.12", + "rustls-webpki 0.101.7", + "serde", + "serde_json", + "webpki-roots 0.25.4", ] [[package]] -name = "idna_adapter" -version = "1.2.1" +name = "mio" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" dependencies = [ - "icu_normalizer", - "icu_properties", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "windows-sys 0.61.2", ] [[package]] -name = "if_chain" -version = "1.0.3" +name = "muda" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd62e6b5e86ea8eeeb8db1de02880a6abc01a397b2ebb64b5d74ac255318f5cb" +checksum = "01c1738382f66ed56b3b9c8119e794a2e23148ac8ea214eda86622d4cb9d415a" +dependencies = [ + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "libxdo", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "once_cell", + "png", + "thiserror 2.0.18", + "windows-sys 0.60.2", +] [[package]] -name = "indexmap" -version = "2.13.0" +name = "multer" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" dependencies = [ - "equivalent", - "hashbrown 0.16.1", - "serde", - "serde_core", + "bytes", + "encoding_rs", + "futures-util", + "http", + "httparse", + "memchr", + "mime", + "spin", + "version_check", ] [[package]] -name = "indoc" -version = "2.0.7" +name = "nanoid" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" dependencies = [ - "rustversion", + "rand 0.8.5", ] [[package]] -name = "ipnet" -version = "2.12.0" +name = "native-tls" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] [[package]] -name = "iri-string" -version = "0.7.10" +name = "ndk" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c91338f0783edbd6195decb37bae672fd3b165faffb89bf7b9e6942f8b1a731a" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "memchr", - "serde", + "bitflags 2.11.0", + "jni-sys", + "log", + "ndk-sys", + "num_enum", + "raw-window-handle 0.6.2", + "thiserror 1.0.69", ] [[package]] -name = "itoa" -version = "1.0.17" +name = "ndk-context" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] -name = "jni" -version = "0.21.1" +name = "ndk-sys" +version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ - "cesu8", - "cfg-if", - "combine", "jni-sys", - "log", - "thiserror 1.0.69", - "walkdir", - "windows-sys 0.45.0", ] [[package]] -name = "jni-sys" -version = "0.3.0" +name = "negentropy" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +checksum = "f0efe882e02d206d8d279c20eb40e03baf7cb5136a1476dc084a324fbc3ec42d" [[package]] -name = "jobserver" -version = "0.1.34" +name = "new_debug_unreachable" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" -dependencies = [ - "getrandom 0.3.4", - "libc", -] +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] -name = "js-sys" -version = "0.3.91" +name = "nodrop" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b49715b7073f385ba4bc528e5747d02e66cb39c6146efb66b781f131f0fb399c" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ - "once_cell", - "wasm-bindgen", + "memchr", + "minimal-lexical", ] [[package]] -name = "lazy_static" -version = "1.5.0" +name = "nostr" +version = "0.44.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "3aa5e3b6a278ed061835fe1ee293b71641e6bf8b401cfe4e1834bbf4ef0a34e1" +dependencies = [ + "aes", + "base64 0.22.1", + "bech32", + "bip39", + "bitcoin_hashes", + "cbc", + "chacha20", + "chacha20poly1305", + "getrandom 0.2.17", + "hex", + "instant", + "scrypt", + "secp256k1", + "serde", + "serde_json", + "unicode-normalization", + "url", +] [[package]] -name = "leb128fmt" -version = "0.1.0" +name = "nostr-database" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" +checksum = "7462c9d8ae5ef6a28d66a192d399ad2530f1f2130b13186296dbb11bdef5b3d1" +dependencies = [ + "lru", + "nostr", + "tokio", +] [[package]] -name = "libc" -version = "0.2.182" +name = "nostr-gossip" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "ade30de16869618919c6b5efc8258f47b654a98b51541eb77f85e8ec5e3c83a6" +dependencies = [ + "nostr", +] [[package]] -name = "libredox" -version = "0.1.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1744e39d1d6a9948f4f388969627434e31128196de472883b39f148769bfe30a" +name = "nostr-lib" +version = "0.1.0" dependencies = [ - "libc", + "dcosl-core", + "nostr-sdk", + "phoenixd-lib", + "serde", + "serde_json", + "thiserror 2.0.18", + "tokio", + "tracing", ] [[package]] -name = "linux-raw-sys" -version = "0.12.1" +name = "nostr-relay-pool" +version = "0.44.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +checksum = "4b1073ccfbaea5549fb914a9d52c68dab2aecda61535e5143dd73e95445a804b" +dependencies = [ + "async-utility", + "async-wsocket", + "atomic-destructor", + "hex", + "lru", + "negentropy", + "nostr", + "nostr-database", + "tokio", + "tracing", +] [[package]] -name = "litemap" -version = "0.8.1" +name = "nostr-sdk" +version = "0.44.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +checksum = "471732576710e779b64f04c55e3f8b5292f865fea228436daf19694f0bf70393" +dependencies = [ + "async-utility", + "nostr", + "nostr-database", + "nostr-gossip", + "nostr-relay-pool", + "tokio", + "tracing", +] [[package]] -name = "lock_api" -version = "0.4.14" +name = "nu-ansi-term" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "scopeguard", + "windows-sys 0.61.2", ] [[package]] -name = "log" -version = "0.4.29" +name = "num-conv" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +checksum = "cf97ec579c3c42f953ef76dbf8d55ac91fb219dde70e49aa4a6b7d74e9919050" [[package]] -name = "lru-slab" -version = "0.1.2" +name = "num-traits" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] [[package]] -name = "matchers" -version = "0.2.0" +name = "num_enum" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +checksum = "b1207a7e20ad57b847bbddc6776b968420d38292bbfe2089accff5e19e82454c" dependencies = [ - "regex-automata", + "num_enum_derive", + "rustversion", ] [[package]] -name = "memchr" -version = "2.8.0" +name = "num_enum_derive" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +checksum = "ff32365de1b6743cb203b710788263c44a03de03802daf96092f2da4fe6ba4d7" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro2", + "quote", + "syn 2.0.117", +] [[package]] -name = "mime" -version = "0.3.17" +name = "objc" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] [[package]] -name = "mime_guess" -version = "2.0.5" +name = "objc2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +checksum = "3a12a8ed07aefc768292f076dc3ac8c48f3781c8f2d5851dd3d98950e8c5a89f" dependencies = [ - "mime", - "unicase", + "objc2-encode", + "objc2-exception-helper", ] [[package]] -name = "minimal-lexical" -version = "0.2.1" +name = "objc2-app-kit" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" +dependencies = [ + "bitflags 2.11.0", + "block2", + "objc2", + "objc2-core-foundation", + "objc2-foundation", +] [[package]] -name = "miniscript" -version = "12.3.5" +name = "objc2-core-foundation" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487906208f38448e186e3deb02f2b8ef046a9078b0de00bdb28bf4fb9b76951c" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ - "bech32", - "bitcoin", - "serde", + "bitflags 2.11.0", + "dispatch2", + "objc2", ] [[package]] -name = "minreq" -version = "2.14.1" +name = "objc2-core-graphics" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05015102dad0f7d61691ca347e9d9d9006685a64aefb3d79eecf62665de2153d" +checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ - "base64 0.22.1", - "rustls 0.21.12", - "rustls-webpki 0.101.7", - "serde", - "serde_json", - "webpki-roots", + "bitflags 2.11.0", + "objc2-core-foundation", ] [[package]] -name = "mio" -version = "1.1.1" +name = "objc2-encode" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" -dependencies = [ - "libc", - "wasi", - "windows-sys 0.61.2", -] +checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] -name = "nanoid" -version = "0.4.0" +name = "objc2-exception-helper" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ffa00dec017b5b1a8b7cf5e2c008bfda1aa7e0697ac1508b491fdf2622fb4d8" +checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a" dependencies = [ - "rand 0.8.5", + "cc", ] [[package]] -name = "native-tls" -version = "0.2.18" +name = "objc2-foundation" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" +checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", + "bitflags 2.11.0", + "block2", + "objc2", + "objc2-core-foundation", ] [[package]] -name = "nom" -version = "7.1.3" +name = "objc2-ui-kit" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ - "memchr", - "minimal-lexical", + "bitflags 2.11.0", + "objc2", + "objc2-core-foundation", + "objc2-foundation", ] [[package]] -name = "nu-ansi-term" -version = "0.50.3" +name = "objc2-web-kit" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" +checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "windows-sys 0.61.2", + "bitflags 2.11.0", + "block2", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", ] [[package]] -name = "num-traits" -version = "0.2.19" +name = "objc_id" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" dependencies = [ - "autocfg", + "objc", ] [[package]] @@ -1340,15 +4069,21 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "opaque-debug" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" + [[package]] name = "openssl" version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags", + "bitflags 2.11.0", "cfg-if", - "foreign-types", + "foreign-types 0.3.2", "libc", "once_cell", "openssl-macros", @@ -1363,7 +4098,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1399,6 +4134,31 @@ dependencies = [ "num-traits", ] +[[package]] +name = "pango" +version = "0.18.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" +dependencies = [ + "gio", + "glib", + "libc", + "once_cell", + "pango-sys", +] + +[[package]] +name = "pango-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + [[package]] name = "parking_lot" version = "0.12.5" @@ -1419,7 +4179,28 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "password-hash" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166" +dependencies = [ + "base64ct", + "rand_core 0.6.4", + "subtle", +] + +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", ] [[package]] @@ -1428,6 +4209,126 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "phf" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" +dependencies = [ + "phf_shared 0.8.0", +] + +[[package]] +name = "phf" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" +dependencies = [ + "phf_macros", + "phf_shared 0.10.0", + "proc-macro-hack", +] + +[[package]] +name = "phf" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_shared 0.11.3", +] + +[[package]] +name = "phf_codegen" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" +dependencies = [ + "phf_generator 0.8.0", + "phf_shared 0.8.0", +] + +[[package]] +name = "phf_codegen" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared 0.8.0", + "rand 0.7.3", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.5", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared 0.11.3", + "rand 0.8.5", +] + +[[package]] +name = "phf_macros" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher 1.0.2", +] + [[package]] name = "phoenixd-agcli" version = "0.1.0" @@ -1466,7 +4367,7 @@ checksum = "d9b20ed30f105399776b9c883e68e536ef602a16ae6f596d2c473591d6ad64c6" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1487,6 +4388,36 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "png" +version = "0.17.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide", +] + +[[package]] +name = "pollster" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" + +[[package]] +name = "poly1305" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8159bd90725d2df49889a078b54f4f79e87f1f8a8444194cdca81d38f5393abf" +dependencies = [ + "cpufeatures", + "opaque-debug", + "universal-hash", +] + [[package]] name = "potential_utf" version = "0.1.4" @@ -1496,6 +4427,12 @@ dependencies = [ "zerovec", ] +[[package]] +name = "powerfmt" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -1506,32 +4443,106 @@ dependencies = [ ] [[package]] -name = "prettyplease" -version = "0.2.37" +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + +[[package]] +name = "prettyplease" +version = "0.2.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +dependencies = [ + "proc-macro2", + "syn 2.0.117", +] + +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime", + "toml_edit 0.20.2", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479ca8adacdd7ce8f1fb39ce9ecccbfe93a3f1344b3d0d97f20bc0196208f62b" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", - "syn", + "quote", + "syn 2.0.117", + "version_check", ] [[package]] -name = "proc-macro-crate" -version = "1.3.1" +name = "psl-types" +version = "2.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" -dependencies = [ - "once_cell", - "toml_edit", -] +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" [[package]] -name = "proc-macro2" -version = "1.0.106" +name = "publicsuffix" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "6f42ea446cab60335f76979ec15e12619a2165b5ae2c12166bef27d283a9fadf" dependencies = [ - "unicode-ident", + "idna", + "psl-types", ] [[package]] @@ -1545,7 +4556,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash", + "rustc-hash 2.1.1", "rustls 0.23.37", "socket2", "thiserror 2.0.18", @@ -1566,7 +4577,7 @@ dependencies = [ "lru-slab", "rand 0.9.2", "ring", - "rustc-hash", + "rustc-hash 2.1.1", "rustls 0.23.37", "rustls-pki-types", "slab", @@ -1611,6 +4622,20 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "rand" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg", +] + [[package]] name = "rand" version = "0.8.5" @@ -1632,6 +4657,16 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -1652,6 +4687,15 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + [[package]] name = "rand_core" version = "0.6.4" @@ -1670,13 +4714,43 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", +] + +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + +[[package]] +name = "raw-window-handle" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" + [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags", + "bitflags 2.11.0", ] [[package]] @@ -1707,7 +4781,7 @@ checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -1735,8 +4809,11 @@ checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" dependencies = [ "base64 0.22.1", "bytes", + "cookie", + "cookie_store", "encoding_rs", "futures-core", + "futures-util", "h2", "http", "http-body", @@ -1748,9 +4825,12 @@ dependencies = [ "js-sys", "log", "mime", + "mime_guess", "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls 0.23.37", "rustls-pki-types", "serde", "serde_json", @@ -1758,13 +4838,17 @@ dependencies = [ "sync_wrapper", "tokio", "tokio-native-tls", + "tokio-rustls", + "tokio-util", "tower", "tower-http", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", + "wasm-streams 0.4.2", "web-sys", + "webpki-roots 1.0.6", ] [[package]] @@ -1807,8 +4891,32 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.5.0", + "web-sys", +] + +[[package]] +name = "rfd" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20dafead71c16a34e1ff357ddefc8afc11e7d51d6d2b9fbd07eaa48e3e540220" +dependencies = [ + "block2", + "dispatch2", + "js-sys", + "libc", + "log", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "percent-encoding", + "pollster", + "raw-window-handle 0.6.2", + "wasm-bindgen", + "wasm-bindgen-futures", "web-sys", + "windows-sys 0.61.2", ] [[package]] @@ -1850,13 +4958,13 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b6d9818c9cb13d00664b52fd3e47b0554bc2d5c59cfb90340dd9411b09553bc" dependencies = [ - "convert_case", + "convert_case 0.10.0", "deluxe", "indoc", "proc-macro2", "quote", "serde_json", - "syn", + "syn 2.0.117", ] [[package]] @@ -1873,19 +4981,34 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ - "bitflags", + "bitflags 2.11.0", "errno", "libc", "linux-raw-sys", @@ -1912,6 +5035,7 @@ checksum = "758025cb5fccfd3bc2fd74708fd4682be41d99e5dff73c377c0646c6012c73a4" dependencies = [ "aws-lc-rs", "once_cell", + "ring", "rustls-pki-types", "rustls-webpki 0.103.9", "subtle", @@ -2001,6 +5125,15 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +[[package]] +name = "salsa20" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" +dependencies = [ + "cipher", +] + [[package]] name = "same-file" version = "1.0.6" @@ -2041,7 +5174,7 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn", + "syn 2.0.117", ] [[package]] @@ -2050,6 +5183,18 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "scrypt" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" +dependencies = [ + "password-hash", + "pbkdf2", + "salsa20", + "sha2", +] + [[package]] name = "sct" version = "0.7.1" @@ -2087,7 +5232,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags", + "bitflags 2.11.0", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -2104,12 +5249,39 @@ dependencies = [ "libc", ] +[[package]] +name = "selectors" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416" +dependencies = [ + "bitflags 1.3.2", + "cssparser", + "derive_more 0.99.20", + "fxhash", + "log", + "phf 0.8.0", + "phf_codegen 0.8.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + [[package]] name = "semver" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2" +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" +dependencies = [ + "futures-core", +] + [[package]] name = "serde" version = "1.0.228" @@ -2120,6 +5292,17 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde_core" version = "1.0.228" @@ -2137,7 +5320,7 @@ checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2148,7 +5331,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2164,6 +5347,48 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +dependencies = [ + "itoa", + "serde", + "serde_core", +] + +[[package]] +name = "serde_qs" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3faaf9e727533a19351a43cc5a8de957372163c7d35cc48c90b75cdda13c352" +dependencies = [ + "percent-encoding", + "serde", + "thiserror 2.0.18", +] + +[[package]] +name = "serde_repr" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175ee3e80ae9982737ca543e96133087cbd9a485eecc3bc4de9c1a37b47ea59c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -2176,6 +5401,38 @@ dependencies = [ "serde", ] +[[package]] +name = "servo_arc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741" +dependencies = [ + "nodrop", + "stable_deref_trait", +] + +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "sha2" +version = "0.10.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -2191,43 +5448,167 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + [[package]] name = "signal-hook-registry" version = "1.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "siphasher" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2aa850e253778c88a04c3d7323b043aeda9d3e30d5971937c1855769763678e" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "sledgehammer_bindgen" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e83e178d176459c92bc129cfd0958afac3ced925471b889b3a75546cfc4133" +dependencies = [ + "sledgehammer_bindgen_macro", + "wasm-bindgen", +] + +[[package]] +name = "sledgehammer_bindgen_macro" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb251b407f50028476a600541542b605bb864d35d9ee1de4f6cab45d88475e6d" +dependencies = [ + "quote", + "syn 2.0.117", +] + +[[package]] +name = "sledgehammer_utils" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "debdd4b83524961983cea3c55383b3910fd2f24fd13a188f5b091d2d504a61ae" +dependencies = [ + "rustc-hash 1.1.0", +] + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "serde", + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "socket2" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "soup3" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f" +dependencies = [ + "futures-channel", + "gio", + "glib", + "libc", + "soup3-sys", +] + +[[package]] +name = "soup3-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27" dependencies = [ - "errno", + "gio-sys", + "glib-sys", + "gobject-sys", "libc", + "system-deps", ] [[package]] -name = "slab" -version = "0.4.12" +name = "spin" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" [[package]] -name = "smallvec" -version = "1.15.1" +name = "stable_deref_trait" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] -name = "socket2" -version = "0.6.3" +name = "string_cache" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ - "libc", - "windows-sys 0.61.2", + "new_debug_unreachable", + "parking_lot", + "phf_shared 0.11.3", + "precomputed-hash", + "serde", ] [[package]] -name = "stable_deref_trait" -version = "1.2.1" +name = "string_cache_codegen" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", +] [[package]] name = "strsim" @@ -2235,12 +5616,51 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +[[package]] +name = "subsecond" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8438668e545834d795d04c4335aafc332ce046106521a29f0a5c6501de34187c" +dependencies = [ + "js-sys", + "libc", + "libloading 0.8.9", + "memfd", + "memmap2", + "serde", + "subsecond-types", + "thiserror 2.0.18", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "subsecond-types" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e72f747606fc19fe81d6c59e491af93ed7dcbcb6aad9d1d18b05129914ec298" +dependencies = [ + "serde", +] + [[package]] name = "subtle" version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + [[package]] name = "syn" version = "2.0.117" @@ -2269,7 +5689,7 @@ checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2278,7 +5698,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags", + "bitflags 2.11.0", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -2293,6 +5713,75 @@ dependencies = [ "libc", ] +[[package]] +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck 0.5.0", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "tao" +version = "0.34.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d52c379e63da659a483a958110bbde891695a0ecb53e48cc7786d5eda7bb" +dependencies = [ + "bitflags 2.11.0", + "block2", + "core-foundation 0.10.1", + "core-graphics 0.25.0", + "crossbeam-channel", + "dispatch2", + "dlopen2", + "dpi", + "gdkwayland-sys", + "gdkx11-sys", + "gtk", + "jni", + "libc", + "log", + "ndk", + "ndk-context", + "ndk-sys", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "once_cell", + "parking_lot", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", + "tao-macros", + "unicode-segmentation", + "url", + "windows", + "windows-core 0.61.2", + "windows-version", + "x11-dl", +] + +[[package]] +name = "tao-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4e16beb8b2ac17db28eab8bca40e62dbfbb34c0fcdc6d9826b11b7b5d047dfd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "target-lexicon" +version = "0.12.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" + [[package]] name = "tempfile" version = "3.26.0" @@ -2306,6 +5795,17 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -2332,7 +5832,7 @@ checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2343,7 +5843,7 @@ checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2355,6 +5855,37 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "time" +version = "0.3.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "743bd48c283afc0388f9b8827b976905fb217ad9e647fae3a379a9283c4def2c" +dependencies = [ + "deranged", + "itoa", + "num-conv", + "powerfmt", + "serde_core", + "time-core", + "time-macros", +] + +[[package]] +name = "time-core" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7694e1cfe791f8d31026952abf09c69ca6f6fa4e1a1229e18988f06a04a12dca" + +[[package]] +name = "time-macros" +version = "0.2.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e70e4c5a0e0a8a4823ad65dfe1a6930e4f4d756dcd9dd7939022b5e8c501215" +dependencies = [ + "num-conv", + "time-core", +] + [[package]] name = "tinystr" version = "0.8.2" @@ -2405,7 +5936,7 @@ checksum = "5c55a2eff8b69ce66c84f85e1da1c233edc36ceb85a2058d11b0d6a3c7e7569c" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2428,6 +5959,70 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-socks" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d4770b8024672c1101b3f6733eab95b18007dbe0847a8afe341fcf79e06043f" +dependencies = [ + "either", + "futures-util", + "thiserror 1.0.69", + "tokio", +] + +[[package]] +name = "tokio-stream" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", + "tokio-util", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084" +dependencies = [ + "futures-util", + "log", + "rustls 0.23.37", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tungstenite 0.26.2", + "webpki-roots 0.26.11", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "489a59b6730eda1b0171fcfda8b121f4bee2b35cba8645ca35c5f7ba3eb736c1" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite 0.27.0", +] + +[[package]] +name = "tokio-tungstenite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d25a406cddcc431a75d3d9afc6a7c0f7428d4891dd973e4d54c56b46127bf857" +dependencies = [ + "futures-util", + "log", + "tokio", + "tungstenite 0.28.0", +] + [[package]] name = "tokio-util" version = "0.7.18" @@ -2436,16 +6031,33 @@ checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", + "futures-util", "pin-project-lite", "tokio", ] +[[package]] +name = "toml" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.2", +] + [[package]] name = "toml_datetime" -version = "0.6.11" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", +] [[package]] name = "toml_edit" @@ -2455,7 +6067,20 @@ checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ "indexmap", "toml_datetime", - "winnow", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.5.40", ] [[package]] @@ -2471,6 +6096,7 @@ dependencies = [ "tokio", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -2479,16 +6105,26 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags", + "bitflags 2.11.0", "bytes", + "futures-core", "futures-util", "http", "http-body", + "http-body-util", + "http-range-header", + "httpdate", "iri-string", + "mime", + "mime_guess", + "percent-encoding", "pin-project-lite", + "tokio", + "tokio-util", "tower", "tower-layer", "tower-service", + "tracing", ] [[package]] @@ -2509,6 +6145,7 @@ version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2522,7 +6159,7 @@ checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -2576,12 +6213,105 @@ dependencies = [ "tracing-log", ] +[[package]] +name = "tracing-wasm" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07" +dependencies = [ + "tracing", + "tracing-subscriber", + "wasm-bindgen", +] + +[[package]] +name = "tray-icon" +version = "0.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e85aa143ceb072062fc4d6356c1b520a51d636e7bc8e77ec94be3608e5e80c" +dependencies = [ + "crossbeam-channel", + "dirs", + "libappindicator", + "muda", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation", + "once_cell", + "png", + "thiserror 2.0.18", + "windows-sys 0.60.2", +] + [[package]] name = "try-lock" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tungstenite" +version = "0.26.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.9.2", + "rustls 0.23.37", + "rustls-pki-types", + "sha1", + "thiserror 2.0.18", + "utf-8", +] + +[[package]] +name = "tungstenite" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "native-tls", + "rand 0.9.2", + "rustls 0.23.37", + "sha1", + "thiserror 2.0.18", + "utf-8", +] + +[[package]] +name = "tungstenite" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand 0.9.2", + "sha1", + "thiserror 2.0.18", + "utf-8", +] + +[[package]] +name = "typenum" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "562d481066bde0658276a35467c4af00bdc6ee726305698a55b86e61d7ad82bb" + [[package]] name = "unicase" version = "2.9.0" @@ -2615,6 +6345,16 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" +[[package]] +name = "universal-hash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc1de2c688dc15305988b563c3854064043356019f97a4b46276fe734c4f07ea" +dependencies = [ + "crypto-common", + "subtle", +] + [[package]] name = "untrusted" version = "0.9.0" @@ -2631,13 +6371,30 @@ dependencies = [ "idna", "percent-encoding", "serde", + "serde_derive", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8_iter" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + +[[package]] +name = "uuid" +version = "1.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a68d3c8f01c0cfa54a75291d83601161799e4a89a39e0929f4b0354d88757a37" +dependencies = [ + "js-sys", + "wasm-bindgen", +] [[package]] name = "valuable" @@ -2651,6 +6408,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version-compare" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" + [[package]] name = "version_check" version = "0.9.5" @@ -2676,6 +6439,34 @@ dependencies = [ "try-lock", ] +[[package]] +name = "warnings" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f68998838dab65727c9b30465595c6f7c953313559371ca8bf31759b3680ad" +dependencies = [ + "pin-project", + "tracing", + "warnings-macro", +] + +[[package]] +name = "warnings-macro" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59195a1db0e95b920366d949ba5e0d3fc0e70b67c09be15ce5abb790106b0571" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -2746,7 +6537,7 @@ dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wasm-bindgen-shared", ] @@ -2781,6 +6572,19 @@ dependencies = [ "wasmparser", ] +[[package]] +name = "wasm-streams" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + [[package]] name = "wasm-streams" version = "0.5.0" @@ -2800,7 +6604,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags", + "bitflags 2.11.0", "hashbrown 0.15.5", "indexmap", "semver", @@ -2826,6 +6630,66 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webbrowser" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f00bb839c1cf1e3036066614cbdcd035ecf215206691ea646aa3c60a24f68f2" +dependencies = [ + "core-foundation 0.10.1", + "jni", + "log", + "ndk-context", + "objc2", + "objc2-foundation", + "url", + "web-sys", +] + +[[package]] +name = "webkit2gtk" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "soup3", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c" +dependencies = [ + "bitflags 1.3.2", + "cairo-sys-rs", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pkg-config", + "soup3-sys", + "system-deps", +] + [[package]] name = "webpki-root-certs" version = "1.0.6" @@ -2841,6 +6705,76 @@ version = "0.25.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" +[[package]] +name = "webpki-roots" +version = "0.26.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9" +dependencies = [ + "webpki-roots 1.0.6", +] + +[[package]] +name = "webpki-roots" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22cfaf3c063993ff62e73cb4311efde4db1efb31ab78a3e5c457939ad5cc0bed" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "webview2-com" +version = "0.38.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a" +dependencies = [ + "webview2-com-macros", + "webview2-com-sys", + "windows", + "windows-core 0.61.2", + "windows-implement", + "windows-interface", +] + +[[package]] +name = "webview2-com-macros" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "webview2-com-sys" +version = "0.38.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" +dependencies = [ + "thiserror 2.0.18", + "windows", + "windows-core 0.61.2", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.11" @@ -2850,21 +6784,133 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections", + "windows-core 0.61.2", + "windows-future", + "windows-link 0.1.3", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", +] + +[[package]] +name = "windows-core" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading", +] + +[[package]] +name = "windows-implement" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-interface" +version = "0.59.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + [[package]] name = "windows-registry" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "02752bf7fbdcce7f2a27a742f798510f3e5ad88dbe84871e5168e2120c3d5720" dependencies = [ - "windows-link", - "windows-result", - "windows-strings", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", ] [[package]] @@ -2873,7 +6919,16 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", ] [[package]] @@ -2882,7 +6937,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -2903,6 +6958,15 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.60.2" @@ -2918,7 +6982,7 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -2958,7 +7022,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link", + "windows-link 0.2.1", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", @@ -2969,6 +7033,24 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + +[[package]] +name = "windows-version" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" +dependencies = [ + "windows-link 0.2.1", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -3116,6 +7198,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", +] + [[package]] name = "wit-bindgen" version = "0.51.0" @@ -3146,7 +7237,7 @@ dependencies = [ "heck 0.5.0", "indexmap", "prettyplease", - "syn", + "syn 2.0.117", "wasm-metadata", "wit-bindgen-core", "wit-component", @@ -3162,7 +7253,7 @@ dependencies = [ "prettyplease", "proc-macro2", "quote", - "syn", + "syn 2.0.117", "wit-bindgen-core", "wit-bindgen-rust", ] @@ -3174,7 +7265,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags", + "bitflags 2.11.0", "indexmap", "log", "serde", @@ -3210,6 +7301,99 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +[[package]] +name = "wry" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728b7d4c8ec8d81cab295e0b5b8a4c263c0d41a785fb8f8c4df284e5411140a2" +dependencies = [ + "base64 0.22.1", + "block2", + "cookie", + "crossbeam-channel", + "dirs", + "dpi", + "dunce", + "gtk", + "html5ever", + "http", + "javascriptcore-rs", + "jni", + "kuchikiki", + "libc", + "ndk", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "objc2-ui-kit", + "objc2-web-kit", + "once_cell", + "percent-encoding", + "raw-window-handle 0.6.2", + "sha2", + "soup3", + "tao-macros", + "thiserror 2.0.18", + "url", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows", + "windows-core 0.61.2", + "windows-version", +] + +[[package]] +name = "x11" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" +dependencies = [ + "libc", + "pkg-config", +] + +[[package]] +name = "x11-dl" +version = "2.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38735924fedd5314a6e548792904ed8c6de6636285cb9fec04d5b1db85c1516f" +dependencies = [ + "libc", + "once_cell", + "pkg-config", +] + +[[package]] +name = "x11rb" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" +dependencies = [ + "gethostname", + "rustix", + "x11rb-protocol", +] + +[[package]] +name = "x11rb-protocol" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" + +[[package]] +name = "xkeysym" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" + +[[package]] +name = "xxhash-rust" +version = "0.8.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3" + [[package]] name = "yoke" version = "0.8.1" @@ -3229,7 +7413,7 @@ checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", "synstructure", ] @@ -3250,7 +7434,7 @@ checksum = "f65c489a7071a749c849713807783f70672b28094011623e200cb86dcb835953" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] @@ -3270,7 +7454,7 @@ checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", "synstructure", ] @@ -3310,7 +7494,7 @@ checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" dependencies = [ "proc-macro2", "quote", - "syn", + "syn 2.0.117", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a303a9b..8feca9f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,15 @@ [workspace] resolver = "2" members = ["crates/*"] +# Exclude carpet-ui from default workspace checks — it needs platform-specific features +default-members = [ + "crates/bdk-lib", + "crates/bdk-agcli", + "crates/phoenixd-lib", + "crates/phoenixd-agcli", + "crates/carpet-agent", + "crates/nostr-lib", +] [workspace.package] edition = "2024" diff --git a/crates/carpet-ui/Cargo.toml b/crates/carpet-ui/Cargo.toml new file mode 100644 index 0000000..5e5db3a --- /dev/null +++ b/crates/carpet-ui/Cargo.toml @@ -0,0 +1,24 @@ +[package] +name = "carpet-ui" +version = "0.1.0" +edition.workspace = true + +[dependencies] +nostr-lib = { path = "../nostr-lib" } +bdk-lib = { path = "../bdk-lib" } +phoenixd-lib = { path = "../phoenixd-lib" } +dcosl-core = { path = "../../../dcosl-core" } +dioxus = { version = "0.7", features = ["router"] } +serde = { workspace = true } +serde_json = { workspace = true } +tracing = { workspace = true } + +# Platform-specific (optional) +axum = { version = "0.8", optional = true } +tokio = { version = "1", features = ["full"], optional = true } + +[features] +default = [] +web = ["dioxus/web"] +server = ["dioxus/server", "dep:axum", "dep:tokio"] +desktop = ["dioxus/desktop"] diff --git a/crates/carpet-ui/Dioxus.toml b/crates/carpet-ui/Dioxus.toml new file mode 100644 index 0000000..b9c893c --- /dev/null +++ b/crates/carpet-ui/Dioxus.toml @@ -0,0 +1,16 @@ +[application] + +[web.app] +title = "Magic Carpet — Decentralized List Marketplace" + +[web.watcher] +reload_html = true +watch_path = ["src", "assets"] + +[web.resource] +style = [] +script = [] + +[web.resource.dev] +style = [] +script = [] diff --git a/crates/carpet-ui/src/app.rs b/crates/carpet-ui/src/app.rs new file mode 100644 index 0000000..00ffffa --- /dev/null +++ b/crates/carpet-ui/src/app.rs @@ -0,0 +1,17 @@ +use dioxus::prelude::*; + +use crate::routes::Route; +use crate::state::marketplace::MarketplaceState; +use crate::state::nostr::NostrState; +use crate::state::wallet::WalletState; + +pub fn App() -> Element { + // Provide global state via context + use_context_provider(|| Signal::new(NostrState::default())); + use_context_provider(|| Signal::new(WalletState::default())); + use_context_provider(|| Signal::new(MarketplaceState::default())); + + rsx! { + Router:: {} + } +} diff --git a/crates/carpet-ui/src/components/layout.rs b/crates/carpet-ui/src/components/layout.rs new file mode 100644 index 0000000..d6d63f3 --- /dev/null +++ b/crates/carpet-ui/src/components/layout.rs @@ -0,0 +1,42 @@ +use dioxus::prelude::*; + +use crate::routes::Route; +use crate::state::nostr::NostrState; +use crate::state::wallet::WalletState; + +#[component] +pub fn MainLayout() -> Element { + let nostr_state: Signal = use_context(); + let wallet_state: Signal = use_context(); + + let relay_count = nostr_state.read().connected_relays.len(); + let ln_balance = wallet_state.read().ln_balance_sats; + + rsx! { + div { class: "app-container", + nav { class: "main-nav", + div { class: "nav-brand", + Link { to: Route::Marketplace {}, "Magic Carpet" } + } + div { class: "nav-links", + Link { to: Route::Marketplace {}, "Home" } + Link { to: Route::ListBrowsePage {}, "Lists" } + Link { to: Route::BountyBrowse {}, "Bounties" } + Link { to: Route::WalletOverview {}, "Wallet" } + Link { to: Route::Profile {}, "Profile" } + } + div { class: "nav-status", + span { class: "relay-indicator", + "⚡ {relay_count} relays" + } + span { class: "wallet-bar", + "{ln_balance} sats" + } + } + } + main { class: "main-content", + Outlet:: {} + } + } + } +} diff --git a/crates/carpet-ui/src/components/list_card.rs b/crates/carpet-ui/src/components/list_card.rs new file mode 100644 index 0000000..56df3ec --- /dev/null +++ b/crates/carpet-ui/src/components/list_card.rs @@ -0,0 +1,41 @@ +use dioxus::prelude::*; + +use crate::routes::Route; + +/// Displays a grid of list headers from the marketplace. +#[component] +pub fn ListBrowse() -> Element { + // TODO: Wire up to NostrService to fetch real headers + rsx! { + div { class: "list-grid", + p { class: "placeholder", + "Connect to a relay to browse lists." + } + } + } +} + +/// A single list card for the browse view. +#[component] +pub fn ListCard( + coordinate: String, + name: String, + description: Option, + item_count: usize, + zap_count: u64, +) -> Element { + rsx! { + div { class: "list-card", + Link { to: Route::ListDetailPage { coordinate: coordinate.clone() }, + h3 { "{name}" } + if let Some(desc) = &description { + p { class: "description", "{desc}" } + } + div { class: "card-meta", + span { "{item_count} items" } + span { "{zap_count} zaps" } + } + } + } + } +} diff --git a/crates/carpet-ui/src/components/list_detail.rs b/crates/carpet-ui/src/components/list_detail.rs new file mode 100644 index 0000000..e7b3682 --- /dev/null +++ b/crates/carpet-ui/src/components/list_detail.rs @@ -0,0 +1,28 @@ +use dioxus::prelude::*; + +/// Detail view for a single list (header + items + zap button). +#[component] +pub fn ListDetail(coordinate: String) -> Element { + // TODO: Fetch full MarketplaceList via NostrService + rsx! { + div { class: "list-detail", + h1 { "List: {coordinate}" } + p { "Loading list details..." } + + div { class: "zap-section", + button { class: "zap-button", + onclick: move |_| { + // TODO: Trigger NIP-57 zap flow + tracing::info!("Zap clicked for {}", coordinate); + }, + "Zap Curator" + } + } + + div { class: "items-section", + h2 { "Items" } + p { "Loading items..." } + } + } + } +} diff --git a/crates/carpet-ui/src/components/mod.rs b/crates/carpet-ui/src/components/mod.rs new file mode 100644 index 0000000..45e3f84 --- /dev/null +++ b/crates/carpet-ui/src/components/mod.rs @@ -0,0 +1,3 @@ +pub mod layout; +pub mod list_card; +pub mod list_detail; diff --git a/crates/carpet-ui/src/main.rs b/crates/carpet-ui/src/main.rs new file mode 100644 index 0000000..af92a45 --- /dev/null +++ b/crates/carpet-ui/src/main.rs @@ -0,0 +1,10 @@ +#![allow(non_snake_case)] + +mod app; +mod components; +mod routes; +mod state; + +fn main() { + dioxus::launch(app::App); +} diff --git a/crates/carpet-ui/src/routes.rs b/crates/carpet-ui/src/routes.rs new file mode 100644 index 0000000..eae7d80 --- /dev/null +++ b/crates/carpet-ui/src/routes.rs @@ -0,0 +1,95 @@ +use dioxus::prelude::*; + +use crate::components::layout::MainLayout; +use crate::components::list_card::ListBrowse; +use crate::components::list_detail::ListDetail; + +#[derive(Routable, Clone, PartialEq)] +pub enum Route { + #[layout(MainLayout)] + #[route("/")] + Marketplace {}, + + #[route("/lists")] + ListBrowsePage {}, + + #[route("/lists/:coordinate")] + ListDetailPage { coordinate: String }, + + #[route("/bounties")] + BountyBrowse {}, + + #[route("/wallet")] + WalletOverview {}, + + #[route("/profile")] + Profile {}, +} + +// --- Page components --- + +#[component] +fn Marketplace() -> Element { + rsx! { + div { class: "marketplace", + h1 { "Magic Carpet" } + p { "Decentralized List Marketplace" } + div { class: "featured-lists", + h2 { "Featured Lists" } + ListBrowse {} + } + } + } +} + +#[component] +fn ListBrowsePage() -> Element { + rsx! { + div { class: "list-browse", + h1 { "Browse Lists" } + ListBrowse {} + } + } +} + +#[component] +fn ListDetailPage(coordinate: String) -> Element { + rsx! { + ListDetail { coordinate } + } +} + +#[component] +fn BountyBrowse() -> Element { + rsx! { + div { class: "bounty-browse", + h1 { "Active Bounties" } + p { "Coming soon — bounty listings will appear here." } + } + } +} + +#[component] +fn WalletOverview() -> Element { + rsx! { + div { class: "wallet", + h1 { "Wallet" } + div { class: "balances", + h2 { "Bitcoin (on-chain)" } + p { "Balance: loading..." } + h2 { "Lightning" } + p { "Balance: loading..." } + } + } + } +} + +#[component] +fn Profile() -> Element { + rsx! { + div { class: "profile", + h1 { "Profile" } + p { "Key management and relay settings." } + } + } +} diff --git a/crates/carpet-ui/src/state/marketplace.rs b/crates/carpet-ui/src/state/marketplace.rs new file mode 100644 index 0000000..7cfd4b8 --- /dev/null +++ b/crates/carpet-ui/src/state/marketplace.rs @@ -0,0 +1,7 @@ +/// Marketplace view state tracked in the UI. +#[derive(Debug, Clone, Default)] +pub struct MarketplaceState { + pub search_query: String, + pub selected_category: Option, + pub is_loading: bool, +} diff --git a/crates/carpet-ui/src/state/mod.rs b/crates/carpet-ui/src/state/mod.rs new file mode 100644 index 0000000..eb06767 --- /dev/null +++ b/crates/carpet-ui/src/state/mod.rs @@ -0,0 +1,3 @@ +pub mod marketplace; +pub mod nostr; +pub mod wallet; diff --git a/crates/carpet-ui/src/state/nostr.rs b/crates/carpet-ui/src/state/nostr.rs new file mode 100644 index 0000000..197e11d --- /dev/null +++ b/crates/carpet-ui/src/state/nostr.rs @@ -0,0 +1,8 @@ +/// Nostr connection state tracked in the UI. +#[derive(Debug, Clone, Default)] +pub struct NostrState { + pub connected_relays: Vec, + pub is_connecting: bool, + pub has_signer: bool, + pub npub: Option, +} diff --git a/crates/carpet-ui/src/state/wallet.rs b/crates/carpet-ui/src/state/wallet.rs new file mode 100644 index 0000000..f4e525e --- /dev/null +++ b/crates/carpet-ui/src/state/wallet.rs @@ -0,0 +1,7 @@ +/// Wallet balances tracked in the UI. +#[derive(Debug, Clone, Default)] +pub struct WalletState { + pub btc_balance_sats: u64, + pub ln_balance_sats: u64, + pub is_loading: bool, +} diff --git a/crates/nostr-lib/Cargo.toml b/crates/nostr-lib/Cargo.toml new file mode 100644 index 0000000..5fc4048 --- /dev/null +++ b/crates/nostr-lib/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "nostr-lib" +version = "0.1.0" +edition.workspace = true + +[dependencies] +dcosl-core = { path = "../../../dcosl-core" } +nostr-sdk = { version = "0.44", features = ["nip57"] } +phoenixd-lib = { path = "../phoenixd-lib" } +serde = { workspace = true } +serde_json = { workspace = true } +thiserror = { workspace = true } +tokio = { workspace = true } +tracing = { workspace = true } diff --git a/crates/nostr-lib/src/error.rs b/crates/nostr-lib/src/error.rs new file mode 100644 index 0000000..3e46b28 --- /dev/null +++ b/crates/nostr-lib/src/error.rs @@ -0,0 +1,31 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum NostrLibError { + #[error("Relay connection failed: {url}")] + RelayConnection { url: String }, + + #[error("Event publish failed: {reason}")] + PublishFailed { reason: String }, + + #[error("Protocol error: {0}")] + Protocol(#[from] dcosl_core::DcoslError), + + #[error("Zap error: {reason}")] + Zap { reason: String }, + + #[error("Profile not found for pubkey: {pubkey}")] + ProfileNotFound { pubkey: String }, + + #[error("Missing lud16 in profile for pubkey: {pubkey}")] + MissingLud16 { pubkey: String }, + + #[error("LNURL error: {reason}")] + Lnurl { reason: String }, + + #[error("PhoenixD error: {0}")] + Phoenixd(#[from] phoenixd_lib::PhoenixdError), + + #[error("Nostr SDK error: {0}")] + Sdk(String), +} diff --git a/crates/nostr-lib/src/filters.rs b/crates/nostr-lib/src/filters.rs new file mode 100644 index 0000000..80a4c12 --- /dev/null +++ b/crates/nostr-lib/src/filters.rs @@ -0,0 +1,60 @@ +use nostr_sdk::prelude::*; + +use crate::types::kinds; + +/// Build a filter for DCoSL list headers (kinds 9998 + 39998). +pub fn list_headers_filter(author: Option, hashtag: Option<&str>) -> Filter { + let mut filter = Filter::new().kinds(vec![kinds::HEADER_REGULAR, kinds::HEADER]); + + if let Some(pk) = author { + filter = filter.author(pk); + } + if let Some(t) = hashtag { + filter = filter.hashtag(t); + } + + filter +} + +/// Build a filter for list items matching a parent z-ref. +pub fn list_items_filter(z_ref: &str) -> Filter { + Filter::new() + .kinds(vec![kinds::ITEM_REGULAR, kinds::ITEM]) + .custom_tag(SingleLetterTag::lowercase(Alphabet::Z), z_ref.to_string()) +} + +/// Build a filter for bounties (NIP-99 kind 30402) with bounty hashtag. +pub fn bounties_filter(target_coordinate: Option<&str>) -> Filter { + let mut filter = Filter::new() + .kind(kinds::BOUNTY) + .hashtag("bounty"); + + if let Some(coord) = target_coordinate { + filter = filter.custom_tag(SingleLetterTag::lowercase(Alphabet::A), coord.to_string()); + } + + filter +} + +/// Build a filter for zap receipts (kind 9735) targeting a specific event or coordinate. +pub fn zap_receipts_filter(target_pubkey: PublicKey) -> Filter { + Filter::new() + .kind(kinds::ZAP_RECEIPT) + .pubkey(target_pubkey) +} + +/// Build a filter for profile metadata (kind 0). +pub fn profile_filter(pubkey: PublicKey) -> Filter { + Filter::new() + .kind(Kind::Metadata) + .author(pubkey) + .limit(1) +} + +/// Build a filter for relay list (NIP-65 kind 10002). +pub fn relay_list_filter(pubkey: PublicKey) -> Filter { + Filter::new() + .kind(kinds::RELAY_LIST) + .author(pubkey) + .limit(1) +} diff --git a/crates/nostr-lib/src/lib.rs b/crates/nostr-lib/src/lib.rs new file mode 100644 index 0000000..3261a3d --- /dev/null +++ b/crates/nostr-lib/src/lib.rs @@ -0,0 +1,10 @@ +pub mod error; +pub mod filters; +pub mod profile; +pub mod service; +pub mod types; +pub mod zap; + +pub use error::NostrLibError; +pub use service::NostrService; +pub use types::*; diff --git a/crates/nostr-lib/src/profile.rs b/crates/nostr-lib/src/profile.rs new file mode 100644 index 0000000..aa216fe --- /dev/null +++ b/crates/nostr-lib/src/profile.rs @@ -0,0 +1,71 @@ +use std::time::Duration; + +use nostr_sdk::prelude::*; + +use crate::error::NostrLibError; +use crate::filters; +use crate::types::ProfileMetadata; + +const FETCH_TIMEOUT: Duration = Duration::from_secs(10); + +/// Fetch kind 0 profile metadata for a pubkey. +pub async fn fetch_profile( + client: &Client, + pubkey: PublicKey, +) -> Result { + let filter = filters::profile_filter(pubkey); + let events = client + .fetch_events(filter, FETCH_TIMEOUT) + .await + .map_err(|e| NostrLibError::Sdk(e.to_string()))?; + + let event = events.into_iter().next().ok_or(NostrLibError::ProfileNotFound { + pubkey: pubkey.to_hex(), + })?; + + serde_json::from_str(&event.content).map_err(|_| NostrLibError::ProfileNotFound { + pubkey: pubkey.to_hex(), + }) +} + +/// Extract lud16 (Lightning Address) from a profile. +pub async fn fetch_lud16( + client: &Client, + pubkey: PublicKey, +) -> Result { + let profile = fetch_profile(client, pubkey).await?; + profile.lud16.ok_or(NostrLibError::MissingLud16 { + pubkey: pubkey.to_hex(), + }) +} + +/// Fetch NIP-65 relay list (kind 10002) for a pubkey. +pub async fn fetch_relay_list( + client: &Client, + pubkey: PublicKey, +) -> Result, NostrLibError> { + let filter = filters::relay_list_filter(pubkey); + let events = client + .fetch_events(filter, FETCH_TIMEOUT) + .await + .map_err(|e| NostrLibError::Sdk(e.to_string()))?; + + let Some(event) = events.into_iter().next() else { + return Ok(vec![]); + }; + + let relays: Vec = event + .tags + .iter() + .filter_map(|t| { + let parts = t.as_slice(); + if parts.first().map(String::as_str) == Some("r") { + parts.get(1).cloned() + } else { + None + } + }) + .collect(); + + Ok(relays) +} diff --git a/crates/nostr-lib/src/service.rs b/crates/nostr-lib/src/service.rs new file mode 100644 index 0000000..9c46e6c --- /dev/null +++ b/crates/nostr-lib/src/service.rs @@ -0,0 +1,275 @@ +use std::collections::HashSet; +use std::time::Duration; + +use nostr_sdk::prelude::*; + +use crate::error::NostrLibError; +use crate::filters; +use crate::types::{MarketplaceList, kinds}; + +const FETCH_TIMEOUT: Duration = Duration::from_secs(10); +const FETCH_PAGE_SIZE: usize = 500; + +/// Commands that the UI can send to the NostrService. +#[derive(Debug)] +pub enum NostrCommand { + /// Connect to a relay URL. + AddRelay(String), + /// Disconnect from a relay URL. + RemoveRelay(String), + /// Publish a header event. + PublishHeader { + params: dcosl_core::header::HeaderParams, + addressable: bool, + }, + /// Publish an item event. + PublishItem { + parent_z_ref: String, + resource: String, + fields: Vec, + content: Option, + }, +} + +/// Marketplace-aware Nostr client wrapping nostr_sdk::Client. +pub struct NostrService { + client: Client, +} + +impl NostrService { + pub fn new(keys: Keys) -> Self { + let client = Client::builder().signer(keys).build(); + Self { client } + } + + pub fn new_readonly() -> Self { + let client = Client::default(); + Self { client } + } + + pub fn client(&self) -> &Client { + &self.client + } + + pub async fn add_relay(&self, url: &str) -> Result<(), NostrLibError> { + self.client + .add_relay(url) + .await + .map_err(|_| NostrLibError::RelayConnection { + url: url.to_string(), + })?; + Ok(()) + } + + pub async fn connect(&self) { + self.client.connect().await; + } + + pub async fn disconnect(&self) { + self.client.disconnect().await; + } + + /// Fetch all list headers, optionally filtered. + pub async fn fetch_headers( + &self, + author: Option, + hashtag: Option<&str>, + ) -> Result, NostrLibError> { + let filter = filters::list_headers_filter(author, hashtag); + self.fetch_all_events(filter).await + } + + /// Fetch items for a list by z-ref. + pub async fn fetch_items(&self, z_ref: &str) -> Result, NostrLibError> { + let filter = filters::list_items_filter(z_ref); + let events = self + .client + .fetch_events(filter, FETCH_TIMEOUT) + .await + .map_err(|e| NostrLibError::Sdk(e.to_string()))?; + + Ok(events.into_iter().collect()) + } + + /// Fetch a full MarketplaceList by coordinate. + pub async fn fetch_marketplace_list( + &self, + coordinate: &str, + ) -> Result { + let (kind_num, pubkey, d_tag) = dcosl_core::item::parse_coordinate_str(coordinate)?; + + // Fetch header + let header_filter = Filter::new() + .kind(Kind::Custom(kind_num)) + .author(pubkey) + .custom_tag(SingleLetterTag::lowercase(Alphabet::D), d_tag.clone()) + .limit(1); + + let header_events = self + .client + .fetch_events(header_filter, FETCH_TIMEOUT) + .await + .map_err(|e| NostrLibError::Sdk(e.to_string()))?; + + let header = header_events.into_iter().next().ok_or_else(|| { + NostrLibError::Sdk(format!("Header not found for coordinate: {coordinate}")) + })?; + + // Fetch items + let items = self.fetch_items(coordinate).await?; + + // Extract metadata from header tags + let header_json = dcosl_core::query::event_to_json(&header); + let name = header_json["name"] + .as_str() + .unwrap_or("Unknown") + .to_string(); + let plural_name = header_json["plural_name"].as_str().map(String::from); + let description = header_json["description"].as_str().map(String::from); + + let categories: Vec = header + .tags + .iter() + .filter_map(|t| { + let parts = t.as_slice(); + if parts.first().map(String::as_str) == Some("t") { + parts.get(1).cloned() + } else { + None + } + }) + .collect(); + + // Try to fetch curator profile + let curator_profile = crate::profile::fetch_profile(&self.client, pubkey) + .await + .ok(); + + Ok(MarketplaceList { + header, + items, + coordinate: coordinate.to_string(), + name, + plural_name, + description, + categories, + zap_count: 0, // TODO: count zap receipts + curator_pubkey: pubkey, + curator_profile, + }) + } + + /// Publish a header event and return it. + pub async fn publish_header( + &self, + params: dcosl_core::header::HeaderParams, + addressable: bool, + ) -> Result { + let kind = if addressable { + kinds::HEADER + } else { + kinds::HEADER_REGULAR + }; + + let tags = dcosl_core::header::build_header_tags(¶ms); + let builder = EventBuilder::new(kind, "").tags(tags); + + let output = self + .client + .send_event_builder(builder) + .await + .map_err(|e| NostrLibError::PublishFailed { + reason: e.to_string(), + })?; + + // Fetch the published event back + let filter = Filter::new().id(output.val).limit(1); + let events = self + .client + .fetch_events(filter, FETCH_TIMEOUT) + .await + .map_err(|e| NostrLibError::Sdk(e.to_string()))?; + + events + .into_iter() + .next() + .ok_or_else(|| NostrLibError::PublishFailed { + reason: "Event published but not found on relay".to_string(), + }) + } + + /// Publish an item event and return its ID. + pub async fn publish_item( + &self, + parent_z_ref: &str, + resource: &str, + fields: &[String], + content: Option<&str>, + d_tag: Option<&str>, + ) -> Result { + let tags = dcosl_core::item::build_item_tags( + parent_z_ref, + resource, + fields, + d_tag, + Some("magic-carpet"), + ); + + let builder = EventBuilder::new(kinds::ITEM, content.unwrap_or("")).tags(tags); + + let output = self + .client + .send_event_builder(builder) + .await + .map_err(|e| NostrLibError::PublishFailed { + reason: e.to_string(), + })?; + + Ok(output.val) + } + + /// Paginated fetch with dedupe (same pattern as wokhei). + async fn fetch_all_events(&self, base_filter: Filter) -> Result, NostrLibError> { + let mut all_events: Vec = Vec::new(); + let mut seen_ids: HashSet = HashSet::new(); + let mut until_secs: Option = None; + + loop { + let mut filter = base_filter.clone().limit(FETCH_PAGE_SIZE); + if let Some(secs) = until_secs { + filter = filter.until(Timestamp::from_secs(secs)); + } + + let batch = self + .client + .fetch_events(filter, FETCH_TIMEOUT) + .await + .map_err(|e| NostrLibError::Sdk(e.to_string()))?; + + if batch.is_empty() { + break; + } + + let mut oldest_created_at = u64::MAX; + for event in batch.iter() { + oldest_created_at = oldest_created_at.min(event.created_at.as_secs()); + let event_id = event.id.to_hex(); + if seen_ids.insert(event_id) { + all_events.push(event.clone()); + } + } + + if batch.len() < FETCH_PAGE_SIZE || oldest_created_at == 0 { + break; + } + + let next_until = oldest_created_at.saturating_sub(1); + if until_secs == Some(next_until) { + break; + } + until_secs = Some(next_until); + } + + Ok(all_events) + } +} diff --git a/crates/nostr-lib/src/types.rs b/crates/nostr-lib/src/types.rs new file mode 100644 index 0000000..bbc4c88 --- /dev/null +++ b/crates/nostr-lib/src/types.rs @@ -0,0 +1,72 @@ +use nostr_sdk::prelude::*; +use serde::{Deserialize, Serialize}; + +/// A marketplace list: header event + items + metadata. +#[derive(Debug, Clone)] +pub struct MarketplaceList { + pub header: Event, + pub items: Vec, + pub coordinate: String, + pub name: String, + pub plural_name: Option, + pub description: Option, + pub categories: Vec, + pub zap_count: u64, + pub curator_pubkey: PublicKey, + pub curator_profile: Option, +} + +/// Curator profile metadata (kind 0). +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ProfileMetadata { + pub name: Option, + pub about: Option, + pub picture: Option, + pub nip05: Option, + pub lud16: Option, + pub display_name: Option, +} + +/// A bounty targeting a specific list (NIP-99 kind 30402). +#[derive(Debug, Clone)] +pub struct Bounty { + pub event: Event, + pub d_tag: String, + pub target_list_coordinate: String, + pub reward_sats: u64, + pub criteria: String, + pub expiry: Option, + pub status: BountyStatus, + pub creator_pubkey: PublicKey, +} + +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum BountyStatus { + Open, + Fulfilled, + Expired, +} + +/// Links a list update event to a bounty it fulfills. +#[derive(Debug, Clone)] +pub struct BountyFulfillment { + pub bounty_id: String, + pub update_event_id: EventId, + pub updater_pubkey: PublicKey, + pub zap_receipt_id: Option, +} + +/// DCoSL event kinds used in the marketplace. +pub mod kinds { + use nostr_sdk::Kind; + + pub const HEADER: Kind = Kind::Custom(39998); + pub const HEADER_REGULAR: Kind = Kind::Custom(9998); + pub const ITEM: Kind = Kind::Custom(39999); + pub const ITEM_REGULAR: Kind = Kind::Custom(9999); + pub const BOUNTY: Kind = Kind::Custom(30402); + pub const ZAP_REQUEST: Kind = Kind::Custom(9734); + pub const ZAP_RECEIPT: Kind = Kind::Custom(9735); + pub const PROFILE_METADATA: Kind = Kind::Custom(0); + pub const RELAY_LIST: Kind = Kind::Custom(10002); +} diff --git a/crates/nostr-lib/src/zap.rs b/crates/nostr-lib/src/zap.rs new file mode 100644 index 0000000..2366901 --- /dev/null +++ b/crates/nostr-lib/src/zap.rs @@ -0,0 +1,119 @@ +use nostr_sdk::prelude::*; + +use crate::error::NostrLibError; +use crate::profile; + +/// Construct a NIP-57 zap request (kind 9734). +/// +/// This returns the zap request event — it should be sent to the LNURL callback, +/// NOT published to relays. +#[allow(clippy::too_many_arguments)] +pub async fn build_zap_request( + _client: &Client, + signer: &Keys, + recipient_pubkey: PublicKey, + target_event_id: Option, + target_coordinate: Option, + amount_msats: u64, + relay_urls: Vec, + content: Option, +) -> Result { + let relay_urls: Vec = relay_urls + .into_iter() + .filter_map(|u| RelayUrl::parse(&u).ok()) + .collect(); + + let mut zap_data = ZapRequestData::new(recipient_pubkey, relay_urls) + .amount(amount_msats) + .message(content.unwrap_or_default()); + + if let Some(event_id) = target_event_id { + zap_data = zap_data.event_id(event_id); + } + if let Some(coord) = target_coordinate { + // Parse coordinate and add as `a` tag + let (kind_num, pubkey, d_tag) = dcosl_core::item::parse_coordinate_str(&coord)?; + let coordinate = Coordinate::new(Kind::Custom(kind_num), pubkey).identifier(d_tag); + zap_data = zap_data.event_coordinate(coordinate); + } + + let zap_request = EventBuilder::public_zap_request(zap_data) + .sign_with_keys(signer) + .map_err(|e| NostrLibError::Zap { + reason: e.to_string(), + })?; + + Ok(zap_request) +} + +/// Resolve a recipient's LNURL callback URL from their lud16. +/// +/// lud16 format: `user@domain` → `https://domain/.well-known/lnurlp/user` +pub fn lud16_to_lnurl_callback(lud16: &str) -> Result { + let (user, domain) = lud16.split_once('@').ok_or(NostrLibError::Lnurl { + reason: format!("Invalid lud16 format: {lud16}"), + })?; + + Ok(format!("https://{domain}/.well-known/lnurlp/{user}")) +} + +/// Full NIP-57 zap flow: +/// 1. Fetch recipient's lud16 from kind 0 profile +/// 2. Build zap request event +/// 3. Return (zap_request, lnurl_callback) for the caller to send +pub async fn prepare_zap( + client: &Client, + signer: &Keys, + recipient_pubkey: PublicKey, + target_event_id: Option, + target_coordinate: Option, + amount_msats: u64, + content: Option, +) -> Result<(Event, String), NostrLibError> { + let lud16 = profile::fetch_lud16(client, recipient_pubkey).await?; + let callback_url = lud16_to_lnurl_callback(&lud16)?; + + // Use recipient's relay list for zap routing + let relay_urls = profile::fetch_relay_list(client, recipient_pubkey).await?; + let relay_urls = if relay_urls.is_empty() { + // Fallback to connected relays + client + .relays() + .await + .keys() + .map(|u| u.to_string()) + .collect() + } else { + relay_urls + }; + + let zap_request = build_zap_request( + client, + signer, + recipient_pubkey, + target_event_id, + target_coordinate, + amount_msats, + relay_urls, + content, + ) + .await?; + + Ok((zap_request, callback_url)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn lud16_to_lnurl_valid() { + let url = lud16_to_lnurl_callback("user@example.com").unwrap(); + assert_eq!(url, "https://example.com/.well-known/lnurlp/user"); + } + + #[test] + fn lud16_to_lnurl_invalid_format() { + assert!(lud16_to_lnurl_callback("no-at-sign").is_err()); + } +} diff --git a/docker-compose.phoenixd.yml b/docker-compose.phoenixd.yml new file mode 100644 index 0000000..895f6b5 --- /dev/null +++ b/docker-compose.phoenixd.yml @@ -0,0 +1,13 @@ +services: + phoenixd: + image: acinq/phoenixd:latest + container_name: phoenixd + restart: unless-stopped + command: --agree-to-terms-of-service --http-bind-ip=0.0.0.0 + volumes: + - phoenixd-data:/phoenix/.phoenix + ports: + - "127.0.0.1:9740:9740" + +volumes: + phoenixd-data: diff --git a/phoenixd.justfile b/phoenixd.justfile new file mode 100644 index 0000000..10b7036 --- /dev/null +++ b/phoenixd.justfile @@ -0,0 +1,156 @@ +# phoenixd Docker management and API commands + +compose := "docker compose -f docker-compose.phoenixd.yml" +vault := "phoenixd" + +# Start phoenixd +up: + {{compose}} up -d + @echo "phoenixd starting... run 'just -f phoenixd.justfile backup-to-1p' after first start" + +# Stop phoenixd +down: + {{compose}} down + +# Stop and destroy volume (CAUTION: deletes seed + channels) +nuke: + {{compose}} down -v + +# Show logs +logs *args: + {{compose}} logs {{args}} + +# Follow logs +follow: + {{compose}} logs -f + +# Create dedicated 1Password vault (run once, idempotent) +setup-1p: + op vault get {{vault}} >/dev/null 2>&1 || op vault create {{vault}} + @echo "1Password vault '{{vault}}' ready" + +# Backup seed + password to 1Password (idempotent — updates if item exists) +backup-to-1p: + #!/usr/bin/env bash + set -euo pipefail + SEED=$(docker exec phoenixd cat /phoenix/.phoenix/seed.dat) + PW=$(docker exec phoenixd cat /phoenix/.phoenix/phoenix.conf | grep http-password | cut -d= -f2) + NODE_ID=$(docker exec phoenixd /phoenix/phoenix-cli getinfo | jq -r .nodeId) + if op item get "phoenixd mainnet" --vault="{{vault}}" >/dev/null 2>&1; then + op item edit "phoenixd mainnet" --vault="{{vault}}" \ + "seed=${SEED}" \ + "http-password=${PW}" \ + "node-id=${NODE_ID}" + echo "Updated existing item in 1Password vault '{{vault}}'" + else + op item create \ + --category="Secure Note" \ + --vault="{{vault}}" \ + --title="phoenixd mainnet" \ + "seed=${SEED}" \ + "http-password=${PW}" \ + "node-id=${NODE_ID}" + echo "Created new item in 1Password vault '{{vault}}'" + fi + +# Show the seed from 1Password +seed: + @op item get "phoenixd mainnet" --vault={{vault}} --fields seed --reveal + +# Verify running node ID matches 1Password backup +verify-node: + #!/usr/bin/env bash + set -euo pipefail + LIVE=$(docker exec phoenixd /phoenix/phoenix-cli getinfo | jq -r .nodeId) + STORED=$(op item get "phoenixd mainnet" --vault={{vault}} --fields node-id --reveal) + if [ "$LIVE" = "$STORED" ]; then + echo "✅ Node ID matches: $LIVE" + else + echo "❌ MISMATCH" + echo " Running: $LIVE" + echo " 1Password: $STORED" + exit 1 + fi + +# --- API commands via phoenix-cli (password auto-read from config) --- + +# Shorthand for docker exec +cli := "docker exec phoenixd /phoenix/phoenix-cli" + +# Get node info +info: + {{cli}} getinfo + +# Get balance +balance: + {{cli}} getbalance + +# List channels +channels: + {{cli}} listchannels + +# Estimate liquidity fees for an amount +estimate-fees amount: + {{cli}} estimateliquidityfees --amountSat={{amount}} + +# Create invoice: just -f phoenixd.justfile invoice 1000 "test payment" +invoice amount desc="magic-carpet": + {{cli}} createinvoice --amountSat={{amount}} --desc="{{desc}}" + +# Create invoice and display as QR code: just -f phoenixd.justfile qr-invoice 3000 "initial funding" +qr-invoice amount desc="magic-carpet": + #!/usr/bin/env bash + set -euo pipefail + BOLT11=$({{cli}} createinvoice --amountSat={{amount}} --desc="{{desc}}" | jq -r .serialized) + echo "$BOLT11" + echo "$BOLT11" | qrencode -t ANSIUTF8 + +# Create a reusable offer (amount optional) +offer desc="magic-carpet" amount="": + #!/usr/bin/env bash + ARGS="--desc={{desc}}" + [ -n "{{amount}}" ] && ARGS="$ARGS --amountSat={{amount}}" + {{cli}} createoffer $ARGS + +# Get default offer (reusable invoice) +get-offer: + {{cli}} getoffer + +# Get Lightning address (requires a channel) +ln-address: + {{cli}} getlnaddress + +# Pay a BOLT11 invoice +pay bolt11: + {{cli}} payinvoice --invoice={{bolt11}} + +# Scan a QR code via webcam and pay the invoice +scan-pay: + #!/usr/bin/env bash + set -euo pipefail + BOLT11=$(python3 scripts/scan_qr.py) + echo "" + echo "Invoice: $BOLT11" + read -p "Pay this invoice? [y/N] " confirm + [[ "$confirm" =~ ^[Yy]$ ]] || { echo "Cancelled."; exit 0; } + {{cli}} payinvoice --invoice="$BOLT11" + +# Pay a Lightning offer +pay-offer offer amount: + {{cli}} payoffer --offer={{offer}} --amountSat={{amount}} + +# List incoming payments +incoming: + {{cli}} listincomingpayments + +# Get incoming payment by hash +incoming-payment hash: + {{cli}} getincomingpayment --hash={{hash}} + +# List outgoing payments +outgoing: + {{cli}} listoutgoingpayments + +# Get outgoing payment by UUID or hash +outgoing-payment id: + {{cli}} getoutgoingpayment --uuid={{id}} diff --git a/scripts/scan_qr.py b/scripts/scan_qr.py new file mode 100755 index 0000000..e14b93b --- /dev/null +++ b/scripts/scan_qr.py @@ -0,0 +1,35 @@ +#!/usr/bin/env python3 +"""Scan a Lightning invoice QR code via webcam and print the BOLT11 string.""" +import sys +import cv2 +from pyzbar.pyzbar import decode + +cap = cv2.VideoCapture(0) +if not cap.isOpened(): + print("Error: cannot open webcam", file=sys.stderr) + sys.exit(1) + +print("Point webcam at a Lightning invoice QR code. Press 'q' to quit.", file=sys.stderr) + +while True: + ret, frame = cap.read() + if not ret: + break + for obj in decode(frame): + data = obj.data.decode("utf-8").strip() + # Strip lightning: URI scheme if present + if data.lower().startswith("lightning:"): + data = data[len("lightning:"):] + if data.lower().startswith("lnbc"): + cap.release() + cv2.destroyAllWindows() + print(data) + sys.exit(0) + cv2.imshow("Scan QR - press q to quit", frame) + if cv2.waitKey(1) & 0xFF == ord("q"): + break + +cap.release() +cv2.destroyAllWindows() +print("No invoice scanned", file=sys.stderr) +sys.exit(1) From dc0990a4a2887b3a8d07080acde0d49d9ba1f61b Mon Sep 17 00:00:00 2001 From: matthiasdebernardini Date: Sat, 7 Mar 2026 22:11:47 -0600 Subject: [PATCH 2/3] Restyle carpet-ui with Tailwind CSS and Phosphor icons Add Tailwind CSS build pipeline and restyle all pages (Marketplace, ListBrowse, Bounties, Wallet, Profile) and components (list_card, list_detail, bounty_card, wallet_card, zap_button, layout) with modern styling. Add mock data types and Tailwind watcher justfile recipe. Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitignore | 2 + Cargo.lock | 1 - crates/carpet-ui/Cargo.toml | 11 +- crates/carpet-ui/assets/Phosphor.woff2 | Bin 0 -> 147380 bytes crates/carpet-ui/assets/phosphor.css | 4623 +++++++++++++++++ crates/carpet-ui/assets/tailwind.css | 903 ++++ crates/carpet-ui/input.css | 2 + crates/carpet-ui/src/app.rs | 13 +- .../carpet-ui/src/components/bounty_card.rs | 51 + crates/carpet-ui/src/components/layout.rs | 61 +- crates/carpet-ui/src/components/list_card.rs | 75 +- .../carpet-ui/src/components/list_detail.rs | 119 +- crates/carpet-ui/src/components/mod.rs | 3 + .../carpet-ui/src/components/wallet_card.rs | 52 + crates/carpet-ui/src/components/zap_button.rs | 15 + crates/carpet-ui/src/main.rs | 2 + crates/carpet-ui/src/mock_data.rs | 168 + crates/carpet-ui/src/routes.rs | 166 +- crates/carpet-ui/src/types.rs | 37 + justfile | 16 + package-lock.json | 991 ++++ package.json | 6 + 22 files changed, 7229 insertions(+), 88 deletions(-) create mode 100644 crates/carpet-ui/assets/Phosphor.woff2 create mode 100644 crates/carpet-ui/assets/phosphor.css create mode 100644 crates/carpet-ui/assets/tailwind.css create mode 100644 crates/carpet-ui/input.css create mode 100644 crates/carpet-ui/src/components/bounty_card.rs create mode 100644 crates/carpet-ui/src/components/wallet_card.rs create mode 100644 crates/carpet-ui/src/components/zap_button.rs create mode 100644 crates/carpet-ui/src/mock_data.rs create mode 100644 crates/carpet-ui/src/types.rs create mode 100644 package-lock.json create mode 100644 package.json diff --git a/.gitignore b/.gitignore index e63f8ae..06b8884 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,5 @@ *.sqlite .env *.db-journal +node_modules/ +.cargo/ diff --git a/Cargo.lock b/Cargo.lock index e297b7b..4d27b72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -653,7 +653,6 @@ version = "0.1.0" dependencies = [ "axum", "bdk-lib", - "dcosl-core", "dioxus", "nostr-lib", "phoenixd-lib", diff --git a/crates/carpet-ui/Cargo.toml b/crates/carpet-ui/Cargo.toml index 5e5db3a..112f17b 100644 --- a/crates/carpet-ui/Cargo.toml +++ b/crates/carpet-ui/Cargo.toml @@ -4,21 +4,20 @@ version = "0.1.0" edition.workspace = true [dependencies] -nostr-lib = { path = "../nostr-lib" } -bdk-lib = { path = "../bdk-lib" } -phoenixd-lib = { path = "../phoenixd-lib" } -dcosl-core = { path = "../../../dcosl-core" } dioxus = { version = "0.7", features = ["router"] } serde = { workspace = true } serde_json = { workspace = true } tracing = { workspace = true } -# Platform-specific (optional) +# Backend crates — only needed on the server (they contain C deps that don't compile to wasm) +nostr-lib = { path = "../nostr-lib", optional = true } +bdk-lib = { path = "../bdk-lib", optional = true } +phoenixd-lib = { path = "../phoenixd-lib", optional = true } axum = { version = "0.8", optional = true } tokio = { version = "1", features = ["full"], optional = true } [features] default = [] web = ["dioxus/web"] -server = ["dioxus/server", "dep:axum", "dep:tokio"] +server = ["dioxus/server", "dep:axum", "dep:tokio", "dep:nostr-lib", "dep:bdk-lib", "dep:phoenixd-lib"] desktop = ["dioxus/desktop"] diff --git a/crates/carpet-ui/assets/Phosphor.woff2 b/crates/carpet-ui/assets/Phosphor.woff2 new file mode 100644 index 0000000000000000000000000000000000000000..76ff203b162893f79d094cde45241a54285d6e31 GIT binary patch literal 147380 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

91{!l*ruxJQ%%LB?W3} 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 literal 0 HcmV?d00001 diff --git a/crates/carpet-ui/assets/phosphor.css b/crates/carpet-ui/assets/phosphor.css new file mode 100644 index 0000000..0e5c790 --- /dev/null +++ b/crates/carpet-ui/assets/phosphor.css @@ -0,0 +1,4623 @@ +@font-face { + font-family: "Phosphor"; + src: url("./Phosphor.woff2") format("woff2"); + font-weight: normal; + font-style: normal; + font-display: block; +} + +.ph { + /* use !important to prevent issues with browser extensions that change fonts */ + font-family: "Phosphor" !important; + speak: never; + font-style: normal; + font-weight: normal; + font-variant: normal; + text-transform: none; + line-height: 1; + + /* Enable Ligatures ================ */ + letter-spacing: 0; + -webkit-font-feature-settings: "liga"; + -moz-font-feature-settings: "liga=1"; + -moz-font-feature-settings: "liga"; + -ms-font-feature-settings: "liga" 1; + font-feature-settings: "liga"; + -webkit-font-variant-ligatures: discretionary-ligatures; + font-variant-ligatures: discretionary-ligatures; + + /* Better Font Rendering =========== */ + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +.ph.ph-acorn:before { + content: "\eb9a"; +} +.ph.ph-address-book:before { + content: "\e6f8"; +} +.ph.ph-address-book-tabs:before { + content: "\ee4e"; +} +.ph.ph-air-traffic-control:before { + content: "\ecd8"; +} +.ph.ph-airplane:before { + content: "\e002"; +} +.ph.ph-airplane-in-flight:before { + content: "\e4fe"; +} +.ph.ph-airplane-landing:before { + content: "\e502"; +} +.ph.ph-airplane-takeoff:before { + content: "\e504"; +} +.ph.ph-airplane-taxiing:before { + content: "\e500"; +} +.ph.ph-airplane-tilt:before { + content: "\e5d6"; +} +.ph.ph-airplay:before { + content: "\e004"; +} +.ph.ph-alarm:before { + content: "\e006"; +} +.ph.ph-alien:before { + content: "\e8a6"; +} +.ph.ph-align-bottom:before { + content: "\e506"; +} +.ph.ph-align-bottom-simple:before { + content: "\eb0c"; +} +.ph.ph-align-center-horizontal:before { + content: "\e50a"; +} +.ph.ph-align-center-horizontal-simple:before { + content: "\eb0e"; +} +.ph.ph-align-center-vertical:before { + content: "\e50c"; +} +.ph.ph-align-center-vertical-simple:before { + content: "\eb10"; +} +.ph.ph-align-left:before { + content: "\e50e"; +} +.ph.ph-align-left-simple:before { + content: "\eaee"; +} +.ph.ph-align-right:before { + content: "\e510"; +} +.ph.ph-align-right-simple:before { + content: "\eb12"; +} +.ph.ph-align-top:before { + content: "\e512"; +} +.ph.ph-align-top-simple:before { + content: "\eb14"; +} +.ph.ph-amazon-logo:before { + content: "\e96c"; +} +.ph.ph-ambulance:before { + content: "\e572"; +} +.ph.ph-anchor:before { + content: "\e514"; +} +.ph.ph-anchor-simple:before { + content: "\e5d8"; +} +.ph.ph-android-logo:before { + content: "\e008"; +} +.ph.ph-angle:before { + content: "\e7bc"; +} +.ph.ph-angular-logo:before { + content: "\eb80"; +} +.ph.ph-aperture:before { + content: "\e00a"; +} +.ph.ph-app-store-logo:before { + content: "\e974"; +} +.ph.ph-app-window:before { + content: "\e5da"; +} +.ph.ph-apple-logo:before { + content: "\e516"; +} +.ph.ph-apple-podcasts-logo:before { + content: "\eb96"; +} +.ph.ph-approximate-equals:before { + content: "\edaa"; +} +.ph.ph-archive:before { + content: "\e00c"; +} +.ph.ph-armchair:before { + content: "\e012"; +} +.ph.ph-arrow-arc-left:before { + content: "\e014"; +} +.ph.ph-arrow-arc-right:before { + content: "\e016"; +} +.ph.ph-arrow-bend-double-up-left:before { + content: "\e03a"; +} +.ph.ph-arrow-bend-double-up-right:before { + content: "\e03c"; +} +.ph.ph-arrow-bend-down-left:before { + content: "\e018"; +} +.ph.ph-arrow-bend-down-right:before { + content: "\e01a"; +} +.ph.ph-arrow-bend-left-down:before { + content: "\e01c"; +} +.ph.ph-arrow-bend-left-up:before { + content: "\e01e"; +} +.ph.ph-arrow-bend-right-down:before { + content: "\e020"; +} +.ph.ph-arrow-bend-right-up:before { + content: "\e022"; +} +.ph.ph-arrow-bend-up-left:before { + content: "\e024"; +} +.ph.ph-arrow-bend-up-right:before { + content: "\e026"; +} +.ph.ph-arrow-circle-down:before { + content: "\e028"; +} +.ph.ph-arrow-circle-down-left:before { + content: "\e02a"; +} +.ph.ph-arrow-circle-down-right:before { + content: "\e02c"; +} +.ph.ph-arrow-circle-left:before { + content: "\e05a"; +} +.ph.ph-arrow-circle-right:before { + content: "\e02e"; +} +.ph.ph-arrow-circle-up:before { + content: "\e030"; +} +.ph.ph-arrow-circle-up-left:before { + content: "\e032"; +} +.ph.ph-arrow-circle-up-right:before { + content: "\e034"; +} +.ph.ph-arrow-clockwise:before { + content: "\e036"; +} +.ph.ph-arrow-counter-clockwise:before { + content: "\e038"; +} +.ph.ph-arrow-down:before { + content: "\e03e"; +} +.ph.ph-arrow-down-left:before { + content: "\e040"; +} +.ph.ph-arrow-down-right:before { + content: "\e042"; +} +.ph.ph-arrow-elbow-down-left:before { + content: "\e044"; +} +.ph.ph-arrow-elbow-down-right:before { + content: "\e046"; +} +.ph.ph-arrow-elbow-left:before { + content: "\e048"; +} +.ph.ph-arrow-elbow-left-down:before { + content: "\e04a"; +} +.ph.ph-arrow-elbow-left-up:before { + content: "\e04c"; +} +.ph.ph-arrow-elbow-right:before { + content: "\e04e"; +} +.ph.ph-arrow-elbow-right-down:before { + content: "\e050"; +} +.ph.ph-arrow-elbow-right-up:before { + content: "\e052"; +} +.ph.ph-arrow-elbow-up-left:before { + content: "\e054"; +} +.ph.ph-arrow-elbow-up-right:before { + content: "\e056"; +} +.ph.ph-arrow-fat-down:before { + content: "\e518"; +} +.ph.ph-arrow-fat-left:before { + content: "\e51a"; +} +.ph.ph-arrow-fat-line-down:before { + content: "\e51c"; +} +.ph.ph-arrow-fat-line-left:before { + content: "\e51e"; +} +.ph.ph-arrow-fat-line-right:before { + content: "\e520"; +} +.ph.ph-arrow-fat-line-up:before { + content: "\e522"; +} +.ph.ph-arrow-fat-lines-down:before { + content: "\e524"; +} +.ph.ph-arrow-fat-lines-left:before { + content: "\e526"; +} +.ph.ph-arrow-fat-lines-right:before { + content: "\e528"; +} +.ph.ph-arrow-fat-lines-up:before { + content: "\e52a"; +} +.ph.ph-arrow-fat-right:before { + content: "\e52c"; +} +.ph.ph-arrow-fat-up:before { + content: "\e52e"; +} +.ph.ph-arrow-left:before { + content: "\e058"; +} +.ph.ph-arrow-line-down:before { + content: "\e05c"; +} +.ph.ph-arrow-line-down-left:before { + content: "\e05e"; +} +.ph.ph-arrow-line-down-right:before { + content: "\e060"; +} +.ph.ph-arrow-line-left:before { + content: "\e062"; +} +.ph.ph-arrow-line-right:before { + content: "\e064"; +} +.ph.ph-arrow-line-up:before { + content: "\e066"; +} +.ph.ph-arrow-line-up-left:before { + content: "\e068"; +} +.ph.ph-arrow-line-up-right:before { + content: "\e06a"; +} +.ph.ph-arrow-right:before { + content: "\e06c"; +} +.ph.ph-arrow-square-down:before { + content: "\e06e"; +} +.ph.ph-arrow-square-down-left:before { + content: "\e070"; +} +.ph.ph-arrow-square-down-right:before { + content: "\e072"; +} +.ph.ph-arrow-square-in:before { + content: "\e5dc"; +} +.ph.ph-arrow-square-left:before { + content: "\e074"; +} +.ph.ph-arrow-square-out:before { + content: "\e5de"; +} +.ph.ph-arrow-square-right:before { + content: "\e076"; +} +.ph.ph-arrow-square-up:before { + content: "\e078"; +} +.ph.ph-arrow-square-up-left:before { + content: "\e07a"; +} +.ph.ph-arrow-square-up-right:before { + content: "\e07c"; +} +.ph.ph-arrow-u-down-left:before { + content: "\e07e"; +} +.ph.ph-arrow-u-down-right:before { + content: "\e080"; +} +.ph.ph-arrow-u-left-down:before { + content: "\e082"; +} +.ph.ph-arrow-u-left-up:before { + content: "\e084"; +} +.ph.ph-arrow-u-right-down:before { + content: "\e086"; +} +.ph.ph-arrow-u-right-up:before { + content: "\e088"; +} +.ph.ph-arrow-u-up-left:before { + content: "\e08a"; +} +.ph.ph-arrow-u-up-right:before { + content: "\e08c"; +} +.ph.ph-arrow-up:before { + content: "\e08e"; +} +.ph.ph-arrow-up-left:before { + content: "\e090"; +} +.ph.ph-arrow-up-right:before { + content: "\e092"; +} +.ph.ph-arrows-clockwise:before { + content: "\e094"; +} +.ph.ph-arrows-counter-clockwise:before { + content: "\e096"; +} +.ph.ph-arrows-down-up:before { + content: "\e098"; +} +.ph.ph-arrows-horizontal:before { + content: "\eb06"; +} +.ph.ph-arrows-in:before { + content: "\e09a"; +} +.ph.ph-arrows-in-cardinal:before { + content: "\e09c"; +} +.ph.ph-arrows-in-line-horizontal:before { + content: "\e530"; +} +.ph.ph-arrows-in-line-vertical:before { + content: "\e532"; +} +.ph.ph-arrows-in-simple:before { + content: "\e09e"; +} +.ph.ph-arrows-left-right:before { + content: "\e0a0"; +} +.ph.ph-arrows-merge:before { + content: "\ed3e"; +} +.ph.ph-arrows-out:before { + content: "\e0a2"; +} +.ph.ph-arrows-out-cardinal:before { + content: "\e0a4"; +} +.ph.ph-arrows-out-line-horizontal:before { + content: "\e534"; +} +.ph.ph-arrows-out-line-vertical:before { + content: "\e536"; +} +.ph.ph-arrows-out-simple:before { + content: "\e0a6"; +} +.ph.ph-arrows-split:before { + content: "\ed3c"; +} +.ph.ph-arrows-vertical:before { + content: "\eb04"; +} +.ph.ph-article:before { + content: "\e0a8"; +} +.ph.ph-article-medium:before { + content: "\e5e0"; +} +.ph.ph-article-ny-times:before { + content: "\e5e2"; +} +.ph.ph-asclepius:before { + content: "\ee34"; +} +.ph.ph-caduceus:before { + content: "\ee34"; +} +.ph.ph-asterisk:before { + content: "\e0aa"; +} +.ph.ph-asterisk-simple:before { + content: "\e832"; +} +.ph.ph-at:before { + content: "\e0ac"; +} +.ph.ph-atom:before { + content: "\e5e4"; +} +.ph.ph-avocado:before { + content: "\ee04"; +} +.ph.ph-axe:before { + content: "\e9fc"; +} +.ph.ph-baby:before { + content: "\e774"; +} +.ph.ph-baby-carriage:before { + content: "\e818"; +} +.ph.ph-backpack:before { + content: "\e922"; +} +.ph.ph-backspace:before { + content: "\e0ae"; +} +.ph.ph-bag:before { + content: "\e0b0"; +} +.ph.ph-bag-simple:before { + content: "\e5e6"; +} +.ph.ph-balloon:before { + content: "\e76c"; +} +.ph.ph-bandaids:before { + content: "\e0b2"; +} +.ph.ph-bank:before { + content: "\e0b4"; +} +.ph.ph-barbell:before { + content: "\e0b6"; +} +.ph.ph-barcode:before { + content: "\e0b8"; +} +.ph.ph-barn:before { + content: "\ec72"; +} +.ph.ph-barricade:before { + content: "\e948"; +} +.ph.ph-baseball:before { + content: "\e71a"; +} +.ph.ph-baseball-cap:before { + content: "\ea28"; +} +.ph.ph-baseball-helmet:before { + content: "\ee4a"; +} +.ph.ph-basket:before { + content: "\e964"; +} +.ph.ph-basketball:before { + content: "\e724"; +} +.ph.ph-bathtub:before { + content: "\e81e"; +} +.ph.ph-battery-charging:before { + content: "\e0ba"; +} +.ph.ph-battery-charging-vertical:before { + content: "\e0bc"; +} +.ph.ph-battery-empty:before { + content: "\e0be"; +} +.ph.ph-battery-full:before { + content: "\e0c0"; +} +.ph.ph-battery-high:before { + content: "\e0c2"; +} +.ph.ph-battery-low:before { + content: "\e0c4"; +} +.ph.ph-battery-medium:before { + content: "\e0c6"; +} +.ph.ph-battery-plus:before { + content: "\e808"; +} +.ph.ph-battery-plus-vertical:before { + content: "\ec50"; +} +.ph.ph-battery-vertical-empty:before { + content: "\e7c6"; +} +.ph.ph-battery-vertical-full:before { + content: "\e7c4"; +} +.ph.ph-battery-vertical-high:before { + content: "\e7c2"; +} +.ph.ph-battery-vertical-low:before { + content: "\e7be"; +} +.ph.ph-battery-vertical-medium:before { + content: "\e7c0"; +} +.ph.ph-battery-warning:before { + content: "\e0c8"; +} +.ph.ph-battery-warning-vertical:before { + content: "\e0ca"; +} +.ph.ph-beach-ball:before { + content: "\ed24"; +} +.ph.ph-beanie:before { + content: "\ea2a"; +} +.ph.ph-bed:before { + content: "\e0cc"; +} +.ph.ph-beer-bottle:before { + content: "\e7b0"; +} +.ph.ph-beer-stein:before { + content: "\eb62"; +} +.ph.ph-behance-logo:before { + content: "\e7f4"; +} +.ph.ph-bell:before { + content: "\e0ce"; +} +.ph.ph-bell-ringing:before { + content: "\e5e8"; +} +.ph.ph-bell-simple:before { + content: "\e0d0"; +} +.ph.ph-bell-simple-ringing:before { + content: "\e5ea"; +} +.ph.ph-bell-simple-slash:before { + content: "\e0d2"; +} +.ph.ph-bell-simple-z:before { + content: "\e5ec"; +} +.ph.ph-bell-slash:before { + content: "\e0d4"; +} +.ph.ph-bell-z:before { + content: "\e5ee"; +} +.ph.ph-belt:before { + content: "\ea2c"; +} +.ph.ph-bezier-curve:before { + content: "\eb00"; +} +.ph.ph-bicycle:before { + content: "\e0d6"; +} +.ph.ph-binary:before { + content: "\ee60"; +} +.ph.ph-binoculars:before { + content: "\ea64"; +} +.ph.ph-biohazard:before { + content: "\e9e0"; +} +.ph.ph-bird:before { + content: "\e72c"; +} +.ph.ph-blueprint:before { + content: "\eda0"; +} +.ph.ph-bluetooth:before { + content: "\e0da"; +} +.ph.ph-bluetooth-connected:before { + content: "\e0dc"; +} +.ph.ph-bluetooth-slash:before { + content: "\e0de"; +} +.ph.ph-bluetooth-x:before { + content: "\e0e0"; +} +.ph.ph-boat:before { + content: "\e786"; +} +.ph.ph-bomb:before { + content: "\ee0a"; +} +.ph.ph-bone:before { + content: "\e7f2"; +} +.ph.ph-book:before { + content: "\e0e2"; +} +.ph.ph-book-bookmark:before { + content: "\e0e4"; +} +.ph.ph-book-open:before { + content: "\e0e6"; +} +.ph.ph-book-open-text:before { + content: "\e8f2"; +} +.ph.ph-book-open-user:before { + content: "\ede0"; +} +.ph.ph-bookmark:before { + content: "\e0e8"; +} +.ph.ph-bookmark-simple:before { + content: "\e0ea"; +} +.ph.ph-bookmarks:before { + content: "\e0ec"; +} +.ph.ph-bookmarks-simple:before { + content: "\e5f0"; +} +.ph.ph-books:before { + content: "\e758"; +} +.ph.ph-boot:before { + content: "\ecca"; +} +.ph.ph-boules:before { + content: "\e722"; +} +.ph.ph-bounding-box:before { + content: "\e6ce"; +} +.ph.ph-bowl-food:before { + content: "\eaa4"; +} +.ph.ph-bowl-steam:before { + content: "\e8e4"; +} +.ph.ph-bowling-ball:before { + content: "\ea34"; +} +.ph.ph-box-arrow-down:before { + content: "\e00e"; +} +.ph.ph-archive-box:before { + content: "\e00e"; +} +.ph.ph-box-arrow-up:before { + content: "\ee54"; +} +.ph.ph-boxing-glove:before { + content: "\ea36"; +} +.ph.ph-brackets-angle:before { + content: "\e862"; +} +.ph.ph-brackets-curly:before { + content: "\e860"; +} +.ph.ph-brackets-round:before { + content: "\e864"; +} +.ph.ph-brackets-square:before { + content: "\e85e"; +} +.ph.ph-brain:before { + content: "\e74e"; +} +.ph.ph-brandy:before { + content: "\e6b4"; +} +.ph.ph-bread:before { + content: "\e81c"; +} +.ph.ph-bridge:before { + content: "\ea68"; +} +.ph.ph-briefcase:before { + content: "\e0ee"; +} +.ph.ph-briefcase-metal:before { + content: "\e5f2"; +} +.ph.ph-broadcast:before { + content: "\e0f2"; +} +.ph.ph-broom:before { + content: "\ec54"; +} +.ph.ph-browser:before { + content: "\e0f4"; +} +.ph.ph-browsers:before { + content: "\e0f6"; +} +.ph.ph-bug:before { + content: "\e5f4"; +} +.ph.ph-bug-beetle:before { + content: "\e5f6"; +} +.ph.ph-bug-droid:before { + content: "\e5f8"; +} +.ph.ph-building:before { + content: "\e100"; +} +.ph.ph-building-apartment:before { + content: "\e0fe"; +} +.ph.ph-building-office:before { + content: "\e0ff"; +} +.ph.ph-buildings:before { + content: "\e102"; +} +.ph.ph-bulldozer:before { + content: "\ec6c"; +} +.ph.ph-bus:before { + content: "\e106"; +} +.ph.ph-butterfly:before { + content: "\ea6e"; +} +.ph.ph-cable-car:before { + content: "\e49c"; +} +.ph.ph-cactus:before { + content: "\e918"; +} +.ph.ph-cake:before { + content: "\e780"; +} +.ph.ph-calculator:before { + content: "\e538"; +} +.ph.ph-calendar:before { + content: "\e108"; +} +.ph.ph-calendar-blank:before { + content: "\e10a"; +} +.ph.ph-calendar-check:before { + content: "\e712"; +} +.ph.ph-calendar-dot:before { + content: "\e7b2"; +} +.ph.ph-calendar-dots:before { + content: "\e7b4"; +} +.ph.ph-calendar-heart:before { + content: "\e8b0"; +} +.ph.ph-calendar-minus:before { + content: "\ea14"; +} +.ph.ph-calendar-plus:before { + content: "\e714"; +} +.ph.ph-calendar-slash:before { + content: "\ea12"; +} +.ph.ph-calendar-star:before { + content: "\e8b2"; +} +.ph.ph-calendar-x:before { + content: "\e10c"; +} +.ph.ph-call-bell:before { + content: "\e7de"; +} +.ph.ph-camera:before { + content: "\e10e"; +} +.ph.ph-camera-plus:before { + content: "\ec58"; +} +.ph.ph-camera-rotate:before { + content: "\e7a4"; +} +.ph.ph-camera-slash:before { + content: "\e110"; +} +.ph.ph-campfire:before { + content: "\e9d8"; +} +.ph.ph-car:before { + content: "\e112"; +} +.ph.ph-car-battery:before { + content: "\ee30"; +} +.ph.ph-car-profile:before { + content: "\e8cc"; +} +.ph.ph-car-simple:before { + content: "\e114"; +} +.ph.ph-cardholder:before { + content: "\e5fa"; +} +.ph.ph-cards:before { + content: "\e0f8"; +} +.ph.ph-cards-three:before { + content: "\ee50"; +} +.ph.ph-caret-circle-double-down:before { + content: "\e116"; +} +.ph.ph-caret-circle-double-left:before { + content: "\e118"; +} +.ph.ph-caret-circle-double-right:before { + content: "\e11a"; +} +.ph.ph-caret-circle-double-up:before { + content: "\e11c"; +} +.ph.ph-caret-circle-down:before { + content: "\e11e"; +} +.ph.ph-caret-circle-left:before { + content: "\e120"; +} +.ph.ph-caret-circle-right:before { + content: "\e122"; +} +.ph.ph-caret-circle-up:before { + content: "\e124"; +} +.ph.ph-caret-circle-up-down:before { + content: "\e13e"; +} +.ph.ph-caret-double-down:before { + content: "\e126"; +} +.ph.ph-caret-double-left:before { + content: "\e128"; +} +.ph.ph-caret-double-right:before { + content: "\e12a"; +} +.ph.ph-caret-double-up:before { + content: "\e12c"; +} +.ph.ph-caret-down:before { + content: "\e136"; +} +.ph.ph-caret-left:before { + content: "\e138"; +} +.ph.ph-caret-line-down:before { + content: "\e134"; +} +.ph.ph-caret-line-left:before { + content: "\e132"; +} +.ph.ph-caret-line-right:before { + content: "\e130"; +} +.ph.ph-caret-line-up:before { + content: "\e12e"; +} +.ph.ph-caret-right:before { + content: "\e13a"; +} +.ph.ph-caret-up:before { + content: "\e13c"; +} +.ph.ph-caret-up-down:before { + content: "\e140"; +} +.ph.ph-carrot:before { + content: "\ed38"; +} +.ph.ph-cash-register:before { + content: "\ed80"; +} +.ph.ph-cassette-tape:before { + content: "\ed2e"; +} +.ph.ph-castle-turret:before { + content: "\e9d0"; +} +.ph.ph-cat:before { + content: "\e748"; +} +.ph.ph-cell-signal-full:before { + content: "\e142"; +} +.ph.ph-cell-signal-high:before { + content: "\e144"; +} +.ph.ph-cell-signal-low:before { + content: "\e146"; +} +.ph.ph-cell-signal-medium:before { + content: "\e148"; +} +.ph.ph-cell-signal-none:before { + content: "\e14a"; +} +.ph.ph-cell-signal-slash:before { + content: "\e14c"; +} +.ph.ph-cell-signal-x:before { + content: "\e14e"; +} +.ph.ph-cell-tower:before { + content: "\ebaa"; +} +.ph.ph-certificate:before { + content: "\e766"; +} +.ph.ph-chair:before { + content: "\e950"; +} +.ph.ph-chalkboard:before { + content: "\e5fc"; +} +.ph.ph-chalkboard-simple:before { + content: "\e5fe"; +} +.ph.ph-chalkboard-teacher:before { + content: "\e600"; +} +.ph.ph-champagne:before { + content: "\eaca"; +} +.ph.ph-charging-station:before { + content: "\e8d0"; +} +.ph.ph-chart-bar:before { + content: "\e150"; +} +.ph.ph-chart-bar-horizontal:before { + content: "\e152"; +} +.ph.ph-chart-donut:before { + content: "\eaa6"; +} +.ph.ph-chart-line:before { + content: "\e154"; +} +.ph.ph-chart-line-down:before { + content: "\e8b6"; +} +.ph.ph-chart-line-up:before { + content: "\e156"; +} +.ph.ph-chart-pie:before { + content: "\e158"; +} +.ph.ph-chart-pie-slice:before { + content: "\e15a"; +} +.ph.ph-chart-polar:before { + content: "\eaa8"; +} +.ph.ph-chart-scatter:before { + content: "\eaac"; +} +.ph.ph-chat:before { + content: "\e15c"; +} +.ph.ph-chat-centered:before { + content: "\e160"; +} +.ph.ph-chat-centered-dots:before { + content: "\e164"; +} +.ph.ph-chat-centered-slash:before { + content: "\e162"; +} +.ph.ph-chat-centered-text:before { + content: "\e166"; +} +.ph.ph-chat-circle:before { + content: "\e168"; +} +.ph.ph-chat-circle-dots:before { + content: "\e16c"; +} +.ph.ph-chat-circle-slash:before { + content: "\e16a"; +} +.ph.ph-chat-circle-text:before { + content: "\e16e"; +} +.ph.ph-chat-dots:before { + content: "\e170"; +} +.ph.ph-chat-slash:before { + content: "\e15e"; +} +.ph.ph-chat-teardrop:before { + content: "\e172"; +} +.ph.ph-chat-teardrop-dots:before { + content: "\e176"; +} +.ph.ph-chat-teardrop-slash:before { + content: "\e174"; +} +.ph.ph-chat-teardrop-text:before { + content: "\e178"; +} +.ph.ph-chat-text:before { + content: "\e17a"; +} +.ph.ph-chats:before { + content: "\e17c"; +} +.ph.ph-chats-circle:before { + content: "\e17e"; +} +.ph.ph-chats-teardrop:before { + content: "\e180"; +} +.ph.ph-check:before { + content: "\e182"; +} +.ph.ph-check-circle:before { + content: "\e184"; +} +.ph.ph-check-fat:before { + content: "\eba6"; +} +.ph.ph-check-square:before { + content: "\e186"; +} +.ph.ph-check-square-offset:before { + content: "\e188"; +} +.ph.ph-checkerboard:before { + content: "\e8c4"; +} +.ph.ph-checks:before { + content: "\e53a"; +} +.ph.ph-cheers:before { + content: "\ea4a"; +} +.ph.ph-cheese:before { + content: "\e9fe"; +} +.ph.ph-chef-hat:before { + content: "\ed8e"; +} +.ph.ph-cherries:before { + content: "\e830"; +} +.ph.ph-church:before { + content: "\ecea"; +} +.ph.ph-cigarette:before { + content: "\ed90"; +} +.ph.ph-cigarette-slash:before { + content: "\ed92"; +} +.ph.ph-circle:before { + content: "\e18a"; +} +.ph.ph-circle-dashed:before { + content: "\e602"; +} +.ph.ph-circle-half:before { + content: "\e18c"; +} +.ph.ph-circle-half-tilt:before { + content: "\e18e"; +} +.ph.ph-circle-notch:before { + content: "\eb44"; +} +.ph.ph-circles-four:before { + content: "\e190"; +} +.ph.ph-circles-three:before { + content: "\e192"; +} +.ph.ph-circles-three-plus:before { + content: "\e194"; +} +.ph.ph-circuitry:before { + content: "\e9c2"; +} +.ph.ph-city:before { + content: "\ea6a"; +} +.ph.ph-clipboard:before { + content: "\e196"; +} +.ph.ph-clipboard-text:before { + content: "\e198"; +} +.ph.ph-clock:before { + content: "\e19a"; +} +.ph.ph-clock-afternoon:before { + content: "\e19c"; +} +.ph.ph-clock-clockwise:before { + content: "\e19e"; +} +.ph.ph-clock-countdown:before { + content: "\ed2c"; +} +.ph.ph-clock-counter-clockwise:before { + content: "\e1a0"; +} +.ph.ph-clock-user:before { + content: "\edec"; +} +.ph.ph-closed-captioning:before { + content: "\e1a4"; +} +.ph.ph-cloud:before { + content: "\e1aa"; +} +.ph.ph-cloud-arrow-down:before { + content: "\e1ac"; +} +.ph.ph-cloud-arrow-up:before { + content: "\e1ae"; +} +.ph.ph-cloud-check:before { + content: "\e1b0"; +} +.ph.ph-cloud-fog:before { + content: "\e53c"; +} +.ph.ph-cloud-lightning:before { + content: "\e1b2"; +} +.ph.ph-cloud-moon:before { + content: "\e53e"; +} +.ph.ph-cloud-rain:before { + content: "\e1b4"; +} +.ph.ph-cloud-slash:before { + content: "\e1b6"; +} +.ph.ph-cloud-snow:before { + content: "\e1b8"; +} +.ph.ph-cloud-sun:before { + content: "\e540"; +} +.ph.ph-cloud-warning:before { + content: "\ea98"; +} +.ph.ph-cloud-x:before { + content: "\ea96"; +} +.ph.ph-clover:before { + content: "\edc8"; +} +.ph.ph-club:before { + content: "\e1ba"; +} +.ph.ph-coat-hanger:before { + content: "\e7fe"; +} +.ph.ph-coda-logo:before { + content: "\e7ce"; +} +.ph.ph-code:before { + content: "\e1bc"; +} +.ph.ph-code-block:before { + content: "\eafe"; +} +.ph.ph-code-simple:before { + content: "\e1be"; +} +.ph.ph-codepen-logo:before { + content: "\e978"; +} +.ph.ph-codesandbox-logo:before { + content: "\ea06"; +} +.ph.ph-coffee:before { + content: "\e1c2"; +} +.ph.ph-coffee-bean:before { + content: "\e1c0"; +} +.ph.ph-coin:before { + content: "\e60e"; +} +.ph.ph-coin-vertical:before { + content: "\eb48"; +} +.ph.ph-coins:before { + content: "\e78e"; +} +.ph.ph-columns:before { + content: "\e546"; +} +.ph.ph-columns-plus-left:before { + content: "\e544"; +} +.ph.ph-columns-plus-right:before { + content: "\e542"; +} +.ph.ph-command:before { + content: "\e1c4"; +} +.ph.ph-compass:before { + content: "\e1c8"; +} +.ph.ph-compass-rose:before { + content: "\e1c6"; +} +.ph.ph-compass-tool:before { + content: "\ea0e"; +} +.ph.ph-computer-tower:before { + content: "\e548"; +} +.ph.ph-confetti:before { + content: "\e81a"; +} +.ph.ph-contactless-payment:before { + content: "\ed42"; +} +.ph.ph-control:before { + content: "\eca6"; +} +.ph.ph-cookie:before { + content: "\e6ca"; +} +.ph.ph-cooking-pot:before { + content: "\e764"; +} +.ph.ph-copy:before { + content: "\e1ca"; +} +.ph.ph-copy-simple:before { + content: "\e1cc"; +} +.ph.ph-copyleft:before { + content: "\e86a"; +} +.ph.ph-copyright:before { + content: "\e54a"; +} +.ph.ph-corners-in:before { + content: "\e1ce"; +} +.ph.ph-corners-out:before { + content: "\e1d0"; +} +.ph.ph-couch:before { + content: "\e7f6"; +} +.ph.ph-court-basketball:before { + content: "\ee36"; +} +.ph.ph-cow:before { + content: "\eabe"; +} +.ph.ph-cowboy-hat:before { + content: "\ed12"; +} +.ph.ph-cpu:before { + content: "\e610"; +} +.ph.ph-crane:before { + content: "\ed48"; +} +.ph.ph-crane-tower:before { + content: "\ed49"; +} +.ph.ph-credit-card:before { + content: "\e1d2"; +} +.ph.ph-cricket:before { + content: "\ee12"; +} +.ph.ph-crop:before { + content: "\e1d4"; +} +.ph.ph-cross:before { + content: "\e8a0"; +} +.ph.ph-crosshair:before { + content: "\e1d6"; +} +.ph.ph-crosshair-simple:before { + content: "\e1d8"; +} +.ph.ph-crown:before { + content: "\e614"; +} +.ph.ph-crown-cross:before { + content: "\ee5e"; +} +.ph.ph-crown-simple:before { + content: "\e616"; +} +.ph.ph-cube:before { + content: "\e1da"; +} +.ph.ph-cube-focus:before { + content: "\ed0a"; +} +.ph.ph-cube-transparent:before { + content: "\ec7c"; +} +.ph.ph-currency-btc:before { + content: "\e618"; +} +.ph.ph-currency-circle-dollar:before { + content: "\e54c"; +} +.ph.ph-currency-cny:before { + content: "\e54e"; +} +.ph.ph-currency-dollar:before { + content: "\e550"; +} +.ph.ph-currency-dollar-simple:before { + content: "\e552"; +} +.ph.ph-currency-eth:before { + content: "\eada"; +} +.ph.ph-currency-eur:before { + content: "\e554"; +} +.ph.ph-currency-gbp:before { + content: "\e556"; +} +.ph.ph-currency-inr:before { + content: "\e558"; +} +.ph.ph-currency-jpy:before { + content: "\e55a"; +} +.ph.ph-currency-krw:before { + content: "\e55c"; +} +.ph.ph-currency-kzt:before { + content: "\ec4c"; +} +.ph.ph-currency-ngn:before { + content: "\eb52"; +} +.ph.ph-currency-rub:before { + content: "\e55e"; +} +.ph.ph-cursor:before { + content: "\e1dc"; +} +.ph.ph-cursor-click:before { + content: "\e7c8"; +} +.ph.ph-cursor-text:before { + content: "\e7d8"; +} +.ph.ph-cylinder:before { + content: "\e8fc"; +} +.ph.ph-database:before { + content: "\e1de"; +} +.ph.ph-desk:before { + content: "\ed16"; +} +.ph.ph-desktop:before { + content: "\e560"; +} +.ph.ph-desktop-tower:before { + content: "\e562"; +} +.ph.ph-detective:before { + content: "\e83e"; +} +.ph.ph-dev-to-logo:before { + content: "\ed0e"; +} +.ph.ph-device-mobile:before { + content: "\e1e0"; +} +.ph.ph-device-mobile-camera:before { + content: "\e1e2"; +} +.ph.ph-device-mobile-slash:before { + content: "\ee46"; +} +.ph.ph-device-mobile-speaker:before { + content: "\e1e4"; +} +.ph.ph-device-rotate:before { + content: "\edf2"; +} +.ph.ph-device-tablet:before { + content: "\e1e6"; +} +.ph.ph-device-tablet-camera:before { + content: "\e1e8"; +} +.ph.ph-device-tablet-speaker:before { + content: "\e1ea"; +} +.ph.ph-devices:before { + content: "\eba4"; +} +.ph.ph-diamond:before { + content: "\e1ec"; +} +.ph.ph-diamonds-four:before { + content: "\e8f4"; +} +.ph.ph-dice-five:before { + content: "\e1ee"; +} +.ph.ph-dice-four:before { + content: "\e1f0"; +} +.ph.ph-dice-one:before { + content: "\e1f2"; +} +.ph.ph-dice-six:before { + content: "\e1f4"; +} +.ph.ph-dice-three:before { + content: "\e1f6"; +} +.ph.ph-dice-two:before { + content: "\e1f8"; +} +.ph.ph-disc:before { + content: "\e564"; +} +.ph.ph-disco-ball:before { + content: "\ed98"; +} +.ph.ph-discord-logo:before { + content: "\e61a"; +} +.ph.ph-divide:before { + content: "\e1fa"; +} +.ph.ph-dna:before { + content: "\e924"; +} +.ph.ph-dog:before { + content: "\e74a"; +} +.ph.ph-door:before { + content: "\e61c"; +} +.ph.ph-door-open:before { + content: "\e7e6"; +} +.ph.ph-dot:before { + content: "\ecde"; +} +.ph.ph-dot-outline:before { + content: "\ece0"; +} +.ph.ph-dots-nine:before { + content: "\e1fc"; +} +.ph.ph-dots-six:before { + content: "\e794"; +} +.ph.ph-dots-six-vertical:before { + content: "\eae2"; +} +.ph.ph-dots-three:before { + content: "\e1fe"; +} +.ph.ph-dots-three-circle:before { + content: "\e200"; +} +.ph.ph-dots-three-circle-vertical:before { + content: "\e202"; +} +.ph.ph-dots-three-outline:before { + content: "\e204"; +} +.ph.ph-dots-three-outline-vertical:before { + content: "\e206"; +} +.ph.ph-dots-three-vertical:before { + content: "\e208"; +} +.ph.ph-download:before { + content: "\e20a"; +} +.ph.ph-download-simple:before { + content: "\e20c"; +} +.ph.ph-dress:before { + content: "\ea7e"; +} +.ph.ph-dresser:before { + content: "\e94e"; +} +.ph.ph-dribbble-logo:before { + content: "\e20e"; +} +.ph.ph-drone:before { + content: "\ed74"; +} +.ph.ph-drop:before { + content: "\e210"; +} +.ph.ph-drop-half:before { + content: "\e566"; +} +.ph.ph-drop-half-bottom:before { + content: "\eb40"; +} +.ph.ph-drop-simple:before { + content: "\ee32"; +} +.ph.ph-drop-slash:before { + content: "\e954"; +} +.ph.ph-dropbox-logo:before { + content: "\e7d0"; +} +.ph.ph-ear:before { + content: "\e70c"; +} +.ph.ph-ear-slash:before { + content: "\e70e"; +} +.ph.ph-egg:before { + content: "\e812"; +} +.ph.ph-egg-crack:before { + content: "\eb64"; +} +.ph.ph-eject:before { + content: "\e212"; +} +.ph.ph-eject-simple:before { + content: "\e6ae"; +} +.ph.ph-elevator:before { + content: "\ecc0"; +} +.ph.ph-empty:before { + content: "\edbc"; +} +.ph.ph-engine:before { + content: "\ea80"; +} +.ph.ph-envelope:before { + content: "\e214"; +} +.ph.ph-envelope-open:before { + content: "\e216"; +} +.ph.ph-envelope-simple:before { + content: "\e218"; +} +.ph.ph-envelope-simple-open:before { + content: "\e21a"; +} +.ph.ph-equalizer:before { + content: "\ebbc"; +} +.ph.ph-equals:before { + content: "\e21c"; +} +.ph.ph-eraser:before { + content: "\e21e"; +} +.ph.ph-escalator-down:before { + content: "\ecba"; +} +.ph.ph-escalator-up:before { + content: "\ecbc"; +} +.ph.ph-exam:before { + content: "\e742"; +} +.ph.ph-exclamation-mark:before { + content: "\ee44"; +} +.ph.ph-exclude:before { + content: "\e882"; +} +.ph.ph-exclude-square:before { + content: "\e880"; +} +.ph.ph-export:before { + content: "\eaf0"; +} +.ph.ph-eye:before { + content: "\e220"; +} +.ph.ph-eye-closed:before { + content: "\e222"; +} +.ph.ph-eye-slash:before { + content: "\e224"; +} +.ph.ph-eyedropper:before { + content: "\e568"; +} +.ph.ph-eyedropper-sample:before { + content: "\eac4"; +} +.ph.ph-eyeglasses:before { + content: "\e7ba"; +} +.ph.ph-eyes:before { + content: "\ee5c"; +} +.ph.ph-face-mask:before { + content: "\e56a"; +} +.ph.ph-facebook-logo:before { + content: "\e226"; +} +.ph.ph-factory:before { + content: "\e760"; +} +.ph.ph-faders:before { + content: "\e228"; +} +.ph.ph-faders-horizontal:before { + content: "\e22a"; +} +.ph.ph-fallout-shelter:before { + content: "\e9de"; +} +.ph.ph-fan:before { + content: "\e9f2"; +} +.ph.ph-farm:before { + content: "\ec70"; +} +.ph.ph-fast-forward:before { + content: "\e6a6"; +} +.ph.ph-fast-forward-circle:before { + content: "\e22c"; +} +.ph.ph-feather:before { + content: "\e9c0"; +} +.ph.ph-fediverse-logo:before { + content: "\ed66"; +} +.ph.ph-figma-logo:before { + content: "\e22e"; +} +.ph.ph-file:before { + content: "\e230"; +} +.ph.ph-file-archive:before { + content: "\eb2a"; +} +.ph.ph-file-arrow-down:before { + content: "\e232"; +} +.ph.ph-file-arrow-up:before { + content: "\e61e"; +} +.ph.ph-file-audio:before { + content: "\ea20"; +} +.ph.ph-file-c:before { + content: "\eb32"; +} +.ph.ph-file-c-sharp:before { + content: "\eb30"; +} +.ph.ph-file-cloud:before { + content: "\e95e"; +} +.ph.ph-file-code:before { + content: "\e914"; +} +.ph.ph-file-cpp:before { + content: "\eb2e"; +} +.ph.ph-file-css:before { + content: "\eb34"; +} +.ph.ph-file-csv:before { + content: "\eb1c"; +} +.ph.ph-file-dashed:before { + content: "\e704"; +} +.ph.ph-file-dotted:before { + content: "\e704"; +} +.ph.ph-file-doc:before { + content: "\eb1e"; +} +.ph.ph-file-html:before { + content: "\eb38"; +} +.ph.ph-file-image:before { + content: "\ea24"; +} +.ph.ph-file-ini:before { + content: "\eb33"; +} +.ph.ph-file-jpg:before { + content: "\eb1a"; +} +.ph.ph-file-js:before { + content: "\eb24"; +} +.ph.ph-file-jsx:before { + content: "\eb3a"; +} +.ph.ph-file-lock:before { + content: "\e95c"; +} +.ph.ph-file-magnifying-glass:before { + content: "\e238"; +} +.ph.ph-file-search:before { + content: "\e238"; +} +.ph.ph-file-md:before { + content: "\ed50"; +} +.ph.ph-file-minus:before { + content: "\e234"; +} +.ph.ph-file-pdf:before { + content: "\e702"; +} +.ph.ph-file-plus:before { + content: "\e236"; +} +.ph.ph-file-png:before { + content: "\eb18"; +} +.ph.ph-file-ppt:before { + content: "\eb20"; +} +.ph.ph-file-py:before { + content: "\eb2c"; +} +.ph.ph-file-rs:before { + content: "\eb28"; +} +.ph.ph-file-sql:before { + content: "\ed4e"; +} +.ph.ph-file-svg:before { + content: "\ed08"; +} +.ph.ph-file-text:before { + content: "\e23a"; +} +.ph.ph-file-ts:before { + content: "\eb26"; +} +.ph.ph-file-tsx:before { + content: "\eb3c"; +} +.ph.ph-file-txt:before { + content: "\eb35"; +} +.ph.ph-file-video:before { + content: "\ea22"; +} +.ph.ph-file-vue:before { + content: "\eb3e"; +} +.ph.ph-file-x:before { + content: "\e23c"; +} +.ph.ph-file-xls:before { + content: "\eb22"; +} +.ph.ph-file-zip:before { + content: "\e958"; +} +.ph.ph-files:before { + content: "\e710"; +} +.ph.ph-film-reel:before { + content: "\e8c0"; +} +.ph.ph-film-script:before { + content: "\eb50"; +} +.ph.ph-film-slate:before { + content: "\e8c2"; +} +.ph.ph-film-strip:before { + content: "\e792"; +} +.ph.ph-fingerprint:before { + content: "\e23e"; +} +.ph.ph-fingerprint-simple:before { + content: "\e240"; +} +.ph.ph-finn-the-human:before { + content: "\e56c"; +} +.ph.ph-fire:before { + content: "\e242"; +} +.ph.ph-fire-extinguisher:before { + content: "\e9e8"; +} +.ph.ph-fire-simple:before { + content: "\e620"; +} +.ph.ph-fire-truck:before { + content: "\e574"; +} +.ph.ph-first-aid:before { + content: "\e56e"; +} +.ph.ph-first-aid-kit:before { + content: "\e570"; +} +.ph.ph-fish:before { + content: "\e728"; +} +.ph.ph-fish-simple:before { + content: "\e72a"; +} +.ph.ph-flag:before { + content: "\e244"; +} +.ph.ph-flag-banner:before { + content: "\e622"; +} +.ph.ph-flag-banner-fold:before { + content: "\ecf2"; +} +.ph.ph-flag-checkered:before { + content: "\ea38"; +} +.ph.ph-flag-pennant:before { + content: "\ecf0"; +} +.ph.ph-flame:before { + content: "\e624"; +} +.ph.ph-flashlight:before { + content: "\e246"; +} +.ph.ph-flask:before { + content: "\e79e"; +} +.ph.ph-flip-horizontal:before { + content: "\ed6a"; +} +.ph.ph-flip-vertical:before { + content: "\ed6c"; +} +.ph.ph-floppy-disk:before { + content: "\e248"; +} +.ph.ph-floppy-disk-back:before { + content: "\eaf4"; +} +.ph.ph-flow-arrow:before { + content: "\e6ec"; +} +.ph.ph-flower:before { + content: "\e75e"; +} +.ph.ph-flower-lotus:before { + content: "\e6cc"; +} +.ph.ph-flower-tulip:before { + content: "\eacc"; +} +.ph.ph-flying-saucer:before { + content: "\eb4a"; +} +.ph.ph-folder:before { + content: "\e24a"; +} +.ph.ph-folder-notch:before { + content: "\e24a"; +} +.ph.ph-folder-dashed:before { + content: "\e8f8"; +} +.ph.ph-folder-dotted:before { + content: "\e8f8"; +} +.ph.ph-folder-lock:before { + content: "\ea3c"; +} +.ph.ph-folder-minus:before { + content: "\e254"; +} +.ph.ph-folder-notch-minus:before { + content: "\e254"; +} +.ph.ph-folder-open:before { + content: "\e256"; +} +.ph.ph-folder-notch-open:before { + content: "\e256"; +} +.ph.ph-folder-plus:before { + content: "\e258"; +} +.ph.ph-folder-notch-plus:before { + content: "\e258"; +} +.ph.ph-folder-simple:before { + content: "\e25a"; +} +.ph.ph-folder-simple-dashed:before { + content: "\ec2a"; +} +.ph.ph-folder-simple-dotted:before { + content: "\ec2a"; +} +.ph.ph-folder-simple-lock:before { + content: "\eb5e"; +} +.ph.ph-folder-simple-minus:before { + content: "\e25c"; +} +.ph.ph-folder-simple-plus:before { + content: "\e25e"; +} +.ph.ph-folder-simple-star:before { + content: "\ec2e"; +} +.ph.ph-folder-simple-user:before { + content: "\eb60"; +} +.ph.ph-folder-star:before { + content: "\ea86"; +} +.ph.ph-folder-user:before { + content: "\eb46"; +} +.ph.ph-folders:before { + content: "\e260"; +} +.ph.ph-football:before { + content: "\e718"; +} +.ph.ph-football-helmet:before { + content: "\ee4c"; +} +.ph.ph-footprints:before { + content: "\ea88"; +} +.ph.ph-fork-knife:before { + content: "\e262"; +} +.ph.ph-four-k:before { + content: "\ea5c"; +} +.ph.ph-frame-corners:before { + content: "\e626"; +} +.ph.ph-framer-logo:before { + content: "\e264"; +} +.ph.ph-function:before { + content: "\ebe4"; +} +.ph.ph-funnel:before { + content: "\e266"; +} +.ph.ph-funnel-simple:before { + content: "\e268"; +} +.ph.ph-funnel-simple-x:before { + content: "\e26a"; +} +.ph.ph-funnel-x:before { + content: "\e26c"; +} +.ph.ph-game-controller:before { + content: "\e26e"; +} +.ph.ph-garage:before { + content: "\ecd6"; +} +.ph.ph-gas-can:before { + content: "\e8ce"; +} +.ph.ph-gas-pump:before { + content: "\e768"; +} +.ph.ph-gauge:before { + content: "\e628"; +} +.ph.ph-gavel:before { + content: "\ea32"; +} +.ph.ph-gear:before { + content: "\e270"; +} +.ph.ph-gear-fine:before { + content: "\e87c"; +} +.ph.ph-gear-six:before { + content: "\e272"; +} +.ph.ph-gender-female:before { + content: "\e6e0"; +} +.ph.ph-gender-intersex:before { + content: "\e6e6"; +} +.ph.ph-gender-male:before { + content: "\e6e2"; +} +.ph.ph-gender-neuter:before { + content: "\e6ea"; +} +.ph.ph-gender-nonbinary:before { + content: "\e6e4"; +} +.ph.ph-gender-transgender:before { + content: "\e6e8"; +} +.ph.ph-ghost:before { + content: "\e62a"; +} +.ph.ph-gif:before { + content: "\e274"; +} +.ph.ph-gift:before { + content: "\e276"; +} +.ph.ph-git-branch:before { + content: "\e278"; +} +.ph.ph-git-commit:before { + content: "\e27a"; +} +.ph.ph-git-diff:before { + content: "\e27c"; +} +.ph.ph-git-fork:before { + content: "\e27e"; +} +.ph.ph-git-merge:before { + content: "\e280"; +} +.ph.ph-git-pull-request:before { + content: "\e282"; +} +.ph.ph-github-logo:before { + content: "\e576"; +} +.ph.ph-gitlab-logo:before { + content: "\e694"; +} +.ph.ph-gitlab-logo-simple:before { + content: "\e696"; +} +.ph.ph-globe:before { + content: "\e288"; +} +.ph.ph-globe-hemisphere-east:before { + content: "\e28a"; +} +.ph.ph-globe-hemisphere-west:before { + content: "\e28c"; +} +.ph.ph-globe-simple:before { + content: "\e28e"; +} +.ph.ph-globe-simple-x:before { + content: "\e284"; +} +.ph.ph-globe-stand:before { + content: "\e290"; +} +.ph.ph-globe-x:before { + content: "\e286"; +} +.ph.ph-goggles:before { + content: "\ecb4"; +} +.ph.ph-golf:before { + content: "\ea3e"; +} +.ph.ph-goodreads-logo:before { + content: "\ed10"; +} +.ph.ph-google-cardboard-logo:before { + content: "\e7b6"; +} +.ph.ph-google-chrome-logo:before { + content: "\e976"; +} +.ph.ph-google-drive-logo:before { + content: "\e8f6"; +} +.ph.ph-google-logo:before { + content: "\e292"; +} +.ph.ph-google-photos-logo:before { + content: "\eb92"; +} +.ph.ph-google-play-logo:before { + content: "\e294"; +} +.ph.ph-google-podcasts-logo:before { + content: "\eb94"; +} +.ph.ph-gps:before { + content: "\edd8"; +} +.ph.ph-gps-fix:before { + content: "\edd6"; +} +.ph.ph-gps-slash:before { + content: "\edd4"; +} +.ph.ph-gradient:before { + content: "\eb42"; +} +.ph.ph-graduation-cap:before { + content: "\e62c"; +} +.ph.ph-grains:before { + content: "\ec68"; +} +.ph.ph-grains-slash:before { + content: "\ec6a"; +} +.ph.ph-graph:before { + content: "\eb58"; +} +.ph.ph-graphics-card:before { + content: "\e612"; +} +.ph.ph-greater-than:before { + content: "\edc4"; +} +.ph.ph-greater-than-or-equal:before { + content: "\eda2"; +} +.ph.ph-grid-four:before { + content: "\e296"; +} +.ph.ph-grid-nine:before { + content: "\ec8c"; +} +.ph.ph-guitar:before { + content: "\ea8a"; +} +.ph.ph-hair-dryer:before { + content: "\ea66"; +} +.ph.ph-hamburger:before { + content: "\e790"; +} +.ph.ph-hammer:before { + content: "\e80e"; +} +.ph.ph-hand:before { + content: "\e298"; +} +.ph.ph-hand-arrow-down:before { + content: "\ea4e"; +} +.ph.ph-hand-arrow-up:before { + content: "\ee5a"; +} +.ph.ph-hand-coins:before { + content: "\ea8c"; +} +.ph.ph-hand-deposit:before { + content: "\ee82"; +} +.ph.ph-hand-eye:before { + content: "\ea4c"; +} +.ph.ph-hand-fist:before { + content: "\e57a"; +} +.ph.ph-hand-grabbing:before { + content: "\e57c"; +} +.ph.ph-hand-heart:before { + content: "\e810"; +} +.ph.ph-hand-palm:before { + content: "\e57e"; +} +.ph.ph-hand-peace:before { + content: "\e7cc"; +} +.ph.ph-hand-pointing:before { + content: "\e29a"; +} +.ph.ph-hand-soap:before { + content: "\e630"; +} +.ph.ph-hand-swipe-left:before { + content: "\ec94"; +} +.ph.ph-hand-swipe-right:before { + content: "\ec92"; +} +.ph.ph-hand-tap:before { + content: "\ec90"; +} +.ph.ph-hand-waving:before { + content: "\e580"; +} +.ph.ph-hand-withdraw:before { + content: "\ee80"; +} +.ph.ph-handbag:before { + content: "\e29c"; +} +.ph.ph-handbag-simple:before { + content: "\e62e"; +} +.ph.ph-hands-clapping:before { + content: "\e6a0"; +} +.ph.ph-hands-praying:before { + content: "\ecc8"; +} +.ph.ph-handshake:before { + content: "\e582"; +} +.ph.ph-hard-drive:before { + content: "\e29e"; +} +.ph.ph-hard-drives:before { + content: "\e2a0"; +} +.ph.ph-hard-hat:before { + content: "\ed46"; +} +.ph.ph-hash:before { + content: "\e2a2"; +} +.ph.ph-hash-straight:before { + content: "\e2a4"; +} +.ph.ph-head-circuit:before { + content: "\e7d4"; +} +.ph.ph-headlights:before { + content: "\e6fe"; +} +.ph.ph-headphones:before { + content: "\e2a6"; +} +.ph.ph-headset:before { + content: "\e584"; +} +.ph.ph-heart:before { + content: "\e2a8"; +} +.ph.ph-heart-break:before { + content: "\ebe8"; +} +.ph.ph-heart-half:before { + content: "\ec48"; +} +.ph.ph-heart-straight:before { + content: "\e2aa"; +} +.ph.ph-heart-straight-break:before { + content: "\eb98"; +} +.ph.ph-heartbeat:before { + content: "\e2ac"; +} +.ph.ph-hexagon:before { + content: "\e2ae"; +} +.ph.ph-high-definition:before { + content: "\ea8e"; +} +.ph.ph-high-heel:before { + content: "\e8e8"; +} +.ph.ph-highlighter:before { + content: "\ec76"; +} +.ph.ph-highlighter-circle:before { + content: "\e632"; +} +.ph.ph-hockey:before { + content: "\ec86"; +} +.ph.ph-hoodie:before { + content: "\ecd0"; +} +.ph.ph-horse:before { + content: "\e2b0"; +} +.ph.ph-hospital:before { + content: "\e844"; +} +.ph.ph-hourglass:before { + content: "\e2b2"; +} +.ph.ph-hourglass-high:before { + content: "\e2b4"; +} +.ph.ph-hourglass-low:before { + content: "\e2b6"; +} +.ph.ph-hourglass-medium:before { + content: "\e2b8"; +} +.ph.ph-hourglass-simple:before { + content: "\e2ba"; +} +.ph.ph-hourglass-simple-high:before { + content: "\e2bc"; +} +.ph.ph-hourglass-simple-low:before { + content: "\e2be"; +} +.ph.ph-hourglass-simple-medium:before { + content: "\e2c0"; +} +.ph.ph-house:before { + content: "\e2c2"; +} +.ph.ph-house-line:before { + content: "\e2c4"; +} +.ph.ph-house-simple:before { + content: "\e2c6"; +} +.ph.ph-hurricane:before { + content: "\e88e"; +} +.ph.ph-ice-cream:before { + content: "\e804"; +} +.ph.ph-identification-badge:before { + content: "\e6f6"; +} +.ph.ph-identification-card:before { + content: "\e2c8"; +} +.ph.ph-image:before { + content: "\e2ca"; +} +.ph.ph-image-broken:before { + content: "\e7a8"; +} +.ph.ph-image-square:before { + content: "\e2cc"; +} +.ph.ph-images:before { + content: "\e836"; +} +.ph.ph-images-square:before { + content: "\e834"; +} +.ph.ph-infinity:before { + content: "\e634"; +} +.ph.ph-lemniscate:before { + content: "\e634"; +} +.ph.ph-info:before { + content: "\e2ce"; +} +.ph.ph-instagram-logo:before { + content: "\e2d0"; +} +.ph.ph-intersect:before { + content: "\e2d2"; +} +.ph.ph-intersect-square:before { + content: "\e87a"; +} +.ph.ph-intersect-three:before { + content: "\ecc4"; +} +.ph.ph-intersection:before { + content: "\edba"; +} +.ph.ph-invoice:before { + content: "\ee42"; +} +.ph.ph-island:before { + content: "\ee06"; +} +.ph.ph-jar:before { + content: "\e7e0"; +} +.ph.ph-jar-label:before { + content: "\e7e1"; +} +.ph.ph-jeep:before { + content: "\e2d4"; +} +.ph.ph-joystick:before { + content: "\ea5e"; +} +.ph.ph-kanban:before { + content: "\eb54"; +} +.ph.ph-key:before { + content: "\e2d6"; +} +.ph.ph-key-return:before { + content: "\e782"; +} +.ph.ph-keyboard:before { + content: "\e2d8"; +} +.ph.ph-keyhole:before { + content: "\ea78"; +} +.ph.ph-knife:before { + content: "\e636"; +} +.ph.ph-ladder:before { + content: "\e9e4"; +} +.ph.ph-ladder-simple:before { + content: "\ec26"; +} +.ph.ph-lamp:before { + content: "\e638"; +} +.ph.ph-lamp-pendant:before { + content: "\ee2e"; +} +.ph.ph-laptop:before { + content: "\e586"; +} +.ph.ph-lasso:before { + content: "\edc6"; +} +.ph.ph-lastfm-logo:before { + content: "\e842"; +} +.ph.ph-layout:before { + content: "\e6d6"; +} +.ph.ph-leaf:before { + content: "\e2da"; +} +.ph.ph-lectern:before { + content: "\e95a"; +} +.ph.ph-lego:before { + content: "\e8c6"; +} +.ph.ph-lego-smiley:before { + content: "\e8c7"; +} +.ph.ph-less-than:before { + content: "\edac"; +} +.ph.ph-less-than-or-equal:before { + content: "\eda4"; +} +.ph.ph-letter-circle-h:before { + content: "\ebf8"; +} +.ph.ph-letter-circle-p:before { + content: "\ec08"; +} +.ph.ph-letter-circle-v:before { + content: "\ec14"; +} +.ph.ph-lifebuoy:before { + content: "\e63a"; +} +.ph.ph-lightbulb:before { + content: "\e2dc"; +} +.ph.ph-lightbulb-filament:before { + content: "\e63c"; +} +.ph.ph-lighthouse:before { + content: "\e9f6"; +} +.ph.ph-lightning:before { + content: "\e2de"; +} +.ph.ph-lightning-a:before { + content: "\ea84"; +} +.ph.ph-lightning-slash:before { + content: "\e2e0"; +} +.ph.ph-line-segment:before { + content: "\e6d2"; +} +.ph.ph-line-segments:before { + content: "\e6d4"; +} +.ph.ph-line-vertical:before { + content: "\ed70"; +} +.ph.ph-link:before { + content: "\e2e2"; +} +.ph.ph-link-break:before { + content: "\e2e4"; +} +.ph.ph-link-simple:before { + content: "\e2e6"; +} +.ph.ph-link-simple-break:before { + content: "\e2e8"; +} +.ph.ph-link-simple-horizontal:before { + content: "\e2ea"; +} +.ph.ph-link-simple-horizontal-break:before { + content: "\e2ec"; +} +.ph.ph-linkedin-logo:before { + content: "\e2ee"; +} +.ph.ph-linktree-logo:before { + content: "\edee"; +} +.ph.ph-linux-logo:before { + content: "\eb02"; +} +.ph.ph-list:before { + content: "\e2f0"; +} +.ph.ph-list-bullets:before { + content: "\e2f2"; +} +.ph.ph-list-checks:before { + content: "\eadc"; +} +.ph.ph-list-dashes:before { + content: "\e2f4"; +} +.ph.ph-list-heart:before { + content: "\ebde"; +} +.ph.ph-list-magnifying-glass:before { + content: "\ebe0"; +} +.ph.ph-list-numbers:before { + content: "\e2f6"; +} +.ph.ph-list-plus:before { + content: "\e2f8"; +} +.ph.ph-list-star:before { + content: "\ebdc"; +} +.ph.ph-lock:before { + content: "\e2fa"; +} +.ph.ph-lock-key:before { + content: "\e2fe"; +} +.ph.ph-lock-key-open:before { + content: "\e300"; +} +.ph.ph-lock-laminated:before { + content: "\e302"; +} +.ph.ph-lock-laminated-open:before { + content: "\e304"; +} +.ph.ph-lock-open:before { + content: "\e306"; +} +.ph.ph-lock-simple:before { + content: "\e308"; +} +.ph.ph-lock-simple-open:before { + content: "\e30a"; +} +.ph.ph-lockers:before { + content: "\ecb8"; +} +.ph.ph-log:before { + content: "\ed82"; +} +.ph.ph-magic-wand:before { + content: "\e6b6"; +} +.ph.ph-magnet:before { + content: "\e680"; +} +.ph.ph-magnet-straight:before { + content: "\e682"; +} +.ph.ph-magnifying-glass:before { + content: "\e30c"; +} +.ph.ph-magnifying-glass-minus:before { + content: "\e30e"; +} +.ph.ph-magnifying-glass-plus:before { + content: "\e310"; +} +.ph.ph-mailbox:before { + content: "\ec1e"; +} +.ph.ph-map-pin:before { + content: "\e316"; +} +.ph.ph-map-pin-area:before { + content: "\ee3a"; +} +.ph.ph-map-pin-line:before { + content: "\e318"; +} +.ph.ph-map-pin-plus:before { + content: "\e314"; +} +.ph.ph-map-pin-simple:before { + content: "\ee3e"; +} +.ph.ph-map-pin-simple-area:before { + content: "\ee3c"; +} +.ph.ph-map-pin-simple-line:before { + content: "\ee38"; +} +.ph.ph-map-trifold:before { + content: "\e31a"; +} +.ph.ph-markdown-logo:before { + content: "\e508"; +} +.ph.ph-marker-circle:before { + content: "\e640"; +} +.ph.ph-martini:before { + content: "\e31c"; +} +.ph.ph-mask-happy:before { + content: "\e9f4"; +} +.ph.ph-mask-sad:before { + content: "\eb9e"; +} +.ph.ph-mastodon-logo:before { + content: "\ed68"; +} +.ph.ph-math-operations:before { + content: "\e31e"; +} +.ph.ph-matrix-logo:before { + content: "\ed64"; +} +.ph.ph-medal:before { + content: "\e320"; +} +.ph.ph-medal-military:before { + content: "\ecfc"; +} +.ph.ph-medium-logo:before { + content: "\e322"; +} +.ph.ph-megaphone:before { + content: "\e324"; +} +.ph.ph-megaphone-simple:before { + content: "\e642"; +} +.ph.ph-member-of:before { + content: "\edc2"; +} +.ph.ph-memory:before { + content: "\e9c4"; +} +.ph.ph-messenger-logo:before { + content: "\e6d8"; +} +.ph.ph-meta-logo:before { + content: "\ed02"; +} +.ph.ph-meteor:before { + content: "\e9ba"; +} +.ph.ph-metronome:before { + content: "\ec8e"; +} +.ph.ph-microphone:before { + content: "\e326"; +} +.ph.ph-microphone-slash:before { + content: "\e328"; +} +.ph.ph-microphone-stage:before { + content: "\e75c"; +} +.ph.ph-microscope:before { + content: "\ec7a"; +} +.ph.ph-microsoft-excel-logo:before { + content: "\eb6c"; +} +.ph.ph-microsoft-outlook-logo:before { + content: "\eb70"; +} +.ph.ph-microsoft-powerpoint-logo:before { + content: "\eace"; +} +.ph.ph-microsoft-teams-logo:before { + content: "\eb66"; +} +.ph.ph-microsoft-word-logo:before { + content: "\eb6a"; +} +.ph.ph-minus:before { + content: "\e32a"; +} +.ph.ph-minus-circle:before { + content: "\e32c"; +} +.ph.ph-minus-square:before { + content: "\ed4c"; +} +.ph.ph-money:before { + content: "\e588"; +} +.ph.ph-money-wavy:before { + content: "\ee68"; +} +.ph.ph-monitor:before { + content: "\e32e"; +} +.ph.ph-monitor-arrow-up:before { + content: "\e58a"; +} +.ph.ph-monitor-play:before { + content: "\e58c"; +} +.ph.ph-moon:before { + content: "\e330"; +} +.ph.ph-moon-stars:before { + content: "\e58e"; +} +.ph.ph-moped:before { + content: "\e824"; +} +.ph.ph-moped-front:before { + content: "\e822"; +} +.ph.ph-mosque:before { + content: "\ecee"; +} +.ph.ph-motorcycle:before { + content: "\e80a"; +} +.ph.ph-mountains:before { + content: "\e7ae"; +} +.ph.ph-mouse:before { + content: "\e33a"; +} +.ph.ph-mouse-left-click:before { + content: "\e334"; +} +.ph.ph-mouse-middle-click:before { + content: "\e338"; +} +.ph.ph-mouse-right-click:before { + content: "\e336"; +} +.ph.ph-mouse-scroll:before { + content: "\e332"; +} +.ph.ph-mouse-simple:before { + content: "\e644"; +} +.ph.ph-music-note:before { + content: "\e33c"; +} +.ph.ph-music-note-simple:before { + content: "\e33e"; +} +.ph.ph-music-notes:before { + content: "\e340"; +} +.ph.ph-music-notes-minus:before { + content: "\ee0c"; +} +.ph.ph-music-notes-plus:before { + content: "\eb7c"; +} +.ph.ph-music-notes-simple:before { + content: "\e342"; +} +.ph.ph-navigation-arrow:before { + content: "\eade"; +} +.ph.ph-needle:before { + content: "\e82e"; +} +.ph.ph-network:before { + content: "\edde"; +} +.ph.ph-network-slash:before { + content: "\eddc"; +} +.ph.ph-network-x:before { + content: "\edda"; +} +.ph.ph-newspaper:before { + content: "\e344"; +} +.ph.ph-newspaper-clipping:before { + content: "\e346"; +} +.ph.ph-not-equals:before { + content: "\eda6"; +} +.ph.ph-not-member-of:before { + content: "\edae"; +} +.ph.ph-not-subset-of:before { + content: "\edb0"; +} +.ph.ph-not-superset-of:before { + content: "\edb2"; +} +.ph.ph-notches:before { + content: "\ed3a"; +} +.ph.ph-note:before { + content: "\e348"; +} +.ph.ph-note-blank:before { + content: "\e34a"; +} +.ph.ph-note-pencil:before { + content: "\e34c"; +} +.ph.ph-notebook:before { + content: "\e34e"; +} +.ph.ph-notepad:before { + content: "\e63e"; +} +.ph.ph-notification:before { + content: "\e6fa"; +} +.ph.ph-notion-logo:before { + content: "\e9a0"; +} +.ph.ph-nuclear-plant:before { + content: "\ed7c"; +} +.ph.ph-number-circle-eight:before { + content: "\e352"; +} +.ph.ph-number-circle-five:before { + content: "\e358"; +} +.ph.ph-number-circle-four:before { + content: "\e35e"; +} +.ph.ph-number-circle-nine:before { + content: "\e364"; +} +.ph.ph-number-circle-one:before { + content: "\e36a"; +} +.ph.ph-number-circle-seven:before { + content: "\e370"; +} +.ph.ph-number-circle-six:before { + content: "\e376"; +} +.ph.ph-number-circle-three:before { + content: "\e37c"; +} +.ph.ph-number-circle-two:before { + content: "\e382"; +} +.ph.ph-number-circle-zero:before { + content: "\e388"; +} +.ph.ph-number-eight:before { + content: "\e350"; +} +.ph.ph-number-five:before { + content: "\e356"; +} +.ph.ph-number-four:before { + content: "\e35c"; +} +.ph.ph-number-nine:before { + content: "\e362"; +} +.ph.ph-number-one:before { + content: "\e368"; +} +.ph.ph-number-seven:before { + content: "\e36e"; +} +.ph.ph-number-six:before { + content: "\e374"; +} +.ph.ph-number-square-eight:before { + content: "\e354"; +} +.ph.ph-number-square-five:before { + content: "\e35a"; +} +.ph.ph-number-square-four:before { + content: "\e360"; +} +.ph.ph-number-square-nine:before { + content: "\e366"; +} +.ph.ph-number-square-one:before { + content: "\e36c"; +} +.ph.ph-number-square-seven:before { + content: "\e372"; +} +.ph.ph-number-square-six:before { + content: "\e378"; +} +.ph.ph-number-square-three:before { + content: "\e37e"; +} +.ph.ph-number-square-two:before { + content: "\e384"; +} +.ph.ph-number-square-zero:before { + content: "\e38a"; +} +.ph.ph-number-three:before { + content: "\e37a"; +} +.ph.ph-number-two:before { + content: "\e380"; +} +.ph.ph-number-zero:before { + content: "\e386"; +} +.ph.ph-numpad:before { + content: "\e3c8"; +} +.ph.ph-nut:before { + content: "\e38c"; +} +.ph.ph-ny-times-logo:before { + content: "\e646"; +} +.ph.ph-octagon:before { + content: "\e38e"; +} +.ph.ph-office-chair:before { + content: "\ea46"; +} +.ph.ph-onigiri:before { + content: "\ee2c"; +} +.ph.ph-open-ai-logo:before { + content: "\e7d2"; +} +.ph.ph-option:before { + content: "\e8a8"; +} +.ph.ph-orange:before { + content: "\ee40"; +} +.ph.ph-orange-slice:before { + content: "\ed36"; +} +.ph.ph-oven:before { + content: "\ed8c"; +} +.ph.ph-package:before { + content: "\e390"; +} +.ph.ph-paint-brush:before { + content: "\e6f0"; +} +.ph.ph-paint-brush-broad:before { + content: "\e590"; +} +.ph.ph-paint-brush-household:before { + content: "\e6f2"; +} +.ph.ph-paint-bucket:before { + content: "\e392"; +} +.ph.ph-paint-roller:before { + content: "\e6f4"; +} +.ph.ph-palette:before { + content: "\e6c8"; +} +.ph.ph-panorama:before { + content: "\eaa2"; +} +.ph.ph-pants:before { + content: "\ec88"; +} +.ph.ph-paper-plane:before { + content: "\e394"; +} +.ph.ph-paper-plane-right:before { + content: "\e396"; +} +.ph.ph-paper-plane-tilt:before { + content: "\e398"; +} +.ph.ph-paperclip:before { + content: "\e39a"; +} +.ph.ph-paperclip-horizontal:before { + content: "\e592"; +} +.ph.ph-parachute:before { + content: "\ea7c"; +} +.ph.ph-paragraph:before { + content: "\e960"; +} +.ph.ph-parallelogram:before { + content: "\ecc6"; +} +.ph.ph-park:before { + content: "\ecb2"; +} +.ph.ph-password:before { + content: "\e752"; +} +.ph.ph-path:before { + content: "\e39c"; +} +.ph.ph-patreon-logo:before { + content: "\e98a"; +} +.ph.ph-pause:before { + content: "\e39e"; +} +.ph.ph-pause-circle:before { + content: "\e3a0"; +} +.ph.ph-paw-print:before { + content: "\e648"; +} +.ph.ph-paypal-logo:before { + content: "\e98c"; +} +.ph.ph-peace:before { + content: "\e3a2"; +} +.ph.ph-pen:before { + content: "\e3aa"; +} +.ph.ph-pen-nib:before { + content: "\e3ac"; +} +.ph.ph-pen-nib-straight:before { + content: "\e64a"; +} +.ph.ph-pencil:before { + content: "\e3ae"; +} +.ph.ph-pencil-circle:before { + content: "\e3b0"; +} +.ph.ph-pencil-line:before { + content: "\e3b2"; +} +.ph.ph-pencil-ruler:before { + content: "\e906"; +} +.ph.ph-pencil-simple:before { + content: "\e3b4"; +} +.ph.ph-pencil-simple-line:before { + content: "\ebc6"; +} +.ph.ph-pencil-simple-slash:before { + content: "\ecf6"; +} +.ph.ph-pencil-slash:before { + content: "\ecf8"; +} +.ph.ph-pentagon:before { + content: "\ec7e"; +} +.ph.ph-pentagram:before { + content: "\ec5c"; +} +.ph.ph-pepper:before { + content: "\e94a"; +} +.ph.ph-percent:before { + content: "\e3b6"; +} +.ph.ph-person:before { + content: "\e3a8"; +} +.ph.ph-person-arms-spread:before { + content: "\ecfe"; +} +.ph.ph-person-simple:before { + content: "\e72e"; +} +.ph.ph-person-simple-bike:before { + content: "\e734"; +} +.ph.ph-person-simple-circle:before { + content: "\ee58"; +} +.ph.ph-person-simple-hike:before { + content: "\ed54"; +} +.ph.ph-person-simple-run:before { + content: "\e730"; +} +.ph.ph-person-simple-ski:before { + content: "\e71c"; +} +.ph.ph-person-simple-snowboard:before { + content: "\e71e"; +} +.ph.ph-person-simple-swim:before { + content: "\e736"; +} +.ph.ph-person-simple-tai-chi:before { + content: "\ed5c"; +} +.ph.ph-person-simple-throw:before { + content: "\e732"; +} +.ph.ph-person-simple-walk:before { + content: "\e73a"; +} +.ph.ph-perspective:before { + content: "\ebe6"; +} +.ph.ph-phone:before { + content: "\e3b8"; +} +.ph.ph-phone-call:before { + content: "\e3ba"; +} +.ph.ph-phone-disconnect:before { + content: "\e3bc"; +} +.ph.ph-phone-incoming:before { + content: "\e3be"; +} +.ph.ph-phone-list:before { + content: "\e3cc"; +} +.ph.ph-phone-outgoing:before { + content: "\e3c0"; +} +.ph.ph-phone-pause:before { + content: "\e3ca"; +} +.ph.ph-phone-plus:before { + content: "\ec56"; +} +.ph.ph-phone-slash:before { + content: "\e3c2"; +} +.ph.ph-phone-transfer:before { + content: "\e3c6"; +} +.ph.ph-phone-x:before { + content: "\e3c4"; +} +.ph.ph-phosphor-logo:before { + content: "\e3ce"; +} +.ph.ph-pi:before { + content: "\ec80"; +} +.ph.ph-piano-keys:before { + content: "\e9c8"; +} +.ph.ph-picnic-table:before { + content: "\ee26"; +} +.ph.ph-picture-in-picture:before { + content: "\e64c"; +} +.ph.ph-piggy-bank:before { + content: "\ea04"; +} +.ph.ph-pill:before { + content: "\e700"; +} +.ph.ph-ping-pong:before { + content: "\ea42"; +} +.ph.ph-pint-glass:before { + content: "\edd0"; +} +.ph.ph-pinterest-logo:before { + content: "\e64e"; +} +.ph.ph-pinwheel:before { + content: "\eb9c"; +} +.ph.ph-pipe:before { + content: "\ed86"; +} +.ph.ph-pipe-wrench:before { + content: "\ed88"; +} +.ph.ph-pix-logo:before { + content: "\ecc2"; +} +.ph.ph-pizza:before { + content: "\e796"; +} +.ph.ph-placeholder:before { + content: "\e650"; +} +.ph.ph-planet:before { + content: "\e652"; +} +.ph.ph-plant:before { + content: "\ebae"; +} +.ph.ph-play:before { + content: "\e3d0"; +} +.ph.ph-play-circle:before { + content: "\e3d2"; +} +.ph.ph-play-pause:before { + content: "\e8be"; +} +.ph.ph-playlist:before { + content: "\e6aa"; +} +.ph.ph-plug:before { + content: "\e946"; +} +.ph.ph-plug-charging:before { + content: "\eb5c"; +} +.ph.ph-plugs:before { + content: "\eb56"; +} +.ph.ph-plugs-connected:before { + content: "\eb5a"; +} +.ph.ph-plus:before { + content: "\e3d4"; +} +.ph.ph-plus-circle:before { + content: "\e3d6"; +} +.ph.ph-plus-minus:before { + content: "\e3d8"; +} +.ph.ph-plus-square:before { + content: "\ed4a"; +} +.ph.ph-poker-chip:before { + content: "\e594"; +} +.ph.ph-police-car:before { + content: "\ec4a"; +} +.ph.ph-polygon:before { + content: "\e6d0"; +} +.ph.ph-popcorn:before { + content: "\eb4e"; +} +.ph.ph-popsicle:before { + content: "\ebbe"; +} +.ph.ph-potted-plant:before { + content: "\ec22"; +} +.ph.ph-power:before { + content: "\e3da"; +} +.ph.ph-prescription:before { + content: "\e7a2"; +} +.ph.ph-presentation:before { + content: "\e654"; +} +.ph.ph-presentation-chart:before { + content: "\e656"; +} +.ph.ph-printer:before { + content: "\e3dc"; +} +.ph.ph-prohibit:before { + content: "\e3de"; +} +.ph.ph-prohibit-inset:before { + content: "\e3e0"; +} +.ph.ph-projector-screen:before { + content: "\e658"; +} +.ph.ph-projector-screen-chart:before { + content: "\e65a"; +} +.ph.ph-pulse:before { + content: "\e000"; +} +.ph.ph-activity:before { + content: "\e000"; +} +.ph.ph-push-pin:before { + content: "\e3e2"; +} +.ph.ph-push-pin-simple:before { + content: "\e65c"; +} +.ph.ph-push-pin-simple-slash:before { + content: "\e65e"; +} +.ph.ph-push-pin-slash:before { + content: "\e3e4"; +} +.ph.ph-puzzle-piece:before { + content: "\e596"; +} +.ph.ph-qr-code:before { + content: "\e3e6"; +} +.ph.ph-question:before { + content: "\e3e8"; +} +.ph.ph-question-mark:before { + content: "\e3e9"; +} +.ph.ph-queue:before { + content: "\e6ac"; +} +.ph.ph-quotes:before { + content: "\e660"; +} +.ph.ph-rabbit:before { + content: "\eac2"; +} +.ph.ph-racquet:before { + content: "\ee02"; +} +.ph.ph-radical:before { + content: "\e3ea"; +} +.ph.ph-radio:before { + content: "\e77e"; +} +.ph.ph-radio-button:before { + content: "\eb08"; +} +.ph.ph-radioactive:before { + content: "\e9dc"; +} +.ph.ph-rainbow:before { + content: "\e598"; +} +.ph.ph-rainbow-cloud:before { + content: "\e59a"; +} +.ph.ph-ranking:before { + content: "\ed62"; +} +.ph.ph-read-cv-logo:before { + content: "\ed0c"; +} +.ph.ph-receipt:before { + content: "\e3ec"; +} +.ph.ph-receipt-x:before { + content: "\ed40"; +} +.ph.ph-record:before { + content: "\e3ee"; +} +.ph.ph-rectangle:before { + content: "\e3f0"; +} +.ph.ph-rectangle-dashed:before { + content: "\e3f2"; +} +.ph.ph-recycle:before { + content: "\e75a"; +} +.ph.ph-reddit-logo:before { + content: "\e59c"; +} +.ph.ph-repeat:before { + content: "\e3f6"; +} +.ph.ph-repeat-once:before { + content: "\e3f8"; +} +.ph.ph-replit-logo:before { + content: "\eb8a"; +} +.ph.ph-resize:before { + content: "\ed6e"; +} +.ph.ph-rewind:before { + content: "\e6a8"; +} +.ph.ph-rewind-circle:before { + content: "\e3fa"; +} +.ph.ph-road-horizon:before { + content: "\e838"; +} +.ph.ph-robot:before { + content: "\e762"; +} +.ph.ph-rocket:before { + content: "\e3fc"; +} +.ph.ph-rocket-launch:before { + content: "\e3fe"; +} +.ph.ph-rows:before { + content: "\e5a2"; +} +.ph.ph-rows-plus-bottom:before { + content: "\e59e"; +} +.ph.ph-rows-plus-top:before { + content: "\e5a0"; +} +.ph.ph-rss:before { + content: "\e400"; +} +.ph.ph-rss-simple:before { + content: "\e402"; +} +.ph.ph-rug:before { + content: "\ea1a"; +} +.ph.ph-ruler:before { + content: "\e6b8"; +} +.ph.ph-sailboat:before { + content: "\e78a"; +} +.ph.ph-scales:before { + content: "\e750"; +} +.ph.ph-scan:before { + content: "\ebb6"; +} +.ph.ph-scan-smiley:before { + content: "\ebb4"; +} +.ph.ph-scissors:before { + content: "\eae0"; +} +.ph.ph-scooter:before { + content: "\e820"; +} +.ph.ph-screencast:before { + content: "\e404"; +} +.ph.ph-screwdriver:before { + content: "\e86e"; +} +.ph.ph-scribble:before { + content: "\e806"; +} +.ph.ph-scribble-loop:before { + content: "\e662"; +} +.ph.ph-scroll:before { + content: "\eb7a"; +} +.ph.ph-seal:before { + content: "\e604"; +} +.ph.ph-circle-wavy:before { + content: "\e604"; +} +.ph.ph-seal-check:before { + content: "\e606"; +} +.ph.ph-circle-wavy-check:before { + content: "\e606"; +} +.ph.ph-seal-percent:before { + content: "\e60a"; +} +.ph.ph-seal-question:before { + content: "\e608"; +} +.ph.ph-circle-wavy-question:before { + content: "\e608"; +} +.ph.ph-seal-warning:before { + content: "\e60c"; +} +.ph.ph-circle-wavy-warning:before { + content: "\e60c"; +} +.ph.ph-seat:before { + content: "\eb8e"; +} +.ph.ph-seatbelt:before { + content: "\edfe"; +} +.ph.ph-security-camera:before { + content: "\eca4"; +} +.ph.ph-selection:before { + content: "\e69a"; +} +.ph.ph-selection-all:before { + content: "\e746"; +} +.ph.ph-selection-background:before { + content: "\eaf8"; +} +.ph.ph-selection-foreground:before { + content: "\eaf6"; +} +.ph.ph-selection-inverse:before { + content: "\e744"; +} +.ph.ph-selection-plus:before { + content: "\e69c"; +} +.ph.ph-selection-slash:before { + content: "\e69e"; +} +.ph.ph-shapes:before { + content: "\ec5e"; +} +.ph.ph-share:before { + content: "\e406"; +} +.ph.ph-share-fat:before { + content: "\ed52"; +} +.ph.ph-share-network:before { + content: "\e408"; +} +.ph.ph-shield:before { + content: "\e40a"; +} +.ph.ph-shield-check:before { + content: "\e40c"; +} +.ph.ph-shield-checkered:before { + content: "\e708"; +} +.ph.ph-shield-chevron:before { + content: "\e40e"; +} +.ph.ph-shield-plus:before { + content: "\e706"; +} +.ph.ph-shield-slash:before { + content: "\e410"; +} +.ph.ph-shield-star:before { + content: "\ec34"; +} +.ph.ph-shield-warning:before { + content: "\e412"; +} +.ph.ph-shipping-container:before { + content: "\e78c"; +} +.ph.ph-shirt-folded:before { + content: "\ea92"; +} +.ph.ph-shooting-star:before { + content: "\ecfa"; +} +.ph.ph-shopping-bag:before { + content: "\e416"; +} +.ph.ph-shopping-bag-open:before { + content: "\e418"; +} +.ph.ph-shopping-cart:before { + content: "\e41e"; +} +.ph.ph-shopping-cart-simple:before { + content: "\e420"; +} +.ph.ph-shovel:before { + content: "\e9e6"; +} +.ph.ph-shower:before { + content: "\e776"; +} +.ph.ph-shrimp:before { + content: "\eab4"; +} +.ph.ph-shuffle:before { + content: "\e422"; +} +.ph.ph-shuffle-angular:before { + content: "\e424"; +} +.ph.ph-shuffle-simple:before { + content: "\e426"; +} +.ph.ph-sidebar:before { + content: "\eab6"; +} +.ph.ph-sidebar-simple:before { + content: "\ec24"; +} +.ph.ph-sigma:before { + content: "\eab8"; +} +.ph.ph-sign-in:before { + content: "\e428"; +} +.ph.ph-sign-out:before { + content: "\e42a"; +} +.ph.ph-signature:before { + content: "\ebac"; +} +.ph.ph-signpost:before { + content: "\e89c"; +} +.ph.ph-sim-card:before { + content: "\e664"; +} +.ph.ph-siren:before { + content: "\e9b8"; +} +.ph.ph-sketch-logo:before { + content: "\e42c"; +} +.ph.ph-skip-back:before { + content: "\e5a4"; +} +.ph.ph-skip-back-circle:before { + content: "\e42e"; +} +.ph.ph-skip-forward:before { + content: "\e5a6"; +} +.ph.ph-skip-forward-circle:before { + content: "\e430"; +} +.ph.ph-skull:before { + content: "\e916"; +} +.ph.ph-skype-logo:before { + content: "\e8dc"; +} +.ph.ph-slack-logo:before { + content: "\e5a8"; +} +.ph.ph-sliders:before { + content: "\e432"; +} +.ph.ph-sliders-horizontal:before { + content: "\e434"; +} +.ph.ph-slideshow:before { + content: "\ed32"; +} +.ph.ph-smiley:before { + content: "\e436"; +} +.ph.ph-smiley-angry:before { + content: "\ec62"; +} +.ph.ph-smiley-blank:before { + content: "\e438"; +} +.ph.ph-smiley-meh:before { + content: "\e43a"; +} +.ph.ph-smiley-melting:before { + content: "\ee56"; +} +.ph.ph-smiley-nervous:before { + content: "\e43c"; +} +.ph.ph-smiley-sad:before { + content: "\e43e"; +} +.ph.ph-smiley-sticker:before { + content: "\e440"; +} +.ph.ph-smiley-wink:before { + content: "\e666"; +} +.ph.ph-smiley-x-eyes:before { + content: "\e442"; +} +.ph.ph-snapchat-logo:before { + content: "\e668"; +} +.ph.ph-sneaker:before { + content: "\e80c"; +} +.ph.ph-sneaker-move:before { + content: "\ed60"; +} +.ph.ph-snowflake:before { + content: "\e5aa"; +} +.ph.ph-soccer-ball:before { + content: "\e716"; +} +.ph.ph-sock:before { + content: "\ecce"; +} +.ph.ph-solar-panel:before { + content: "\ed7a"; +} +.ph.ph-solar-roof:before { + content: "\ed7b"; +} +.ph.ph-sort-ascending:before { + content: "\e444"; +} +.ph.ph-sort-descending:before { + content: "\e446"; +} +.ph.ph-soundcloud-logo:before { + content: "\e8de"; +} +.ph.ph-spade:before { + content: "\e448"; +} +.ph.ph-sparkle:before { + content: "\e6a2"; +} +.ph.ph-speaker-hifi:before { + content: "\ea08"; +} +.ph.ph-speaker-high:before { + content: "\e44a"; +} +.ph.ph-speaker-low:before { + content: "\e44c"; +} +.ph.ph-speaker-none:before { + content: "\e44e"; +} +.ph.ph-speaker-simple-high:before { + content: "\e450"; +} +.ph.ph-speaker-simple-low:before { + content: "\e452"; +} +.ph.ph-speaker-simple-none:before { + content: "\e454"; +} +.ph.ph-speaker-simple-slash:before { + content: "\e456"; +} +.ph.ph-speaker-simple-x:before { + content: "\e458"; +} +.ph.ph-speaker-slash:before { + content: "\e45a"; +} +.ph.ph-speaker-x:before { + content: "\e45c"; +} +.ph.ph-speedometer:before { + content: "\ee74"; +} +.ph.ph-sphere:before { + content: "\ee66"; +} +.ph.ph-spinner:before { + content: "\e66a"; +} +.ph.ph-spinner-ball:before { + content: "\ee28"; +} +.ph.ph-spinner-gap:before { + content: "\e66c"; +} +.ph.ph-spiral:before { + content: "\e9fa"; +} +.ph.ph-split-horizontal:before { + content: "\e872"; +} +.ph.ph-split-vertical:before { + content: "\e876"; +} +.ph.ph-spotify-logo:before { + content: "\e66e"; +} +.ph.ph-spray-bottle:before { + content: "\e7e4"; +} +.ph.ph-square:before { + content: "\e45e"; +} +.ph.ph-square-half:before { + content: "\e462"; +} +.ph.ph-square-half-bottom:before { + content: "\eb16"; +} +.ph.ph-square-logo:before { + content: "\e690"; +} +.ph.ph-square-split-horizontal:before { + content: "\e870"; +} +.ph.ph-square-split-vertical:before { + content: "\e874"; +} +.ph.ph-squares-four:before { + content: "\e464"; +} +.ph.ph-stack:before { + content: "\e466"; +} +.ph.ph-stack-minus:before { + content: "\edf4"; +} +.ph.ph-stack-overflow-logo:before { + content: "\eb78"; +} +.ph.ph-stack-plus:before { + content: "\edf6"; +} +.ph.ph-stack-simple:before { + content: "\e468"; +} +.ph.ph-stairs:before { + content: "\e8ec"; +} +.ph.ph-stamp:before { + content: "\ea48"; +} +.ph.ph-standard-definition:before { + content: "\ea90"; +} +.ph.ph-star:before { + content: "\e46a"; +} +.ph.ph-star-and-crescent:before { + content: "\ecf4"; +} +.ph.ph-star-four:before { + content: "\e6a4"; +} +.ph.ph-star-half:before { + content: "\e70a"; +} +.ph.ph-star-of-david:before { + content: "\e89e"; +} +.ph.ph-steam-logo:before { + content: "\ead4"; +} +.ph.ph-steering-wheel:before { + content: "\e9ac"; +} +.ph.ph-steps:before { + content: "\ecbe"; +} +.ph.ph-stethoscope:before { + content: "\e7ea"; +} +.ph.ph-sticker:before { + content: "\e5ac"; +} +.ph.ph-stool:before { + content: "\ea44"; +} +.ph.ph-stop:before { + content: "\e46c"; +} +.ph.ph-stop-circle:before { + content: "\e46e"; +} +.ph.ph-storefront:before { + content: "\e470"; +} +.ph.ph-strategy:before { + content: "\ea3a"; +} +.ph.ph-stripe-logo:before { + content: "\e698"; +} +.ph.ph-student:before { + content: "\e73e"; +} +.ph.ph-subset-of:before { + content: "\edc0"; +} +.ph.ph-subset-proper-of:before { + content: "\edb6"; +} +.ph.ph-subtitles:before { + content: "\e1a8"; +} +.ph.ph-subtitles-slash:before { + content: "\e1a6"; +} +.ph.ph-subtract:before { + content: "\ebd6"; +} +.ph.ph-subtract-square:before { + content: "\ebd4"; +} +.ph.ph-subway:before { + content: "\e498"; +} +.ph.ph-suitcase:before { + content: "\e5ae"; +} +.ph.ph-suitcase-rolling:before { + content: "\e9b0"; +} +.ph.ph-suitcase-simple:before { + content: "\e5b0"; +} +.ph.ph-sun:before { + content: "\e472"; +} +.ph.ph-sun-dim:before { + content: "\e474"; +} +.ph.ph-sun-horizon:before { + content: "\e5b6"; +} +.ph.ph-sunglasses:before { + content: "\e816"; +} +.ph.ph-superset-of:before { + content: "\edb8"; +} +.ph.ph-superset-proper-of:before { + content: "\edb4"; +} +.ph.ph-swap:before { + content: "\e83c"; +} +.ph.ph-swatches:before { + content: "\e5b8"; +} +.ph.ph-swimming-pool:before { + content: "\ecb6"; +} +.ph.ph-sword:before { + content: "\e5ba"; +} +.ph.ph-synagogue:before { + content: "\ecec"; +} +.ph.ph-syringe:before { + content: "\e968"; +} +.ph.ph-t-shirt:before { + content: "\e670"; +} +.ph.ph-table:before { + content: "\e476"; +} +.ph.ph-tabs:before { + content: "\e778"; +} +.ph.ph-tag:before { + content: "\e478"; +} +.ph.ph-tag-chevron:before { + content: "\e672"; +} +.ph.ph-tag-simple:before { + content: "\e47a"; +} +.ph.ph-target:before { + content: "\e47c"; +} +.ph.ph-taxi:before { + content: "\e902"; +} +.ph.ph-tea-bag:before { + content: "\e8e6"; +} +.ph.ph-telegram-logo:before { + content: "\e5bc"; +} +.ph.ph-television:before { + content: "\e754"; +} +.ph.ph-television-simple:before { + content: "\eae6"; +} +.ph.ph-tennis-ball:before { + content: "\e720"; +} +.ph.ph-tent:before { + content: "\e8ba"; +} +.ph.ph-terminal:before { + content: "\e47e"; +} +.ph.ph-terminal-window:before { + content: "\eae8"; +} +.ph.ph-test-tube:before { + content: "\e7a0"; +} +.ph.ph-text-a-underline:before { + content: "\ed34"; +} +.ph.ph-text-aa:before { + content: "\e6ee"; +} +.ph.ph-text-align-center:before { + content: "\e480"; +} +.ph.ph-text-align-justify:before { + content: "\e482"; +} +.ph.ph-text-align-left:before { + content: "\e484"; +} +.ph.ph-text-align-right:before { + content: "\e486"; +} +.ph.ph-text-b:before { + content: "\e5be"; +} +.ph.ph-text-bolder:before { + content: "\e5be"; +} +.ph.ph-text-columns:before { + content: "\ec96"; +} +.ph.ph-text-h:before { + content: "\e6ba"; +} +.ph.ph-text-h-five:before { + content: "\e6c4"; +} +.ph.ph-text-h-four:before { + content: "\e6c2"; +} +.ph.ph-text-h-one:before { + content: "\e6bc"; +} +.ph.ph-text-h-six:before { + content: "\e6c6"; +} +.ph.ph-text-h-three:before { + content: "\e6c0"; +} +.ph.ph-text-h-two:before { + content: "\e6be"; +} +.ph.ph-text-indent:before { + content: "\ea1e"; +} +.ph.ph-text-italic:before { + content: "\e5c0"; +} +.ph.ph-text-outdent:before { + content: "\ea1c"; +} +.ph.ph-text-strikethrough:before { + content: "\e5c2"; +} +.ph.ph-text-subscript:before { + content: "\ec98"; +} +.ph.ph-text-superscript:before { + content: "\ec9a"; +} +.ph.ph-text-t:before { + content: "\e48a"; +} +.ph.ph-text-t-slash:before { + content: "\e488"; +} +.ph.ph-text-underline:before { + content: "\e5c4"; +} +.ph.ph-textbox:before { + content: "\eb0a"; +} +.ph.ph-thermometer:before { + content: "\e5c6"; +} +.ph.ph-thermometer-cold:before { + content: "\e5c8"; +} +.ph.ph-thermometer-hot:before { + content: "\e5ca"; +} +.ph.ph-thermometer-simple:before { + content: "\e5cc"; +} +.ph.ph-threads-logo:before { + content: "\ed9e"; +} +.ph.ph-three-d:before { + content: "\ea5a"; +} +.ph.ph-thumbs-down:before { + content: "\e48c"; +} +.ph.ph-thumbs-up:before { + content: "\e48e"; +} +.ph.ph-ticket:before { + content: "\e490"; +} +.ph.ph-tidal-logo:before { + content: "\ed1c"; +} +.ph.ph-tiktok-logo:before { + content: "\eaf2"; +} +.ph.ph-tilde:before { + content: "\eda8"; +} +.ph.ph-timer:before { + content: "\e492"; +} +.ph.ph-tip-jar:before { + content: "\e7e2"; +} +.ph.ph-tipi:before { + content: "\ed30"; +} +.ph.ph-tire:before { + content: "\edd2"; +} +.ph.ph-toggle-left:before { + content: "\e674"; +} +.ph.ph-toggle-right:before { + content: "\e676"; +} +.ph.ph-toilet:before { + content: "\e79a"; +} +.ph.ph-toilet-paper:before { + content: "\e79c"; +} +.ph.ph-toolbox:before { + content: "\eca0"; +} +.ph.ph-tooth:before { + content: "\e9cc"; +} +.ph.ph-tornado:before { + content: "\e88c"; +} +.ph.ph-tote:before { + content: "\e494"; +} +.ph.ph-tote-simple:before { + content: "\e678"; +} +.ph.ph-towel:before { + content: "\ede6"; +} +.ph.ph-tractor:before { + content: "\ec6e"; +} +.ph.ph-trademark:before { + content: "\e9f0"; +} +.ph.ph-trademark-registered:before { + content: "\e3f4"; +} +.ph.ph-traffic-cone:before { + content: "\e9a8"; +} +.ph.ph-traffic-sign:before { + content: "\e67a"; +} +.ph.ph-traffic-signal:before { + content: "\e9aa"; +} +.ph.ph-train:before { + content: "\e496"; +} +.ph.ph-train-regional:before { + content: "\e49e"; +} +.ph.ph-train-simple:before { + content: "\e4a0"; +} +.ph.ph-tram:before { + content: "\e9ec"; +} +.ph.ph-translate:before { + content: "\e4a2"; +} +.ph.ph-trash:before { + content: "\e4a6"; +} +.ph.ph-trash-simple:before { + content: "\e4a8"; +} +.ph.ph-tray:before { + content: "\e4aa"; +} +.ph.ph-tray-arrow-down:before { + content: "\e010"; +} +.ph.ph-archive-tray:before { + content: "\e010"; +} +.ph.ph-tray-arrow-up:before { + content: "\ee52"; +} +.ph.ph-treasure-chest:before { + content: "\ede2"; +} +.ph.ph-tree:before { + content: "\e6da"; +} +.ph.ph-tree-evergreen:before { + content: "\e6dc"; +} +.ph.ph-tree-palm:before { + content: "\e91a"; +} +.ph.ph-tree-structure:before { + content: "\e67c"; +} +.ph.ph-tree-view:before { + content: "\ee48"; +} +.ph.ph-trend-down:before { + content: "\e4ac"; +} +.ph.ph-trend-up:before { + content: "\e4ae"; +} +.ph.ph-triangle:before { + content: "\e4b0"; +} +.ph.ph-triangle-dashed:before { + content: "\e4b2"; +} +.ph.ph-trolley:before { + content: "\e5b2"; +} +.ph.ph-trolley-suitcase:before { + content: "\e5b4"; +} +.ph.ph-trophy:before { + content: "\e67e"; +} +.ph.ph-truck:before { + content: "\e4b4"; +} +.ph.ph-truck-trailer:before { + content: "\e4b6"; +} +.ph.ph-tumblr-logo:before { + content: "\e8d4"; +} +.ph.ph-twitch-logo:before { + content: "\e5ce"; +} +.ph.ph-twitter-logo:before { + content: "\e4ba"; +} +.ph.ph-umbrella:before { + content: "\e684"; +} +.ph.ph-umbrella-simple:before { + content: "\e686"; +} +.ph.ph-union:before { + content: "\edbe"; +} +.ph.ph-unite:before { + content: "\e87e"; +} +.ph.ph-unite-square:before { + content: "\e878"; +} +.ph.ph-upload:before { + content: "\e4be"; +} +.ph.ph-upload-simple:before { + content: "\e4c0"; +} +.ph.ph-usb:before { + content: "\e956"; +} +.ph.ph-user:before { + content: "\e4c2"; +} +.ph.ph-user-check:before { + content: "\eafa"; +} +.ph.ph-user-circle:before { + content: "\e4c4"; +} +.ph.ph-user-circle-check:before { + content: "\ec38"; +} +.ph.ph-user-circle-dashed:before { + content: "\ec36"; +} +.ph.ph-user-circle-gear:before { + content: "\e4c6"; +} +.ph.ph-user-circle-minus:before { + content: "\e4c8"; +} +.ph.ph-user-circle-plus:before { + content: "\e4ca"; +} +.ph.ph-user-focus:before { + content: "\e6fc"; +} +.ph.ph-user-gear:before { + content: "\e4cc"; +} +.ph.ph-user-list:before { + content: "\e73c"; +} +.ph.ph-user-minus:before { + content: "\e4ce"; +} +.ph.ph-user-plus:before { + content: "\e4d0"; +} +.ph.ph-user-rectangle:before { + content: "\e4d2"; +} +.ph.ph-user-sound:before { + content: "\eca8"; +} +.ph.ph-user-square:before { + content: "\e4d4"; +} +.ph.ph-user-switch:before { + content: "\e756"; +} +.ph.ph-users:before { + content: "\e4d6"; +} +.ph.ph-users-four:before { + content: "\e68c"; +} +.ph.ph-users-three:before { + content: "\e68e"; +} +.ph.ph-van:before { + content: "\e826"; +} +.ph.ph-vault:before { + content: "\e76e"; +} +.ph.ph-vector-three:before { + content: "\ee62"; +} +.ph.ph-vector-two:before { + content: "\ee64"; +} +.ph.ph-vibrate:before { + content: "\e4d8"; +} +.ph.ph-video:before { + content: "\e740"; +} +.ph.ph-video-camera:before { + content: "\e4da"; +} +.ph.ph-video-camera-slash:before { + content: "\e4dc"; +} +.ph.ph-video-conference:before { + content: "\edce"; +} +.ph.ph-vignette:before { + content: "\eba2"; +} +.ph.ph-vinyl-record:before { + content: "\ecac"; +} +.ph.ph-virtual-reality:before { + content: "\e7b8"; +} +.ph.ph-virus:before { + content: "\e7d6"; +} +.ph.ph-visor:before { + content: "\ee2a"; +} +.ph.ph-voicemail:before { + content: "\e4de"; +} +.ph.ph-volleyball:before { + content: "\e726"; +} +.ph.ph-wall:before { + content: "\e688"; +} +.ph.ph-wallet:before { + content: "\e68a"; +} +.ph.ph-warehouse:before { + content: "\ecd4"; +} +.ph.ph-warning:before { + content: "\e4e0"; +} +.ph.ph-warning-circle:before { + content: "\e4e2"; +} +.ph.ph-warning-diamond:before { + content: "\e7fc"; +} +.ph.ph-warning-octagon:before { + content: "\e4e4"; +} +.ph.ph-washing-machine:before { + content: "\ede8"; +} +.ph.ph-watch:before { + content: "\e4e6"; +} +.ph.ph-wave-sawtooth:before { + content: "\ea9c"; +} +.ph.ph-wave-sine:before { + content: "\ea9a"; +} +.ph.ph-wave-square:before { + content: "\ea9e"; +} +.ph.ph-wave-triangle:before { + content: "\eaa0"; +} +.ph.ph-waveform:before { + content: "\e802"; +} +.ph.ph-waveform-slash:before { + content: "\e800"; +} +.ph.ph-waves:before { + content: "\e6de"; +} +.ph.ph-webcam:before { + content: "\e9b2"; +} +.ph.ph-webcam-slash:before { + content: "\ecdc"; +} +.ph.ph-webhooks-logo:before { + content: "\ecae"; +} +.ph.ph-wechat-logo:before { + content: "\e8d2"; +} +.ph.ph-whatsapp-logo:before { + content: "\e5d0"; +} +.ph.ph-wheelchair:before { + content: "\e4e8"; +} +.ph.ph-wheelchair-motion:before { + content: "\e89a"; +} +.ph.ph-wifi-high:before { + content: "\e4ea"; +} +.ph.ph-wifi-low:before { + content: "\e4ec"; +} +.ph.ph-wifi-medium:before { + content: "\e4ee"; +} +.ph.ph-wifi-none:before { + content: "\e4f0"; +} +.ph.ph-wifi-slash:before { + content: "\e4f2"; +} +.ph.ph-wifi-x:before { + content: "\e4f4"; +} +.ph.ph-wind:before { + content: "\e5d2"; +} +.ph.ph-windmill:before { + content: "\e9f8"; +} +.ph.ph-windows-logo:before { + content: "\e692"; +} +.ph.ph-wine:before { + content: "\e6b2"; +} +.ph.ph-wrench:before { + content: "\e5d4"; +} +.ph.ph-x:before { + content: "\e4f6"; +} +.ph.ph-x-circle:before { + content: "\e4f8"; +} +.ph.ph-x-logo:before { + content: "\e4bc"; +} +.ph.ph-x-square:before { + content: "\e4fa"; +} +.ph.ph-yarn:before { + content: "\ed9a"; +} +.ph.ph-yin-yang:before { + content: "\e92a"; +} +.ph.ph-youtube-logo:before { + content: "\e4fc"; +} diff --git a/crates/carpet-ui/assets/tailwind.css b/crates/carpet-ui/assets/tailwind.css new file mode 100644 index 0000000..8497e98 --- /dev/null +++ b/crates/carpet-ui/assets/tailwind.css @@ -0,0 +1,903 @@ +/*! tailwindcss v4.2.1 | MIT License | https://tailwindcss.com */ +@layer properties; +@layer theme, base, components, utilities; +@layer theme { + :root, :host { + --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", + "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", + "Courier New", monospace; + --color-orange-400: oklch(75% 0.183 55.934); + --color-orange-500: oklch(70.5% 0.213 47.604); + --color-amber-300: oklch(87.9% 0.169 91.605); + --color-amber-400: oklch(82.8% 0.189 84.429); + --color-emerald-400: oklch(76.5% 0.177 163.223); + --color-blue-400: oklch(70.7% 0.165 254.624); + --color-gray-100: oklch(96.7% 0.003 264.542); + --color-gray-200: oklch(92.8% 0.006 264.531); + --color-gray-300: oklch(87.2% 0.01 258.338); + --color-gray-400: oklch(70.7% 0.022 261.325); + --color-gray-500: oklch(55.1% 0.027 264.364); + --color-gray-600: oklch(44.6% 0.03 256.802); + --color-gray-700: oklch(37.3% 0.034 259.733); + --color-gray-800: oklch(27.8% 0.033 256.848); + --color-gray-900: oklch(21% 0.034 264.665); + --color-gray-950: oklch(13% 0.028 261.692); + --color-white: #fff; + --spacing: 0.25rem; + --container-xl: 36rem; + --container-2xl: 42rem; + --container-3xl: 48rem; + --container-4xl: 56rem; + --container-7xl: 80rem; + --text-xs: 0.75rem; + --text-xs--line-height: calc(1 / 0.75); + --text-sm: 0.875rem; + --text-sm--line-height: calc(1.25 / 0.875); + --text-lg: 1.125rem; + --text-lg--line-height: calc(1.75 / 1.125); + --text-xl: 1.25rem; + --text-xl--line-height: calc(1.75 / 1.25); + --text-2xl: 1.5rem; + --text-2xl--line-height: calc(2 / 1.5); + --text-3xl: 1.875rem; + --text-3xl--line-height: calc(2.25 / 1.875); + --text-4xl: 2.25rem; + --text-4xl--line-height: calc(2.5 / 2.25); + --font-weight-medium: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + --radius-lg: 0.5rem; + --radius-xl: 0.75rem; + --blur-md: 12px; + --default-transition-duration: 150ms; + --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); + --default-font-family: var(--font-sans); + --default-mono-font-family: var(--font-mono); + } +} +@layer base { + *, ::after, ::before, ::backdrop, ::file-selector-button { + box-sizing: border-box; + margin: 0; + padding: 0; + border: 0 solid; + } + html, :host { + line-height: 1.5; + -webkit-text-size-adjust: 100%; + tab-size: 4; + font-family: var(--default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"); + font-feature-settings: var(--default-font-feature-settings, normal); + font-variation-settings: var(--default-font-variation-settings, normal); + -webkit-tap-highlight-color: transparent; + } + hr { + height: 0; + color: inherit; + border-top-width: 1px; + } + abbr:where([title]) { + -webkit-text-decoration: underline dotted; + text-decoration: underline dotted; + } + h1, h2, h3, h4, h5, h6 { + font-size: inherit; + font-weight: inherit; + } + a { + color: inherit; + -webkit-text-decoration: inherit; + text-decoration: inherit; + } + b, strong { + font-weight: bolder; + } + code, kbd, samp, pre { + font-family: var(--default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace); + font-feature-settings: var(--default-mono-font-feature-settings, normal); + font-variation-settings: var(--default-mono-font-variation-settings, normal); + font-size: 1em; + } + small { + font-size: 80%; + } + sub, sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; + } + sub { + bottom: -0.25em; + } + sup { + top: -0.5em; + } + table { + text-indent: 0; + border-color: inherit; + border-collapse: collapse; + } + :-moz-focusring { + outline: auto; + } + progress { + vertical-align: baseline; + } + summary { + display: list-item; + } + ol, ul, menu { + list-style: none; + } + img, svg, video, canvas, audio, iframe, embed, object { + display: block; + vertical-align: middle; + } + img, video { + max-width: 100%; + height: auto; + } + button, input, select, optgroup, textarea, ::file-selector-button { + font: inherit; + font-feature-settings: inherit; + font-variation-settings: inherit; + letter-spacing: inherit; + color: inherit; + border-radius: 0; + background-color: transparent; + opacity: 1; + } + :where(select:is([multiple], [size])) optgroup { + font-weight: bolder; + } + :where(select:is([multiple], [size])) optgroup option { + padding-inline-start: 20px; + } + ::file-selector-button { + margin-inline-end: 4px; + } + ::placeholder { + opacity: 1; + } + @supports (not (-webkit-appearance: -apple-pay-button)) or (contain-intrinsic-size: 1px) { + ::placeholder { + color: currentcolor; + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, currentcolor 50%, transparent); + } + } + } + textarea { + resize: vertical; + } + ::-webkit-search-decoration { + -webkit-appearance: none; + } + ::-webkit-date-and-time-value { + min-height: 1lh; + text-align: inherit; + } + ::-webkit-datetime-edit { + display: inline-flex; + } + ::-webkit-datetime-edit-fields-wrapper { + padding: 0; + } + ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field { + padding-block: 0; + } + ::-webkit-calendar-picker-indicator { + line-height: 1; + } + :-moz-ui-invalid { + box-shadow: none; + } + button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button { + appearance: button; + } + ::-webkit-inner-spin-button, ::-webkit-outer-spin-button { + height: auto; + } + [hidden]:where(:not([hidden="until-found"])) { + display: none !important; + } +} +@layer utilities { + .visible { + visibility: visible; + } + .absolute { + position: absolute; + } + .fixed { + position: fixed; + } + .relative { + position: relative; + } + .static { + position: static; + } + .start { + inset-inline-start: var(--spacing); + } + .top-0 { + top: calc(var(--spacing) * 0); + } + .top-1\/2 { + top: calc(1 / 2 * 100%); + } + .right-0 { + right: calc(var(--spacing) * 0); + } + .left-0 { + left: calc(var(--spacing) * 0); + } + .left-3 { + left: calc(var(--spacing) * 3); + } + .z-50 { + z-index: 50; + } + .mx-auto { + margin-inline: auto; + } + .mt-2 { + margin-top: calc(var(--spacing) * 2); + } + .mr-1 { + margin-right: calc(var(--spacing) * 1); + } + .mb-1 { + margin-bottom: calc(var(--spacing) * 1); + } + .mb-2 { + margin-bottom: calc(var(--spacing) * 2); + } + .mb-3 { + margin-bottom: calc(var(--spacing) * 3); + } + .mb-4 { + margin-bottom: calc(var(--spacing) * 4); + } + .mb-6 { + margin-bottom: calc(var(--spacing) * 6); + } + .mb-8 { + margin-bottom: calc(var(--spacing) * 8); + } + .mb-10 { + margin-bottom: calc(var(--spacing) * 10); + } + .ml-2 { + margin-left: calc(var(--spacing) * 2); + } + .line-clamp-2 { + overflow: hidden; + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; + } + .block { + display: block; + } + .contents { + display: contents; + } + .flex { + display: flex; + } + .grid { + display: grid; + } + .inline-flex { + display: inline-flex; + } + .h-2 { + height: calc(var(--spacing) * 2); + } + .h-7 { + height: calc(var(--spacing) * 7); + } + .h-10 { + height: calc(var(--spacing) * 10); + } + .h-14 { + height: calc(var(--spacing) * 14); + } + .h-16 { + height: calc(var(--spacing) * 16); + } + .min-h-screen { + min-height: 100vh; + } + .w-2 { + width: calc(var(--spacing) * 2); + } + .w-7 { + width: calc(var(--spacing) * 7); + } + .w-10 { + width: calc(var(--spacing) * 10); + } + .w-16 { + width: calc(var(--spacing) * 16); + } + .w-full { + width: 100%; + } + .max-w-2xl { + max-width: var(--container-2xl); + } + .max-w-3xl { + max-width: var(--container-3xl); + } + .max-w-4xl { + max-width: var(--container-4xl); + } + .max-w-7xl { + max-width: var(--container-7xl); + } + .max-w-xl { + max-width: var(--container-xl); + } + .flex-1 { + flex: 1; + } + .-translate-y-1\/2 { + --tw-translate-y: calc(calc(1 / 2 * 100%) * -1); + translate: var(--tw-translate-x) var(--tw-translate-y); + } + .cursor-pointer { + cursor: pointer; + } + .grid-cols-1 { + grid-template-columns: repeat(1, minmax(0, 1fr)); + } + .flex-wrap { + flex-wrap: wrap; + } + .items-center { + align-items: center; + } + .items-start { + align-items: flex-start; + } + .justify-between { + justify-content: space-between; + } + .justify-center { + justify-content: center; + } + .gap-1 { + gap: calc(var(--spacing) * 1); + } + .gap-1\.5 { + gap: calc(var(--spacing) * 1.5); + } + .gap-2 { + gap: calc(var(--spacing) * 2); + } + .gap-3 { + gap: calc(var(--spacing) * 3); + } + .gap-4 { + gap: calc(var(--spacing) * 4); + } + .gap-6 { + gap: calc(var(--spacing) * 6); + } + .space-y-1 { + :where(& > :not(:last-child)) { + --tw-space-y-reverse: 0; + margin-block-start: calc(calc(var(--spacing) * 1) * var(--tw-space-y-reverse)); + margin-block-end: calc(calc(var(--spacing) * 1) * calc(1 - var(--tw-space-y-reverse))); + } + } + .space-y-2 { + :where(& > :not(:last-child)) { + --tw-space-y-reverse: 0; + margin-block-start: calc(calc(var(--spacing) * 2) * var(--tw-space-y-reverse)); + margin-block-end: calc(calc(var(--spacing) * 2) * calc(1 - var(--tw-space-y-reverse))); + } + } + .gap-x-4 { + column-gap: calc(var(--spacing) * 4); + } + .gap-y-1 { + row-gap: calc(var(--spacing) * 1); + } + .rounded-full { + border-radius: calc(infinity * 1px); + } + .rounded-lg { + border-radius: var(--radius-lg); + } + .rounded-xl { + border-radius: var(--radius-xl); + } + .border { + border-style: var(--tw-border-style); + border-width: 1px; + } + .border-b { + border-bottom-style: var(--tw-border-style); + border-bottom-width: 1px; + } + .border-blue-400\/20 { + border-color: color-mix(in srgb, oklch(70.7% 0.165 254.624) 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-blue-400) 20%, transparent); + } + } + .border-emerald-400\/20 { + border-color: color-mix(in srgb, oklch(76.5% 0.177 163.223) 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-emerald-400) 20%, transparent); + } + } + .border-gray-400\/20 { + border-color: color-mix(in srgb, oklch(70.7% 0.022 261.325) 20%, transparent); + @supports (color: color-mix(in lab, red, red)) { + border-color: color-mix(in oklab, var(--color-gray-400) 20%, transparent); + } + } + .border-gray-800 { + border-color: var(--color-gray-800); + } + .bg-amber-400 { + background-color: var(--color-amber-400); + } + .bg-blue-400\/10 { + background-color: color-mix(in srgb, oklch(70.7% 0.165 254.624) 10%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-blue-400) 10%, transparent); + } + } + .bg-emerald-400 { + background-color: var(--color-emerald-400); + } + .bg-emerald-400\/10 { + background-color: color-mix(in srgb, oklch(76.5% 0.177 163.223) 10%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-emerald-400) 10%, transparent); + } + } + .bg-gray-400\/10 { + background-color: color-mix(in srgb, oklch(70.7% 0.022 261.325) 10%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-gray-400) 10%, transparent); + } + } + .bg-gray-800 { + background-color: var(--color-gray-800); + } + .bg-gray-900 { + background-color: var(--color-gray-900); + } + .bg-gray-900\/50 { + background-color: color-mix(in srgb, oklch(21% 0.034 264.665) 50%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-gray-900) 50%, transparent); + } + } + .bg-gray-900\/80 { + background-color: color-mix(in srgb, oklch(21% 0.034 264.665) 80%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-gray-900) 80%, transparent); + } + } + .bg-gray-950 { + background-color: var(--color-gray-950); + } + .bg-orange-500 { + background-color: var(--color-orange-500); + } + .p-4 { + padding: calc(var(--spacing) * 4); + } + .p-5 { + padding: calc(var(--spacing) * 5); + } + .p-6 { + padding: calc(var(--spacing) * 6); + } + .px-2 { + padding-inline: calc(var(--spacing) * 2); + } + .px-2\.5 { + padding-inline: calc(var(--spacing) * 2.5); + } + .px-3 { + padding-inline: calc(var(--spacing) * 3); + } + .px-4 { + padding-inline: calc(var(--spacing) * 4); + } + .px-6 { + padding-inline: calc(var(--spacing) * 6); + } + .py-0\.5 { + padding-block: calc(var(--spacing) * 0.5); + } + .py-1 { + padding-block: calc(var(--spacing) * 1); + } + .py-1\.5 { + padding-block: calc(var(--spacing) * 1.5); + } + .py-2 { + padding-block: calc(var(--spacing) * 2); + } + .py-2\.5 { + padding-block: calc(var(--spacing) * 2.5); + } + .py-3 { + padding-block: calc(var(--spacing) * 3); + } + .py-8 { + padding-block: calc(var(--spacing) * 8); + } + .py-20 { + padding-block: calc(var(--spacing) * 20); + } + .pt-14 { + padding-top: calc(var(--spacing) * 14); + } + .pr-4 { + padding-right: calc(var(--spacing) * 4); + } + .pl-10 { + padding-left: calc(var(--spacing) * 10); + } + .text-center { + text-align: center; + } + .font-mono { + font-family: var(--font-mono); + } + .text-2xl { + font-size: var(--text-2xl); + line-height: var(--tw-leading, var(--text-2xl--line-height)); + } + .text-3xl { + font-size: var(--text-3xl); + line-height: var(--tw-leading, var(--text-3xl--line-height)); + } + .text-4xl { + font-size: var(--text-4xl); + line-height: var(--tw-leading, var(--text-4xl--line-height)); + } + .text-lg { + font-size: var(--text-lg); + line-height: var(--tw-leading, var(--text-lg--line-height)); + } + .text-sm { + font-size: var(--text-sm); + line-height: var(--tw-leading, var(--text-sm--line-height)); + } + .text-xl { + font-size: var(--text-xl); + line-height: var(--tw-leading, var(--text-xl--line-height)); + } + .text-xs { + font-size: var(--text-xs); + line-height: var(--tw-leading, var(--text-xs--line-height)); + } + .font-bold { + --tw-font-weight: var(--font-weight-bold); + font-weight: var(--font-weight-bold); + } + .font-medium { + --tw-font-weight: var(--font-weight-medium); + font-weight: var(--font-weight-medium); + } + .font-semibold { + --tw-font-weight: var(--font-weight-semibold); + font-weight: var(--font-weight-semibold); + } + .break-all { + word-break: break-all; + } + .text-amber-400 { + color: var(--color-amber-400); + } + .text-amber-400\/70 { + color: color-mix(in srgb, oklch(82.8% 0.189 84.429) 70%, transparent); + @supports (color: color-mix(in lab, red, red)) { + color: color-mix(in oklab, var(--color-amber-400) 70%, transparent); + } + } + .text-blue-400 { + color: var(--color-blue-400); + } + .text-emerald-400 { + color: var(--color-emerald-400); + } + .text-gray-100 { + color: var(--color-gray-100); + } + .text-gray-200 { + color: var(--color-gray-200); + } + .text-gray-300 { + color: var(--color-gray-300); + } + .text-gray-400 { + color: var(--color-gray-400); + } + .text-gray-500 { + color: var(--color-gray-500); + } + .text-gray-600 { + color: var(--color-gray-600); + } + .text-gray-950 { + color: var(--color-gray-950); + } + .text-orange-500 { + color: var(--color-orange-500); + } + .text-white { + color: var(--color-white); + } + .placeholder-gray-500 { + &::placeholder { + color: var(--color-gray-500); + } + } + .filter { + filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,); + } + .backdrop-blur-md { + --tw-backdrop-blur: blur(var(--blur-md)); + -webkit-backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); + backdrop-filter: var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,); + } + .transition-colors { + transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to; + transition-timing-function: var(--tw-ease, var(--default-transition-timing-function)); + transition-duration: var(--tw-duration, var(--default-transition-duration)); + } + .group-hover\:text-orange-400 { + &:is(:where(.group):hover *) { + @media (hover: hover) { + color: var(--color-orange-400); + } + } + } + .hover\:border-gray-700 { + &:hover { + @media (hover: hover) { + border-color: var(--color-gray-700); + } + } + } + .hover\:bg-amber-300 { + &:hover { + @media (hover: hover) { + background-color: var(--color-amber-300); + } + } + } + .hover\:bg-gray-700 { + &:hover { + @media (hover: hover) { + background-color: var(--color-gray-700); + } + } + } + .hover\:bg-gray-800 { + &:hover { + @media (hover: hover) { + background-color: var(--color-gray-800); + } + } + } + .hover\:bg-gray-900\/80 { + &:hover { + @media (hover: hover) { + background-color: color-mix(in srgb, oklch(21% 0.034 264.665) 80%, transparent); + @supports (color: color-mix(in lab, red, red)) { + background-color: color-mix(in oklab, var(--color-gray-900) 80%, transparent); + } + } + } + } + .hover\:text-gray-200 { + &:hover { + @media (hover: hover) { + color: var(--color-gray-200); + } + } + } + .hover\:text-gray-400 { + &:hover { + @media (hover: hover) { + color: var(--color-gray-400); + } + } + } + .hover\:text-orange-400 { + &:hover { + @media (hover: hover) { + color: var(--color-orange-400); + } + } + } + .focus\:border-gray-700 { + &:focus { + border-color: var(--color-gray-700); + } + } + .focus\:outline-none { + &:focus { + --tw-outline-style: none; + outline-style: none; + } + } + .md\:grid-cols-2 { + @media (width >= 48rem) { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + } + .lg\:grid-cols-3 { + @media (width >= 64rem) { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + } +} +@property --tw-translate-x { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-translate-y { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-translate-z { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-space-y-reverse { + syntax: "*"; + inherits: false; + initial-value: 0; +} +@property --tw-border-style { + syntax: "*"; + inherits: false; + initial-value: solid; +} +@property --tw-font-weight { + syntax: "*"; + inherits: false; +} +@property --tw-blur { + syntax: "*"; + inherits: false; +} +@property --tw-brightness { + syntax: "*"; + inherits: false; +} +@property --tw-contrast { + syntax: "*"; + inherits: false; +} +@property --tw-grayscale { + syntax: "*"; + inherits: false; +} +@property --tw-hue-rotate { + syntax: "*"; + inherits: false; +} +@property --tw-invert { + syntax: "*"; + inherits: false; +} +@property --tw-opacity { + syntax: "*"; + inherits: false; +} +@property --tw-saturate { + syntax: "*"; + inherits: false; +} +@property --tw-sepia { + syntax: "*"; + inherits: false; +} +@property --tw-drop-shadow { + syntax: "*"; + inherits: false; +} +@property --tw-drop-shadow-color { + syntax: "*"; + inherits: false; +} +@property --tw-drop-shadow-alpha { + syntax: ""; + inherits: false; + initial-value: 100%; +} +@property --tw-drop-shadow-size { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-blur { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-brightness { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-contrast { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-grayscale { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-hue-rotate { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-invert { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-opacity { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-saturate { + syntax: "*"; + inherits: false; +} +@property --tw-backdrop-sepia { + syntax: "*"; + inherits: false; +} +@layer properties { + @supports ((-webkit-hyphens: none) and (not (margin-trim: inline))) or ((-moz-orient: inline) and (not (color:rgb(from red r g b)))) { + *, ::before, ::after, ::backdrop { + --tw-translate-x: 0; + --tw-translate-y: 0; + --tw-translate-z: 0; + --tw-space-y-reverse: 0; + --tw-border-style: solid; + --tw-font-weight: initial; + --tw-blur: initial; + --tw-brightness: initial; + --tw-contrast: initial; + --tw-grayscale: initial; + --tw-hue-rotate: initial; + --tw-invert: initial; + --tw-opacity: initial; + --tw-saturate: initial; + --tw-sepia: initial; + --tw-drop-shadow: initial; + --tw-drop-shadow-color: initial; + --tw-drop-shadow-alpha: 100%; + --tw-drop-shadow-size: initial; + --tw-backdrop-blur: initial; + --tw-backdrop-brightness: initial; + --tw-backdrop-contrast: initial; + --tw-backdrop-grayscale: initial; + --tw-backdrop-hue-rotate: initial; + --tw-backdrop-invert: initial; + --tw-backdrop-opacity: initial; + --tw-backdrop-saturate: initial; + --tw-backdrop-sepia: initial; + } + } +} diff --git a/crates/carpet-ui/input.css b/crates/carpet-ui/input.css new file mode 100644 index 0000000..1cbfd34 --- /dev/null +++ b/crates/carpet-ui/input.css @@ -0,0 +1,2 @@ +@import "tailwindcss"; +@source "./src/**/*.rs"; diff --git a/crates/carpet-ui/src/app.rs b/crates/carpet-ui/src/app.rs index 00ffffa..621b30f 100644 --- a/crates/carpet-ui/src/app.rs +++ b/crates/carpet-ui/src/app.rs @@ -1,17 +1,20 @@ use dioxus::prelude::*; +use crate::mock_data; use crate::routes::Route; use crate::state::marketplace::MarketplaceState; -use crate::state::nostr::NostrState; -use crate::state::wallet::WalletState; +static TAILWIND: Asset = asset!("/assets/tailwind.css"); +static PHOSPHOR: Asset = asset!("/assets/phosphor.css"); pub fn App() -> Element { - // Provide global state via context - use_context_provider(|| Signal::new(NostrState::default())); - use_context_provider(|| Signal::new(WalletState::default())); + use_context_provider(|| Signal::new(mock_data::nostr_state())); + use_context_provider(|| Signal::new(mock_data::wallet_state())); use_context_provider(|| Signal::new(MarketplaceState::default())); + use_context_provider(|| Signal::new(mock_data::mock_lists())); rsx! { + document::Stylesheet { href: TAILWIND } + document::Stylesheet { href: PHOSPHOR } Router:: {} } } diff --git a/crates/carpet-ui/src/components/bounty_card.rs b/crates/carpet-ui/src/components/bounty_card.rs new file mode 100644 index 0000000..f5b2750 --- /dev/null +++ b/crates/carpet-ui/src/components/bounty_card.rs @@ -0,0 +1,51 @@ +use dioxus::prelude::*; + +use crate::routes::Route; +use crate::types::{BountyDisplay, BountyStatus}; + +#[component] +pub fn BountyCard(bounty: BountyDisplay) -> Element { + let (badge_class, badge_text) = match bounty.status { + BountyStatus::Open => ( + "bg-emerald-400/10 text-emerald-400 border border-emerald-400/20", + "Open", + ), + BountyStatus::Fulfilled => ( + "bg-blue-400/10 text-blue-400 border border-blue-400/20", + "Fulfilled", + ), + BountyStatus::Expired => ( + "bg-gray-400/10 text-gray-400 border border-gray-400/20", + "Expired", + ), + }; + + rsx! { + div { class: "bg-gray-900 border border-gray-800 rounded-xl p-5 hover:border-gray-700 transition-colors", + div { class: "flex items-center justify-between mb-3", + span { class: "px-3 py-1 rounded-full text-xs font-medium {badge_class}", + "{badge_text}" + } + span { class: "text-amber-400 font-mono font-bold text-lg", + i { class: "ph ph-lightning mr-1" } + "{bounty.reward_sats} sats" + } + } + h3 { class: "text-gray-100 font-semibold mb-2", + "Bounty for " + Link { + to: Route::ListDetailPage { coordinate: bounty.target_list_coordinate }, + class: "text-orange-500 hover:text-orange-400", + "{bounty.target_list_name}" + } + } + p { class: "text-gray-400 text-sm mb-4", + "{bounty.criteria}" + } + div { class: "flex items-center gap-2 text-gray-500 text-sm", + i { class: "ph ph-user-circle" } + span { "{bounty.creator_name}" } + } + } + } +} diff --git a/crates/carpet-ui/src/components/layout.rs b/crates/carpet-ui/src/components/layout.rs index d6d63f3..565ec92 100644 --- a/crates/carpet-ui/src/components/layout.rs +++ b/crates/carpet-ui/src/components/layout.rs @@ -13,30 +13,55 @@ pub fn MainLayout() -> Element { let ln_balance = wallet_state.read().ln_balance_sats; rsx! { - div { class: "app-container", - nav { class: "main-nav", - div { class: "nav-brand", - Link { to: Route::Marketplace {}, "Magic Carpet" } - } - div { class: "nav-links", - Link { to: Route::Marketplace {}, "Home" } - Link { to: Route::ListBrowsePage {}, "Lists" } - Link { to: Route::BountyBrowse {}, "Bounties" } - Link { to: Route::WalletOverview {}, "Wallet" } - Link { to: Route::Profile {}, "Profile" } - } - div { class: "nav-status", - span { class: "relay-indicator", - "⚡ {relay_count} relays" + div { class: "min-h-screen bg-gray-950 text-gray-100", + nav { class: "fixed top-0 left-0 right-0 z-50 bg-gray-900/80 backdrop-blur-md border-b border-gray-800", + div { class: "max-w-7xl mx-auto px-4 h-14 flex items-center justify-between", + // Brand + Link { + to: Route::Marketplace {}, + class: "flex items-center gap-2 text-orange-500 font-bold text-lg hover:text-orange-400 transition-colors", + i { class: "ph ph-flying-saucer text-2xl" } + "Magic Carpet" + } + + // Nav links + div { class: "flex items-center gap-1", + NavLink { to: Route::Marketplace {}, icon: "ph-house", label: "Home" } + NavLink { to: Route::ListBrowsePage {}, icon: "ph-list-bullets", label: "Lists" } + NavLink { to: Route::BountyBrowse {}, icon: "ph-hand-coins", label: "Bounties" } + NavLink { to: Route::WalletOverview {}, icon: "ph-wallet", label: "Wallet" } + NavLink { to: Route::Profile {}, icon: "ph-user-circle", label: "Profile" } } - span { class: "wallet-bar", - "{ln_balance} sats" + + // Status + div { class: "flex items-center gap-4", + span { class: "flex items-center gap-1.5 text-sm text-gray-400", + span { class: "w-2 h-2 rounded-full bg-emerald-400" } + "{relay_count} relays" + } + span { class: "flex items-center gap-1 text-amber-400 text-sm font-mono font-medium", + i { class: "ph ph-lightning" } + "{ln_balance} sats" + } } } } - main { class: "main-content", + + main { class: "pt-14", Outlet:: {} } } } } + +#[component] +fn NavLink(to: Route, icon: &'static str, label: &'static str) -> Element { + rsx! { + Link { + to, + class: "flex items-center gap-1.5 px-3 py-1.5 text-sm text-gray-400 hover:text-gray-200 hover:bg-gray-800 rounded-lg transition-colors", + i { class: "ph {icon}" } + "{label}" + } + } +} diff --git a/crates/carpet-ui/src/components/list_card.rs b/crates/carpet-ui/src/components/list_card.rs index 56df3ec..878a391 100644 --- a/crates/carpet-ui/src/components/list_card.rs +++ b/crates/carpet-ui/src/components/list_card.rs @@ -1,15 +1,17 @@ use dioxus::prelude::*; use crate::routes::Route; +use crate::types::ListDisplay; -/// Displays a grid of list headers from the marketplace. +/// Displays a grid of list cards from context. #[component] pub fn ListBrowse() -> Element { - // TODO: Wire up to NostrService to fetch real headers + let lists: Signal> = use_context(); + rsx! { - div { class: "list-grid", - p { class: "placeholder", - "Connect to a relay to browse lists." + div { class: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", + for list in lists.read().iter() { + ListCard { key: "{list.coordinate}", list: list.clone() } } } } @@ -17,23 +19,56 @@ pub fn ListBrowse() -> Element { /// A single list card for the browse view. #[component] -pub fn ListCard( - coordinate: String, - name: String, - description: Option, - item_count: usize, - zap_count: u64, -) -> Element { +pub fn ListCard(list: ListDisplay) -> Element { + let initial = list + .curator_name + .chars() + .next() + .unwrap_or('?') + .to_uppercase() + .to_string(); + rsx! { - div { class: "list-card", - Link { to: Route::ListDetailPage { coordinate: coordinate.clone() }, - h3 { "{name}" } - if let Some(desc) = &description { - p { class: "description", "{desc}" } + Link { + to: Route::ListDetailPage { coordinate: list.coordinate.clone() }, + class: "block bg-gray-900 border border-gray-800 rounded-xl p-5 hover:border-gray-700 hover:bg-gray-900/80 transition-colors group", + + // Category pills + div { class: "flex flex-wrap gap-1.5 mb-3", + for cat in list.categories.iter() { + span { class: "px-2 py-0.5 text-xs rounded-full bg-gray-800 text-gray-400", + "{cat}" + } + } + } + + // Title + description + h3 { class: "text-gray-100 font-semibold text-lg mb-1 group-hover:text-orange-400 transition-colors", + "{list.name}" + } + p { class: "text-gray-400 text-sm mb-4 line-clamp-2", + "{list.description}" + } + + // Footer: curator + stats + div { class: "flex items-center justify-between", + // Curator + div { class: "flex items-center gap-2", + div { class: "w-7 h-7 rounded-full bg-gray-800 flex items-center justify-center text-xs font-medium text-gray-300", + "{initial}" + } + span { class: "text-gray-500 text-sm", "{list.curator_name}" } } - div { class: "card-meta", - span { "{item_count} items" } - span { "{zap_count} zaps" } + // Stats + div { class: "flex items-center gap-3 text-sm text-gray-500", + span { class: "flex items-center gap-1", + i { class: "ph ph-list-bullets" } + "{list.item_count}" + } + span { class: "flex items-center gap-1 text-amber-400/70", + i { class: "ph ph-lightning" } + "{list.zap_count}" + } } } } diff --git a/crates/carpet-ui/src/components/list_detail.rs b/crates/carpet-ui/src/components/list_detail.rs index e7b3682..2328c3f 100644 --- a/crates/carpet-ui/src/components/list_detail.rs +++ b/crates/carpet-ui/src/components/list_detail.rs @@ -1,27 +1,112 @@ use dioxus::prelude::*; +use crate::components::zap_button::ZapButton; +use crate::mock_data; +use crate::types::ListDisplay; + /// Detail view for a single list (header + items + zap button). #[component] pub fn ListDetail(coordinate: String) -> Element { - // TODO: Fetch full MarketplaceList via NostrService - rsx! { - div { class: "list-detail", - h1 { "List: {coordinate}" } - p { "Loading list details..." } - - div { class: "zap-section", - button { class: "zap-button", - onclick: move |_| { - // TODO: Trigger NIP-57 zap flow - tracing::info!("Zap clicked for {}", coordinate); - }, - "Zap Curator" + let lists: Signal> = use_context(); + let list = lists.read().iter().find(|l| l.coordinate == coordinate).cloned(); + let items = mock_data::mock_items(); + + match list { + Some(list) => { + let initial = list + .curator_name + .chars() + .next() + .unwrap_or('?') + .to_uppercase() + .to_string(); + + let npub_display = list + .curator_nip05 + .clone() + .unwrap_or_else(|| "npub1...".into()); + + rsx! { + div { class: "max-w-4xl mx-auto px-4 py-8", + // Header + div { class: "mb-8", + div { class: "flex flex-wrap gap-2 mb-3", + for cat in list.categories.iter() { + span { class: "px-3 py-1 text-xs rounded-full bg-gray-800 text-gray-400", + "{cat}" + } + } + } + h1 { class: "text-3xl font-bold text-gray-100 mb-2", "{list.name}" } + p { class: "text-gray-400 text-lg", "{list.description}" } + } + + // Curator bar + zap button + div { class: "flex items-center justify-between bg-gray-900 border border-gray-800 rounded-xl p-4 mb-8", + div { class: "flex items-center gap-3", + div { class: "w-10 h-10 rounded-full bg-gray-800 flex items-center justify-center text-sm font-medium text-gray-300", + "{initial}" + } + div { + p { class: "text-gray-100 font-medium", "{list.curator_name}" } + p { class: "text-gray-500 text-sm font-mono", "{npub_display}" } + } + } + ZapButton { coordinate: coordinate.clone() } + } + + // Stats + div { class: "flex items-center gap-6 mb-6 text-sm text-gray-400", + span { class: "flex items-center gap-1.5", + i { class: "ph ph-list-bullets" } + "{list.item_count} items" + } + span { class: "flex items-center gap-1.5 text-amber-400/70", + i { class: "ph ph-lightning" } + "{list.zap_count} zaps" + } + } + + // Items + div { + h2 { class: "text-xl font-semibold text-gray-100 mb-4", "Items" } + div { class: "space-y-1", + for (i, item) in items.iter().enumerate() { + div { + class: if i % 2 == 0 { "bg-gray-900 rounded-lg p-4" } else { "bg-gray-900/50 rounded-lg p-4" }, + div { class: "flex items-start justify-between mb-2", + a { + href: "{item.resource}", + target: "_blank", + class: "text-orange-500 hover:text-orange-400 text-sm font-mono break-all", + "{item.resource}" + } + } + p { class: "text-gray-300 text-sm mb-3", "{item.content}" } + div { class: "flex flex-wrap gap-x-4 gap-y-1 text-xs text-gray-500", + for (key, val) in item.fields.iter() { + span { + span { class: "text-gray-600", "{key}: " } + span { class: "text-gray-400", "{val}" } + } + } + } + } + } + } + } } } - - div { class: "items-section", - h2 { "Items" } - p { "Loading items..." } + } + None => { + rsx! { + div { class: "max-w-4xl mx-auto px-4 py-8", + div { class: "text-center py-20", + i { class: "ph ph-magnifying-glass text-4xl text-gray-600 mb-4" } + h2 { class: "text-xl text-gray-400", "List not found" } + p { class: "text-gray-500 mt-2 font-mono text-sm", "{coordinate}" } + } + } } } } diff --git a/crates/carpet-ui/src/components/mod.rs b/crates/carpet-ui/src/components/mod.rs index 45e3f84..2dbbb1a 100644 --- a/crates/carpet-ui/src/components/mod.rs +++ b/crates/carpet-ui/src/components/mod.rs @@ -1,3 +1,6 @@ +pub mod bounty_card; pub mod layout; pub mod list_card; pub mod list_detail; +pub mod wallet_card; +pub mod zap_button; diff --git a/crates/carpet-ui/src/components/wallet_card.rs b/crates/carpet-ui/src/components/wallet_card.rs new file mode 100644 index 0000000..36e04d8 --- /dev/null +++ b/crates/carpet-ui/src/components/wallet_card.rs @@ -0,0 +1,52 @@ +use dioxus::prelude::*; + +#[derive(Clone, PartialEq)] +pub enum WalletVariant { + Bitcoin, + Lightning, +} + +#[component] +pub fn WalletCard(variant: WalletVariant, balance_sats: u64) -> Element { + let (icon, label, accent) = match variant { + WalletVariant::Bitcoin => ("ph ph-currency-btc", "Bitcoin (on-chain)", "text-orange-500"), + WalletVariant::Lightning => ("ph ph-lightning", "Lightning", "text-amber-400"), + }; + + let formatted = format_sats(balance_sats); + + rsx! { + div { class: "bg-gray-900 border border-gray-800 rounded-xl p-6", + div { class: "flex items-center gap-3 mb-4", + div { class: "w-10 h-10 rounded-lg bg-gray-800 flex items-center justify-center", + i { class: "{icon} text-xl {accent}" } + } + span { class: "text-gray-400 text-sm font-medium", "{label}" } + } + div { class: "mb-4", + span { class: "text-3xl font-bold font-mono text-gray-100", "{formatted}" } + span { class: "text-gray-500 text-sm ml-2", "sats" } + } + div { class: "flex gap-3", + button { class: "flex-1 py-2 px-4 bg-gray-800 hover:bg-gray-700 text-gray-200 rounded-lg text-sm font-medium transition-colors cursor-pointer", + "Receive" + } + button { class: "flex-1 py-2 px-4 bg-gray-800 hover:bg-gray-700 text-gray-200 rounded-lg text-sm font-medium transition-colors cursor-pointer", + "Send" + } + } + } + } +} + +fn format_sats(sats: u64) -> String { + let s = sats.to_string(); + let mut result = String::new(); + for (i, c) in s.chars().rev().enumerate() { + if i > 0 && i % 3 == 0 { + result.push(','); + } + result.push(c); + } + result.chars().rev().collect() +} diff --git a/crates/carpet-ui/src/components/zap_button.rs b/crates/carpet-ui/src/components/zap_button.rs new file mode 100644 index 0000000..ae241d2 --- /dev/null +++ b/crates/carpet-ui/src/components/zap_button.rs @@ -0,0 +1,15 @@ +use dioxus::prelude::*; + +#[component] +pub fn ZapButton(coordinate: String) -> Element { + rsx! { + button { + class: "inline-flex items-center gap-2 px-6 py-3 bg-amber-400 hover:bg-amber-300 text-gray-950 font-bold rounded-lg transition-colors cursor-pointer", + onclick: move |_| { + tracing::info!("Zap clicked for {}", coordinate); + }, + i { class: "ph ph-lightning text-xl" } + "Zap Curator" + } + } +} diff --git a/crates/carpet-ui/src/main.rs b/crates/carpet-ui/src/main.rs index af92a45..481117a 100644 --- a/crates/carpet-ui/src/main.rs +++ b/crates/carpet-ui/src/main.rs @@ -2,8 +2,10 @@ mod app; mod components; +mod mock_data; mod routes; mod state; +mod types; fn main() { dioxus::launch(app::App); diff --git a/crates/carpet-ui/src/mock_data.rs b/crates/carpet-ui/src/mock_data.rs new file mode 100644 index 0000000..9dcb096 --- /dev/null +++ b/crates/carpet-ui/src/mock_data.rs @@ -0,0 +1,168 @@ +use crate::state::nostr::NostrState; +use crate::state::wallet::WalletState; +use crate::types::{BountyDisplay, BountyStatus, ItemDisplay, ListDisplay}; + +pub fn mock_lists() -> Vec { + vec![ + ListDisplay { + coordinate: "30001:abc123:best-bitcoin-books".into(), + name: "Best Bitcoin Books".into(), + description: "Essential reading for understanding Bitcoin, from technical deep-dives to economic philosophy.".into(), + categories: vec!["Books".into(), "Education".into()], + item_count: 12, + zap_count: 847, + curator_name: "Satoshi Reader".into(), + curator_picture: None, + curator_nip05: Some("reader@bitcoinbooks.com".into()), + }, + ListDisplay { + coordinate: "30001:def456:lightning-wallets".into(), + name: "Lightning Wallets".into(), + description: "The best Lightning Network wallets ranked by usability, features, and sovereignty.".into(), + categories: vec!["Wallets".into(), "Lightning".into()], + item_count: 8, + zap_count: 1203, + curator_name: "LN Explorer".into(), + curator_picture: None, + curator_nip05: Some("explorer@ln.tips".into()), + }, + ListDisplay { + coordinate: "30001:ghi789:nostr-clients".into(), + name: "Nostr Clients".into(), + description: "A comprehensive guide to Nostr clients across all platforms — mobile, desktop, and web.".into(), + categories: vec!["Nostr".into(), "Apps".into()], + item_count: 15, + zap_count: 2100, + curator_name: "Nostr Enthusiast".into(), + curator_picture: None, + curator_nip05: Some("fan@nostr.com".into()), + }, + ListDisplay { + coordinate: "30001:jkl012:bitcoin-podcasts".into(), + name: "Bitcoin Podcasts".into(), + description: "Top podcasts covering Bitcoin technology, economics, and culture.".into(), + categories: vec!["Podcasts".into(), "Media".into()], + item_count: 10, + zap_count: 523, + curator_name: "Pod Collector".into(), + curator_picture: None, + curator_nip05: None, + }, + ListDisplay { + coordinate: "30001:mno345:privacy-tools".into(), + name: "Privacy Tools".into(), + description: "Tools and services for protecting your privacy in the digital age.".into(), + categories: vec!["Privacy".into(), "Security".into()], + item_count: 7, + zap_count: 341, + curator_name: "Privacy Max".into(), + curator_picture: None, + curator_nip05: Some("max@privacytools.io".into()), + }, + ListDisplay { + coordinate: "30001:pqr678:dev-resources".into(), + name: "Bitcoin Dev Resources".into(), + description: "Libraries, frameworks, and learning resources for Bitcoin developers.".into(), + categories: vec!["Development".into(), "Education".into()], + item_count: 20, + zap_count: 1580, + curator_name: "Dev Builder".into(), + curator_picture: None, + curator_nip05: Some("builder@devs.bitcoin".into()), + }, + ] +} + +pub fn mock_bounties() -> Vec { + vec![ + BountyDisplay { + d_tag: "bounty-001".into(), + target_list_name: "Best Bitcoin Books".into(), + target_list_coordinate: "30001:abc123:best-bitcoin-books".into(), + reward_sats: 50_000, + criteria: "Add 3 books published in 2025 covering Bitcoin Layer 2 protocols".into(), + status: BountyStatus::Open, + creator_name: "Bookworm".into(), + }, + BountyDisplay { + d_tag: "bounty-002".into(), + target_list_name: "Nostr Clients".into(), + target_list_coordinate: "30001:ghi789:nostr-clients".into(), + reward_sats: 25_000, + criteria: "Review and rate all listed clients on NIP-44 support".into(), + status: BountyStatus::Open, + creator_name: "NIP Checker".into(), + }, + BountyDisplay { + d_tag: "bounty-003".into(), + target_list_name: "Privacy Tools".into(), + target_list_coordinate: "30001:mno345:privacy-tools".into(), + reward_sats: 100_000, + criteria: "Add Tor-based tools and verify each tool's open-source status".into(), + status: BountyStatus::Fulfilled, + creator_name: "Privacy Max".into(), + }, + ] +} + +pub fn mock_items() -> Vec { + vec![ + ItemDisplay { + resource: "https://www.amazon.com/Bitcoin-Standard-Decentralized-Alternative-Central/dp/1119473861".into(), + content: "The foundational text on Bitcoin's economic significance. Saifedean Ammous makes the case for Bitcoin as sound money.".into(), + fields: vec![ + ("Author".into(), "Saifedean Ammous".into()), + ("Year".into(), "2018".into()), + ("Rating".into(), "5/5".into()), + ], + }, + ItemDisplay { + resource: "https://www.amazon.com/Mastering-Bitcoin-Programming-Open-Blockchain/dp/1491954388".into(), + content: "The technical bible for Bitcoin developers. Covers everything from keys to mining to the protocol.".into(), + fields: vec![ + ("Author".into(), "Andreas M. Antonopoulos".into()), + ("Year".into(), "2017".into()), + ("Rating".into(), "5/5".into()), + ], + }, + ItemDisplay { + resource: "https://www.amazon.com/Broken-Money-Financial-System-Failing/dp/B0CG8837J5".into(), + content: "A deep exploration of monetary history and how Bitcoin fits into the evolution of money.".into(), + fields: vec![ + ("Author".into(), "Lyn Alden".into()), + ("Year".into(), "2023".into()), + ("Rating".into(), "4.5/5".into()), + ], + }, + ItemDisplay { + resource: "https://www.amazon.com/Sovereign-Individual-Mastering-Transition-Information/dp/0684832720".into(), + content: "Prescient predictions about the impact of digital technology on society and economics.".into(), + fields: vec![ + ("Author".into(), "James Dale Davidson".into()), + ("Year".into(), "1999".into()), + ("Rating".into(), "4/5".into()), + ], + }, + ] +} + +pub fn nostr_state() -> NostrState { + NostrState { + connected_relays: vec![ + "wss://relay.damus.io".into(), + "wss://nos.lol".into(), + "wss://relay.nostr.band".into(), + ], + is_connecting: false, + has_signer: true, + npub: Some("npub1a2b3c4d5e6f7890abcdef1234567890abcdef1234567890abcdef12345678".into()), + } +} + +pub fn wallet_state() -> WalletState { + WalletState { + btc_balance_sats: 1_250_000, + ln_balance_sats: 350_000, + is_loading: false, + } +} diff --git a/crates/carpet-ui/src/routes.rs b/crates/carpet-ui/src/routes.rs index eae7d80..bf16ed1 100644 --- a/crates/carpet-ui/src/routes.rs +++ b/crates/carpet-ui/src/routes.rs @@ -1,8 +1,13 @@ use dioxus::prelude::*; +use crate::components::bounty_card::BountyCard; use crate::components::layout::MainLayout; use crate::components::list_card::ListBrowse; use crate::components::list_detail::ListDetail; +use crate::components::wallet_card::{WalletCard, WalletVariant}; +use crate::mock_data; +use crate::state::nostr::NostrState; +use crate::state::wallet::WalletState; #[derive(Routable, Clone, PartialEq)] pub enum Route { @@ -31,22 +36,72 @@ pub enum Route { #[component] fn Marketplace() -> Element { rsx! { - div { class: "marketplace", - h1 { "Magic Carpet" } - p { "Decentralized List Marketplace" } - div { class: "featured-lists", - h2 { "Featured Lists" } - ListBrowse {} + div { class: "max-w-7xl mx-auto px-4 py-8", + // Hero + div { class: "text-center mb-10", + h1 { class: "text-4xl font-bold text-gray-100 mb-3", + "Discover Curated Lists" + } + p { class: "text-gray-400 text-lg max-w-2xl mx-auto", + "A decentralized marketplace for community-curated lists, powered by Nostr and Lightning." + } } + + // Search + div { class: "max-w-xl mx-auto mb-8", + div { class: "relative", + i { class: "ph ph-magnifying-glass absolute left-3 top-1/2 -translate-y-1/2 text-gray-500" } + input { + r#type: "text", + placeholder: "Search lists...", + class: "w-full bg-gray-900 border border-gray-800 rounded-lg pl-10 pr-4 py-2.5 text-gray-200 placeholder-gray-500 focus:outline-none focus:border-gray-700", + } + } + } + + // Category filters + div { class: "flex flex-wrap justify-center gap-2 mb-8", + for cat in ["All", "Books", "Wallets", "Nostr", "Podcasts", "Privacy", "Development"] { + button { + class: if cat == "All" { + "px-4 py-1.5 text-sm rounded-full bg-orange-500 text-white font-medium cursor-pointer" + } else { + "px-4 py-1.5 text-sm rounded-full bg-gray-900 text-gray-400 hover:bg-gray-800 hover:text-gray-200 transition-colors border border-gray-800 cursor-pointer" + }, + "{cat}" + } + } + } + + // Grid + ListBrowse {} } } } #[component] fn ListBrowsePage() -> Element { + let lists: Signal> = use_context(); + let count = lists.read().len(); + rsx! { - div { class: "list-browse", - h1 { "Browse Lists" } + div { class: "max-w-7xl mx-auto px-4 py-8", + div { class: "flex items-center justify-between mb-6", + div { class: "flex items-center gap-3", + h1 { class: "text-2xl font-bold text-gray-100", "Browse Lists" } + span { class: "px-2.5 py-0.5 text-xs rounded-full bg-gray-800 text-gray-400 font-mono", + "{count}" + } + } + div { class: "relative", + i { class: "ph ph-magnifying-glass absolute left-3 top-1/2 -translate-y-1/2 text-gray-500" } + input { + r#type: "text", + placeholder: "Search...", + class: "bg-gray-900 border border-gray-800 rounded-lg pl-10 pr-4 py-2 text-sm text-gray-200 placeholder-gray-500 focus:outline-none focus:border-gray-700", + } + } + } ListBrowse {} } } @@ -61,24 +116,36 @@ fn ListDetailPage(coordinate: String) -> Element { #[component] fn BountyBrowse() -> Element { + let bounties = mock_data::mock_bounties(); + rsx! { - div { class: "bounty-browse", - h1 { "Active Bounties" } - p { "Coming soon — bounty listings will appear here." } + div { class: "max-w-7xl mx-auto px-4 py-8", + div { class: "flex items-center gap-3 mb-6", + h1 { class: "text-2xl font-bold text-gray-100", "Active Bounties" } + span { class: "px-2.5 py-0.5 text-xs rounded-full bg-gray-800 text-gray-400 font-mono", + "{bounties.len()}" + } + } + div { class: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4", + for bounty in bounties { + BountyCard { bounty } + } + } } } } #[component] fn WalletOverview() -> Element { + let wallet_state: Signal = use_context(); + let wallet = wallet_state.read(); + rsx! { - div { class: "wallet", - h1 { "Wallet" } - div { class: "balances", - h2 { "Bitcoin (on-chain)" } - p { "Balance: loading..." } - h2 { "Lightning" } - p { "Balance: loading..." } + div { class: "max-w-3xl mx-auto px-4 py-8", + h1 { class: "text-2xl font-bold text-gray-100 mb-6", "Wallet" } + div { class: "grid grid-cols-1 md:grid-cols-2 gap-4", + WalletCard { variant: WalletVariant::Bitcoin, balance_sats: wallet.btc_balance_sats } + WalletCard { variant: WalletVariant::Lightning, balance_sats: wallet.ln_balance_sats } } } } @@ -86,10 +153,67 @@ fn WalletOverview() -> Element { #[component] fn Profile() -> Element { + let nostr_state: Signal = use_context(); + let nostr = nostr_state.read(); + + let npub_display = nostr + .npub + .as_ref() + .map(|n| { + if n.len() > 20 { + format!("{}...{}", &n[..12], &n[n.len() - 8..]) + } else { + n.clone() + } + }) + .unwrap_or_else(|| "Not connected".into()); + rsx! { - div { class: "profile", - h1 { "Profile" } - p { "Key management and relay settings." } + div { class: "max-w-3xl mx-auto px-4 py-8", + // Profile header + div { class: "bg-gray-900 border border-gray-800 rounded-xl p-6 mb-6", + div { class: "flex items-center gap-4 mb-4", + div { class: "w-16 h-16 rounded-full bg-gray-800 flex items-center justify-center text-2xl font-bold text-orange-500", + "M" + } + div { + h1 { class: "text-2xl font-bold text-gray-100", "Magic Carpet User" } + p { class: "text-gray-500 text-sm font-mono flex items-center gap-2", + "{npub_display}" + button { class: "text-gray-600 hover:text-gray-400 transition-colors cursor-pointer", + i { class: "ph ph-copy" } + } + } + } + } + } + + // Relays + div { class: "bg-gray-900 border border-gray-800 rounded-xl p-6 mb-6", + h2 { class: "text-lg font-semibold text-gray-100 mb-4 flex items-center gap-2", + i { class: "ph ph-globe text-gray-400" } + "Connected Relays" + } + div { class: "space-y-2", + for relay in nostr.connected_relays.iter() { + div { class: "flex items-center gap-2 text-sm", + span { class: "w-2 h-2 rounded-full bg-emerald-400" } + span { class: "text-gray-300 font-mono", "{relay}" } + } + } + } + } + + // Key management + div { class: "bg-gray-900 border border-gray-800 rounded-xl p-6", + h2 { class: "text-lg font-semibold text-gray-100 mb-4 flex items-center gap-2", + i { class: "ph ph-key text-gray-400" } + "Key Management" + } + p { class: "text-gray-400 text-sm", + "Key import, export, and NIP-46 remote signer configuration coming soon." + } + } } } } diff --git a/crates/carpet-ui/src/types.rs b/crates/carpet-ui/src/types.rs new file mode 100644 index 0000000..5de2124 --- /dev/null +++ b/crates/carpet-ui/src/types.rs @@ -0,0 +1,37 @@ +#[derive(Debug, Clone, PartialEq)] +pub struct ListDisplay { + pub coordinate: String, + pub name: String, + pub description: String, + pub categories: Vec, + pub item_count: usize, + pub zap_count: u64, + pub curator_name: String, + pub curator_picture: Option, + pub curator_nip05: Option, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct BountyDisplay { + pub d_tag: String, + pub target_list_name: String, + pub target_list_coordinate: String, + pub reward_sats: u64, + pub criteria: String, + pub status: BountyStatus, + pub creator_name: String, +} + +#[derive(Debug, Clone, PartialEq)] +pub enum BountyStatus { + Open, + Fulfilled, + Expired, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct ItemDisplay { + pub resource: String, + pub content: String, + pub fields: Vec<(String, String)>, +} diff --git a/justfile b/justfile index 08496f8..d58f20f 100644 --- a/justfile +++ b/justfile @@ -76,3 +76,19 @@ e2e-run: e2e-down: docker compose down -v + +# Build Tailwind CSS for carpet-ui (watch mode) +dx-tw: + npx @tailwindcss/cli -i crates/carpet-ui/input.css -o crates/carpet-ui/assets/tailwind.css --watch + +# Build Tailwind CSS once (for CI / before build) +dx-tw-build: + npx @tailwindcss/cli -i crates/carpet-ui/input.css -o crates/carpet-ui/assets/tailwind.css + +# Serve carpet-ui for web development +dx-web: + dx serve -p carpet-ui --platform web + +# Serve carpet-ui as a desktop app +dx-desktop: + dx serve -p carpet-ui --platform desktop diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..9454a0f --- /dev/null +++ b/package-lock.json @@ -0,0 +1,991 @@ +{ + "name": "magic-carpet", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "dependencies": { + "@tailwindcss/cli": "^4.2.1", + "tailwindcss": "^4.2.1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.6.tgz", + "integrity": "sha512-tmmZ3lQxAe/k/+rNnXQRawJ4NjxO2hqiOLTHvWchtGZULp4RyFeh6aU4XdOYBFe2KE1oShQTv4AblOs2iOrNnQ==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.5.6", + "@parcel/watcher-darwin-arm64": "2.5.6", + "@parcel/watcher-darwin-x64": "2.5.6", + "@parcel/watcher-freebsd-x64": "2.5.6", + "@parcel/watcher-linux-arm-glibc": "2.5.6", + "@parcel/watcher-linux-arm-musl": "2.5.6", + "@parcel/watcher-linux-arm64-glibc": "2.5.6", + "@parcel/watcher-linux-arm64-musl": "2.5.6", + "@parcel/watcher-linux-x64-glibc": "2.5.6", + "@parcel/watcher-linux-x64-musl": "2.5.6", + "@parcel/watcher-win32-arm64": "2.5.6", + "@parcel/watcher-win32-ia32": "2.5.6", + "@parcel/watcher-win32-x64": "2.5.6" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.5.6.tgz", + "integrity": "sha512-YQxSS34tPF/6ZG7r/Ih9xy+kP/WwediEUsqmtf0cuCV5TPPKw/PQHRhueUo6JdeFJaqV3pyjm0GdYjZotbRt/A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.5.6.tgz", + "integrity": "sha512-Z2ZdrnwyXvvvdtRHLmM4knydIdU9adO3D4n/0cVipF3rRiwP+3/sfzpAwA/qKFL6i1ModaabkU7IbpeMBgiVEA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.5.6.tgz", + "integrity": "sha512-HgvOf3W9dhithcwOWX9uDZyn1lW9R+7tPZ4sug+NGrGIo4Rk1hAXLEbcH1TQSqxts0NYXXlOWqVpvS1SFS4fRg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.5.6.tgz", + "integrity": "sha512-vJVi8yd/qzJxEKHkeemh7w3YAn6RJCtYlE4HPMoVnCpIXEzSrxErBW5SJBgKLbXU3WdIpkjBTeUNtyBVn8TRng==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.5.6.tgz", + "integrity": "sha512-9JiYfB6h6BgV50CCfasfLf/uvOcJskMSwcdH1PHH9rvS1IrNy8zad6IUVPVUfmXr+u+Km9IxcfMLzgdOudz9EQ==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.5.6.tgz", + "integrity": "sha512-Ve3gUCG57nuUUSyjBq/MAM0CzArtuIOxsBdQ+ftz6ho8n7s1i9E1Nmk/xmP323r2YL0SONs1EuwqBp2u1k5fxg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.5.6.tgz", + "integrity": "sha512-f2g/DT3NhGPdBmMWYoxixqYr3v/UXcmLOYy16Bx0TM20Tchduwr4EaCbmxh1321TABqPGDpS8D/ggOTaljijOA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.5.6.tgz", + "integrity": "sha512-qb6naMDGlbCwdhLj6hgoVKJl2odL34z2sqkC7Z6kzir8b5W65WYDpLB6R06KabvZdgoHI/zxke4b3zR0wAbDTA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.5.6.tgz", + "integrity": "sha512-kbT5wvNQlx7NaGjzPFu8nVIW1rWqV780O7ZtkjuWaPUgpv2NMFpjYERVi0UYj1msZNyCzGlaCWEtzc+exjMGbQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.5.6.tgz", + "integrity": "sha512-1JRFeC+h7RdXwldHzTsmdtYR/Ku8SylLgTU/reMuqdVD7CtLwf0VR1FqeprZ0eHQkO0vqsbvFLXUmYm/uNKJBg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.5.6.tgz", + "integrity": "sha512-3ukyebjc6eGlw9yRt678DxVF7rjXatWiHvTXqphZLvo7aC5NdEgFufVwjFfY51ijYEWpXbqF5jtrK275z52D4Q==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-ia32": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.5.6.tgz", + "integrity": "sha512-k35yLp1ZMwwee3Ez/pxBi5cf4AoBKYXj00CZ80jUz5h8prpiaQsiRPKQMxoLstNuqe2vR4RNPEAEcjEFzhEz/g==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.5.6", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.5.6.tgz", + "integrity": "sha512-hbQlYcCq5dlAX9Qx+kFb0FHue6vbjlf0FrNzSKdYK2APUf7tGfGxQCk2ihEREmbR6ZMc0MVAD5RIX/41gpUzTw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@tailwindcss/cli": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/cli/-/cli-4.2.1.tgz", + "integrity": "sha512-b7MGn51IA80oSG+7fuAgzfQ+7pZBgjzbqwmiv6NO7/+a1sev32cGqnwhscT7h0EcAvMa9r7gjRylqOH8Xhc4DA==", + "license": "MIT", + "dependencies": { + "@parcel/watcher": "^2.5.1", + "@tailwindcss/node": "4.2.1", + "@tailwindcss/oxide": "4.2.1", + "enhanced-resolve": "^5.19.0", + "mri": "^1.2.0", + "picocolors": "^1.1.1", + "tailwindcss": "4.2.1" + }, + "bin": { + "tailwindcss": "dist/index.mjs" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.2.1.tgz", + "integrity": "sha512-jlx6sLk4EOwO6hHe1oCGm1Q4AN/s0rSrTTPBGPM0/RQ6Uylwq17FuU8IeJJKEjtc6K6O07zsvP+gDO6MMWo7pg==", + "license": "MIT", + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.19.0", + "jiti": "^2.6.1", + "lightningcss": "1.31.1", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.2.1" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.2.1.tgz", + "integrity": "sha512-yv9jeEFWnjKCI6/T3Oq50yQEOqmpmpfzG1hcZsAOaXFQPfzWprWrlHSdGPEF3WQTi8zu8ohC9Mh9J470nT5pUw==", + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.2.1", + "@tailwindcss/oxide-darwin-arm64": "4.2.1", + "@tailwindcss/oxide-darwin-x64": "4.2.1", + "@tailwindcss/oxide-freebsd-x64": "4.2.1", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.2.1", + "@tailwindcss/oxide-linux-arm64-gnu": "4.2.1", + "@tailwindcss/oxide-linux-arm64-musl": "4.2.1", + "@tailwindcss/oxide-linux-x64-gnu": "4.2.1", + "@tailwindcss/oxide-linux-x64-musl": "4.2.1", + "@tailwindcss/oxide-wasm32-wasi": "4.2.1", + "@tailwindcss/oxide-win32-arm64-msvc": "4.2.1", + "@tailwindcss/oxide-win32-x64-msvc": "4.2.1" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.2.1.tgz", + "integrity": "sha512-eZ7G1Zm5EC8OOKaesIKuw77jw++QJ2lL9N+dDpdQiAB/c/B2wDh0QPFHbkBVrXnwNugvrbJFk1gK2SsVjwWReg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.2.1.tgz", + "integrity": "sha512-q/LHkOstoJ7pI1J0q6djesLzRvQSIfEto148ppAd+BVQK0JYjQIFSK3JgYZJa+Yzi0DDa52ZsQx2rqytBnf8Hw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.2.1.tgz", + "integrity": "sha512-/f/ozlaXGY6QLbpvd/kFTro2l18f7dHKpB+ieXz+Cijl4Mt9AI2rTrpq7V+t04nK+j9XBQHnSMdeQRhbGyt6fw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.2.1.tgz", + "integrity": "sha512-5e/AkgYJT/cpbkys/OU2Ei2jdETCLlifwm7ogMC7/hksI2fC3iiq6OcXwjibcIjPung0kRtR3TxEITkqgn0TcA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.2.1.tgz", + "integrity": "sha512-Uny1EcVTTmerCKt/1ZuKTkb0x8ZaiuYucg2/kImO5A5Y/kBz41/+j0gxUZl+hTF3xkWpDmHX+TaWhOtba2Fyuw==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.2.1.tgz", + "integrity": "sha512-CTrwomI+c7n6aSSQlsPL0roRiNMDQ/YzMD9EjcR+H4f0I1SQ8QqIuPnsVp7QgMkC1Qi8rtkekLkOFjo7OlEFRQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.2.1.tgz", + "integrity": "sha512-WZA0CHRL/SP1TRbA5mp9htsppSEkWuQ4KsSUumYQnyl8ZdT39ntwqmz4IUHGN6p4XdSlYfJwM4rRzZLShHsGAQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.2.1.tgz", + "integrity": "sha512-qMFzxI2YlBOLW5PhblzuSWlWfwLHaneBE0xHzLrBgNtqN6mWfs+qYbhryGSXQjFYB1Dzf5w+LN5qbUTPhW7Y5g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.2.1.tgz", + "integrity": "sha512-5r1X2FKnCMUPlXTWRYpHdPYUY6a1Ar/t7P24OuiEdEOmms5lyqjDRvVY1yy9Rmioh+AunQ0rWiOTPE8F9A3v5g==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.2.1.tgz", + "integrity": "sha512-MGFB5cVPvshR85MTJkEvqDUnuNoysrsRxd6vnk1Lf2tbiqNlXpHYZqkqOQalydienEWOHHFyyuTSYRsLfxFJ2Q==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.8.1", + "@emnapi/runtime": "^1.8.1", + "@emnapi/wasi-threads": "^1.1.0", + "@napi-rs/wasm-runtime": "^1.1.1", + "@tybys/wasm-util": "^0.10.1", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.1.tgz", + "integrity": "sha512-YlUEHRHBGnCMh4Nj4GnqQyBtsshUPdiNroZj8VPkvTZSoHsilRCwXcVKnG9kyi0ZFAS/3u+qKHBdDc81SADTRA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.2.1.tgz", + "integrity": "sha512-rbO34G5sMWWyrN/idLeVxAZgAKWrn5LiR3/I90Q9MkA67s6T1oB0xtTe+0heoBvHSpbU9Mk7i6uwJnpo4u21XQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.20.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.20.0.tgz", + "integrity": "sha512-/ce7+jQ1PQ6rVXwe+jKEg5hW5ciicHwIQUagZkp6IufBoY3YDgdTTY1azVs0qoRgVmvsNB+rbjLJxDAeHHtwsQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.3.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/lightningcss": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.31.1.tgz", + "integrity": "sha512-l51N2r93WmGUye3WuFoN5k10zyvrVs0qfKBhyC5ogUQ6Ew6JUSswh78mbSO+IU3nTWsyOArqPCcShdQSadghBQ==", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-android-arm64": "1.31.1", + "lightningcss-darwin-arm64": "1.31.1", + "lightningcss-darwin-x64": "1.31.1", + "lightningcss-freebsd-x64": "1.31.1", + "lightningcss-linux-arm-gnueabihf": "1.31.1", + "lightningcss-linux-arm64-gnu": "1.31.1", + "lightningcss-linux-arm64-musl": "1.31.1", + "lightningcss-linux-x64-gnu": "1.31.1", + "lightningcss-linux-x64-musl": "1.31.1", + "lightningcss-win32-arm64-msvc": "1.31.1", + "lightningcss-win32-x64-msvc": "1.31.1" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.31.1.tgz", + "integrity": "sha512-HXJF3x8w9nQ4jbXRiNppBCqeZPIAfUo8zE/kOEGbW5NZvGc/K7nMxbhIr+YlFlHW5mpbg/YFPdbnCh1wAXCKFg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.31.1.tgz", + "integrity": "sha512-02uTEqf3vIfNMq3h/z2cJfcOXnQ0GRwQrkmPafhueLb2h7mqEidiCzkE4gBMEH65abHRiQvhdcQ+aP0D0g67sg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.31.1.tgz", + "integrity": "sha512-1ObhyoCY+tGxtsz1lSx5NXCj3nirk0Y0kB/g8B8DT+sSx4G9djitg9ejFnjb3gJNWo7qXH4DIy2SUHvpoFwfTA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.31.1.tgz", + "integrity": "sha512-1RINmQKAItO6ISxYgPwszQE1BrsVU5aB45ho6O42mu96UiZBxEXsuQ7cJW4zs4CEodPUioj/QrXW1r9pLUM74A==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.31.1.tgz", + "integrity": "sha512-OOCm2//MZJ87CdDK62rZIu+aw9gBv4azMJuA8/KB74wmfS3lnC4yoPHm0uXZ/dvNNHmnZnB8XLAZzObeG0nS1g==", + "cpu": [ + "arm" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.31.1.tgz", + "integrity": "sha512-WKyLWztD71rTnou4xAD5kQT+982wvca7E6QoLpoawZ1gP9JM0GJj4Tp5jMUh9B3AitHbRZ2/H3W5xQmdEOUlLg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.31.1.tgz", + "integrity": "sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.31.1.tgz", + "integrity": "sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.31.1.tgz", + "integrity": "sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.31.1.tgz", + "integrity": "sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==", + "cpu": [ + "arm64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.31.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.31.1.tgz", + "integrity": "sha512-I9aiFrbd7oYHwlnQDqr1Roz+fTz61oDDJX7n9tYF9FJymH1cIN1DtKw3iYt6b8WZgEjoNwVSncwF4wx/ZedMhw==", + "cpu": [ + "x64" + ], + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/tailwindcss": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.2.1.tgz", + "integrity": "sha512-/tBrSQ36vCleJkAOsy9kbNTgaxvGbyOamC30PRePTQe/o1MFwEKHQk4Cn7BNGaPtjp+PuUrByJehM1hgxfq4sw==", + "license": "MIT" + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..7d24e87 --- /dev/null +++ b/package.json @@ -0,0 +1,6 @@ +{ + "dependencies": { + "@tailwindcss/cli": "^4.2.1", + "tailwindcss": "^4.2.1" + } +} From d6158850a1757cac67e0f37e9fdea49bf1d82db2 Mon Sep 17 00:00:00 2001 From: matthiasdebernardini Date: Sat, 7 Mar 2026 22:46:04 -0600 Subject: [PATCH 3/3] chore: add pre-commit hooks, apply cargo fmt, fix clippy and machete warnings Add pre-commit config with cargo fmt, machete, clippy (pedantic), sem-diff, and conventional commit enforcement. Fix all formatting, unused dependency warnings, and clippy pedantic lints across the workspace. Co-Authored-By: Claude Opus 4.6 (1M context) --- .pre-commit-config.yaml | 52 ++++ crates/bdk-agcli/src/main.rs | 262 ++++++++---------- crates/bdk-lib/src/config.rs | 2 +- crates/bdk-lib/src/lib.rs | 4 + crates/bdk-lib/src/wallet.rs | 10 +- crates/bdk-lib/tests/e2e.rs | 40 +-- crates/carpet-agent/Cargo.toml | 3 + crates/carpet-agent/src/main.rs | 26 +- crates/carpet-ui/Cargo.toml | 3 + .../carpet-ui/src/components/list_detail.rs | 6 +- .../carpet-ui/src/components/wallet_card.rs | 6 +- crates/nostr-lib/Cargo.toml | 3 + crates/nostr-lib/src/filters.rs | 15 +- crates/nostr-lib/src/lib.rs | 4 + crates/nostr-lib/src/profile.rs | 14 +- crates/nostr-lib/src/service.rs | 26 +- crates/nostr-lib/src/types.rs | 2 +- crates/nostr-lib/src/zap.rs | 9 +- crates/phoenixd-agcli/src/main.rs | 209 +++++++------- crates/phoenixd-lib/src/client.rs | 20 +- crates/phoenixd-lib/src/lib.rs | 4 + 21 files changed, 383 insertions(+), 337 deletions(-) create mode 100644 .pre-commit-config.yaml diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..d928734 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,52 @@ +repos: + - repo: https://github.com/compilerla/conventional-pre-commit + rev: v4.4.0 + hooks: + - id: conventional-pre-commit + stages: [commit-msg] + args: + - feat + - fix + - chore + - test + - doc + - refactor + - perf + - ci + - style + - revert + + - repo: local + hooks: + - id: cargo-fmt + name: cargo fmt + language: system + entry: cargo fmt --all -- --check + pass_filenames: false + always_run: true + priority: 0 + + - id: cargo-machete + name: cargo machete + language: system + entry: cargo machete + pass_filenames: false + always_run: true + priority: 0 + + - id: cargo-clippy + name: cargo clippy + language: system + entry: cargo clippy --all-targets -- -W clippy::all -W clippy::pedantic -D warnings + pass_filenames: false + always_run: true + priority: 1 + + - id: sem-diff + name: sem diff (semantic changes) + language: system + entry: bash -c 'sem diff --staged --file-exts .rs || true' + pass_filenames: false + always_run: true + verbose: true + priority: 2 diff --git a/crates/bdk-agcli/src/main.rs b/crates/bdk-agcli/src/main.rs index 3dfc0ab..0128316 100644 --- a/crates/bdk-agcli/src/main.rs +++ b/crates/bdk-agcli/src/main.rs @@ -19,6 +19,7 @@ fn parse_bool_flag(req: &CommandRequest<'_>, name: &str) -> Result CommandError { let code = match &e { BdkLibError::Wallet(_) => "WALLET_ERROR", @@ -56,189 +57,170 @@ fn resolve_config() -> WalletConfig { } fn init_command() -> Command { - Command::new("init", "Generate or import a wallet mnemonic and descriptors") - .usage("bdk-agcli init --generate | --import=") - .sync_handler(|req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let generate = parse_bool_flag(req, "generate")?; - let import = req.flag("import").map(String::from); + Command::new( + "init", + "Generate or import a wallet mnemonic and descriptors", + ) + .usage("bdk-agcli init --generate | --import=") + .sync_handler(|req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let generate = parse_bool_flag(req, "generate")?; + let import = req.flag("import").map(String::from); - if generate && import.is_some() { - return Err(CommandError::new( - "--generate and --import are mutually exclusive", - "INVALID_ARGS", - "Use either --generate or --import, not both", - )); - } + if generate && import.is_some() { + return Err(CommandError::new( + "--generate and --import are mutually exclusive", + "INVALID_ARGS", + "Use either --generate or --import, not both", + )); + } - if !generate && import.is_none() { - return Err(CommandError::new( - "Specify --generate or --import", - "MISSING_ARG", - "Use --generate to create a new wallet, or --import=", - ) - .next_actions(vec![NextAction::new( - "bdk-agcli init --generate", - "Generate new wallet", - )])); - } + if !generate && import.is_none() { + return Err(CommandError::new( + "Specify --generate or --import", + "MISSING_ARG", + "Use --generate to create a new wallet, or --import=", + ) + .next_actions(vec![NextAction::new( + "bdk-agcli init --generate", + "Generate new wallet", + )])); + } - let config = resolve_config(); + let config = resolve_config(); - let result = if generate { - bdk_lib::init_wallet(&config).map_err(err)? - } else { - let mnemonic = import.unwrap(); - bdk_lib::import_wallet(&config, &mnemonic).map_err(err)? - }; + let result = if generate { + bdk_lib::init_wallet(&config).map_err(err)? + } else { + let mnemonic = import.unwrap(); + bdk_lib::import_wallet(&config, &mnemonic).map_err(err)? + }; - Ok(CommandOutput::new(json!(result)).next_actions(vec![ - NextAction::new("bdk-agcli address", "Get a receive address"), - NextAction::new("bdk-agcli sync", "Sync wallet with Esplora"), - ])) - }) + Ok(CommandOutput::new(json!(result)).next_actions(vec![ + NextAction::new("bdk-agcli address", "Get a receive address"), + NextAction::new("bdk-agcli sync", "Sync wallet with Esplora"), + ])) + }) } fn address_command() -> Command { Command::new("address", "Get next unused receive address") .usage("bdk-agcli address") - .sync_handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let config = resolve_config(); - let (mut db, mut wallet) = bdk_lib::load_wallet(&config).map_err(err)?; - let addr = bdk_lib::next_address(&mut wallet, &mut db).map_err(err)?; + .sync_handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let config = resolve_config(); + let (mut db, mut wallet) = bdk_lib::load_wallet(&config).map_err(err)?; + let addr = bdk_lib::next_address(&mut wallet, &mut db).map_err(err)?; - Ok(CommandOutput::new(json!(addr)).next_actions(vec![ - NextAction::new( - format!("just fund-bdk {}", addr.address), - "Fund this address (regtest)", - ), - NextAction::new("bdk-agcli sync", "Sync wallet after funding"), - ])) - }, - ) + Ok(CommandOutput::new(json!(addr)).next_actions(vec![ + NextAction::new( + format!("just fund-bdk {}", addr.address), + "Fund this address (regtest)", + ), + NextAction::new("bdk-agcli sync", "Sync wallet after funding"), + ])) + }) } fn sync_command() -> Command { Command::new("sync", "Sync wallet with Esplora") .usage("bdk-agcli sync") - .handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - Box::pin(async move { - let config = resolve_config(); - let (mut db, mut wallet) = bdk_lib::load_wallet(&config).map_err(err)?; + .handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + Box::pin(async move { + let config = resolve_config(); + let (mut db, mut wallet) = bdk_lib::load_wallet(&config).map_err(err)?; - bdk_lib::sync_wallet(&mut wallet, &mut db, &config.esplora_url) - .await - .map_err(err)?; + bdk_lib::sync_wallet(&mut wallet, &mut db, &config.esplora_url) + .await + .map_err(err)?; - let balance = bdk_lib::get_balance(&wallet); - Ok(CommandOutput::new(json!({ - "synced": true, - "balance": balance, - })) - .next_actions(vec![ - NextAction::new("bdk-agcli balance", "View balance"), - NextAction::new("bdk-agcli list-tx", "List transactions"), - ])) - }) - }, - ) + let balance = bdk_lib::get_balance(&wallet); + Ok(CommandOutput::new(json!({ + "synced": true, + "balance": balance, + })) + .next_actions(vec![ + NextAction::new("bdk-agcli balance", "View balance"), + NextAction::new("bdk-agcli list-tx", "List transactions"), + ])) + }) + }) } fn balance_command() -> Command { Command::new("balance", "Show wallet balance") .usage("bdk-agcli balance") - .sync_handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let config = resolve_config(); - let (_db, wallet) = bdk_lib::load_wallet(&config).map_err(err)?; - let balance = bdk_lib::get_balance(&wallet); + .sync_handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let config = resolve_config(); + let (_db, wallet) = bdk_lib::load_wallet(&config).map_err(err)?; + let balance = bdk_lib::get_balance(&wallet); - Ok(CommandOutput::new(json!(balance)).next_actions(vec![ - NextAction::new("bdk-agcli sync", "Sync first if stale"), - NextAction::new( - "bdk-agcli send --to --amount ", - "Send BTC", - ), - ])) - }, - ) + Ok(CommandOutput::new(json!(balance)).next_actions(vec![ + NextAction::new("bdk-agcli sync", "Sync first if stale"), + NextAction::new("bdk-agcli send --to --amount ", "Send BTC"), + ])) + }) } fn send_command() -> Command { Command::new("send", "Send BTC to an address") .usage("bdk-agcli send --to

--amount ") - .handler( - |req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let to = req.flag("to").map(String::from); - let amount_str = req.flag("amount").map(String::from); + .handler(|req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let to = req.flag("to").map(String::from); + let amount_str = req.flag("amount").map(String::from); - Box::pin(async move { - let to = to.ok_or_else(|| { + Box::pin(async move { + let to = to.ok_or_else(|| { + CommandError::new("--to is required", "MISSING_ARG", "Provide --to=
") + })?; + let amount_sats: u64 = amount_str + .ok_or_else(|| { CommandError::new( - "--to is required", + "--amount is required", "MISSING_ARG", - "Provide --to=
", + "Provide --amount=", + ) + })? + .parse() + .map_err(|_| { + CommandError::new( + "--amount must be a number", + "INVALID_ARGS", + "Provide amount in satoshis", ) })?; - let amount_sats: u64 = amount_str - .ok_or_else(|| { - CommandError::new( - "--amount is required", - "MISSING_ARG", - "Provide --amount=", - ) - })? - .parse() - .map_err(|_| { - CommandError::new( - "--amount must be a number", - "INVALID_ARGS", - "Provide amount in satoshis", - ) - })?; - let config = resolve_config(); - let (mut db, mut wallet) = bdk_lib::load_wallet(&config).map_err(err)?; + let config = resolve_config(); + let (mut db, mut wallet) = bdk_lib::load_wallet(&config).map_err(err)?; - let result = bdk_lib::send( - &mut wallet, - &mut db, - &config.esplora_url, - &to, - amount_sats, - ) - .await - .map_err(err)?; + let result = + bdk_lib::send(&mut wallet, &mut db, &config.esplora_url, &to, amount_sats) + .await + .map_err(err)?; - Ok(CommandOutput::new(json!(result)).next_actions(vec![ - NextAction::new("bdk-agcli sync", "Sync to see updated balance"), - NextAction::new("bdk-agcli list-tx", "View transactions"), - ])) - }) - }, - ) + Ok(CommandOutput::new(json!(result)).next_actions(vec![ + NextAction::new("bdk-agcli sync", "Sync to see updated balance"), + NextAction::new("bdk-agcli list-tx", "View transactions"), + ])) + }) + }) } fn list_tx_command() -> Command { Command::new("list-tx", "List wallet transactions") .usage("bdk-agcli list-tx") - .sync_handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let config = resolve_config(); - let (_db, wallet) = bdk_lib::load_wallet(&config).map_err(err)?; - let txs = bdk_lib::list_transactions(&wallet); + .sync_handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let config = resolve_config(); + let (_db, wallet) = bdk_lib::load_wallet(&config).map_err(err)?; + let txs = bdk_lib::list_transactions(&wallet); - Ok(CommandOutput::new(json!({ - "count": txs.len(), - "transactions": txs, - })) - .next_actions(vec![ - NextAction::new("bdk-agcli sync", "Sync for latest"), - NextAction::new("bdk-agcli balance", "View balance"), - ])) - }, - ) + Ok(CommandOutput::new(json!({ + "count": txs.len(), + "transactions": txs, + })) + .next_actions(vec![ + NextAction::new("bdk-agcli sync", "Sync for latest"), + NextAction::new("bdk-agcli balance", "View balance"), + ])) + }) } #[tokio::main] diff --git a/crates/bdk-lib/src/config.rs b/crates/bdk-lib/src/config.rs index 31c2d16..9493773 100644 --- a/crates/bdk-lib/src/config.rs +++ b/crates/bdk-lib/src/config.rs @@ -16,7 +16,7 @@ impl WalletConfig { Network::Testnet => "testnet", Network::Signet => "signet", Network::Regtest => "regtest", - _ => "unknown", + Network::Testnet4 => "testnet4", }; Self { network, diff --git a/crates/bdk-lib/src/lib.rs b/crates/bdk-lib/src/lib.rs index 04dd36b..6fcaeb7 100644 --- a/crates/bdk-lib/src/lib.rs +++ b/crates/bdk-lib/src/lib.rs @@ -1,3 +1,7 @@ +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::must_use_candidate)] + pub mod config; pub mod error; pub mod wallet; diff --git a/crates/bdk-lib/src/wallet.rs b/crates/bdk-lib/src/wallet.rs index 4b83cad..3c9be2e 100644 --- a/crates/bdk-lib/src/wallet.rs +++ b/crates/bdk-lib/src/wallet.rs @@ -1,8 +1,8 @@ use std::fs; use std::str::FromStr; -use bdk_esplora::esplora_client; use bdk_esplora::EsploraAsyncExt; +use bdk_esplora::esplora_client; use bdk_wallet::bitcoin::bip32::Xpriv; use bdk_wallet::bitcoin::{Address, Amount, Network}; use bdk_wallet::file_store::Store; @@ -278,6 +278,7 @@ pub async fn send( .finish() .map_err(|e| BdkLibError::Transaction(e.to_string()))?; + #[allow(clippy::default_trait_access)] let finalized = wallet .sign(&mut psbt, Default::default()) .map_err(|e| BdkLibError::Transaction(e.to_string()))?; @@ -293,10 +294,7 @@ pub async fn send( .map_err(|e| BdkLibError::Transaction(e.to_string()))?; let txid = tx.compute_txid(); - let fee_sats = wallet - .calculate_fee(&tx) - .map(|f| f.to_sat()) - .unwrap_or(0); + let fee_sats = wallet.calculate_fee(&tx).map(Amount::to_sat).unwrap_or(0); let client = esplora_client::Builder::new(esplora_url) .build_async() @@ -327,7 +325,7 @@ pub fn list_transactions(wallet: &BdkWallet) -> Vec { let fee = wallet .calculate_fee(&tx.tx_node.tx) .ok() - .map(|f| f.to_sat()); + .map(Amount::to_sat); let (confirmed, height) = match &tx.chain_position { bdk_wallet::chain::ChainPosition::Confirmed { anchor, .. } => { (true, Some(anchor.block_id.height)) diff --git a/crates/bdk-lib/tests/e2e.rs b/crates/bdk-lib/tests/e2e.rs index ec171ba..578429f 100644 --- a/crates/bdk-lib/tests/e2e.rs +++ b/crates/bdk-lib/tests/e2e.rs @@ -6,16 +6,17 @@ use bdk_wallet::bitcoin::Network; use tempfile::TempDir; fn workspace_root() -> PathBuf { - std::env::var("WORKSPACE_ROOT") - .map(PathBuf::from) - .unwrap_or_else(|_| { + std::env::var("WORKSPACE_ROOT").map_or_else( + |_| { PathBuf::from(env!("CARGO_MANIFEST_DIR")) .parent() .unwrap() .parent() .unwrap() .to_path_buf() - }) + }, + PathBuf::from, + ) } fn bitcoin_cli(args: &[&str]) -> String { @@ -70,18 +71,16 @@ async fn wait_for_sync( if balance.confirmed_sats > 0 { return; } - if start.elapsed().as_secs() > timeout_secs { - panic!( - "Timed out after {}s waiting for confirmed balance", - timeout_secs - ); - } + assert!( + start.elapsed().as_secs() <= timeout_secs, + "Timed out after {timeout_secs}s waiting for confirmed balance" + ); tokio::time::sleep(std::time::Duration::from_secs(2)).await; } } #[tokio::test] -#[ignore] +#[ignore = "requires Docker infrastructure (bitcoind + esplora)"] async fn test_full_wallet_lifecycle() { let tmp = TempDir::new().unwrap(); let config = make_config(&tmp); @@ -110,9 +109,15 @@ async fn test_full_wallet_lifecycle() { let addr2 = next_address(&mut wallet, &mut db).unwrap(); // Send 50M sats to second address - let send_result = send(&mut wallet, &mut db, &config.esplora_url, &addr2.address, 50_000_000) - .await - .unwrap(); + let send_result = send( + &mut wallet, + &mut db, + &config.esplora_url, + &addr2.address, + 50_000_000, + ) + .await + .unwrap(); assert!(!send_result.txid.is_empty()); assert!(send_result.fee_sats > 0); @@ -138,7 +143,7 @@ async fn test_full_wallet_lifecycle() { } #[tokio::test] -#[ignore] +#[ignore = "requires Docker infrastructure (bitcoind + esplora)"] async fn test_wallet_already_exists() { let tmp = TempDir::new().unwrap(); let config = make_config(&tmp); @@ -147,13 +152,12 @@ async fn test_wallet_already_exists() { let err = init_wallet(&config).unwrap_err(); assert!( matches!(err, BdkLibError::WalletAlreadyExists { .. }), - "expected WalletAlreadyExists, got: {:?}", - err + "expected WalletAlreadyExists, got: {err:?}", ); } #[tokio::test] -#[ignore] +#[ignore = "requires Docker infrastructure (bitcoind + esplora)"] async fn test_sync_empty_wallet() { let tmp = TempDir::new().unwrap(); let config = make_config(&tmp); diff --git a/crates/carpet-agent/Cargo.toml b/crates/carpet-agent/Cargo.toml index 5f10c86..60c05a1 100644 --- a/crates/carpet-agent/Cargo.toml +++ b/crates/carpet-agent/Cargo.toml @@ -18,3 +18,6 @@ serde_json = { workspace = true } anyhow = { workspace = true } tracing = { workspace = true } tracing-subscriber = { workspace = true } + +[package.metadata.cargo-machete] +ignored = ["rig-core", "tracing"] diff --git a/crates/carpet-agent/src/main.rs b/crates/carpet-agent/src/main.rs index 8815d37..f91fe3d 100644 --- a/crates/carpet-agent/src/main.rs +++ b/crates/carpet-agent/src/main.rs @@ -35,8 +35,7 @@ async fn ensure_loaded(shared: &SharedWallet) -> Result<(), ToolError> { let mut guard = shared.lock().await; if guard.is_none() { let config = wallet_config(); - let (db, wallet) = - bdk_lib::load_wallet(&config).map_err(|e| ToolError(e.to_string()))?; + let (db, wallet) = bdk_lib::load_wallet(&config).map_err(|e| ToolError(e.to_string()))?; *guard = Some((db, wallet)); } Ok(()) @@ -112,7 +111,9 @@ impl Tool for GetAddressTool { async fn call(&self, _args: Self::Args) -> Result { ensure_loaded(&self.wallet).await?; let mut guard = self.wallet.lock().await; - let (db, wallet) = guard.as_mut().ok_or(ToolError("Wallet not loaded".into()))?; + let (db, wallet) = guard + .as_mut() + .ok_or(ToolError("Wallet not loaded".into()))?; let addr = bdk_lib::next_address(wallet, db).map_err(|e| ToolError(e.to_string()))?; serde_json::to_value(addr).map_err(|e| ToolError(e.to_string())) } @@ -140,7 +141,9 @@ impl Tool for SyncWalletTool { ensure_loaded(&self.wallet).await?; let config = wallet_config(); let mut guard = self.wallet.lock().await; - let (db, wallet) = guard.as_mut().ok_or(ToolError("Wallet not loaded".into()))?; + let (db, wallet) = guard + .as_mut() + .ok_or(ToolError("Wallet not loaded".into()))?; bdk_lib::sync_wallet(wallet, db, &config.esplora_url) .await .map_err(|e| ToolError(e.to_string()))?; @@ -171,7 +174,9 @@ impl Tool for GetBalanceTool { async fn call(&self, _args: Self::Args) -> Result { ensure_loaded(&self.wallet).await?; let guard = self.wallet.lock().await; - let (_, wallet) = guard.as_ref().ok_or(ToolError("Wallet not loaded".into()))?; + let (_, wallet) = guard + .as_ref() + .ok_or(ToolError("Wallet not loaded".into()))?; let balance = bdk_lib::get_balance(wallet); serde_json::to_value(balance).map_err(|e| ToolError(e.to_string())) } @@ -212,7 +217,9 @@ impl Tool for SendBitcoinTool { ensure_loaded(&self.wallet).await?; let config = wallet_config(); let mut guard = self.wallet.lock().await; - let (db, wallet) = guard.as_mut().ok_or(ToolError("Wallet not loaded".into()))?; + let (db, wallet) = guard + .as_mut() + .ok_or(ToolError("Wallet not loaded".into()))?; let result = bdk_lib::send(wallet, db, &config.esplora_url, &args.to, args.amount_sats) .await .map_err(|e| ToolError(e.to_string()))?; @@ -241,7 +248,9 @@ impl Tool for ListTransactionsTool { async fn call(&self, _args: Self::Args) -> Result { ensure_loaded(&self.wallet).await?; let guard = self.wallet.lock().await; - let (_, wallet) = guard.as_ref().ok_or(ToolError("Wallet not loaded".into()))?; + let (_, wallet) = guard + .as_ref() + .ok_or(ToolError("Wallet not loaded".into()))?; let txs = bdk_lib::list_transactions(wallet); serde_json::to_value(json!({"count": txs.len(), "transactions": txs})) .map_err(|e| ToolError(e.to_string())) @@ -425,8 +434,7 @@ async fn main() -> Result<()> { ) .init(); - let api_key = - std::env::var("ANTHROPIC_API_KEY").expect("ANTHROPIC_API_KEY must be set"); + let api_key = std::env::var("ANTHROPIC_API_KEY").expect("ANTHROPIC_API_KEY must be set"); let shared_wallet: SharedWallet = Arc::new(Mutex::new(None)); diff --git a/crates/carpet-ui/Cargo.toml b/crates/carpet-ui/Cargo.toml index 112f17b..35776be 100644 --- a/crates/carpet-ui/Cargo.toml +++ b/crates/carpet-ui/Cargo.toml @@ -21,3 +21,6 @@ default = [] web = ["dioxus/web"] server = ["dioxus/server", "dep:axum", "dep:tokio", "dep:nostr-lib", "dep:bdk-lib", "dep:phoenixd-lib"] desktop = ["dioxus/desktop"] + +[package.metadata.cargo-machete] +ignored = ["axum", "tokio", "nostr-lib", "bdk-lib", "phoenixd-lib", "serde", "serde_json"] diff --git a/crates/carpet-ui/src/components/list_detail.rs b/crates/carpet-ui/src/components/list_detail.rs index 2328c3f..1e3480d 100644 --- a/crates/carpet-ui/src/components/list_detail.rs +++ b/crates/carpet-ui/src/components/list_detail.rs @@ -8,7 +8,11 @@ use crate::types::ListDisplay; #[component] pub fn ListDetail(coordinate: String) -> Element { let lists: Signal> = use_context(); - let list = lists.read().iter().find(|l| l.coordinate == coordinate).cloned(); + let list = lists + .read() + .iter() + .find(|l| l.coordinate == coordinate) + .cloned(); let items = mock_data::mock_items(); match list { diff --git a/crates/carpet-ui/src/components/wallet_card.rs b/crates/carpet-ui/src/components/wallet_card.rs index 36e04d8..ed4fea6 100644 --- a/crates/carpet-ui/src/components/wallet_card.rs +++ b/crates/carpet-ui/src/components/wallet_card.rs @@ -9,7 +9,11 @@ pub enum WalletVariant { #[component] pub fn WalletCard(variant: WalletVariant, balance_sats: u64) -> Element { let (icon, label, accent) = match variant { - WalletVariant::Bitcoin => ("ph ph-currency-btc", "Bitcoin (on-chain)", "text-orange-500"), + WalletVariant::Bitcoin => ( + "ph ph-currency-btc", + "Bitcoin (on-chain)", + "text-orange-500", + ), WalletVariant::Lightning => ("ph ph-lightning", "Lightning", "text-amber-400"), }; diff --git a/crates/nostr-lib/Cargo.toml b/crates/nostr-lib/Cargo.toml index 5fc4048..138c3ee 100644 --- a/crates/nostr-lib/Cargo.toml +++ b/crates/nostr-lib/Cargo.toml @@ -12,3 +12,6 @@ serde_json = { workspace = true } thiserror = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } + +[package.metadata.cargo-machete] +ignored = ["tokio", "tracing"] diff --git a/crates/nostr-lib/src/filters.rs b/crates/nostr-lib/src/filters.rs index 80a4c12..ad81ef8 100644 --- a/crates/nostr-lib/src/filters.rs +++ b/crates/nostr-lib/src/filters.rs @@ -2,7 +2,7 @@ use nostr_sdk::prelude::*; use crate::types::kinds; -/// Build a filter for DCoSL list headers (kinds 9998 + 39998). +/// Build a filter for `DCoSL` list headers (kinds 9998 + 39998). pub fn list_headers_filter(author: Option, hashtag: Option<&str>) -> Filter { let mut filter = Filter::new().kinds(vec![kinds::HEADER_REGULAR, kinds::HEADER]); @@ -25,9 +25,7 @@ pub fn list_items_filter(z_ref: &str) -> Filter { /// Build a filter for bounties (NIP-99 kind 30402) with bounty hashtag. pub fn bounties_filter(target_coordinate: Option<&str>) -> Filter { - let mut filter = Filter::new() - .kind(kinds::BOUNTY) - .hashtag("bounty"); + let mut filter = Filter::new().kind(kinds::BOUNTY).hashtag("bounty"); if let Some(coord) = target_coordinate { filter = filter.custom_tag(SingleLetterTag::lowercase(Alphabet::A), coord.to_string()); @@ -38,17 +36,12 @@ pub fn bounties_filter(target_coordinate: Option<&str>) -> Filter { /// Build a filter for zap receipts (kind 9735) targeting a specific event or coordinate. pub fn zap_receipts_filter(target_pubkey: PublicKey) -> Filter { - Filter::new() - .kind(kinds::ZAP_RECEIPT) - .pubkey(target_pubkey) + Filter::new().kind(kinds::ZAP_RECEIPT).pubkey(target_pubkey) } /// Build a filter for profile metadata (kind 0). pub fn profile_filter(pubkey: PublicKey) -> Filter { - Filter::new() - .kind(Kind::Metadata) - .author(pubkey) - .limit(1) + Filter::new().kind(Kind::Metadata).author(pubkey).limit(1) } /// Build a filter for relay list (NIP-65 kind 10002). diff --git a/crates/nostr-lib/src/lib.rs b/crates/nostr-lib/src/lib.rs index 3261a3d..a1d7f0e 100644 --- a/crates/nostr-lib/src/lib.rs +++ b/crates/nostr-lib/src/lib.rs @@ -1,3 +1,7 @@ +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::must_use_candidate)] + pub mod error; pub mod filters; pub mod profile; diff --git a/crates/nostr-lib/src/profile.rs b/crates/nostr-lib/src/profile.rs index aa216fe..880d8ad 100644 --- a/crates/nostr-lib/src/profile.rs +++ b/crates/nostr-lib/src/profile.rs @@ -19,9 +19,12 @@ pub async fn fetch_profile( .await .map_err(|e| NostrLibError::Sdk(e.to_string()))?; - let event = events.into_iter().next().ok_or(NostrLibError::ProfileNotFound { - pubkey: pubkey.to_hex(), - })?; + let event = events + .into_iter() + .next() + .ok_or(NostrLibError::ProfileNotFound { + pubkey: pubkey.to_hex(), + })?; serde_json::from_str(&event.content).map_err(|_| NostrLibError::ProfileNotFound { pubkey: pubkey.to_hex(), @@ -29,10 +32,7 @@ pub async fn fetch_profile( } /// Extract lud16 (Lightning Address) from a profile. -pub async fn fetch_lud16( - client: &Client, - pubkey: PublicKey, -) -> Result { +pub async fn fetch_lud16(client: &Client, pubkey: PublicKey) -> Result { let profile = fetch_profile(client, pubkey).await?; profile.lud16.ok_or(NostrLibError::MissingLud16 { pubkey: pubkey.to_hex(), diff --git a/crates/nostr-lib/src/service.rs b/crates/nostr-lib/src/service.rs index 9c46e6c..b934820 100644 --- a/crates/nostr-lib/src/service.rs +++ b/crates/nostr-lib/src/service.rs @@ -10,7 +10,7 @@ use crate::types::{MarketplaceList, kinds}; const FETCH_TIMEOUT: Duration = Duration::from_secs(10); const FETCH_PAGE_SIZE: usize = 500; -/// Commands that the UI can send to the NostrService. +/// Commands that the UI can send to the `NostrService`. #[derive(Debug)] pub enum NostrCommand { /// Connect to a relay URL. @@ -31,7 +31,7 @@ pub enum NostrCommand { }, } -/// Marketplace-aware Nostr client wrapping nostr_sdk::Client. +/// Marketplace-aware Nostr client wrapping `nostr_sdk::Client`. pub struct NostrService { client: Client, } @@ -91,7 +91,7 @@ impl NostrService { Ok(events.into_iter().collect()) } - /// Fetch a full MarketplaceList by coordinate. + /// Fetch a full `MarketplaceList` by coordinate. pub async fn fetch_marketplace_list( &self, coordinate: &str, @@ -174,13 +174,11 @@ impl NostrService { let tags = dcosl_core::header::build_header_tags(¶ms); let builder = EventBuilder::new(kind, "").tags(tags); - let output = self - .client - .send_event_builder(builder) - .await - .map_err(|e| NostrLibError::PublishFailed { + let output = self.client.send_event_builder(builder).await.map_err(|e| { + NostrLibError::PublishFailed { reason: e.to_string(), - })?; + } + })?; // Fetch the published event back let filter = Filter::new().id(output.val).limit(1); @@ -217,13 +215,11 @@ impl NostrService { let builder = EventBuilder::new(kinds::ITEM, content.unwrap_or("")).tags(tags); - let output = self - .client - .send_event_builder(builder) - .await - .map_err(|e| NostrLibError::PublishFailed { + let output = self.client.send_event_builder(builder).await.map_err(|e| { + NostrLibError::PublishFailed { reason: e.to_string(), - })?; + } + })?; Ok(output.val) } diff --git a/crates/nostr-lib/src/types.rs b/crates/nostr-lib/src/types.rs index bbc4c88..b4fb09a 100644 --- a/crates/nostr-lib/src/types.rs +++ b/crates/nostr-lib/src/types.rs @@ -56,7 +56,7 @@ pub struct BountyFulfillment { pub zap_receipt_id: Option, } -/// DCoSL event kinds used in the marketplace. +/// `DCoSL` event kinds used in the marketplace. pub mod kinds { use nostr_sdk::Kind; diff --git a/crates/nostr-lib/src/zap.rs b/crates/nostr-lib/src/zap.rs index 2366901..840881d 100644 --- a/crates/nostr-lib/src/zap.rs +++ b/crates/nostr-lib/src/zap.rs @@ -8,7 +8,7 @@ use crate::profile; /// This returns the zap request event — it should be sent to the LNURL callback, /// NOT published to relays. #[allow(clippy::too_many_arguments)] -pub async fn build_zap_request( +pub fn build_zap_request( _client: &Client, signer: &Keys, recipient_pubkey: PublicKey, @@ -60,7 +60,7 @@ pub fn lud16_to_lnurl_callback(lud16: &str) -> Result { /// Full NIP-57 zap flow: /// 1. Fetch recipient's lud16 from kind 0 profile /// 2. Build zap request event -/// 3. Return (zap_request, lnurl_callback) for the caller to send +/// 3. Return (`zap_request`, `lnurl_callback`) for the caller to send pub async fn prepare_zap( client: &Client, signer: &Keys, @@ -81,7 +81,7 @@ pub async fn prepare_zap( .relays() .await .keys() - .map(|u| u.to_string()) + .map(std::string::ToString::to_string) .collect() } else { relay_urls @@ -96,8 +96,7 @@ pub async fn prepare_zap( amount_msats, relay_urls, content, - ) - .await?; + )?; Ok((zap_request, callback_url)) } diff --git a/crates/phoenixd-agcli/src/main.rs b/crates/phoenixd-agcli/src/main.rs index ce63814..df8ecdd 100644 --- a/crates/phoenixd-agcli/src/main.rs +++ b/crates/phoenixd-agcli/src/main.rs @@ -7,6 +7,7 @@ use agcli::{ use phoenixd_lib::PhoenixdError; use serde_json::json; +#[allow(clippy::needless_pass_by_value)] fn err(e: PhoenixdError) -> CommandError { let (code, retryable) = match &e { PhoenixdError::Http(_) => ("HTTP_ERROR", true), @@ -28,136 +29,126 @@ fn build_client() -> Result { fn info_command() -> Command { Command::new("info", "Show PhoenixD node info") .usage("phoenixd-agcli info") - .handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - Box::pin(async move { - let client = build_client()?; - let info = client.node_info().await.map_err(err)?; - Ok(CommandOutput::new(json!(info)).next_actions(vec![ - NextAction::new("phoenixd-agcli balance", "Check balance"), - NextAction::new("phoenixd-agcli channels", "List channels"), - ])) - }) - }, - ) + .handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + Box::pin(async move { + let client = build_client()?; + let info = client.node_info().await.map_err(err)?; + Ok(CommandOutput::new(json!(info)).next_actions(vec![ + NextAction::new("phoenixd-agcli balance", "Check balance"), + NextAction::new("phoenixd-agcli channels", "List channels"), + ])) + }) + }) } fn balance_command() -> Command { Command::new("balance", "Show wallet balance") .usage("phoenixd-agcli balance") - .handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - Box::pin(async move { - let client = build_client()?; - let balance = client.get_balance().await.map_err(err)?; - Ok(CommandOutput::new(json!(balance)).next_actions(vec![ - NextAction::new( - "phoenixd-agcli invoice --amount --description ", - "Create an invoice to receive", - ), - NextAction::new( - "phoenixd-agcli pay --invoice ", - "Pay an invoice", - ), - ])) - }) - }, - ) + .handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + Box::pin(async move { + let client = build_client()?; + let balance = client.get_balance().await.map_err(err)?; + Ok(CommandOutput::new(json!(balance)).next_actions(vec![ + NextAction::new( + "phoenixd-agcli invoice --amount --description ", + "Create an invoice to receive", + ), + NextAction::new("phoenixd-agcli pay --invoice ", "Pay an invoice"), + ])) + }) + }) } fn invoice_command() -> Command { Command::new("invoice", "Create a BOLT11 invoice") .usage("phoenixd-agcli invoice --amount --description ") - .handler( - |req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let amount_str = req.flag("amount").map(String::from); - let description = req - .flag("description") - .unwrap_or("magic-carpet invoice") - .to_string(); - let external_id = req.flag("external-id").map(String::from); - - Box::pin(async move { - let amount: u64 = amount_str - .ok_or_else(|| { - CommandError::new( - "--amount is required", - "MISSING_ARG", - "Provide --amount=", - ) - })? - .parse() - .map_err(|_| { - CommandError::new( - "--amount must be a number", - "INVALID_ARGS", - "Provide amount in satoshis", - ) - })?; - - let client = build_client()?; - let invoice = client - .create_invoice(amount, &description, external_id.as_deref()) - .await - .map_err(err)?; - - Ok(CommandOutput::new(json!(invoice)).next_actions(vec![ - NextAction::new( - "phoenixd-agcli balance", - "Check balance after payment", - ), - ])) - }) - }, - ) -} - -fn pay_command() -> Command { - Command::new("pay", "Pay a BOLT11 invoice") - .usage("phoenixd-agcli pay --invoice ") - .handler( - |req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - let bolt11 = req.flag("invoice").map(String::from); - - Box::pin(async move { - let bolt11 = bolt11.ok_or_else(|| { + .handler(|req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let amount_str = req.flag("amount").map(String::from); + let description = req + .flag("description") + .unwrap_or("magic-carpet invoice") + .to_string(); + let external_id = req.flag("external-id").map(String::from); + + Box::pin(async move { + let amount: u64 = amount_str + .ok_or_else(|| { CommandError::new( - "--invoice is required", + "--amount is required", "MISSING_ARG", - "Provide --invoice=", + "Provide --amount=", + ) + })? + .parse() + .map_err(|_| { + CommandError::new( + "--amount must be a number", + "INVALID_ARGS", + "Provide amount in satoshis", ) })?; - let client = build_client()?; - let result = client.pay_invoice(&bolt11).await.map_err(err)?; + let client = build_client()?; + let invoice = client + .create_invoice(amount, &description, external_id.as_deref()) + .await + .map_err(err)?; + + Ok( + CommandOutput::new(json!(invoice)).next_actions(vec![NextAction::new( + "phoenixd-agcli balance", + "Check balance after payment", + )]), + ) + }) + }) +} - Ok(CommandOutput::new(json!(result)).next_actions(vec![ - NextAction::new("phoenixd-agcli balance", "Check updated balance"), - ])) - }) - }, - ) +fn pay_command() -> Command { + Command::new("pay", "Pay a BOLT11 invoice") + .usage("phoenixd-agcli pay --invoice ") + .handler(|req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + let bolt11 = req.flag("invoice").map(String::from); + + Box::pin(async move { + let bolt11 = bolt11.ok_or_else(|| { + CommandError::new( + "--invoice is required", + "MISSING_ARG", + "Provide --invoice=", + ) + })?; + + let client = build_client()?; + let result = client.pay_invoice(&bolt11).await.map_err(err)?; + + Ok( + CommandOutput::new(json!(result)).next_actions(vec![NextAction::new( + "phoenixd-agcli balance", + "Check updated balance", + )]), + ) + }) + }) } fn channels_command() -> Command { Command::new("channels", "List channels") .usage("phoenixd-agcli channels") - .handler( - |_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { - Box::pin(async move { - let client = build_client()?; - let channels = client.list_channels().await.map_err(err)?; - Ok(CommandOutput::new(json!({ - "count": channels.len(), - "channels": channels, - })) - .next_actions(vec![ - NextAction::new("phoenixd-agcli info", "Node info"), - NextAction::new("phoenixd-agcli balance", "Balance"), - ])) - }) - }, - ) + .handler(|_req: &CommandRequest<'_>, _ctx: &mut ExecutionContext| { + Box::pin(async move { + let client = build_client()?; + let channels = client.list_channels().await.map_err(err)?; + Ok(CommandOutput::new(json!({ + "count": channels.len(), + "channels": channels, + })) + .next_actions(vec![ + NextAction::new("phoenixd-agcli info", "Node info"), + NextAction::new("phoenixd-agcli balance", "Balance"), + ])) + }) + }) } #[tokio::main] diff --git a/crates/phoenixd-lib/src/client.rs b/crates/phoenixd-lib/src/client.rs index fdb75e4..e3961d3 100644 --- a/crates/phoenixd-lib/src/client.rs +++ b/crates/phoenixd-lib/src/client.rs @@ -1,8 +1,10 @@ -use reqwest::header::{AUTHORIZATION, HeaderValue}; use reqwest::Client; +use reqwest::header::{AUTHORIZATION, HeaderValue}; use crate::error::PhoenixdError; -use crate::types::*; +use crate::types::{ + ChannelInfo, IncomingPayment, Invoice, NodeInfo, OutgoingPayment, PaymentResult, WalletBalance, +}; pub struct PhoenixdClient { http: Client, @@ -117,10 +119,7 @@ impl PhoenixdClient { Ok(()) } - pub async fn get_incoming_payment( - &self, - hash: &str, - ) -> Result { + pub async fn get_incoming_payment(&self, hash: &str) -> Result { let resp = self .http .get(format!("{}/payments/incoming/{hash}", self.base_url)) @@ -130,10 +129,7 @@ impl PhoenixdClient { Self::handle_response(resp).await } - pub async fn get_outgoing_payment( - &self, - id: &str, - ) -> Result { + pub async fn get_outgoing_payment(&self, id: &str) -> Result { let resp = self .http .get(format!("{}/payments/outgoing/{id}", self.base_url)) @@ -151,8 +147,6 @@ impl PhoenixdClient { return Err(PhoenixdError::Api { message: text }); } let text = resp.text().await?; - serde_json::from_str(&text).map_err(|e| { - PhoenixdError::Deserialize(format!("{e}: {text}")) - }) + serde_json::from_str(&text).map_err(|e| PhoenixdError::Deserialize(format!("{e}: {text}"))) } } diff --git a/crates/phoenixd-lib/src/lib.rs b/crates/phoenixd-lib/src/lib.rs index 546d2a3..daede96 100644 --- a/crates/phoenixd-lib/src/lib.rs +++ b/crates/phoenixd-lib/src/lib.rs @@ -1,3 +1,7 @@ +#![allow(clippy::missing_errors_doc)] +#![allow(clippy::missing_panics_doc)] +#![allow(clippy::must_use_candidate)] + pub mod client; pub mod error; pub mod types;