Files
mqttx/gpui-app/src/ui/widgets/common.rs
T
JoeAllen bc9f55c889 refactor(ui): 拆分 app/connection_view/widgets 为子组件,对话框归拢 dialogs/
- ui/app/ 拆为门面、events(引擎事件泵)、actions(用户动作)、io(导入导出)、
  theme(主题)、titlebar/sidebar/main_area(渲染分区)
- ui/connection_view/ 拆为门面、subscribe、messages、publish、vars、util(纯函数)
- ui/widgets/ 拆为 select(可搜索下拉)、kv_editor、common(字段行/状态/时间)
- 五个对话框归拢 ui/dialogs/,linear-theme.json 随 theme.rs 迁入 ui/app/
- clippy 0 警告,全部路径经门面保持稳定
2026-09-29 22:20:53 +08:00

69 lines
2.5 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 基础部件:字段行布局、连接状态指示、时间格式化。
use gpui_kit::component::{h_flex, v_flex, ActiveTheme as _};
use gpui_kit::{div, px, App, Hsla, IntoElement, ParentElement as _, SharedString, Styled as _};
use crate::model::ConnectionStatus;
/// 小号标签 + 控件的垂直字段容器(可选字段,无校验态)。
pub fn field(label: impl Into<SharedString>, control: impl IntoElement) -> impl IntoElement {
field_ex(label, control, false, None, Hsla::default())
}
/// 字段行变体:`required` 时标签后追加红色 `*`;
/// `error` 为 Some 时在控件下方渲染红字提示(`danger` 为主题错误色)。
pub fn field_ex(
label: impl Into<SharedString>,
control: impl IntoElement,
required: bool,
error: Option<SharedString>,
danger: Hsla,
) -> impl IntoElement {
v_flex()
.gap_1()
.min_w(px(0.))
.child(
h_flex()
.gap_0p5()
.items_baseline()
.child(div().text_xs().child(label.into()))
.children(required.then(|| div().text_xs().text_color(danger).child("*"))),
)
.child(control)
.children(error.map(|e| div().text_xs().text_color(danger).child(e)))
}
// ─── 状态颜色 ────────────────────────────────────────────────────────────────
pub fn status_color(status: ConnectionStatus, cx: &App) -> Hsla {
let t = cx.theme();
match status {
ConnectionStatus::Connected => t.success,
ConnectionStatus::Connecting => t.warning,
ConnectionStatus::Error => t.danger,
ConnectionStatus::Disconnected => t.muted_foreground,
}
}
pub fn status_dot(status: ConnectionStatus, cx: &App) -> impl IntoElement {
div()
.size(px(8.))
.rounded_full()
.bg(status_color(status, cx))
}
// ─── 键值对编辑器 ────────────────────────────────────────────────────────────
pub fn format_time(ts_ms: i64, show_millis: bool) -> String {
use chrono::TimeZone as _;
let Some(dt) = chrono::Local.timestamp_millis_opt(ts_ms).single() else {
return String::new();
};
if show_millis {
dt.format("%H:%M:%S%.3f").to_string()
} else {
dt.format("%H:%M:%S").to_string()
}
}