Updated dependencies; migrated tui-realm to 0.6.0

This commit is contained in:
veeso
2021-08-17 12:38:24 +02:00
parent 1558f4ffe4
commit d15997cca0
21 changed files with 863 additions and 1413 deletions

View File

@@ -22,7 +22,17 @@
## 0.6.1 ## 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 ## 0.6.0

176
Cargo.lock generated
View File

@@ -94,9 +94,9 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]] [[package]]
name = "bitflags" name = "bitflags"
version = "1.2.1" version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]] [[package]]
name = "block-buffer" name = "block-buffer"
@@ -138,9 +138,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
[[package]] [[package]]
name = "bytesize" name = "bytesize"
version = "1.0.1" version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81a18687293a1546b67c246452202bbbf143d239cb43494cc163da14979082da" checksum = "6c58ec36aac5066d5ca17df51b3e70279f5670a72102f5752cb7e7c856adfc70"
[[package]] [[package]]
name = "cassowary" name = "cassowary"
@@ -150,9 +150,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.68" version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787" checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@@ -264,34 +264,34 @@ dependencies = [
[[package]] [[package]]
name = "crossterm" name = "crossterm"
version = "0.19.0" version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7c36c10130df424b2f3552fcc2ddcd9b28a27b1e54b358b45874f88d1ca6888c" checksum = "c0ebde6a9dd5e331cd6c6f48253254d117642c31653baa475e394657c59c1f7d"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"crossterm_winapi", "crossterm_winapi",
"lazy_static",
"libc", "libc",
"mio", "mio",
"parking_lot 0.11.1", "parking_lot 0.11.1",
"signal-hook", "signal-hook",
"signal-hook-mio",
"winapi", "winapi",
] ]
[[package]] [[package]]
name = "crossterm_winapi" name = "crossterm_winapi"
version = "0.7.0" version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0da8964ace4d3e4a044fd027919b2237000b24315a37c916f61809f1ff2140b9" checksum = "3a6966607622438301997d3dac0d2f6e9a90c68bb6bc1785ea98456ab93c0507"
dependencies = [ dependencies = [
"winapi", "winapi",
] ]
[[package]] [[package]]
name = "crypto-mac" name = "crypto-mac"
version = "0.10.0" version = "0.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4857fd85a0c34b3c3297875b747c1e02e06b6a0ea32dd892d8192b9ce0813ea6" checksum = "bff07008ec701e8028e2ceb8f83f0e4274ee62bd2dbdc4fefff2e9a91824081a"
dependencies = [ dependencies = [
"generic-array", "generic-array",
"subtle", "subtle",
@@ -506,9 +506,9 @@ dependencies = [
[[package]] [[package]]
name = "instant" name = "instant"
version = "0.1.9" version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec" checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
] ]
@@ -521,9 +521,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.51" version = "0.3.52"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" checksum = "ce791b7ca6638aae45be056e068fc756d871eb3b3b10b8efa62d1c9cec616752"
dependencies = [ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
@@ -548,9 +548,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.98" version = "0.2.99"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
[[package]] [[package]]
name = "libssh2-sys" name = "libssh2-sys"
@@ -630,9 +630,9 @@ checksum = "ffbee8634e0d45d258acb448e7eaab3fce7a0a467395d4d9f228e3c1f01fb2e4"
[[package]] [[package]]
name = "matches" name = "matches"
version = "0.1.8" version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]] [[package]]
name = "md-5" name = "md-5"
@@ -675,9 +675,9 @@ dependencies = [
[[package]] [[package]]
name = "native-tls" name = "native-tls"
version = "0.2.7" version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d"
dependencies = [ dependencies = [
"lazy_static", "lazy_static",
"libc", "libc",
@@ -790,11 +790,11 @@ checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5"
[[package]] [[package]]
name = "open" name = "open"
version = "1.7.0" version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1711eb4b31ce4ad35b0f316d8dfba4fe5c7ad601c448446d84aae7a896627b20" checksum = "b46b233de7d83bc167fe43ae2dda3b5b84e80e09cceba581e4decb958a4896bf"
dependencies = [ dependencies = [
"which", "pathdiff",
"winapi", "winapi",
] ]
@@ -884,7 +884,7 @@ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"instant", "instant",
"libc", "libc",
"redox_syscall 0.2.9", "redox_syscall 0.2.10",
"smallvec", "smallvec",
"winapi", "winapi",
] ]
@@ -895,6 +895,12 @@ version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cacbb3c4ff353b534a67fb8d7524d00229da4cb1dc8c79f4db96e375ab5b619" checksum = "3cacbb3c4ff353b534a67fb8d7524d00229da4cb1dc8c79f4db96e375ab5b619"
[[package]]
name = "pathdiff"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "877630b3de15c0b64cc52f659345724fbf6bdad9bd9566699fc53688f3c34a34"
[[package]] [[package]]
name = "percent-encoding" name = "percent-encoding"
version = "2.1.0" version = "2.1.0"
@@ -927,9 +933,9 @@ dependencies = [
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.27" version = "1.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0d8caf72986c1a598726adc988bb5984792ef84f5ee5aa50209145ee8077038" checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
dependencies = [ dependencies = [
"unicode-xid", "unicode-xid",
] ]
@@ -1032,9 +1038,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
[[package]] [[package]]
name = "redox_syscall" name = "redox_syscall"
version = "0.2.9" version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff"
dependencies = [ dependencies = [
"bitflags", "bitflags",
] ]
@@ -1046,7 +1052,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
dependencies = [ dependencies = [
"getrandom 0.2.3", "getrandom 0.2.3",
"redox_syscall 0.2.9", "redox_syscall 0.2.10",
] ]
[[package]] [[package]]
@@ -1209,18 +1215,18 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.126" version = "1.0.127"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" checksum = "f03b9878abf6d14e6779d3f24f07b2cfa90352cfec4acc5aab8f1ac7f146fae8"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.126" version = "1.0.127"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" checksum = "a024926d3432516606328597e0f224a51355a493b49fdd67e9209187cbe55ecc"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -1229,9 +1235,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.64" version = "1.0.66"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@@ -1253,13 +1259,23 @@ dependencies = [
[[package]] [[package]]
name = "signal-hook" name = "signal-hook"
version = "0.1.17" version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index" 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 = [ dependencies = [
"libc", "libc",
"mio", "mio",
"signal-hook-registry", "signal-hook",
] ]
[[package]] [[package]]
@@ -1314,15 +1330,15 @@ dependencies = [
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.4.0" version = "2.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e81da0851ada1f3e9d4312c704aa4f8806f0f9d69faaf8df2f3464b4a9437c2" checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601"
[[package]] [[package]]
name = "syn" name = "syn"
version = "1.0.73" version = "1.0.74"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f71489ff30030d2ae598524f61326b902466f72a0fb1a8564c001cc63425bcc7" checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -1338,7 +1354,7 @@ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"libc", "libc",
"rand 0.8.4", "rand 0.8.4",
"redox_syscall 0.2.9", "redox_syscall 0.2.10",
"remove_dir_all", "remove_dir_all",
"winapi", "winapi",
] ]
@@ -1383,6 +1399,7 @@ dependencies = [
"textwrap", "textwrap",
"thiserror", "thiserror",
"toml", "toml",
"tui-realm-stdlib",
"tuirealm", "tuirealm",
"ureq", "ureq",
"users", "users",
@@ -1445,9 +1462,9 @@ dependencies = [
[[package]] [[package]]
name = "tinyvec" name = "tinyvec"
version = "1.2.0" version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b5220f05bb7de7f3f53c7c065e1199b3172696fe2db9f9c4d8ad9b4ee74c342" checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338"
dependencies = [ dependencies = [
"tinyvec_macros", "tinyvec_macros",
] ]
@@ -1469,9 +1486,9 @@ dependencies = [
[[package]] [[package]]
name = "tui" name = "tui"
version = "0.15.0" version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "861d8f3ad314ede6219bcb2ab844054b1de279ee37a9bc38e3d606f9d3fb2a71" checksum = "39c8ce4e27049eed97cfa363a5048b09d995e209994634a0efc26a14ab6c0c23"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"cassowary", "cassowary",
@@ -1481,15 +1498,24 @@ dependencies = [
] ]
[[package]] [[package]]
name = "tuirealm" name = "tui-realm-stdlib"
version = "0.4.3" version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" 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 = [ dependencies = [
"crossterm", "crossterm",
"textwrap",
"tui", "tui",
"unicode-width",
] ]
[[package]] [[package]]
@@ -1500,18 +1526,15 @@ checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06"
[[package]] [[package]]
name = "unicode-bidi" name = "unicode-bidi"
version = "0.3.5" version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085"
dependencies = [
"matches",
]
[[package]] [[package]]
name = "unicode-linebreak" name = "unicode-linebreak"
version = "0.1.1" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05a31f45d18a3213b918019f78fe6a73a14ab896807f0aaf5622aa0684749455" checksum = "3a52dcaab0c48d931f7cc8ef826fa51690a08e1ea55117ef26f89864f532383f"
dependencies = [ dependencies = [
"regex", "regex",
] ]
@@ -1615,9 +1638,9 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.74" version = "0.2.75"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" checksum = "b608ecc8f4198fe8680e2ed18eccab5f0cd4caaf3d83516fa5fb2e927fda2586"
dependencies = [ dependencies = [
"cfg-if 1.0.0", "cfg-if 1.0.0",
"wasm-bindgen-macro", "wasm-bindgen-macro",
@@ -1625,9 +1648,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-backend" name = "wasm-bindgen-backend"
version = "0.2.74" version = "0.2.75"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" checksum = "580aa3a91a63d23aac5b6b267e2d13cb4f363e31dce6c352fca4752ae12e479f"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"lazy_static", "lazy_static",
@@ -1640,9 +1663,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.74" version = "0.2.75"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" checksum = "171ebf0ed9e1458810dfcb31f2e766ad6b3a89dbda42d8901f2b268277e5f09c"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@@ -1650,9 +1673,9 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.74" version = "0.2.75"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" checksum = "6c2657dd393f03aa2a659c25c6ae18a13a4048cebd220e147933ea837efc589f"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -1663,15 +1686,15 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.74" version = "0.2.75"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" checksum = "2e0c4a743a309662d45f4ede961d7afa4ba4131a59a639f29b0069c3798bbcc2"
[[package]] [[package]]
name = "web-sys" name = "web-sys"
version = "0.3.51" version = "0.3.52"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" checksum = "01c70a82d842c9979078c772d4a1344685045f1a5628f677c2b2eab4dd7d2696"
dependencies = [ dependencies = [
"js-sys", "js-sys",
"wasm-bindgen", "wasm-bindgen",
@@ -1698,11 +1721,12 @@ dependencies = [
[[package]] [[package]]
name = "which" name = "which"
version = "4.1.0" version = "4.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b55551e42cbdf2ce2bedd2203d0cc08dba002c27510f86dab6d0ce304cba3dfe" checksum = "ea187a8ef279bc014ec368c27a920da2024d2a711109bfbe3440585d5cf27ad9"
dependencies = [ dependencies = [
"either", "either",
"lazy_static",
"libc", "libc",
] ]

View File

@@ -28,11 +28,11 @@ path = "src/main.rs"
[dependencies] [dependencies]
argh = "0.1.5" argh = "0.1.5"
bitflags = "1.2.1" bitflags = "1.3.2"
bytesize = "1.0.1" bytesize = "1.1.0"
chrono = "0.4.19" chrono = "0.4.19"
content_inspector = "0.2.4" content_inspector = "0.2.4"
crossterm = "0.19.0" crossterm = "0.20"
dirs = "3.0.1" dirs = "3.0.1"
edit = "0.1.3" edit = "0.1.3"
ftp4 = { version = "4.0.2", features = [ "secure" ] } ftp4 = { version = "4.0.2", features = [ "secure" ] }
@@ -41,7 +41,7 @@ keyring = { version = "0.10.1", optional = true }
lazy_static = "1.4.0" lazy_static = "1.4.0"
log = "0.4.14" log = "0.4.14"
magic-crypt = "3.1.7" magic-crypt = "3.1.7"
open = "1.7.0" open = "2.0.1"
rand = "0.8.4" rand = "0.8.4"
regex = "1.5.4" regex = "1.5.4"
rpassword = "5.0.1" rpassword = "5.0.1"
@@ -52,7 +52,8 @@ tempfile = "3.1.0"
textwrap = "0.14.2" textwrap = "0.14.2"
thiserror = "^1.0.0" thiserror = "^1.0.0"
toml = "0.5.8" 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" ] } ureq = { version = "2.1.0", features = [ "json" ] }
whoami = "1.1.1" whoami = "1.1.1"
wildmatch = "2.0.0" wildmatch = "2.0.0"

View File

@@ -56,6 +56,7 @@ extern crate regex;
extern crate ssh2; extern crate ssh2;
extern crate tempfile; extern crate tempfile;
extern crate textwrap; extern crate textwrap;
extern crate tui_realm_stdlib;
extern crate tuirealm; extern crate tuirealm;
extern crate ureq; extern crate ureq;
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]

View File

@@ -32,7 +32,7 @@ use crate::system::environment;
// Ext // Ext
use std::path::PathBuf; use std::path::PathBuf;
use tuirealm::components::{input::InputPropsBuilder, radio::RadioPropsBuilder}; use tui_realm_stdlib::{input::InputPropsBuilder, radio::RadioPropsBuilder};
use tuirealm::{Payload, PropsBuilder, Value}; use tuirealm::{Payload, PropsBuilder, Value};
impl AuthActivity { impl AuthActivity {

View File

@@ -35,7 +35,7 @@ use super::{
COMPONENT_TEXT_HELP, COMPONENT_TEXT_NEW_VERSION_NOTES, COMPONENT_TEXT_SIZE_ERR, COMPONENT_TEXT_HELP, COMPONENT_TEXT_NEW_VERSION_NOTES, COMPONENT_TEXT_SIZE_ERR,
}; };
use crate::ui::keymap::*; use crate::ui::keymap::*;
use tuirealm::components::InputPropsBuilder; use tui_realm_stdlib::InputPropsBuilder;
use tuirealm::{Msg, Payload, PropsBuilder, Update, Value}; use tuirealm::{Msg, Payload, PropsBuilder, Update, Value};
// -- update // -- update
@@ -52,53 +52,53 @@ impl Update for AuthActivity {
None => None, // Exit after None None => None, // Exit after None
Some(msg) => match msg { Some(msg) => match msg {
// Focus ( DOWN ) // Focus ( DOWN )
(COMPONENT_RADIO_PROTOCOL, &MSG_KEY_DOWN) => { (COMPONENT_RADIO_PROTOCOL, key) if key == &MSG_KEY_DOWN => {
// Give focus to port // Give focus to port
self.view.active(COMPONENT_INPUT_ADDR); self.view.active(COMPONENT_INPUT_ADDR);
None None
} }
(COMPONENT_INPUT_ADDR, &MSG_KEY_DOWN) => { (COMPONENT_INPUT_ADDR, key) if key == &MSG_KEY_DOWN => {
// Give focus to port // Give focus to port
self.view.active(COMPONENT_INPUT_PORT); self.view.active(COMPONENT_INPUT_PORT);
None None
} }
(COMPONENT_INPUT_PORT, &MSG_KEY_DOWN) => { (COMPONENT_INPUT_PORT, key) if key == &MSG_KEY_DOWN => {
// Give focus to port // Give focus to port
self.view.active(COMPONENT_INPUT_USERNAME); self.view.active(COMPONENT_INPUT_USERNAME);
None None
} }
(COMPONENT_INPUT_USERNAME, &MSG_KEY_DOWN) => { (COMPONENT_INPUT_USERNAME, key) if key == &MSG_KEY_DOWN => {
// Give focus to port // Give focus to port
self.view.active(COMPONENT_INPUT_PASSWORD); self.view.active(COMPONENT_INPUT_PASSWORD);
None None
} }
(COMPONENT_INPUT_PASSWORD, &MSG_KEY_DOWN) => { (COMPONENT_INPUT_PASSWORD, key) if key == &MSG_KEY_DOWN => {
// Give focus to port // Give focus to port
self.view.active(COMPONENT_RADIO_PROTOCOL); self.view.active(COMPONENT_RADIO_PROTOCOL);
None None
} }
// Focus ( UP ) // Focus ( UP )
(COMPONENT_INPUT_PASSWORD, &MSG_KEY_UP) => { (COMPONENT_INPUT_PASSWORD, key) if key == &MSG_KEY_UP => {
// Give focus to port // Give focus to port
self.view.active(COMPONENT_INPUT_USERNAME); self.view.active(COMPONENT_INPUT_USERNAME);
None None
} }
(COMPONENT_INPUT_USERNAME, &MSG_KEY_UP) => { (COMPONENT_INPUT_USERNAME, key) if key == &MSG_KEY_UP => {
// Give focus to port // Give focus to port
self.view.active(COMPONENT_INPUT_PORT); self.view.active(COMPONENT_INPUT_PORT);
None None
} }
(COMPONENT_INPUT_PORT, &MSG_KEY_UP) => { (COMPONENT_INPUT_PORT, key) if key == &MSG_KEY_UP => {
// Give focus to port // Give focus to port
self.view.active(COMPONENT_INPUT_ADDR); self.view.active(COMPONENT_INPUT_ADDR);
None None
} }
(COMPONENT_INPUT_ADDR, &MSG_KEY_UP) => { (COMPONENT_INPUT_ADDR, key) if key == &MSG_KEY_UP => {
// Give focus to port // Give focus to port
self.view.active(COMPONENT_RADIO_PROTOCOL); self.view.active(COMPONENT_RADIO_PROTOCOL);
None None
} }
(COMPONENT_RADIO_PROTOCOL, &MSG_KEY_UP) => { (COMPONENT_RADIO_PROTOCOL, key) if key == &MSG_KEY_UP => {
// Give focus to port // Give focus to port
self.view.active(COMPONENT_INPUT_PASSWORD); self.view.active(COMPONENT_INPUT_PASSWORD);
None None
@@ -118,25 +118,25 @@ impl Update for AuthActivity {
} }
// Bookmarks commands // Bookmarks commands
// <RIGHT> / <LEFT> // <RIGHT> / <LEFT>
(COMPONENT_BOOKMARKS_LIST, &MSG_KEY_RIGHT) => { (COMPONENT_BOOKMARKS_LIST, key) if key == &MSG_KEY_RIGHT => {
// Give focus to recents // Give focus to recents
self.view.active(COMPONENT_RECENTS_LIST); self.view.active(COMPONENT_RECENTS_LIST);
None None
} }
(COMPONENT_RECENTS_LIST, &MSG_KEY_LEFT) => { (COMPONENT_RECENTS_LIST, key) if key == &MSG_KEY_LEFT => {
// Give focus to bookmarks // Give focus to bookmarks
self.view.active(COMPONENT_BOOKMARKS_LIST); self.view.active(COMPONENT_BOOKMARKS_LIST);
None None
} }
// <DEL | 'E'> // <DEL | 'E'>
(COMPONENT_BOOKMARKS_LIST, &MSG_KEY_DEL) (COMPONENT_BOOKMARKS_LIST, key)
| (COMPONENT_BOOKMARKS_LIST, &MSG_KEY_CHAR_E) => { if key == &MSG_KEY_DEL || key == &MSG_KEY_CHAR_E =>
{
// Show delete popup // Show delete popup
self.mount_bookmark_del_dialog(); self.mount_bookmark_del_dialog();
None None
} }
(COMPONENT_RECENTS_LIST, &MSG_KEY_DEL) (COMPONENT_RECENTS_LIST, key) if key == &MSG_KEY_DEL || key == &MSG_KEY_CHAR_E => {
| (COMPONENT_RECENTS_LIST, &MSG_KEY_CHAR_E) => {
// Show delete popup // Show delete popup
self.mount_recent_del_dialog(); self.mount_recent_del_dialog();
None None
@@ -203,67 +203,68 @@ impl Update for AuthActivity {
} }
} }
// <ESC> hide tab // <ESC> 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(); self.umount_recent_del_dialog();
None None
} }
(COMPONENT_RADIO_BOOKMARK_DEL_RECENT, _) => 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(); self.umount_bookmark_del_dialog();
None None
} }
(COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK, _) => None, (COMPONENT_RADIO_BOOKMARK_DEL_BOOKMARK, _) => None,
// Error message // 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 // Umount text error
self.umount_error(); self.umount_error();
None None
} }
(COMPONENT_TEXT_ERROR, _) => None, (COMPONENT_TEXT_ERROR, _) => None,
(COMPONENT_TEXT_NEW_VERSION_NOTES, &MSG_KEY_ESC) (COMPONENT_TEXT_NEW_VERSION_NOTES, key)
| (COMPONENT_TEXT_NEW_VERSION_NOTES, &MSG_KEY_ENTER) => { if key == &MSG_KEY_ESC || key == &MSG_KEY_ENTER =>
{
// Umount release notes // Umount release notes
self.umount_release_notes(); self.umount_release_notes();
None None
} }
(COMPONENT_TEXT_NEW_VERSION_NOTES, _) => None, (COMPONENT_TEXT_NEW_VERSION_NOTES, _) => None,
// Help // Help
(_, &MSG_KEY_CTRL_H) => { (_, key) if key == &MSG_KEY_CTRL_H => {
// Show help // Show help
self.mount_help(); self.mount_help();
None None
} }
// Release notes // Release notes
(_, &MSG_KEY_CTRL_R) => { (_, key) if key == &MSG_KEY_CTRL_R => {
// Show release notes // Show release notes
self.mount_release_notes(); self.mount_release_notes();
None 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 // Hide text help
self.umount_help(); self.umount_help();
None None
} }
(COMPONENT_TEXT_HELP, _) => None, (COMPONENT_TEXT_HELP, _) => None,
// Enter setup // Enter setup
(_, &MSG_KEY_CTRL_C) => { (_, key) if key == &MSG_KEY_CTRL_C => {
self.exit_reason = Some(super::ExitReason::EnterSetup); self.exit_reason = Some(super::ExitReason::EnterSetup);
None None
} }
// Save bookmark; show popup // Save bookmark; show popup
(_, &MSG_KEY_CTRL_S) => { (_, key) if key == &MSG_KEY_CTRL_S => {
// Show popup // Show popup
self.mount_bookmark_save_dialog(); self.mount_bookmark_save_dialog();
// Give focus to bookmark name // Give focus to bookmark name
self.view.active(COMPONENT_INPUT_BOOKMARK_NAME); self.view.active(COMPONENT_INPUT_BOOKMARK_NAME);
None None
} }
(COMPONENT_INPUT_BOOKMARK_NAME, &MSG_KEY_DOWN) => { (COMPONENT_INPUT_BOOKMARK_NAME, key) if key == &MSG_KEY_DOWN => {
// Give focus to pwd // Give focus to pwd
self.view.active(COMPONENT_RADIO_BOOKMARK_SAVE_PWD); self.view.active(COMPONENT_RADIO_BOOKMARK_SAVE_PWD);
None None
} }
(COMPONENT_RADIO_BOOKMARK_SAVE_PWD, &MSG_KEY_UP) => { (COMPONENT_RADIO_BOOKMARK_SAVE_PWD, key) if key == &MSG_KEY_UP => {
// Give focus to pwd // Give focus to pwd
self.view.active(COMPONENT_INPUT_BOOKMARK_NAME); self.view.active(COMPONENT_INPUT_BOOKMARK_NAME);
None None
@@ -291,8 +292,9 @@ impl Update for AuthActivity {
self.view_bookmarks() self.view_bookmarks()
} }
// Hide save bookmark // Hide save bookmark
(COMPONENT_INPUT_BOOKMARK_NAME, &MSG_KEY_ESC) (COMPONENT_INPUT_BOOKMARK_NAME, key) | (COMPONENT_RADIO_BOOKMARK_SAVE_PWD, key)
| (COMPONENT_RADIO_BOOKMARK_SAVE_PWD, &MSG_KEY_ESC) => { if key == &MSG_KEY_ESC =>
{
// Umount popup // Umount popup
self.umount_bookmark_save_dialog(); self.umount_bookmark_save_dialog();
None None
@@ -307,45 +309,30 @@ impl Update for AuthActivity {
self.umount_quit(); self.umount_quit();
None None
} }
(COMPONENT_RADIO_QUIT, &MSG_KEY_ESC) => { (COMPONENT_RADIO_QUIT, key) if key == &MSG_KEY_ESC => {
self.umount_quit(); self.umount_quit();
None None
} }
// -- text size error; block everything // -- text size error; block everything
(COMPONENT_TEXT_SIZE_ERR, _) => None, (COMPONENT_TEXT_SIZE_ERR, _) => None,
// <TAB> bookmarks // <TAB> bookmarks
(COMPONENT_BOOKMARKS_LIST, &MSG_KEY_TAB) (COMPONENT_BOOKMARKS_LIST, key) | (COMPONENT_RECENTS_LIST, key)
| (COMPONENT_RECENTS_LIST, &MSG_KEY_TAB) => { if key == &MSG_KEY_TAB =>
{
// Give focus to address // Give focus to address
self.view.active(COMPONENT_INPUT_ADDR); self.view.active(COMPONENT_INPUT_ADDR);
None None
} }
// Any <TAB>, go to bookmarks // Any <TAB>, go to bookmarks
(_, &MSG_KEY_TAB) => { (_, key) if key == &MSG_KEY_TAB => {
self.view.active(COMPONENT_BOOKMARKS_LIST); self.view.active(COMPONENT_BOOKMARKS_LIST);
None None
} }
// On submit on any unhandled (connect) // On submit on any unhandled (connect)
(_, Msg::OnSubmit(_)) | (_, &MSG_KEY_ENTER) => { (_, Msg::OnSubmit(_)) => self.on_unhandled_submit(),
// Validate fields (_, key) if key == &MSG_KEY_ENTER => self.on_unhandled_submit(),
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
}
// <ESC> => Quit // <ESC> => Quit
(_, &MSG_KEY_ESC) => { (_, key) if key == &MSG_KEY_ESC => {
self.mount_quit(); self.mount_quit();
None 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
}
} }

View File

@@ -27,17 +27,15 @@
*/ */
// Locals // Locals
use super::{AuthActivity, Context, FileTransferProtocol}; use super::{AuthActivity, Context, FileTransferProtocol};
use crate::ui::components::{ use crate::ui::components::bookmark_list::{BookmarkList, BookmarkListPropsBuilder};
bookmark_list::{BookmarkList, BookmarkListPropsBuilder},
msgbox::{MsgBox, MsgBoxPropsBuilder},
};
use crate::utils::ui::draw_area_in; use crate::utils::ui::draw_area_in;
// Ext // Ext
use tuirealm::components::{ use tui_realm_stdlib::{
input::{Input, InputPropsBuilder}, input::{Input, InputPropsBuilder},
label::{Label, LabelPropsBuilder}, label::{Label, LabelPropsBuilder},
list::{List, ListPropsBuilder},
paragraph::{Paragraph, ParagraphPropsBuilder},
radio::{Radio, RadioPropsBuilder}, radio::{Radio, RadioPropsBuilder},
scrolltable::{ScrollTablePropsBuilder, Scrolltable},
span::{Span, SpanPropsBuilder}, span::{Span, SpanPropsBuilder},
textarea::{Textarea, TextareaPropsBuilder}, textarea::{Textarea, TextareaPropsBuilder},
}; };
@@ -47,7 +45,7 @@ use tuirealm::tui::{
widgets::{BorderType, Borders, Clear}, widgets::{BorderType, Borders, Clear},
}; };
use tuirealm::{ use tuirealm::{
props::{InputType, PropsBuilder, TableBuilder, TextSpan, TextSpanBuilder}, props::{Alignment, InputType, PropsBuilder, TableBuilder, TextSpan},
Msg, Payload, Value, Msg, Payload, Value,
}; };
@@ -91,19 +89,11 @@ impl AuthActivity {
Box::new(Span::new( Box::new(Span::new(
SpanPropsBuilder::default() SpanPropsBuilder::default()
.with_spans(vec![ .with_spans(vec![
TextSpanBuilder::new("Press ").bold().build(), TextSpan::new("Press ").bold(),
TextSpanBuilder::new("<CTRL+H>") TextSpan::new("<CTRL+H>").bold().fg(key_color),
.bold() TextSpan::new(" to show keybindings; ").bold(),
.with_foreground(key_color) TextSpan::new("<CTRL+C>").bold().fg(key_color),
.build(), TextSpan::new(" to enter setup").bold(),
TextSpanBuilder::new(" to show keybindings; ")
.bold()
.build(),
TextSpanBuilder::new("<CTRL+C>")
.bold()
.with_foreground(key_color)
.build(),
TextSpanBuilder::new(" to enter setup").bold().build(),
]) ])
.build(), .build(),
)), )),
@@ -118,15 +108,8 @@ impl AuthActivity {
.with_color(protocol_color) .with_color(protocol_color)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Rounded, protocol_color) .with_borders(Borders::ALL, BorderType::Rounded, protocol_color)
.with_options( .with_title("Protocol", Alignment::Left)
Some(String::from("Protocol")), .with_options(&["SFTP", "SCP", "FTP", "FTPS"])
vec![
String::from("SFTP"),
String::from("SCP"),
String::from("FTP"),
String::from("FTPS"),
],
)
.with_value(Self::protocol_enum_to_opt(default_protocol)) .with_value(Self::protocol_enum_to_opt(default_protocol))
.build(), .build(),
)), )),
@@ -138,7 +121,7 @@ impl AuthActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_foreground(addr_color) .with_foreground(addr_color)
.with_borders(Borders::ALL, BorderType::Rounded, addr_color) .with_borders(Borders::ALL, BorderType::Rounded, addr_color)
.with_label(String::from("Remote host")) .with_label("Remote host", Alignment::Left)
.build(), .build(),
)), )),
); );
@@ -149,7 +132,7 @@ impl AuthActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_foreground(port_color) .with_foreground(port_color)
.with_borders(Borders::ALL, BorderType::Rounded, 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(InputType::Number)
.with_input_len(5) .with_input_len(5)
.with_value(Self::get_default_port_for_protocol(default_protocol).to_string()) .with_value(Self::get_default_port_for_protocol(default_protocol).to_string())
@@ -163,7 +146,7 @@ impl AuthActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_foreground(username_color) .with_foreground(username_color)
.with_borders(Borders::ALL, BorderType::Rounded, username_color) .with_borders(Borders::ALL, BorderType::Rounded, username_color)
.with_label(String::from("Username")) .with_label("Username", Alignment::Left)
.build(), .build(),
)), )),
); );
@@ -174,7 +157,7 @@ impl AuthActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_foreground(password_color) .with_foreground(password_color)
.with_borders(Borders::ALL, BorderType::Rounded, password_color) .with_borders(Borders::ALL, BorderType::Rounded, password_color)
.with_label(String::from("Password")) .with_label("Password", Alignment::Left)
.with_input(InputType::Password) .with_input(InputType::Password)
.build(), .build(),
)), )),
@@ -193,7 +176,7 @@ impl AuthActivity {
.with_foreground(Color::Yellow) .with_foreground(Color::Yellow)
.with_spans(vec![ .with_spans(vec![
TextSpan::from("termscp "), 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 <https://veeso.github.io/termscp/>; view release notes with <CTRL+R>"), TextSpan::from(" is NOW available! Get it from <https://veeso.github.io/termscp/>; view release notes with <CTRL+R>"),
]) ])
.build(), .build(),
@@ -208,7 +191,7 @@ impl AuthActivity {
.with_background(bookmarks_color) .with_background(bookmarks_color)
.with_foreground(Color::Black) .with_foreground(Color::Black)
.with_borders(Borders::ALL, BorderType::Plain, bookmarks_color) .with_borders(Borders::ALL, BorderType::Plain, bookmarks_color)
.with_bookmarks(Some(String::from("Bookmarks")), vec![]) .with_title("Bookmarks", Alignment::Left)
.build(), .build(),
)), )),
); );
@@ -220,7 +203,7 @@ impl AuthActivity {
.with_background(recents_color) .with_background(recents_color)
.with_foreground(Color::Black) .with_foreground(Color::Black)
.with_borders(Borders::ALL, BorderType::Plain, recents_color) .with_borders(Borders::ALL, BorderType::Plain, recents_color)
.with_bookmarks(Some(String::from("Recent connections")), vec![]) .with_title("Recent connections", Alignment::Left)
.build(), .build(),
)), )),
); );
@@ -426,7 +409,7 @@ impl AuthActivity {
let msg = self.view.update( let msg = self.view.update(
super::COMPONENT_BOOKMARKS_LIST, super::COMPONENT_BOOKMARKS_LIST,
BookmarkListPropsBuilder::from(props) BookmarkListPropsBuilder::from(props)
.with_bookmarks(Some(String::from("Bookmarks")), bookmarks) .with_bookmarks(bookmarks)
.build(), .build(),
); );
msg msg
@@ -464,7 +447,7 @@ impl AuthActivity {
let msg = self.view.update( let msg = self.view.update(
super::COMPONENT_RECENTS_LIST, super::COMPONENT_RECENTS_LIST,
BookmarkListPropsBuilder::from(props) BookmarkListPropsBuilder::from(props)
.with_bookmarks(Some(String::from("Recent connections")), bookmarks) .with_bookmarks(bookmarks)
.build(), .build(),
); );
msg msg
@@ -482,12 +465,13 @@ impl AuthActivity {
let err_color = self.theme().misc_error_dialog; let err_color = self.theme().misc_error_dialog;
self.view.mount( self.view.mount(
super::COMPONENT_TEXT_ERROR, super::COMPONENT_TEXT_ERROR,
Box::new(MsgBox::new( Box::new(Paragraph::new(
MsgBoxPropsBuilder::default() ParagraphPropsBuilder::default()
.with_foreground(err_color) .with_foreground(err_color)
.with_borders(Borders::ALL, BorderType::Thick, err_color) .with_borders(Borders::ALL, BorderType::Thick, err_color)
.bold() .bold()
.with_texts(None, vec![TextSpan::from(text)]) .with_text_alignment(Alignment::Center)
.with_texts(vec![TextSpan::from(text)])
.build(), .build(),
)), )),
); );
@@ -510,17 +494,15 @@ impl AuthActivity {
let err_color = self.theme().misc_error_dialog; let err_color = self.theme().misc_error_dialog;
self.view.mount( self.view.mount(
super::COMPONENT_TEXT_SIZE_ERR, super::COMPONENT_TEXT_SIZE_ERR,
Box::new(MsgBox::new( Box::new(Paragraph::new(
MsgBoxPropsBuilder::default() ParagraphPropsBuilder::default()
.with_foreground(err_color) .with_foreground(err_color)
.with_borders(Borders::ALL, BorderType::Thick, err_color) .with_borders(Borders::ALL, BorderType::Thick, err_color)
.bold() .bold()
.with_texts( .with_texts(vec![TextSpan::from(
None, "termscp requires at least 24 lines of height to run",
vec![TextSpan::from( )])
"termscp requires at least 24 lines of height to run", .with_text_alignment(Alignment::Center)
)],
)
.build(), .build(),
)), )),
); );
@@ -548,10 +530,8 @@ impl AuthActivity {
.with_color(quit_color) .with_color(quit_color)
.with_borders(Borders::ALL, BorderType::Rounded, quit_color) .with_borders(Borders::ALL, BorderType::Rounded, quit_color)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_options( .with_title("Quit termscp?", Alignment::Center)
Some(String::from("Quit termscp?")), .with_options(&[String::from("Yes"), String::from("No")])
vec![String::from("Yes"), String::from("No")],
)
.build(), .build(),
)), )),
); );
@@ -577,10 +557,8 @@ impl AuthActivity {
.with_color(warn_color) .with_color(warn_color)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Rounded, warn_color) .with_borders(Borders::ALL, BorderType::Rounded, warn_color)
.with_options( .with_title("Delete bookmark?", Alignment::Center)
Some(String::from("Delete bookmark?")), .with_options(&[String::from("Yes"), String::from("No")])
vec![String::from("Yes"), String::from("No")],
)
.with_value(1) .with_value(1)
.build(), .build(),
)), )),
@@ -610,10 +588,8 @@ impl AuthActivity {
.with_color(warn_color) .with_color(warn_color)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Rounded, warn_color) .with_borders(Borders::ALL, BorderType::Rounded, warn_color)
.with_options( .with_title("Delete bookmark?", Alignment::Center)
Some(String::from("Delete bookmark?")), .with_options(&[String::from("Yes"), String::from("No")])
vec![String::from("Yes"), String::from("No")],
)
.with_value(1) .with_value(1)
.build(), .build(),
)), )),
@@ -640,7 +616,7 @@ impl AuthActivity {
Box::new(Input::new( Box::new(Input::new(
InputPropsBuilder::default() InputPropsBuilder::default()
.with_foreground(save_color) .with_foreground(save_color)
.with_label(String::from("Save bookmark as…")) .with_label("Save bookmark as…", Alignment::Center)
.with_borders( .with_borders(
Borders::TOP | Borders::RIGHT | Borders::LEFT, Borders::TOP | Borders::RIGHT | Borders::LEFT,
BorderType::Rounded, BorderType::Rounded,
@@ -659,10 +635,8 @@ impl AuthActivity {
BorderType::Rounded, BorderType::Rounded,
Color::Reset, Color::Reset,
) )
.with_options( .with_title("Save password?", Alignment::Center)
Some(String::from("Save password?")), .with_options(&[String::from("Yes"), String::from("No")])
vec![String::from("Yes"), String::from("No")],
)
.build(), .build(),
)), )),
); );
@@ -685,77 +659,38 @@ impl AuthActivity {
let key_color = self.theme().misc_keys; let key_color = self.theme().misc_keys;
self.view.mount( self.view.mount(
super::COMPONENT_TEXT_HELP, super::COMPONENT_TEXT_HELP,
Box::new(Scrolltable::new( Box::new(List::new(
ScrollTablePropsBuilder::default() ListPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, Color::White) .with_borders(Borders::ALL, BorderType::Rounded, Color::White)
.with_highlighted_str(Some("?")) .with_highlighted_str(Some("?"))
.with_max_scroll_step(8) .with_max_scroll_step(8)
.scrollable(true)
.bold() .bold()
.with_table( .with_title("Help", Alignment::Center)
Some(String::from("Help")), .with_rows(
TableBuilder::default() TableBuilder::default()
.add_col( .add_col(TextSpan::new("<ESC>").bold().fg(key_color))
TextSpanBuilder::new("<ESC>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Quit termscp")) .add_col(TextSpan::from(" Quit termscp"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<TAB>").bold().fg(key_color))
TextSpanBuilder::new("<TAB>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Switch from form and bookmarks")) .add_col(TextSpan::from(" Switch from form and bookmarks"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<RIGHT/LEFT>").bold().fg(key_color))
TextSpanBuilder::new("<RIGHT/LEFT>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Switch bookmark tab")) .add_col(TextSpan::from(" Switch bookmark tab"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<UP/DOWN>").bold().fg(key_color))
TextSpanBuilder::new("<UP/DOWN>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Move up/down in current tab")) .add_col(TextSpan::from(" Move up/down in current tab"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<ENTER>").bold().fg(key_color))
TextSpanBuilder::new("<ENTER>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Connect/Load bookmark")) .add_col(TextSpan::from(" Connect/Load bookmark"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<DEL|E>").bold().fg(key_color))
TextSpanBuilder::new("<DEL|E>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Delete selected bookmark")) .add_col(TextSpan::from(" Delete selected bookmark"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<CTRL+C>").bold().fg(key_color))
TextSpanBuilder::new("<CTRL+C>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Enter setup")) .add_col(TextSpan::from(" Enter setup"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<CTRL+S>").bold().fg(key_color))
TextSpanBuilder::new("<CTRL+S>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Save bookmark")) .add_col(TextSpan::from(" Save bookmark"))
.build(), .build(),
) )
@@ -786,7 +721,8 @@ impl AuthActivity {
Box::new(Textarea::new( Box::new(Textarea::new(
TextareaPropsBuilder::default() TextareaPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightYellow) .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(), .build(),
)), )),
); );

View File

@@ -42,9 +42,9 @@ use crate::ui::components::{file_list::FileListPropsBuilder, logbox::LogboxProps
use crate::ui::keymap::*; use crate::ui::keymap::*;
use crate::utils::fmt::fmt_path_elide_ex; use crate::utils::fmt::fmt_path_elide_ex;
// externals // externals
use tui_realm_stdlib::progress_bar::ProgressBarPropsBuilder;
use tuirealm::{ use tuirealm::{
components::progress_bar::ProgressBarPropsBuilder, props::{Alignment, PropsBuilder, TableBuilder, TextSpan},
props::{PropsBuilder, TableBuilder, TextSpan, TextSpanBuilder},
tui::style::Color, tui::style::Color,
Msg, Payload, Update, Value, Msg, Payload, Update, Value,
}; };
@@ -63,13 +63,13 @@ impl Update for FileTransferActivity {
None => None, // Exit after None None => None, // Exit after None
Some(msg) => match msg { Some(msg) => match msg {
// -- local tab // -- local tab
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_RIGHT) => { (COMPONENT_EXPLORER_LOCAL, key) if key == &MSG_KEY_RIGHT => {
// Change tab // Change tab
self.view.active(COMPONENT_EXPLORER_REMOTE); self.view.active(COMPONENT_EXPLORER_REMOTE);
self.browser.change_tab(FileExplorerTab::Remote); self.browser.change_tab(FileExplorerTab::Remote);
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_BACKSPACE) => { (COMPONENT_EXPLORER_LOCAL, key) if key == &MSG_KEY_BACKSPACE => {
// Go to previous directory // Go to previous directory
self.action_go_to_previous_local_dir(false); self.action_go_to_previous_local_dir(false);
if self.browser.sync_browsing { if self.browser.sync_browsing {
@@ -98,11 +98,11 @@ impl Update for FileTransferActivity {
None None
} }
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_SPACE) => { (COMPONENT_EXPLORER_LOCAL, key) if key == &MSG_KEY_SPACE => {
self.action_local_send(); self.action_local_send();
self.update_remote_filelist() self.update_remote_filelist()
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_A) => { (COMPONENT_EXPLORER_LOCAL, key) if key == &MSG_KEY_CHAR_A => {
// Toggle hidden files // Toggle hidden files
self.local_mut().toggle_hidden_files(); self.local_mut().toggle_hidden_files();
// Update status bar // Update status bar
@@ -110,24 +110,24 @@ impl Update for FileTransferActivity {
// Reload file list component // Reload file list component
self.update_local_filelist() 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() { if let SelectedEntry::One(file) = self.get_local_selected_entries() {
self.mount_file_info(&file); self.mount_file_info(&file);
} }
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_L) => { (COMPONENT_EXPLORER_LOCAL, key) if key == &MSG_KEY_CHAR_L => {
// Reload directory // Reload directory
self.reload_local_dir(); self.reload_local_dir();
// Reload file list component // Reload file list component
self.update_local_filelist() 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(); self.action_edit_local_file();
// Reload file list component // Reload file list component
self.update_local_filelist() 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); self.action_go_to_local_upper_dir(false);
if self.browser.sync_browsing { if self.browser.sync_browsing {
let _ = self.update_remote_filelist(); let _ = self.update_remote_filelist();
@@ -136,7 +136,7 @@ impl Update for FileTransferActivity {
self.update_local_filelist() self.update_local_filelist()
} }
// -- remote tab // -- remote tab
(COMPONENT_EXPLORER_REMOTE, &MSG_KEY_LEFT) => { (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_LEFT => {
// Change tab // Change tab
self.view.active(COMPONENT_EXPLORER_LOCAL); self.view.active(COMPONENT_EXPLORER_LOCAL);
self.browser.change_tab(FileExplorerTab::Local); self.browser.change_tab(FileExplorerTab::Local);
@@ -162,11 +162,11 @@ impl Update for FileTransferActivity {
None None
} }
} }
(COMPONENT_EXPLORER_REMOTE, &MSG_KEY_SPACE) => { (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_SPACE => {
self.action_remote_recv(); self.action_remote_recv();
self.update_local_filelist() self.update_local_filelist()
} }
(COMPONENT_EXPLORER_REMOTE, &MSG_KEY_BACKSPACE) => { (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_BACKSPACE => {
// Go to previous directory // Go to previous directory
self.action_go_to_previous_remote_dir(false); self.action_go_to_previous_remote_dir(false);
// If sync is enabled update local too // If sync is enabled update local too
@@ -176,7 +176,7 @@ impl Update for FileTransferActivity {
// Reload file list component // Reload file list component
self.update_remote_filelist() self.update_remote_filelist()
} }
(COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_A) => { (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_CHAR_A => {
// Toggle hidden files // Toggle hidden files
self.remote_mut().toggle_hidden_files(); self.remote_mut().toggle_hidden_files();
// Update status bar // Update status bar
@@ -184,25 +184,25 @@ impl Update for FileTransferActivity {
// Reload file list component // Reload file list component
self.update_remote_filelist() 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() { if let SelectedEntry::One(file) = self.get_remote_selected_entries() {
self.mount_file_info(&file); self.mount_file_info(&file);
} }
None None
} }
(COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_L) => { (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_CHAR_L => {
// Reload directory // Reload directory
self.reload_remote_dir(); self.reload_remote_dir();
// Reload file list component // Reload file list component
self.update_remote_filelist() self.update_remote_filelist()
} }
(COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_O) => { (COMPONENT_EXPLORER_REMOTE, key) if key == &MSG_KEY_CHAR_O => {
// Edit file // Edit file
self.action_edit_remote_file(); self.action_edit_remote_file();
// Reload file list component // Reload file list component
self.update_remote_filelist() 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); self.action_go_to_remote_upper_dir(false);
if self.browser.sync_browsing { if self.browser.sync_browsing {
let _ = self.update_local_filelist(); let _ = self.update_local_filelist();
@@ -211,64 +211,78 @@ impl Update for FileTransferActivity {
self.update_remote_filelist() self.update_remote_filelist()
} }
// -- common explorer keys // -- common explorer keys
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_B) (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_B) => { if key == &MSG_KEY_CHAR_B =>
{
// Show sorting file // Show sorting file
self.mount_file_sorting(); self.mount_file_sorting();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_C) (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_C) => { if key == &MSG_KEY_CHAR_C =>
{
self.mount_copy(); self.mount_copy();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_D) (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_D) => { if key == &MSG_KEY_CHAR_D =>
{
self.mount_mkdir(); self.mount_mkdir();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_F) (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_F) => { if key == &MSG_KEY_CHAR_F =>
{
self.mount_find_input(); self.mount_find_input();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_G) (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_G) => { if key == &MSG_KEY_CHAR_G =>
{
self.mount_goto(); self.mount_goto();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_H) (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_H) => { if key == &MSG_KEY_CHAR_H =>
{
self.mount_help(); self.mount_help();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_N) (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_N) => { if key == &MSG_KEY_CHAR_N =>
{
self.mount_newfile(); self.mount_newfile();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_Q) (COMPONENT_EXPLORER_LOCAL, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_Q) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_LOG_BOX, &MSG_KEY_CHAR_Q) => { | (COMPONENT_LOG_BOX, key)
if key == &MSG_KEY_CHAR_Q =>
{
self.mount_quit(); self.mount_quit();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_R) (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_R) => { if key == &MSG_KEY_CHAR_R =>
{
// Mount rename // Mount rename
self.mount_rename(); self.mount_rename();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_S) (COMPONENT_EXPLORER_LOCAL, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_S) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_FIND, &MSG_KEY_CHAR_S) => { | (COMPONENT_EXPLORER_FIND, key)
if key == &MSG_KEY_CHAR_S =>
{
// Mount save as // Mount save as
self.mount_saveas(); self.mount_saveas();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_V) (COMPONENT_EXPLORER_LOCAL, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_V) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_FIND, &MSG_KEY_CHAR_V) => { | (COMPONENT_EXPLORER_FIND, key)
if key == &MSG_KEY_CHAR_V =>
{
// View // View
match self.browser.tab() { match self.browser.tab() {
FileExplorerTab::Local => self.action_open_local(), FileExplorerTab::Local => self.action_open_local(),
@@ -279,44 +293,49 @@ impl Update for FileTransferActivity {
} }
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_W) (COMPONENT_EXPLORER_LOCAL, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_W) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_FIND, &MSG_KEY_CHAR_W) => { | (COMPONENT_EXPLORER_FIND, key)
if key == &MSG_KEY_CHAR_W =>
{
// Open with // Open with
self.mount_openwith(); self.mount_openwith();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_X) (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_X) => { if key == &MSG_KEY_CHAR_X =>
{
// Mount exec // Mount exec
self.mount_exec(); self.mount_exec();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_Y) (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_Y) => { if key == &MSG_KEY_CHAR_Y =>
{
// Toggle browser sync // Toggle browser sync
self.browser.toggle_sync_browsing(); self.browser.toggle_sync_browsing();
// Update status bar // Update status bar
self.refresh_remote_status_bar(); self.refresh_remote_status_bar();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_ESC) (COMPONENT_EXPLORER_LOCAL, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_ESC) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_LOG_BOX, &MSG_KEY_ESC) => { | (COMPONENT_LOG_BOX, key)
if key == &MSG_KEY_ESC =>
{
self.mount_disconnect(); self.mount_disconnect();
None None
} }
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_DEL) (COMPONENT_EXPLORER_LOCAL, key)
| (COMPONENT_EXPLORER_LOCAL, &MSG_KEY_CHAR_E) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_DEL) | (COMPONENT_EXPLORER_FIND, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_CHAR_E) if key == &MSG_KEY_CHAR_E || key == &MSG_KEY_DEL =>
| (COMPONENT_EXPLORER_FIND, &MSG_KEY_DEL) {
| (COMPONENT_EXPLORER_FIND, &MSG_KEY_CHAR_E) => {
self.mount_radio_delete(); self.mount_radio_delete();
None None
} }
// -- find result explorer // -- find result explorer
(COMPONENT_EXPLORER_FIND, &MSG_KEY_ESC) => { (COMPONENT_EXPLORER_FIND, key) if key == &MSG_KEY_ESC => {
// Umount find // Umount find
self.umount_find(); self.umount_find();
// Finalize find // Finalize find
@@ -337,7 +356,7 @@ impl Update for FileTransferActivity {
_ => None, _ => None,
} }
} }
(COMPONENT_EXPLORER_FIND, &MSG_KEY_SPACE) => { (COMPONENT_EXPLORER_FIND, key) if key == &MSG_KEY_SPACE => {
// Get entry // Get entry
self.action_find_transfer(None); self.action_find_transfer(None);
// Reload files // Reload files
@@ -349,18 +368,19 @@ impl Update for FileTransferActivity {
} }
} }
// -- switch to log // -- switch to log
(COMPONENT_EXPLORER_LOCAL, &MSG_KEY_TAB) (COMPONENT_EXPLORER_LOCAL, key) | (COMPONENT_EXPLORER_REMOTE, key)
| (COMPONENT_EXPLORER_REMOTE, &MSG_KEY_TAB) => { if key == &MSG_KEY_TAB =>
{
self.view.active(COMPONENT_LOG_BOX); // Active log box self.view.active(COMPONENT_LOG_BOX); // Active log box
None None
} }
// -- Log box // -- Log box
(COMPONENT_LOG_BOX, &MSG_KEY_TAB) => { (COMPONENT_LOG_BOX, key) if key == &MSG_KEY_TAB => {
self.view.blur(); // Blur log box self.view.blur(); // Blur log box
None None
} }
// -- copy popup // -- copy popup
(COMPONENT_INPUT_COPY, &MSG_KEY_ESC) => { (COMPONENT_INPUT_COPY, key) if key == &MSG_KEY_ESC => {
self.umount_copy(); self.umount_copy();
None None
} }
@@ -383,7 +403,7 @@ impl Update for FileTransferActivity {
} }
(COMPONENT_INPUT_COPY, _) => None, (COMPONENT_INPUT_COPY, _) => None,
// -- exec popup // -- exec popup
(COMPONENT_INPUT_EXEC, &MSG_KEY_ESC) => { (COMPONENT_INPUT_EXEC, key) if key == &MSG_KEY_ESC => {
self.umount_exec(); self.umount_exec();
None None
} }
@@ -406,7 +426,7 @@ impl Update for FileTransferActivity {
} }
(COMPONENT_INPUT_EXEC, _) => None, (COMPONENT_INPUT_EXEC, _) => None,
// -- find popup // -- find popup
(COMPONENT_INPUT_FIND, &MSG_KEY_ESC) => { (COMPONENT_INPUT_FIND, key) if key == &MSG_KEY_ESC => {
self.umount_find_input(); self.umount_find_input();
None None
} }
@@ -441,7 +461,7 @@ impl Update for FileTransferActivity {
None None
} }
// -- goto popup // -- goto popup
(COMPONENT_INPUT_GOTO, &MSG_KEY_ESC) => { (COMPONENT_INPUT_GOTO, key) if key == &MSG_KEY_ESC => {
self.umount_goto(); self.umount_goto();
None None
} }
@@ -474,7 +494,7 @@ impl Update for FileTransferActivity {
} }
(COMPONENT_INPUT_GOTO, _) => None, (COMPONENT_INPUT_GOTO, _) => None,
// -- make directory // -- make directory
(COMPONENT_INPUT_MKDIR, &MSG_KEY_ESC) => { (COMPONENT_INPUT_MKDIR, key) if key == &MSG_KEY_ESC => {
self.umount_mkdir(); self.umount_mkdir();
None None
} }
@@ -494,7 +514,7 @@ impl Update for FileTransferActivity {
} }
(COMPONENT_INPUT_MKDIR, _) => None, (COMPONENT_INPUT_MKDIR, _) => None,
// -- new file // -- new file
(COMPONENT_INPUT_NEWFILE, &MSG_KEY_ESC) => { (COMPONENT_INPUT_NEWFILE, key) if key == &MSG_KEY_ESC => {
self.umount_newfile(); self.umount_newfile();
None None
} }
@@ -514,7 +534,7 @@ impl Update for FileTransferActivity {
} }
(COMPONENT_INPUT_NEWFILE, _) => None, (COMPONENT_INPUT_NEWFILE, _) => None,
// -- open with // -- open with
(COMPONENT_INPUT_OPEN_WITH, &MSG_KEY_ESC) => { (COMPONENT_INPUT_OPEN_WITH, key) if key == &MSG_KEY_ESC => {
self.umount_openwith(); self.umount_openwith();
None None
} }
@@ -531,7 +551,7 @@ impl Update for FileTransferActivity {
} }
(COMPONENT_INPUT_OPEN_WITH, _) => None, (COMPONENT_INPUT_OPEN_WITH, _) => None,
// -- rename // -- rename
(COMPONENT_INPUT_RENAME, &MSG_KEY_ESC) => { (COMPONENT_INPUT_RENAME, key) if key == &MSG_KEY_ESC => {
self.umount_rename(); self.umount_rename();
None None
} }
@@ -553,7 +573,7 @@ impl Update for FileTransferActivity {
} }
(COMPONENT_INPUT_RENAME, _) => None, (COMPONENT_INPUT_RENAME, _) => None,
// -- save as // -- save as
(COMPONENT_INPUT_SAVEAS, &MSG_KEY_ESC) => { (COMPONENT_INPUT_SAVEAS, key) if key == &MSG_KEY_ESC => {
self.umount_saveas(); self.umount_saveas();
None None
} }
@@ -578,15 +598,18 @@ impl Update for FileTransferActivity {
} }
(COMPONENT_INPUT_SAVEAS, _) => None, (COMPONENT_INPUT_SAVEAS, _) => None,
// -- fileinfo // -- fileinfo
(COMPONENT_LIST_FILEINFO, &MSG_KEY_ENTER) (COMPONENT_LIST_FILEINFO, key) | (COMPONENT_LIST_FILEINFO, key)
| (COMPONENT_LIST_FILEINFO, &MSG_KEY_ESC) => { if key == &MSG_KEY_ENTER || key == &MSG_KEY_ESC =>
{
self.umount_file_info(); self.umount_file_info();
None None
} }
(COMPONENT_LIST_FILEINFO, _) => None, (COMPONENT_LIST_FILEINFO, _) => None,
// -- delete // -- delete
(COMPONENT_RADIO_DELETE, &MSG_KEY_ESC) (COMPONENT_RADIO_DELETE, key)
| (COMPONENT_RADIO_DELETE, Msg::OnSubmit(Payload::One(Value::Usize(1)))) => { if key == &MSG_KEY_ESC
|| key == &Msg::OnSubmit(Payload::One(Value::Usize(1))) =>
{
self.umount_radio_delete(); self.umount_radio_delete();
None None
} }
@@ -631,8 +654,10 @@ impl Update for FileTransferActivity {
} }
(COMPONENT_RADIO_DELETE, _) => None, (COMPONENT_RADIO_DELETE, _) => None,
// -- disconnect // -- disconnect
(COMPONENT_RADIO_DISCONNECT, &MSG_KEY_ESC) (COMPONENT_RADIO_DISCONNECT, key)
| (COMPONENT_RADIO_DISCONNECT, Msg::OnSubmit(Payload::One(Value::Usize(1)))) => { if key == &MSG_KEY_ESC
|| key == &Msg::OnSubmit(Payload::One(Value::Usize(1))) =>
{
self.umount_disconnect(); self.umount_disconnect();
None None
} }
@@ -643,8 +668,10 @@ impl Update for FileTransferActivity {
} }
(COMPONENT_RADIO_DISCONNECT, _) => None, (COMPONENT_RADIO_DISCONNECT, _) => None,
// -- quit // -- quit
(COMPONENT_RADIO_QUIT, &MSG_KEY_ESC) (COMPONENT_RADIO_QUIT, key)
| (COMPONENT_RADIO_QUIT, Msg::OnSubmit(Payload::One(Value::Usize(1)))) => { if key == &MSG_KEY_ESC
|| key == &Msg::OnSubmit(Payload::One(Value::Usize(1))) =>
{
self.umount_quit(); self.umount_quit();
None None
} }
@@ -655,8 +682,11 @@ impl Update for FileTransferActivity {
} }
(COMPONENT_RADIO_QUIT, _) => None, (COMPONENT_RADIO_QUIT, _) => None,
// -- sorting // -- sorting
(COMPONENT_RADIO_SORTING, &MSG_KEY_ESC) (COMPONENT_RADIO_SORTING, key) if key == &MSG_KEY_ESC => {
| (COMPONENT_RADIO_SORTING, Msg::OnSubmit(_)) => { self.umount_file_sorting();
None
}
(COMPONENT_RADIO_SORTING, Msg::OnSubmit(_)) => {
self.umount_file_sorting(); self.umount_file_sorting();
None None
} }
@@ -688,25 +718,31 @@ impl Update for FileTransferActivity {
} }
(COMPONENT_RADIO_SORTING, _) => None, (COMPONENT_RADIO_SORTING, _) => None,
// -- error // -- 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(); self.umount_error();
None None
} }
(COMPONENT_TEXT_ERROR, _) => None, (COMPONENT_TEXT_ERROR, _) => None,
// -- fatal // -- 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); self.exit_reason = Some(super::ExitReason::Disconnect);
None None
} }
(COMPONENT_TEXT_FATAL, _) => None, (COMPONENT_TEXT_FATAL, _) => None,
// -- help // -- 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(); self.umount_help();
None None
} }
(COMPONENT_TEXT_HELP, _) => None, (COMPONENT_TEXT_HELP, _) => None,
// -- progress bar // -- 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 // Set transfer aborted to True
self.transfer.abort(); self.transfer.abort();
None None
@@ -752,7 +788,8 @@ impl FileTransferActivity {
.collect(); .collect();
// Update // Update
let props = FileListPropsBuilder::from(props) let props = FileListPropsBuilder::from(props)
.with_files(Some(hostname), files) .with_files(files)
.with_title(hostname, Alignment::Left)
.build(); .build();
// Update // Update
self.view.update(super::COMPONENT_EXPLORER_LOCAL, props) self.view.update(super::COMPONENT_EXPLORER_LOCAL, props)
@@ -790,7 +827,8 @@ impl FileTransferActivity {
.collect(); .collect();
// Update // Update
let props = FileListPropsBuilder::from(props) let props = FileListPropsBuilder::from(props)
.with_files(Some(hostname), files) .with_files(files)
.with_title(hostname, Alignment::Left)
.build(); .build();
self.view.update(super::COMPONENT_EXPLORER_REMOTE, props) self.view.update(super::COMPONENT_EXPLORER_REMOTE, props)
} }
@@ -823,7 +861,7 @@ impl FileTransferActivity {
))) )))
.add_col(TextSpan::from(" [")) .add_col(TextSpan::from(" ["))
.add_col( .add_col(
TextSpanBuilder::new( TextSpan::new(
format!( format!(
"{:5}", "{:5}",
match record.level { match record.level {
@@ -834,16 +872,13 @@ impl FileTransferActivity {
) )
.as_str(), .as_str(),
) )
.with_foreground(fg) .fg(fg),
.build(),
) )
.add_col(TextSpan::from("]: ")) .add_col(TextSpan::from("]: "))
.add_col(TextSpan::from(record.msg.as_ref())); .add_col(TextSpan::from(record.msg.as_ref()));
} }
let table = table.build(); let table = table.build();
let props = LogboxPropsBuilder::from(props) let props = LogboxPropsBuilder::from(props).with_log(table).build();
.with_log(Some(String::from("Log")), table)
.build();
self.view.update(super::COMPONENT_LOG_BOX, props) self.view.update(super::COMPONENT_LOG_BOX, props)
} }
None => None, None => None,
@@ -852,9 +887,8 @@ impl FileTransferActivity {
pub(super) fn update_progress_bar(&mut self, filename: String) -> Option<(String, Msg)> { 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) { 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) 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()) .with_progress(self.transfer.full.calc_progress())
.build(); .build();
let _ = self.view.update(COMPONENT_PROGRESS_BAR_FULL, props); let _ = self.view.update(COMPONENT_PROGRESS_BAR_FULL, props);
@@ -862,7 +896,8 @@ impl FileTransferActivity {
match self.view.get_props(COMPONENT_PROGRESS_BAR_PARTIAL) { match self.view.get_props(COMPONENT_PROGRESS_BAR_PARTIAL) {
Some(props) => { Some(props) => {
let props = ProgressBarPropsBuilder::from(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()) .with_progress(self.transfer.partial.calc_progress())
.build(); .build();
self.view.update(COMPONENT_PROGRESS_BAR_PARTIAL, props) self.view.update(COMPONENT_PROGRESS_BAR_PARTIAL, props)
@@ -889,7 +924,6 @@ impl FileTransferActivity {
match self.view.get_props(COMPONENT_EXPLORER_FIND) { match self.view.get_props(COMPONENT_EXPLORER_FIND) {
None => None, None => None,
Some(props) => { Some(props) => {
let title: String = props.texts.title.clone().unwrap_or_default();
// Prepare files // Prepare files
let files: Vec<String> = self let files: Vec<String> = self
.found() .found()
@@ -897,9 +931,7 @@ impl FileTransferActivity {
.iter_files() .iter_files()
.map(|x: &FsEntry| self.found().unwrap().fmt_file(x)) .map(|x: &FsEntry| self.found().unwrap().fmt_file(x))
.collect(); .collect();
let props = FileListPropsBuilder::from(props) let props = FileListPropsBuilder::from(props).with_files(files).build();
.with_files(Some(title), files)
.build();
self.view.update(COMPONENT_EXPLORER_FIND, props) self.view.update(COMPONENT_EXPLORER_FIND, props)
} }
} }

View File

@@ -32,7 +32,6 @@ use crate::fs::FsEntry;
use crate::ui::components::{ use crate::ui::components::{
file_list::{FileList, FileListPropsBuilder}, file_list::{FileList, FileListPropsBuilder},
logbox::{LogBox, LogboxPropsBuilder}, logbox::{LogBox, LogboxPropsBuilder},
msgbox::{MsgBox, MsgBoxPropsBuilder},
}; };
use crate::ui::store::Store; use crate::ui::store::Store;
use crate::utils::fmt::fmt_time; use crate::utils::fmt::fmt_time;
@@ -40,15 +39,16 @@ use crate::utils::ui::draw_area_in;
// Ext // Ext
use bytesize::ByteSize; use bytesize::ByteSize;
use std::path::PathBuf; use std::path::PathBuf;
use tuirealm::components::{ use tui_realm_stdlib::{
input::{Input, InputPropsBuilder}, input::{Input, InputPropsBuilder},
list::{List, ListPropsBuilder},
paragraph::{Paragraph, ParagraphPropsBuilder},
progress_bar::{ProgressBar, ProgressBarPropsBuilder}, progress_bar::{ProgressBar, ProgressBarPropsBuilder},
radio::{Radio, RadioPropsBuilder}, radio::{Radio, RadioPropsBuilder},
scrolltable::{ScrollTablePropsBuilder, Scrolltable},
span::{Span, SpanPropsBuilder}, span::{Span, SpanPropsBuilder},
table::{Table, TablePropsBuilder}, table::{Table, TablePropsBuilder},
}; };
use tuirealm::props::{PropsBuilder, TableBuilder, TextSpan, TextSpanBuilder}; use tuirealm::props::{Alignment, PropsBuilder, TableBuilder, TextSpan};
use tuirealm::tui::{ use tuirealm::tui::{
layout::{Constraint, Direction, Layout}, layout::{Constraint, Direction, Layout},
style::Color, style::Color,
@@ -101,6 +101,7 @@ impl FileTransferActivity {
super::COMPONENT_LOG_BOX, super::COMPONENT_LOG_BOX,
Box::new(LogBox::new( Box::new(LogBox::new(
LogboxPropsBuilder::default() LogboxPropsBuilder::default()
.with_title("Log", Alignment::Left)
.with_background(log_background) .with_background(log_background)
.with_borders(Borders::ALL, BorderType::Plain, log_panel) .with_borders(Borders::ALL, BorderType::Plain, log_panel)
.build(), .build(),
@@ -383,12 +384,13 @@ impl FileTransferActivity {
let error_color = self.theme().misc_error_dialog; let error_color = self.theme().misc_error_dialog;
self.view.mount( self.view.mount(
super::COMPONENT_TEXT_ERROR, super::COMPONENT_TEXT_ERROR,
Box::new(MsgBox::new( Box::new(Paragraph::new(
MsgBoxPropsBuilder::default() ParagraphPropsBuilder::default()
.with_foreground(error_color) .with_foreground(error_color)
.with_borders(Borders::ALL, BorderType::Rounded, error_color) .with_borders(Borders::ALL, BorderType::Rounded, error_color)
.bold() .bold()
.with_texts(None, vec![TextSpan::from(text)]) .with_text_alignment(Alignment::Center)
.with_texts(vec![TextSpan::from(text)])
.build(), .build(),
)), )),
); );
@@ -408,12 +410,13 @@ impl FileTransferActivity {
let error_color = self.theme().misc_error_dialog; let error_color = self.theme().misc_error_dialog;
self.view.mount( self.view.mount(
super::COMPONENT_TEXT_FATAL, super::COMPONENT_TEXT_FATAL,
Box::new(MsgBox::new( Box::new(Paragraph::new(
MsgBoxPropsBuilder::default() ParagraphPropsBuilder::default()
.with_foreground(error_color) .with_foreground(error_color)
.with_borders(Borders::ALL, BorderType::Rounded, error_color) .with_borders(Borders::ALL, BorderType::Rounded, error_color)
.bold() .bold()
.with_texts(None, vec![TextSpan::from(text)]) .with_text_alignment(Alignment::Center)
.with_texts(vec![TextSpan::from(text)])
.build(), .build(),
)), )),
); );
@@ -422,28 +425,26 @@ impl FileTransferActivity {
} }
pub(super) fn mount_wait(&mut self, text: &str) { 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) { 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(); 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 // Mount
let mut builder: MsgBoxPropsBuilder = MsgBoxPropsBuilder::default(); let mut builder: ParagraphPropsBuilder = ParagraphPropsBuilder::default();
builder builder
.with_foreground(color) .with_foreground(color)
.with_borders(Borders::ALL, BorderType::Rounded, Color::White) .with_borders(Borders::ALL, BorderType::Rounded, Color::White)
.bold() .bold()
.with_texts(None, vec![TextSpan::from(text)]); .with_text_alignment(Alignment::Center)
if blink { .with_texts(vec![TextSpan::from(text)]);
builder.blink();
}
self.view.mount( self.view.mount(
super::COMPONENT_TEXT_WAIT, super::COMPONENT_TEXT_WAIT,
Box::new(MsgBox::new(builder.build())), Box::new(Paragraph::new(builder.build())),
); );
// Give focus to info // Give focus to info
self.view.active(super::COMPONENT_TEXT_WAIT); self.view.active(super::COMPONENT_TEXT_WAIT);
@@ -466,10 +467,8 @@ impl FileTransferActivity {
.with_color(quit_color) .with_color(quit_color)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Rounded, quit_color) .with_borders(Borders::ALL, BorderType::Rounded, quit_color)
.with_options( .with_title("Are you sure you want to quit?", Alignment::Center)
Some(String::from("Are you sure you want to quit?")), .with_options(&[String::from("Yes"), String::from("No")])
vec![String::from("Yes"), String::from("No")],
)
.build(), .build(),
)), )),
); );
@@ -496,10 +495,8 @@ impl FileTransferActivity {
.with_color(quit_color) .with_color(quit_color)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Rounded, quit_color) .with_borders(Borders::ALL, BorderType::Rounded, quit_color)
.with_options( .with_title("Are you sure you want to disconnect?", Alignment::Center)
Some(String::from("Are you sure you want to disconnect?")), .with_options(&[String::from("Yes"), String::from("No")])
vec![String::from("Yes"), String::from("No")],
)
.build(), .build(),
)), )),
); );
@@ -521,7 +518,7 @@ impl FileTransferActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_borders(Borders::ALL, BorderType::Rounded, input_color)
.with_foreground(input_color) .with_foreground(input_color)
.with_label(String::from("Copy file(s) to…")) .with_label("Copy file(s) to…", Alignment::Center)
.build(), .build(),
)), )),
); );
@@ -540,7 +537,7 @@ impl FileTransferActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_borders(Borders::ALL, BorderType::Rounded, input_color)
.with_foreground(input_color) .with_foreground(input_color)
.with_label(String::from("Execute command")) .with_label("Execute command", Alignment::Center)
.build(), .build(),
)), )),
); );
@@ -570,7 +567,10 @@ impl FileTransferActivity {
super::COMPONENT_EXPLORER_FIND, super::COMPONENT_EXPLORER_FIND,
Box::new(FileList::new( Box::new(FileList::new(
FileListPropsBuilder::default() 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_borders(Borders::ALL, BorderType::Plain, hg)
.with_highlight_color(hg) .with_highlight_color(hg)
.with_background(bg) .with_background(bg)
@@ -594,7 +594,7 @@ impl FileTransferActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_borders(Borders::ALL, BorderType::Rounded, input_color)
.with_foreground(input_color) .with_foreground(input_color)
.with_label(String::from("Search files by name")) .with_label("Search files by name", Alignment::Center)
.build(), .build(),
)), )),
); );
@@ -615,7 +615,7 @@ impl FileTransferActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_borders(Borders::ALL, BorderType::Rounded, input_color)
.with_foreground(input_color) .with_foreground(input_color)
.with_label(String::from("Change working directory")) .with_label("Change working directory", Alignment::Center)
.build(), .build(),
)), )),
); );
@@ -634,7 +634,7 @@ impl FileTransferActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_borders(Borders::ALL, BorderType::Rounded, input_color)
.with_foreground(input_color) .with_foreground(input_color)
.with_label(String::from("Insert directory name")) .with_label("Insert directory name", Alignment::Center)
.build(), .build(),
)), )),
); );
@@ -653,7 +653,7 @@ impl FileTransferActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_borders(Borders::ALL, BorderType::Rounded, input_color)
.with_foreground(input_color) .with_foreground(input_color)
.with_label(String::from("New file name")) .with_label("New file name", Alignment::Center)
.build(), .build(),
)), )),
); );
@@ -672,7 +672,7 @@ impl FileTransferActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_borders(Borders::ALL, BorderType::Rounded, input_color)
.with_foreground(input_color) .with_foreground(input_color)
.with_label(String::from("Open file with…")) .with_label("Open file with…", Alignment::Center)
.build(), .build(),
)), )),
); );
@@ -691,7 +691,7 @@ impl FileTransferActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_borders(Borders::ALL, BorderType::Rounded, input_color)
.with_foreground(input_color) .with_foreground(input_color)
.with_label(String::from("Move file(s) to…")) .with_label("Move file(s) to…", Alignment::Center)
.build(), .build(),
)), )),
); );
@@ -710,7 +710,7 @@ impl FileTransferActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, input_color) .with_borders(Borders::ALL, BorderType::Rounded, input_color)
.with_foreground(input_color) .with_foreground(input_color)
.with_label(String::from("Save as…")) .with_label("Save as…", Alignment::Center)
.build(), .build(),
)), )),
); );
@@ -735,7 +735,7 @@ impl FileTransferActivity {
BorderType::Rounded, BorderType::Rounded,
Color::Reset, Color::Reset,
) )
.with_texts(Some(root_name), String::new()) .with_title(root_name, Alignment::Center)
.build(), .build(),
)), )),
); );
@@ -750,7 +750,7 @@ impl FileTransferActivity {
BorderType::Rounded, BorderType::Rounded,
Color::Reset, Color::Reset,
) )
.with_texts(Some(String::from("Please wait")), String::new()) .with_title("Please wait", Alignment::Center)
.build(), .build(),
)), )),
); );
@@ -782,15 +782,13 @@ impl FileTransferActivity {
.with_color(sorting_color) .with_color(sorting_color)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Rounded, sorting_color) .with_borders(Borders::ALL, BorderType::Rounded, sorting_color)
.with_options( .with_title("Sort files by", Alignment::Center)
Some(String::from("Sort files by")), .with_options(&[
vec![ String::from("Name"),
String::from("Name"), String::from("Modify time"),
String::from("Modify time"), String::from("Creation time"),
String::from("Creation time"), String::from("Size"),
String::from("Size"), ])
],
)
.with_value(index) .with_value(index)
.build(), .build(),
)), )),
@@ -811,10 +809,8 @@ impl FileTransferActivity {
.with_color(warn_color) .with_color(warn_color)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Plain, warn_color) .with_borders(Borders::ALL, BorderType::Plain, warn_color)
.with_options( .with_title("Delete file", Alignment::Center)
Some(String::from("Delete file")), .with_options(&[String::from("Yes"), String::from("No")])
vec![String::from("Yes"), String::from("No")],
)
.with_value(1) .with_value(1)
.build(), .build(),
)), )),
@@ -841,54 +837,35 @@ impl FileTransferActivity {
None => format!("{}", file.get_abs_path().display()), None => format!("{}", file.get_abs_path().display()),
}; };
// Make texts // Make texts
texts.add_col(TextSpan::from("Path: ")).add_col( texts
TextSpanBuilder::new(path.as_str()) .add_col(TextSpan::from("Path: "))
.with_foreground(Color::Yellow) .add_col(TextSpan::new(path.as_str()).fg(Color::Yellow));
.build(),
);
if let Some(filetype) = file.get_ftype() { if let Some(filetype) = file.get_ftype() {
texts texts
.add_row() .add_row()
.add_col(TextSpan::from("File type: ")) .add_col(TextSpan::from("File type: "))
.add_col( .add_col(TextSpan::new(filetype.as_str()).fg(Color::LightGreen));
TextSpanBuilder::new(filetype.as_str())
.with_foreground(Color::LightGreen)
.build(),
);
} }
let (bsize, size): (ByteSize, usize) = (ByteSize(file.get_size() as u64), file.get_size()); let (bsize, size): (ByteSize, usize) = (ByteSize(file.get_size() as u64), file.get_size());
texts.add_row().add_col(TextSpan::from("Size: ")).add_col( texts
TextSpanBuilder::new(format!("{} ({})", bsize, size).as_str()) .add_row()
.with_foreground(Color::Cyan) .add_col(TextSpan::from("Size: "))
.build(), .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 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 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"); let mtime: String = fmt_time(file.get_creation_time(), "%b %d %Y %H:%M:%S");
texts texts
.add_row() .add_row()
.add_col(TextSpan::from("Creation time: ")) .add_col(TextSpan::from("Creation time: "))
.add_col( .add_col(TextSpan::new(ctime.as_str()).fg(Color::LightGreen));
TextSpanBuilder::new(ctime.as_str())
.with_foreground(Color::LightGreen)
.build(),
);
texts texts
.add_row() .add_row()
.add_col(TextSpan::from("Last modified time: ")) .add_col(TextSpan::from("Last modified time: "))
.add_col( .add_col(TextSpan::new(mtime.as_str()).fg(Color::LightBlue));
TextSpanBuilder::new(mtime.as_str())
.with_foreground(Color::LightBlue)
.build(),
);
texts texts
.add_row() .add_row()
.add_col(TextSpan::from("Last access time: ")) .add_col(TextSpan::from("Last access time: "))
.add_col( .add_col(TextSpan::new(atime.as_str()).fg(Color::LightRed));
TextSpanBuilder::new(atime.as_str())
.with_foreground(Color::LightRed)
.build(),
);
// User // User
#[cfg(target_family = "unix")] #[cfg(target_family = "unix")]
let username: String = match file.get_user() { let username: String = match file.get_user() {
@@ -911,22 +888,21 @@ impl FileTransferActivity {
}; };
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let group: String = format!("{}", file.get_group().unwrap_or(0)); let group: String = format!("{}", file.get_group().unwrap_or(0));
texts.add_row().add_col(TextSpan::from("User: ")).add_col( texts
TextSpanBuilder::new(username.as_str()) .add_row()
.with_foreground(Color::LightYellow) .add_col(TextSpan::from("User: "))
.build(), .add_col(TextSpan::new(username.as_str()).fg(Color::LightYellow));
); texts
texts.add_row().add_col(TextSpan::from("Group: ")).add_col( .add_row()
TextSpanBuilder::new(group.as_str()) .add_col(TextSpan::from("Group: "))
.with_foreground(Color::Blue) .add_col(TextSpan::new(group.as_str()).fg(Color::Blue));
.build(),
);
self.view.mount( self.view.mount(
super::COMPONENT_LIST_FILEINFO, super::COMPONENT_LIST_FILEINFO,
Box::new(Table::new( Box::new(Table::new(
TablePropsBuilder::default() TablePropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, Color::White) .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(), .build(),
)), )),
); );
@@ -941,22 +917,16 @@ impl FileTransferActivity {
let sorting_color = self.theme().transfer_status_sorting; let sorting_color = self.theme().transfer_status_sorting;
let hidden_color = self.theme().transfer_status_hidden; let hidden_color = self.theme().transfer_status_hidden;
let local_bar_spans: Vec<TextSpan> = vec![ let local_bar_spans: Vec<TextSpan> = vec![
TextSpanBuilder::new("File sorting: ") TextSpan::new("File sorting: ").fg(sorting_color),
.with_foreground(sorting_color) TextSpan::new(Self::get_file_sorting_str(self.local().get_file_sorting()))
.build(), .fg(sorting_color)
TextSpanBuilder::new(Self::get_file_sorting_str(self.local().get_file_sorting())) .reversed(),
.with_foreground(sorting_color) TextSpan::new(" Hidden files: ").fg(hidden_color),
.reversed() TextSpan::new(Self::get_hidden_files_str(
.build(),
TextSpanBuilder::new(" Hidden files: ")
.with_foreground(hidden_color)
.build(),
TextSpanBuilder::new(Self::get_hidden_files_str(
self.local().hidden_files_visible(), self.local().hidden_files_visible(),
)) ))
.with_foreground(hidden_color) .fg(hidden_color)
.reversed() .reversed(),
.build(),
]; ];
if let Some(props) = self.view.get_props(super::COMPONENT_SPAN_STATUS_BAR_LOCAL) { if let Some(props) = self.view.get_props(super::COMPONENT_SPAN_STATUS_BAR_LOCAL) {
self.view.update( self.view.update(
@@ -973,32 +943,23 @@ impl FileTransferActivity {
let hidden_color = self.theme().transfer_status_hidden; let hidden_color = self.theme().transfer_status_hidden;
let sync_color = self.theme().transfer_status_sync_browsing; let sync_color = self.theme().transfer_status_sync_browsing;
let remote_bar_spans: Vec<TextSpan> = vec![ let remote_bar_spans: Vec<TextSpan> = vec![
TextSpanBuilder::new("File sorting: ") TextSpan::new("File sorting: ").fg(sorting_color),
.with_foreground(sorting_color) TextSpan::new(Self::get_file_sorting_str(self.remote().get_file_sorting()))
.build(), .fg(sorting_color)
TextSpanBuilder::new(Self::get_file_sorting_str(self.remote().get_file_sorting())) .reversed(),
.with_foreground(sorting_color) TextSpan::new(" Hidden files: ").fg(hidden_color),
.reversed() TextSpan::new(Self::get_hidden_files_str(
.build(),
TextSpanBuilder::new(" Hidden files: ")
.with_foreground(hidden_color)
.build(),
TextSpanBuilder::new(Self::get_hidden_files_str(
self.remote().hidden_files_visible(), self.remote().hidden_files_visible(),
)) ))
.with_foreground(hidden_color) .fg(hidden_color)
.reversed() .reversed(),
.build(), TextSpan::new(" Sync Browsing: ").fg(sync_color),
TextSpanBuilder::new(" Sync Browsing: ") TextSpan::new(match self.browser.sync_browsing {
.with_foreground(sync_color)
.build(),
TextSpanBuilder::new(match self.browser.sync_browsing {
true => "ON ", true => "ON ",
false => "OFF", false => "OFF",
}) })
.with_foreground(sync_color) .fg(sync_color)
.reversed() .reversed(),
.build(),
]; ];
if let Some(props) = self.view.get_props(super::COMPONENT_SPAN_STATUS_BAR_REMOTE) { if let Some(props) = self.view.get_props(super::COMPONENT_SPAN_STATUS_BAR_REMOTE) {
self.view.update( self.view.update(
@@ -1017,253 +978,109 @@ impl FileTransferActivity {
let key_color = self.theme().misc_keys; let key_color = self.theme().misc_keys;
self.view.mount( self.view.mount(
super::COMPONENT_TEXT_HELP, super::COMPONENT_TEXT_HELP,
Box::new(Scrolltable::new( Box::new(List::new(
ScrollTablePropsBuilder::default() ListPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, Color::White) .with_borders(Borders::ALL, BorderType::Rounded, Color::White)
.with_highlighted_str(Some("?")) .with_highlighted_str(Some("?"))
.with_max_scroll_step(8) .with_max_scroll_step(8)
.bold() .bold()
.with_table( .scrollable(true)
Some(String::from("Help")), .with_title("Help", Alignment::Center)
.with_rows(
TableBuilder::default() TableBuilder::default()
.add_col( .add_col(TextSpan::new("<ESC>").bold().fg(key_color))
TextSpanBuilder::new("<ESC>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Disconnect")) .add_col(TextSpan::from(" Disconnect"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<TAB>").bold().fg(key_color))
TextSpanBuilder::new("<TAB>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from( .add_col(TextSpan::from(
" Switch between explorer and logs", " Switch between explorer and logs",
)) ))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<BACKSPACE>").bold().fg(key_color))
TextSpanBuilder::new("<BACKSPACE>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Go to previous directory")) .add_col(TextSpan::from(" Go to previous directory"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<RIGHT/LEFT>").bold().fg(key_color))
TextSpanBuilder::new("<RIGHT/LEFT>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Change explorer tab")) .add_col(TextSpan::from(" Change explorer tab"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<UP/DOWN>").bold().fg(key_color))
TextSpanBuilder::new("<UP/DOWN>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Move up/down in list")) .add_col(TextSpan::from(" Move up/down in list"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<ENTER>").bold().fg(key_color))
TextSpanBuilder::new("<ENTER>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Enter directory")) .add_col(TextSpan::from(" Enter directory"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<SPACE>").bold().fg(key_color))
TextSpanBuilder::new("<SPACE>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Upload/Download file")) .add_col(TextSpan::from(" Upload/Download file"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<A>").bold().fg(key_color))
TextSpanBuilder::new("<A>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Toggle hidden files")) .add_col(TextSpan::from(" Toggle hidden files"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<B>").bold().fg(key_color))
TextSpanBuilder::new("<B>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Change file sorting mode")) .add_col(TextSpan::from(" Change file sorting mode"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<C>").bold().fg(key_color))
TextSpanBuilder::new("<C>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Copy")) .add_col(TextSpan::from(" Copy"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<D>").bold().fg(key_color))
TextSpanBuilder::new("<D>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Make directory")) .add_col(TextSpan::from(" Make directory"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<G>").bold().fg(key_color))
TextSpanBuilder::new("<G>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Go to path")) .add_col(TextSpan::from(" Go to path"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<H>").bold().fg(key_color))
TextSpanBuilder::new("<H>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Show help")) .add_col(TextSpan::from(" Show help"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<I>").bold().fg(key_color))
TextSpanBuilder::new("<I>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Show info about selected file")) .add_col(TextSpan::from(" Show info about selected file"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<L>").bold().fg(key_color))
TextSpanBuilder::new("<L>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Reload directory content")) .add_col(TextSpan::from(" Reload directory content"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<M>").bold().fg(key_color))
TextSpanBuilder::new("<M>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Select file")) .add_col(TextSpan::from(" Select file"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<N>").bold().fg(key_color))
TextSpanBuilder::new("<N>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Create new file")) .add_col(TextSpan::from(" Create new file"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<O>").bold().fg(key_color))
TextSpanBuilder::new("<O>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from( .add_col(TextSpan::from(
" Open text file with preferred editor", " Open text file with preferred editor",
)) ))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<Q>").bold().fg(key_color))
TextSpanBuilder::new("<Q>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Quit termscp")) .add_col(TextSpan::from(" Quit termscp"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<R>").bold().fg(key_color))
TextSpanBuilder::new("<R>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Rename file")) .add_col(TextSpan::from(" Rename file"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<S>").bold().fg(key_color))
TextSpanBuilder::new("<S>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Save file as")) .add_col(TextSpan::from(" Save file as"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<U>").bold().fg(key_color))
TextSpanBuilder::new("<U>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Go to parent directory")) .add_col(TextSpan::from(" Go to parent directory"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<V>").bold().fg(key_color))
TextSpanBuilder::new("<V>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from( .add_col(TextSpan::from(
" Open file with default application for file type", " Open file with default application for file type",
)) ))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<W>").bold().fg(key_color))
TextSpanBuilder::new("<W>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from( .add_col(TextSpan::from(
" Open file with specified application", " Open file with specified application",
)) ))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<X>").bold().fg(key_color))
TextSpanBuilder::new("<X>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Execute shell command")) .add_col(TextSpan::from(" Execute shell command"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<Y>").bold().fg(key_color))
TextSpanBuilder::new("<Y>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Toggle synchronized browsing")) .add_col(TextSpan::from(" Toggle synchronized browsing"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<DEL|E>").bold().fg(key_color))
TextSpanBuilder::new("<DEL|E>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Delete selected file")) .add_col(TextSpan::from(" Delete selected file"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<CTRL+A>").bold().fg(key_color))
TextSpanBuilder::new("<CTRL+A>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Select all files")) .add_col(TextSpan::from(" Select all files"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<CTRL+C>").bold().fg(key_color))
TextSpanBuilder::new("<CTRL+C>")
.bold()
.with_foreground(key_color)
.build(),
)
.add_col(TextSpan::from(" Interrupt file transfer")) .add_col(TextSpan::from(" Interrupt file transfer"))
.build(), .build(),
) )

View File

@@ -74,65 +74,67 @@ impl SetupActivity {
None => None, None => None,
Some(msg) => match msg { Some(msg) => match msg {
// Input field <DOWN> // Input field <DOWN>
(COMPONENT_INPUT_TEXT_EDITOR, &MSG_KEY_DOWN) => { (COMPONENT_INPUT_TEXT_EDITOR, key) if key == &MSG_KEY_DOWN => {
self.view.active(COMPONENT_RADIO_DEFAULT_PROTOCOL); self.view.active(COMPONENT_RADIO_DEFAULT_PROTOCOL);
None 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); self.view.active(COMPONENT_RADIO_HIDDEN_FILES);
None None
} }
(COMPONENT_RADIO_HIDDEN_FILES, &MSG_KEY_DOWN) => { (COMPONENT_RADIO_HIDDEN_FILES, key) if key == &MSG_KEY_DOWN => {
self.view.active(COMPONENT_RADIO_UPDATES); self.view.active(COMPONENT_RADIO_UPDATES);
None None
} }
(COMPONENT_RADIO_UPDATES, &MSG_KEY_DOWN) => { (COMPONENT_RADIO_UPDATES, key) if key == &MSG_KEY_DOWN => {
self.view.active(COMPONENT_RADIO_GROUP_DIRS); self.view.active(COMPONENT_RADIO_GROUP_DIRS);
None 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); self.view.active(COMPONENT_INPUT_LOCAL_FILE_FMT);
None 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); self.view.active(COMPONENT_INPUT_REMOTE_FILE_FMT);
None 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); self.view.active(COMPONENT_INPUT_TEXT_EDITOR);
None None
} }
// Input field <UP> // Input field <UP>
(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); self.view.active(COMPONENT_INPUT_LOCAL_FILE_FMT);
None 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); self.view.active(COMPONENT_RADIO_GROUP_DIRS);
None None
} }
(COMPONENT_RADIO_GROUP_DIRS, &MSG_KEY_UP) => { (COMPONENT_RADIO_GROUP_DIRS, key) if key == &MSG_KEY_UP => {
self.view.active(COMPONENT_RADIO_UPDATES); self.view.active(COMPONENT_RADIO_UPDATES);
None None
} }
(COMPONENT_RADIO_UPDATES, &MSG_KEY_UP) => { (COMPONENT_RADIO_UPDATES, key) if key == &MSG_KEY_UP => {
self.view.active(COMPONENT_RADIO_HIDDEN_FILES); self.view.active(COMPONENT_RADIO_HIDDEN_FILES);
None 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); self.view.active(COMPONENT_RADIO_DEFAULT_PROTOCOL);
None 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); self.view.active(COMPONENT_INPUT_TEXT_EDITOR);
None 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); self.view.active(COMPONENT_INPUT_REMOTE_FILE_FMT);
None None
} }
// Error <ENTER> or <ESC> // Error <ENTER> or <ESC>
(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 // Umount text error
self.umount_error(); self.umount_error();
None None
@@ -161,7 +163,9 @@ impl SetupActivity {
} }
(COMPONENT_RADIO_QUIT, _) => None, (COMPONENT_RADIO_QUIT, _) => None,
// Close help // 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 // Umount help
self.umount_help(); self.umount_help();
None None
@@ -189,12 +193,12 @@ impl SetupActivity {
None None
} }
// <CTRL+H> Show help // <CTRL+H> Show help
(_, &MSG_KEY_CTRL_H) => { (_, key) if key == &MSG_KEY_CTRL_H => {
// Show help // Show help
self.mount_help(); self.mount_help();
None None
} }
(_, &MSG_KEY_TAB) => { (_, key) if key == &MSG_KEY_TAB => {
// Change view // Change view
if let Err(err) = self.action_change_tab(ViewLayout::SshKeys) { if let Err(err) = self.action_change_tab(ViewLayout::SshKeys) {
self.mount_error(err.as_str()); self.mount_error(err.as_str());
@@ -202,7 +206,7 @@ impl SetupActivity {
None None
} }
// <CTRL+R> Revert changes // <CTRL+R> Revert changes
(_, &MSG_KEY_CTRL_R) => { (_, key) if key == &MSG_KEY_CTRL_R => {
// Revert changes // Revert changes
if let Err(err) = self.action_reset_config() { if let Err(err) = self.action_reset_config() {
self.mount_error(err.as_str()); self.mount_error(err.as_str());
@@ -210,13 +214,13 @@ impl SetupActivity {
None None
} }
// <CTRL+S> Save // <CTRL+S> Save
(_, &MSG_KEY_CTRL_S) => { (_, key) if key == &MSG_KEY_CTRL_S => {
// Show save // Show save
self.mount_save_popup(); self.mount_save_popup();
None None
} }
// <ESC> // <ESC>
(_, &MSG_KEY_ESC) => { (_, key) if key == &MSG_KEY_ESC => {
self.action_on_esc(); self.action_on_esc();
None None
} }
@@ -232,7 +236,9 @@ impl SetupActivity {
None => None, None => None,
Some(msg) => match msg { Some(msg) => match msg {
// Error <ENTER> or <ESC> // Error <ENTER> or <ESC>
(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 // Umount text error
self.umount_error(); self.umount_error();
None None
@@ -261,7 +267,9 @@ impl SetupActivity {
} }
(COMPONENT_RADIO_QUIT, _) => None, (COMPONENT_RADIO_QUIT, _) => None,
// Close help // 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 // Umount help
self.umount_help(); self.umount_help();
None None
@@ -300,28 +308,30 @@ impl SetupActivity {
(COMPONENT_RADIO_SAVE, _) => None, (COMPONENT_RADIO_SAVE, _) => None,
// Edit SSH Key // Edit SSH Key
// <CTRL+H> Show help // <CTRL+H> Show help
(_, &MSG_KEY_CTRL_H) => { (_, key) if key == &MSG_KEY_CTRL_H => {
// Show help // Show help
self.mount_help(); self.mount_help();
None None
} }
// New key <DOWN> // New key <DOWN>
(COMPONENT_INPUT_SSH_HOST, &MSG_KEY_DOWN) => { (COMPONENT_INPUT_SSH_HOST, key) if key == &MSG_KEY_DOWN => {
self.view.active(COMPONENT_INPUT_SSH_USERNAME); self.view.active(COMPONENT_INPUT_SSH_USERNAME);
None 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); self.view.active(COMPONENT_INPUT_SSH_HOST);
None None
} }
// New key <UP> // New key <UP>
(COMPONENT_INPUT_SSH_USERNAME, &MSG_KEY_UP) (COMPONENT_INPUT_SSH_USERNAME, key) | (COMPONENT_INPUT_SSH_USERNAME, key)
| (COMPONENT_INPUT_SSH_USERNAME, &MSG_KEY_TAB) => { if key == &MSG_KEY_UP || key == &MSG_KEY_TAB =>
{
self.view.active(COMPONENT_INPUT_SSH_HOST); self.view.active(COMPONENT_INPUT_SSH_HOST);
None None
} }
(COMPONENT_INPUT_SSH_HOST, &MSG_KEY_UP) (COMPONENT_INPUT_SSH_HOST, key) | (COMPONENT_INPUT_SSH_HOST, key)
| (COMPONENT_INPUT_SSH_HOST, &MSG_KEY_TAB) => { if key == &MSG_KEY_UP || key == &MSG_KEY_TAB =>
{
self.view.active(COMPONENT_INPUT_SSH_USERNAME); self.view.active(COMPONENT_INPUT_SSH_USERNAME);
None None
} }
@@ -335,14 +345,15 @@ impl SetupActivity {
None None
} }
// New key <ESC> // New key <ESC>
(COMPONENT_INPUT_SSH_HOST, &MSG_KEY_ESC) (COMPONENT_INPUT_SSH_HOST, key) | (COMPONENT_INPUT_SSH_USERNAME, key)
| (COMPONENT_INPUT_SSH_USERNAME, &MSG_KEY_ESC) => { if key == &MSG_KEY_ESC =>
{
// Umount new ssh key // Umount new ssh key
self.umount_new_ssh_key(); self.umount_new_ssh_key();
None None
} }
// <CTRL+N> New key // <CTRL+N> 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 // Show new key popup
self.mount_new_ssh_key(); self.mount_new_ssh_key();
None None
@@ -356,13 +367,14 @@ impl SetupActivity {
None None
} }
// <DEL | CTRL+E> Show delete // <DEL | CTRL+E> Show delete
(COMPONENT_LIST_SSH_KEYS, &MSG_KEY_CTRL_E) (COMPONENT_LIST_SSH_KEYS, key) | (COMPONENT_LIST_SSH_KEYS, key)
| (COMPONENT_LIST_SSH_KEYS, &MSG_KEY_DEL) => { if key == &MSG_KEY_CTRL_E || key == &MSG_KEY_DEL =>
{
// Show delete key // Show delete key
self.mount_del_ssh_key(); self.mount_del_ssh_key();
None None
} }
(_, &MSG_KEY_TAB) => { (_, key) if key == &MSG_KEY_TAB => {
// Change view // Change view
if let Err(err) = self.action_change_tab(ViewLayout::Theme) { if let Err(err) = self.action_change_tab(ViewLayout::Theme) {
self.mount_error(err.as_str()); self.mount_error(err.as_str());
@@ -370,7 +382,7 @@ impl SetupActivity {
None None
} }
// <CTRL+R> Revert changes // <CTRL+R> Revert changes
(_, &MSG_KEY_CTRL_R) => { (_, key) if key == &MSG_KEY_CTRL_R => {
// Revert changes // Revert changes
if let Err(err) = self.action_reset_config() { if let Err(err) = self.action_reset_config() {
self.mount_error(err.as_str()); self.mount_error(err.as_str());
@@ -378,13 +390,13 @@ impl SetupActivity {
None None
} }
// <CTRL+S> Save // <CTRL+S> Save
(_, &MSG_KEY_CTRL_S) => { (_, key) if key == &MSG_KEY_CTRL_S => {
// Show save // Show save
self.mount_save_popup(); self.mount_save_popup();
None None
} }
// <ESC> // <ESC>
(_, &MSG_KEY_ESC) => { (_, key) if key == &MSG_KEY_ESC => {
self.action_on_esc(); self.action_on_esc();
None None
} }
@@ -400,217 +412,217 @@ impl SetupActivity {
None => None, None => None,
Some(msg) => match msg { Some(msg) => match msg {
// Input fields // 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); self.view.active(COMPONENT_COLOR_AUTH_ADDR);
None 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); self.view.active(COMPONENT_COLOR_AUTH_PORT);
None 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); self.view.active(COMPONENT_COLOR_AUTH_USERNAME);
None 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); self.view.active(COMPONENT_COLOR_AUTH_PASSWORD);
None 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); self.view.active(COMPONENT_COLOR_AUTH_BOOKMARKS);
None 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); self.view.active(COMPONENT_COLOR_AUTH_RECENTS);
None 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); self.view.active(COMPONENT_COLOR_MISC_ERROR);
None 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); self.view.active(COMPONENT_COLOR_MISC_INPUT);
None 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); self.view.active(COMPONENT_COLOR_MISC_KEYS);
None 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); self.view.active(COMPONENT_COLOR_MISC_QUIT);
None 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); self.view.active(COMPONENT_COLOR_MISC_SAVE);
None 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); self.view.active(COMPONENT_COLOR_MISC_WARN);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_BG);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_FG);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_HG);
None None
} }
(COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_HG, &MSG_KEY_DOWN) => { (COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_HG, key) if key == &MSG_KEY_DOWN => {
self.view self.view
.active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_BG); .active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_BG);
None None
} }
(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_BG, &MSG_KEY_DOWN) => { (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_BG, key) if key == &MSG_KEY_DOWN => {
self.view self.view
.active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG); .active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG);
None None
} }
(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG, &MSG_KEY_DOWN) => { (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG, key) if key == &MSG_KEY_DOWN => {
self.view self.view
.active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_HG); .active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_HG);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_PROG_BAR_FULL);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_PROG_BAR_PARTIAL);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_LOG_BG);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_LOG_WIN);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_STATUS_SORTING);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_STATUS_HIDDEN);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_STATUS_SYNC);
None 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); self.view.active(COMPONENT_COLOR_AUTH_PROTOCOL);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_STATUS_SYNC);
None 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); self.view.active(COMPONENT_COLOR_AUTH_PROTOCOL);
None 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); self.view.active(COMPONENT_COLOR_AUTH_ADDR);
None 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); self.view.active(COMPONENT_COLOR_AUTH_PORT);
None 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); self.view.active(COMPONENT_COLOR_AUTH_USERNAME);
None 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); self.view.active(COMPONENT_COLOR_AUTH_PASSWORD);
None 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); self.view.active(COMPONENT_COLOR_AUTH_BOOKMARKS);
None 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); self.view.active(COMPONENT_COLOR_AUTH_RECENTS);
None 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); self.view.active(COMPONENT_COLOR_MISC_ERROR);
None 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); self.view.active(COMPONENT_COLOR_MISC_INPUT);
None 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); self.view.active(COMPONENT_COLOR_MISC_KEYS);
None 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); self.view.active(COMPONENT_COLOR_MISC_QUIT);
None 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); self.view.active(COMPONENT_COLOR_MISC_SAVE);
None 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); self.view.active(COMPONENT_COLOR_MISC_WARN);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_BG);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_FG);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_EXPLORER_LOCAL_HG);
None None
} }
(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG, &MSG_KEY_UP) => { (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG, key) if key == &MSG_KEY_UP => {
self.view self.view
.active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_BG); .active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_BG);
None None
} }
(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_HG, &MSG_KEY_UP) => { (COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_HG, key) if key == &MSG_KEY_UP => {
self.view self.view
.active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG); .active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_FG);
None None
} }
(COMPONENT_COLOR_TRANSFER_PROG_BAR_FULL, &MSG_KEY_UP) => { (COMPONENT_COLOR_TRANSFER_PROG_BAR_FULL, key) if key == &MSG_KEY_UP => {
self.view self.view
.active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_HG); .active(COMPONENT_COLOR_TRANSFER_EXPLORER_REMOTE_HG);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_PROG_BAR_FULL);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_PROG_BAR_PARTIAL);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_LOG_BG);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_LOG_WIN);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_STATUS_SORTING);
None 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); self.view.active(COMPONENT_COLOR_TRANSFER_STATUS_HIDDEN);
None None
} }
@@ -624,7 +636,9 @@ impl SetupActivity {
None None
} }
// Error <ENTER> or <ESC> // Error <ENTER> or <ESC>
(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 // Umount text error
self.umount_error(); self.umount_error();
None None
@@ -653,7 +667,9 @@ impl SetupActivity {
} }
(COMPONENT_RADIO_QUIT, _) => None, (COMPONENT_RADIO_QUIT, _) => None,
// Close help // 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 // Umount help
self.umount_help(); self.umount_help();
None None
@@ -676,12 +692,12 @@ impl SetupActivity {
(COMPONENT_RADIO_SAVE, _) => None, (COMPONENT_RADIO_SAVE, _) => None,
// Edit SSH Key // Edit SSH Key
// <CTRL+H> Show help // <CTRL+H> Show help
(_, &MSG_KEY_CTRL_H) => { (_, key) if key == &MSG_KEY_CTRL_H => {
// Show help // Show help
self.mount_help(); self.mount_help();
None None
} }
(_, &MSG_KEY_TAB) => { (_, key) if key == &MSG_KEY_TAB => {
// Change view // Change view
if let Err(err) = self.action_change_tab(ViewLayout::SetupForm) { if let Err(err) = self.action_change_tab(ViewLayout::SetupForm) {
self.mount_error(err.as_str()); self.mount_error(err.as_str());
@@ -689,7 +705,7 @@ impl SetupActivity {
None None
} }
// <CTRL+R> Revert changes // <CTRL+R> Revert changes
(_, &MSG_KEY_CTRL_R) => { (_, key) if key == &MSG_KEY_CTRL_R => {
// Revert changes // Revert changes
if let Err(err) = self.action_reset_theme() { if let Err(err) = self.action_reset_theme() {
self.mount_error(err.as_str()); self.mount_error(err.as_str());
@@ -697,13 +713,13 @@ impl SetupActivity {
None None
} }
// <CTRL+S> Save // <CTRL+S> Save
(_, &MSG_KEY_CTRL_S) => { (_, key) if key == &MSG_KEY_CTRL_S => {
// Show save // Show save
self.mount_save_popup(); self.mount_save_popup();
None None
} }
// <ESC> // <ESC>
(_, &MSG_KEY_ESC) => { (_, key) if key == &MSG_KEY_ESC => {
self.action_on_esc(); self.action_on_esc();
None None
} }

View File

@@ -34,14 +34,14 @@ use super::*;
pub use setup::*; pub use setup::*;
pub use ssh_keys::*; pub use ssh_keys::*;
pub use theme::*; pub use theme::*;
// Locals
use crate::ui::components::msgbox::{MsgBox, MsgBoxPropsBuilder};
// Ext // Ext
use tuirealm::components::{ use tui_realm_stdlib::{
list::{List, ListPropsBuilder},
paragraph::{Paragraph, ParagraphPropsBuilder},
radio::{Radio, RadioPropsBuilder}, 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::{ use tuirealm::tui::{
style::Color, style::Color,
widgets::{BorderType, Borders}, widgets::{BorderType, Borders},
@@ -79,12 +79,13 @@ impl SetupActivity {
// Mount // Mount
self.view.mount( self.view.mount(
super::COMPONENT_TEXT_ERROR, super::COMPONENT_TEXT_ERROR,
Box::new(MsgBox::new( Box::new(Paragraph::new(
MsgBoxPropsBuilder::default() ParagraphPropsBuilder::default()
.with_foreground(Color::Red) .with_foreground(Color::Red)
.bold() .bold()
.with_borders(Borders::ALL, BorderType::Rounded, Color::Red) .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(), .build(),
)), )),
); );
@@ -110,16 +111,15 @@ impl SetupActivity {
.with_color(Color::LightRed) .with_color(Color::LightRed)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightRed) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightRed)
.with_options( .with_title(
Some(String::from( "There are unsaved changes! Save changes before leaving?",
"There are unsaved changes! Save changes before leaving?", Alignment::Center,
)),
vec![
String::from("Save"),
String::from("Don't save"),
String::from("Cancel"),
],
) )
.with_options(&[
String::from("Save"),
String::from("Don't save"),
String::from("Cancel"),
])
.build(), .build(),
)), )),
); );
@@ -145,10 +145,8 @@ impl SetupActivity {
.with_color(Color::LightYellow) .with_color(Color::LightYellow)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightYellow) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightYellow)
.with_options( .with_title("Save changes?", Alignment::Center)
Some(String::from("Save changes?")), .with_options(&[String::from("Yes"), String::from("No")])
vec![String::from("Yes"), String::from("No")],
)
.build(), .build(),
)), )),
); );
@@ -163,91 +161,81 @@ impl SetupActivity {
self.view.umount(super::COMPONENT_RADIO_SAVE); 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("<CTRL+H>").bold().fg(Color::Cyan),
TextSpan::new(" to show keybindings").bold(),
])
.build(),
)),
);
}
/// ### mount_help /// ### mount_help
/// ///
/// Mount help /// Mount help
pub(super) fn mount_help(&mut self) { pub(super) fn mount_help(&mut self) {
self.view.mount( self.view.mount(
super::COMPONENT_TEXT_HELP, super::COMPONENT_TEXT_HELP,
Box::new(Scrolltable::new( Box::new(List::new(
ScrollTablePropsBuilder::default() ListPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, Color::White) .with_borders(Borders::ALL, BorderType::Rounded, Color::White)
.with_highlighted_str(Some("?")) .with_highlighted_str(Some("?"))
.with_max_scroll_step(8) .with_max_scroll_step(8)
.bold() .bold()
.with_table( .with_title("Help", Alignment::Center)
Some(String::from("Help")), .scrollable(true)
.with_rows(
TableBuilder::default() TableBuilder::default()
.add_col( .add_col(TextSpan::new("<ESC>").bold().fg(Color::Cyan))
TextSpanBuilder::new("<ESC>")
.bold()
.with_foreground(Color::Cyan)
.build(),
)
.add_col(TextSpan::from(" Exit setup")) .add_col(TextSpan::from(" Exit setup"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<TAB>").bold().fg(Color::Cyan))
TextSpanBuilder::new("<TAB>")
.bold()
.with_foreground(Color::Cyan)
.build(),
)
.add_col(TextSpan::from(" Change setup page")) .add_col(TextSpan::from(" Change setup page"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<RIGHT/LEFT>").bold().fg(Color::Cyan))
TextSpanBuilder::new("<RIGHT/LEFT>")
.bold()
.with_foreground(Color::Cyan)
.build(),
)
.add_col(TextSpan::from(" Change cursor")) .add_col(TextSpan::from(" Change cursor"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<UP/DOWN>").bold().fg(Color::Cyan))
TextSpanBuilder::new("<UP/DOWN>")
.bold()
.with_foreground(Color::Cyan)
.build(),
)
.add_col(TextSpan::from(" Change input field")) .add_col(TextSpan::from(" Change input field"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<ENTER>").bold().fg(Color::Cyan))
TextSpanBuilder::new("<ENTER>")
.bold()
.with_foreground(Color::Cyan)
.build(),
)
.add_col(TextSpan::from(" Select / Dismiss popup")) .add_col(TextSpan::from(" Select / Dismiss popup"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<DEL|E>").bold().fg(Color::Cyan))
TextSpanBuilder::new("<DEL|E>")
.bold()
.with_foreground(Color::Cyan)
.build(),
)
.add_col(TextSpan::from(" Delete SSH key")) .add_col(TextSpan::from(" Delete SSH key"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<CTRL+N>").bold().fg(Color::Cyan))
TextSpanBuilder::new("<CTRL+N>")
.bold()
.with_foreground(Color::Cyan)
.build(),
)
.add_col(TextSpan::from(" New SSH key")) .add_col(TextSpan::from(" New SSH key"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<CTRL+R>").bold().fg(Color::Cyan))
TextSpanBuilder::new("<CTRL+R>")
.bold()
.with_foreground(Color::Cyan)
.build(),
)
.add_col(TextSpan::from(" Revert changes")) .add_col(TextSpan::from(" Revert changes"))
.add_row() .add_row()
.add_col( .add_col(TextSpan::new("<CTRL+S>").bold().fg(Color::Cyan))
TextSpanBuilder::new("<CTRL+S>")
.bold()
.with_foreground(Color::Cyan)
.build(),
)
.add_col(TextSpan::from(" Save configuration")) .add_col(TextSpan::from(" Save configuration"))
.build(), .build(),
) )

View File

@@ -33,10 +33,9 @@ use crate::fs::explorer::GroupDirs;
use crate::utils::ui::draw_area_in; use crate::utils::ui::draw_area_in;
// Ext // Ext
use std::path::PathBuf; use std::path::PathBuf;
use tuirealm::components::{ use tui_realm_stdlib::{
input::{Input, InputPropsBuilder}, input::{Input, InputPropsBuilder},
radio::{Radio, RadioPropsBuilder}, radio::{Radio, RadioPropsBuilder},
span::{Span, SpanPropsBuilder},
}; };
use tuirealm::tui::{ use tuirealm::tui::{
layout::{Constraint, Direction, Layout}, layout::{Constraint, Direction, Layout},
@@ -44,7 +43,7 @@ use tuirealm::tui::{
widgets::{BorderType, Borders, Clear}, widgets::{BorderType, Borders, Clear},
}; };
use tuirealm::{ use tuirealm::{
props::{PropsBuilder, TextSpanBuilder}, props::{Alignment, PropsBuilder},
Payload, Value, View, Payload, Value, View,
}; };
@@ -59,41 +58,9 @@ impl SetupActivity {
self.view = View::init(); self.view = View::init();
// Common stuff // Common stuff
// Radio tab // Radio tab
self.view.mount( self.mount_header_tab(0);
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(),
)),
);
// Footer // Footer
self.view.mount( self.mount_footer();
super::COMPONENT_TEXT_FOOTER,
Box::new(Span::new(
SpanPropsBuilder::default()
.with_spans(vec![
TextSpanBuilder::new("Press ").bold().build(),
TextSpanBuilder::new("<CTRL+H>")
.bold()
.with_foreground(Color::Cyan)
.build(),
TextSpanBuilder::new(" to show keybindings").bold().build(),
])
.build(),
)),
);
// Input fields // Input fields
self.view.mount( self.view.mount(
super::COMPONENT_INPUT_TEXT_EDITOR, super::COMPONENT_INPUT_TEXT_EDITOR,
@@ -101,7 +68,7 @@ impl SetupActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_foreground(Color::LightGreen) .with_foreground(Color::LightGreen)
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightGreen) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightGreen)
.with_label(String::from("Text editor")) .with_label("Text editor", Alignment::Left)
.build(), .build(),
)), )),
); );
@@ -113,15 +80,13 @@ impl SetupActivity {
.with_color(Color::LightCyan) .with_color(Color::LightCyan)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightCyan) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightCyan)
.with_options( .with_title("Default file transfer protocol", Alignment::Left)
Some(String::from("Default file transfer protocol")), .with_options(&[
vec![ String::from("SFTP"),
String::from("SFTP"), String::from("SCP"),
String::from("SCP"), String::from("FTP"),
String::from("FTP"), String::from("FTPS"),
String::from("FTPS"), ])
],
)
.build(), .build(),
)), )),
); );
@@ -132,10 +97,8 @@ impl SetupActivity {
.with_color(Color::LightRed) .with_color(Color::LightRed)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightRed) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightRed)
.with_options( .with_title("Show hidden files (by default)?", Alignment::Left)
Some(String::from("Show hidden files (by default)")), .with_options(&[String::from("Yes"), String::from("No")])
vec![String::from("Yes"), String::from("No")],
)
.build(), .build(),
)), )),
); );
@@ -146,10 +109,8 @@ impl SetupActivity {
.with_color(Color::LightYellow) .with_color(Color::LightYellow)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightYellow) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightYellow)
.with_options( .with_title("Check for updates?", Alignment::Left)
Some(String::from("Check for updates?")), .with_options(&[String::from("Yes"), String::from("No")])
vec![String::from("Yes"), String::from("No")],
)
.build(), .build(),
)), )),
); );
@@ -160,14 +121,12 @@ impl SetupActivity {
.with_color(Color::LightMagenta) .with_color(Color::LightMagenta)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightMagenta) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightMagenta)
.with_options( .with_title("Group directories", Alignment::Left)
Some(String::from("Group directories")), .with_options(&[
vec![ String::from("Display first"),
String::from("Display first"), String::from("Display Last"),
String::from("Display Last"), String::from("No"),
String::from("No"), ])
],
)
.build(), .build(),
)), )),
); );
@@ -177,7 +136,7 @@ impl SetupActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_foreground(Color::LightBlue) .with_foreground(Color::LightBlue)
.with_borders(Borders::ALL, BorderType::Rounded, 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(), .build(),
)), )),
); );
@@ -187,7 +146,7 @@ impl SetupActivity {
InputPropsBuilder::default() InputPropsBuilder::default()
.with_foreground(Color::LightGreen) .with_foreground(Color::LightGreen)
.with_borders(Borders::ALL, BorderType::Rounded, 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(), .build(),
)), )),
); );

View File

@@ -31,10 +31,9 @@ use super::{Context, SetupActivity};
use crate::ui::components::bookmark_list::{BookmarkList, BookmarkListPropsBuilder}; use crate::ui::components::bookmark_list::{BookmarkList, BookmarkListPropsBuilder};
use crate::utils::ui::draw_area_in; use crate::utils::ui::draw_area_in;
// Ext // Ext
use tuirealm::components::{ use tui_realm_stdlib::{
input::{Input, InputPropsBuilder}, input::{Input, InputPropsBuilder},
radio::{Radio, RadioPropsBuilder}, radio::{Radio, RadioPropsBuilder},
span::{Span, SpanPropsBuilder},
}; };
use tuirealm::tui::{ use tuirealm::tui::{
layout::{Constraint, Direction, Layout}, layout::{Constraint, Direction, Layout},
@@ -42,7 +41,7 @@ use tuirealm::tui::{
widgets::{BorderType, Borders, Clear}, widgets::{BorderType, Borders, Clear},
}; };
use tuirealm::{ use tuirealm::{
props::{PropsBuilder, TextSpanBuilder}, props::{Alignment, PropsBuilder},
View, View,
}; };
@@ -57,46 +56,15 @@ impl SetupActivity {
self.view = View::init(); self.view = View::init();
// Common stuff // Common stuff
// Radio tab // Radio tab
self.view.mount( // Radio tab
super::COMPONENT_RADIO_TAB, self.mount_header_tab(1);
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(),
)),
);
// Footer // Footer
self.view.mount( self.mount_footer();
super::COMPONENT_TEXT_FOOTER,
Box::new(Span::new(
SpanPropsBuilder::default()
.with_spans(vec![
TextSpanBuilder::new("Press ").bold().build(),
TextSpanBuilder::new("<CTRL+H>")
.bold()
.with_foreground(Color::Cyan)
.build(),
TextSpanBuilder::new(" to show keybindings").bold().build(),
])
.build(),
)),
);
self.view.mount( self.view.mount(
super::COMPONENT_LIST_SSH_KEYS, super::COMPONENT_LIST_SSH_KEYS,
Box::new(BookmarkList::new( Box::new(BookmarkList::new(
BookmarkListPropsBuilder::default() 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_borders(Borders::ALL, BorderType::Plain, Color::LightGreen)
.with_background(Color::LightGreen) .with_background(Color::LightGreen)
.with_foreground(Color::Black) .with_foreground(Color::Black)
@@ -211,10 +179,8 @@ impl SetupActivity {
.with_color(Color::LightRed) .with_color(Color::LightRed)
.with_inverted_color(Color::Black) .with_inverted_color(Color::Black)
.with_borders(Borders::ALL, BorderType::Rounded, Color::LightRed) .with_borders(Borders::ALL, BorderType::Rounded, Color::LightRed)
.with_options( .with_title("Delete key?", Alignment::Center)
Some(String::from("Delete key?")), .with_options(&[String::from("Yes"), String::from("No")])
vec![String::from("Yes"), String::from("No")],
)
.with_value(1) // Default: No .with_value(1) // Default: No
.build(), .build(),
)), )),
@@ -238,7 +204,7 @@ impl SetupActivity {
super::COMPONENT_INPUT_SSH_HOST, super::COMPONENT_INPUT_SSH_HOST,
Box::new(Input::new( Box::new(Input::new(
InputPropsBuilder::default() InputPropsBuilder::default()
.with_label(String::from("Hostname or address")) .with_label("Hostname or address", Alignment::Center)
.with_borders( .with_borders(
Borders::TOP | Borders::RIGHT | Borders::LEFT, Borders::TOP | Borders::RIGHT | Borders::LEFT,
BorderType::Plain, BorderType::Plain,
@@ -251,7 +217,7 @@ impl SetupActivity {
super::COMPONENT_INPUT_SSH_USERNAME, super::COMPONENT_INPUT_SSH_USERNAME,
Box::new(Input::new( Box::new(Input::new(
InputPropsBuilder::default() InputPropsBuilder::default()
.with_label(String::from("Username")) .with_label("Username", Alignment::Center)
.with_borders( .with_borders(
Borders::BOTTOM | Borders::RIGHT | Borders::LEFT, Borders::BOTTOM | Borders::RIGHT | Borders::LEFT,
BorderType::Plain, BorderType::Plain,
@@ -287,7 +253,7 @@ impl SetupActivity {
}) })
.collect(); .collect();
let props = BookmarkListPropsBuilder::from(props) let props = BookmarkListPropsBuilder::from(props)
.with_bookmarks(Some(String::from("SSH Keys")), keys) .with_bookmarks(keys)
.build(); .build();
self.view.update(super::COMPONENT_LIST_SSH_KEYS, props); self.view.update(super::COMPONENT_LIST_SSH_KEYS, props);
} }

View File

@@ -33,18 +33,14 @@ use crate::ui::components::color_picker::{ColorPicker, ColorPickerPropsBuilder};
use crate::utils::parser::parse_color; use crate::utils::parser::parse_color;
use crate::utils::ui::draw_area_in; use crate::utils::ui::draw_area_in;
// Ext // Ext
use tuirealm::components::{ use tui_realm_stdlib::label::{Label, LabelPropsBuilder};
label::{Label, LabelPropsBuilder},
radio::{Radio, RadioPropsBuilder},
span::{Span, SpanPropsBuilder},
};
use tuirealm::tui::{ use tuirealm::tui::{
layout::{Constraint, Direction, Layout}, layout::{Constraint, Direction, Layout},
style::Color, style::Color,
widgets::{BorderType, Borders, Clear}, widgets::{BorderType, Borders, Clear},
}; };
use tuirealm::{ use tuirealm::{
props::{PropsBuilder, TextSpanBuilder}, props::{Alignment, PropsBuilder},
Payload, Value, View, Payload, Value, View,
}; };
@@ -59,41 +55,9 @@ impl SetupActivity {
self.view = View::init(); self.view = View::init();
// Common stuff // Common stuff
// Radio tab // Radio tab
self.view.mount( self.mount_header_tab(2);
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(),
)),
);
// Footer // Footer
self.view.mount( self.mount_footer();
super::COMPONENT_TEXT_FOOTER,
Box::new(Span::new(
SpanPropsBuilder::default()
.with_spans(vec![
TextSpanBuilder::new("Press ").bold().build(),
TextSpanBuilder::new("<CTRL+H>")
.bold()
.with_foreground(Color::Cyan)
.build(),
TextSpanBuilder::new(" to show keybindings").bold().build(),
])
.build(),
)),
);
// auth colors // auth colors
self.mount_title(super::COMPONENT_COLOR_AUTH_TITLE, "Authentication styles"); self.mount_title(super::COMPONENT_COLOR_AUTH_TITLE, "Authentication styles");
self.mount_color_picker(super::COMPONENT_COLOR_AUTH_PROTOCOL, "Protocol"); self.mount_color_picker(super::COMPONENT_COLOR_AUTH_PROTOCOL, "Protocol");
@@ -653,7 +617,7 @@ impl SetupActivity {
Box::new(ColorPicker::new( Box::new(ColorPicker::new(
ColorPickerPropsBuilder::default() ColorPickerPropsBuilder::default()
.with_borders(Borders::ALL, BorderType::Rounded, Color::Reset) .with_borders(Borders::ALL, BorderType::Rounded, Color::Reset)
.with_label(label.to_string()) .with_label(label.to_string(), Alignment::Left)
.build(), .build(),
)), )),
); );

View File

@@ -26,18 +26,19 @@
* SOFTWARE. * SOFTWARE.
*/ */
// ext // ext
use tuirealm::components::utils::get_block; use tui_realm_stdlib::utils::get_block;
use tuirealm::event::{Event, KeyCode}; use tuirealm::event::{Event, KeyCode};
use tuirealm::props::{BordersProps, Props, PropsBuilder, TextParts, TextSpan}; use tuirealm::props::{Alignment, BlockTitle, BordersProps, Props, PropsBuilder};
use tuirealm::tui::{ use tuirealm::tui::{
layout::{Corner, Rect}, layout::{Corner, Rect},
style::{Color, Style}, style::{Color, Style},
text::Span, text::Span,
widgets::{BorderType, Borders, List, ListItem, ListState}, widgets::{BorderType, Borders, List, ListItem, ListState},
}; };
use tuirealm::{Canvas, Component, Msg, Payload, Value}; use tuirealm::{Component, Frame, Msg, Payload, PropPayload, PropValue, Value};
// -- props // -- props
const PROP_BOOKMARKS: &str = "bookmarks";
pub struct BookmarkListPropsBuilder { pub struct BookmarkListPropsBuilder {
props: Option<Props>, props: Option<Props>,
@@ -117,10 +118,19 @@ impl BookmarkListPropsBuilder {
self self
} }
pub fn with_bookmarks(&mut self, title: Option<String>, bookmarks: Vec<String>) -> &mut Self { pub fn with_title<S: AsRef<str>>(&mut self, text: S, alignment: Alignment) -> &mut Self {
if let Some(props) = self.props.as_mut() { if let Some(props) = self.props.as_mut() {
let bookmarks: Vec<TextSpan> = bookmarks.into_iter().map(TextSpan::from).collect(); props.title = Some(BlockTitle::new(text, alignment));
props.texts = TextParts::new(title, Some(bookmarks)); }
self
}
pub fn with_bookmarks(&mut self, bookmarks: Vec<String>) -> &mut Self {
if let Some(props) = self.props.as_mut() {
let bookmarks: Vec<PropValue> = bookmarks.into_iter().map(PropValue::Str).collect();
props
.own
.insert(PROP_BOOKMARKS, PropPayload::Vec(bookmarks));
} }
self self
} }
@@ -210,25 +220,30 @@ impl BookmarkList {
// Initialize states // Initialize states
let mut states: OwnStates = OwnStates::default(); let mut states: OwnStates = OwnStates::default();
// Set list length // Set list length
states.set_list_len(match &props.texts.spans { states.set_list_len(Self::bookmarks_len(&props));
Some(tokens) => tokens.len(),
None => 0,
});
BookmarkList { props, states } 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 { impl Component for BookmarkList {
#[cfg(not(tarpaulin_include))] #[cfg(not(tarpaulin_include))]
fn render(&self, render: &mut Canvas, area: Rect) { fn render(&self, render: &mut Frame, area: Rect) {
if self.props.visible { if self.props.visible {
// Make list // Make list
let list_item: Vec<ListItem> = match self.props.texts.spans.as_ref() { let list_item: Vec<ListItem> = match self.props.own.get(PROP_BOOKMARKS) {
None => vec![], Some(PropPayload::Vec(lines)) => lines
Some(lines) => lines
.iter() .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(), .collect(),
_ => vec![],
}; };
let (fg, bg): (Color, Color) = match self.states.focus { let (fg, bg): (Color, Color) = match self.states.focus {
true => (self.props.foreground, self.props.background), true => (self.props.foreground, self.props.background),
@@ -241,7 +256,7 @@ impl Component for BookmarkList {
List::new(list_item) List::new(list_item)
.block(get_block( .block(get_block(
&self.props.borders, &self.props.borders,
&self.props.texts.title, self.props.title.as_ref(),
self.states.focus, self.states.focus,
)) ))
.start_corner(Corner::TopLeft) .start_corner(Corner::TopLeft)
@@ -260,10 +275,7 @@ impl Component for BookmarkList {
fn update(&mut self, props: Props) -> Msg { fn update(&mut self, props: Props) -> Msg {
self.props = props; self.props = props;
// re-Set list length // re-Set list length
self.states.set_list_len(match &self.props.texts.spans { self.states.set_list_len(Self::bookmarks_len(&self.props));
Some(tokens) => tokens.len(),
None => 0,
});
// Reset list index // Reset list index
self.states.reset_list_index(); self.states.reset_list_index();
Msg::None Msg::None
@@ -347,20 +359,24 @@ mod tests {
.with_foreground(Color::Red) .with_foreground(Color::Red)
.with_background(Color::Blue) .with_background(Color::Blue)
.with_borders(Borders::ALL, BorderType::Double, Color::Red) .with_borders(Borders::ALL, BorderType::Double, Color::Red)
.with_bookmarks( .with_title("filelist", Alignment::Left)
Some(String::from("filelist")), .with_bookmarks(vec![String::from("file1"), String::from("file2")])
vec![String::from("file1"), String::from("file2")],
)
.build(), .build(),
); );
assert_eq!(component.props.foreground, Color::Red); assert_eq!(component.props.foreground, Color::Red);
assert_eq!(component.props.background, Color::Blue); assert_eq!(component.props.background, Color::Blue);
assert_eq!(component.props.visible, true); assert_eq!(component.props.visible, true);
assert_eq!(component.props.title.as_ref().unwrap().text(), "filelist");
assert_eq!( assert_eq!(
component.props.texts.title.as_ref().unwrap().as_str(), component
"filelist" .props
.own
.get(PROP_BOOKMARKS)
.unwrap()
.unwrap_vec()
.len(),
2
); );
assert_eq!(component.props.texts.spans.as_ref().unwrap().len(), 2);
// Verify states // Verify states
assert_eq!(component.states.list_index, 0); assert_eq!(component.states.list_index, 0);
assert_eq!(component.states.list_len, 2); assert_eq!(component.states.list_len, 2);
@@ -384,14 +400,11 @@ mod tests {
// Update // Update
component.update( component.update(
BookmarkListPropsBuilder::from(component.get_props()) BookmarkListPropsBuilder::from(component.get_props())
.with_bookmarks( .with_bookmarks(vec![
Some(String::from("filelist")), String::from("file1"),
vec![ String::from("file2"),
String::from("file1"), String::from("file3"),
String::from("file2"), ])
String::from("file3"),
],
)
.build(), .build(),
); );
// Verify states // Verify states

View File

@@ -30,15 +30,15 @@
use crate::utils::fmt::fmt_color; use crate::utils::fmt::fmt_color;
use crate::utils::parser::parse_color; use crate::utils::parser::parse_color;
// ext // ext
use tuirealm::components::input::{Input, InputPropsBuilder}; use tui_realm_stdlib::input::{Input, InputPropsBuilder};
use tuirealm::event::Event; use tuirealm::event::Event;
use tuirealm::props::{Props, PropsBuilder}; use tuirealm::props::{Alignment, Props, PropsBuilder};
use tuirealm::tui::{ use tuirealm::tui::{
layout::Rect, layout::Rect,
style::Color, style::Color,
widgets::{BorderType, Borders}, widgets::{BorderType, Borders},
}; };
use tuirealm::{Canvas, Component, Msg, Payload, Value}; use tuirealm::{Component, Frame, Msg, Payload, Value};
// -- props // -- props
@@ -98,8 +98,8 @@ impl ColorPickerPropsBuilder {
/// ### with_label /// ### with_label
/// ///
/// Set input label /// Set input label
pub fn with_label(&mut self, label: String) -> &mut Self { pub fn with_label<S: AsRef<str>>(&mut self, label: S, alignment: Alignment) -> &mut Self {
self.puppet.with_label(label); self.puppet.with_label(label, alignment);
self 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 /// 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) /// If focused, cursor is also set (if supported by widget)
#[cfg(not(tarpaulin_include))] #[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); self.input.render(render, area);
} }
@@ -260,6 +260,7 @@ mod test {
.visible() .visible()
.with_color(&Color::Rgb(204, 170, 0)) .with_color(&Color::Rgb(204, 170, 0))
.with_borders(Borders::ALL, BorderType::Double, Color::Rgb(204, 170, 0)) .with_borders(Borders::ALL, BorderType::Double, Color::Rgb(204, 170, 0))
.with_label("omar", Alignment::Left)
.build(), .build(),
); );
// Focus // Focus

View File

@@ -26,10 +26,10 @@
* SOFTWARE. * SOFTWARE.
*/ */
// ext // ext
use tuirealm::components::utils::get_block; use tui_realm_stdlib::utils::get_block;
use tuirealm::event::{Event, KeyCode, KeyModifiers}; use tuirealm::event::{Event, KeyCode, KeyModifiers};
use tuirealm::props::{ use tuirealm::props::{
BordersProps, PropPayload, PropValue, Props, PropsBuilder, TextParts, TextSpan, Alignment, BlockTitle, BordersProps, PropPayload, PropValue, Props, PropsBuilder,
}; };
use tuirealm::tui::{ use tuirealm::tui::{
layout::{Corner, Rect}, layout::{Corner, Rect},
@@ -37,11 +37,12 @@ use tuirealm::tui::{
text::Span, text::Span,
widgets::{BorderType, Borders, List, ListItem, ListState}, widgets::{BorderType, Borders, List, ListItem, ListState},
}; };
use tuirealm::{Canvas, Component, Msg, Payload, Value}; use tuirealm::{Component, Frame, Msg, Payload, Value};
// -- props // -- 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 { pub struct FileListPropsBuilder {
props: Option<Props>, props: Option<Props>,
@@ -107,10 +108,7 @@ impl FileListPropsBuilder {
/// Set highlighted color /// Set highlighted color
pub fn with_highlight_color(&mut self, color: Color) -> &mut Self { pub fn with_highlight_color(&mut self, color: Color) -> &mut Self {
if let Some(props) = self.props.as_mut() { if let Some(props) = self.props.as_mut() {
props.own.insert( props.palette.insert(PALETTE_HIGHLIGHT_COLOR, color);
PROP_HIGHLIGHT_COLOR,
PropPayload::One(PropValue::Color(color)),
);
} }
self self
} }
@@ -134,10 +132,17 @@ impl FileListPropsBuilder {
self self
} }
pub fn with_files(&mut self, title: Option<String>, files: Vec<String>) -> &mut Self { pub fn with_title<S: AsRef<str>>(&mut self, text: S, alignment: Alignment) -> &mut Self {
if let Some(props) = self.props.as_mut() { if let Some(props) = self.props.as_mut() {
let files: Vec<TextSpan> = files.into_iter().map(TextSpan::from).collect(); props.title = Some(BlockTitle::new(text, alignment));
props.texts = TextParts::new(title, Some(files)); }
self
}
pub fn with_files(&mut self, files: Vec<String>) -> &mut Self {
if let Some(props) = self.props.as_mut() {
let files: Vec<PropValue> = files.into_iter().map(PropValue::Str).collect();
props.own.insert(PROP_FILES, PropPayload::Vec(files));
} }
self self
} }
@@ -299,32 +304,39 @@ impl FileList {
// Initialize states // Initialize states
let mut states: OwnStates = OwnStates::default(); let mut states: OwnStates = OwnStates::default();
// Init list states // 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 } 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 { impl Component for FileList {
#[cfg(not(tarpaulin_include))] #[cfg(not(tarpaulin_include))]
fn render(&self, render: &mut Canvas, area: Rect) { fn render(&self, render: &mut Frame, area: Rect) {
if self.props.visible { if self.props.visible {
// Make list // Make list
let list_item: Vec<ListItem> = match self.props.texts.spans.as_ref() { let list_item: Vec<ListItem> = match self.props.own.get(PROP_FILES) {
None => vec![], Some(PropPayload::Vec(lines)) => lines
Some(lines) => lines
.iter() .iter()
.enumerate() .enumerate()
.map(|(num, line)| { .map(|(num, line)| {
let to_display: String = match self.states.is_selected(num) { let to_display: String = match self.states.is_selected(num) {
true => format!("*{}", line.content), true => format!("*{}", line.unwrap_str()),
false => line.content.to_string(), false => line.unwrap_str().to_string(),
}; };
ListItem::new(Span::from(to_display)) ListItem::new(Span::from(to_display))
}) })
.collect(), .collect(),
_ => vec![],
}; };
let highlighted_color: Color = match self.props.own.get(PROP_HIGHLIGHT_COLOR) { let highlighted_color: Color = match self.props.palette.get(PALETTE_HIGHLIGHT_COLOR) {
Some(PropPayload::One(PropValue::Color(c))) => *c, Some(c) => *c,
_ => Color::Reset, _ => Color::Reset,
}; };
let (h_fg, h_bg): (Color, Color) = match self.states.focus { let (h_fg, h_bg): (Color, Color) = match self.states.focus {
@@ -338,7 +350,7 @@ impl Component for FileList {
List::new(list_item) List::new(list_item)
.block(get_block( .block(get_block(
&self.props.borders, &self.props.borders,
&self.props.texts.title, self.props.title.as_ref(),
self.states.focus, self.states.focus,
)) ))
.start_corner(Corner::TopLeft) .start_corner(Corner::TopLeft)
@@ -362,14 +374,7 @@ impl Component for FileList {
fn update(&mut self, props: Props) -> Msg { fn update(&mut self, props: Props) -> Msg {
self.props = props; self.props = props;
// re-Set list states // re-Set list states
self.states.init_list_states( self.states.init_list_states(Self::files_len(&self.props));
self.props
.texts
.spans
.as_ref()
.map(|x| x.len())
.unwrap_or(0),
);
Msg::None Msg::None
} }
@@ -551,24 +556,33 @@ mod tests {
.with_background(Color::Blue) .with_background(Color::Blue)
.with_highlight_color(Color::LightRed) .with_highlight_color(Color::LightRed)
.with_borders(Borders::ALL, BorderType::Double, Color::Red) .with_borders(Borders::ALL, BorderType::Double, Color::Red)
.with_files( .with_title("files", Alignment::Left)
Some(String::from("files")), .with_files(vec![String::from("file1"), String::from("file2")])
vec![String::from("file1"), String::from("file2")],
)
.build(), .build(),
); );
assert_eq!( assert_eq!(
*component.props.own.get(PROP_HIGHLIGHT_COLOR).unwrap(), *component
PropPayload::One(PropValue::Color(Color::LightRed)) .props
.palette
.get(PALETTE_HIGHLIGHT_COLOR)
.unwrap(),
Color::LightRed
); );
assert_eq!(component.props.foreground, Color::Red); assert_eq!(component.props.foreground, Color::Red);
assert_eq!(component.props.background, Color::Blue); assert_eq!(component.props.background, Color::Blue);
assert_eq!(component.props.visible, true); assert_eq!(component.props.visible, true);
assert_eq!(component.props.title.as_ref().unwrap().text(), "files");
assert_eq!( assert_eq!(
component.props.texts.title.as_ref().unwrap().as_str(), component
"files" .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 // Verify states
assert_eq!(component.states.list_index, 0); assert_eq!(component.states.list_index, 0);
assert_eq!(component.states.selected.len(), 0); assert_eq!(component.states.selected.len(), 0);
@@ -594,14 +608,11 @@ mod tests {
// Update // Update
component.update( component.update(
FileListPropsBuilder::from(component.get_props()) FileListPropsBuilder::from(component.get_props())
.with_files( .with_files(vec![
Some(String::from("filelist")), String::from("file1"),
vec![ String::from("file2"),
String::from("file1"), String::from("file3"),
String::from("file2"), ])
String::from("file3"),
],
)
.build(), .build(),
); );
// Verify states // Verify states
@@ -670,14 +681,11 @@ mod tests {
// Make component // Make component
let mut component: FileList = FileList::new( let mut component: FileList = FileList::new(
FileListPropsBuilder::default() FileListPropsBuilder::default()
.with_files( .with_files(vec![
Some(String::from("files")), String::from("file1"),
vec![ String::from("file2"),
String::from("file1"), String::from("file3"),
String::from("file2"), ])
String::from("file3"),
],
)
.build(), .build(),
); );
// Get state // Get state
@@ -735,10 +743,7 @@ mod tests {
// Update files // Update files
component.update( component.update(
FileListPropsBuilder::from(component.get_props()) FileListPropsBuilder::from(component.get_props())
.with_files( .with_files(vec![String::from("file1"), String::from("file2")])
Some(String::from("filelist")),
vec![String::from("file1"), String::from("file2")],
)
.build(), .build(),
); );
// Selection should now be empty // Selection should now be empty

View File

@@ -26,18 +26,22 @@
* SOFTWARE. * SOFTWARE.
*/ */
// ext // 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::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::{ use tuirealm::tui::{
layout::{Corner, Rect}, layout::{Corner, Rect},
style::{Color, Style}, style::{Color, Style},
widgets::{BorderType, Borders, List, ListItem, ListState}, widgets::{BorderType, Borders, List, ListItem, ListState},
}; };
use tuirealm::{Canvas, Component, Msg, Payload, Value}; use tuirealm::{Component, Frame, Msg, Payload, PropPayload, PropValue, Value};
// -- props // -- props
const PROP_TABLE: &str = "table";
pub struct LogboxPropsBuilder { pub struct LogboxPropsBuilder {
props: Option<Props>, props: Option<Props>,
} }
@@ -106,9 +110,18 @@ impl LogboxPropsBuilder {
self self
} }
pub fn with_log(&mut self, title: Option<String>, table: TextTable) -> &mut Self { pub fn with_title<S: AsRef<str>>(&mut self, text: S, alignment: Alignment) -> &mut Self {
if let Some(props) = self.props.as_mut() { 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 self
} }
@@ -198,33 +211,37 @@ impl LogBox {
// Initialize states // Initialize states
let mut states: OwnStates = OwnStates::default(); let mut states: OwnStates = OwnStates::default();
// Set list length // Set list length
states.set_list_len(match &props.texts.table { states.set_list_len(Self::table_len(&props));
Some(rows) => rows.len(),
None => 0,
});
// Reset list index // Reset list index
states.reset_list_index(); states.reset_list_index();
LogBox { props, states } 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 { impl Component for LogBox {
#[cfg(not(tarpaulin_include))] #[cfg(not(tarpaulin_include))]
fn render(&self, render: &mut Canvas, area: Rect) { fn render(&self, render: &mut Frame, area: Rect) {
if self.props.visible { if self.props.visible {
let width: usize = area.width as usize - 4; let width: usize = area.width as usize - 4;
// Make list // Make list
let list_items: Vec<ListItem> = match self.props.texts.table.as_ref() { let list_items: Vec<ListItem> = match self.props.own.get(PROP_TABLE) {
None => Vec::new(), Some(PropPayload::One(PropValue::Table(table))) => table
Some(table) => table
.iter() .iter()
.map(|row| ListItem::new(wrap_spans(row, width, &self.props))) .map(|row| ListItem::new(wrap_spans(row, width, &self.props)))
.collect(), // Make List item from TextSpan .collect(), // Make List item from TextSpan
_ => Vec::new(),
}; };
let w = List::new(list_items) let w = List::new(list_items)
.block(get_block( .block(get_block(
&self.props.borders, &self.props.borders,
&self.props.texts.title, self.props.title.as_ref(),
self.states.focus, self.states.focus,
)) ))
.start_corner(Corner::BottomLeft) .start_corner(Corner::BottomLeft)
@@ -240,10 +257,7 @@ impl Component for LogBox {
fn update(&mut self, props: Props) -> Msg { fn update(&mut self, props: Props) -> Msg {
self.props = props; self.props = props;
// re-Set list length // re-Set list length
self.states.set_list_len(match &self.props.texts.table { self.states.set_list_len(Self::table_len(&self.props));
Some(rows) => rows.len(),
None => 0,
});
// Reset list index // Reset list index
self.states.reset_list_index(); self.states.reset_list_index();
Msg::None Msg::None
@@ -323,8 +337,8 @@ mod tests {
.visible() .visible()
.with_borders(Borders::ALL, BorderType::Double, Color::Red) .with_borders(Borders::ALL, BorderType::Double, Color::Red)
.with_background(Color::Blue) .with_background(Color::Blue)
.with_title("log", Alignment::Left)
.with_log( .with_log(
Some(String::from("Log")),
TableBuilder::default() TableBuilder::default()
.add_col(TextSpan::from("12:29")) .add_col(TextSpan::from("12:29"))
.add_col(TextSpan::from("system crashed")) .add_col(TextSpan::from("system crashed"))
@@ -337,11 +351,7 @@ mod tests {
); );
assert_eq!(component.props.visible, true); assert_eq!(component.props.visible, true);
assert_eq!(component.props.background, Color::Blue); assert_eq!(component.props.background, Color::Blue);
assert_eq!( assert_eq!(component.props.title.as_ref().unwrap().text(), "Log");
component.props.texts.title.as_ref().unwrap().as_str(),
"Log"
);
assert_eq!(component.props.texts.table.as_ref().unwrap().len(), 2);
// Verify states // Verify states
assert_eq!(component.states.list_index, 0); assert_eq!(component.states.list_index, 0);
assert_eq!(component.states.list_len, 2); assert_eq!(component.states.list_len, 2);
@@ -364,7 +374,6 @@ mod tests {
component.update( component.update(
LogboxPropsBuilder::from(component.get_props()) LogboxPropsBuilder::from(component.get_props())
.with_log( .with_log(
Some(String::from("Log")),
TableBuilder::default() TableBuilder::default()
.add_col(TextSpan::from("12:29")) .add_col(TextSpan::from("12:29"))
.add_col(TextSpan::from("system crashed")) .add_col(TextSpan::from("system crashed"))

View File

@@ -30,4 +30,3 @@ pub mod bookmark_list;
pub mod color_picker; pub mod color_picker;
pub mod file_list; pub mod file_list;
pub mod logbox; pub mod logbox;
pub mod msgbox;

View File

@@ -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<Props>,
}
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<Props> 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<String>, texts: Vec<TextSpan>) -> &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<ListItem> = match self.props.texts.spans.as_ref() {
None => Vec::new(),
Some(rows) => {
let mut lines: Vec<ListItem> = 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("<ESC>")
.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))
);
}
}

View File

@@ -100,23 +100,6 @@ pub fn fmt_millis(duration: Duration) -> String {
format!("{}.{:0width$}", seconds, millis, width = 3) 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::<String>().as_str(),
)
.trim_end()
.to_string()
}
/// ### elide_path /// ### elide_path
/// ///
/// Elide a path if longer than width /// 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] #[test]
fn test_utils_fmt_millis() { fn test_utils_fmt_millis() {
assert_eq!( assert_eq!(