Skip to content

Commit 8271e6e

Browse files
authored
Feature/components (#34)
1 parent 07eac18 commit 8271e6e

6 files changed

Lines changed: 146 additions & 3 deletions

File tree

src/components/input_bar.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ pub fn InputBar(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
4444
});
4545

4646
element!(Border(
47-
height: Constraint::Length(4),
47+
height: Constraint::Length(6),
4848
style: Style::default().green(),
49-
bottom_title: Line::styled(
50-
"Press 'Enter' to submit, 'Esc' to exit",
49+
top_title: Line::styled(
50+
"Composer",
5151
Style::default().yellow(),
5252
).centered(),
5353
) {

src/components/main_scroll.rs

Whitespace-only changes.

src/components/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
pub mod welcome;
22
pub mod input_bar;
33
pub mod status_bar;
4+
mod main_scroll;
5+
mod progress_bar;

src/components/progress_bar.rs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
use ratatui_kit::prelude::*;
2+
use ratatui_kit::ratatui::{
3+
style::{Modifier, Style},
4+
text::{Line, Span},
5+
};
6+
use ratatui_kit::ratatui::layout::Direction;
7+
8+
#[derive(Debug, Clone, Props)]
9+
pub struct ProgressBarProps {
10+
pub style: Style,
11+
pub menu_style: Style,
12+
pub install_message: String,
13+
pub stage: String,
14+
pub percent: f64,
15+
pub downloaded: u64,
16+
pub total: u64,
17+
pub speed: f64,
18+
}
19+
20+
impl Default for ProgressBarProps {
21+
fn default() -> Self {
22+
Self {
23+
style: Style::default(),
24+
menu_style: Style::default(),
25+
install_message: String::new(),
26+
stage: String::new(),
27+
percent: 0.0,
28+
downloaded: 0,
29+
total: 0,
30+
speed: 0.0,
31+
}
32+
}
33+
}
34+
35+
#[component]
36+
pub fn ProgressBar(
37+
_hooks: Hooks,
38+
props: &ProgressBarProps,
39+
) -> impl Into<AnyElement<'static>> {
40+
// 计算进度条
41+
let percent = props.percent.clamp(0.0, 100.0);
42+
const BAR_WIDTH: usize = 30;
43+
let fill = ((percent / 100.0 * BAR_WIDTH as f64) as usize).min(BAR_WIDTH);
44+
let bar = format!("[{}{}]", "█".repeat(fill), "░".repeat(BAR_WIDTH - fill));
45+
46+
let mut spans = vec![
47+
Span::styled(bar, props.menu_style),
48+
Span::raw(format!(" {:.2}%", percent)),
49+
];
50+
51+
if props.stage.contains("Downloading") {
52+
let mb = props.downloaded as f64 / 1024.0 / 1024.0;
53+
let total_mb = props.total as f64 / 1024.0 / 1024.0;
54+
let speed_mb = props.speed / 1024.0 / 1024.0;
55+
spans.push(Span::raw(format!(" ({:.2} MB/{:.2} MB)", mb, total_mb)));
56+
spans.push(Span::raw(format!(" {:.2} MB/s", speed_mb)));
57+
} else {
58+
spans.push(Span::raw(format!(" {} / {}", props.downloaded, props.total)));
59+
}
60+
61+
// 官方标准 element! 语法(零错误)
62+
element! {
63+
View(flex_direction: Direction::Vertical) {
64+
// 必须传 String,不能传 &str
65+
Text(text: props.install_message.clone(), style: props.style.add_modifier(Modifier::BOLD)) {}
66+
Text(text: String::new()) {}
67+
68+
// 官方条件渲染:#(if ...)
69+
#(if !props.stage.is_empty() {
70+
Some(element! {
71+
View {
72+
Text(text: props.stage.clone(), style: props.style.add_modifier(Modifier::BOLD)) {}
73+
// Text(spans: spans) {}
74+
}
75+
})
76+
} else {
77+
None
78+
})
79+
}
80+
}
81+
}

src/db/store/mod.rs

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
use ratatui_kit::Store;
2+
3+
pub struct TodoItem {
4+
pub id: u32,
5+
pub title: String,
6+
pub completed: bool,
7+
}
8+
9+
pub struct TodoList {
10+
pub items: Vec<TodoItem>,
11+
}
12+
13+
pub struct TaskItem {
14+
pub id: u32,
15+
pub title: String,
16+
pub completed: bool,
17+
}
18+
19+
pub struct TaskList {
20+
pub items: Vec<TaskItem>,
21+
}
22+
23+
#[derive(Store)]
24+
pub struct GlobalStore {
25+
pub llm_name: String,
26+
pub current_chat: String,
27+
pub cache_size: f64,
28+
pub context_size: f64,
29+
pub model_context_window: f64,
30+
pub input_tokens: u32,
31+
pub output_tokens: u32,
32+
pub current_chat_count: u32,
33+
pub todo_list: TodoList,
34+
pub task_list: TaskList,
35+
pub input_buffer: String,
36+
}
37+
38+
impl Default for GlobalStore {
39+
fn default() -> Self {
40+
Self {
41+
llm_name: String::new(),
42+
current_chat: String::new(),
43+
cache_size: 0.0,
44+
context_size: 0.0,
45+
model_context_window: 0.0,
46+
input_tokens: 0,
47+
output_tokens: 0,
48+
current_chat_count: 0,
49+
todo_list: TodoList {
50+
items: Vec::new(),
51+
},
52+
task_list: TaskList {
53+
items: Vec::new(),
54+
},
55+
input_buffer: String::new(),
56+
}
57+
}
58+
}

src/pages/router.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ pub fn RouterPage(mut hooks: Hooks) -> impl Into<AnyElement<'static>> {
2424
});
2525

2626
//todo 这里的逻辑是通过数据库查询是否初始化,从而确定要路由到 Welcome 还是 Chat
27+
//todo 为了开发方便,这里的逻辑还需要判断是否是开发环境,如果是开发环境,默认路由到路由页面,路由页面在生产环境不对外暴露
28+
//todo 同时路由函数禁止在生成环境中调用,避免在生产环境中路由到路由页面
2729

2830
element!(
2931
View(height: Constraint::Length(10),) {

0 commit comments

Comments
 (0)