From d15997cca0c2dec26fe91888c4aeafaa9447444b Mon Sep 17 00:00:00 2001 From: veeso Date: Tue, 17 Aug 2021 12:38:24 +0200 Subject: [PATCH] Updated dependencies; migrated tui-realm to 0.6.0 --- CHANGELOG.md | 10 + Cargo.lock | 176 ++++++---- Cargo.toml | 11 +- src/lib.rs | 1 + src/ui/activities/auth/bookmarks.rs | 2 +- src/ui/activities/auth/update.rs | 114 +++--- src/ui/activities/auth/view.rs | 174 +++------ src/ui/activities/filetransfer/update.rs | 236 +++++++------ src/ui/activities/filetransfer/view.rs | 429 +++++++---------------- src/ui/activities/setup/update.rs | 212 +++++------ src/ui/activities/setup/view/mod.rs | 146 ++++---- src/ui/activities/setup/view/setup.rs | 89 ++--- src/ui/activities/setup/view/ssh_keys.rs | 56 +-- src/ui/activities/setup/view/theme.rs | 46 +-- src/ui/components/bookmark_list.rs | 83 +++-- src/ui/components/color_picker.rs | 13 +- src/ui/components/file_list.rs | 121 ++++--- src/ui/components/logbox.rs | 59 ++-- src/ui/components/mod.rs | 1 - src/ui/components/msgbox.rs | 268 -------------- src/utils/fmt.rs | 29 -- 21 files changed, 863 insertions(+), 1413 deletions(-) delete mode 100644 src/ui/components/msgbox.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index dcb7c20..8528caf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,7 +22,17 @@ ## 0.6.1 +Released on ?? +- Enhancements: + - Now that tui-rs supports title alignment, UI has been improved +- Dependencies: + - Updated `bitflags` to `1.3.2` + - Updated `bytesize` to `1.1.0` + - Updated `crossterm` to `0.20` + - Updated `open` to `2.0.1` + - Added `tui-realm-stdlib 0.6.0` + - Updated `tui-realm` to `0.6.0` ## 0.6.0 diff --git a/Cargo.lock b/Cargo.lock index 05279d4..1517e69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -94,9 +94,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "block-buffer" @@ -138,9 +138,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytesize" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da" +checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70" [[package]] name = "cassowary" @@ -150,9 +150,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" [[package]] name = "cc" -version = "1.0.68" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" +checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" [[package]] name = "cfg-if" @@ -264,34 +264,34 @@ dependencies = [ [[package]] name = "crossterm" -version = "0.19.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c36c10130df424b2f3552fcc2ddcd9b28a27b1e54b358b45874f88d1ca6888c" +checksum = "c0ebde6a9dd5e331cd6c6f48253254d117642c31653baa475e394657c59c1f7d" dependencies = [ "bitflags", "crossterm_winapi", - "lazy_static", "libc", "mio", "parking_lot 0.11.1", "signal-hook", + "signal-hook-mio", "winapi", ] [[package]] name = "crossterm_winapi" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0da8964ace4d3e4a044fd027919b2237000b24315a37c916f61809f1ff2140b9" +checksum = "3a6966607622438301997d3dac0d2f6e9a90c68bb6bc1785ea98456ab93c0507" dependencies = [ "winapi", ] [[package]] name = "crypto-mac" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" +checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a" dependencies = [ "generic-array", "subtle", @@ -506,9 +506,9 @@ dependencies = [ [[package]] name = "instant" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" +checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" dependencies = [ "cfg-if 1.0.0", ] @@ -521,9 +521,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" [[package]] name = "js-sys" -version = "0.3.51" +version = "0.3.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" +checksum = "ce791b7ca6638aae45be056e068fc756d871eb3b3b10b8efa62d1c9cec616752" dependencies = [ "wasm-bindgen", ] @@ -548,9 +548,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.98" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765" [[package]] name = "libssh2-sys" @@ -630,9 +630,9 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4" [[package]] name = "matches" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "md-5" @@ -675,9 +675,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" +checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" dependencies = [ "lazy_static", "libc", @@ -790,11 +790,11 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" [[package]] name = "open" -version = "1.7.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1711eb4b31ce4ad35b0f316d8dfba4fe5c7ad601c448446d84aae7a896627b20" +checksum = "b46b233de7d83bc167fe43ae2dda3b5b84e80e09cceba581e4decb958a4896bf" dependencies = [ - "which", + "pathdiff", "winapi", ] @@ -884,7 +884,7 @@ dependencies = [ "cfg-if 1.0.0", "instant", "libc", - "redox_syscall 0.2.9", + "redox_syscall 0.2.10", "smallvec", "winapi", ] @@ -895,6 +895,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3cacbb3c4ff353b534a67fb8d7524d00229da4cb1dc8c79f4db96e375ab5b619" +[[package]] +name = "pathdiff" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877630b3de15c0b64cc52f659345724fbf6bdad9bd9566699fc53688f3c34a34" + [[package]] name = "percent-encoding" version = "2.1.0" @@ -927,9 +933,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.27" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" +checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" dependencies = [ "unicode-xid", ] @@ -1032,9 +1038,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ "bitflags", ] @@ -1046,7 +1052,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ "getrandom 0.2.3", - "redox_syscall 0.2.9", + "redox_syscall 0.2.10", ] [[package]] @@ -1209,18 +1215,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.126" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" +checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.126" +version = "1.0.127" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" +checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc" dependencies = [ "proc-macro2", "quote", @@ -1229,9 +1235,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.64" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127" dependencies = [ "itoa", "ryu", @@ -1253,13 +1259,23 @@ dependencies = [ [[package]] name = "signal-hook" -version = "0.1.17" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e31d442c16f047a671b5a71e2161d6e68814012b7f5379d269ebd915fac2729" +checksum = "470c5a6397076fae0094aaf06a08e6ba6f37acb77d3b1b91ea92b4d6c8650c39" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-mio" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29fd5867f1c4f2c5be079aee7a2adf1152ebb04a4bc4d341f504b7dece607ed4" dependencies = [ "libc", "mio", - "signal-hook-registry", + "signal-hook", ] [[package]] @@ -1314,15 +1330,15 @@ dependencies = [ [[package]] name = "subtle" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.73" +version = "1.0.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" +checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" dependencies = [ "proc-macro2", "quote", @@ -1338,7 +1354,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "rand 0.8.4", - "redox_syscall 0.2.9", + "redox_syscall 0.2.10", "remove_dir_all", "winapi", ] @@ -1383,6 +1399,7 @@ dependencies = [ "textwrap", "thiserror", "toml", + "tui-realm-stdlib", "tuirealm", "ureq", "users", @@ -1445,9 +1462,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.2.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" +checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338" dependencies = [ "tinyvec_macros", ] @@ -1469,9 +1486,9 @@ dependencies = [ [[package]] name = "tui" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "861d8f3ad314ede6219bcb2ab844054b1de279ee37a9bc38e3d606f9d3fb2a71" +checksum = "39c8ce4e27049eed97cfa363a5048b09d995e209994634a0efc26a14ab6c0c23" dependencies = [ "bitflags", "cassowary", @@ -1481,15 +1498,24 @@ dependencies = [ ] [[package]] -name = "tuirealm" -version = "0.4.3" +name = "tui-realm-stdlib" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcbd06f2aa6a2424aaa245c10e8767fe3f0fee234ac8c144cb15eaf2ee37ce9" +checksum = "6bff91e1cdc741a7487d8cb20ac038e5ba926a0ec97b0f2ea918ac75640b9da5" +dependencies = [ + "textwrap", + "tuirealm", + "unicode-width", +] + +[[package]] +name = "tuirealm" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634ad8e6a4b80ef032d31356b55964a995da5d05a9cf3a1bd134bae1ba7c197a" dependencies = [ "crossterm", - "textwrap", "tui", - "unicode-width", ] [[package]] @@ -1500,18 +1526,15 @@ checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" [[package]] name = "unicode-bidi" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" -dependencies = [ - "matches", -] +checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085" [[package]] name = "unicode-linebreak" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05a31f45d18a3213b918019f78fe6a73a14ab896807f0aaf5622aa0684749455" +checksum = "3a52dcaab0c48d931f7cc8ef826fa51690a08e1ea55117ef26f89864f532383f" dependencies = [ "regex", ] @@ -1615,9 +1638,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" +checksum = "b608ecc8f4198fe8680e2ed18eccab5f0cd4caaf3d83516fa5fb2e927fda2586" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -1625,9 +1648,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" +checksum = "580aa3a91a63d23aac5b6b267e2d13cb4f363e31dce6c352fca4752ae12e479f" dependencies = [ "bumpalo", "lazy_static", @@ -1640,9 +1663,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" +checksum = "171ebf0ed9e1458810dfcb31f2e766ad6b3a89dbda42d8901f2b268277e5f09c" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1650,9 +1673,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" +checksum = "6c2657dd393f03aa2a659c25c6ae18a13a4048cebd220e147933ea837efc589f" dependencies = [ "proc-macro2", "quote", @@ -1663,15 +1686,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.74" +version = "0.2.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" +checksum = "2e0c4a743a309662d45f4ede961d7afa4ba4131a59a639f29b0069c3798bbcc2" [[package]] name = "web-sys" -version = "0.3.51" +version = "0.3.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" +checksum = "01c70a82d842c9979078c772d4a1344685045f1a5628f677c2b2eab4dd7d2696" dependencies = [ "js-sys", "wasm-bindgen", @@ -1698,11 +1721,12 @@ dependencies = [ [[package]] name = "which" -version = "4.1.0" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55551e42cbdf2ce2bedd2203d0cc08dba002c27510f86dab6d0ce304cba3dfe" +checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9" dependencies = [ "either", + "lazy_static", "libc", ] diff --git a/Cargo.toml b/Cargo.toml index d0390b6..7216e80 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,11 +28,11 @@ path = "src/main.rs" [dependencies] argh = "0.1.5" -bitflags = "1.2.1" -bytesize = "1.0.1" +bitflags = "1.3.2" +bytesize = "1.1.0" chrono = "0.4.19" content_inspector = "0.2.4" -crossterm = "0.19.0" +crossterm = "0.20" dirs = "3.0.1" edit = "0.1.3" ftp4 = { version = "4.0.2", features = [ "secure" ] } @@ -41,7 +41,7 @@ keyring = { version = "0.10.1", optional = true } lazy_static = "1.4.0" log = "0.4.14" magic-crypt = "3.1.7" -open = "1.7.0" +open = "2.0.1" rand = "0.8.4" regex = "1.5.4" rpassword = "5.0.1" @@ -52,7 +52,8 @@ tempfile = "3.1.0" textwrap = "0.14.2" thiserror = "^1.0.0" toml = "0.5.8" -tuirealm = { version = "0.4.3", features = [ "with-components" ] } +tui-realm-stdlib = "0.6.0" +tuirealm = "0.6.0" ureq = { version = "2.1.0", features = [ "json" ] } whoami = "1.1.1" wildmatch = "2.0.0" diff --git a/src/lib.rs b/src/lib.rs index b6e3d0e..48bed11 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -56,6 +56,7 @@ extern crate regex; extern crate ssh2; extern crate tempfile; extern crate textwrap; +extern crate tui_realm_stdlib; extern crate tuirealm; extern crate ureq; #[cfg(target_family = "unix")] diff --git a/src/ui/activities/auth/bookmarks.rs b/src/ui/activities/auth/bookmarks.rs index d4115f1..dcd9946 100644 --- a/src/ui/activities/auth/bookmarks.rs +++ b/src/ui/activities/auth/bookmarks.rs @@ -32,7 +32,7 @@ use crate::system::environment; // Ext use std::path::PathBuf; -use tuirealm::components::{input::InputPropsBuilder, radio::RadioPropsBuilder}; +use tui_realm_stdlib::{input::InputPropsBuilder, radio::RadioPropsBuilder}; use tuirealm::{Payload, PropsBuilder, Value}; impl AuthActivity { diff --git a/src/ui/activities/auth/update.rs b/src/ui/activities/auth/update.rs index 9c6822a..dd2275d 100644 --- a/src/ui/activities/auth/update.rs +++ b/src/ui/activities/auth/update.rs @@ -35,7 +35,7 @@ use super::{ COMPONENT_TEXT_HELP, COMPONENT_TEXT_NEW_VERSION_NOTES, COMPONENT_TEXT_SIZE_ERR, }; use crate::ui::keymap::*; -use tuirealm::components::InputPropsBuilder; +use tui_realm_stdlib::InputPropsBuilder; use tuirealm::{Msg, Payload, PropsBuilder, Update, Value}; // -- update @@ -52,53 +52,53 @@ impl Update for AuthActivity { None => None, // Exit after None Some(msg) => match msg { // Focus ( DOWN ) - (COMPONENT_RADIO_PROTOCOL, &MSG_KEY_DOWN) => { + (COMPONENT_RADIO_PROTOCOL, key) if key == &MSG_KEY_DOWN => { // Give focus to port self.view.active(COMPONENT_INPUT_ADDR); None } - (COMPONENT_INPUT_ADDR, &MSG_KEY_DOWN) => { + (COMPONENT_INPUT_ADDR, key) if key == &MSG_KEY_DOWN => { // Give focus to port self.view.active(COMPONENT_INPUT_PORT); None } - (COMPONENT_INPUT_PORT, &MSG_KEY_DOWN) => { + (COMPONENT_INPUT_PORT, key) if key == &MSG_KEY_DOWN => { // Give focus to port self.view.active(COMPONENT_INPUT_USERNAME); None } - (COMPONENT_INPUT_USERNAME, &MSG_KEY_DOWN) => { + (COMPONENT_INPUT_USERNAME, key) if key == &MSG_KEY_DOWN => { // Give focus to port self.view.active(COMPONENT_INPUT_PASSWORD); None } - (COMPONENT_INPUT_PASSWORD, &MSG_KEY_DOWN) => { + (COMPONENT_INPUT_PASSWORD, key) if key == &MSG_KEY_DOWN => { // Give focus to port self.view.active(COMPONENT_RADIO_PROTOCOL); None } // Focus ( UP ) - (COMPONENT_INPUT_PASSWORD, &MSG_KEY_UP) => { + (COMPONENT_INPUT_PASSWORD, key) if key == &MSG_KEY_UP => { // Give focus to port self.view.active(COMPONENT_INPUT_USERNAME); None } - (COMPONENT_INPUT_USERNAME, &MSG_KEY_UP) => { + (COMPONENT_INPUT_USERNAME, key) if key == &MSG_KEY_UP => { // Give focus to port self.view.active(COMPONENT_INPUT_PORT); None } - (COMPONENT_INPUT_PORT, &MSG_KEY_UP) => { + (COMPONENT_INPUT_PORT, key) if key == &MSG_KEY_UP => { // Give focus to port self.view.active(COMPONENT_INPUT_ADDR); None } - (COMPONENT_INPUT_ADDR, &MSG_KEY_UP) => { + (COMPONENT_INPUT_ADDR, key) if key == &MSG_KEY_UP => { // Give focus to port self.view.active(COMPONENT_RADIO_PROTOCOL); None } - (COMPONENT_RADIO_PROTOCOL, &MSG_KEY_UP) => { + (COMPONENT_RADIO_PROTOCOL, key) if key == &MSG_KEY_UP => { // Give focus to port self.view.active(COMPONENT_INPUT_PASSWORD); None @@ -118,25 +118,25 @@ impl Update for AuthActivity { } // Bookmarks commands // / - (COMPONENT_BOOKMARKS_LIST, &MSG_KEY_RIGHT) => { + (COMPONENT_BOOKMARKS_LIST, key) if key == &MSG_KEY_RIGHT => { // Give focus to recents self.view.active(COMPONENT_RECENTS_LIST); None } - (COMPONENT_RECENTS_LIST, &MSG_KEY_LEFT) => { + (COMPONENT_RECENTS_LIST, key) if key == &MSG_KEY_LEFT => { // Give focus to bookmarks self.view.active(COMPONENT_BOOKMARKS_LIST); None } // - (COMPONENT_BOOKMARKS_LIST, &MSG_KEY_DEL) - | (COMPONENT_BOOKMARKS_LIST, &MSG_KEY_CHAR_E) => { + (COMPONENT_BOOKMARKS_LIST, key) + if key == &MSG_KEY_DEL || key == &MSG_KEY_CHAR_E => + { // Show delete popup self.mount_bookmark_del_dialog(); None } - (COMPONENT_RECENTS_LIST, &MSG_KEY_DEL) - | (COMPONENT_RECENTS_LIST, &MSG_KEY_CHAR_E) => { + (COMPONENT_RECENTS_LIST, key) if key == &MSG_KEY_DEL || key == &MSG_KEY_CHAR_E => { // Show delete popup self.mount_recent_del_dialog(); None @@ -203,67 +203,68 @@ impl Update for AuthActivity { } } // hide tab - (COMPONENT_RADIO_BOOKMARK_DEL_RECENT, &MSG_KEY_ESC) => { + (COMPONENT_RADIO_BOOKMARK_DEL_RECENT, key) if key == &MSG_KEY_ESC => { self.umount_recent_del_dialog(); None } (COMPONENT_RADIO_BOOKMARK_DEL_RECENT, _) => None, - (COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK, &MSG_KEY_ESC) => { + (COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK, key) if key == &MSG_KEY_ESC => { self.umount_bookmark_del_dialog(); None } (COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK, _) => None, // Error message - (COMPONENT_TEXT_ERROR, &MSG_KEY_ENTER) | (COMPONENT_TEXT_ERROR, &MSG_KEY_ESC) => { + (COMPONENT_TEXT_ERROR, key) if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER => { // Umount text error self.umount_error(); None } (COMPONENT_TEXT_ERROR, _) => None, - (COMPONENT_TEXT_NEW_VERSION_NOTES, &MSG_KEY_ESC) - | (COMPONENT_TEXT_NEW_VERSION_NOTES, &MSG_KEY_ENTER) => { + (COMPONENT_TEXT_NEW_VERSION_NOTES, key) + if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER => + { // Umount release notes self.umount_release_notes(); None } (COMPONENT_TEXT_NEW_VERSION_NOTES, _) => None, // Help - (_, &MSG_KEY_CTRL_H) => { + (_, key) if key == &MSG_KEY_CTRL_H => { // Show help self.mount_help(); None } // Release notes - (_, &MSG_KEY_CTRL_R) => { + (_, key) if key == &MSG_KEY_CTRL_R => { // Show release notes self.mount_release_notes(); None } - (COMPONENT_TEXT_HELP, &MSG_KEY_ENTER) | (COMPONENT_TEXT_HELP, &MSG_KEY_ESC) => { + (COMPONENT_TEXT_HELP, key) if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER => { // Hide text help self.umount_help(); None } (COMPONENT_TEXT_HELP, _) => None, // Enter setup - (_, &MSG_KEY_CTRL_C) => { + (_, key) if key == &MSG_KEY_CTRL_C => { self.exit_reason = Some(super::ExitReason::EnterSetup); None } // Save bookmark; show popup - (_, &MSG_KEY_CTRL_S) => { + (_, key) if key == &MSG_KEY_CTRL_S => { // Show popup self.mount_bookmark_save_dialog(); // Give focus to bookmark name self.view.active(COMPONENT_INPUT_BOOKMARK_NAME); None } - (COMPONENT_INPUT_BOOKMARK_NAME, &MSG_KEY_DOWN) => { + (COMPONENT_INPUT_BOOKMARK_NAME, key) if key == &MSG_KEY_DOWN => { // Give focus to pwd self.view.active(COMPONENT_RADIO_BOOKMARK_SAVE_PWD); None } - (COMPONENT_RADIO_BOOKMARK_SAVE_PWD, &MSG_KEY_UP) => { + (COMPONENT_RADIO_BOOKMARK_SAVE_PWD, key) if key == &MSG_KEY_UP => { // Give focus to pwd self.view.active(COMPONENT_INPUT_BOOKMARK_NAME); None @@ -291,8 +292,9 @@ impl Update for AuthActivity { self.view_bookmarks() } // Hide save bookmark - (COMPONENT_INPUT_BOOKMARK_NAME, &MSG_KEY_ESC) - | (COMPONENT_RADIO_BOOKMARK_SAVE_PWD, &MSG_KEY_ESC) => { + (COMPONENT_INPUT_BOOKMARK_NAME, key) | (COMPONENT_RADIO_BOOKMARK_SAVE_PWD, key) + if key == &MSG_KEY_ESC => + { // Umount popup self.umount_bookmark_save_dialog(); None @@ -307,45 +309,30 @@ impl Update for AuthActivity { self.umount_quit(); None } - (COMPONENT_RADIO_QUIT, &MSG_KEY_ESC) => { + (COMPONENT_RADIO_QUIT, key) if key == &MSG_KEY_ESC => { self.umount_quit(); None } // -- text size error; block everything (COMPONENT_TEXT_SIZE_ERR, _) => None, // bookmarks - (COMPONENT_BOOKMARKS_LIST, &MSG_KEY_TAB) - | (COMPONENT_RECENTS_LIST, &MSG_KEY_TAB) => { + (COMPONENT_BOOKMARKS_LIST, key) | (COMPONENT_RECENTS_LIST, key) + if key == &MSG_KEY_TAB => + { // Give focus to address self.view.active(COMPONENT_INPUT_ADDR); None } // Any , go to bookmarks - (_, &MSG_KEY_TAB) => { + (_, key) if key == &MSG_KEY_TAB => { self.view.active(COMPONENT_BOOKMARKS_LIST); None } // On submit on any unhandled (connect) - (_, Msg::OnSubmit(_)) | (_, &MSG_KEY_ENTER) => { - // Validate fields - match self.collect_host_params() { - Err(err) => { - // mount error - self.mount_error(err); - } - Ok(params) => { - self.save_recent(); - // Set file transfer params to context - self.context_mut().set_ftparams(params); - // Set exit reason - self.exit_reason = Some(super::ExitReason::Connect); - } - } - // Return None - None - } + (_, Msg::OnSubmit(_)) => self.on_unhandled_submit(), + (_, key) if key == &MSG_KEY_ENTER => self.on_unhandled_submit(), // => Quit - (_, &MSG_KEY_ESC) => { + (_, key) if key == &MSG_KEY_ESC => { self.mount_quit(); None } @@ -367,4 +354,23 @@ impl AuthActivity { } } } + + fn on_unhandled_submit(&mut self) -> Option<(String, Msg)> { + // Validate fields + match self.collect_host_params() { + Err(err) => { + // mount error + self.mount_error(err); + } + Ok(params) => { + self.save_recent(); + // Set file transfer params to context + self.context_mut().set_ftparams(params); + // Set exit reason + self.exit_reason = Some(super::ExitReason::Connect); + } + } + // Return None + None + } } diff --git a/src/ui/activities/auth/view.rs b/src/ui/activities/auth/view.rs index 8ec4763..2f61f94 100644 --- a/src/ui/activities/auth/view.rs +++ b/src/ui/activities/auth/view.rs @@ -27,17 +27,15 @@ */ // Locals use super::{AuthActivity, Context, FileTransferProtocol}; -use crate::ui::components::{ - bookmark_list::{BookmarkList, BookmarkListPropsBuilder}, - msgbox::{MsgBox, MsgBoxPropsBuilder}, -}; +use crate::ui::components::bookmark_list::{BookmarkList, BookmarkListPropsBuilder}; use crate::utils::ui::draw_area_in; // Ext -use tuirealm::components::{ +use tui_realm_stdlib::{ input::{Input, InputPropsBuilder}, label::{Label, LabelPropsBuilder}, + list::{List, ListPropsBuilder}, + paragraph::{Paragraph, ParagraphPropsBuilder}, radio::{Radio, RadioPropsBuilder}, - scrolltable::{ScrollTablePropsBuilder, Scrolltable}, span::{Span, SpanPropsBuilder}, textarea::{Textarea, TextareaPropsBuilder}, }; @@ -47,7 +45,7 @@ use tuirealm::tui::{ widgets::{BorderType, Borders, Clear}, }; use tuirealm::{ - props::{InputType, PropsBuilder, TableBuilder, TextSpan, TextSpanBuilder}, + props::{Alignment, InputType, PropsBuilder, TableBuilder, TextSpan}, Msg, Payload, Value, }; @@ -91,19 +89,11 @@ impl AuthActivity { Box::new(Span::new( SpanPropsBuilder::default() .with_spans(vec![ - TextSpanBuilder::new("Press ").bold().build(), - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - TextSpanBuilder::new(" to show keybindings; ") - .bold() - .build(), - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - TextSpanBuilder::new(" to enter setup").bold().build(), + TextSpan::new("Press ").bold(), + TextSpan::new("").bold().fg(key_color), + TextSpan::new(" to show keybindings; ").bold(), + TextSpan::new("").bold().fg(key_color), + TextSpan::new(" to enter setup").bold(), ]) .build(), )), @@ -118,15 +108,8 @@ impl AuthActivity { .with_color(protocol_color) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Rounded, protocol_color) - .with_options( - Some(String::from("Protocol")), - vec![ - String::from("SFTP"), - String::from("SCP"), - String::from("FTP"), - String::from("FTPS"), - ], - ) + .with_title("Protocol", Alignment::Left) + .with_options(&["SFTP", "SCP", "FTP", "FTPS"]) .with_value(Self::protocol_enum_to_opt(default_protocol)) .build(), )), @@ -138,7 +121,7 @@ impl AuthActivity { InputPropsBuilder::default() .with_foreground(addr_color) .with_borders(Borders::ALL, BorderType::Rounded, addr_color) - .with_label(String::from("Remote host")) + .with_label("Remote host", Alignment::Left) .build(), )), ); @@ -149,7 +132,7 @@ impl AuthActivity { InputPropsBuilder::default() .with_foreground(port_color) .with_borders(Borders::ALL, BorderType::Rounded, port_color) - .with_label(String::from("Port number")) + .with_label("Port number", Alignment::Left) .with_input(InputType::Number) .with_input_len(5) .with_value(Self::get_default_port_for_protocol(default_protocol).to_string()) @@ -163,7 +146,7 @@ impl AuthActivity { InputPropsBuilder::default() .with_foreground(username_color) .with_borders(Borders::ALL, BorderType::Rounded, username_color) - .with_label(String::from("Username")) + .with_label("Username", Alignment::Left) .build(), )), ); @@ -174,7 +157,7 @@ impl AuthActivity { InputPropsBuilder::default() .with_foreground(password_color) .with_borders(Borders::ALL, BorderType::Rounded, password_color) - .with_label(String::from("Password")) + .with_label("Password", Alignment::Left) .with_input(InputType::Password) .build(), )), @@ -193,7 +176,7 @@ impl AuthActivity { .with_foreground(Color::Yellow) .with_spans(vec![ TextSpan::from("termscp "), - TextSpanBuilder::new(version.as_str()).underlined().bold().build(), + TextSpan::new(version.as_str()).underlined().bold(), TextSpan::from(" is NOW available! Get it from ; view release notes with "), ]) .build(), @@ -208,7 +191,7 @@ impl AuthActivity { .with_background(bookmarks_color) .with_foreground(Color::Black) .with_borders(Borders::ALL, BorderType::Plain, bookmarks_color) - .with_bookmarks(Some(String::from("Bookmarks")), vec![]) + .with_title("Bookmarks", Alignment::Left) .build(), )), ); @@ -220,7 +203,7 @@ impl AuthActivity { .with_background(recents_color) .with_foreground(Color::Black) .with_borders(Borders::ALL, BorderType::Plain, recents_color) - .with_bookmarks(Some(String::from("Recent connections")), vec![]) + .with_title("Recent connections", Alignment::Left) .build(), )), ); @@ -426,7 +409,7 @@ impl AuthActivity { let msg = self.view.update( super::COMPONENT_BOOKMARKS_LIST, BookmarkListPropsBuilder::from(props) - .with_bookmarks(Some(String::from("Bookmarks")), bookmarks) + .with_bookmarks(bookmarks) .build(), ); msg @@ -464,7 +447,7 @@ impl AuthActivity { let msg = self.view.update( super::COMPONENT_RECENTS_LIST, BookmarkListPropsBuilder::from(props) - .with_bookmarks(Some(String::from("Recent connections")), bookmarks) + .with_bookmarks(bookmarks) .build(), ); msg @@ -482,12 +465,13 @@ impl AuthActivity { let err_color = self.theme().misc_error_dialog; self.view.mount( super::COMPONENT_TEXT_ERROR, - Box::new(MsgBox::new( - MsgBoxPropsBuilder::default() + Box::new(Paragraph::new( + ParagraphPropsBuilder::default() .with_foreground(err_color) .with_borders(Borders::ALL, BorderType::Thick, err_color) .bold() - .with_texts(None, vec![TextSpan::from(text)]) + .with_text_alignment(Alignment::Center) + .with_texts(vec![TextSpan::from(text)]) .build(), )), ); @@ -510,17 +494,15 @@ impl AuthActivity { let err_color = self.theme().misc_error_dialog; self.view.mount( super::COMPONENT_TEXT_SIZE_ERR, - Box::new(MsgBox::new( - MsgBoxPropsBuilder::default() + Box::new(Paragraph::new( + ParagraphPropsBuilder::default() .with_foreground(err_color) .with_borders(Borders::ALL, BorderType::Thick, err_color) .bold() - .with_texts( - None, - vec![TextSpan::from( - "termscp requires at least 24 lines of height to run", - )], - ) + .with_texts(vec![TextSpan::from( + "termscp requires at least 24 lines of height to run", + )]) + .with_text_alignment(Alignment::Center) .build(), )), ); @@ -548,10 +530,8 @@ impl AuthActivity { .with_color(quit_color) .with_borders(Borders::ALL, BorderType::Rounded, quit_color) .with_inverted_color(Color::Black) - .with_options( - Some(String::from("Quit termscp?")), - vec![String::from("Yes"), String::from("No")], - ) + .with_title("Quit termscp?", Alignment::Center) + .with_options(&[String::from("Yes"), String::from("No")]) .build(), )), ); @@ -577,10 +557,8 @@ impl AuthActivity { .with_color(warn_color) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Rounded, warn_color) - .with_options( - Some(String::from("Delete bookmark?")), - vec![String::from("Yes"), String::from("No")], - ) + .with_title("Delete bookmark?", Alignment::Center) + .with_options(&[String::from("Yes"), String::from("No")]) .with_value(1) .build(), )), @@ -610,10 +588,8 @@ impl AuthActivity { .with_color(warn_color) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Rounded, warn_color) - .with_options( - Some(String::from("Delete bookmark?")), - vec![String::from("Yes"), String::from("No")], - ) + .with_title("Delete bookmark?", Alignment::Center) + .with_options(&[String::from("Yes"), String::from("No")]) .with_value(1) .build(), )), @@ -640,7 +616,7 @@ impl AuthActivity { Box::new(Input::new( InputPropsBuilder::default() .with_foreground(save_color) - .with_label(String::from("Save bookmark as…")) + .with_label("Save bookmark as…", Alignment::Center) .with_borders( Borders::TOP | Borders::RIGHT | Borders::LEFT, BorderType::Rounded, @@ -659,10 +635,8 @@ impl AuthActivity { BorderType::Rounded, Color::Reset, ) - .with_options( - Some(String::from("Save password?")), - vec![String::from("Yes"), String::from("No")], - ) + .with_title("Save password?", Alignment::Center) + .with_options(&[String::from("Yes"), String::from("No")]) .build(), )), ); @@ -685,77 +659,38 @@ impl AuthActivity { let key_color = self.theme().misc_keys; self.view.mount( super::COMPONENT_TEXT_HELP, - Box::new(Scrolltable::new( - ScrollTablePropsBuilder::default() + Box::new(List::new( + ListPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, Color::White) .with_highlighted_str(Some("?")) .with_max_scroll_step(8) + .scrollable(true) .bold() - .with_table( - Some(String::from("Help")), + .with_title("Help", Alignment::Center) + .with_rows( TableBuilder::default() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Quit termscp")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Switch from form and bookmarks")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Switch bookmark tab")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Move up/down in current tab")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Connect/Load bookmark")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Delete selected bookmark")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Enter setup")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Save bookmark")) .build(), ) @@ -786,7 +721,8 @@ impl AuthActivity { Box::new(Textarea::new( TextareaPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, Color::LightYellow) - .with_texts(Some(String::from("Release notes")), spans) + .with_title("Release notes", Alignment::Center) + .with_texts(spans) .build(), )), ); diff --git a/src/ui/activities/filetransfer/update.rs b/src/ui/activities/filetransfer/update.rs index fb6e828..3dc40fc 100644 --- a/src/ui/activities/filetransfer/update.rs +++ b/src/ui/activities/filetransfer/update.rs @@ -42,9 +42,9 @@ use crate::ui::components::{file_list::FileListPropsBuilder, logbox::LogboxProps use crate::ui::keymap::*; use crate::utils::fmt::fmt_path_elide_ex; // externals +use tui_realm_stdlib::progress_bar::ProgressBarPropsBuilder; use tuirealm::{ - components::progress_bar::ProgressBarPropsBuilder, - props::{PropsBuilder, TableBuilder, TextSpan, TextSpanBuilder}, + props::{Alignment, PropsBuilder, TableBuilder, TextSpan}, tui::style::Color, Msg, Payload, Update, Value, }; @@ -63,13 +63,13 @@ impl Update for FileTransferActivity { None => None, // Exit after None Some(msg) => match msg { // -- local tab - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_RIGHT) => { + (COMPONENT_EXPLORER_LOCAL, key) if key == &MSG_KEY_RIGHT => { // Change tab self.view.active(COMPONENT_EXPLORER_REMOTE); self.browser.change_tab(FileExplorerTab::Remote); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_BACKSPACE) => { + (COMPONENT_EXPLORER_LOCAL, key) if key == &MSG_KEY_BACKSPACE => { // Go to previous directory self.action_go_to_previous_local_dir(false); if self.browser.sync_browsing { @@ -98,11 +98,11 @@ impl Update for FileTransferActivity { None } } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_SPACE) => { + (COMPONENT_EXPLORER_LOCAL, key) if key == &MSG_KEY_SPACE => { self.action_local_send(); self.update_remote_filelist() } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_A) => { + (COMPONENT_EXPLORER_LOCAL, key) if key == &MSG_KEY_CHAR_A => { // Toggle hidden files self.local_mut().toggle_hidden_files(); // Update status bar @@ -110,24 +110,24 @@ impl Update for FileTransferActivity { // Reload file list component self.update_local_filelist() } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_I) => { + (COMPONENT_EXPLORER_LOCAL, key) if key == &MSG_KEY_CHAR_I => { if let SelectedEntry::One(file) = self.get_local_selected_entries() { self.mount_file_info(&file); } None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_L) => { + (COMPONENT_EXPLORER_LOCAL, key) if key == &MSG_KEY_CHAR_L => { // Reload directory self.reload_local_dir(); // Reload file list component self.update_local_filelist() } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_O) => { + (COMPONENT_EXPLORER_LOCAL, key) if key == &MSG_KEY_CHAR_O => { self.action_edit_local_file(); // Reload file list component self.update_local_filelist() } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_U) => { + (COMPONENT_EXPLORER_LOCAL, key) if key == &MSG_KEY_CHAR_U => { self.action_go_to_local_upper_dir(false); if self.browser.sync_browsing { let _ = self.update_remote_filelist(); @@ -136,7 +136,7 @@ impl Update for FileTransferActivity { self.update_local_filelist() } // -- remote tab - (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_LEFT) => { + (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_LEFT => { // Change tab self.view.active(COMPONENT_EXPLORER_LOCAL); self.browser.change_tab(FileExplorerTab::Local); @@ -162,11 +162,11 @@ impl Update for FileTransferActivity { None } } - (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_SPACE) => { + (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_SPACE => { self.action_remote_recv(); self.update_local_filelist() } - (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_BACKSPACE) => { + (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_BACKSPACE => { // Go to previous directory self.action_go_to_previous_remote_dir(false); // If sync is enabled update local too @@ -176,7 +176,7 @@ impl Update for FileTransferActivity { // Reload file list component self.update_remote_filelist() } - (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_A) => { + (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_CHAR_A => { // Toggle hidden files self.remote_mut().toggle_hidden_files(); // Update status bar @@ -184,25 +184,25 @@ impl Update for FileTransferActivity { // Reload file list component self.update_remote_filelist() } - (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_I) => { + (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_CHAR_I => { if let SelectedEntry::One(file) = self.get_remote_selected_entries() { self.mount_file_info(&file); } None } - (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_L) => { + (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_CHAR_L => { // Reload directory self.reload_remote_dir(); // Reload file list component self.update_remote_filelist() } - (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_O) => { + (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_CHAR_O => { // Edit file self.action_edit_remote_file(); // Reload file list component self.update_remote_filelist() } - (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_U) => { + (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_CHAR_U => { self.action_go_to_remote_upper_dir(false); if self.browser.sync_browsing { let _ = self.update_local_filelist(); @@ -211,64 +211,78 @@ impl Update for FileTransferActivity { self.update_remote_filelist() } // -- common explorer keys - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_B) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_B) => { + (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key) + if key == &MSG_KEY_CHAR_B => + { // Show sorting file self.mount_file_sorting(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_C) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_C) => { + (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key) + if key == &MSG_KEY_CHAR_C => + { self.mount_copy(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_D) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_D) => { + (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key) + if key == &MSG_KEY_CHAR_D => + { self.mount_mkdir(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_F) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_F) => { + (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key) + if key == &MSG_KEY_CHAR_F => + { self.mount_find_input(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_G) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_G) => { + (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key) + if key == &MSG_KEY_CHAR_G => + { self.mount_goto(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_H) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_H) => { + (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key) + if key == &MSG_KEY_CHAR_H => + { self.mount_help(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_N) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_N) => { + (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key) + if key == &MSG_KEY_CHAR_N => + { self.mount_newfile(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_Q) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_Q) - | (COMPONENT_LOG_BOX, &MSG_KEY_CHAR_Q) => { + (COMPONENT_EXPLORER_LOCAL, key) + | (COMPONENT_EXPLORER_REMOTE, key) + | (COMPONENT_LOG_BOX, key) + if key == &MSG_KEY_CHAR_Q => + { self.mount_quit(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_R) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_R) => { + (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key) + if key == &MSG_KEY_CHAR_R => + { // Mount rename self.mount_rename(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_S) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_S) - | (COMPONENT_EXPLORER_FIND, &MSG_KEY_CHAR_S) => { + (COMPONENT_EXPLORER_LOCAL, key) + | (COMPONENT_EXPLORER_REMOTE, key) + | (COMPONENT_EXPLORER_FIND, key) + if key == &MSG_KEY_CHAR_S => + { // Mount save as self.mount_saveas(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_V) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_V) - | (COMPONENT_EXPLORER_FIND, &MSG_KEY_CHAR_V) => { + (COMPONENT_EXPLORER_LOCAL, key) + | (COMPONENT_EXPLORER_REMOTE, key) + | (COMPONENT_EXPLORER_FIND, key) + if key == &MSG_KEY_CHAR_V => + { // View match self.browser.tab() { FileExplorerTab::Local => self.action_open_local(), @@ -279,44 +293,49 @@ impl Update for FileTransferActivity { } None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_W) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_W) - | (COMPONENT_EXPLORER_FIND, &MSG_KEY_CHAR_W) => { + (COMPONENT_EXPLORER_LOCAL, key) + | (COMPONENT_EXPLORER_REMOTE, key) + | (COMPONENT_EXPLORER_FIND, key) + if key == &MSG_KEY_CHAR_W => + { // Open with self.mount_openwith(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_X) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_X) => { + (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key) + if key == &MSG_KEY_CHAR_X => + { // Mount exec self.mount_exec(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_Y) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_Y) => { + (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key) + if key == &MSG_KEY_CHAR_Y => + { // Toggle browser sync self.browser.toggle_sync_browsing(); // Update status bar self.refresh_remote_status_bar(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_ESC) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_ESC) - | (COMPONENT_LOG_BOX, &MSG_KEY_ESC) => { + (COMPONENT_EXPLORER_LOCAL, key) + | (COMPONENT_EXPLORER_REMOTE, key) + | (COMPONENT_LOG_BOX, key) + if key == &MSG_KEY_ESC => + { self.mount_disconnect(); None } - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_DEL) - | (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_E) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_DEL) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_E) - | (COMPONENT_EXPLORER_FIND, &MSG_KEY_DEL) - | (COMPONENT_EXPLORER_FIND, &MSG_KEY_CHAR_E) => { + (COMPONENT_EXPLORER_LOCAL, key) + | (COMPONENT_EXPLORER_REMOTE, key) + | (COMPONENT_EXPLORER_FIND, key) + if key == &MSG_KEY_CHAR_E || key == &MSG_KEY_DEL => + { self.mount_radio_delete(); None } // -- find result explorer - (COMPONENT_EXPLORER_FIND, &MSG_KEY_ESC) => { + (COMPONENT_EXPLORER_FIND, key) if key == &MSG_KEY_ESC => { // Umount find self.umount_find(); // Finalize find @@ -337,7 +356,7 @@ impl Update for FileTransferActivity { _ => None, } } - (COMPONENT_EXPLORER_FIND, &MSG_KEY_SPACE) => { + (COMPONENT_EXPLORER_FIND, key) if key == &MSG_KEY_SPACE => { // Get entry self.action_find_transfer(None); // Reload files @@ -349,18 +368,19 @@ impl Update for FileTransferActivity { } } // -- switch to log - (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_TAB) - | (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_TAB) => { + (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key) + if key == &MSG_KEY_TAB => + { self.view.active(COMPONENT_LOG_BOX); // Active log box None } // -- Log box - (COMPONENT_LOG_BOX, &MSG_KEY_TAB) => { + (COMPONENT_LOG_BOX, key) if key == &MSG_KEY_TAB => { self.view.blur(); // Blur log box None } // -- copy popup - (COMPONENT_INPUT_COPY, &MSG_KEY_ESC) => { + (COMPONENT_INPUT_COPY, key) if key == &MSG_KEY_ESC => { self.umount_copy(); None } @@ -383,7 +403,7 @@ impl Update for FileTransferActivity { } (COMPONENT_INPUT_COPY, _) => None, // -- exec popup - (COMPONENT_INPUT_EXEC, &MSG_KEY_ESC) => { + (COMPONENT_INPUT_EXEC, key) if key == &MSG_KEY_ESC => { self.umount_exec(); None } @@ -406,7 +426,7 @@ impl Update for FileTransferActivity { } (COMPONENT_INPUT_EXEC, _) => None, // -- find popup - (COMPONENT_INPUT_FIND, &MSG_KEY_ESC) => { + (COMPONENT_INPUT_FIND, key) if key == &MSG_KEY_ESC => { self.umount_find_input(); None } @@ -441,7 +461,7 @@ impl Update for FileTransferActivity { None } // -- goto popup - (COMPONENT_INPUT_GOTO, &MSG_KEY_ESC) => { + (COMPONENT_INPUT_GOTO, key) if key == &MSG_KEY_ESC => { self.umount_goto(); None } @@ -474,7 +494,7 @@ impl Update for FileTransferActivity { } (COMPONENT_INPUT_GOTO, _) => None, // -- make directory - (COMPONENT_INPUT_MKDIR, &MSG_KEY_ESC) => { + (COMPONENT_INPUT_MKDIR, key) if key == &MSG_KEY_ESC => { self.umount_mkdir(); None } @@ -494,7 +514,7 @@ impl Update for FileTransferActivity { } (COMPONENT_INPUT_MKDIR, _) => None, // -- new file - (COMPONENT_INPUT_NEWFILE, &MSG_KEY_ESC) => { + (COMPONENT_INPUT_NEWFILE, key) if key == &MSG_KEY_ESC => { self.umount_newfile(); None } @@ -514,7 +534,7 @@ impl Update for FileTransferActivity { } (COMPONENT_INPUT_NEWFILE, _) => None, // -- open with - (COMPONENT_INPUT_OPEN_WITH, &MSG_KEY_ESC) => { + (COMPONENT_INPUT_OPEN_WITH, key) if key == &MSG_KEY_ESC => { self.umount_openwith(); None } @@ -531,7 +551,7 @@ impl Update for FileTransferActivity { } (COMPONENT_INPUT_OPEN_WITH, _) => None, // -- rename - (COMPONENT_INPUT_RENAME, &MSG_KEY_ESC) => { + (COMPONENT_INPUT_RENAME, key) if key == &MSG_KEY_ESC => { self.umount_rename(); None } @@ -553,7 +573,7 @@ impl Update for FileTransferActivity { } (COMPONENT_INPUT_RENAME, _) => None, // -- save as - (COMPONENT_INPUT_SAVEAS, &MSG_KEY_ESC) => { + (COMPONENT_INPUT_SAVEAS, key) if key == &MSG_KEY_ESC => { self.umount_saveas(); None } @@ -578,15 +598,18 @@ impl Update for FileTransferActivity { } (COMPONENT_INPUT_SAVEAS, _) => None, // -- fileinfo - (COMPONENT_LIST_FILEINFO, &MSG_KEY_ENTER) - | (COMPONENT_LIST_FILEINFO, &MSG_KEY_ESC) => { + (COMPONENT_LIST_FILEINFO, key) | (COMPONENT_LIST_FILEINFO, key) + if key == &MSG_KEY_ENTER || key == &MSG_KEY_ESC => + { self.umount_file_info(); None } (COMPONENT_LIST_FILEINFO, _) => None, // -- delete - (COMPONENT_RADIO_DELETE, &MSG_KEY_ESC) - | (COMPONENT_RADIO_DELETE, Msg::OnSubmit(Payload::One(Value::Usize(1)))) => { + (COMPONENT_RADIO_DELETE, key) + if key == &MSG_KEY_ESC + || key == &Msg::OnSubmit(Payload::One(Value::Usize(1))) => + { self.umount_radio_delete(); None } @@ -631,8 +654,10 @@ impl Update for FileTransferActivity { } (COMPONENT_RADIO_DELETE, _) => None, // -- disconnect - (COMPONENT_RADIO_DISCONNECT, &MSG_KEY_ESC) - | (COMPONENT_RADIO_DISCONNECT, Msg::OnSubmit(Payload::One(Value::Usize(1)))) => { + (COMPONENT_RADIO_DISCONNECT, key) + if key == &MSG_KEY_ESC + || key == &Msg::OnSubmit(Payload::One(Value::Usize(1))) => + { self.umount_disconnect(); None } @@ -643,8 +668,10 @@ impl Update for FileTransferActivity { } (COMPONENT_RADIO_DISCONNECT, _) => None, // -- quit - (COMPONENT_RADIO_QUIT, &MSG_KEY_ESC) - | (COMPONENT_RADIO_QUIT, Msg::OnSubmit(Payload::One(Value::Usize(1)))) => { + (COMPONENT_RADIO_QUIT, key) + if key == &MSG_KEY_ESC + || key == &Msg::OnSubmit(Payload::One(Value::Usize(1))) => + { self.umount_quit(); None } @@ -655,8 +682,11 @@ impl Update for FileTransferActivity { } (COMPONENT_RADIO_QUIT, _) => None, // -- sorting - (COMPONENT_RADIO_SORTING, &MSG_KEY_ESC) - | (COMPONENT_RADIO_SORTING, Msg::OnSubmit(_)) => { + (COMPONENT_RADIO_SORTING, key) if key == &MSG_KEY_ESC => { + self.umount_file_sorting(); + None + } + (COMPONENT_RADIO_SORTING, Msg::OnSubmit(_)) => { self.umount_file_sorting(); None } @@ -688,25 +718,31 @@ impl Update for FileTransferActivity { } (COMPONENT_RADIO_SORTING, _) => None, // -- error - (COMPONENT_TEXT_ERROR, &MSG_KEY_ESC) | (COMPONENT_TEXT_ERROR, &MSG_KEY_ENTER) => { + (COMPONENT_TEXT_ERROR, key) | (COMPONENT_TEXT_ERROR, key) + if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER => + { self.umount_error(); None } (COMPONENT_TEXT_ERROR, _) => None, // -- fatal - (COMPONENT_TEXT_FATAL, &MSG_KEY_ESC) | (COMPONENT_TEXT_FATAL, &MSG_KEY_ENTER) => { + (COMPONENT_TEXT_FATAL, key) | (COMPONENT_TEXT_FATAL, key) + if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER => + { self.exit_reason = Some(super::ExitReason::Disconnect); None } (COMPONENT_TEXT_FATAL, _) => None, // -- help - (COMPONENT_TEXT_HELP, &MSG_KEY_ESC) | (COMPONENT_TEXT_HELP, &MSG_KEY_ENTER) => { + (COMPONENT_TEXT_HELP, key) | (COMPONENT_TEXT_HELP, key) + if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER => + { self.umount_help(); None } (COMPONENT_TEXT_HELP, _) => None, // -- progress bar - (COMPONENT_PROGRESS_BAR_PARTIAL, &MSG_KEY_CTRL_C) => { + (COMPONENT_PROGRESS_BAR_PARTIAL, key) if key == &MSG_KEY_CTRL_C => { // Set transfer aborted to True self.transfer.abort(); None @@ -752,7 +788,8 @@ impl FileTransferActivity { .collect(); // Update let props = FileListPropsBuilder::from(props) - .with_files(Some(hostname), files) + .with_files(files) + .with_title(hostname, Alignment::Left) .build(); // Update self.view.update(super::COMPONENT_EXPLORER_LOCAL, props) @@ -790,7 +827,8 @@ impl FileTransferActivity { .collect(); // Update let props = FileListPropsBuilder::from(props) - .with_files(Some(hostname), files) + .with_files(files) + .with_title(hostname, Alignment::Left) .build(); self.view.update(super::COMPONENT_EXPLORER_REMOTE, props) } @@ -823,7 +861,7 @@ impl FileTransferActivity { ))) .add_col(TextSpan::from(" [")) .add_col( - TextSpanBuilder::new( + TextSpan::new( format!( "{:5}", match record.level { @@ -834,16 +872,13 @@ impl FileTransferActivity { ) .as_str(), ) - .with_foreground(fg) - .build(), + .fg(fg), ) .add_col(TextSpan::from("]: ")) .add_col(TextSpan::from(record.msg.as_ref())); } let table = table.build(); - let props = LogboxPropsBuilder::from(props) - .with_log(Some(String::from("Log")), table) - .build(); + let props = LogboxPropsBuilder::from(props).with_log(table).build(); self.view.update(super::COMPONENT_LOG_BOX, props) } None => None, @@ -852,9 +887,8 @@ impl FileTransferActivity { pub(super) fn update_progress_bar(&mut self, filename: String) -> Option<(String, Msg)> { if let Some(props) = self.view.get_props(COMPONENT_PROGRESS_BAR_FULL) { - let root_name: String = props.texts.title.as_deref().unwrap_or("").to_string(); let props = ProgressBarPropsBuilder::from(props) - .with_texts(Some(root_name), self.transfer.full.to_string()) + .with_label(self.transfer.full.to_string()) .with_progress(self.transfer.full.calc_progress()) .build(); let _ = self.view.update(COMPONENT_PROGRESS_BAR_FULL, props); @@ -862,7 +896,8 @@ impl FileTransferActivity { match self.view.get_props(COMPONENT_PROGRESS_BAR_PARTIAL) { Some(props) => { let props = ProgressBarPropsBuilder::from(props) - .with_texts(Some(filename), self.transfer.partial.to_string()) + .with_title(filename, Alignment::Center) + .with_label(self.transfer.partial.to_string()) .with_progress(self.transfer.partial.calc_progress()) .build(); self.view.update(COMPONENT_PROGRESS_BAR_PARTIAL, props) @@ -889,7 +924,6 @@ impl FileTransferActivity { match self.view.get_props(COMPONENT_EXPLORER_FIND) { None => None, Some(props) => { - let title: String = props.texts.title.clone().unwrap_or_default(); // Prepare files let files: Vec = self .found() @@ -897,9 +931,7 @@ impl FileTransferActivity { .iter_files() .map(|x: &FsEntry| self.found().unwrap().fmt_file(x)) .collect(); - let props = FileListPropsBuilder::from(props) - .with_files(Some(title), files) - .build(); + let props = FileListPropsBuilder::from(props).with_files(files).build(); self.view.update(COMPONENT_EXPLORER_FIND, props) } } diff --git a/src/ui/activities/filetransfer/view.rs b/src/ui/activities/filetransfer/view.rs index c0685a5..e31bd3f 100644 --- a/src/ui/activities/filetransfer/view.rs +++ b/src/ui/activities/filetransfer/view.rs @@ -32,7 +32,6 @@ use crate::fs::FsEntry; use crate::ui::components::{ file_list::{FileList, FileListPropsBuilder}, logbox::{LogBox, LogboxPropsBuilder}, - msgbox::{MsgBox, MsgBoxPropsBuilder}, }; use crate::ui::store::Store; use crate::utils::fmt::fmt_time; @@ -40,15 +39,16 @@ use crate::utils::ui::draw_area_in; // Ext use bytesize::ByteSize; use std::path::PathBuf; -use tuirealm::components::{ +use tui_realm_stdlib::{ input::{Input, InputPropsBuilder}, + list::{List, ListPropsBuilder}, + paragraph::{Paragraph, ParagraphPropsBuilder}, progress_bar::{ProgressBar, ProgressBarPropsBuilder}, radio::{Radio, RadioPropsBuilder}, - scrolltable::{ScrollTablePropsBuilder, Scrolltable}, span::{Span, SpanPropsBuilder}, table::{Table, TablePropsBuilder}, }; -use tuirealm::props::{PropsBuilder, TableBuilder, TextSpan, TextSpanBuilder}; +use tuirealm::props::{Alignment, PropsBuilder, TableBuilder, TextSpan}; use tuirealm::tui::{ layout::{Constraint, Direction, Layout}, style::Color, @@ -101,6 +101,7 @@ impl FileTransferActivity { super::COMPONENT_LOG_BOX, Box::new(LogBox::new( LogboxPropsBuilder::default() + .with_title("Log", Alignment::Left) .with_background(log_background) .with_borders(Borders::ALL, BorderType::Plain, log_panel) .build(), @@ -383,12 +384,13 @@ impl FileTransferActivity { let error_color = self.theme().misc_error_dialog; self.view.mount( super::COMPONENT_TEXT_ERROR, - Box::new(MsgBox::new( - MsgBoxPropsBuilder::default() + Box::new(Paragraph::new( + ParagraphPropsBuilder::default() .with_foreground(error_color) .with_borders(Borders::ALL, BorderType::Rounded, error_color) .bold() - .with_texts(None, vec![TextSpan::from(text)]) + .with_text_alignment(Alignment::Center) + .with_texts(vec![TextSpan::from(text)]) .build(), )), ); @@ -408,12 +410,13 @@ impl FileTransferActivity { let error_color = self.theme().misc_error_dialog; self.view.mount( super::COMPONENT_TEXT_FATAL, - Box::new(MsgBox::new( - MsgBoxPropsBuilder::default() + Box::new(Paragraph::new( + ParagraphPropsBuilder::default() .with_foreground(error_color) .with_borders(Borders::ALL, BorderType::Rounded, error_color) .bold() - .with_texts(None, vec![TextSpan::from(text)]) + .with_text_alignment(Alignment::Center) + .with_texts(vec![TextSpan::from(text)]) .build(), )), ); @@ -422,28 +425,26 @@ impl FileTransferActivity { } pub(super) fn mount_wait(&mut self, text: &str) { - self.mount_wait_ex(text, false, Color::Reset); + self.mount_wait_ex(text, Color::Reset); } pub(super) fn mount_blocking_wait(&mut self, text: &str) { - self.mount_wait_ex(text, true, Color::Reset); + self.mount_wait_ex(text, Color::Reset); self.view(); } - fn mount_wait_ex(&mut self, text: &str, blink: bool, color: Color) { + fn mount_wait_ex(&mut self, text: &str, color: Color) { // Mount - let mut builder: MsgBoxPropsBuilder = MsgBoxPropsBuilder::default(); + let mut builder: ParagraphPropsBuilder = ParagraphPropsBuilder::default(); builder .with_foreground(color) .with_borders(Borders::ALL, BorderType::Rounded, Color::White) .bold() - .with_texts(None, vec![TextSpan::from(text)]); - if blink { - builder.blink(); - } + .with_text_alignment(Alignment::Center) + .with_texts(vec![TextSpan::from(text)]); self.view.mount( super::COMPONENT_TEXT_WAIT, - Box::new(MsgBox::new(builder.build())), + Box::new(Paragraph::new(builder.build())), ); // Give focus to info self.view.active(super::COMPONENT_TEXT_WAIT); @@ -466,10 +467,8 @@ impl FileTransferActivity { .with_color(quit_color) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Rounded, quit_color) - .with_options( - Some(String::from("Are you sure you want to quit?")), - vec![String::from("Yes"), String::from("No")], - ) + .with_title("Are you sure you want to quit?", Alignment::Center) + .with_options(&[String::from("Yes"), String::from("No")]) .build(), )), ); @@ -496,10 +495,8 @@ impl FileTransferActivity { .with_color(quit_color) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Rounded, quit_color) - .with_options( - Some(String::from("Are you sure you want to disconnect?")), - vec![String::from("Yes"), String::from("No")], - ) + .with_title("Are you sure you want to disconnect?", Alignment::Center) + .with_options(&[String::from("Yes"), String::from("No")]) .build(), )), ); @@ -521,7 +518,7 @@ impl FileTransferActivity { InputPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_foreground(input_color) - .with_label(String::from("Copy file(s) to…")) + .with_label("Copy file(s) to…", Alignment::Center) .build(), )), ); @@ -540,7 +537,7 @@ impl FileTransferActivity { InputPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_foreground(input_color) - .with_label(String::from("Execute command")) + .with_label("Execute command", Alignment::Center) .build(), )), ); @@ -570,7 +567,10 @@ impl FileTransferActivity { super::COMPONENT_EXPLORER_FIND, Box::new(FileList::new( FileListPropsBuilder::default() - .with_files(Some(format!("Search results for \"{}\"", search)), vec![]) + .with_title( + format!("Search results for \"{}\"", search), + Alignment::Left, + ) .with_borders(Borders::ALL, BorderType::Plain, hg) .with_highlight_color(hg) .with_background(bg) @@ -594,7 +594,7 @@ impl FileTransferActivity { InputPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_foreground(input_color) - .with_label(String::from("Search files by name")) + .with_label("Search files by name", Alignment::Center) .build(), )), ); @@ -615,7 +615,7 @@ impl FileTransferActivity { InputPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_foreground(input_color) - .with_label(String::from("Change working directory")) + .with_label("Change working directory", Alignment::Center) .build(), )), ); @@ -634,7 +634,7 @@ impl FileTransferActivity { InputPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_foreground(input_color) - .with_label(String::from("Insert directory name")) + .with_label("Insert directory name", Alignment::Center) .build(), )), ); @@ -653,7 +653,7 @@ impl FileTransferActivity { InputPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_foreground(input_color) - .with_label(String::from("New file name")) + .with_label("New file name", Alignment::Center) .build(), )), ); @@ -672,7 +672,7 @@ impl FileTransferActivity { InputPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_foreground(input_color) - .with_label(String::from("Open file with…")) + .with_label("Open file with…", Alignment::Center) .build(), )), ); @@ -691,7 +691,7 @@ impl FileTransferActivity { InputPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_foreground(input_color) - .with_label(String::from("Move file(s) to…")) + .with_label("Move file(s) to…", Alignment::Center) .build(), )), ); @@ -710,7 +710,7 @@ impl FileTransferActivity { InputPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_foreground(input_color) - .with_label(String::from("Save as…")) + .with_label("Save as…", Alignment::Center) .build(), )), ); @@ -735,7 +735,7 @@ impl FileTransferActivity { BorderType::Rounded, Color::Reset, ) - .with_texts(Some(root_name), String::new()) + .with_title(root_name, Alignment::Center) .build(), )), ); @@ -750,7 +750,7 @@ impl FileTransferActivity { BorderType::Rounded, Color::Reset, ) - .with_texts(Some(String::from("Please wait")), String::new()) + .with_title("Please wait", Alignment::Center) .build(), )), ); @@ -782,15 +782,13 @@ impl FileTransferActivity { .with_color(sorting_color) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Rounded, sorting_color) - .with_options( - Some(String::from("Sort files by")), - vec![ - String::from("Name"), - String::from("Modify time"), - String::from("Creation time"), - String::from("Size"), - ], - ) + .with_title("Sort files by", Alignment::Center) + .with_options(&[ + String::from("Name"), + String::from("Modify time"), + String::from("Creation time"), + String::from("Size"), + ]) .with_value(index) .build(), )), @@ -811,10 +809,8 @@ impl FileTransferActivity { .with_color(warn_color) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Plain, warn_color) - .with_options( - Some(String::from("Delete file")), - vec![String::from("Yes"), String::from("No")], - ) + .with_title("Delete file", Alignment::Center) + .with_options(&[String::from("Yes"), String::from("No")]) .with_value(1) .build(), )), @@ -841,54 +837,35 @@ impl FileTransferActivity { None => format!("{}", file.get_abs_path().display()), }; // Make texts - texts.add_col(TextSpan::from("Path: ")).add_col( - TextSpanBuilder::new(path.as_str()) - .with_foreground(Color::Yellow) - .build(), - ); + texts + .add_col(TextSpan::from("Path: ")) + .add_col(TextSpan::new(path.as_str()).fg(Color::Yellow)); if let Some(filetype) = file.get_ftype() { texts .add_row() .add_col(TextSpan::from("File type: ")) - .add_col( - TextSpanBuilder::new(filetype.as_str()) - .with_foreground(Color::LightGreen) - .build(), - ); + .add_col(TextSpan::new(filetype.as_str()).fg(Color::LightGreen)); } let (bsize, size): (ByteSize, usize) = (ByteSize(file.get_size() as u64), file.get_size()); - texts.add_row().add_col(TextSpan::from("Size: ")).add_col( - TextSpanBuilder::new(format!("{} ({})", bsize, size).as_str()) - .with_foreground(Color::Cyan) - .build(), - ); + texts + .add_row() + .add_col(TextSpan::from("Size: ")) + .add_col(TextSpan::new(format!("{} ({})", bsize, size).as_str()).fg(Color::Cyan)); let ctime: String = fmt_time(file.get_creation_time(), "%b %d %Y %H:%M:%S"); let atime: String = fmt_time(file.get_last_access_time(), "%b %d %Y %H:%M:%S"); let mtime: String = fmt_time(file.get_creation_time(), "%b %d %Y %H:%M:%S"); texts .add_row() .add_col(TextSpan::from("Creation time: ")) - .add_col( - TextSpanBuilder::new(ctime.as_str()) - .with_foreground(Color::LightGreen) - .build(), - ); + .add_col(TextSpan::new(ctime.as_str()).fg(Color::LightGreen)); texts .add_row() .add_col(TextSpan::from("Last modified time: ")) - .add_col( - TextSpanBuilder::new(mtime.as_str()) - .with_foreground(Color::LightBlue) - .build(), - ); + .add_col(TextSpan::new(mtime.as_str()).fg(Color::LightBlue)); texts .add_row() .add_col(TextSpan::from("Last access time: ")) - .add_col( - TextSpanBuilder::new(atime.as_str()) - .with_foreground(Color::LightRed) - .build(), - ); + .add_col(TextSpan::new(atime.as_str()).fg(Color::LightRed)); // User #[cfg(target_family = "unix")] let username: String = match file.get_user() { @@ -911,22 +888,21 @@ impl FileTransferActivity { }; #[cfg(target_os = "windows")] let group: String = format!("{}", file.get_group().unwrap_or(0)); - texts.add_row().add_col(TextSpan::from("User: ")).add_col( - TextSpanBuilder::new(username.as_str()) - .with_foreground(Color::LightYellow) - .build(), - ); - texts.add_row().add_col(TextSpan::from("Group: ")).add_col( - TextSpanBuilder::new(group.as_str()) - .with_foreground(Color::Blue) - .build(), - ); + texts + .add_row() + .add_col(TextSpan::from("User: ")) + .add_col(TextSpan::new(username.as_str()).fg(Color::LightYellow)); + texts + .add_row() + .add_col(TextSpan::from("Group: ")) + .add_col(TextSpan::new(group.as_str()).fg(Color::Blue)); self.view.mount( super::COMPONENT_LIST_FILEINFO, Box::new(Table::new( TablePropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, Color::White) - .with_table(Some(file.get_name().to_string()), texts.build()) + .with_title(file.get_name(), Alignment::Left) + .with_table(texts.build()) .build(), )), ); @@ -941,22 +917,16 @@ impl FileTransferActivity { let sorting_color = self.theme().transfer_status_sorting; let hidden_color = self.theme().transfer_status_hidden; let local_bar_spans: Vec = vec![ - TextSpanBuilder::new("File sorting: ") - .with_foreground(sorting_color) - .build(), - TextSpanBuilder::new(Self::get_file_sorting_str(self.local().get_file_sorting())) - .with_foreground(sorting_color) - .reversed() - .build(), - TextSpanBuilder::new(" Hidden files: ") - .with_foreground(hidden_color) - .build(), - TextSpanBuilder::new(Self::get_hidden_files_str( + TextSpan::new("File sorting: ").fg(sorting_color), + TextSpan::new(Self::get_file_sorting_str(self.local().get_file_sorting())) + .fg(sorting_color) + .reversed(), + TextSpan::new(" Hidden files: ").fg(hidden_color), + TextSpan::new(Self::get_hidden_files_str( self.local().hidden_files_visible(), )) - .with_foreground(hidden_color) - .reversed() - .build(), + .fg(hidden_color) + .reversed(), ]; if let Some(props) = self.view.get_props(super::COMPONENT_SPAN_STATUS_BAR_LOCAL) { self.view.update( @@ -973,32 +943,23 @@ impl FileTransferActivity { let hidden_color = self.theme().transfer_status_hidden; let sync_color = self.theme().transfer_status_sync_browsing; let remote_bar_spans: Vec = vec![ - TextSpanBuilder::new("File sorting: ") - .with_foreground(sorting_color) - .build(), - TextSpanBuilder::new(Self::get_file_sorting_str(self.remote().get_file_sorting())) - .with_foreground(sorting_color) - .reversed() - .build(), - TextSpanBuilder::new(" Hidden files: ") - .with_foreground(hidden_color) - .build(), - TextSpanBuilder::new(Self::get_hidden_files_str( + TextSpan::new("File sorting: ").fg(sorting_color), + TextSpan::new(Self::get_file_sorting_str(self.remote().get_file_sorting())) + .fg(sorting_color) + .reversed(), + TextSpan::new(" Hidden files: ").fg(hidden_color), + TextSpan::new(Self::get_hidden_files_str( self.remote().hidden_files_visible(), )) - .with_foreground(hidden_color) - .reversed() - .build(), - TextSpanBuilder::new(" Sync Browsing: ") - .with_foreground(sync_color) - .build(), - TextSpanBuilder::new(match self.browser.sync_browsing { + .fg(hidden_color) + .reversed(), + TextSpan::new(" Sync Browsing: ").fg(sync_color), + TextSpan::new(match self.browser.sync_browsing { true => "ON ", false => "OFF", }) - .with_foreground(sync_color) - .reversed() - .build(), + .fg(sync_color) + .reversed(), ]; if let Some(props) = self.view.get_props(super::COMPONENT_SPAN_STATUS_BAR_REMOTE) { self.view.update( @@ -1017,253 +978,109 @@ impl FileTransferActivity { let key_color = self.theme().misc_keys; self.view.mount( super::COMPONENT_TEXT_HELP, - Box::new(Scrolltable::new( - ScrollTablePropsBuilder::default() + Box::new(List::new( + ListPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, Color::White) .with_highlighted_str(Some("?")) .with_max_scroll_step(8) .bold() - .with_table( - Some(String::from("Help")), + .scrollable(true) + .with_title("Help", Alignment::Center) + .with_rows( TableBuilder::default() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Disconnect")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from( " Switch between explorer and logs", )) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Go to previous directory")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Change explorer tab")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Move up/down in list")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Enter directory")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Upload/Download file")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Toggle hidden files")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Change file sorting mode")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Copy")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Make directory")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Go to path")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Show help")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Show info about selected file")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Reload directory content")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Select file")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Create new file")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from( " Open text file with preferred editor", )) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Quit termscp")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Rename file")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Save file as")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Go to parent directory")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from( " Open file with default application for file type", )) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from( " Open file with specified application", )) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Execute shell command")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Toggle synchronized browsing")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Delete selected file")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Select all files")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(key_color) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(key_color)) .add_col(TextSpan::from(" Interrupt file transfer")) .build(), ) diff --git a/src/ui/activities/setup/update.rs b/src/ui/activities/setup/update.rs index 0f70114..06593e8 100644 --- a/src/ui/activities/setup/update.rs +++ b/src/ui/activities/setup/update.rs @@ -74,65 +74,67 @@ impl SetupActivity { None => None, Some(msg) => match msg { // Input field - (COMPONENT_INPUT_TEXT_EDITOR, &MSG_KEY_DOWN) => { + (COMPONENT_INPUT_TEXT_EDITOR, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_RADIO_DEFAULT_PROTOCOL); None } - (COMPONENT_RADIO_DEFAULT_PROTOCOL, &MSG_KEY_DOWN) => { + (COMPONENT_RADIO_DEFAULT_PROTOCOL, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_RADIO_HIDDEN_FILES); None } - (COMPONENT_RADIO_HIDDEN_FILES, &MSG_KEY_DOWN) => { + (COMPONENT_RADIO_HIDDEN_FILES, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_RADIO_UPDATES); None } - (COMPONENT_RADIO_UPDATES, &MSG_KEY_DOWN) => { + (COMPONENT_RADIO_UPDATES, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_RADIO_GROUP_DIRS); None } - (COMPONENT_RADIO_GROUP_DIRS, &MSG_KEY_DOWN) => { + (COMPONENT_RADIO_GROUP_DIRS, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_INPUT_LOCAL_FILE_FMT); None } - (COMPONENT_INPUT_LOCAL_FILE_FMT, &MSG_KEY_DOWN) => { + (COMPONENT_INPUT_LOCAL_FILE_FMT, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_INPUT_REMOTE_FILE_FMT); None } - (COMPONENT_INPUT_REMOTE_FILE_FMT, &MSG_KEY_DOWN) => { + (COMPONENT_INPUT_REMOTE_FILE_FMT, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_INPUT_TEXT_EDITOR); None } // Input field - (COMPONENT_INPUT_REMOTE_FILE_FMT, &MSG_KEY_UP) => { + (COMPONENT_INPUT_REMOTE_FILE_FMT, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_INPUT_LOCAL_FILE_FMT); None } - (COMPONENT_INPUT_LOCAL_FILE_FMT, &MSG_KEY_UP) => { + (COMPONENT_INPUT_LOCAL_FILE_FMT, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_RADIO_GROUP_DIRS); None } - (COMPONENT_RADIO_GROUP_DIRS, &MSG_KEY_UP) => { + (COMPONENT_RADIO_GROUP_DIRS, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_RADIO_UPDATES); None } - (COMPONENT_RADIO_UPDATES, &MSG_KEY_UP) => { + (COMPONENT_RADIO_UPDATES, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_RADIO_HIDDEN_FILES); None } - (COMPONENT_RADIO_HIDDEN_FILES, &MSG_KEY_UP) => { + (COMPONENT_RADIO_HIDDEN_FILES, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_RADIO_DEFAULT_PROTOCOL); None } - (COMPONENT_RADIO_DEFAULT_PROTOCOL, &MSG_KEY_UP) => { + (COMPONENT_RADIO_DEFAULT_PROTOCOL, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_INPUT_TEXT_EDITOR); None } - (COMPONENT_INPUT_TEXT_EDITOR, &MSG_KEY_UP) => { + (COMPONENT_INPUT_TEXT_EDITOR, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_INPUT_REMOTE_FILE_FMT); None } // Error or - (COMPONENT_TEXT_ERROR, &MSG_KEY_ENTER) | (COMPONENT_TEXT_ERROR, &MSG_KEY_ESC) => { + (COMPONENT_TEXT_ERROR, key) | (COMPONENT_TEXT_ERROR, key) + if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER => + { // Umount text error self.umount_error(); None @@ -161,7 +163,9 @@ impl SetupActivity { } (COMPONENT_RADIO_QUIT, _) => None, // Close help - (COMPONENT_TEXT_HELP, &MSG_KEY_ENTER) | (COMPONENT_TEXT_HELP, &MSG_KEY_ESC) => { + (COMPONENT_TEXT_HELP, key) | (COMPONENT_TEXT_HELP, key) + if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER => + { // Umount help self.umount_help(); None @@ -189,12 +193,12 @@ impl SetupActivity { None } // Show help - (_, &MSG_KEY_CTRL_H) => { + (_, key) if key == &MSG_KEY_CTRL_H => { // Show help self.mount_help(); None } - (_, &MSG_KEY_TAB) => { + (_, key) if key == &MSG_KEY_TAB => { // Change view if let Err(err) = self.action_change_tab(ViewLayout::SshKeys) { self.mount_error(err.as_str()); @@ -202,7 +206,7 @@ impl SetupActivity { None } // Revert changes - (_, &MSG_KEY_CTRL_R) => { + (_, key) if key == &MSG_KEY_CTRL_R => { // Revert changes if let Err(err) = self.action_reset_config() { self.mount_error(err.as_str()); @@ -210,13 +214,13 @@ impl SetupActivity { None } // Save - (_, &MSG_KEY_CTRL_S) => { + (_, key) if key == &MSG_KEY_CTRL_S => { // Show save self.mount_save_popup(); None } // - (_, &MSG_KEY_ESC) => { + (_, key) if key == &MSG_KEY_ESC => { self.action_on_esc(); None } @@ -232,7 +236,9 @@ impl SetupActivity { None => None, Some(msg) => match msg { // Error or - (COMPONENT_TEXT_ERROR, &MSG_KEY_ENTER) | (COMPONENT_TEXT_ERROR, &MSG_KEY_ESC) => { + (COMPONENT_TEXT_ERROR, key) | (COMPONENT_TEXT_ERROR, key) + if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER => + { // Umount text error self.umount_error(); None @@ -261,7 +267,9 @@ impl SetupActivity { } (COMPONENT_RADIO_QUIT, _) => None, // Close help - (COMPONENT_TEXT_HELP, &MSG_KEY_ENTER) | (COMPONENT_TEXT_HELP, &MSG_KEY_ESC) => { + (COMPONENT_TEXT_HELP, key) | (COMPONENT_TEXT_HELP, key) + if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER => + { // Umount help self.umount_help(); None @@ -300,28 +308,30 @@ impl SetupActivity { (COMPONENT_RADIO_SAVE, _) => None, // Edit SSH Key // Show help - (_, &MSG_KEY_CTRL_H) => { + (_, key) if key == &MSG_KEY_CTRL_H => { // Show help self.mount_help(); None } // New key - (COMPONENT_INPUT_SSH_HOST, &MSG_KEY_DOWN) => { + (COMPONENT_INPUT_SSH_HOST, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_INPUT_SSH_USERNAME); None } - (COMPONENT_INPUT_SSH_USERNAME, &MSG_KEY_DOWN) => { + (COMPONENT_INPUT_SSH_USERNAME, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_INPUT_SSH_HOST); None } // New key - (COMPONENT_INPUT_SSH_USERNAME, &MSG_KEY_UP) - | (COMPONENT_INPUT_SSH_USERNAME, &MSG_KEY_TAB) => { + (COMPONENT_INPUT_SSH_USERNAME, key) | (COMPONENT_INPUT_SSH_USERNAME, key) + if key == &MSG_KEY_UP || key == &MSG_KEY_TAB => + { self.view.active(COMPONENT_INPUT_SSH_HOST); None } - (COMPONENT_INPUT_SSH_HOST, &MSG_KEY_UP) - | (COMPONENT_INPUT_SSH_HOST, &MSG_KEY_TAB) => { + (COMPONENT_INPUT_SSH_HOST, key) | (COMPONENT_INPUT_SSH_HOST, key) + if key == &MSG_KEY_UP || key == &MSG_KEY_TAB => + { self.view.active(COMPONENT_INPUT_SSH_USERNAME); None } @@ -335,14 +345,15 @@ impl SetupActivity { None } // New key - (COMPONENT_INPUT_SSH_HOST, &MSG_KEY_ESC) - | (COMPONENT_INPUT_SSH_USERNAME, &MSG_KEY_ESC) => { + (COMPONENT_INPUT_SSH_HOST, key) | (COMPONENT_INPUT_SSH_USERNAME, key) + if key == &MSG_KEY_ESC => + { // Umount new ssh key self.umount_new_ssh_key(); None } // New key - (COMPONENT_LIST_SSH_KEYS, &MSG_KEY_CTRL_N) => { + (COMPONENT_LIST_SSH_KEYS, key) if key == &MSG_KEY_CTRL_N => { // Show new key popup self.mount_new_ssh_key(); None @@ -356,13 +367,14 @@ impl SetupActivity { None } // Show delete - (COMPONENT_LIST_SSH_KEYS, &MSG_KEY_CTRL_E) - | (COMPONENT_LIST_SSH_KEYS, &MSG_KEY_DEL) => { + (COMPONENT_LIST_SSH_KEYS, key) | (COMPONENT_LIST_SSH_KEYS, key) + if key == &MSG_KEY_CTRL_E || key == &MSG_KEY_DEL => + { // Show delete key self.mount_del_ssh_key(); None } - (_, &MSG_KEY_TAB) => { + (_, key) if key == &MSG_KEY_TAB => { // Change view if let Err(err) = self.action_change_tab(ViewLayout::Theme) { self.mount_error(err.as_str()); @@ -370,7 +382,7 @@ impl SetupActivity { None } // Revert changes - (_, &MSG_KEY_CTRL_R) => { + (_, key) if key == &MSG_KEY_CTRL_R => { // Revert changes if let Err(err) = self.action_reset_config() { self.mount_error(err.as_str()); @@ -378,13 +390,13 @@ impl SetupActivity { None } // Save - (_, &MSG_KEY_CTRL_S) => { + (_, key) if key == &MSG_KEY_CTRL_S => { // Show save self.mount_save_popup(); None } // - (_, &MSG_KEY_ESC) => { + (_, key) if key == &MSG_KEY_ESC => { self.action_on_esc(); None } @@ -400,217 +412,217 @@ impl SetupActivity { None => None, Some(msg) => match msg { // Input fields - (COMPONENT_COLOR_AUTH_PROTOCOL, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_AUTH_PROTOCOL, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_AUTH_ADDR); None } - (COMPONENT_COLOR_AUTH_ADDR, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_AUTH_ADDR, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_AUTH_PORT); None } - (COMPONENT_COLOR_AUTH_PORT, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_AUTH_PORT, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_AUTH_USERNAME); None } - (COMPONENT_COLOR_AUTH_USERNAME, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_AUTH_USERNAME, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_AUTH_PASSWORD); None } - (COMPONENT_COLOR_AUTH_PASSWORD, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_AUTH_PASSWORD, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_AUTH_BOOKMARKS); None } - (COMPONENT_COLOR_AUTH_BOOKMARKS, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_AUTH_BOOKMARKS, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_AUTH_RECENTS); None } - (COMPONENT_COLOR_AUTH_RECENTS, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_AUTH_RECENTS, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_MISC_ERROR); None } - (COMPONENT_COLOR_MISC_ERROR, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_MISC_ERROR, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_MISC_INPUT); None } - (COMPONENT_COLOR_MISC_INPUT, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_MISC_INPUT, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_MISC_KEYS); None } - (COMPONENT_COLOR_MISC_KEYS, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_MISC_KEYS, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_MISC_QUIT); None } - (COMPONENT_COLOR_MISC_QUIT, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_MISC_QUIT, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_MISC_SAVE); None } - (COMPONENT_COLOR_MISC_SAVE, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_MISC_SAVE, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_MISC_WARN); None } - (COMPONENT_COLOR_MISC_WARN, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_MISC_WARN, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_BG); None } - (COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_BG, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_BG, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_FG); None } - (COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_FG, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_FG, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_HG); None } - (COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_HG, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_HG, key) if key == &MSG_KEY_DOWN => { self.view .active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_BG); None } - (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_BG, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_BG, key) if key == &MSG_KEY_DOWN => { self.view .active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG); None } - (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG, key) if key == &MSG_KEY_DOWN => { self.view .active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_HG); None } - (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_HG, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_HG, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_TRANSFER_PROG_BAR_FULL); None } - (COMPONENT_COLOR_TRANSFER_PROG_BAR_FULL, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_TRANSFER_PROG_BAR_FULL, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_TRANSFER_PROG_BAR_PARTIAL); None } - (COMPONENT_COLOR_TRANSFER_PROG_BAR_PARTIAL, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_TRANSFER_PROG_BAR_PARTIAL, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_TRANSFER_LOG_BG); None } - (COMPONENT_COLOR_TRANSFER_LOG_BG, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_TRANSFER_LOG_BG, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_TRANSFER_LOG_WIN); None } - (COMPONENT_COLOR_TRANSFER_LOG_WIN, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_TRANSFER_LOG_WIN, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_TRANSFER_STATUS_SORTING); None } - (COMPONENT_COLOR_TRANSFER_STATUS_SORTING, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_TRANSFER_STATUS_SORTING, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_TRANSFER_STATUS_HIDDEN); None } - (COMPONENT_COLOR_TRANSFER_STATUS_HIDDEN, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_TRANSFER_STATUS_HIDDEN, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_TRANSFER_STATUS_SYNC); None } - (COMPONENT_COLOR_TRANSFER_STATUS_SYNC, &MSG_KEY_DOWN) => { + (COMPONENT_COLOR_TRANSFER_STATUS_SYNC, key) if key == &MSG_KEY_DOWN => { self.view.active(COMPONENT_COLOR_AUTH_PROTOCOL); None } - (COMPONENT_COLOR_AUTH_PROTOCOL, &MSG_KEY_UP) => { + (COMPONENT_COLOR_AUTH_PROTOCOL, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_TRANSFER_STATUS_SYNC); None } - (COMPONENT_COLOR_AUTH_ADDR, &MSG_KEY_UP) => { + (COMPONENT_COLOR_AUTH_ADDR, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_AUTH_PROTOCOL); None } - (COMPONENT_COLOR_AUTH_PORT, &MSG_KEY_UP) => { + (COMPONENT_COLOR_AUTH_PORT, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_AUTH_ADDR); None } - (COMPONENT_COLOR_AUTH_USERNAME, &MSG_KEY_UP) => { + (COMPONENT_COLOR_AUTH_USERNAME, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_AUTH_PORT); None } - (COMPONENT_COLOR_AUTH_PASSWORD, &MSG_KEY_UP) => { + (COMPONENT_COLOR_AUTH_PASSWORD, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_AUTH_USERNAME); None } - (COMPONENT_COLOR_AUTH_BOOKMARKS, &MSG_KEY_UP) => { + (COMPONENT_COLOR_AUTH_BOOKMARKS, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_AUTH_PASSWORD); None } - (COMPONENT_COLOR_AUTH_RECENTS, &MSG_KEY_UP) => { + (COMPONENT_COLOR_AUTH_RECENTS, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_AUTH_BOOKMARKS); None } - (COMPONENT_COLOR_MISC_ERROR, &MSG_KEY_UP) => { + (COMPONENT_COLOR_MISC_ERROR, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_AUTH_RECENTS); None } - (COMPONENT_COLOR_MISC_INPUT, &MSG_KEY_UP) => { + (COMPONENT_COLOR_MISC_INPUT, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_MISC_ERROR); None } - (COMPONENT_COLOR_MISC_KEYS, &MSG_KEY_UP) => { + (COMPONENT_COLOR_MISC_KEYS, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_MISC_INPUT); None } - (COMPONENT_COLOR_MISC_QUIT, &MSG_KEY_UP) => { + (COMPONENT_COLOR_MISC_QUIT, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_MISC_KEYS); None } - (COMPONENT_COLOR_MISC_SAVE, &MSG_KEY_UP) => { + (COMPONENT_COLOR_MISC_SAVE, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_MISC_QUIT); None } - (COMPONENT_COLOR_MISC_WARN, &MSG_KEY_UP) => { + (COMPONENT_COLOR_MISC_WARN, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_MISC_SAVE); None } - (COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_BG, &MSG_KEY_UP) => { + (COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_BG, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_MISC_WARN); None } - (COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_FG, &MSG_KEY_UP) => { + (COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_FG, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_BG); None } - (COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_HG, &MSG_KEY_UP) => { + (COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_HG, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_FG); None } - (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_BG, &MSG_KEY_UP) => { + (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_BG, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_HG); None } - (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG, &MSG_KEY_UP) => { + (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG, key) if key == &MSG_KEY_UP => { self.view .active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_BG); None } - (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_HG, &MSG_KEY_UP) => { + (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_HG, key) if key == &MSG_KEY_UP => { self.view .active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG); None } - (COMPONENT_COLOR_TRANSFER_PROG_BAR_FULL, &MSG_KEY_UP) => { + (COMPONENT_COLOR_TRANSFER_PROG_BAR_FULL, key) if key == &MSG_KEY_UP => { self.view .active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_HG); None } - (COMPONENT_COLOR_TRANSFER_PROG_BAR_PARTIAL, &MSG_KEY_UP) => { + (COMPONENT_COLOR_TRANSFER_PROG_BAR_PARTIAL, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_TRANSFER_PROG_BAR_FULL); None } - (COMPONENT_COLOR_TRANSFER_LOG_BG, &MSG_KEY_UP) => { + (COMPONENT_COLOR_TRANSFER_LOG_BG, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_TRANSFER_PROG_BAR_PARTIAL); None } - (COMPONENT_COLOR_TRANSFER_LOG_WIN, &MSG_KEY_UP) => { + (COMPONENT_COLOR_TRANSFER_LOG_WIN, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_TRANSFER_LOG_BG); None } - (COMPONENT_COLOR_TRANSFER_STATUS_SORTING, &MSG_KEY_UP) => { + (COMPONENT_COLOR_TRANSFER_STATUS_SORTING, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_TRANSFER_LOG_WIN); None } - (COMPONENT_COLOR_TRANSFER_STATUS_HIDDEN, &MSG_KEY_UP) => { + (COMPONENT_COLOR_TRANSFER_STATUS_HIDDEN, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_TRANSFER_STATUS_SORTING); None } - (COMPONENT_COLOR_TRANSFER_STATUS_SYNC, &MSG_KEY_UP) => { + (COMPONENT_COLOR_TRANSFER_STATUS_SYNC, key) if key == &MSG_KEY_UP => { self.view.active(COMPONENT_COLOR_TRANSFER_STATUS_HIDDEN); None } @@ -624,7 +636,9 @@ impl SetupActivity { None } // Error or - (COMPONENT_TEXT_ERROR, &MSG_KEY_ENTER) | (COMPONENT_TEXT_ERROR, &MSG_KEY_ESC) => { + (COMPONENT_TEXT_ERROR, key) | (COMPONENT_TEXT_ERROR, key) + if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER => + { // Umount text error self.umount_error(); None @@ -653,7 +667,9 @@ impl SetupActivity { } (COMPONENT_RADIO_QUIT, _) => None, // Close help - (COMPONENT_TEXT_HELP, &MSG_KEY_ENTER) | (COMPONENT_TEXT_HELP, &MSG_KEY_ESC) => { + (COMPONENT_TEXT_HELP, key) | (COMPONENT_TEXT_HELP, key) + if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER => + { // Umount help self.umount_help(); None @@ -676,12 +692,12 @@ impl SetupActivity { (COMPONENT_RADIO_SAVE, _) => None, // Edit SSH Key // Show help - (_, &MSG_KEY_CTRL_H) => { + (_, key) if key == &MSG_KEY_CTRL_H => { // Show help self.mount_help(); None } - (_, &MSG_KEY_TAB) => { + (_, key) if key == &MSG_KEY_TAB => { // Change view if let Err(err) = self.action_change_tab(ViewLayout::SetupForm) { self.mount_error(err.as_str()); @@ -689,7 +705,7 @@ impl SetupActivity { None } // Revert changes - (_, &MSG_KEY_CTRL_R) => { + (_, key) if key == &MSG_KEY_CTRL_R => { // Revert changes if let Err(err) = self.action_reset_theme() { self.mount_error(err.as_str()); @@ -697,13 +713,13 @@ impl SetupActivity { None } // Save - (_, &MSG_KEY_CTRL_S) => { + (_, key) if key == &MSG_KEY_CTRL_S => { // Show save self.mount_save_popup(); None } // - (_, &MSG_KEY_ESC) => { + (_, key) if key == &MSG_KEY_ESC => { self.action_on_esc(); None } diff --git a/src/ui/activities/setup/view/mod.rs b/src/ui/activities/setup/view/mod.rs index a4b6784..393c1b6 100644 --- a/src/ui/activities/setup/view/mod.rs +++ b/src/ui/activities/setup/view/mod.rs @@ -34,14 +34,14 @@ use super::*; pub use setup::*; pub use ssh_keys::*; pub use theme::*; -// Locals -use crate::ui::components::msgbox::{MsgBox, MsgBoxPropsBuilder}; // Ext -use tuirealm::components::{ +use tui_realm_stdlib::{ + list::{List, ListPropsBuilder}, + paragraph::{Paragraph, ParagraphPropsBuilder}, radio::{Radio, RadioPropsBuilder}, - scrolltable::{ScrollTablePropsBuilder, Scrolltable}, + span::{Span, SpanPropsBuilder}, }; -use tuirealm::props::{PropsBuilder, TableBuilder, TextSpan, TextSpanBuilder}; +use tuirealm::props::{Alignment, PropsBuilder, TableBuilder, TextSpan}; use tuirealm::tui::{ style::Color, widgets::{BorderType, Borders}, @@ -79,12 +79,13 @@ impl SetupActivity { // Mount self.view.mount( super::COMPONENT_TEXT_ERROR, - Box::new(MsgBox::new( - MsgBoxPropsBuilder::default() + Box::new(Paragraph::new( + ParagraphPropsBuilder::default() .with_foreground(Color::Red) .bold() .with_borders(Borders::ALL, BorderType::Rounded, Color::Red) - .with_texts(None, vec![TextSpan::from(text)]) + .with_texts(vec![TextSpan::from(text)]) + .with_text_alignment(Alignment::Center) .build(), )), ); @@ -110,16 +111,15 @@ impl SetupActivity { .with_color(Color::LightRed) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightRed) - .with_options( - Some(String::from( - "There are unsaved changes! Save changes before leaving?", - )), - vec![ - String::from("Save"), - String::from("Don't save"), - String::from("Cancel"), - ], + .with_title( + "There are unsaved changes! Save changes before leaving?", + Alignment::Center, ) + .with_options(&[ + String::from("Save"), + String::from("Don't save"), + String::from("Cancel"), + ]) .build(), )), ); @@ -145,10 +145,8 @@ impl SetupActivity { .with_color(Color::LightYellow) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightYellow) - .with_options( - Some(String::from("Save changes?")), - vec![String::from("Yes"), String::from("No")], - ) + .with_title("Save changes?", Alignment::Center) + .with_options(&[String::from("Yes"), String::from("No")]) .build(), )), ); @@ -163,91 +161,81 @@ impl SetupActivity { self.view.umount(super::COMPONENT_RADIO_SAVE); } + pub(self) fn mount_header_tab(&mut self, idx: usize) { + self.view.mount( + super::COMPONENT_RADIO_TAB, + Box::new(Radio::new( + RadioPropsBuilder::default() + .with_color(Color::LightYellow) + .with_inverted_color(Color::Black) + .with_borders(Borders::BOTTOM, BorderType::Thick, Color::White) + .with_options(&[ + String::from("User Interface"), + String::from("SSH Keys"), + String::from("Theme"), + ]) + .with_value(idx) + .build(), + )), + ); + } + + pub(self) fn mount_footer(&mut self) { + self.view.mount( + super::COMPONENT_TEXT_FOOTER, + Box::new(Span::new( + SpanPropsBuilder::default() + .with_spans(vec![ + TextSpan::new("Press ").bold(), + TextSpan::new("").bold().fg(Color::Cyan), + TextSpan::new(" to show keybindings").bold(), + ]) + .build(), + )), + ); + } + /// ### mount_help /// /// Mount help pub(super) fn mount_help(&mut self) { self.view.mount( super::COMPONENT_TEXT_HELP, - Box::new(Scrolltable::new( - ScrollTablePropsBuilder::default() + Box::new(List::new( + ListPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, Color::White) .with_highlighted_str(Some("?")) .with_max_scroll_step(8) .bold() - .with_table( - Some(String::from("Help")), + .with_title("Help", Alignment::Center) + .scrollable(true) + .with_rows( TableBuilder::default() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(Color::Cyan) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(Color::Cyan)) .add_col(TextSpan::from(" Exit setup")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(Color::Cyan) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(Color::Cyan)) .add_col(TextSpan::from(" Change setup page")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(Color::Cyan) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(Color::Cyan)) .add_col(TextSpan::from(" Change cursor")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(Color::Cyan) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(Color::Cyan)) .add_col(TextSpan::from(" Change input field")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(Color::Cyan) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(Color::Cyan)) .add_col(TextSpan::from(" Select / Dismiss popup")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(Color::Cyan) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(Color::Cyan)) .add_col(TextSpan::from(" Delete SSH key")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(Color::Cyan) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(Color::Cyan)) .add_col(TextSpan::from(" New SSH key")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(Color::Cyan) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(Color::Cyan)) .add_col(TextSpan::from(" Revert changes")) .add_row() - .add_col( - TextSpanBuilder::new("") - .bold() - .with_foreground(Color::Cyan) - .build(), - ) + .add_col(TextSpan::new("").bold().fg(Color::Cyan)) .add_col(TextSpan::from(" Save configuration")) .build(), ) diff --git a/src/ui/activities/setup/view/setup.rs b/src/ui/activities/setup/view/setup.rs index 9a8c316..b97b690 100644 --- a/src/ui/activities/setup/view/setup.rs +++ b/src/ui/activities/setup/view/setup.rs @@ -33,10 +33,9 @@ use crate::fs::explorer::GroupDirs; use crate::utils::ui::draw_area_in; // Ext use std::path::PathBuf; -use tuirealm::components::{ +use tui_realm_stdlib::{ input::{Input, InputPropsBuilder}, radio::{Radio, RadioPropsBuilder}, - span::{Span, SpanPropsBuilder}, }; use tuirealm::tui::{ layout::{Constraint, Direction, Layout}, @@ -44,7 +43,7 @@ use tuirealm::tui::{ widgets::{BorderType, Borders, Clear}, }; use tuirealm::{ - props::{PropsBuilder, TextSpanBuilder}, + props::{Alignment, PropsBuilder}, Payload, Value, View, }; @@ -59,41 +58,9 @@ impl SetupActivity { self.view = View::init(); // Common stuff // Radio tab - self.view.mount( - super::COMPONENT_RADIO_TAB, - Box::new(Radio::new( - RadioPropsBuilder::default() - .with_color(Color::LightYellow) - .with_inverted_color(Color::Black) - .with_borders(Borders::BOTTOM, BorderType::Thick, Color::White) - .with_options( - None, - vec![ - String::from("User Interface"), - String::from("SSH Keys"), - String::from("Theme"), - ], - ) - .with_value(0) - .build(), - )), - ); + self.mount_header_tab(0); // Footer - self.view.mount( - super::COMPONENT_TEXT_FOOTER, - Box::new(Span::new( - SpanPropsBuilder::default() - .with_spans(vec![ - TextSpanBuilder::new("Press ").bold().build(), - TextSpanBuilder::new("") - .bold() - .with_foreground(Color::Cyan) - .build(), - TextSpanBuilder::new(" to show keybindings").bold().build(), - ]) - .build(), - )), - ); + self.mount_footer(); // Input fields self.view.mount( super::COMPONENT_INPUT_TEXT_EDITOR, @@ -101,7 +68,7 @@ impl SetupActivity { InputPropsBuilder::default() .with_foreground(Color::LightGreen) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightGreen) - .with_label(String::from("Text editor")) + .with_label("Text editor", Alignment::Left) .build(), )), ); @@ -113,15 +80,13 @@ impl SetupActivity { .with_color(Color::LightCyan) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightCyan) - .with_options( - Some(String::from("Default file transfer protocol")), - vec![ - String::from("SFTP"), - String::from("SCP"), - String::from("FTP"), - String::from("FTPS"), - ], - ) + .with_title("Default file transfer protocol", Alignment::Left) + .with_options(&[ + String::from("SFTP"), + String::from("SCP"), + String::from("FTP"), + String::from("FTPS"), + ]) .build(), )), ); @@ -132,10 +97,8 @@ impl SetupActivity { .with_color(Color::LightRed) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightRed) - .with_options( - Some(String::from("Show hidden files (by default)")), - vec![String::from("Yes"), String::from("No")], - ) + .with_title("Show hidden files (by default)?", Alignment::Left) + .with_options(&[String::from("Yes"), String::from("No")]) .build(), )), ); @@ -146,10 +109,8 @@ impl SetupActivity { .with_color(Color::LightYellow) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightYellow) - .with_options( - Some(String::from("Check for updates?")), - vec![String::from("Yes"), String::from("No")], - ) + .with_title("Check for updates?", Alignment::Left) + .with_options(&[String::from("Yes"), String::from("No")]) .build(), )), ); @@ -160,14 +121,12 @@ impl SetupActivity { .with_color(Color::LightMagenta) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightMagenta) - .with_options( - Some(String::from("Group directories")), - vec![ - String::from("Display first"), - String::from("Display Last"), - String::from("No"), - ], - ) + .with_title("Group directories", Alignment::Left) + .with_options(&[ + String::from("Display first"), + String::from("Display Last"), + String::from("No"), + ]) .build(), )), ); @@ -177,7 +136,7 @@ impl SetupActivity { InputPropsBuilder::default() .with_foreground(Color::LightBlue) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightBlue) - .with_label(String::from("File formatter syntax (local)")) + .with_label("File formatter syntax (local)", Alignment::Left) .build(), )), ); @@ -187,7 +146,7 @@ impl SetupActivity { InputPropsBuilder::default() .with_foreground(Color::LightGreen) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightGreen) - .with_label(String::from("File formatter syntax (remote)")) + .with_label("File formatter syntax (remote)", Alignment::Left) .build(), )), ); diff --git a/src/ui/activities/setup/view/ssh_keys.rs b/src/ui/activities/setup/view/ssh_keys.rs index 3517178..7b6ba5c 100644 --- a/src/ui/activities/setup/view/ssh_keys.rs +++ b/src/ui/activities/setup/view/ssh_keys.rs @@ -31,10 +31,9 @@ use super::{Context, SetupActivity}; use crate::ui::components::bookmark_list::{BookmarkList, BookmarkListPropsBuilder}; use crate::utils::ui::draw_area_in; // Ext -use tuirealm::components::{ +use tui_realm_stdlib::{ input::{Input, InputPropsBuilder}, radio::{Radio, RadioPropsBuilder}, - span::{Span, SpanPropsBuilder}, }; use tuirealm::tui::{ layout::{Constraint, Direction, Layout}, @@ -42,7 +41,7 @@ use tuirealm::tui::{ widgets::{BorderType, Borders, Clear}, }; use tuirealm::{ - props::{PropsBuilder, TextSpanBuilder}, + props::{Alignment, PropsBuilder}, View, }; @@ -57,46 +56,15 @@ impl SetupActivity { self.view = View::init(); // Common stuff // Radio tab - self.view.mount( - super::COMPONENT_RADIO_TAB, - Box::new(Radio::new( - RadioPropsBuilder::default() - .with_color(Color::LightYellow) - .with_inverted_color(Color::Black) - .with_borders(Borders::BOTTOM, BorderType::Thick, Color::LightYellow) - .with_options( - None, - vec![ - String::from("User Interface"), - String::from("SSH Keys"), - String::from("Theme"), - ], - ) - .with_value(1) - .build(), - )), - ); + // Radio tab + self.mount_header_tab(1); // Footer - self.view.mount( - super::COMPONENT_TEXT_FOOTER, - Box::new(Span::new( - SpanPropsBuilder::default() - .with_spans(vec![ - TextSpanBuilder::new("Press ").bold().build(), - TextSpanBuilder::new("") - .bold() - .with_foreground(Color::Cyan) - .build(), - TextSpanBuilder::new(" to show keybindings").bold().build(), - ]) - .build(), - )), - ); + self.mount_footer(); self.view.mount( super::COMPONENT_LIST_SSH_KEYS, Box::new(BookmarkList::new( BookmarkListPropsBuilder::default() - .with_bookmarks(Some(String::from("SSH Keys")), vec![]) + .with_title("SSH keys", Alignment::Left) .with_borders(Borders::ALL, BorderType::Plain, Color::LightGreen) .with_background(Color::LightGreen) .with_foreground(Color::Black) @@ -211,10 +179,8 @@ impl SetupActivity { .with_color(Color::LightRed) .with_inverted_color(Color::Black) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightRed) - .with_options( - Some(String::from("Delete key?")), - vec![String::from("Yes"), String::from("No")], - ) + .with_title("Delete key?", Alignment::Center) + .with_options(&[String::from("Yes"), String::from("No")]) .with_value(1) // Default: No .build(), )), @@ -238,7 +204,7 @@ impl SetupActivity { super::COMPONENT_INPUT_SSH_HOST, Box::new(Input::new( InputPropsBuilder::default() - .with_label(String::from("Hostname or address")) + .with_label("Hostname or address", Alignment::Center) .with_borders( Borders::TOP | Borders::RIGHT | Borders::LEFT, BorderType::Plain, @@ -251,7 +217,7 @@ impl SetupActivity { super::COMPONENT_INPUT_SSH_USERNAME, Box::new(Input::new( InputPropsBuilder::default() - .with_label(String::from("Username")) + .with_label("Username", Alignment::Center) .with_borders( Borders::BOTTOM | Borders::RIGHT | Borders::LEFT, BorderType::Plain, @@ -287,7 +253,7 @@ impl SetupActivity { }) .collect(); let props = BookmarkListPropsBuilder::from(props) - .with_bookmarks(Some(String::from("SSH Keys")), keys) + .with_bookmarks(keys) .build(); self.view.update(super::COMPONENT_LIST_SSH_KEYS, props); } diff --git a/src/ui/activities/setup/view/theme.rs b/src/ui/activities/setup/view/theme.rs index 5bb092b..e3af5dc 100644 --- a/src/ui/activities/setup/view/theme.rs +++ b/src/ui/activities/setup/view/theme.rs @@ -33,18 +33,14 @@ use crate::ui::components::color_picker::{ColorPicker, ColorPickerPropsBuilder}; use crate::utils::parser::parse_color; use crate::utils::ui::draw_area_in; // Ext -use tuirealm::components::{ - label::{Label, LabelPropsBuilder}, - radio::{Radio, RadioPropsBuilder}, - span::{Span, SpanPropsBuilder}, -}; +use tui_realm_stdlib::label::{Label, LabelPropsBuilder}; use tuirealm::tui::{ layout::{Constraint, Direction, Layout}, style::Color, widgets::{BorderType, Borders, Clear}, }; use tuirealm::{ - props::{PropsBuilder, TextSpanBuilder}, + props::{Alignment, PropsBuilder}, Payload, Value, View, }; @@ -59,41 +55,9 @@ impl SetupActivity { self.view = View::init(); // Common stuff // Radio tab - self.view.mount( - super::COMPONENT_RADIO_TAB, - Box::new(Radio::new( - RadioPropsBuilder::default() - .with_color(Color::LightYellow) - .with_inverted_color(Color::Black) - .with_borders(Borders::BOTTOM, BorderType::Thick, Color::White) - .with_options( - None, - vec![ - String::from("User Interface"), - String::from("SSH Keys"), - String::from("Theme"), - ], - ) - .with_value(2) - .build(), - )), - ); + self.mount_header_tab(2); // Footer - self.view.mount( - super::COMPONENT_TEXT_FOOTER, - Box::new(Span::new( - SpanPropsBuilder::default() - .with_spans(vec![ - TextSpanBuilder::new("Press ").bold().build(), - TextSpanBuilder::new("") - .bold() - .with_foreground(Color::Cyan) - .build(), - TextSpanBuilder::new(" to show keybindings").bold().build(), - ]) - .build(), - )), - ); + self.mount_footer(); // auth colors self.mount_title(super::COMPONENT_COLOR_AUTH_TITLE, "Authentication styles"); self.mount_color_picker(super::COMPONENT_COLOR_AUTH_PROTOCOL, "Protocol"); @@ -653,7 +617,7 @@ impl SetupActivity { Box::new(ColorPicker::new( ColorPickerPropsBuilder::default() .with_borders(Borders::ALL, BorderType::Rounded, Color::Reset) - .with_label(label.to_string()) + .with_label(label.to_string(), Alignment::Left) .build(), )), ); diff --git a/src/ui/components/bookmark_list.rs b/src/ui/components/bookmark_list.rs index a541db7..01d81c0 100644 --- a/src/ui/components/bookmark_list.rs +++ b/src/ui/components/bookmark_list.rs @@ -26,18 +26,19 @@ * SOFTWARE. */ // ext -use tuirealm::components::utils::get_block; +use tui_realm_stdlib::utils::get_block; use tuirealm::event::{Event, KeyCode}; -use tuirealm::props::{BordersProps, Props, PropsBuilder, TextParts, TextSpan}; +use tuirealm::props::{Alignment, BlockTitle, BordersProps, Props, PropsBuilder}; use tuirealm::tui::{ layout::{Corner, Rect}, style::{Color, Style}, text::Span, widgets::{BorderType, Borders, List, ListItem, ListState}, }; -use tuirealm::{Canvas, Component, Msg, Payload, Value}; +use tuirealm::{Component, Frame, Msg, Payload, PropPayload, PropValue, Value}; // -- props +const PROP_BOOKMARKS: &str = "bookmarks"; pub struct BookmarkListPropsBuilder { props: Option, @@ -117,10 +118,19 @@ impl BookmarkListPropsBuilder { self } - pub fn with_bookmarks(&mut self, title: Option, bookmarks: Vec) -> &mut Self { + pub fn with_title>(&mut self, text: S, alignment: Alignment) -> &mut Self { if let Some(props) = self.props.as_mut() { - let bookmarks: Vec = bookmarks.into_iter().map(TextSpan::from).collect(); - props.texts = TextParts::new(title, Some(bookmarks)); + props.title = Some(BlockTitle::new(text, alignment)); + } + self + } + + pub fn with_bookmarks(&mut self, bookmarks: Vec) -> &mut Self { + if let Some(props) = self.props.as_mut() { + let bookmarks: Vec = bookmarks.into_iter().map(PropValue::Str).collect(); + props + .own + .insert(PROP_BOOKMARKS, PropPayload::Vec(bookmarks)); } self } @@ -210,25 +220,30 @@ impl BookmarkList { // Initialize states let mut states: OwnStates = OwnStates::default(); // Set list length - states.set_list_len(match &props.texts.spans { - Some(tokens) => tokens.len(), - None => 0, - }); + states.set_list_len(Self::bookmarks_len(&props)); BookmarkList { props, states } } + + fn bookmarks_len(props: &Props) -> usize { + match props.own.get(PROP_BOOKMARKS) { + None => 0, + Some(bookmarks) => bookmarks.unwrap_vec().len(), + } + } } impl Component for BookmarkList { #[cfg(not(tarpaulin_include))] - fn render(&self, render: &mut Canvas, area: Rect) { + fn render(&self, render: &mut Frame, area: Rect) { if self.props.visible { // Make list - let list_item: Vec = match self.props.texts.spans.as_ref() { - None => vec![], - Some(lines) => lines + let list_item: Vec = match self.props.own.get(PROP_BOOKMARKS) { + Some(PropPayload::Vec(lines)) => lines .iter() - .map(|line| ListItem::new(Span::from(line.content.to_string()))) + .map(|x| x.unwrap_str()) + .map(|x| ListItem::new(Span::from(x.to_string()))) .collect(), + _ => vec![], }; let (fg, bg): (Color, Color) = match self.states.focus { true => (self.props.foreground, self.props.background), @@ -241,7 +256,7 @@ impl Component for BookmarkList { List::new(list_item) .block(get_block( &self.props.borders, - &self.props.texts.title, + self.props.title.as_ref(), self.states.focus, )) .start_corner(Corner::TopLeft) @@ -260,10 +275,7 @@ impl Component for BookmarkList { fn update(&mut self, props: Props) -> Msg { self.props = props; // re-Set list length - self.states.set_list_len(match &self.props.texts.spans { - Some(tokens) => tokens.len(), - None => 0, - }); + self.states.set_list_len(Self::bookmarks_len(&self.props)); // Reset list index self.states.reset_list_index(); Msg::None @@ -347,20 +359,24 @@ mod tests { .with_foreground(Color::Red) .with_background(Color::Blue) .with_borders(Borders::ALL, BorderType::Double, Color::Red) - .with_bookmarks( - Some(String::from("filelist")), - vec![String::from("file1"), String::from("file2")], - ) + .with_title("filelist", Alignment::Left) + .with_bookmarks(vec![String::from("file1"), String::from("file2")]) .build(), ); assert_eq!(component.props.foreground, Color::Red); assert_eq!(component.props.background, Color::Blue); assert_eq!(component.props.visible, true); + assert_eq!(component.props.title.as_ref().unwrap().text(), "filelist"); assert_eq!( - component.props.texts.title.as_ref().unwrap().as_str(), - "filelist" + component + .props + .own + .get(PROP_BOOKMARKS) + .unwrap() + .unwrap_vec() + .len(), + 2 ); - assert_eq!(component.props.texts.spans.as_ref().unwrap().len(), 2); // Verify states assert_eq!(component.states.list_index, 0); assert_eq!(component.states.list_len, 2); @@ -384,14 +400,11 @@ mod tests { // Update component.update( BookmarkListPropsBuilder::from(component.get_props()) - .with_bookmarks( - Some(String::from("filelist")), - vec![ - String::from("file1"), - String::from("file2"), - String::from("file3"), - ], - ) + .with_bookmarks(vec![ + String::from("file1"), + String::from("file2"), + String::from("file3"), + ]) .build(), ); // Verify states diff --git a/src/ui/components/color_picker.rs b/src/ui/components/color_picker.rs index 2fc9df8..c1ba2bb 100644 --- a/src/ui/components/color_picker.rs +++ b/src/ui/components/color_picker.rs @@ -30,15 +30,15 @@ use crate::utils::fmt::fmt_color; use crate::utils::parser::parse_color; // ext -use tuirealm::components::input::{Input, InputPropsBuilder}; +use tui_realm_stdlib::input::{Input, InputPropsBuilder}; use tuirealm::event::Event; -use tuirealm::props::{Props, PropsBuilder}; +use tuirealm::props::{Alignment, Props, PropsBuilder}; use tuirealm::tui::{ layout::Rect, style::Color, widgets::{BorderType, Borders}, }; -use tuirealm::{Canvas, Component, Msg, Payload, Value}; +use tuirealm::{Component, Frame, Msg, Payload, Value}; // -- props @@ -98,8 +98,8 @@ impl ColorPickerPropsBuilder { /// ### with_label /// /// Set input label - pub fn with_label(&mut self, label: String) -> &mut Self { - self.puppet.with_label(label); + pub fn with_label>(&mut self, label: S, alignment: Alignment) -> &mut Self { + self.puppet.with_label(label, alignment); self } @@ -149,7 +149,7 @@ impl Component for ColorPicker { /// Based on the current properties and states, renders a widget using the provided render engine in the provided Area /// If focused, cursor is also set (if supported by widget) #[cfg(not(tarpaulin_include))] - fn render(&self, render: &mut Canvas, area: Rect) { + fn render(&self, render: &mut Frame, area: Rect) { self.input.render(render, area); } @@ -260,6 +260,7 @@ mod test { .visible() .with_color(&Color::Rgb(204, 170, 0)) .with_borders(Borders::ALL, BorderType::Double, Color::Rgb(204, 170, 0)) + .with_label("omar", Alignment::Left) .build(), ); // Focus diff --git a/src/ui/components/file_list.rs b/src/ui/components/file_list.rs index a0db059..9600659 100644 --- a/src/ui/components/file_list.rs +++ b/src/ui/components/file_list.rs @@ -26,10 +26,10 @@ * SOFTWARE. */ // ext -use tuirealm::components::utils::get_block; +use tui_realm_stdlib::utils::get_block; use tuirealm::event::{Event, KeyCode, KeyModifiers}; use tuirealm::props::{ - BordersProps, PropPayload, PropValue, Props, PropsBuilder, TextParts, TextSpan, + Alignment, BlockTitle, BordersProps, PropPayload, PropValue, Props, PropsBuilder, }; use tuirealm::tui::{ layout::{Corner, Rect}, @@ -37,11 +37,12 @@ use tuirealm::tui::{ text::Span, widgets::{BorderType, Borders, List, ListItem, ListState}, }; -use tuirealm::{Canvas, Component, Msg, Payload, Value}; +use tuirealm::{Component, Frame, Msg, Payload, Value}; // -- props -const PROP_HIGHLIGHT_COLOR: &str = "props-highlight-color"; +const PROP_FILES: &str = "files"; +const PALETTE_HIGHLIGHT_COLOR: &str = "props-highlight-color"; pub struct FileListPropsBuilder { props: Option, @@ -107,10 +108,7 @@ impl FileListPropsBuilder { /// Set highlighted color pub fn with_highlight_color(&mut self, color: Color) -> &mut Self { if let Some(props) = self.props.as_mut() { - props.own.insert( - PROP_HIGHLIGHT_COLOR, - PropPayload::One(PropValue::Color(color)), - ); + props.palette.insert(PALETTE_HIGHLIGHT_COLOR, color); } self } @@ -134,10 +132,17 @@ impl FileListPropsBuilder { self } - pub fn with_files(&mut self, title: Option, files: Vec) -> &mut Self { + pub fn with_title>(&mut self, text: S, alignment: Alignment) -> &mut Self { if let Some(props) = self.props.as_mut() { - let files: Vec = files.into_iter().map(TextSpan::from).collect(); - props.texts = TextParts::new(title, Some(files)); + props.title = Some(BlockTitle::new(text, alignment)); + } + self + } + + pub fn with_files(&mut self, files: Vec) -> &mut Self { + if let Some(props) = self.props.as_mut() { + let files: Vec = files.into_iter().map(PropValue::Str).collect(); + props.own.insert(PROP_FILES, PropPayload::Vec(files)); } self } @@ -299,32 +304,39 @@ impl FileList { // Initialize states let mut states: OwnStates = OwnStates::default(); // Init list states - states.init_list_states(props.texts.spans.as_ref().map(|x| x.len()).unwrap_or(0)); + states.init_list_states(Self::files_len(&props)); FileList { props, states } } + + fn files_len(props: &Props) -> usize { + match props.own.get(PROP_FILES) { + None => 0, + Some(files) => files.unwrap_vec().len(), + } + } } impl Component for FileList { #[cfg(not(tarpaulin_include))] - fn render(&self, render: &mut Canvas, area: Rect) { + fn render(&self, render: &mut Frame, area: Rect) { if self.props.visible { // Make list - let list_item: Vec = match self.props.texts.spans.as_ref() { - None => vec![], - Some(lines) => lines + let list_item: Vec = match self.props.own.get(PROP_FILES) { + Some(PropPayload::Vec(lines)) => lines .iter() .enumerate() .map(|(num, line)| { let to_display: String = match self.states.is_selected(num) { - true => format!("*{}", line.content), - false => line.content.to_string(), + true => format!("*{}", line.unwrap_str()), + false => line.unwrap_str().to_string(), }; ListItem::new(Span::from(to_display)) }) .collect(), + _ => vec![], }; - let highlighted_color: Color = match self.props.own.get(PROP_HIGHLIGHT_COLOR) { - Some(PropPayload::One(PropValue::Color(c))) => *c, + let highlighted_color: Color = match self.props.palette.get(PALETTE_HIGHLIGHT_COLOR) { + Some(c) => *c, _ => Color::Reset, }; let (h_fg, h_bg): (Color, Color) = match self.states.focus { @@ -338,7 +350,7 @@ impl Component for FileList { List::new(list_item) .block(get_block( &self.props.borders, - &self.props.texts.title, + self.props.title.as_ref(), self.states.focus, )) .start_corner(Corner::TopLeft) @@ -362,14 +374,7 @@ impl Component for FileList { fn update(&mut self, props: Props) -> Msg { self.props = props; // re-Set list states - self.states.init_list_states( - self.props - .texts - .spans - .as_ref() - .map(|x| x.len()) - .unwrap_or(0), - ); + self.states.init_list_states(Self::files_len(&self.props)); Msg::None } @@ -551,24 +556,33 @@ mod tests { .with_background(Color::Blue) .with_highlight_color(Color::LightRed) .with_borders(Borders::ALL, BorderType::Double, Color::Red) - .with_files( - Some(String::from("files")), - vec![String::from("file1"), String::from("file2")], - ) + .with_title("files", Alignment::Left) + .with_files(vec![String::from("file1"), String::from("file2")]) .build(), ); assert_eq!( - *component.props.own.get(PROP_HIGHLIGHT_COLOR).unwrap(), - PropPayload::One(PropValue::Color(Color::LightRed)) + *component + .props + .palette + .get(PALETTE_HIGHLIGHT_COLOR) + .unwrap(), + Color::LightRed ); assert_eq!(component.props.foreground, Color::Red); assert_eq!(component.props.background, Color::Blue); assert_eq!(component.props.visible, true); + assert_eq!(component.props.title.as_ref().unwrap().text(), "files"); assert_eq!( - component.props.texts.title.as_ref().unwrap().as_str(), - "files" + component + .props + .own + .get(PROP_FILES) + .as_ref() + .unwrap() + .unwrap_vec() + .len(), + 2 ); - assert_eq!(component.props.texts.spans.as_ref().unwrap().len(), 2); // Verify states assert_eq!(component.states.list_index, 0); assert_eq!(component.states.selected.len(), 0); @@ -594,14 +608,11 @@ mod tests { // Update component.update( FileListPropsBuilder::from(component.get_props()) - .with_files( - Some(String::from("filelist")), - vec![ - String::from("file1"), - String::from("file2"), - String::from("file3"), - ], - ) + .with_files(vec![ + String::from("file1"), + String::from("file2"), + String::from("file3"), + ]) .build(), ); // Verify states @@ -670,14 +681,11 @@ mod tests { // Make component let mut component: FileList = FileList::new( FileListPropsBuilder::default() - .with_files( - Some(String::from("files")), - vec![ - String::from("file1"), - String::from("file2"), - String::from("file3"), - ], - ) + .with_files(vec![ + String::from("file1"), + String::from("file2"), + String::from("file3"), + ]) .build(), ); // Get state @@ -735,10 +743,7 @@ mod tests { // Update files component.update( FileListPropsBuilder::from(component.get_props()) - .with_files( - Some(String::from("filelist")), - vec![String::from("file1"), String::from("file2")], - ) + .with_files(vec![String::from("file1"), String::from("file2")]) .build(), ); // Selection should now be empty diff --git a/src/ui/components/logbox.rs b/src/ui/components/logbox.rs index 8e134a5..69f5117 100644 --- a/src/ui/components/logbox.rs +++ b/src/ui/components/logbox.rs @@ -26,18 +26,22 @@ * SOFTWARE. */ // ext -use tuirealm::components::utils::{get_block, wrap_spans}; +use tui_realm_stdlib::utils::{get_block, wrap_spans}; use tuirealm::event::{Event, KeyCode}; -use tuirealm::props::{BordersProps, Props, PropsBuilder, Table as TextTable, TextParts}; +use tuirealm::props::{ + Alignment, BlockTitle, BordersProps, Props, PropsBuilder, Table as TextTable, +}; use tuirealm::tui::{ layout::{Corner, Rect}, style::{Color, Style}, widgets::{BorderType, Borders, List, ListItem, ListState}, }; -use tuirealm::{Canvas, Component, Msg, Payload, Value}; +use tuirealm::{Component, Frame, Msg, Payload, PropPayload, PropValue, Value}; // -- props +const PROP_TABLE: &str = "table"; + pub struct LogboxPropsBuilder { props: Option, } @@ -106,9 +110,18 @@ impl LogboxPropsBuilder { self } - pub fn with_log(&mut self, title: Option, table: TextTable) -> &mut Self { + pub fn with_title>(&mut self, text: S, alignment: Alignment) -> &mut Self { if let Some(props) = self.props.as_mut() { - props.texts = TextParts::table(title, table); + props.title = Some(BlockTitle::new(text, alignment)); + } + self + } + + pub fn with_log(&mut self, table: TextTable) -> &mut Self { + if let Some(props) = self.props.as_mut() { + props + .own + .insert(PROP_TABLE, PropPayload::One(PropValue::Table(table))); } self } @@ -198,33 +211,37 @@ impl LogBox { // Initialize states let mut states: OwnStates = OwnStates::default(); // Set list length - states.set_list_len(match &props.texts.table { - Some(rows) => rows.len(), - None => 0, - }); + states.set_list_len(Self::table_len(&props)); // Reset list index states.reset_list_index(); LogBox { props, states } } + + fn table_len(props: &Props) -> usize { + match props.own.get(PROP_TABLE) { + Some(PropPayload::One(PropValue::Table(table))) => table.len(), + _ => 0, + } + } } impl Component for LogBox { #[cfg(not(tarpaulin_include))] - fn render(&self, render: &mut Canvas, area: Rect) { + fn render(&self, render: &mut Frame, area: Rect) { if self.props.visible { let width: usize = area.width as usize - 4; // Make list - let list_items: Vec = match self.props.texts.table.as_ref() { - None => Vec::new(), - Some(table) => table + let list_items: Vec = match self.props.own.get(PROP_TABLE) { + Some(PropPayload::One(PropValue::Table(table))) => table .iter() .map(|row| ListItem::new(wrap_spans(row, width, &self.props))) .collect(), // Make List item from TextSpan + _ => Vec::new(), }; let w = List::new(list_items) .block(get_block( &self.props.borders, - &self.props.texts.title, + self.props.title.as_ref(), self.states.focus, )) .start_corner(Corner::BottomLeft) @@ -240,10 +257,7 @@ impl Component for LogBox { fn update(&mut self, props: Props) -> Msg { self.props = props; // re-Set list length - self.states.set_list_len(match &self.props.texts.table { - Some(rows) => rows.len(), - None => 0, - }); + self.states.set_list_len(Self::table_len(&self.props)); // Reset list index self.states.reset_list_index(); Msg::None @@ -323,8 +337,8 @@ mod tests { .visible() .with_borders(Borders::ALL, BorderType::Double, Color::Red) .with_background(Color::Blue) + .with_title("log", Alignment::Left) .with_log( - Some(String::from("Log")), TableBuilder::default() .add_col(TextSpan::from("12:29")) .add_col(TextSpan::from("system crashed")) @@ -337,11 +351,7 @@ mod tests { ); assert_eq!(component.props.visible, true); assert_eq!(component.props.background, Color::Blue); - assert_eq!( - component.props.texts.title.as_ref().unwrap().as_str(), - "Log" - ); - assert_eq!(component.props.texts.table.as_ref().unwrap().len(), 2); + assert_eq!(component.props.title.as_ref().unwrap().text(), "Log"); // Verify states assert_eq!(component.states.list_index, 0); assert_eq!(component.states.list_len, 2); @@ -364,7 +374,6 @@ mod tests { component.update( LogboxPropsBuilder::from(component.get_props()) .with_log( - Some(String::from("Log")), TableBuilder::default() .add_col(TextSpan::from("12:29")) .add_col(TextSpan::from("system crashed")) diff --git a/src/ui/components/mod.rs b/src/ui/components/mod.rs index a613ff9..bcb878a 100644 --- a/src/ui/components/mod.rs +++ b/src/ui/components/mod.rs @@ -30,4 +30,3 @@ pub mod bookmark_list; pub mod color_picker; pub mod file_list; pub mod logbox; -pub mod msgbox; diff --git a/src/ui/components/msgbox.rs b/src/ui/components/msgbox.rs deleted file mode 100644 index 226864a..0000000 --- a/src/ui/components/msgbox.rs +++ /dev/null @@ -1,268 +0,0 @@ -//! ## MsgBox -//! -//! `MsgBox` component renders a simple readonly no event associated centered text - -/** - * MIT License - * - * termscp - Copyright (c) 2021 Christian Visintin - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -// locals -use crate::utils::fmt::align_text_center; -// ext -use tuirealm::components::utils::{get_block, use_or_default_styles}; -use tuirealm::event::Event; -use tuirealm::props::{BordersProps, Props, PropsBuilder, TextParts, TextSpan}; -use tuirealm::tui::{ - layout::{Corner, Rect}, - style::{Color, Modifier, Style}, - text::{Span, Spans}, - widgets::{BorderType, Borders, List, ListItem}, -}; -use tuirealm::{Canvas, Component, Msg, Payload}; - -// -- Props - -pub struct MsgBoxPropsBuilder { - props: Option, -} - -impl Default for MsgBoxPropsBuilder { - fn default() -> Self { - MsgBoxPropsBuilder { - props: Some(Props::default()), - } - } -} - -impl PropsBuilder for MsgBoxPropsBuilder { - fn build(&mut self) -> Props { - self.props.take().unwrap() - } - - fn hidden(&mut self) -> &mut Self { - if let Some(props) = self.props.as_mut() { - props.visible = false; - } - self - } - - fn visible(&mut self) -> &mut Self { - if let Some(props) = self.props.as_mut() { - props.visible = true; - } - self - } -} - -impl From for MsgBoxPropsBuilder { - fn from(props: Props) -> Self { - MsgBoxPropsBuilder { props: Some(props) } - } -} - -impl MsgBoxPropsBuilder { - pub fn with_foreground(&mut self, color: Color) -> &mut Self { - if let Some(props) = self.props.as_mut() { - props.foreground = color; - } - self - } - - pub fn bold(&mut self) -> &mut Self { - if let Some(props) = self.props.as_mut() { - props.modifiers |= Modifier::BOLD; - } - self - } - - pub fn blink(&mut self) -> &mut Self { - if let Some(props) = self.props.as_mut() { - props.modifiers |= Modifier::SLOW_BLINK; - } - self - } - - pub fn with_borders( - &mut self, - borders: Borders, - variant: BorderType, - color: Color, - ) -> &mut Self { - if let Some(props) = self.props.as_mut() { - props.borders = BordersProps { - borders, - variant, - color, - } - } - self - } - - pub fn with_texts(&mut self, title: Option, texts: Vec) -> &mut Self { - if let Some(props) = self.props.as_mut() { - props.texts = TextParts::new(title, Some(texts)); - } - self - } -} - -// -- component - -pub struct MsgBox { - props: Props, -} - -impl MsgBox { - /// ### new - /// - /// Instantiate a new Text component - pub fn new(props: Props) -> Self { - MsgBox { props } - } -} - -impl Component for MsgBox { - #[cfg(not(tarpaulin_include))] - fn render(&self, render: &mut Canvas, area: Rect) { - // Make a Span - if self.props.visible { - let lines: Vec = match self.props.texts.spans.as_ref() { - None => Vec::new(), - Some(rows) => { - let mut lines: Vec = Vec::new(); - for line in rows.iter() { - // Keep line color, or use default - let (fg, bg, modifiers) = use_or_default_styles(&self.props, line); - let message_row = - textwrap::wrap(line.content.as_str(), area.width as usize); - for msg in message_row.iter() { - lines.push(ListItem::new(Spans::from(vec![Span::styled( - align_text_center(msg, area.width), - Style::default().add_modifier(modifiers).fg(fg).bg(bg), - )]))); - } - } - lines - } - }; - render.render_widget( - List::new(lines) - .block(get_block( - &self.props.borders, - &self.props.texts.title, - true, - )) - .start_corner(Corner::TopLeft) - .style( - Style::default() - .fg(self.props.foreground) - .bg(self.props.background), - ), - area, - ); - } - } - - fn update(&mut self, props: Props) -> Msg { - self.props = props; - // Return None - Msg::None - } - - fn get_props(&self) -> Props { - self.props.clone() - } - - fn on(&mut self, ev: Event) -> Msg { - // Return key - if let Event::Key(key) = ev { - Msg::OnKey(key) - } else { - Msg::None - } - } - - fn get_state(&self) -> Payload { - Payload::None - } - - fn blur(&mut self) {} - - fn active(&mut self) {} -} - -#[cfg(test)] -mod tests { - - use super::*; - - use pretty_assertions::assert_eq; - use tuirealm::event::{KeyCode, KeyEvent}; - use tuirealm::props::{TextSpan, TextSpanBuilder}; - use tuirealm::tui::style::Color; - - #[test] - fn test_ui_components_msgbox() { - let mut component: MsgBox = MsgBox::new( - MsgBoxPropsBuilder::default() - .hidden() - .visible() - .with_foreground(Color::Red) - .bold() - .blink() - .with_borders(Borders::ALL, BorderType::Double, Color::Red) - .with_texts( - None, - vec![ - TextSpan::from("Press "), - TextSpanBuilder::new("") - .with_foreground(Color::Cyan) - .bold() - .build(), - TextSpan::from(" to quit"), - ], - ) - .build(), - ); - assert_eq!(component.props.foreground, Color::Red); - assert!(component.props.modifiers.intersects(Modifier::BOLD)); - assert_eq!(component.props.visible, true); - assert_eq!(component.props.texts.spans.as_ref().unwrap().len(), 3); - component.active(); - component.blur(); - // Update - let props = MsgBoxPropsBuilder::from(component.get_props()) - .hidden() - .with_foreground(Color::Yellow) - .build(); - assert_eq!(component.update(props), Msg::None); - assert_eq!(component.props.visible, false); - assert_eq!(component.props.foreground, Color::Yellow); - // Get value - assert_eq!(component.get_state(), Payload::None); - // Event - assert_eq!( - component.on(Event::Key(KeyEvent::from(KeyCode::Delete))), - Msg::OnKey(KeyEvent::from(KeyCode::Delete)) - ); - } -} diff --git a/src/utils/fmt.rs b/src/utils/fmt.rs index 703cd91..44f8f6a 100644 --- a/src/utils/fmt.rs +++ b/src/utils/fmt.rs @@ -100,23 +100,6 @@ pub fn fmt_millis(duration: Duration) -> String { format!("{}.{:0width$}", seconds, millis, width = 3) } -/// align_text_center -/// -/// Align text to center for a given width -pub fn align_text_center(text: &str, width: u16) -> String { - let indent_size: usize = match (width as usize) >= text.len() { - // NOTE: The check prevents underflow - true => (width as usize - text.len()) / 2, - false => 0, - }; - textwrap::indent( - text, - (0..indent_size).map(|_| " ").collect::().as_str(), - ) - .trim_end() - .to_string() -} - /// ### elide_path /// /// Elide a path if longer than width @@ -362,18 +345,6 @@ mod tests { ); } - #[test] - fn test_utils_align_text_center() { - assert_eq!( - align_text_center("hello world!", 24), - String::from(" hello world!") - ); - // Bad case - assert_eq!( - align_text_center("hello world!", 8), - String::from("hello world!") - ); - } #[test] fn test_utils_fmt_millis() { assert_eq!(