diff --git a/Cargo.lock b/Cargo.lock index b77ef42..8982910 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -236,7 +236,7 @@ dependencies = [ "bitflags", "cexpr", "clang-sys", - "itertools", + "itertools 0.13.0", "log", "prettyplease", "proc-macro2", @@ -253,6 +253,12 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "block-buffer" version = "0.10.4" @@ -359,6 +365,28 @@ dependencies = [ "libloading", ] +[[package]] +name = "clipboard" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a904646c0340239dcf7c51677b33928bf24fdf424b79a57909c0109075b2e7" +dependencies = [ + "clipboard-win", + "objc", + "objc-foundation", + "objc_id", + "x11-clipboard", +] + +[[package]] +name = "clipboard-win" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a093d6fed558e5fe24c3dfc85a68bb68f1c824f440d3ba5aca189e2998786b" +dependencies = [ + "winapi", +] + [[package]] name = "cmake" version = "0.1.54" @@ -395,6 +423,19 @@ dependencies = [ "tracing-error", ] +[[package]] +name = "compact_str" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "ryu", + "static_assertions", +] + [[package]] name = "compact_str" version = "0.8.1" @@ -504,6 +545,22 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crossterm" +version = "0.27.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f476fe445d41c9e991fd07515a6f463074b782242ccf4a5b7b1d1012e70824df" +dependencies = [ + "bitflags", + "crossterm_winapi", + "libc", + "mio 0.8.11", + "parking_lot", + "signal-hook", + "signal-hook-mio", + "winapi", +] + [[package]] name = "crossterm" version = "0.28.1" @@ -512,7 +569,7 @@ checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ "bitflags", "crossterm_winapi", - "mio", + "mio 1.1.0", "parking_lot", "rustix 0.38.44", "signal-hook", @@ -1330,7 +1387,7 @@ dependencies = [ "bytes", "cmake", "color-eyre", - "crossterm", + "crossterm 0.28.1", "der", "futures", "futures-util", @@ -1344,9 +1401,11 @@ dependencies = [ "native-tls", "once_cell", "pkcs8", + "pnet", "rand 0.8.5", "rand_core 0.6.4", - "ratatui", + "ratatui 0.29.0", + "ratatui_input", "reactive-rs", "reqwest", "rustls", @@ -1361,6 +1420,8 @@ dependencies = [ "tokio-tungstenite", "tokio-util", "tower", + "tui-input", + "tui-textarea", "tungstenite", "uuid", "walkdir", @@ -1376,6 +1437,15 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" +[[package]] +name = "ipnetwork" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf466541e9d546596ee94f9f69590f89473455f88372423e0008fc1a7daf100e" +dependencies = [ + "serde", +] + [[package]] name = "iri-string" version = "0.7.9" @@ -1386,6 +1456,15 @@ dependencies = [ "serde", ] +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.13.0" @@ -1525,6 +1604,15 @@ dependencies = [ "libc", ] +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "matchit" version = "0.8.4" @@ -1569,6 +1657,18 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "log", + "wasi", + "windows-sys 0.48.0", +] + [[package]] name = "mio" version = "1.1.0" @@ -1598,6 +1698,12 @@ dependencies = [ "tempfile", ] +[[package]] +name = "no-std-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43794a0ace135be66a25d3ae77d41b91615fb68ae937f904090203e81f755b65" + [[package]] name = "nom" version = "7.1.3" @@ -1641,6 +1747,35 @@ dependencies = [ "libc", ] +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + [[package]] name = "object" version = "0.37.3" @@ -1805,6 +1940,97 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "pnet" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "682396b533413cc2e009fbb48aadf93619a149d3e57defba19ff50ce0201bd0d" +dependencies = [ + "ipnetwork", + "pnet_base", + "pnet_datalink", + "pnet_packet", + "pnet_sys", + "pnet_transport", +] + +[[package]] +name = "pnet_base" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc190d4067df16af3aba49b3b74c469e611cad6314676eaf1157f31aa0fb2f7" +dependencies = [ + "no-std-net", +] + +[[package]] +name = "pnet_datalink" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e79e70ec0be163102a332e1d2d5586d362ad76b01cec86f830241f2b6452a7b7" +dependencies = [ + "ipnetwork", + "libc", + "pnet_base", + "pnet_sys", + "winapi", +] + +[[package]] +name = "pnet_macros" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13325ac86ee1a80a480b0bc8e3d30c25d133616112bb16e86f712dcf8a71c863" +dependencies = [ + "proc-macro2", + "quote", + "regex", + "syn", +] + +[[package]] +name = "pnet_macros_support" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed67a952585d509dd0003049b1fc56b982ac665c8299b124b90ea2bdb3134ab" +dependencies = [ + "pnet_base", +] + +[[package]] +name = "pnet_packet" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c96ebadfab635fcc23036ba30a7d33a80c39e8461b8bd7dc7bb186acb96560f" +dependencies = [ + "glob", + "pnet_base", + "pnet_macros", + "pnet_macros_support", +] + +[[package]] +name = "pnet_sys" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d4643d3d4db6b08741050c2f3afa9a892c4244c085a72fcda93c9c2c9a00f4b" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "pnet_transport" +version = "0.35.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f604d98bc2a6591cf719b58d3203fd882bdd6bf1db696c4ac97978e9f4776bf" +dependencies = [ + "libc", + "pnet_base", + "pnet_packet", + "pnet_sys", +] + [[package]] name = "polyval" version = "0.6.2" @@ -1946,6 +2172,26 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "ratatui" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f44c9e68fd46eda15c646fbb85e1040b657a58cdc8c98db1d97a55930d991eef" +dependencies = [ + "bitflags", + "cassowary", + "compact_str 0.7.1", + "crossterm 0.27.0", + "itertools 0.12.1", + "lru", + "paste", + "stability", + "strum", + "unicode-segmentation", + "unicode-truncate", + "unicode-width 0.1.14", +] + [[package]] name = "ratatui" version = "0.29.0" @@ -1954,11 +2200,11 @@ checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" dependencies = [ "bitflags", "cassowary", - "compact_str", - "crossterm", + "compact_str 0.8.1", + "crossterm 0.28.1", "indoc", "instability", - "itertools", + "itertools 0.13.0", "lru", "paste", "strum", @@ -1968,6 +2214,17 @@ dependencies = [ "unicode-width 0.2.0", ] +[[package]] +name = "ratatui_input" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e8a34033089cf174da43769390c383c12bdc318e201f7ed667970bd99e3912b" +dependencies = [ + "clipboard", + "crossterm 0.27.0", + "ratatui 0.26.3", +] + [[package]] name = "rayon" version = "1.11.0" @@ -2357,7 +2614,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc" dependencies = [ "libc", - "mio", + "mio 0.8.11", + "mio 1.1.0", "signal-hook", ] @@ -2419,6 +2677,16 @@ dependencies = [ "der", ] +[[package]] +name = "stability" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d904e7009df136af5297832a3ace3370cd14ff1546a232f4f185036c2736fcac" +dependencies = [ + "quote", + "syn", +] + [[package]] name = "stable_deref_trait" version = "1.2.1" @@ -2623,7 +2891,7 @@ checksum = "ff360e02eab121e0bc37a2d3b4d4dc622e6eda3a8e5253d5435ecf5bd4c68408" dependencies = [ "bytes", "libc", - "mio", + "mio 1.1.0", "parking_lot", "pin-project-lite", "signal-hook-registry", @@ -2788,6 +3056,27 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "tui-input" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "911e93158bf80bbc94bad533b2b16e3d711e1132d69a6a6980c3920a63422c19" +dependencies = [ + "ratatui 0.29.0", + "unicode-width 0.2.0", +] + +[[package]] +name = "tui-textarea" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a5318dd619ed73c52a9417ad19046724effc1287fb75cdcc4eca1d6ac1acbae" +dependencies = [ + "crossterm 0.28.1", + "ratatui 0.29.0", + "unicode-width 0.2.0", +] + [[package]] name = "tungstenite" version = "0.28.0" @@ -2836,7 +3125,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" dependencies = [ - "itertools", + "itertools 0.13.0", "unicode-segmentation", "unicode-width 0.1.14", ] @@ -3201,6 +3490,15 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" @@ -3237,6 +3535,21 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + [[package]] name = "windows-targets" version = "0.52.6" @@ -3270,6 +3583,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -3282,6 +3601,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -3294,6 +3619,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -3318,6 +3649,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -3330,6 +3667,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -3342,6 +3685,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -3354,6 +3703,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -3378,6 +3733,15 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9" +[[package]] +name = "x11-clipboard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89bd49c06c9eb5d98e6ba6536cf64ac9f7ee3a009b2f53996d405b3944f6bcea" +dependencies = [ + "xcb", +] + [[package]] name = "x448" version = "0.6.0" @@ -3399,6 +3763,16 @@ dependencies = [ "cookie-factory", ] +[[package]] +name = "xcb" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e917a3f24142e9ff8be2414e36c649d47d6cc2ba81f16201cdef96e533e02de" +dependencies = [ + "libc", + "log", +] + [[package]] name = "yoke" version = "0.8.1" diff --git a/Cargo.toml b/Cargo.toml index 79a6bd7..5586b07 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,3 +51,7 @@ async-trait = "0.1.89" sha1 = "0.10.6" async-tungstenite = "0.32.0" zip = "6.0.0" +ratatui_input = "0.1.3" +tui-textarea = "0.7.0" +tui-input = "0.14.0" +pnet = "0.35.0" diff --git a/src/auth/auth_connector.rs b/src/auth/auth_connector.rs index 574fdfa..3066b5b 100644 --- a/src/auth/auth_connector.rs +++ b/src/auth/auth_connector.rs @@ -142,7 +142,7 @@ pub async fn migrate_user(user_profile: &mut UserProfile) -> bool { let client = client(); let mut payload = JsonValue::new_object(); - payload["iota_id"] = JsonValue::String(CONFIG.lock().await.get_iota_id().to_string()); + payload["iota_id"] = JsonValue::String(CONFIG.read().await.get_iota_id().to_string()); payload["reset_token"] = user_profile.reset_token.clone().into(); payload["new_token"] = user_profile.randomize_reset_token().into(); diff --git a/src/gui/input_handler.rs b/src/gui/input_handler.rs new file mode 100644 index 0000000..f46972c --- /dev/null +++ b/src/gui/input_handler.rs @@ -0,0 +1,64 @@ +use crate::{SHUTDOWN, gui::tui::UNIQUE, util::config_util::CONFIG}; +use crossterm::event::{KeyEvent, KeyModifiers}; +use ratatui::crossterm::event::{Event, KeyCode, read}; +use tokio::{self}; +use tokio_util::sync::WaitForCancellationFutureOwned; + +pub fn setup_input_handler() { + tokio::spawn(async move { + while let Ok(event) = read() { + if *SHUTDOWN.read().await { + break; + } + if let Event::Key(key) = event { + handle_input(key).await; + } + } + }); +} + +pub async fn handle_input(key: KeyEvent) { + match (key.code, key.modifiers) { + (KeyCode::Char('c'), KeyModifiers::CONTROL) => { + *SHUTDOWN.write().await = true; + } + (KeyCode::Backspace, KeyModifiers::NONE) => { + let password: String = { + let cfg = CONFIG.read().await; + cfg.get("password").as_str().unwrap_or("").to_string() + }; + let password: &str = &password; + let password = match password.char_indices().next_back() { + Some((i, _)) => &password[..i], + None => password, + }; + + CONFIG.write().await.change("password", password); + CONFIG.write().await.update(); + *UNIQUE.write().await = true; + } + (KeyCode::Char(c), KeyModifiers::NONE) => { + let password: String = { + let cfg = CONFIG.read().await; + cfg.get("password").as_str().unwrap_or("").to_string() + }; + let password = &format!("{}{}", password, c); + + CONFIG.write().await.change("password", password); + CONFIG.write().await.update(); + *UNIQUE.write().await = true; + } + (KeyCode::Char(c), KeyModifiers::SHIFT) => { + let password: String = { + let cfg = CONFIG.read().await; + cfg.get("password").as_str().unwrap_or("").to_string() + }; + let password = &format!("{}{}", password, c); + + CONFIG.write().await.change("password", password); + CONFIG.write().await.update(); + *UNIQUE.write().await = true; + } + _ => {} + } +} diff --git a/src/gui/mod.rs b/src/gui/mod.rs index 52c7030..e1c7598 100644 --- a/src/gui/mod.rs +++ b/src/gui/mod.rs @@ -1,6 +1,8 @@ pub mod app_state; pub mod log_panel; +pub mod settings_panel; pub mod widgets { pub mod betterblock; } +pub mod input_handler; pub mod tui; diff --git a/src/gui/settings_panel.rs b/src/gui/settings_panel.rs new file mode 100644 index 0000000..1555b7e --- /dev/null +++ b/src/gui/settings_panel.rs @@ -0,0 +1,29 @@ +use ratatui::{ + Frame, + layout::{Constraint, Direction, Layout, Margin, Rect}, + text::Span, + widgets::{Block, Paragraph}, +}; + +use crate::gui::app_state::AppState; +pub fn draw(frame: &mut Frame, area: Rect, block: Block, password: String, _state: AppState) { + frame.render_widget(block, area); + + let padded = area.inner(Margin { + horizontal: 1, + vertical: 1, + }); + + let chunks = Layout::default() + .direction(Direction::Vertical) + .constraints([ + Constraint::Length(3), + Constraint::Length(3), + Constraint::Length(3), + ]) + .split(padded); + + let prefix = Span::raw(format!("select password : {}", password)); + + frame.render_widget(Paragraph::new(prefix), chunks[0]); +} diff --git a/src/gui/tui.rs b/src/gui/tui.rs index bc5753a..2ed223d 100644 --- a/src/gui/tui.rs +++ b/src/gui/tui.rs @@ -1,11 +1,15 @@ use std::{ - default, io::{Stdout, stdout}, sync::Arc, thread, time::Duration, }; +use crate::{ + APP_STATE, SHUTDOWN, + gui::{settings_panel, widgets::betterblock::draw_block_joins}, + util::config_util::CONFIG, +}; use crossterm::{ execute, terminal::{EnterAlternateScreen, enable_raw_mode}, @@ -26,8 +30,6 @@ use tokio::{ sync::{Mutex, RwLock}, }; -use crate::{APP_STATE, SHUTDOWN}; - // ****** UTIL ****** fn init_terminal() { let mut stdout = stdout(); @@ -36,7 +38,7 @@ fn init_terminal() { } // ****** MAIN ****** -pub static UNIQUE: Lazy> = Lazy::new(|| RwLock::new(false)); +pub static UNIQUE: Lazy> = Lazy::new(|| RwLock::new(true)); pub static TERMINAL: Lazy>>>> = Lazy::new(|| { Arc::new(Mutex::new( Terminal::new(CrosstermBackend::new(stdout())).unwrap(), @@ -59,6 +61,13 @@ pub fn start_tui() { }); } pub async fn render_tui() { + let password = CONFIG + .read() + .await + .get("password") + .as_str() + .unwrap_or("") + .to_string(); TERMINAL .lock() .await @@ -98,18 +107,21 @@ pub async fn render_tui() { } // SETTINGS { - let items: Vec = state - .logs - .iter() - .rev() - .map(|s| ListItem::new(s.clone())) - .collect(); - let list = List::new(items).block( + settings_panel::draw( + f, + chunks[1], Block::default() .title("Settings") .borders(Borders::LEFT.union(Borders::TOP).union(Borders::BOTTOM)), + password, + state.clone(), + ); + draw_block_joins( + f, + chunks[1], + Borders::TOP.union(Borders::LEFT).union(Borders::BOTTOM), + Borders::LEFT, ); - f.render_widget(list, chunks[1]); } // GRAPHS { @@ -129,22 +141,44 @@ pub async fn render_tui() { stack[0], "CPU".to_string(), state.with_width(38).cpu, + Borders::TOP.union(Borders::LEFT).union(Borders::RIGHT), Color::Cyan, ); + draw_block_joins( + f, + stack[0], + Borders::TOP.union(Borders::LEFT), + Borders::LEFT, + ); render_graphs( f, stack[1], "RAM".to_string(), state.with_width(38).ram, + Borders::TOP.union(Borders::LEFT).union(Borders::RIGHT), Color::Green, ); + draw_block_joins( + f, + stack[1], + Borders::TOP.union(Borders::LEFT).union(Borders::RIGHT), + Borders::TOP, + ); render_graphs( f, stack[2], "PING".to_string(), state.with_width(38).ping, + Borders::ALL, Color::Magenta, ); + draw_block_joins(f, stack[2], Borders::ALL, Borders::TOP); + draw_block_joins( + f, + stack[2], + Borders::BOTTOM.union(Borders::LEFT), + Borders::LEFT, + ); } }) .unwrap(); @@ -156,6 +190,7 @@ pub fn render_graphs( area: Rect, title: String, graph: Vec<(f64, f64)>, + borders: Borders, color: Color, ) { let min_x = graph.first().map(|(x, _)| *x).unwrap_or(0.0); @@ -169,13 +204,13 @@ pub fn render_graphs( let max_y = graph.iter().map(|(_, y)| *y).fold(f64::MIN, f64::max); let block = Block::default() .title(format!( - "{}: {}, {}/{} MIN/MAX ", + "{}: {}──{}/{} MIN/MAX ", title, graph.last().unwrap_or(&(0.0 as f64, 0.0 as f64)).1 as i64, min_y as i64, max_y as i64 )) - .borders(Borders::ALL); + .borders(borders); let canvas = Canvas::default() .block(block) .x_bounds([min_x, max_x]) diff --git a/src/langu/language_creator.rs b/src/langu/language_creator.rs index c0bc36f..ca18603 100644 --- a/src/langu/language_creator.rs +++ b/src/langu/language_creator.rs @@ -35,7 +35,7 @@ pub fn create_languages() -> Result<(), JsonError> { general_texts.insert("setup_completed", "Launched")?; general_texts.insert( "community_active", - "Communities active on ws://0.0.0.0:{}/community/...", + "Communities active on ws://{}:{}/community/...", )?; general_texts.insert( "community_start_error", diff --git a/src/main.rs b/src/main.rs index 0fee375..d1a174c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ use json::{self, JsonValue::String}; use once_cell::sync::Lazy; +use pnet::datalink::NetworkInterface; use std::sync::Arc; use std::sync::LazyLock; use std::sync::Mutex; @@ -22,6 +23,7 @@ use crate::communities::community_manager; use crate::communities::interactables::registry; use crate::data::communication::{CommunicationType, CommunicationValue, DataTypes}; use crate::gui::app_state::AppState; +use crate::gui::input_handler; use crate::gui::log_panel; use crate::gui::log_panel::{log_message, log_message_trans}; use crate::gui::tui; @@ -57,12 +59,16 @@ async fn main() { // UI log_panel::setup(); tui::start_tui(); + input_handler::setup_input_handler(); // BASIC CONFIGURATION - CONFIG.lock().await.load(); - if !CONFIG.lock().await.config.has_key("iota_id") { - CONFIG.lock().await.change("iota_id", Uuid::new_v4()); - CONFIG.lock().await.update(); + &CONFIG.write().await.load(); + if !CONFIG.read().await.config.has_key("iota_id") { + CONFIG + .write() + .await + .change("iota_id", &Uuid::new_v4().to_string()); + CONFIG.write().await.update(); } // USER MANAGEMENT @@ -84,7 +90,7 @@ async fn main() { log_message(format!( "IOTA ID: {}-####-####-####-############", CONFIG - .lock() + .read() .await .get_iota_id() .to_string() @@ -108,9 +114,18 @@ async fn main() { sb1 = sb1 + ","; } log_message(format!("Community IDS: {}", sb1)); - let port = CONFIG.lock().await.get_port(); + let port = CONFIG.read().await.get_port(); + let mut ip = "0.0.0.0".to_string(); + for iface in pnet::datalink::interfaces() { + let iface: NetworkInterface = iface; + let ipsv = format!("{}", iface.ips[0]); + let ips: &str = ipsv.split('/').next().unwrap(); + if format!("{}", ips).starts_with("10.") || format!("{}", ips).starts_with("192.") { + ip = ips.to_string(); + } + } if start(port).await { - log_message(format("community_active", &[&port.to_string()])); + log_message(format("community_active", &[&ip, &port.to_string()])); } else { if port < 1024 { log_message(format("community_start_error_admin", &[&port.to_string()])); @@ -137,7 +152,7 @@ async fn main() { .add_data(DataTypes::user_ids, String(sb.to_string())) .add_data( DataTypes::iota_id, - String(CONFIG.lock().await.get_iota_id().to_string()), + String(CONFIG.read().await.get_iota_id().to_string()), ) .to_json() .to_string() diff --git a/src/server/api.rs b/src/server/api.rs index 79046ee..715c35c 100644 --- a/src/server/api.rs +++ b/src/server/api.rs @@ -164,7 +164,7 @@ pub async fn handle( if let Some(key) = headers.get("key") { if let Some(value) = headers.get("value") { let _ = CONFIG - .lock() + .write() .await .config .insert(key.to_str().unwrap(), value.to_str().unwrap()); @@ -176,11 +176,11 @@ pub async fn handle( "{\"type\":\"error\"}".to_string() } } - "get" => CONFIG.lock().await.config.to_string(), + "get" => CONFIG.read().await.config.to_string(), _ => "{\"type\":\"error\"}".to_string(), } } else { - CONFIG.lock().await.config.to_string() + CONFIG.read().await.config.to_string() } }), diff --git a/src/server/server.rs b/src/server/server.rs index 64a7431..0bb4afd 100644 --- a/src/server/server.rs +++ b/src/server/server.rs @@ -17,6 +17,7 @@ use hyper::{ }; use hyper_util::rt::tokio::TokioIo; use hyper_util::service::TowerToHyperService; +use pnet::datalink::NetworkInterface; use rustls::ServerConfig; use rustls::pki_types::{CertificateDer, PrivateKeyDer}; use sha1::{Digest, Sha1}; @@ -221,6 +222,15 @@ fn is_local_network(addr: IpAddr) -> bool { } async fn run_http_server(port: u16) -> bool { + let mut ip = "0.0.0.0".to_string(); + for iface in pnet::datalink::interfaces() { + let iface: NetworkInterface = iface; + let ipsv = format!("{}", iface.ips[0]); + let ips: &str = ipsv.split('/').next().unwrap(); + if format!("{}", ips).starts_with("10.") || format!("{}", ips).starts_with("192.") { + ip = ips.to_string(); + } + } let listener = TcpListener::bind(format!("0.0.0.0:{}", port)).await; if let Err(e) = listener { log_message(format!("Failed to bind to port {}: {:?}", port, e)); @@ -228,8 +238,8 @@ async fn run_http_server(port: u16) -> bool { } let listener = listener.unwrap(); log_message(format!( - "Standard Server listening for HTTP and WS on 0.0.0.0:{}", - port + "Standard Server listening for HTTP and WS on {}:{}", + ip, port )); tokio::spawn(async move { @@ -276,6 +286,17 @@ async fn run_http_server(port: u16) -> bool { /// Runs the encrypted HTTPS/WSS server loop using the provided TLS config. async fn run_tls_server(port: u16, tls_config: Arc) -> bool { + let mut ip = "0.0.0.0".to_string(); + for iface in pnet::datalink::interfaces() { + let iface: NetworkInterface = iface; + let ipsv = format!("{}", iface.ips[0]); + let ips: &str = ipsv.split('/').next().unwrap(); + log_message(ips); + if format!("{}", ips).starts_with("10.") { + ip = ips.to_string(); + } + } + let acceptor = TlsAcceptor::from(tls_config); let listener = TcpListener::bind(format!("0.0.0.0:{}", port)).await; @@ -285,8 +306,8 @@ async fn run_tls_server(port: u16, tls_config: Arc) -> bool { } let listener = listener.unwrap(); log_message(format!( - "Encrypted Server listening for HTTPS and WSS on 0.0.0.0:{}", - port + "Encrypted Server listening for HTTPS and WSS on {}:{}", + ip, port )); tokio::spawn(async move { @@ -348,17 +369,10 @@ pub async fn start(port: u16) -> bool { let tls_result = load_tls_config(); match tls_result { - Ok(Some(tls_config)) => { - // Certificates found and config loaded successfully, run the TLS server - run_tls_server(port, tls_config).await - } - Ok(None) => { - // Certificates not found, run the standard HTTP server - run_http_server(port).await - } + Ok(Some(tls_config)) => run_tls_server(port, tls_config).await, + Ok(None) => run_http_server(port).await, Err(e) => { log_message(format!("Fatal error during TLS config load: {}", e)); - // Error, server cannot start false } } diff --git a/src/users/user_manager.rs b/src/users/user_manager.rs index 524e511..77a64d8 100644 --- a/src/users/user_manager.rs +++ b/src/users/user_manager.rs @@ -70,7 +70,7 @@ pub async fn create_user(username: &str) -> (Option, Option reset_token, ); - auth_connector::complete_register(&up, &CONFIG.lock().await.get_iota_id().to_string()).await; + auth_connector::complete_register(&up, &CONFIG.read().await.get_iota_id().to_string()).await; save_file( "", &format!("{}.tu", username), diff --git a/src/util/config_util.rs b/src/util/config_util.rs index 594981d..0f0c566 100644 --- a/src/util/config_util.rs +++ b/src/util/config_util.rs @@ -1,10 +1,10 @@ use crate::util::file_util::{load_file, save_file}; use json::JsonValue; use once_cell::sync::Lazy; -use tokio::sync::Mutex; +use tokio::sync::RwLock; use uuid::Uuid; -pub static CONFIG: Lazy> = Lazy::new(|| Mutex::new(ConfigUtil::new())); +pub static CONFIG: Lazy> = Lazy::new(|| RwLock::new(ConfigUtil::new())); pub struct ConfigUtil { pub config: JsonValue, @@ -38,7 +38,11 @@ impl ConfigUtil { self.config["port"].as_u16().unwrap_or(1984) } - pub fn change(&mut self, key: &str, value: Uuid) { + pub fn get(&self, key: &str) -> &JsonValue { + &self.config[key] + } + + pub fn change(&mut self, key: &str, value: &str) { self.config[key] = JsonValue::String(value.to_string()); self.unique = true; }