diff --git a/Cargo.lock b/Cargo.lock index 407d4d4..a82f148 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,13 +10,15 @@ dependencies = [ "chrono", "clap", "colored", - "crossterm", + "crossterm 0.29.0", "flexi_logger", + "futures", "futures-util", "indicatif", "log", "once_cell", - "ratatui", + "ratatui 0.30.0", + "ratatui-kit", "reqwest", "rmcp", "rusqlite", @@ -101,6 +103,16 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "any_key" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d21bb2cdab8087ed9d69411dd99c608dbede1df847c255b4d609f0399a3cb452" +dependencies = [ + "debugit", + "mopa", +] + [[package]] name = "anyhow" version = "1.0.102" @@ -246,6 +258,12 @@ version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e748733b7cbc798e1434b6ac524f0c1ff2ab456fe201501e6497c8417a4fc33" +[[package]] +name = "cassowary" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" + [[package]] name = "castaway" version = "0.2.4" @@ -354,6 +372,20 @@ dependencies = [ "memchr", ] +[[package]] +name = "compact_str" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "rustversion", + "ryu", + "static_assertions", +] + [[package]] name = "compact_str" version = "0.9.0" @@ -376,7 +408,7 @@ checksum = "d64e8af5551369d19cf50138de61f1c42074ab970f74e99be916646777f8fc87" dependencies = [ "encode_unicode", "libc", - "unicode-width", + "unicode-width 0.2.0", "windows-sys 0.61.2", ] @@ -449,6 +481,23 @@ version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" +[[package]] +name = "crossterm" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" +dependencies = [ + "bitflags 2.11.1", + "crossterm_winapi", + "futures-core", + "mio", + "parking_lot", + "rustix 0.38.44", + "signal-hook", + "signal-hook-mio", + "winapi", +] + [[package]] name = "crossterm" version = "0.29.0" @@ -461,7 +510,7 @@ dependencies = [ "document-features", "mio", "parking_lot", - "rustix", + "rustix 1.1.4", "signal-hook", "signal-hook-mio", "winapi", @@ -530,6 +579,15 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "debugit" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63c2f7e3034df2b09f750327e23c1adfe33301e6b7388f05bb4fcc0fa46825e3" +dependencies = [ + "version_check 0.1.5", +] + [[package]] name = "deltae" version = "0.3.2" @@ -840,6 +898,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generational-box" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a673cf4fb0ea6a91aa86c08695756dfe875277a912cdbf33db9a9f62d47ed82b" +dependencies = [ + "parking_lot", + "tracing", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -847,7 +915,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", - "version_check", + "version_check 0.9.5", ] [[package]] @@ -945,6 +1013,8 @@ version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" dependencies = [ + "allocator-api2", + "equivalent", "foldhash 0.1.5", ] @@ -1261,7 +1331,7 @@ checksum = "25470f23803092da7d239834776d653104d551bc4d7eacaf31e6837854b8e9eb" dependencies = [ "console", "portable-atomic", - "unicode-width", + "unicode-width 0.2.0", "unit-prefix", "web-time", ] @@ -1309,6 +1379,15 @@ dependencies = [ "either", ] +[[package]] +name = "itertools" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.14.0" @@ -1450,6 +1529,12 @@ dependencies = [ "bitflags 2.11.1", ] +[[package]] +name = "linux-raw-sys" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" + [[package]] name = "linux-raw-sys" version = "0.12.1" @@ -1483,6 +1568,15 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "lru" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" +dependencies = [ + "hashbrown 0.15.5", +] + [[package]] name = "lru" version = "0.16.4" @@ -1553,6 +1647,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "mopa" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a785740271256c230f57462d3b83e52f998433a7062fc18f96d5999474a9f915" + [[package]] name = "nix" version = "0.29.0" @@ -1679,6 +1779,12 @@ dependencies = [ "windows-link", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + [[package]] name = "pastey" version = "0.2.2" @@ -1968,6 +2074,27 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "ratatui" +version = "0.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" +dependencies = [ + "bitflags 2.11.1", + "cassowary", + "compact_str 0.8.1", + "crossterm 0.28.1", + "indoc", + "instability", + "itertools 0.13.0", + "lru 0.12.5", + "paste", + "strum 0.26.3", + "unicode-segmentation", + "unicode-truncate 1.1.0", + "unicode-width 0.2.0", +] + [[package]] name = "ratatui" version = "0.30.0" @@ -1989,17 +2116,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ef8dea09a92caaf73bff7adb70b76162e5937524058a7e5bff37869cbbec293" dependencies = [ "bitflags 2.11.1", - "compact_str", + "compact_str 0.9.0", "hashbrown 0.16.1", "indoc", "itertools 0.14.0", "kasuari", - "lru", - "strum", + "lru 0.16.4", + "strum 0.27.2", "thiserror 2.0.18", "unicode-segmentation", - "unicode-truncate", - "unicode-width", + "unicode-truncate 2.0.1", + "unicode-width 0.2.0", ] [[package]] @@ -2009,11 +2136,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "577c9b9f652b4c121fb25c6a391dd06406d3b092ba68827e6d2f09550edc54b3" dependencies = [ "cfg-if", - "crossterm", + "crossterm 0.29.0", "instability", "ratatui-core", ] +[[package]] +name = "ratatui-kit" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9bd1a956e29a6d59ae8212a5d3499f964b8d2a2a8d878614d182d34191280c6" +dependencies = [ + "any_key", + "crossterm 0.28.1", + "futures", + "generational-box", + "ratatui 0.29.0", + "ratatui-kit-macros", + "regex", + "tui-input", + "tui-textarea", + "tui-tree-widget", +] + +[[package]] +name = "ratatui-kit-macros" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22bf3a8e830d8a0db564c642d017597c912580049a7569e79708007acef9de73" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", + "uuid", +] + [[package]] name = "ratatui-macros" version = "0.7.0" @@ -2047,10 +2204,10 @@ dependencies = [ "itertools 0.14.0", "line-clipping", "ratatui-core", - "strum", + "strum 0.27.2", "time", "unicode-segmentation", - "unicode-width", + "unicode-width 0.2.0", ] [[package]] @@ -2289,6 +2446,19 @@ dependencies = [ "semver", ] +[[package]] +name = "rustix" +version = "0.38.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" +dependencies = [ + "bitflags 2.11.1", + "errno", + "libc", + "linux-raw-sys 0.4.15", + "windows-sys 0.52.0", +] + [[package]] name = "rustix" version = "1.1.4" @@ -2298,7 +2468,7 @@ dependencies = [ "bitflags 2.11.1", "errno", "libc", - "linux-raw-sys", + "linux-raw-sys 0.12.1", "windows-sys 0.61.2", ] @@ -2666,13 +2836,35 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros 0.26.4", +] + [[package]] name = "strum" version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf" dependencies = [ - "strum_macros", + "strum_macros 0.27.2", +] + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn 2.0.117", ] [[package]] @@ -2914,7 +3106,9 @@ dependencies = [ "bytes", "libc", "mio", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.61.2", @@ -3099,6 +3293,37 @@ 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 = "tui-tree-widget" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c14c4488e071617f5b5922222193cdf6725835e492c6229557af85d3c1a4e903" +dependencies = [ + "ratatui 0.29.0", + "unicode-width 0.2.0", +] + [[package]] name = "typenum" version = "1.20.0" @@ -3123,6 +3348,17 @@ version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9629274872b2bfaf8d66f5f15725007f635594914870f65218920345aa11aa8c" +[[package]] +name = "unicode-truncate" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" +dependencies = [ + "itertools 0.13.0", + "unicode-segmentation", + "unicode-width 0.1.14", +] + [[package]] name = "unicode-truncate" version = "2.0.1" @@ -3131,14 +3367,20 @@ checksum = "16b380a1238663e5f8a691f9039c73e1cdae598a30e9855f541d29b08b53e9a5" dependencies = [ "itertools 0.14.0", "unicode-segmentation", - "unicode-width", + "unicode-width 0.2.0", ] [[package]] name = "unicode-width" -version = "0.2.2" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" + +[[package]] +name = "unicode-width" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" [[package]] name = "unicode-xid" @@ -3206,6 +3448,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + [[package]] name = "version_check" version = "0.9.5" diff --git a/Cargo.toml b/Cargo.toml index c5a9033..c5591dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,11 +13,12 @@ path = "src/main.rs" [dependencies] clap = "4.6.1" anyhow = "1.0.102" -tokio = "1.52.3" +tokio = { version = "1.52.3", features = ["full"] } colored = "3.1.1" indicatif = "0.18.4" reqwest = "0.13.3" tokio-stream = "0.1.18" +futures = "0.3.32" futures-util = "0.3.32" serde = { version = "1.0.228", features = ["derive"] } serde_json = "1.0.149" @@ -29,4 +30,5 @@ log = "0.4.29" flexi_logger = "0.31.8" chrono = "0.4.44" rust-i18n = "4.0.0" -once_cell = "1.21.4" \ No newline at end of file +once_cell = "1.21.4" +ratatui-kit = { version = "0.5.9", features = ["full"] } diff --git a/locales/en.yml b/locales/en.yml index 8b6bd1b..2f8c1e8 100644 --- a/locales/en.yml +++ b/locales/en.yml @@ -4,4 +4,11 @@ logger_is_initialized: "Logger is initialized." current_locale: "Current locale: %{locale_name}" database_path: "Connecting to database at: %{database_path}" database_initialized: "Database initialized." -database_table_create: "Database table %{table_name} is created." \ No newline at end of file +database_table_create: "Database table %{table_name} is created." + +welcome.version: "Version: %{version}" +welcome.text: "Welcome to Omega Code!" +welcome.menu: "Quick Menu(use ↑/↓ keys to navigate, press enter to select an item):" +welcome.menu_items.0: "Open Omega Code Console Panel, to configure the application." +welcome.menu_items.1: "Start a new project." +welcome.menu_items.2: "Quit" diff --git a/locales/zh-CN.yml b/locales/zh-CN.yml index 7a724f9..e12d17a 100644 --- a/locales/zh-CN.yml +++ b/locales/zh-CN.yml @@ -4,4 +4,12 @@ logger_is_initialized: "日志已经初始化了喵~" current_locale: "当前语言: %{locale_name}" database_path: "数据库位置: %{database_path}" database_initialized: "数据库初始化成功" -database_table_create: "数据表 %{table_name} 已创建" \ No newline at end of file +database_table_create: "数据表 %{table_name} 已创建" + +welcome.version: "版本: %{version}" +welcome.text: "欢迎来到 Omega Code !" +welcome.menu: "快速菜单(使用 ↑/↓ 键导航,按 enter 选择项):" +menu_items: + - "打开 Omega Code 控制台面板,配置应用程序" + - "开始新项目" + - "退出" diff --git a/src/components/input_bar.rs b/src/components/input_bar.rs new file mode 100644 index 0000000..647ab51 --- /dev/null +++ b/src/components/input_bar.rs @@ -0,0 +1,67 @@ +use ratatui_kit::{ + crossterm::event::{Event, KeyCode, KeyEventKind}, + prelude::*, + ratatui::{ + layout::Constraint, + style::{Style, Stylize}, + text::Line, + }, +}; + +#[component] +pub fn InputBar(mut hooks: Hooks) -> impl Into> { + let mut value = hooks.use_state(String::new); + + let mut should_exit = hooks.use_state(|| false); + + let mut system_ctx = hooks.use_context_mut::(); + let insert_before = hooks.use_insert_before(); + + if should_exit.get() { + system_ctx.exit(); + } + + hooks.use_events(move |event| { + if let Event::Key(key_event) = event { + if key_event.kind == KeyEventKind::Press { + match key_event.code { + KeyCode::Esc => { + should_exit.set(true); + } + KeyCode::Enter => { + if !value.read().is_empty() { + insert_before + .render_before(Line::from(format!("message: {value}")), 1) + .finish(); + + value.set(String::new()); + } + } + _ => {} + } + } + } + }); + + element!(Border( + height: Constraint::Length(4), + style: Style::default().green(), + bottom_title: Line::styled( + "Press 'Enter' to submit, 'Esc' to exit", + Style::default().yellow(), + ).centered(), + ) { + TextArea( + value: value.read().to_string(), + is_focus: true, + on_change: move |new_value: String| { + value.set(new_value); + }, + multiline: false, + cursor_style: Style::default().on_green(), + placeholder: Some("Type something...".to_string()), + placeholder_style: Style::default().green(), + ) + + }) +} \ No newline at end of file diff --git a/src/components/mod.rs b/src/components/mod.rs index 3d8b2be..ee26743 100644 --- a/src/components/mod.rs +++ b/src/components/mod.rs @@ -1 +1,3 @@ pub mod welcome; +pub(crate) mod input_bar; +mod status_bar; diff --git a/src/core/route/mod.rs b/src/components/status_bar.rs similarity index 100% rename from src/core/route/mod.rs rename to src/components/status_bar.rs diff --git a/src/components/welcome.rs b/src/components/welcome.rs index decc579..0ef5f9e 100644 --- a/src/components/welcome.rs +++ b/src/components/welcome.rs @@ -1,36 +1,248 @@ -pub fn output_welcome_screen(version: &str, version_info: &str) { - println!(" - ██████╗ ███╗ ███╗███████╗ ██████╗ █████╗ -██╔═══██╗████╗ ████║██╔════╝██╔════╝ ██╔══██╗ -██║ ██║██╔████╔██║█████╗ ██║ ███╗███████║ -██║ ██║██║╚██╔╝██║██╔══╝ ██║ ██║██╔══██║ -╚██████╔╝██║ ╚═╝ ██║███████╗╚██████╔╝██║ ██║ - ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝ - - ██████╗ ██████╗ ██████╗ ███████╗ -██╔════╝██╔═══██╗██╔══██╗██╔════╝ -██║ ██║ ██║██║ ██║█████╗ -██║ ██║ ██║██║ ██║██╔══╝ -╚██████╗╚██████╔╝██████╔╝███████╗ - ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ -Omega Code v{} ({})", - &version, &version_info); -} +use ratatui_kit::{ + Component, + ComponentDrawer, + ComponentUpdater, + Hooks, + Props, + UseEvents, + UseState, +}; + +use ratatui_kit::crossterm::event::{Event, KeyCode}; -pub fn output_main_screen() { - println!(" +use ratatui_kit::ratatui::{ + style::{Modifier, Style}, + text::{Line, Span}, + widgets::{Paragraph, Widget}, +}; +#[derive(Props)] +pub struct WelcomeProps { + pub version: Option, + pub style: Style, + pub menu_style: Style, + pub show_menu: bool, +} + +impl Default for WelcomeProps { + fn default() -> Self { + Self { + version: None, + style: Style::default(), + menu_style: Style::default(), + show_menu: true, + } + } +} - ▄████▄ - ██▀ ▀██ - ██ ██ - ██ ██ - ▄██ ██▄ - ▀▀▀ ▀▀▀ +pub struct Welcome { + selected_index: usize, - -") + // props cache + style: Style, + menu_style: Style, + version: Option, + show_menu: bool, } -fn main() { - output_welcome_screen("123","12"); + +impl Component for Welcome { + type Props<'a> = WelcomeProps; + + fn new(props: &Self::Props<'_>) -> Self { + Self { + selected_index: 0, + + style: props.style, + menu_style: props.menu_style, + version: props.version.clone(), + show_menu: props.show_menu, + } + } + + fn update( + &mut self, + props: &mut Self::Props<'_>, + mut hooks: Hooks, + _updater: &mut ComponentUpdater, + ) { + // sync props + self.style = props.style; + self.menu_style = props.menu_style; + self.version = props.version.clone(); + self.show_menu = props.show_menu; + + let mut state_index = hooks.use_state(|| self.selected_index); + + hooks.use_events(move |event| { + if let Event::Key(key) = event { + match key.code { + KeyCode::Up => { + state_index.set( + state_index + .get() + .saturating_sub(1), + ); + } + + KeyCode::Down => { + let current = state_index.get(); + + state_index.set((current + 1).min(2)); + } + + KeyCode::Enter => { + match state_index.get() { + 0 => { + todo!("打开配置"); + } + + 1 => { + todo!("开启新项目"); + } + + 2 => { + todo!("退出程序"); + } + + _ => {} + } + } + + _ => {} + } + } + }); + + self.selected_index = state_index.get(); + } + + fn draw(&mut self, drawer: &mut ComponentDrawer<'_, '_>) { + let area = drawer.area; + let buf = drawer.buffer_mut(); + + // ASCII LOGO + let ascii_lines = [ + " ██████╗ ███╗ ███╗███████╗ ██████╗ █████╗", + "██╔═══██╗████╗ ████║██╔════╝██╔════╝ ██╔══██╗", + "██║ ██║██╔████╔██║█████╗ ██║ ███╗███████║", + "██║ ██║██║╚██╔╝██║██╔══╝ ██║ ██║██╔══██║", + "╚██████╔╝██║ ╚═╝ ██║███████╗╚██████╔╝██║ ██║", + " ╚═════╝ ╚═╝ ╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═╝", + "", + " ██████╗ ██████╗ ██████╗ ███████╗", + "██╔════╝██╔═══██╗██╔══██╗██╔════╝", + "██║ ██║ ██║██║ ██║█████╗ ", + "██║ ██║ ██║██║ ██║██╔══╝ ", + "╚██████╗╚██████╔╝██████╔╝███████╗", + " ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝", + ]; + + let version = self + .version + .clone() + .unwrap_or_else(|| { + env!("CARGO_PKG_VERSION").to_string() + }); + + let welcome_text = t!("welcome.text"); + + let menu_items = [ + t!("welcome.menu_items.0"), + t!("welcome.menu_items.1"), + t!("welcome.menu_items.2"), + ]; + + let mut lines = Vec::new(); + + // logo + for line in ascii_lines { + lines.push( + Line::from( + Span::styled( + line, + self.style, + ) + ) + ); + } + + lines.push(Line::from("")); + + // version + lines.push( + Line::from( + Span::styled( + t!("welcome.version", version = version), + self.style.add_modifier(Modifier::DIM), + ) + ) + ); + + lines.push(Line::from("")); + + // welcome text + lines.push( + Line::from( + Span::styled( + welcome_text, + self.style, + ) + ) + ); + + lines.push(Line::from("")); + + // menu title + lines.push( + Line::from( + Span::styled( + t!("welcome.menu"), + self.style.add_modifier(Modifier::BOLD), + ) + ) + ); + + lines.push(Line::from("")); + + // menu + if self.show_menu { + let max_index = menu_items + .len() + .saturating_sub(1); + + self.selected_index = + self.selected_index.min(max_index); + + for (i, item) in menu_items.iter().enumerate() { + let selected = + i == self.selected_index; + + let prefix = if selected { + "→ " + } else { + " " + }; + + let style = if selected { + self.menu_style.add_modifier( + Modifier::BOLD + | Modifier::REVERSED, + ) + } else { + self.style + }; + + lines.push( + Line::from( + Span::styled( + format!("{prefix}• {item}"), + style, + ) + ) + ); + } + } + + Paragraph::new(lines).render(area, buf); + } } \ No newline at end of file diff --git a/src/core/mod.rs b/src/core/mod.rs index 6582b9b..f5562e2 100644 --- a/src/core/mod.rs +++ b/src/core/mod.rs @@ -1,6 +1,4 @@ pub mod action; -pub mod state; -pub mod route; pub mod event; pub mod update; pub mod context; diff --git a/src/lib.rs b/src/lib.rs index a649d84..d59f23f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -3,30 +3,36 @@ extern crate rust_i18n; use std::io; use log::info; +use ratatui_kit::{element, ElementExt}; +use ratatui_kit::prelude::RouterProvider; use rust_i18n::t; use crate::core::db::DatabaseManager; -use crate::ui::layout::App; +use crate::pages::layout::App; pub mod core; pub mod runtime; pub mod services; -pub mod ui; +pub mod pages; pub mod utils; pub mod components; pub mod health; pub mod platform; pub mod db; +pub mod state; +pub mod router; + +// use crate::pages::chat::chat_page; +use crate::pages::welcome::WelcomePage; i18n!("locales", fallback = "en"); -pub fn run() -> anyhow::Result<()> { + +#[tokio::main] +pub async fn run() -> anyhow::Result<()> { info!("{}", t!("logger_is_initialized")); info!("{}", t!("test_message", name = "OmegaCode")); info!("{}", t!("current_locale", locale_name = "en")); let db = DatabaseManager::new()?; db.health_check()?; - let mut terminal = ratatui::init(); - let mut app = App::default(); - let result = app.run(&mut terminal); - ratatui::restore(); - result + element!(WelcomePage()).fullscreen().await.expect("Failed to render welcome page"); + Ok(()) } diff --git a/src/pages/chat.rs b/src/pages/chat.rs new file mode 100644 index 0000000..3518cd6 --- /dev/null +++ b/src/pages/chat.rs @@ -0,0 +1,10 @@ +use ratatui_kit::{component, element, AnyElement, ElementExt, Hooks}; +use ratatui_kit::components::View; +use ratatui_kit::ratatui::{TerminalOptions, Viewport}; +use ratatui_kit::ratatui::layout::Direction; +use crate::components::input_bar::InputBar; + +#[component] +pub fn ChatPage(mut hooks: Hooks) -> impl Into> { + element!(ratatui_kit::components::textarea::TextArea) +} \ No newline at end of file diff --git a/src/pages/context.rs b/src/pages/context.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/ui/layout.rs b/src/pages/layout.rs similarity index 100% rename from src/ui/layout.rs rename to src/pages/layout.rs diff --git a/src/pages/mod.rs b/src/pages/mod.rs new file mode 100644 index 0000000..4c2aff3 --- /dev/null +++ b/src/pages/mod.rs @@ -0,0 +1,4 @@ +pub mod layout; +pub mod welcome; +pub mod chat; +pub mod context; diff --git a/src/pages/welcome.rs b/src/pages/welcome.rs new file mode 100644 index 0000000..ce612ea --- /dev/null +++ b/src/pages/welcome.rs @@ -0,0 +1,13 @@ +use ratatui_kit::{component, element, AnyElement}; +use ratatui_kit::prelude::View; +use ratatui_kit::ratatui::prelude::Direction; +use crate::components::welcome::Welcome; + +#[component] +pub fn WelcomePage() -> impl Into> { + element!(View( + flex_direction: Direction::Horizontal, + ) { + Welcome() + }) +} diff --git a/src/router/mod.rs b/src/router/mod.rs new file mode 100644 index 0000000..7c2cbff --- /dev/null +++ b/src/router/mod.rs @@ -0,0 +1,10 @@ +use ratatui_kit::prelude::*; +use crate::pages::welcome::WelcomePage; +// use crate::pages::chat::chat_page; +// use crate::pages::context::context_page; +pub fn app_routes() -> Vec { + let routes = routes!{ + "/welcome" => WelcomePage, + }; + routes +} \ No newline at end of file diff --git a/src/core/state/mod.rs b/src/state/mod.rs similarity index 100% rename from src/core/state/mod.rs rename to src/state/mod.rs diff --git a/src/core/state/state.rs b/src/state/state.rs similarity index 61% rename from src/core/state/state.rs rename to src/state/state.rs index c6f8e30..cd5bccf 100644 --- a/src/core/state/state.rs +++ b/src/state/state.rs @@ -1,4 +1,4 @@ // pub struct AppState { -// pub route: Route; +// pub router: Route; // pub // } \ No newline at end of file diff --git a/src/ui/mod.rs b/src/ui/mod.rs deleted file mode 100644 index 0cc99f7..0000000 --- a/src/ui/mod.rs +++ /dev/null @@ -1 +0,0 @@ -pub mod layout; \ No newline at end of file