diff --git a/Cargo.lock b/Cargo.lock index 253f93f..508d8e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -20,9 +20,9 @@ checksum = "c71b1793ee61086797f5c80b6efa2b8ffa6d5dd703f118545808a7f2e27f7046" [[package]] name = "accesskit" -version = "0.11.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76eb1adf08c5bcaa8490b9851fd53cca27fa9880076f178ea9d29f05196728a8" +checksum = "74a4b14f3d99c1255dcba8f45621ab1a2e7540a0009652d33989005a4d0bfc6b" dependencies = [ "enumn", "serde", @@ -30,59 +30,61 @@ dependencies = [ [[package]] name = "accesskit_consumer" -version = "0.15.2" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04bb4d9e4772fe0d47df57d0d5dbe5d85dd05e2f37ae1ddb6b105e76be58fb00" +checksum = "8c17cca53c09fbd7288667b22a201274b9becaa27f0b91bf52a526db95de45e6" dependencies = [ "accesskit", ] [[package]] name = "accesskit_macos" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134d0acf6acb667c89d3332999b1a5df4edbc8d6113910f392ebb73f2b03bb56" +checksum = "cd3b6ae1eabbfbced10e840fd3fce8a93ae84f174b3e4ba892ab7bcb42e477a7" dependencies = [ "accesskit", "accesskit_consumer", - "objc2", + "objc2 0.3.0-beta.3.patch-leaks.3", "once_cell", ] [[package]] name = "accesskit_unix" -version = "0.5.2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e084cb5168790c0c112626175412dc5ad127083441a8248ae49ddf6725519e83" +checksum = "09f46c18d99ba61ad7123dd13eeb0c104436ab6af1df6a1cd8c11054ed394a08" dependencies = [ "accesskit", "accesskit_consumer", - "async-channel 1.9.0", + "async-channel", + "async-once-cell", "atspi", "futures-lite 1.13.0", + "once_cell", "serde", "zbus", ] [[package]] name = "accesskit_windows" -version = "0.14.3" +version = "0.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eac0a7f2d7cd7a93b938af401d3d8e8b7094217989a7c25c55a953023436e31" +checksum = "afcae27ec0974fc7c3b0b318783be89fd1b2e66dd702179fe600166a38ff4a0b" dependencies = [ "accesskit", "accesskit_consumer", - "arrayvec 0.7.4", "once_cell", "paste", + "static_assertions", "windows 0.48.0", ] [[package]] name = "accesskit_winit" -version = "0.14.4" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "825d23acee1bd6d25cbaa3ca6ed6e73faf24122a774ec33d52c5c86c6ab423c0" +checksum = "5284218aca17d9e150164428a0ebc7b955f70e3a9a78b4c20894513aabf98a67" dependencies = [ "accesskit", "accesskit_macos", @@ -166,6 +168,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if 1.0.0", + "getrandom 0.2.14", "once_cell", "serde", "version_check", @@ -189,20 +192,23 @@ checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" [[package]] name = "android-activity" -version = "0.4.3" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64529721f27c2314ced0890ce45e469574a73e5e6fdd6e9da1860eb29285f5e0" +checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" dependencies = [ "android-properties", - "bitflags 1.3.2", + "bitflags 2.5.0", "cc", + "cesu8", + "jni", "jni-sys", "libc", "log", "ndk", "ndk-context", "ndk-sys", - "num_enum 0.6.1", + "num_enum", + "thiserror", ] [[package]] @@ -251,7 +257,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a2041f1943049c7978768d84e6d0fd95de98b76d6c4727b09e78ec253d29fa58" dependencies = [ "clipboard-win", - "core-graphics 0.23.2", + "core-graphics", "image", "log", "objc", @@ -306,6 +312,12 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "as-raw-xcb-connection" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" + [[package]] name = "ash" version = "0.37.3+1.3.251" @@ -327,20 +339,9 @@ dependencies = [ [[package]] name = "async-channel" -version = "1.9.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81953c529336010edd6d8e358f886d9581267795c61b19475b71314bffa46d35" -dependencies = [ - "concurrent-queue", - "event-listener 2.5.3", - "futures-core", -] - -[[package]] -name = "async-channel" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f28243a43d821d11341ab73c80bed182dc015c514b951616cf79bd4af39af0c3" +checksum = "136d4d23bcc79e27423727b36823d86233aad06dfea531837b038394d11e9928" dependencies = [ "concurrent-queue", "event-listener 5.3.0", @@ -433,6 +434,12 @@ dependencies = [ "pin-project-lite 0.2.14", ] +[[package]] +name = "async-once-cell" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9338790e78aa95a416786ec8389546c4b6a1dfc3dc36071ed9518a9413a542eb" + [[package]] name = "async-process" version = "1.8.1" @@ -504,29 +511,50 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "atspi" -version = "0.10.1" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "674e7a3376837b2e7d12d34d58ac47073c491dc3bf6f71a7adaf687d4d817faa" +checksum = "6059f350ab6f593ea00727b334265c4dfc7fd442ee32d264794bd9bdc68e87ca" dependencies = [ - "async-recursion", - "async-trait", - "atspi-macros", - "enumflags2", - "futures-lite 1.13.0", - "serde", - "tracing", - "zbus", - "zbus_names", + "atspi-common", + "atspi-connection", + "atspi-proxies", ] [[package]] -name = "atspi-macros" -version = "0.2.0" +name = "atspi-common" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97fb4870a32c0eaa17e35bca0e6b16020635157121fb7d45593d242c295bc768" +checksum = "92af95f966d2431f962bc632c2e68eda7777330158bf640c4af4249349b2cdf5" dependencies = [ - "quote 1.0.36", - "syn 1.0.109", + "enumflags2", + "serde", + "static_assertions", + "zbus", + "zbus_names", + "zvariant", +] + +[[package]] +name = "atspi-connection" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0c65e7d70f86d4c0e3b2d585d9bf3f979f0b19d635a336725a88d279f76b939" +dependencies = [ + "atspi-common", + "atspi-proxies", + "futures-lite 1.13.0", + "zbus", +] + +[[package]] +name = "atspi-proxies" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6495661273703e7a229356dcbe8c8f38223d697aacfaf0e13590a9ac9977bb52" +dependencies = [ + "atspi-common", + "serde", + "zbus", ] [[package]] @@ -699,7 +727,16 @@ version = "0.1.0-beta.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa55741ee90902547802152aaf3f8e5248aab7e21468089560d4c8840561146" dependencies = [ - "objc-sys", + "objc-sys 0.2.0-beta.2", +] + +[[package]] +name = "block-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" +dependencies = [ + "objc-sys 0.3.2", ] [[package]] @@ -708,8 +745,18 @@ version = "0.2.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8dd9e63c1744f755c2f60332b88de39d341e5e86239014ad839bd71c106dec42" dependencies = [ - "block-sys", - "objc2-encode", + "block-sys 0.1.0-beta.1", + "objc2-encode 2.0.0-pre.2", +] + +[[package]] +name = "block2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" +dependencies = [ + "block-sys 0.2.1", + "objc2 0.4.1", ] [[package]] @@ -718,7 +765,7 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a37913e8dc4ddcc604f0c6d3bf2887c995153af3611de9e23c352b44c1b9118" dependencies = [ - "async-channel 2.2.0", + "async-channel", "async-lock 3.3.0", "async-task", "fastrand 2.0.2", @@ -815,16 +862,28 @@ checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "calloop" -version = "0.10.6" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52e0d00eb1ea24371a97d2da6201c6747a633dc6dc1988ef503403b4c59504a8" +checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "log", - "nix 0.25.1", - "slotmap", + "polling 3.6.0", + "rustix 0.38.32", + "slab", "thiserror", - "vec_map", +] + +[[package]] +name = "calloop-wayland-source" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" +dependencies = [ + "calloop", + "rustix 0.38.32", + "wayland-backend", + "wayland-client", ] [[package]] @@ -939,16 +998,16 @@ dependencies = [ [[package]] name = "cocoa" -version = "0.24.1" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f425db7937052c684daec3bd6375c8abe2d146dca4b8b143d6db777c39138f3a" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" dependencies = [ "bitflags 1.3.2", "block", "cocoa-foundation", "core-foundation 0.9.4", - "core-graphics 0.22.3", - "foreign-types 0.3.2", + "core-graphics", + "foreign-types 0.5.0", "libc", "objc", ] @@ -984,10 +1043,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] -name = "com-rs" -version = "0.2.1" +name = "com" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf43edc576402991846b093a7ca18a3477e0ef9c588cde84964b5d3e43016642" +checksum = "7e17887fd17353b65b1b2ef1c526c83e26cd72e74f598a8dc1bee13a48f3d9f6" +dependencies = [ + "com_macros", +] + +[[package]] +name = "com_macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d375883580a668c7481ea6631fc1a8863e33cc335bf56bfad8d7e6d4b04b13a5" +dependencies = [ + "com_macros_support", + "proc-macro2 1.0.79", + "syn 1.0.109", +] + +[[package]] +name = "com_macros_support" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad899a1087a9296d5644792d7cb72b8e34c1bec8e7d4fbc002230169a6e8710c" +dependencies = [ + "proc-macro2 1.0.79", + "quote 1.0.36", + "syn 1.0.109", +] [[package]] name = "combine" @@ -1055,19 +1139,6 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" -[[package]] -name = "core-graphics" -version = "0.22.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2581bbab3b8ffc6fcbd550bf46c355135d16e9ff2a6ea032ad6b9bf1d7efe4fb" -dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "core-graphics-types", - "foreign-types 0.3.2", - "libc", -] - [[package]] name = "core-graphics" version = "0.23.2" @@ -1204,6 +1275,12 @@ dependencies = [ "sct", ] +[[package]] +name = "cursor-icon" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991" + [[package]] name = "curve25519-dalek" version = "2.1.3" @@ -1230,17 +1307,6 @@ dependencies = [ "zeroize", ] -[[package]] -name = "d3d12" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e16e44ab292b1dddfdaf7be62cfd8877df52f2f3fde5858d95bab606be259f20" -dependencies = [ - "bitflags 2.5.0", - "libloading 0.8.3", - "winapi 0.3.9", -] - [[package]] name = "dashmap" version = "5.5.3" @@ -1389,6 +1455,15 @@ dependencies = [ "libloading 0.8.3", ] +[[package]] +name = "document-features" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef5282ad69563b5fc40319526ba27e0e7363d552a896f0297d54f767717f9b95" +dependencies = [ + "litrs", +] + [[package]] name = "downcast-rs" version = "1.2.1" @@ -1422,9 +1497,9 @@ dependencies = [ [[package]] name = "ecolor" -version = "0.23.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfdf4e52dbbb615cfd30cf5a5265335c217b5fd8d669593cea74a517d9c605af" +checksum = "20930a432bbd57a6d55e07976089708d4893f3d556cf42a0d79e9e321fa73b10" dependencies = [ "bytemuck", "serde", @@ -1455,12 +1530,13 @@ dependencies = [ [[package]] name = "eframe" -version = "0.23.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d9efede6c8905d3fc51a5ec9a506d4da4011bbcae0253d0304580fe40af3f5" +checksum = "020e2ccef6bbcec71dbc542f7eed64a5846fc3076727f5746da8fd307c91bab2" dependencies = [ "bytemuck", "cocoa", + "document-features", "egui", "egui-wgpu", "egui-winit", @@ -1475,12 +1551,14 @@ dependencies = [ "parking_lot 0.12.1", "percent-encoding", "pollster", - "raw-window-handle", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.0", "static_assertions", "thiserror", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "web-time", "wgpu", "winapi 0.3.9", "winit", @@ -1488,9 +1566,9 @@ dependencies = [ [[package]] name = "egui" -version = "0.23.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd69fed5fcf4fbb8225b24e80ea6193b61e17a625db105ef0c4d71dde6eb8b7" +checksum = "584c5d1bf9a67b25778a3323af222dbe1a1feb532190e103901187f92c7fe29a" dependencies = [ "accesskit", "ahash", @@ -1502,30 +1580,33 @@ dependencies = [ [[package]] name = "egui-wgpu" -version = "0.23.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62d4c9ab93d9528c184ef1d695c8c99b2e6d50833696ec3f513063efeee0fe77" +checksum = "469ff65843f88a702b731a1532b7d03b0e8e96d283e70f3a22b0e06c46cb9b37" dependencies = [ "bytemuck", + "document-features", + "egui", "epaint", "log", "thiserror", "type-map 0.5.0", + "web-time", "wgpu", "winit", ] [[package]] name = "egui-winit" -version = "0.23.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c15479a96d9fadccf5dac690bdc6373b97b8e1c0dd28367058f25a5298da0195" +checksum = "2e3da0cbe020f341450c599b35b92de4af7b00abde85624fd16f09c885573609" dependencies = [ "accesskit_winit", "arboard", "egui", "log", - "raw-window-handle", + "raw-window-handle 0.6.0", "smithay-clipboard", "web-time", "webbrowser", @@ -1534,31 +1615,32 @@ dependencies = [ [[package]] name = "egui_extras" -version = "0.23.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ffe3fe5c00295f91c2a61a74ee271c32f74049c94ba0b1cea8f26eb478bc07" +checksum = "1b78779f35ded1a853786c9ce0b43fe1053e10a21ea3b23ebea411805ce41593" dependencies = [ "egui", "enum-map", "image", "log", - "mime_guess", + "mime_guess2", "serde", ] [[package]] name = "egui_glow" -version = "0.23.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6726c08798822280038bbad2e32f4fc3cbed800cd51c6e34e99cd2d60cc1bc" +checksum = "e0e5d975f3c86edc3d35b1db88bb27c15dde7c55d3b5af164968ab5ede3f44ca" dependencies = [ "bytemuck", "egui", "glow", "log", - "memoffset 0.6.5", + "memoffset 0.9.1", "wasm-bindgen", "web-sys", + "winit", ] [[package]] @@ -1569,9 +1651,9 @@ checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" [[package]] name = "emath" -version = "0.23.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ef2b29de53074e575c18b694167ccbe6e5191f7b25fe65175a0d905a32eeec0" +checksum = "e4c3a552cfca14630702449d35f41c84a0d15963273771c6059175a803620f3f" dependencies = [ "bytemuck", "serde", @@ -1669,9 +1751,9 @@ dependencies = [ [[package]] name = "epaint" -version = "0.23.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58067b840d009143934d91d8dcb8ded054d8301d7c11a517ace0a99bb1e1595e" +checksum = "b381f8b149657a4acf837095351839f32cd5c4aec1817fc4df84e18d76334176" dependencies = [ "ab_glyph", "ahash", @@ -2189,9 +2271,9 @@ dependencies = [ [[package]] name = "glow" -version = "0.12.3" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca0fe580e4b60a8ab24a868bc08e2f03cbcb20d3d676601fa909386713333728" +checksum = "bd348e04c43b32574f2de31c8bb397d96c9fcfa1371bd4ca6d8bdc464ab121b1" dependencies = [ "js-sys", "slotmap", @@ -2201,11 +2283,11 @@ dependencies = [ [[package]] name = "glutin" -version = "0.30.10" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc93b03242719b8ad39fb26ed2b01737144ce7bd4bfc7adadcef806596760fe" +checksum = "18fcd4ae4e86d991ad1300b8f57166e5be0c95ef1f63f3f5b827f8a164548746" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "cfg_aliases", "cgl", "core-foundation 0.9.4", @@ -2213,42 +2295,43 @@ dependencies = [ "glutin_egl_sys", "glutin_glx_sys", "glutin_wgl_sys", - "libloading 0.7.4", - "objc2", + "icrate", + "libloading 0.8.3", + "objc2 0.4.1", "once_cell", - "raw-window-handle", - "wayland-sys 0.30.1", - "windows-sys 0.45.0", + "raw-window-handle 0.5.2", + "wayland-sys", + "windows-sys 0.48.0", "x11-dl", ] [[package]] name = "glutin-winit" -version = "0.3.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629a873fc04062830bfe8f97c03773bcd7b371e23bcc465d0a61448cd1588fa4" +checksum = "1ebcdfba24f73b8412c5181e56f092b5eff16671c514ce896b258a0a64bd7735" dependencies = [ "cfg_aliases", "glutin", - "raw-window-handle", + "raw-window-handle 0.5.2", "winit", ] [[package]] name = "glutin_egl_sys" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af784eb26c5a68ec85391268e074f0aa618c096eadb5d6330b0911cf34fe57c5" +checksum = "77cc5623f5309ef433c3dd4ca1223195347fe62c413da8e2fdd0eb76db2d9bcd" dependencies = [ "gl_generator", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "glutin_glx_sys" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b53cb5fe568964aa066a3ba91eac5ecbac869fb0842cd0dc9e412434f1a1494" +checksum = "a165fd686c10dcc2d45380b35796e577eacfd43d4660ee741ec8ebe2201b3b4f" dependencies = [ "gl_generator", "x11-dl", @@ -2256,9 +2339,9 @@ dependencies = [ [[package]] name = "glutin_wgl_sys" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef89398e90033fc6bc65e9bd42fd29bbbfd483bda5b56dc5562f455550618165" +checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" dependencies = [ "gl_generator", ] @@ -2284,15 +2367,15 @@ dependencies = [ [[package]] name = "gpu-allocator" -version = "0.22.0" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce95f9e2e11c2c6fadfce42b5af60005db06576f231f5c92550fdded43c423e8" +checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884" dependencies = [ - "backtrace", "log", + "presser", "thiserror", "winapi 0.3.9", - "windows 0.44.0", + "windows 0.51.1", ] [[package]] @@ -2345,9 +2428,9 @@ dependencies = [ "grin_wallet_util", "jni", "lazy_static", + "local-ip-address", "log", "openssl-sys", - "pnet", "rand 0.8.5", "rust-i18n", "serde", @@ -2808,14 +2891,14 @@ dependencies = [ [[package]] name = "hassle-rs" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1397650ee315e8891a0df210707f0fc61771b0cc518c3023896064c5407cb3b0" +checksum = "af2a7e73e1f34c48da31fb668a907f250794837e08faa144fd24f0b8b741e890" dependencies = [ - "bitflags 1.3.2", - "com-rs", + "bitflags 2.5.0", + "com", "libc", - "libloading 0.7.4", + "libloading 0.8.3", "thiserror", "widestring", "winapi 0.3.9", @@ -3097,7 +3180,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core", + "windows-core 0.52.0", ] [[package]] @@ -3109,6 +3192,17 @@ dependencies = [ "cc", ] +[[package]] +name = "icrate" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" +dependencies = [ + "block2 0.3.0", + "dispatch", + "objc2 0.4.1", +] + [[package]] name = "idna" version = "0.5.0" @@ -3176,9 +3270,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" dependencies = [ "cfg-if 1.0.0", - "js-sys", - "wasm-bindgen", - "web-sys", ] [[package]] @@ -3226,15 +3317,6 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" -[[package]] -name = "ipnetwork" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" -dependencies = [ - "serde", -] - [[package]] name = "is-terminal" version = "0.4.12" @@ -3338,12 +3420,12 @@ dependencies = [ [[package]] name = "khronos-egl" -version = "4.1.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2352bd1d0bceb871cb9d40f24360c8133c11d7486b68b5381c1dd1a32015e3" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" dependencies = [ "libc", - "libloading 0.7.4", + "libloading 0.8.3", "pkg-config", ] @@ -3458,6 +3540,12 @@ version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +[[package]] +name = "litrs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" + [[package]] name = "lmdb-zero" version = "0.4.4" @@ -3470,6 +3558,18 @@ dependencies = [ "supercow", ] +[[package]] +name = "local-ip-address" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "136ef34e18462b17bf39a7826f8f3bbc223341f8e83822beb8b77db9a3d49696" +dependencies = [ + "libc", + "neli", + "thiserror", + "windows-sys 0.48.0", +] + [[package]] name = "lock_api" version = "0.3.4" @@ -3565,22 +3665,13 @@ dependencies = [ [[package]] name = "memmap2" -version = "0.5.10" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83faa42c0a078c393f6b29d5db232d8be22776a891f8f56e5284faee4a20b327" +checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" -dependencies = [ - "autocfg 1.2.0", -] - [[package]] name = "memoffset" version = "0.7.1" @@ -3601,9 +3692,9 @@ dependencies = [ [[package]] name = "metal" -version = "0.26.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "623b5e6cefd76e58f774bd3cc0c6f5c7615c58c03a97815245a25c3c9bdee318" +checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25" dependencies = [ "bitflags 2.5.0", "block", @@ -3630,6 +3721,16 @@ dependencies = [ "unicase", ] +[[package]] +name = "mime_guess2" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a3333bb1609500601edc766a39b4c1772874a4ce26022f4d866854dc020c41" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -3672,7 +3773,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", - "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.48.0", ] @@ -3723,15 +3823,15 @@ dependencies = [ [[package]] name = "naga" -version = "0.13.0" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1ceaaa4eedaece7e4ec08c55c640ba03dbb73fb812a6570a59bcf1930d0f70e" +checksum = "50e3524642f53d9af419ab5e8dd29d3ba155708267667c2f3f06c88c9e130843" dependencies = [ "bit-set", "bitflags 2.5.0", "codespan-reporting", "hexf-parse", - "indexmap 1.9.3", + "indexmap 2.2.6", "log", "num-traits 0.2.18", "rustc-hash", @@ -3761,15 +3861,17 @@ dependencies = [ [[package]] name = "ndk" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "451422b7e4718271c8b5b3aadf5adedba43dc76312454b387e98fae0fc951aa0" +checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "jni-sys", + "log", "ndk-sys", - "num_enum 0.5.11", - "raw-window-handle", + "num_enum", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.0", "thiserror", ] @@ -3781,13 +3883,38 @@ checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] name = "ndk-sys" -version = "0.4.1+23.1.7779620" +version = "0.5.0+25.2.9519653" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cf2aae958bd232cac5069850591667ad422d263686d75b52a065f9badeee5a3" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" dependencies = [ "jni-sys", ] +[[package]] +name = "neli" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1100229e06604150b3becd61a4965d5c70f3be1759544ea7274166f4be41ef43" +dependencies = [ + "byteorder", + "libc", + "log", + "neli-proc-macros", +] + +[[package]] +name = "neli-proc-macros" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c168194d373b1e134786274020dae7fc5513d565ea2ebb9bc9ff17ffb69106d4" +dependencies = [ + "either", + "proc-macro2 1.0.79", + "quote 1.0.36", + "serde", + "syn 1.0.109", +] + [[package]] name = "net2" version = "0.2.39" @@ -3799,31 +3926,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "nix" -version = "0.24.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa52e972a9a719cecb6864fb88568781eb706bac2cd1d4f04a648542dbf78069" -dependencies = [ - "bitflags 1.3.2", - "cfg-if 1.0.0", - "libc", - "memoffset 0.6.5", -] - -[[package]] -name = "nix" -version = "0.25.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f346ff70e7dbfd675fe90590b92d59ef2de15a8779ae305ebcbfd3f0caf59be4" -dependencies = [ - "autocfg 1.2.0", - "bitflags 1.3.2", - "cfg-if 1.0.0", - "libc", - "memoffset 0.6.5", -] - [[package]] name = "nix" version = "0.26.4" @@ -3836,12 +3938,6 @@ dependencies = [ "memoffset 0.7.1", ] -[[package]] -name = "no-std-net" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" - [[package]] name = "nodrop" version = "0.1.14" @@ -3979,41 +4075,20 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.5.11" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f646caf906c20226733ed5b1374287eb97e3c2a5c227ce668c1f2ce20ae57c9" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" dependencies = [ - "num_enum_derive 0.5.11", -] - -[[package]] -name = "num_enum" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a015b430d3c108a207fd776d2e2196aaf8b1cf8cf93253e3a097ff3085076a1" -dependencies = [ - "num_enum_derive 0.6.1", + "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.5.11" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcbff9bc912032c62bf65ef1d5aea88983b420f4f839db1e9b0c281a25c9c799" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ - "proc-macro-crate", - "proc-macro2 1.0.79", - "quote 1.0.36", - "syn 1.0.109", -] - -[[package]] -name = "num_enum_derive" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96667db765a921f7b295ffee8b60472b686a51d4f21c2ee4ffdb94c7013b65a6" -dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.1.0", "proc-macro2 1.0.79", "quote 1.0.36", "syn 2.0.58", @@ -4046,15 +4121,31 @@ version = "0.2.0-beta.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df3b9834c1e95694a05a828b59f55fa2afec6288359cda67146126b3f90a55d7" +[[package]] +name = "objc-sys" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7c71324e4180d0899963fc83d9d241ac39e699609fc1025a850aadac8257459" + [[package]] name = "objc2" version = "0.3.0-beta.3.patch-leaks.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e01640f9f2cb1220bbe80325e179e532cb3379ebcd1bf2279d703c19fe3a468" dependencies = [ - "block2", - "objc-sys", - "objc2-encode", + "block2 0.2.0-alpha.6", + "objc-sys 0.2.0-beta.2", + "objc2-encode 2.0.0-pre.2", +] + +[[package]] +name = "objc2" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" +dependencies = [ + "objc-sys 0.3.2", + "objc2-encode 3.0.0", ] [[package]] @@ -4063,9 +4154,15 @@ version = "2.0.0-pre.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abfcac41015b00a120608fdaa6938c44cb983fee294351cc4bac7638b4e50512" dependencies = [ - "objc-sys", + "objc-sys 0.2.0-beta.2", ] +[[package]] +name = "objc2-encode" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" + [[package]] name = "objc_exception" version = "0.1.2" @@ -4367,97 +4464,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" -[[package]] -name = "pnet" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "130c5b738eeda2dc5796fe2671e49027e6935e817ab51b930a36ec9e6a206a64" -dependencies = [ - "ipnetwork", - "pnet_base", - "pnet_datalink", - "pnet_packet", - "pnet_sys", - "pnet_transport", -] - -[[package]] -name = "pnet_base" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe4cf6fb3ab38b68d01ab2aea03ed3d1132b4868fa4e06285f29f16da01c5f4c" -dependencies = [ - "no-std-net", -] - -[[package]] -name = "pnet_datalink" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad5854abf0067ebbd3967f7d45ebc8976ff577ff0c7bd101c4973ae3c70f98fe" -dependencies = [ - "ipnetwork", - "libc", - "pnet_base", - "pnet_sys", - "winapi 0.3.9", -] - -[[package]] -name = "pnet_macros" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688b17499eee04a0408aca0aa5cba5fc86401d7216de8a63fdf7a4c227871804" -dependencies = [ - "proc-macro2 1.0.79", - "quote 1.0.36", - "regex", - "syn 2.0.58", -] - -[[package]] -name = "pnet_macros_support" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eea925b72f4bd37f8eab0f221bbe4c78b63498350c983ffa9dd4bcde7e030f56" -dependencies = [ - "pnet_base", -] - -[[package]] -name = "pnet_packet" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a005825396b7fe7a38a8e288dbc342d5034dac80c15212436424fef8ea90ba" -dependencies = [ - "glob", - "pnet_base", - "pnet_macros", - "pnet_macros_support", -] - -[[package]] -name = "pnet_sys" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "417c0becd1b573f6d544f73671070b039051e5ad819cc64aa96377b536128d00" -dependencies = [ - "libc", - "winapi 0.3.9", -] - -[[package]] -name = "pnet_transport" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2637e14d7de974ee2f74393afccbc8704f3e54e6eb31488715e72481d1662cc3" -dependencies = [ - "libc", - "pnet_base", - "pnet_packet", - "pnet_sys", -] - [[package]] name = "png" version = "0.17.13" @@ -4525,6 +4531,12 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "presser" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" + [[package]] name = "prettytable-rs" version = "0.10.0" @@ -4549,6 +4561,15 @@ dependencies = [ "toml_edit 0.19.15", ] +[[package]] +name = "proc-macro-crate" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +dependencies = [ + "toml_edit 0.21.1", +] + [[package]] name = "proc-macro-error" version = "1.0.4" @@ -4609,6 +4630,15 @@ version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" +[[package]] +name = "quick-xml" +version = "0.31.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +dependencies = [ + "memchr", +] + [[package]] name = "quote" version = "0.6.13" @@ -4817,18 +4847,18 @@ dependencies = [ "rand_core 0.3.1", ] -[[package]] -name = "range-alloc" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8a99fddc9f0ba0a85884b8d14e3592853e787d581ca1816c91349b10e4eeab" - [[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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a9830a0e1b9fb145ebb365b8bc4ccd75f290f98c0247deafbbe2c75cefb544" + [[package]] name = "rayon" version = "1.10.0" @@ -5240,9 +5270,9 @@ dependencies = [ [[package]] name = "sctk-adwaita" -version = "0.5.4" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda4e97be1fd174ccc2aae81c8b694e803fa99b34e8fd0f057a9d70698e3ed09" +checksum = "82b2eaf3a5b264a521b988b2e73042e742df700c4f962cde845d1541adb46550" dependencies = [ "ab_glyph", "log", @@ -5528,31 +5558,47 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smithay-client-toolkit" -version = "0.16.1" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "870427e30b8f2cbe64bf43ec4b86e88fe39b0a84b3f15efd9c9c2d020bc86eb9" +checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", "calloop", - "dlib", - "lazy_static", + "calloop-wayland-source", + "cursor-icon", + "libc", "log", "memmap2", - "nix 0.24.3", - "pkg-config", + "rustix 0.38.32", + "thiserror", + "wayland-backend", "wayland-client", + "wayland-csd-frame", "wayland-cursor", "wayland-protocols", + "wayland-protocols-wlr", + "wayland-scanner", + "xkeysym", ] [[package]] name = "smithay-clipboard" -version = "0.6.6" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a345c870a1fae0b1b779085e81b51e614767c239e93503588e54c5b17f4b0e8" +checksum = "c091e7354ea8059d6ad99eace06dd13ddeedbb0ac72d40a9a6e7ff790525882d" dependencies = [ + "libc", "smithay-client-toolkit", - "wayland-client", + "wayland-backend", +] + +[[package]] +name = "smol_str" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49" +dependencies = [ + "serde", ] [[package]] @@ -5594,12 +5640,11 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "spirv" -version = "0.2.0+1.5.4" +version = "0.3.0+sdk-1.3.268.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246bfa38fe3db3f1dfc8ca5a2cdeb7348c78be2112740cc0ec8ef18b6d94f830" +checksum = "eda41003dc44290527a59b13432d4a0379379fa074b70174882adfbdfd917844" dependencies = [ - "bitflags 1.3.2", - "num-traits 0.2.18", + "bitflags 2.5.0", ] [[package]] @@ -5802,23 +5847,23 @@ dependencies = [ [[package]] name = "tiny-skia" -version = "0.8.4" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df8493a203431061e901613751931f047d1971337153f96d0e5e363d6dbf6a67" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" dependencies = [ "arrayref", "arrayvec 0.7.4", "bytemuck", "cfg-if 1.0.0", - "png", + "log", "tiny-skia-path", ] [[package]] name = "tiny-skia-path" -version = "0.8.4" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adbfb5d3f3dd57a0e11d12f4f13d4ebbbc1b5c15b7ab0a156d030b21da5f677c" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" dependencies = [ "arrayref", "bytemuck", @@ -6068,6 +6113,17 @@ dependencies = [ "winnow 0.5.40", ] +[[package]] +name = "toml_edit" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" +dependencies = [ + "indexmap 2.2.6", + "toml_datetime", + "winnow 0.5.40", +] + [[package]] name = "toml_edit" version = "0.22.9" @@ -6316,12 +6372,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.4" @@ -6434,87 +6484,111 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] -name = "wayland-client" -version = "0.29.5" +name = "wayland-backend" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f3b068c05a039c9f755f881dc50f01732214f5685e379829759088967c46715" +checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40" dependencies = [ - "bitflags 1.3.2", + "cc", "downcast-rs", - "libc", - "nix 0.24.3", + "rustix 0.38.32", "scoped-tls", - "wayland-commons", - "wayland-scanner", - "wayland-sys 0.29.5", + "smallvec", + "wayland-sys", ] [[package]] -name = "wayland-commons" -version = "0.29.5" +name = "wayland-client" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8691f134d584a33a6606d9d717b95c4fa20065605f798a3f350d78dced02a902" +checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f" dependencies = [ - "nix 0.24.3", - "once_cell", - "smallvec", - "wayland-sys 0.29.5", + "bitflags 2.5.0", + "rustix 0.38.32", + "wayland-backend", + "wayland-scanner", +] + +[[package]] +name = "wayland-csd-frame" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" +dependencies = [ + "bitflags 2.5.0", + "cursor-icon", + "wayland-backend", ] [[package]] name = "wayland-cursor" -version = "0.29.5" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6865c6b66f13d6257bef1cd40cbfe8ef2f150fb8ebbdb1e8e873455931377661" +checksum = "71ce5fa868dd13d11a0d04c5e2e65726d0897be8de247c0c5a65886e283231ba" dependencies = [ - "nix 0.24.3", + "rustix 0.38.32", "wayland-client", "xcursor", ] [[package]] name = "wayland-protocols" -version = "0.29.5" +version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b950621f9354b322ee817a23474e479b34be96c2e909c14f7bc0100e9a970bc6" +checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.5.0", + "wayland-backend", "wayland-client", - "wayland-commons", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-plasma" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" +dependencies = [ + "bitflags 2.5.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", + "wayland-scanner", +] + +[[package]] +name = "wayland-protocols-wlr" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +dependencies = [ + "bitflags 2.5.0", + "wayland-backend", + "wayland-client", + "wayland-protocols", "wayland-scanner", ] [[package]] name = "wayland-scanner" -version = "0.29.5" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f4303d8fa22ab852f789e75a967f0a2cdc430a607751c0499bada3e451cbd53" +checksum = "63b3a62929287001986fb58c789dce9b67604a397c15c611ad9f747300b6c283" dependencies = [ "proc-macro2 1.0.79", + "quick-xml", "quote 1.0.36", - "xml-rs", ] [[package]] name = "wayland-sys" -version = "0.29.5" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be12ce1a3c39ec7dba25594b97b42cb3195d54953ddb9d3d95a7c3902bc6e9d4" +checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af" dependencies = [ "dlib", - "lazy_static", - "pkg-config", -] - -[[package]] -name = "wayland-sys" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96b2a02ac608e07132978689a6f9bf4214949c85998c247abadd4f4129b1aa06" -dependencies = [ - "dlib", - "lazy_static", "log", + "once_cell", "pkg-config", ] @@ -6550,7 +6624,7 @@ dependencies = [ "log", "ndk-context", "objc", - "raw-window-handle", + "raw-window-handle 0.5.2", "url", "web-sys", ] @@ -6582,18 +6656,19 @@ checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" [[package]] name = "wgpu" -version = "0.17.2" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "752e44d3998ef35f71830dd1ad3da513e628e2e4d4aedb0ab580f850827a0b41" +checksum = "a4b1213b52478a7631d6e387543ed8f642bc02c578ef4e3b49aca2a29a7df0cb" dependencies = [ "arrayvec 0.7.4", "cfg-if 1.0.0", + "cfg_aliases", "js-sys", "log", "naga", "parking_lot 0.12.1", "profiling", - "raw-window-handle", + "raw-window-handle 0.6.0", "smallvec", "static_assertions", "wasm-bindgen", @@ -6606,19 +6681,22 @@ dependencies = [ [[package]] name = "wgpu-core" -version = "0.17.1" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f8a44dd301a30ceeed3c27d8c0090433d3da04d7b2a4042738095a424d12ae7" +checksum = "f9f6b033c2f00ae0bc8ea872c5989777c60bc241aac4e58b24774faa8b391f78" dependencies = [ "arrayvec 0.7.4", "bit-vec", "bitflags 2.5.0", + "cfg_aliases", "codespan-reporting", + "indexmap 2.2.6", "log", "naga", + "once_cell", "parking_lot 0.12.1", "profiling", - "raw-window-handle", + "raw-window-handle 0.6.0", "rustc-hash", "smallvec", "thiserror", @@ -6629,19 +6707,19 @@ dependencies = [ [[package]] name = "wgpu-hal" -version = "0.17.2" +version = "0.19.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a80bf0e3c77399bb52850cb0830af9bad073d5cfcb9dd8253bef8125c42db17" +checksum = "49f972c280505ab52ffe17e94a7413d9d54b58af0114ab226b9fc4999a47082e" dependencies = [ "android_system_properties", "arrayvec 0.7.4", "ash", - "bit-set", "bitflags 2.5.0", "block", + "cfg_aliases", "core-graphics-types", - "d3d12", "glow", + "glutin_wgl_sys", "gpu-alloc", "gpu-allocator", "gpu-descriptor", @@ -6653,11 +6731,12 @@ dependencies = [ "log", "metal", "naga", + "ndk-sys", "objc", + "once_cell", "parking_lot 0.12.1", "profiling", - "range-alloc", - "raw-window-handle", + "raw-window-handle 0.6.0", "renderdoc-sys", "rustc-hash", "smallvec", @@ -6670,9 +6749,9 @@ dependencies = [ [[package]] name = "wgpu-types" -version = "0.17.0" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee64d7398d0c2f9ca48922c902ef69c42d000c759f3db41e355f4a570b052b67" +checksum = "b671ff9fb03f78b46ff176494ee1ebe7d603393f42664be55b64dc8d53969805" dependencies = [ "bitflags 2.5.0", "js-sys", @@ -6728,15 +6807,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.44.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e745dab35a0c4c77aa3ce42d595e13d2003d6902d6b08c9ef5fc326d08da12b" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows" version = "0.48.0" @@ -6748,6 +6818,25 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca229916c5ee38c2f2bc1e9d8f04df975b4bd93f9955dc69fabb5d91270045c9" +dependencies = [ + "windows-core 0.51.1", + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-core" +version = "0.51.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-core" version = "0.52.0" @@ -6986,37 +7075,51 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winit" -version = "0.28.7" +version = "0.29.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9596d90b45384f5281384ab204224876e8e8bf7d58366d9b795ad99aa9894b94" +checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca" dependencies = [ + "ahash", "android-activity", - "bitflags 1.3.2", + "atomic-waker", + "bitflags 2.5.0", + "bytemuck", + "calloop", "cfg_aliases", "core-foundation 0.9.4", - "core-graphics 0.22.3", - "dispatch", - "instant", + "core-graphics", + "cursor-icon", + "icrate", + "js-sys", "libc", "log", - "mio 0.8.11", + "memmap2", "ndk", - "objc2", + "ndk-sys", + "objc2 0.4.1", "once_cell", "orbclient", "percent-encoding", - "raw-window-handle", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.0", "redox_syscall 0.3.5", + "rustix 0.38.32", "sctk-adwaita", "smithay-client-toolkit", + "smol_str", + "unicode-segmentation", "wasm-bindgen", + "wasm-bindgen-futures", + "wayland-backend", "wayland-client", - "wayland-commons", "wayland-protocols", - "wayland-scanner", + "wayland-protocols-plasma", "web-sys", - "windows-sys 0.45.0", + "web-time", + "windows-sys 0.48.0", "x11-dl", + "x11rb", + "xkbcommon-dl", ] [[package]] @@ -7073,7 +7176,11 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" dependencies = [ + "as-raw-xcb-connection", "gethostname", + "libc", + "libloading 0.8.3", + "once_cell", "rustix 0.38.32", "x11rb-protocol", ] @@ -7122,6 +7229,25 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "xkbcommon-dl" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" +dependencies = [ + "bitflags 2.5.0", + "dlib", + "log", + "once_cell", + "xkeysym", +] + +[[package]] +name = "xkeysym" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "054a8e68b76250b253f671d1268cb7f1ae089ec35e195b2efb2a4e9a836d0621" + [[package]] name = "xml-rs" version = "0.8.20" @@ -7161,7 +7287,7 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix 0.26.4", + "nix", "once_cell", "ordered-stream", "rand 0.8.5", @@ -7184,7 +7310,7 @@ version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7131497b0f887e8061b430c530240063d33bf9455fa34438f388a245da69e0a5" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2 1.0.79", "quote 1.0.36", "regex", @@ -7274,7 +7400,7 @@ version = "3.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37c24dc0bed72f5f90d1f8bb5b07228cbf63b3c6e9f82d82559d4bae666e7ed9" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 1.3.1", "proc-macro2 1.0.79", "quote 1.0.36", "syn 1.0.109", diff --git a/Cargo.toml b/Cargo.toml index 61e8152..30de838 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,24 +33,24 @@ grin_wallet_util = { git = "https://github.com/mimblewimble/grin-wallet", branch grin_wallet_controller = { git = "https://github.com/mimblewimble/grin-wallet", branch = "master" } ## ui -egui = { version = "0.23.0", default-features = false } -egui_extras = { version = "0.23.0", features = ["image"] } +egui = { version = "0.27.2", default-features = false } +egui_extras = { version = "0.27.2", features = ["image"] } rust-i18n = "2.1.0" ## other futures = "0.3" dirs = "5.0.1" sys-locale = "0.3.0" -chrono = "0.4.37" +chrono = "0.4.31" lazy_static = "1.4.0" toml = "0.8.2" serde = "1.0.170" -pnet = "0.34.0" +local-ip-address = "0.6.1" url = "2.4.0" # stratum server -serde_derive = "1" -serde_json = "1" +serde_derive = "1.0.197" +serde_json = "1.0.115" tokio = {version = "1.29.1", features = ["full"] } tokio-util = { version = "0.7.8", features = ["codec"] } rand = "0.8.5" @@ -60,13 +60,13 @@ built = { version = "0.7.0", features = ["git2"]} [target.'cfg(not(target_os = "android"))'.dependencies] env_logger = "0.10.0" -winit = { version = "0.28" } -eframe = { version = "0.23.0", features = [ "wgpu" ] } +winit = { version = "0.29.15" } +eframe = { version = "0.27.2", features = [ "wgpu" ] } arboard = "3.2.0" [target.'cfg(target_os = "android")'.dependencies] android_logger = "0.13.1" jni = "0.21.1" -android-activity = "0.4.3" -winit = { version = "0.28", features = [ "android-game-activity" ] } -eframe = { version = "0.23.0", features = [ "wgpu", "android-game-activity" ] } \ No newline at end of file +android-activity = "0.5.2" +winit = { version = "0.29", features = [ "android-game-activity" ] } +eframe = { version = "0.27.2", features = [ "wgpu", "android-game-activity" ] } \ No newline at end of file diff --git a/app/build.gradle b/app/build.gradle index 3701d99..1431656 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -41,7 +41,7 @@ dependencies { //implementation "androidx.games:games-performance-tuner:1.5.0" // To use the Games Activity library - implementation "androidx.games:games-activity:1.1.0" + implementation "androidx.games:games-activity:2.0.2" // To use the Games Controller Library //implementation "androidx.games:games-controller:1.1.0" diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 5a889f0..f28299c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -3,7 +3,6 @@ > - diff --git a/app/src/main/java/mw/gri/android/MainActivity.java b/app/src/main/java/mw/gri/android/MainActivity.java index 56b67b3..a595211 100644 --- a/app/src/main/java/mw/gri/android/MainActivity.java +++ b/app/src/main/java/mw/gri/android/MainActivity.java @@ -7,6 +7,7 @@ import android.system.ErrnoException; import android.system.Os; import android.view.KeyEvent; import android.view.View; +import android.view.inputmethod.InputMethodManager; import androidx.core.graphics.Insets; import androidx.core.view.DisplayCutoutCompat; import androidx.core.view.ViewCompat; @@ -80,12 +81,33 @@ public class MainActivity extends GameActivity { }); } + @Override + public boolean dispatchKeyEvent(KeyEvent event) { + // To support non-english input. + if (event.getAction() == KeyEvent.ACTION_MULTIPLE && event.getKeyCode() == KeyEvent.KEYCODE_UNKNOWN) { + if (!event.getCharacters().isEmpty()) { + onInput(event.getCharacters()); + return false; + } + // Pass any other input values into native code. + } else if (event.getAction() == KeyEvent.ACTION_UP && + event.getKeyCode() != KeyEvent.KEYCODE_ENTER && + event.getKeyCode() != KeyEvent.KEYCODE_BACK) { + onInput(String.valueOf((char)event.getUnicodeChar())); + return false; + } + return super.dispatchKeyEvent(event); + } + + // Provide last entered character from soft keyboard into native code. + public native void onInput(String character); + // Implemented into native code to handle display insets change. native void onDisplayInsets(int[] cutouts); @Override public boolean onKeyDown(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_BACK) { + if (keyCode == KeyEvent.KEYCODE_BACK) { onBack(); return true; } @@ -146,4 +168,14 @@ public class MainActivity extends GameActivity { } return text; } + + public void showKeyboard() { + InputMethodManager imm = (InputMethodManager )getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(getWindow().getDecorView(), InputMethodManager.SHOW_IMPLICIT); + } + + public void hideKeyboard() { + InputMethodManager imm = (InputMethodManager )getSystemService(Context.INPUT_METHOD_SERVICE); + imm.hideSoftInputFromWindow(getWindow().getDecorView().getWindowToken(), 0); + } } \ No newline at end of file diff --git a/build.gradle b/build.gradle index 44ca6e4..3d408a5 100644 --- a/build.gradle +++ b/build.gradle @@ -1,7 +1,7 @@ // Top-level build file where you can add configuration options common to all sub-projects/modules. plugins { - id 'com.android.application' version '7.4.1' apply false - id 'com.android.library' version '7.4.1' apply false + id 'com.android.application' version '8.1.0' apply false + id 'com.android.library' version '8.1.0' apply false } task clean(type: Delete) { diff --git a/build_run_android.sh b/build_run_android.sh index d4e08d5..d39b007 100755 --- a/build_run_android.sh +++ b/build_run_android.sh @@ -29,6 +29,10 @@ type=$1 [[ $2 == "v7" ]] && platform+=(armv7-linux-androideabi) [[ $2 == "v8" ]] && platform+=(aarch64-linux-android) +# Install platform +[[ $2 == "v7" ]] && rustup target install armv7-linux-androideabi +[[ $2 == "v8" ]] && rustup target install aarch64-linux-android + export CPPFLAGS="-DMDB_USE_ROBUST=0" && export CFLAGS="-DMDB_USE_ROBUST=0" \ && cargo ndk -t ${arch} build ${release_param[@]} diff --git a/gradle.properties b/gradle.properties index dab7c28..ec63151 100644 --- a/gradle.properties +++ b/gradle.properties @@ -18,4 +18,6 @@ android.useAndroidX=true # Enables namespacing of each library's R class so that its R class includes only the # resources declared in the library itself and none from the library's dependencies, # thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true \ No newline at end of file +android.nonTransitiveRClass=true +android.defaults.buildfeatures.buildconfig=true +android.nonFinalResIds=false \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 0460660..5538f03 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Mon May 02 15:39:12 BST 2022 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/locales/en.yml b/locales/en.yml index 4e62b5d..bc5287a 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -64,11 +64,18 @@ wallets: tx_canceled: Canceled tx_confirmed: Confirmed manually: Manually - receive_paste_slatepack: 'Enter Slatepack message received from the sender to create a response:' - receive_send_slatepack: 'Send response to the sender to finalize the transaction:' - receive_slatepack_err: An error occurred during creation of the response, check input data. - response_copied: Response copied to the clipboard. + receive_slatepack_desc: 'Enter Slatepack message received from the sender to create response or finalize the transaction:' + receive_send_slatepack: 'Send Slatepack message to the sender to finalize the transaction:' + receive_slatepack_err: 'An error occurred during creation of the response, check input data:' create_response: Create response + invoice: Invoice + issue_invoice: Issue invoice + issue_invoice_desc: 'Create a request to receive funds by entering the required amount:' + invoice_desc: 'You have created a request to receive %{amount} ツ. Send Slatepack message to the sender:' + invoice_slatepack_err: An error occurred during issuing of the invoice, check input data. + finalize_slatepack_err: 'An error occurred during finalization of the transaction, check input data:' + finalize: Finalize + enter_amount: 'Enter amount:' recovery: Recovery repair_wallet: Repair wallet repair_desc: Check a wallet, repairing and restoring missing outputs if required. This operation will take time. diff --git a/locales/ru.yml b/locales/ru.yml index 58e76f6..40bffd5 100644 --- a/locales/ru.yml +++ b/locales/ru.yml @@ -44,7 +44,7 @@ wallets: locked: Заблокирован unlocked: Разблокирован enable_node: 'Чтобы использовать кошелёк, включите встроенный узел или измените настройки подключения, выбрав %{settings} внизу экрана.' - node_loading: Кошелёк будет загружен после синхронизации встроенного узла, вы можете изменить настройки подключения, выбрав %{settings} внизу экрана. + node_loading: 'Кошелёк будет загружен после синхронизации встроенного узла, вы можете изменить настройки подключения, выбрав %{settings} внизу экрана.' loading: Загружается closing: Закрывается checking: Проверяется @@ -64,11 +64,18 @@ wallets: tx_canceled: Отменено tx_confirmed: Подтверждено manually: Вручную - receive_paste_slatepack: 'Введите Slatepack сообщение, полученное от отправителя для создания ответа:' - receive_send_slatepack: 'Отправьте ответ отправителю для завершения транзакции:' - receive_slatepack_err: Во время создания ответа произошла ошибка, проверьте входные данные. - response_copied: Ответ скопирован в буфер обмена. + receive_slatepack_desc: 'Введите Slatepack сообщение, полученное от отправителя, для создания ответа или завершения транзакции:' + receive_send_slatepack: 'Отправьте Slatepack сообщение отправителю для завершения транзакции:' + receive_slatepack_err: 'Во время создания ответа произошла ошибка, проверьте входные данные:' create_response: Создать ответ + invoice: Инвойс + issue_invoice: Выставить счёт + issue_invoice_desc: 'Создайте запрос на получение средств, введя требуемое количество:' + invoice_desc: 'Вы создали запрос на получение %{amount} ツ. Отправьте Slatepack сообщение отправителю:' + invoice_slatepack_err: Во время выставления счёта произошла ошибка, проверьте входные данные. + finalize_slatepack_err: 'Во время завершения транзакции произошла ошибка, проверьте входные данные:' + finalize: Завершить + enter_amount: 'Введите количество:' recovery: Восстановление repair_wallet: Починить кошелёк repair_desc: Проверить кошелёк, исправляя и восстанавливая недостающие выходы, если это необходимо. Эта операция займёт время. diff --git a/src/gui/app.rs b/src/gui/app.rs index d2c6e2d..93e81d1 100644 --- a/src/gui/app.rs +++ b/src/gui/app.rs @@ -45,12 +45,21 @@ impl eframe::App for PlatformApp { // Handle Esc keyboard key event and platform Back button key event. let back_button_pressed = BACK_BUTTON_PRESSED.load(Ordering::Relaxed); if ctx.input_mut(|i| i.consume_key(Modifiers::NONE, egui::Key::Escape)) || back_button_pressed { - if back_button_pressed { - BACK_BUTTON_PRESSED.store(false, Ordering::Relaxed); - } self.root.on_back(); // Request repaint to update previous content. ctx.request_repaint(); + + if back_button_pressed { + BACK_BUTTON_PRESSED.store(false, Ordering::Relaxed); + } + } + + // Handle Close event (on desktop). + if ctx.input(|i| i.viewport().close_requested()) { + if !self.root.exit_allowed { + ctx.send_viewport_cmd(egui::ViewportCommand::CancelClose); + Root::show_exit_modal(); + } } // Show main content. @@ -63,14 +72,6 @@ impl eframe::App for PlatformApp { self.root.ui(ui, frame, &self.platform); }); } - - fn on_close_event(&mut self) -> bool { - let exit = self.root.exit_allowed; - if !exit { - Root::show_exit_modal(); - } - exit - } } #[allow(dead_code)] diff --git a/src/gui/platform/android/mod.rs b/src/gui/platform/android/mod.rs index 0a8eaae..264e945 100644 --- a/src/gui/platform/android/mod.rs +++ b/src/gui/platform/android/mod.rs @@ -30,11 +30,41 @@ impl Android { impl PlatformCallbacks for Android { fn show_keyboard(&self) { - self.android_app.show_soft_input(true); + // Disable NDK soft input show call before fix for egui. + // self.android_app.show_soft_input(false); + + use jni::objects::{JObject}; + + let vm = unsafe { jni::JavaVM::from_raw(self.android_app.vm_as_ptr() as _) }.unwrap(); + let mut env = vm.attach_current_thread().unwrap(); + let activity = unsafe { + JObject::from_raw(self.android_app.activity_as_ptr() as jni::sys::jobject) + }; + let _ = env.call_method( + activity, + "showKeyboard", + "()V", + &[] + ).unwrap(); } fn hide_keyboard(&self) { - self.android_app.hide_soft_input(true); + // Disable NDK soft input hide call before fix for egui. + // self.android_app.hide_soft_input(false); + + use jni::objects::{JObject}; + + let vm = unsafe { jni::JavaVM::from_raw(self.android_app.vm_as_ptr() as _) }.unwrap(); + let mut env = vm.attach_current_thread().unwrap(); + let activity = unsafe { + JObject::from_raw(self.android_app.activity_as_ptr() as jni::sys::jobject) + }; + let _ = env.call_method( + activity, + "hideKeyboard", + "()V", + &[] + ).unwrap(); } fn copy_string_to_buffer(&self, data: String) { diff --git a/src/gui/views/network/content.rs b/src/gui/views/network/content.rs index c34656f..4abf9c0 100644 --- a/src/gui/views/network/content.rs +++ b/src/gui/views/network/content.rs @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use egui::{RichText, ScrollArea, Stroke}; -use egui::style::Margin; +use egui::{Margin, RichText, ScrollArea, Stroke}; use crate::AppConfig; use crate::gui::Colors; @@ -57,7 +56,7 @@ impl NetworkContent { fill: Colors::FILL, inner_margin: Margin { left: View::get_left_inset() + 4.0, - right: View::far_right_inset_margin(ui, frame) + 4.0, + right: View::far_right_inset_margin(ui) + 4.0, top: 4.0, bottom: View::get_bottom_inset() + 4.0, }, @@ -82,7 +81,7 @@ impl NetworkContent { stroke: View::DEFAULT_STROKE, inner_margin: Margin { left: View::get_left_inset() + 4.0, - right: View::far_right_inset_margin(ui, frame) + 4.0, + right: View::far_right_inset_margin(ui) + 4.0, top: 3.0, bottom: 4.0, }, @@ -108,7 +107,7 @@ impl NetworkContent { 0.0 }, right: if show_connections { - View::far_right_inset_margin(ui, frame) + 4.0 + View::far_right_inset_margin(ui) + 4.0 } else { 0.0 }, @@ -128,7 +127,7 @@ impl NetworkContent { .show(ui, |ui| { ui.add_space(1.0); ui.vertical_centered(|ui| { - let max_width = if !Root::is_dual_panel_mode(frame) { + let max_width = if !Root::is_dual_panel_mode(ui) { Root::SIDE_PANEL_WIDTH * 1.3 } else { ui.available_width() @@ -212,7 +211,7 @@ impl NetworkContent { }); } }, |ui, frame| { - if !Root::is_dual_panel_mode(frame) { + if !Root::is_dual_panel_mode(ui) { View::title_button(ui, CARDHOLDER, || { Root::toggle_network_panel(); }); diff --git a/src/gui/views/root.rs b/src/gui/views/root.rs index 8f886e6..b91598c 100644 --- a/src/gui/views/root.rs +++ b/src/gui/views/root.rs @@ -13,7 +13,6 @@ // limitations under the License. use std::sync::atomic::{AtomicBool, Ordering}; - use egui::os::OperatingSystem; use egui::RichText; use lazy_static::lazy_static; @@ -70,11 +69,11 @@ impl ModalContainer for Root { fn modal_ui(&mut self, ui: &mut egui::Ui, - frame: &mut eframe::Frame, + _: &mut eframe::Frame, modal: &Modal, _: &dyn PlatformCallbacks) { match modal.id { - Self::EXIT_MODAL_ID => self.exit_modal_content(ui, frame, modal), + Self::EXIT_MODAL_ID => self.exit_modal_content(ui, modal), _ => {} } } @@ -91,7 +90,7 @@ impl Root { // Draw modal content for current ui container. self.current_modal_ui(ui, frame, cb); - let (is_panel_open, panel_width) = Self::network_panel_state_width(frame); + let (is_panel_open, panel_width) = Self::network_panel_state_width(ui); // Show network content. egui::SidePanel::left("network_panel") .resizable(false) @@ -103,7 +102,8 @@ impl Root { .show_animated_inside(ui, is_panel_open, |ui| { // Set content height as window height. let mut rect = ui.available_rect_before_wrap(); - rect.set_height(frame.info().window_info.size.y); + let window_size = View::window_size(ui); + rect.set_height(window_size.1); ui.allocate_ui_at_rect(rect, |ui| { self.network.ui(ui, frame, cb); }); @@ -118,7 +118,8 @@ impl Root { .show_inside(ui, |ui| { // Set content height as window height. let mut rect = ui.available_rect_before_wrap(); - rect.set_height(frame.info().window_info.size.y); + let window_size = View::window_size(ui); + rect.set_height(window_size.1); ui.allocate_ui_at_rect(rect, |ui| { self.wallets.ui(ui, frame, cb); }); @@ -126,21 +127,20 @@ impl Root { } /// Get [`NetworkContent`] panel state and width. - fn network_panel_state_width(frame: &mut eframe::Frame) -> (bool, f32) { - let dual_panel_mode = Self::is_dual_panel_mode(frame); + fn network_panel_state_width(ui: &mut egui::Ui) -> (bool, f32) { + let dual_panel_mode = Self::is_dual_panel_mode(ui); let is_panel_open = dual_panel_mode || Self::is_network_panel_open(); let panel_width = if dual_panel_mode { Self::SIDE_PANEL_WIDTH + View::get_left_inset() } else { - frame.info().window_info.size.x + View::window_size(ui).0 }; (is_panel_open, panel_width) } /// Check if ui can show [`NetworkContent`] and [`WalletsContent`] at same time. - pub fn is_dual_panel_mode(frame: &mut eframe::Frame) -> bool { - let w = frame.info().window_info.size.x; - let h = frame.info().window_info.size.y; + pub fn is_dual_panel_mode(ui: &mut egui::Ui) -> bool { + let (w, h) = View::window_size(ui); // Screen is wide if width is greater than height or just 20% smaller. let is_wide_screen = w > h || w + (w * 0.2) >= h; // Dual panel mode is available when window is wide and its width is at least 2 times @@ -168,10 +168,11 @@ impl Root { } /// Draw exit confirmation modal content. - fn exit_modal_content(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame, modal: &Modal) { + fn exit_modal_content(&mut self, ui: &mut egui::Ui, modal: &Modal) { if self.show_exit_progress { if !Node::is_running() { - self.exit(frame); + self.exit_allowed = true; + ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close); modal.close(); } ui.add_space(16.0); @@ -199,9 +200,10 @@ impl Root { ui.columns(2, |columns| { columns[0].vertical_centered_justified(|ui| { - View::button(ui, t!("modal_exit.exit"), Colors::WHITE, || { + View::button_ui(ui, t!("modal_exit.exit"), Colors::WHITE, |ui| { if !Node::is_running() { - self.exit(frame); + self.exit_allowed = true; + ui.ctx().send_viewport_cmd(egui::ViewportCommand::Close); modal.close(); } else { Node::stop(true); @@ -221,12 +223,6 @@ impl Root { } } - /// Exit from the application. - fn exit(&mut self, frame: &mut eframe::Frame) { - self.exit_allowed = true; - frame.close(); - } - /// Handle Back key event. pub fn on_back(&mut self) { if Modal::on_back() { diff --git a/src/gui/views/title_panel.rs b/src/gui/views/title_panel.rs index db52a86..43fdccf 100644 --- a/src/gui/views/title_panel.rs +++ b/src/gui/views/title_panel.rs @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use egui::{Color32, Id, lerp, Rgba}; -use egui::style::Margin; +use egui::{Margin, Color32, Id, lerp, Rgba}; use egui_extras::{Size, Strip, StripBuilder}; use crate::gui::Colors; @@ -59,7 +58,7 @@ impl TitlePanel { .resizable(false) .exact_height(Self::DEFAULT_HEIGHT) .frame(egui::Frame { - inner_margin: Self::inner_margin(ui, frame), + inner_margin: Self::inner_margin(ui), fill: Colors::YELLOW, ..Default::default() }) @@ -132,10 +131,10 @@ impl TitlePanel { } /// Calculate inner margin based on display insets (cutouts). - fn inner_margin(ui: &mut egui::Ui, frame: &mut eframe::Frame) -> Margin { + fn inner_margin(ui: &mut egui::Ui) -> Margin { Margin { left: View::far_left_inset_margin(ui), - right: View::far_right_inset_margin(ui, frame), + right: View::far_right_inset_margin(ui), top: View::get_top_inset(), bottom: 0.0, } diff --git a/src/gui/views/views.rs b/src/gui/views/views.rs index e52962e..01a8894 100644 --- a/src/gui/views/views.rs +++ b/src/gui/views/views.rs @@ -12,13 +12,17 @@ // See the License for the specific language governing permissions and // limitations under the License. +use std::ops::Add; use std::sync::atomic::{AtomicI32, Ordering}; +use std::sync::{Arc, RwLock}; +use lazy_static::lazy_static; -use egui::{Align, Button, CursorIcon, Layout, PointerState, Rect, Response, RichText, Sense, Spinner, TextStyle, Vec2, Widget}; +use egui::{Align, Button, CursorIcon, Layout, PointerState, Rect, Response, RichText, Sense, Spinner, TextBuffer, TextStyle, Widget}; use egui::epaint::{CircleShape, Color32, FontId, RectShape, Rounding, Stroke}; use egui::epaint::text::TextWrapping; +use egui::os::OperatingSystem; use egui::text::{LayoutJob, TextFormat}; -use lazy_static::lazy_static; +use egui::text_edit::TextEditState; use crate::gui::Colors; use crate::gui::icons::{CHECK_SQUARE, CLIPBOARD_TEXT, COPY, EYE, EYE_SLASH, SQUARE}; @@ -54,6 +58,21 @@ impl View { }); } + /// Get width and height of app window. + pub fn window_size(ui: &mut egui::Ui) -> (f32, f32) { + ui.ctx().input(|i| { + return match i.viewport().inner_rect { + None => { + let size = i.viewport().monitor_size.unwrap(); + (size.x, size.y) + } + Some(rect) => { + (rect.width(), rect.height()) + } + }; + }) + } + /// Callback on Enter key press event. pub fn on_enter_key(ui: &mut egui::Ui, cb: impl FnOnce()) { if ui.ctx().input(|i| i.key_pressed(egui::Key::Enter)) { @@ -71,9 +90,10 @@ impl View { } /// Calculate margin for far left view based on display insets (cutouts). - pub fn far_right_inset_margin(ui: &mut egui::Ui, frame: &mut eframe::Frame) -> f32 { + pub fn far_right_inset_margin(ui: &mut egui::Ui) -> f32 { let container_width = ui.available_rect_before_wrap().max.x as i32; - let display_width = frame.info().window_info.size.x as i32; + let window_size = Self::window_size(ui); + let display_width = window_size.0 as i32; // Means end of the screen. if container_width == display_width { Self::get_right_inset() @@ -198,6 +218,19 @@ impl View { } } + /// Draw [`Button`] with specified background fill color. + pub fn button_ui(ui: &mut egui::Ui, text: String, fill: Color32, action: impl FnOnce(&mut egui::Ui)) { + let button_text = Self::ellipsize(text.to_uppercase(), 17.0, Colors::TEXT_BUTTON); + let br = Button::new(button_text) + .stroke(Self::DEFAULT_STROKE) + .fill(fill) + .ui(ui) + .on_hover_cursor(CursorIcon::PointingHand); + if Self::touched(ui, br) { + (action)(ui); + } + } + /// Draw list item [`Button`] with provided rounding. pub fn item_button(ui: &mut egui::Ui, rounding: Rounding, @@ -336,15 +369,17 @@ impl View { // Setup text edit size. let mut edit_rect = ui.available_rect_before_wrap(); edit_rect.set_height(Self::TEXT_EDIT_HEIGHT); + // Show text edit. let text_edit_resp = egui::TextEdit::singleline(value) .id(options.id) - .margin(Vec2::new(2.0, 0.0)) + .margin(egui::Vec2::new(2.0, 0.0)) .font(TextStyle::Heading) .min_size(edit_rect.size()) .horizontal_align(if options.h_center { Align::Center } else { Align::Min }) .vertical_align(Align::Center) .password(show_pass) + .cursor_at_end(true) .ui(ui); // Show keyboard on click. if text_edit_resp.clicked() { @@ -355,6 +390,42 @@ impl View { text_edit_resp.request_focus(); cb.show_keyboard(); } + // Apply text from input on Android as temporary fix for egui. + let os = OperatingSystem::from_target_os(); + if os == OperatingSystem::Android && text_edit_resp.has_focus() { + let mut w_input = LAST_SOFT_KEYBOARD_INPUT.write().unwrap(); + + if !w_input.is_empty() { + let mut state = TextEditState::load(ui.ctx(), options.id).unwrap(); + match state.cursor.char_range() { + None => {} + Some(range) => { + let mut r = range.clone(); + + let mut index = r.primary.index; + println!("insert_str {} {}", index, w_input.as_str()); + + value.insert_text(w_input.as_str(), index); + index = index + 1; + + println!("12345 {} {}", value, r.primary.index); + + if index == 0 { + r.primary.index = value.len(); + r.secondary.index = r.primary.index; + } else { + r.primary.index = index; + r.secondary.index = r.primary.index; + } + state.cursor.set_char_range(Some(r)); + TextEditState::store(state, ui.ctx(), options.id); + } + } + } + + *w_input = "".to_string(); + ui.ctx().request_repaint(); + } }); }); } @@ -571,4 +642,33 @@ pub extern "C" fn Java_mw_gri_android_MainActivity_onDisplayInsets( RIGHT_DISPLAY_INSET.store(array[1], Ordering::Relaxed); BOTTOM_DISPLAY_INSET.store(array[2], Ordering::Relaxed); LEFT_DISPLAY_INSET.store(array[3], Ordering::Relaxed); +} + +lazy_static! { + static ref LAST_SOFT_KEYBOARD_INPUT: Arc> = Arc::new(RwLock::new("".to_string())); +} + +#[allow(dead_code)] +#[cfg(target_os = "android")] +#[allow(non_snake_case)] +#[no_mangle] +/// Callback from Java code with last entered character from soft keyboard. +pub extern "C" fn Java_mw_gri_android_MainActivity_onInput( + _env: jni::JNIEnv, + _class: jni::objects::JObject, + char: jni::sys::jstring +) { + use jni::objects::{JString}; + + unsafe { + let j_obj = JString::from_raw(char); + let j_str = _env.get_string_unchecked(j_obj.as_ref()).unwrap(); + match j_str.to_str() { + Ok(str) => { + let mut w_input = LAST_SOFT_KEYBOARD_INPUT.write().unwrap(); + *w_input = w_input.clone().add(str); + } + Err(_) => {} + } + } } \ No newline at end of file diff --git a/src/gui/views/wallets/content.rs b/src/gui/views/wallets/content.rs index 6c55329..2024329 100644 --- a/src/gui/views/wallets/content.rs +++ b/src/gui/views/wallets/content.rs @@ -98,7 +98,7 @@ impl WalletsContent { let show_wallet = self.wallets.is_selected_open(); // Setup panels parameters. - let dual_panel = is_dual_panel_mode(ui, frame); + let dual_panel = is_dual_panel_mode(ui); let open_wallet_panel = dual_panel || show_wallet || create_wallet || empty_list; let wallet_panel_width = self.wallet_panel_width(ui, empty_list, dual_panel, show_wallet); let content_width = ui.available_width(); @@ -131,10 +131,10 @@ impl WalletsContent { if create_wallet || !show_wallet { // Show wallet creation content. self.creation_content.ui(ui, frame, cb, |wallet| { - // Reset wallet content. - self.wallet_content = WalletContent::default(); // Add created wallet to list. self.wallets.add(wallet); + // Reset wallet content. + self.wallet_content = WalletContent::default(); }); } else { let selected_id = self.wallets.selected_id.clone(); @@ -180,7 +180,7 @@ impl WalletsContent { right: if list_hidden { 0.0 } else { - View::far_right_inset_margin(ui, frame) + 4.0 + View::far_right_inset_margin(ui) + 4.0 }, top: 4.0, bottom: View::get_bottom_inset() + 4.0, @@ -274,7 +274,7 @@ impl WalletsContent { self.show_wallets_at_dual_panel = !show_list; AppConfig::toggle_show_wallets_at_dual_panel(); }); - } else if !Root::is_dual_panel_mode(frame) { + } else if !Root::is_dual_panel_mode(ui) { View::title_button(ui, GLOBE, || { Root::toggle_network_panel(); }); @@ -605,8 +605,8 @@ impl WalletsContent { } /// Check if it's possible to show [`WalletsContent`] and [`WalletContent`] panels at same time. -fn is_dual_panel_mode(ui: &mut egui::Ui, frame: &mut eframe::Frame) -> bool { - let dual_panel_root = Root::is_dual_panel_mode(frame); +fn is_dual_panel_mode(ui: &mut egui::Ui) -> bool { + let dual_panel_root = Root::is_dual_panel_mode(ui); let max_width = ui.available_width(); dual_panel_root && max_width >= (Root::SIDE_PANEL_WIDTH * 2.0) + View::get_right_inset() } \ No newline at end of file diff --git a/src/gui/views/wallets/creation/creation.rs b/src/gui/views/wallets/creation/creation.rs index a90f4b4..9795a74 100644 --- a/src/gui/views/wallets/creation/creation.rs +++ b/src/gui/views/wallets/creation/creation.rs @@ -17,7 +17,7 @@ use egui_extras::{RetainedImage, Size, StripBuilder}; use crate::built_info; use crate::gui::Colors; -use crate::gui::icons::{CHECK, EYE, EYE_SLASH, FOLDER_PLUS, SHARE_FAT}; +use crate::gui::icons::{CHECK, CLIPBOARD_TEXT, COPY, EYE, EYE_SLASH, FOLDER_PLUS, SHARE_FAT}; use crate::gui::platform::PlatformCallbacks; use crate::gui::views::{Modal, Root, View}; use crate::gui::views::types::{ModalPosition, TextEditOptions}; @@ -86,7 +86,7 @@ impl WalletCreation { ui.vertical_centered(|ui| { ui.vertical_centered(|ui| { View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 2.0, |ui| { - self.step_control_ui(ui, on_create); + self.step_control_ui(ui, on_create, cb); }); }); @@ -130,17 +130,12 @@ impl WalletCreation { }); } - /// Reset wallet creation to default values. - fn reset(&mut self) { - self.step = None; - self.name_edit = String::from(""); - self.pass_edit = String::from(""); - self.mnemonic_setup.reset(); - } - /// Draw [`Step`] description and confirmation control. - fn step_control_ui(&mut self, ui: &mut egui::Ui, on_create: impl FnOnce(Wallet)) { - if let Some(step) = &self.step { + fn step_control_ui(&mut self, + ui: &mut egui::Ui, + on_create: impl FnOnce(Wallet), + cb: &dyn PlatformCallbacks) { + if let Some(step) = self.step.clone() { // Setup step description text and availability. let (step_text, mut step_available) = match step { Step::EnterMnemonic => { @@ -179,27 +174,121 @@ impl WalletCreation { .color(Colors::RED)); ui.add_space(2.0); } - - // Show next step button if there are no empty words. - if step_available { - // Setup button text. - let (next_text, color) = if step == &Step::SetupConnection { - (format!("{} {}", CHECK, t!("complete")), Colors::GOLD) + if step == Step::EnterMnemonic { + ui.add_space(4.0); + if !step_available { + self.copy_or_paste_button_ui(ui, cb); } else { - let text = format!("{} {}", SHARE_FAT, t!("continue")); - (text, Colors::WHITE) - }; + // Setup spacing between buttons. + ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0); - ui.add_space(4.0); - // Show button. - View::button(ui, next_text.to_uppercase(), color, || { - self.forward(on_create); + ui.columns(2, |columns| { + // Show copy or paste button for mnemonic phrase step. + columns[0].vertical_centered_justified(|ui| { + self.copy_or_paste_button_ui(ui, cb); + }); + + // Show next step button if there are no empty words. + if step_available { + columns[1].vertical_centered_justified(|ui| { + self.next_step_button_ui(ui, step, on_create); + }); + } + }); + } + } else { + if step_available { + ui.add_space(4.0); + self.next_step_button_ui(ui, step, on_create); + } + } + ui.add_space(4.0); + } + } + + /// Draw copy or paste button at [`Step::EnterMnemonic`]. + fn copy_or_paste_button_ui(&mut self, ui: &mut egui::Ui, cb: &dyn PlatformCallbacks) { + match self.mnemonic_setup.mnemonic.mode { + PhraseMode::Generate => { + // Show copy button. + let c_t = format!("{} {}", COPY, t!("copy").to_uppercase()); + View::button(ui, c_t.to_uppercase(), Colors::WHITE, || { + cb.copy_string_to_buffer(self.mnemonic_setup.mnemonic.get_phrase()); + }); + } + PhraseMode::Import => { + // Show paste button. + let p_t = format!("{} {}", CLIPBOARD_TEXT, t!("paste").to_uppercase()); + View::button(ui, p_t, Colors::WHITE, || { + self.mnemonic_setup.mnemonic.import_text(cb.get_string_from_buffer()); }); - ui.add_space(4.0); } } } + /// Draw button to go to next [`Step`]. + fn next_step_button_ui(&mut self, + ui: &mut egui::Ui, + step: Step, + on_create: impl FnOnce(Wallet)) { + // Setup button text. + let (next_text, color) = if step == Step::SetupConnection { + (format!("{} {}", CHECK, t!("complete")), Colors::GOLD) + } else { + let text = format!("{} {}", SHARE_FAT, t!("continue")); + (text, Colors::WHITE) + }; + + + // Show next step button. + View::button(ui, next_text.to_uppercase(), color, || { + self.step = if let Some(step) = &self.step { + match step { + Step::EnterMnemonic => { + if self.mnemonic_setup.mnemonic.mode == PhraseMode::Generate { + Some(Step::ConfirmMnemonic) + } else { + // Check if entered phrase was valid. + if self.mnemonic_setup.valid_phrase { + Some(Step::SetupConnection) + } else { + Some(Step::EnterMnemonic) + } + } + } + Step::ConfirmMnemonic => { + // Check external connections availability on connection setup. + ExternalConnection::start_ext_conn_availability_check(); + Some(Step::SetupConnection) + }, + Step::SetupConnection => { + // Create wallet at last step. + let name = self.name_edit.clone(); + let pass = self.pass_edit.clone(); + let phrase = self.mnemonic_setup.mnemonic.get_phrase(); + let conn_method = &self.network_setup.method; + let mut wallet = Wallet::create(name, + pass.clone(), + phrase, + conn_method).unwrap(); + // Open created wallet. + wallet.open(pass).unwrap(); + // Pass created wallet to callback. + (on_create)(wallet); + // Reset input data. + self.step = None; + self.name_edit = String::from(""); + self.pass_edit = String::from(""); + self.mnemonic_setup.reset(); + None + } + } + } else { + Some(Step::EnterMnemonic) + }; + }); + } + /// Draw wallet creation [`Step`] content. fn step_content_ui(&mut self, ui: &mut egui::Ui, @@ -256,7 +345,12 @@ impl WalletCreation { None => {} Some(step) => { match step { - Step::EnterMnemonic => self.reset(), + Step::EnterMnemonic => { + self.step = None; + self.name_edit = String::from(""); + self.pass_edit = String::from(""); + self.mnemonic_setup.reset(); + }, Step::ConfirmMnemonic => self.step = Some(Step::EnterMnemonic), Step::SetupConnection => self.step = Some(Step::EnterMnemonic) } @@ -264,49 +358,6 @@ impl WalletCreation { } } - /// Go to the next wallet creation [`Step`]. - fn forward(&mut self, on_create: impl FnOnce(Wallet)) { - self.step = if let Some(step) = &self.step { - match step { - Step::EnterMnemonic => { - if self.mnemonic_setup.mnemonic.mode == PhraseMode::Generate { - Some(Step::ConfirmMnemonic) - } else { - // Check if entered phrase was valid. - if self.mnemonic_setup.valid_phrase { - Some(Step::SetupConnection) - } else { - Some(Step::EnterMnemonic) - } - } - } - Step::ConfirmMnemonic => { - // Check external connections availability on connection setup. - ExternalConnection::start_ext_conn_availability_check(); - Some(Step::SetupConnection) - }, - Step::SetupConnection => { - // Create wallet at last step. - let name = self.name_edit.clone(); - let pass = self.pass_edit.clone(); - let phrase = self.mnemonic_setup.mnemonic.get_phrase(); - let conn_method = &self.network_setup.method; - let mut wallet - = Wallet::create(name, pass.clone(), phrase, conn_method).unwrap(); - // Open created wallet. - wallet.open(pass).unwrap(); - // Pass created wallet to callback. - (on_create)(wallet); - // Reset input data. - self.reset(); - None - } - } - } else { - Some(Step::EnterMnemonic) - }; - } - /// Start wallet creation from showing [`Modal`] to enter name and password. pub fn show_name_pass_modal(&mut self, cb: &dyn PlatformCallbacks) { // Reset modal values. diff --git a/src/gui/views/wallets/creation/mnemonic.rs b/src/gui/views/wallets/creation/mnemonic.rs index 689c316..d532398 100644 --- a/src/gui/views/wallets/creation/mnemonic.rs +++ b/src/gui/views/wallets/creation/mnemonic.rs @@ -167,13 +167,13 @@ impl MnemonicSetup { let words = match self.mnemonic.mode { PhraseMode::Generate => { if edit_words { - self.mnemonic.confirm_words.clone() + &self.mnemonic.confirm_words } else { - self.mnemonic.words.clone() + &self.mnemonic.words } } - PhraseMode::Import => self.mnemonic.words.clone() - }; + PhraseMode::Import => &self.mnemonic.words + }.clone(); let mut word_number = 0; let cols = list_columns_count(ui); diff --git a/src/gui/views/wallets/creation/types.rs b/src/gui/views/wallets/creation/types.rs index 58f6dfa..4a48e23 100644 --- a/src/gui/views/wallets/creation/types.rs +++ b/src/gui/views/wallets/creation/types.rs @@ -13,7 +13,7 @@ // limitations under the License. /// Wallet creation step. -#[derive(PartialEq)] +#[derive(PartialEq, Clone)] pub enum Step { /// Mnemonic phrase input. EnterMnemonic, diff --git a/src/gui/views/wallets/setup/recovery.rs b/src/gui/views/wallets/setup/recovery.rs index ddcafeb..b849f71 100644 --- a/src/gui/views/wallets/setup/recovery.rs +++ b/src/gui/views/wallets/setup/recovery.rs @@ -185,22 +185,20 @@ impl RecoverySetup { .size(17.0) .color(Colors::GRAY)); ui.add_space(8.0); - }); - // Draw current wallet password text edit. - let pass_edit_id = Id::from(modal.id).with(wallet.get_config().id); - let pass_edit_opts = TextEditOptions::new(pass_edit_id).password(); - View::text_edit(ui, cb, &mut self.pass_edit, pass_edit_opts); + // Draw current wallet password text edit. + let pass_edit_id = Id::from(modal.id).with(wallet.get_config().id); + let pass_edit_opts = TextEditOptions::new(pass_edit_id).password(); + View::text_edit(ui, cb, &mut self.pass_edit, pass_edit_opts); - // Show information when password is empty. - ui.vertical_centered(|ui| { + // Show information when password is empty or wrong. if self.pass_edit.is_empty() { - ui.add_space(10.0); + ui.add_space(12.0); ui.label(RichText::new(t!("wallets.pass_empty")) .size(17.0) .color(Colors::INACTIVE_TEXT)); } else if self.wrong_pass { - ui.add_space(10.0); + ui.add_space(12.0); ui.label(RichText::new(t!("wallets.wrong_pass")) .size(17.0) .color(Colors::RED)); diff --git a/src/gui/views/wallets/wallet/content.rs b/src/gui/views/wallets/wallet/content.rs index 16664a1..24bdb9a 100644 --- a/src/gui/views/wallets/wallet/content.rs +++ b/src/gui/views/wallets/wallet/content.rs @@ -375,7 +375,7 @@ impl WalletContent { } /// Draw content when wallet is syncing and not ready to use, returns `true` at this case. - pub fn sync_ui(ui: &mut egui::Ui, frame: &mut eframe::Frame, wallet: &Wallet) -> bool { + pub fn sync_ui(ui: &mut egui::Ui, wallet: &Wallet) -> bool { if wallet.is_repairing() && !wallet.sync_error() { Self::sync_progress_ui(ui, wallet); return true; @@ -384,7 +384,7 @@ impl WalletContent { return true; } else if wallet.get_current_ext_conn_id().is_none() { if !Node::is_running() || Node::is_stopping() { - let dual_panel_root = Root::is_dual_panel_mode(frame); + let dual_panel_root = Root::is_dual_panel_mode(ui); View::center_content(ui, 108.0, |ui| { let text = t!("wallets.enable_node", "settings" => GEAR_FINE); ui.label(RichText::new(text).size(16.0).color(Colors::INACTIVE_TEXT)); diff --git a/src/gui/views/wallets/wallet/info.rs b/src/gui/views/wallets/wallet/info.rs index ba2e793..0b40c06 100644 --- a/src/gui/views/wallets/wallet/info.rs +++ b/src/gui/views/wallets/wallet/info.rs @@ -37,10 +37,10 @@ impl WalletTab for WalletInfo { fn ui(&mut self, ui: &mut egui::Ui, - frame: &mut eframe::Frame, + _: &mut eframe::Frame, wallet: &mut Wallet, _: &dyn PlatformCallbacks) { - if WalletContent::sync_ui(ui, frame, wallet) { + if WalletContent::sync_ui(ui, wallet) { return; } diff --git a/src/gui/views/wallets/wallet/receive.rs b/src/gui/views/wallets/wallet/receive.rs index 9364e7a..48dd3ed 100644 --- a/src/gui/views/wallets/wallet/receive.rs +++ b/src/gui/views/wallets/wallet/receive.rs @@ -12,35 +12,58 @@ // See the License for the specific language governing permissions and // limitations under the License. -use egui::{Id, Margin, RichText, ScrollArea, Widget}; +use egui::{Id, Margin, RichText, ScrollArea}; +use egui::scroll_area::ScrollBarVisibility; +use grin_core::core::{amount_from_hr_string, amount_to_hr_string}; use crate::gui::Colors; -use crate::gui::icons::{ARCHIVE_BOX, BROOM, CLIPBOARD_TEXT, COPY, HAND_COINS}; +use crate::gui::icons::{BROOM, CLIPBOARD_TEXT, COPY, HAND_COINS, RECEIPT}; use crate::gui::platform::PlatformCallbacks; -use crate::gui::views::{Root, View}; -use crate::gui::views::wallets::wallet::types::{WalletTab, WalletTabType}; +use crate::gui::views::{Modal, Root, View}; +use crate::gui::views::types::{ModalPosition, TextEditOptions}; +use crate::gui::views::wallets::wallet::types::{SLATEPACK_MESSAGE_HINT, WalletTab, WalletTabType}; use crate::gui::views::wallets::wallet::WalletContent; use crate::wallet::Wallet; /// Receiving tab content. pub struct WalletReceive { - /// Slatepack text from sender to create response. + /// Flag to check if there is invoice transaction type. + is_invoice: bool, + + /// Slatepack message from sender to create response message. message_edit: String, - /// Generated Slatepack response. + /// Generated Slatepack response message for sender. response_edit: String, - /// Flag to check if there is an error happened on receive. - receive_error: bool, - /// Flag to check if response was copied to the clipboard. - response_copied: bool, + /// Flag to check if there is an error happened on response creation. + response_error: bool, + + /// Amount to receive for invoice transaction type. + amount_edit: String, + /// Generated Slatepack message for invoice transaction. + request_edit: String, + /// Flag to check if there is an error happened on invoice creation. + request_error: bool, + /// Slatepack message from sender to finalize transaction. + finalization_edit: String, + /// Flag to check if there is an error happened on transaction finalization. + finalization_error: bool, } +/// Identifier for invoice amount [`Modal`]. +const INVOICE_AMOUNT_MODAL: &'static str = "invoice_amount_modal"; + impl Default for WalletReceive { fn default() -> Self { Self { + is_invoice: false, message_edit: "".to_string(), response_edit: "".to_string(), - receive_error: false, - response_copied: false, + response_error: false, + amount_edit: "".to_string(), + request_edit: "".to_string(), + request_error: false, + finalization_edit: "".to_string(), + finalization_error: false, } } } @@ -52,13 +75,16 @@ impl WalletTab for WalletReceive { fn ui(&mut self, ui: &mut egui::Ui, - frame: &mut eframe::Frame, + _: &mut eframe::Frame, wallet: &mut Wallet, cb: &dyn PlatformCallbacks) { - if WalletContent::sync_ui(ui, frame, wallet) { + if WalletContent::sync_ui(ui, wallet) { return; } + // Show modal content for this ui container. + self.modal_content_ui(ui, wallet, cb); + // Show receiving content panel. egui::CentralPanel::default() .frame(egui::Frame { @@ -73,18 +99,21 @@ impl WalletTab for WalletReceive { ..Default::default() }) .show_inside(ui, |ui| { - ui.vertical_centered(|ui| { - View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| { - self.receive_ui(ui, wallet, cb); + ScrollArea::vertical() + .scroll_bar_visibility(ScrollBarVisibility::AlwaysVisible) + .id_source(Id::from("wallet_receive").with(wallet.get_config().id)) + .auto_shrink([false; 2]) + .show(ui, |ui| { + ui.vertical_centered(|ui| { + View::max_width_ui(ui, Root::SIDE_PANEL_WIDTH * 1.3, |ui| { + self.receive_ui(ui, wallet, cb); + }); + }); }); - }); }); } } -/// Hint for Slatepack Message input. -const RECEIVE_SLATEPACK_HINT: &'static str = "BEGINSLATEPACK.\n...\n...\n...\nENDSLATEPACK."; - impl WalletReceive { /// Draw receiving content. pub fn receive_ui(&mut self, @@ -95,18 +124,91 @@ impl WalletReceive { View::sub_title(ui, format!("{} {}", HAND_COINS, t!("wallets.manually"))); View::horizontal_line(ui, Colors::ITEM_STROKE); ui.add_space(3.0); + // Show manual receiving content. + self.manual_ui(ui, wallet, cb); + } - // Setup manual sending description. - let response_empty = self.response_edit.is_empty(); - let desc_text = if response_empty { - t!("wallets.receive_paste_slatepack") + /// Draw [`Modal`] content for this ui container. + fn modal_content_ui(&mut self, + ui: &mut egui::Ui, + wallet: &mut Wallet, + cb: &dyn PlatformCallbacks) { + match Modal::opened() { + None => {} + Some(id) => { + match id { + INVOICE_AMOUNT_MODAL => { + Modal::ui(ui.ctx(), |ui, modal| { + self.invoice_amount_modal(ui, wallet, modal, cb); + }); + } + _ => {} + } + } + } + } + + /// Draw manual receiving content. + fn manual_ui(&mut self, ui: &mut egui::Ui, wallet: &mut Wallet, cb: &dyn PlatformCallbacks) { + ui.add_space(10.0); + ui.columns(2, |columns| { + let mut is_invoice = self.is_invoice; + columns[0].vertical_centered(|ui| { + View::radio_value(ui, &mut is_invoice, false, t!("wallets.receive")); + }); + columns[1].vertical_centered(|ui| { + View::radio_value(ui, &mut is_invoice, true, t!("wallets.invoice")); + }); + if is_invoice != self.is_invoice { + self.is_invoice = is_invoice; + // Reset fields to default values on mode change. + if is_invoice { + self.amount_edit = "".to_string(); + self.request_edit = "".to_string(); + self.request_error = false; + self.finalization_edit = "".to_string(); + self.finalization_error = false; + } else { + self.message_edit = "".to_string(); + self.response_edit = "".to_string(); + self.response_error = false; + } + } + }); + ui.add_space(10.0); + + if self.is_invoice { + // Show invoice creation content. + self.manual_invoice_ui(ui, wallet, cb); } else { - t!("wallets.receive_send_slatepack") - }; - ui.label(RichText::new(desc_text).size(16.0).color(Colors::INACTIVE_TEXT)); - ui.add_space(3.0); + // Show manual transaction receiving content. + self.manual_receive_ui(ui, wallet, cb); + } + } - // Show Slatepack text input. + /// Draw manual receiving content. + fn manual_receive_ui(&mut self, + ui: &mut egui::Ui, + wallet: &mut Wallet, + cb: &dyn PlatformCallbacks) { + // Setup description. + let response_empty = self.response_edit.is_empty(); + + if self.response_error { + ui.label(RichText::new(t!("wallets.receive_slatepack_err")) + .size(16.0) + .color(Colors::RED)); + } else { + let desc_text = if response_empty { + t!("wallets.receive_slatepack_desc") + } else { + t!("wallets.receive_send_slatepack") + }; + ui.label(RichText::new(desc_text).size(16.0).color(Colors::INACTIVE_TEXT)); + } + ui.add_space(6.0); + + // Setup Slatepack message text input. let message = if response_empty { &mut self.message_edit } else { @@ -126,12 +228,12 @@ impl WalletReceive { .font(egui::TextStyle::Small) .desired_rows(5) .interactive(response_empty) - .hint_text(RECEIVE_SLATEPACK_HINT) + .hint_text(SLATEPACK_MESSAGE_HINT) .desired_width(f32::INFINITY) .show(ui); // Clear an error when message changed. if &message_before != message { - self.receive_error = false; + self.response_error = false; } ui.add_space(6.0); }); @@ -139,38 +241,27 @@ impl WalletReceive { View::horizontal_line(ui, Colors::ITEM_STROKE); ui.add_space(10.0); - // Show receiving input control buttons. - self.receive_buttons_ui(ui, wallet, cb); - } - - /// Draw manual receiving input control buttons. - fn receive_buttons_ui(&mut self, - ui: &mut egui::Ui, - wallet: &mut Wallet, - cb: &dyn PlatformCallbacks) { + // Draw buttons to clear/copy/paste. let field_is_empty = self.message_edit.is_empty() && self.response_edit.is_empty(); let columns_num = if !field_is_empty { 2 } else { 1 }; - - // Draw buttons to clear/copy/paste. ui.scope(|ui| { // Setup spacing between buttons. ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); ui.columns(columns_num, |columns| { let first_column_content = |ui: &mut egui::Ui| { - if !field_is_empty { + if !self.response_edit.is_empty() && !self.response_error { let clear_text = format!("{} {}", BROOM, t!("clear")); View::button(ui, clear_text, Colors::BUTTON, || { - self.receive_error = false; - self.response_copied = false; + self.response_error = false; self.message_edit.clear(); self.response_edit.clear(); }); - } else if self.message_edit.is_empty() { + } else { let paste_text = format!("{} {}", CLIPBOARD_TEXT, t!("paste")); View::button(ui, paste_text, Colors::BUTTON, || { self.message_edit = cb.get_string_from_buffer(); - self.receive_error = false; + self.response_error = false; }); } }; @@ -178,56 +269,253 @@ impl WalletReceive { columns[0].vertical_centered(first_column_content); } else { columns[0].vertical_centered_justified(first_column_content); - } - if !field_is_empty { columns[1].vertical_centered_justified(|ui| { - if !self.message_edit.is_empty() { - let paste_text = format!("{} {}", CLIPBOARD_TEXT, t!("paste")); - View::button(ui, paste_text, Colors::BUTTON, || { - self.message_edit = cb.get_string_from_buffer(); - self.receive_error = false; + if self.response_error { + let clear_text = format!("{} {}", BROOM, t!("clear")); + View::button(ui, clear_text, Colors::BUTTON, || { + self.response_error = false; + self.message_edit.clear(); + self.response_edit.clear(); }); } else if !self.response_edit.is_empty() { let copy_text = format!("{} {}", COPY, t!("copy")); View::button(ui, copy_text, Colors::BUTTON, || { cb.copy_string_to_buffer(self.response_edit.clone()); - self.response_copied = true; + }); + } else { + View::button(ui, t!("wallets.create_response"), Colors::GOLD, || { + match wallet.receive(self.message_edit.clone()) { + Ok(response) => { + self.response_edit = response.trim().to_string(); + self.message_edit.clear(); + cb.copy_string_to_buffer(response); + }, + Err(e) => { + wallet.sync(); + println!("error {}", e); + self.response_error = true + } + } }); } }); } }); }); + } - // Draw button to create response. - if !self.message_edit.is_empty() && !self.receive_error { - ui.add_space(8.0); - let create_text = format!("{} {}", ARCHIVE_BOX, t!("wallets.create_response")); - View::button(ui, create_text, Colors::GOLD, || { - match wallet.receive(self.message_edit.clone()) { - Ok(response) => { - self.response_edit = response.trim().to_string(); - self.message_edit.clear(); - // Copy response to clipboard. - cb.copy_string_to_buffer(response); - self.response_copied = true; - }, - Err(_) => self.receive_error = true + /// Draw invoice creation content. + fn manual_invoice_ui(&mut self, + ui: &mut egui::Ui, + wallet: &mut Wallet, + cb: &dyn PlatformCallbacks) { + ui.label(RichText::new(t!("wallets.issue_invoice_desc")) + .size(16.0) + .color(Colors::INACTIVE_TEXT)); + ui.add_space(6.0); + + // Draw invoice creation button. + let invoice_text = format!("{} {}", RECEIPT, t!("wallets.issue_invoice")); + View::button(ui, invoice_text, Colors::BUTTON, || { + // Reset modal values. + self.amount_edit = "".to_string(); + self.request_error = false; + // Show invoice amount modal. + Modal::new(INVOICE_AMOUNT_MODAL) + .position(ModalPosition::CenterTop) + .title(t!("wallets.issue_invoice")) + .show(); + cb.show_keyboard(); + }); + + ui.add_space(12.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(6.0); + ui.label(RichText::new(t!("wallets.receive_slatepack_desc")) + .size(16.0) + .color(Colors::INACTIVE_TEXT)); + ui.add_space(6.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(3.0); + + // Draw invoice finalization text input. + ScrollArea::vertical() + .max_height(128.0) + .id_source(Id::from("receive_input").with(wallet.get_config().id)) + .auto_shrink([false; 2]) + .show(ui, |ui| { + ui.add_space(7.0); + let finalization_before = self.finalization_edit.clone(); + egui::TextEdit::multiline(&mut self.finalization_edit) + .font(egui::TextStyle::Small) + .desired_rows(5) + .interactive(true) + .hint_text(SLATEPACK_MESSAGE_HINT) + .desired_width(f32::INFINITY) + .show(ui); + // Clear an error when message changed. + if finalization_before != self.finalization_edit { + self.finalization_error = false; } + ui.add_space(6.0); }); + ui.add_space(2.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(10.0); + + // Draw buttons to clear/paste. + ui.scope(|ui| { + // Setup spacing between buttons. + ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0); + + ui.columns(2, |columns| { + columns[0].vertical_centered_justified(|ui| { + let paste_text = format!("{} {}", CLIPBOARD_TEXT, t!("paste")); + View::button(ui, paste_text, Colors::BUTTON, || { + self.finalization_edit = cb.get_string_from_buffer(); + self.response_error = false; + }); + }); + columns[1].vertical_centered_justified(|ui| { + View::button(ui, t!("wallets.finalize"), Colors::GOLD, || { + wallet.finalize(); + //TODO: finalize + }); + }); + }); + }); + + if self.finalization_error { ui.add_space(8.0); - } else if self.receive_error { - ui.add_space(8.0); - ui.label(RichText::new(t!("wallets.receive_slatepack_err")) + ui.label(RichText::new(t!("wallets.finalize_slatepack_err")) .size(16.0) .color(Colors::RED)); + } + ui.add_space(8.0); + } + + /// Draw invoice amount [`Modal`] content. + fn invoice_amount_modal(&mut self, + ui: &mut egui::Ui, + wallet: &mut Wallet, + modal: &Modal, + cb: &dyn PlatformCallbacks) { + ui.add_space(6.0); + if self.request_edit.is_empty() { + ui.vertical_centered(|ui| { + ui.label(RichText::new(t!("wallets.enter_amount")) + .size(17.0) + .color(Colors::GRAY)); + }); ui.add_space(8.0); - } else if self.response_copied { - ui.add_space(8.0); - ui.label(RichText::new(t!("wallets.response_copied")) - .size(16.0) - .color(Colors::GREEN)); - ui.add_space(8.0); + + // Draw invoice amount text edit. + let amount_edit_id = Id::from(modal.id).with(wallet.get_config().id); + let amount_edit_opts = TextEditOptions::new(amount_edit_id).h_center(); + let mut amount_edit = self.amount_edit.clone(); + View::text_edit(ui, cb, &mut amount_edit, amount_edit_opts); + if amount_edit != self.amount_edit { + self.request_error = false; + match amount_from_hr_string(amount_edit.as_str()) { + Ok(_) => { + self.amount_edit = amount_edit; + } + Err(_) => {} + } + } + + // Show invoice creation error. + if self.request_error { + ui.add_space(12.0); + ui.label(RichText::new(t!("wallets.invoice_slatepack_err")) + .size(17.0) + .color(Colors::RED)); + } + + // Show modal buttons. + ui.add_space(12.0); + ui.scope(|ui| { + // Setup spacing between buttons. + ui.spacing_mut().item_spacing = egui::Vec2::new(6.0, 0.0); + + ui.columns(2, |columns| { + columns[0].vertical_centered_justified(|ui| { + View::button(ui, t!("modal.cancel"), Colors::WHITE, || { + self.amount_edit = "".to_string(); + self.request_error = false; + modal.close(); + }); + }); + columns[1].vertical_centered_justified(|ui| { + View::button(ui, t!("continue"), Colors::WHITE, || { + match amount_from_hr_string(self.amount_edit.as_str()) { + Ok(amount) => { + match wallet.issue_invoice(amount) { + Ok(message) => { + self.request_edit = message; + cb.hide_keyboard(); + } + Err(_) => { + self.request_error = true; + } + } + } + Err(_) => { + self.request_error = true; + } + } + }); + }); + }); + }); + ui.add_space(6.0); + } else { + ui.vertical_centered(|ui| { + let amount = amount_from_hr_string(self.amount_edit.as_str()).unwrap(); + let amount_format = amount_to_hr_string(amount, true); + let desc_text = t!("wallets.invoice_desc","amount" => amount_format); + ui.label(RichText::new(desc_text).size(16.0).color(Colors::INACTIVE_TEXT)); + ui.add_space(6.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(3.0); + + // Draw invoice request text. + ScrollArea::vertical() + .max_height(128.0) + .id_source(Id::from("receive_input").with(wallet.get_config().id)) + .auto_shrink([false; 2]) + .show(ui, |ui| { + ui.add_space(7.0); + egui::TextEdit::multiline(&mut self.request_edit) + .font(egui::TextStyle::Small) + .desired_rows(5) + .interactive(false) + .hint_text(SLATEPACK_MESSAGE_HINT) + .desired_width(f32::INFINITY) + .show(ui); + ui.add_space(6.0); + }); + ui.add_space(2.0); + View::horizontal_line(ui, Colors::ITEM_STROKE); + ui.add_space(10.0); + + // Draw copy button. + let copy_text = format!("{} {}", COPY, t!("copy")); + View::button(ui, copy_text, Colors::BUTTON, || { + cb.copy_string_to_buffer(self.request_edit.clone()); + }); + }); + + // Draw button to close modal. + ui.add_space(12.0); + ui.vertical_centered_justified(|ui| { + View::button(ui, t!("close"), Colors::WHITE, || { + self.amount_edit = "".to_string(); + self.request_edit = "".to_string(); + modal.close(); + }); + }); + ui.add_space(6.0); } } } \ No newline at end of file diff --git a/src/gui/views/wallets/wallet/send.rs b/src/gui/views/wallets/wallet/send.rs index b3b260a..4c47bae 100644 --- a/src/gui/views/wallets/wallet/send.rs +++ b/src/gui/views/wallets/wallet/send.rs @@ -31,10 +31,10 @@ impl WalletTab for WalletSend { fn ui(&mut self, ui: &mut egui::Ui, - frame: &mut eframe::Frame, + _: &mut eframe::Frame, wallet: &mut Wallet, _: &dyn PlatformCallbacks) { - if WalletContent::sync_ui(ui, frame, wallet) { + if WalletContent::sync_ui(ui, wallet) { return; } diff --git a/src/lib.rs b/src/lib.rs index 2173f96..7260520 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,7 +16,7 @@ extern crate rust_i18n; use eframe::wgpu; -use egui::{Context, Stroke}; +use egui::{Context, Stroke, vec2}; #[cfg(target_os = "android")] use winit::platform::android::activity::AndroidApp; @@ -61,16 +61,21 @@ fn android_main(app: AndroidApp) { use gui::PlatformApp; let platform = Android::new(app.clone()); - use winit::platform::android::EventLoopBuilderExtAndroid; - let mut options = eframe::NativeOptions::default(); + + let width = app.config().screen_width_dp().unwrap() as f32; + let height = app.config().screen_height_dp().unwrap() as f32; + let mut options = eframe::NativeOptions { + viewport: egui::ViewportBuilder::default().with_inner_size(vec2(width, height)), + ..Default::default() + }; // Setup limits that are guaranteed to be compatible with Android devices. options.wgpu_options.device_descriptor = std::sync::Arc::new(|adapter| { let base_limits = wgpu::Limits::downlevel_webgl2_defaults(); wgpu::DeviceDescriptor { label: Some("egui wgpu device"), - features: wgpu::Features::default(), - limits: wgpu::Limits { + required_features: wgpu::Features::default(), + required_limits: wgpu::Limits { max_texture_dimension_2d: 8192, ..base_limits }, @@ -102,7 +107,6 @@ pub fn app_creator(app: PlatformApp) -> eframe::AppCreator pub fn start(mut options: eframe::NativeOptions, app_creator: eframe::AppCreator) { options.default_theme = eframe::Theme::Light; options.renderer = eframe::Renderer::Wgpu; - options.initial_window_size = Some(egui::Vec2::new(1200.0, 720.0)); // Setup translations. setup_i18n(); // Start integrated node if needed. @@ -119,7 +123,7 @@ pub fn setup_visuals(ctx: &Context) { // Setup spacing for buttons. style.spacing.button_padding = egui::vec2(12.0, 8.0); // Make scroll-bar thinner. - style.spacing.scroll_bar_width = 4.0; + style.spacing.scroll.bar_width = 4.0; // Disable spacing between items. style.spacing.item_spacing = egui::vec2(0.0, 0.0); // Setup radio button/checkbox size and spacing. diff --git a/src/main.rs b/src/main.rs index f8f996f..06c73db 100644 --- a/src/main.rs +++ b/src/main.rs @@ -31,6 +31,9 @@ fn real_main() { use grim::gui::PlatformApp; let platform = Desktop::default(); - let options = eframe::NativeOptions::default(); + let options = eframe::NativeOptions { + viewport: egui::ViewportBuilder::default().with_inner_size([1200.0, 720.0]), + ..Default::default() + }; grim::start(options, grim::app_creator(PlatformApp::new(platform))); } \ No newline at end of file diff --git a/src/node/config.rs b/src/node/config.rs index 2bb606b..fd5a6e7 100644 --- a/src/node/config.rs +++ b/src/node/config.rs @@ -24,6 +24,7 @@ use grin_core::global::ChainTypes; use grin_p2p::{PeerAddr, Seeding}; use grin_p2p::msg::PeerAddrs; use grin_servers::common::types::ChainValidationMode; +use local_ip_address::list_afinet_netifas; use serde::{Deserialize, Serialize}; use crate::{AppConfig, Settings}; @@ -244,10 +245,11 @@ impl NodeConfig { /// List of available IP addresses. pub fn get_ip_addrs() -> Vec { let mut ip_addrs = Vec::new(); - for net_if in pnet::datalink::interfaces() { - for ip in net_if.ips { + let network_interfaces = list_afinet_netifas(); + if let Ok(network_interfaces) = network_interfaces { + for (_, ip) in network_interfaces.iter() { if ip.is_ipv4() { - ip_addrs.push(ip.ip().to_string()); + ip_addrs.push(ip.to_string()); } } } diff --git a/src/wallet/mnemonic.rs b/src/wallet/mnemonic.rs index 78ab853..537cd8c 100644 --- a/src/wallet/mnemonic.rs +++ b/src/wallet/mnemonic.rs @@ -103,4 +103,22 @@ impl Mnemonic { } words } + + /// Set words from provided text if possible. + pub fn import_text(&mut self, text: String) { + if self.mode != PhraseMode::Import { + return; + } + let words_split = text.trim().split(" "); + let count = words_split.clone().count(); + if PhraseSize::is_correct_count(count) { + if self.size == PhraseSize::type_for_value(count).unwrap() { + let mut words = vec![]; + words_split.enumerate().for_each(|(i, word)| { + words.insert(i, word.to_string()) + }); + self.words = words; + } + } + } } \ No newline at end of file diff --git a/src/wallet/types.rs b/src/wallet/types.rs index a866edd..c263494 100644 --- a/src/wallet/types.rs +++ b/src/wallet/types.rs @@ -62,6 +62,38 @@ impl PhraseSize { PhraseSize::Words24 => 32 } } + + pub fn type_for_value(count: usize) -> Option { + if Self::is_correct_count(count) { + match count { + 12 => { + Some(PhraseSize::Words12) + } + 15 => { + Some(PhraseSize::Words15) + } + 18 => { + Some(PhraseSize::Words18) + } + 21 => { + Some(PhraseSize::Words21) + } + 24 => { + Some(PhraseSize::Words24) + } + _ => { + None + } + } + } else { + None + } + } + + /// Check if correct word count provided. + pub fn is_correct_count(count: usize) -> bool { + count == 12 || count == 15 || count == 18 || count == 21 || count == 24 + } } /// Wallet connection method. diff --git a/src/wallet/wallet.rs b/src/wallet/wallet.rs index 00f3743..2c505a9 100644 --- a/src/wallet/wallet.rs +++ b/src/wallet/wallet.rs @@ -27,7 +27,7 @@ use futures::channel::oneshot; use grin_api::{ApiServer, Router}; use grin_chain::SyncStatus; use grin_core::global; -use grin_keychain::{ExtKeychain, Keychain}; +use grin_keychain::{ExtKeychain, Identifier, Keychain}; use grin_util::Mutex; use grin_util::types::ZeroingString; use grin_wallet_api::Owner; @@ -35,7 +35,7 @@ use grin_wallet_controller::command::parse_slatepack; use grin_wallet_controller::controller; use grin_wallet_controller::controller::ForeignAPIHandlerV2; use grin_wallet_impls::{DefaultLCProvider, DefaultWalletImpl, HTTPNodeClient}; -use grin_wallet_libwallet::{AcctPathMapping, Error, NodeClient, StatusMessage, TxLogEntryType, WalletInst, WalletLCProvider}; +use grin_wallet_libwallet::{Error, InitTxArgs, IssueInvoiceTxArgs, NodeClient, RetrieveTxQueryArgs, Slate, StatusMessage, TxLogEntry, TxLogEntryType, WalletInst, WalletLCProvider}; use grin_wallet_libwallet::api_impl::owner::{cancel_tx, retrieve_summary_info, retrieve_txs}; use crate::node::{Node, NodeConfig}; @@ -205,6 +205,15 @@ impl Wallet { Ok(Arc::new(Mutex::new(wallet))) } + /// Get parent key identifier for current account. + pub fn get_parent_key_id(&self) -> Result { + let instance = self.instance.clone().unwrap(); + let mut w_lock = instance.lock(); + let lc = w_lock.lc_provider()?; + let w_inst = lc.wallet_inst()?; + Ok(w_inst.parent_key_id()) + } + /// Get wallet config. pub fn get_config(&self) -> WalletConfig { self.config.read().unwrap().clone() @@ -238,7 +247,7 @@ impl Wallet { } // Create new wallet instance if sync thread was stopped or instance was not created. - if self.sync_thread.write().unwrap().is_none() || self.instance.is_none() { + if self.sync_thread.read().unwrap().is_none() || self.instance.is_none() { let config = self.get_config(); let new_instance = Self::create_wallet_instance(config.clone())?; self.instance = Some(new_instance); @@ -352,6 +361,9 @@ impl Wallet { let mut api = Owner::new(self.instance.clone().unwrap(), None); controller::owner_single_use(None, None, Some(&mut api), |api, m| { api.create_account_path(m, label)?; + + // Sync wallet data. + self.sync(); Ok(()) }) } @@ -448,7 +460,28 @@ impl Wallet { } } - /// Receive transaction via Slatepack Message. + /// Create Slatepack message from provided slate. + fn create_slatepack_message(&self, slate: Slate) -> Result { + let mut message = "".to_string(); + let mut api = Owner::new(self.instance.clone().unwrap(), None); + controller::owner_single_use(None, None, Some(&mut api), |api, m| { + message = api.create_slatepack_message(m, &slate, Some(0), vec![])?; + Ok(()) + })?; + + // Create a directory to which slatepack files will be output. + let mut slatepack_dir = self.get_config().get_slatepacks_path(); + let slatepack_file_name = format!("{}.{}.slatepack", slate.id, slate.state); + slatepack_dir.push(slatepack_file_name); + + // Write Slatepack response into the file. + let mut output = File::create(slatepack_dir)?; + output.write_all(message.as_bytes())?; + output.sync_all()?; + Ok(message) + } + + /// Receive transaction via Slatepack message, return response to sender. pub fn receive(&self, message: String) -> Result { let mut api = Owner::new(self.instance.clone().unwrap(), None); match parse_slatepack(&mut api, None, None, Some(message.clone())) { @@ -458,21 +491,37 @@ impl Wallet { slate = api.receive_tx(&slate, Some(config.account.as_str()), None)?; Ok(()) })?; - let mut response = "".to_string(); - controller::owner_single_use(None, None, Some(&mut api), |api, m| { - response = api.create_slatepack_message(m, &slate, Some(0), vec![])?; - Ok(()) - })?; + // Create Slatepack message response. + let response = self.create_slatepack_message(slate)?; - // Create a directory to which slatepack files will be output. - let mut slatepack_dir = config.get_slatepacks_path(); - let slatepack_file_name = format!("{}.{}.slatepack", slate.id, slate.state); - slatepack_dir.push(slatepack_file_name); + // Sync wallet info. + self.sync(); + Ok(response) + } + Err(_) => { + Err(Error::GenericError("Parsing error".to_string())) + } + } + } - // Write Slatepack response into the file. - let mut output = File::create(slatepack_dir)?; - output.write_all(response.as_bytes())?; - output.sync_all()?; + /// S transaction via Slatepack message and return response to sender. + pub fn pay(&self, message: String) -> Result { + let mut api = Owner::new(self.instance.clone().unwrap(), None); + match parse_slatepack(&mut api, None, None, Some(message.clone())) { + Ok((mut slate, _)) => { + let config = self.get_config(); + let args = InitTxArgs { + src_acct_name: None, + amount: slate.amount, + minimum_confirmations: config.min_confirmations, + selection_strategy_is_use_all: false, + ..Default::default() + }; + let mut api = Owner::new(self.instance.clone().unwrap(), None); + let slate = api.process_invoice_tx(None, &slate, args)?; + + // Create Slatepack message response. + let response = self.create_slatepack_message(slate)?; // Sync wallet info. self.sync(); @@ -485,6 +534,25 @@ impl Wallet { } } + /// Initialize an invoice transaction. + pub fn issue_invoice(&self, amount: u64) -> Result { + let args = IssueInvoiceTxArgs { + dest_acct_name: None, + amount, + target_slate_version: None, + }; + let mut api = Owner::new(self.instance.clone().unwrap(), None); + let slate = api.issue_invoice_tx(None, args)?; + + // Create Slatepack message response. + let response = self.create_slatepack_message(slate)?; + + // Sync wallet info. + self.sync(); + + Ok(response) + } + pub fn send(&self) { } @@ -513,6 +581,7 @@ impl Wallet { cancelling_r.contains(id) } + /// Finalize transaction from provided Slatepack message. pub fn finalize(&self) { } @@ -571,7 +640,7 @@ impl Wallet { wallet_delete.is_open.store(false, Ordering::Relaxed); wallet_delete.deleted.store(true, Ordering::Relaxed); - // Wake up thread to exit. + // Start sync to exit. wallet_delete.sync(); }); } @@ -786,16 +855,13 @@ fn sync_wallet_data(wallet: &Wallet) { } }); - // Retrieve txs. - match retrieve_txs( - instance.clone(), - None, - &Some(txs_tx), - true, - None, - None, - None - ) { + match retrieve_txs(instance.clone(), + None, + &Some(txs_tx), + true, + None, + None, + None) { Ok(txs) => { // Do not sync data if wallet was closed. if !wallet.is_open() { @@ -807,9 +873,20 @@ fn sync_wallet_data(wallet: &Wallet) { wallet.reset_sync_attempts(); // Setup transactions. - let mut txs = txs.1; + let mut sort_txs = txs.1; // Sort txs by creation date. - txs.sort_by_key(|tx| -tx.creation_ts.timestamp()); + sort_txs.sort_by_key(|tx| -tx.creation_ts.timestamp()); + // Filter txs by current wallet account. + let mut txs = sort_txs.iter().map(|v| v.clone()).filter(|tx| { + match wallet.get_parent_key_id() { + Ok(key) => { + tx.parent_key_id == key + } + Err(_) => { + true + } + } + }).collect::>(); // Update txs statuses. for tx in &txs { if tx.tx_type == TxLogEntryType::TxSentCancelled