Skip to content

Commit 51a74a7

Browse files
authored
fix: 修复聊天栏与消息显示相关问题
- 聊天栏支持输入空格 - 消息显示不再自动换行
2 parents 62d480c + 53cf36e commit 51a74a7

3 files changed

Lines changed: 77 additions & 22 deletions

File tree

crates/client/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,13 @@ fn forward_keydown_to_egui(
545545
) {
546546
e.prevent_default();
547547
}
548+
// egui 的 TextEdit 依赖 Text 事件插入字符;Space 同时也是功能键,
549+
// 因此需要在没有组合键修饰时额外补一个文本空格,聊天输入框才能输入空格。
550+
if egui_key == egui::Key::Space && !modifiers.ctrl && !modifiers.alt && !modifiers.mac_cmd {
551+
egui_events
552+
.borrow_mut()
553+
.push(egui::Event::Text(" ".to_string()));
554+
}
548555
} else if key_str.chars().count() == 1
549556
&& !modifiers.ctrl
550557
&& !modifiers.alt

crates/client/src/ui/chat.rs

Lines changed: 62 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,23 @@
66
//!
77
//! 数据模型见 [`crate::chat::ChatHistory`];UI 层仅做渲染与输入捕获,不负责发送 / 持久化。
88
9+
use std::borrow::Cow;
10+
911
use crate::chat::{ChatHistory, ChatKind};
1012

13+
/// 聊天 UI 只按单行展示消息:自动换行由 Label 配置禁止,显式 CR/LF 也在显示层折成空格。
14+
fn single_line_text(text: &str) -> Cow<'_, str> {
15+
if text.contains('\n') || text.contains('\r') {
16+
Cow::Owned(
17+
text.chars()
18+
.map(|c| if matches!(c, '\n' | '\r') { ' ' } else { c })
19+
.collect(),
20+
)
21+
} else {
22+
Cow::Borrowed(text)
23+
}
24+
}
25+
1126
/// 聊天 UI 单帧返回的动作。
1227
#[derive(Clone, Debug, PartialEq, Eq)]
1328
pub enum ChatUiAction {
@@ -45,22 +60,36 @@ pub fn draw_chat_window(ctx: &egui::Context, history: &mut ChatHistory) -> ChatU
4560
.stick_to_bottom(true)
4661
.show(ui, |ui| {
4762
for msg in history.recent(50) {
48-
ui.horizontal_wrapped(|ui| match &msg.kind {
63+
// 一条聊天消息固定占一行;正文用 Extend 禁止自动换行,
64+
// 避免玩家名和消息内容在宽度边界附近被拆到两行。
65+
ui.horizontal(|ui| match &msg.kind {
4966
ChatKind::System => {
50-
ui.colored_label(
51-
egui::Color32::from_rgb(160, 170, 180),
52-
format!("[System] {}", msg.content),
67+
let content = single_line_text(&msg.content);
68+
ui.add(
69+
egui::Label::new(
70+
egui::RichText::new(format!("[System] {content}"))
71+
.color(egui::Color32::from_rgb(160, 170, 180)),
72+
)
73+
.wrap_mode(egui::TextWrapMode::Extend),
5374
);
5475
}
5576
ChatKind::User { from_name, .. } => {
56-
ui.label(
57-
egui::RichText::new(format!("{from_name}: "))
58-
.strong()
59-
.color(egui::Color32::from_rgb(220, 230, 240)),
77+
let from_name = single_line_text(from_name);
78+
let content = single_line_text(&msg.content);
79+
ui.add(
80+
egui::Label::new(
81+
egui::RichText::new(format!("{from_name}: "))
82+
.strong()
83+
.color(egui::Color32::from_rgb(220, 230, 240)),
84+
)
85+
.wrap_mode(egui::TextWrapMode::Extend),
6086
);
61-
ui.label(
62-
egui::RichText::new(&msg.content)
63-
.color(egui::Color32::from_rgb(230, 235, 240)),
87+
ui.add(
88+
egui::Label::new(
89+
egui::RichText::new(content.as_ref())
90+
.color(egui::Color32::from_rgb(230, 235, 240)),
91+
)
92+
.wrap_mode(egui::TextWrapMode::Extend),
6493
);
6594
}
6695
});
@@ -125,23 +154,37 @@ pub fn draw_recent_overlay(ctx: &egui::Context, history: &ChatHistory, now_ms: f
125154
ChatKind::System => {
126155
// 系统消息:淡灰色。
127156
let color = egui::Color32::from_rgba_unmultiplied(170, 180, 195, alpha);
128-
ui.label(
129-
egui::RichText::new(format!("[System] {}", msg.content)).color(color),
157+
let content = single_line_text(&msg.content);
158+
ui.add(
159+
egui::Label::new(
160+
egui::RichText::new(format!("[System] {content}")).color(color),
161+
)
162+
.wrap_mode(egui::TextWrapMode::Extend),
130163
);
131164
}
132165
ChatKind::User { from_name, .. } => {
133166
// 用户消息:发送者加粗稍亮 + 内容白底。
167+
let from_name = single_line_text(from_name);
168+
let content = single_line_text(&msg.content);
134169
let name_color =
135170
egui::Color32::from_rgba_unmultiplied(235, 215, 130, alpha);
136171
let body_color =
137172
egui::Color32::from_rgba_unmultiplied(240, 240, 240, alpha);
138-
ui.horizontal_wrapped(|ui| {
139-
ui.label(
140-
egui::RichText::new(format!("{from_name}: "))
141-
.strong()
142-
.color(name_color),
173+
ui.horizontal(|ui| {
174+
ui.add(
175+
egui::Label::new(
176+
egui::RichText::new(format!("{from_name}: "))
177+
.strong()
178+
.color(name_color),
179+
)
180+
.wrap_mode(egui::TextWrapMode::Extend),
181+
);
182+
ui.add(
183+
egui::Label::new(
184+
egui::RichText::new(content.as_ref()).color(body_color),
185+
)
186+
.wrap_mode(egui::TextWrapMode::Extend),
143187
);
144-
ui.label(egui::RichText::new(&msg.content).color(body_color));
145188
});
146189
}
147190
}

docs/features/ui.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,10 @@ pub fn draw(app: &mut App, ctx: &egui::Context) {
418418
- T 键打开(`chat_open = true`
419419
- Enter 提交并关闭
420420
- ESC 取消并关闭
421+
- 聊天输入接收普通文本事件;Space 既要转成 `egui::Event::Key(Key::Space)`,也要转成
422+
`egui::Event::Text(" ")`,否则 `TextEdit` 只能感知按键状态,无法真正插入空格。
423+
- 聊天历史和最近消息浮窗按单行显示:Label 使用 `TextWrapMode::Extend`,显式 CR/LF
424+
只在显示层折成空格,不改变协议里的原始消息内容。
421425

422426
### 布局
423427

@@ -443,12 +447,13 @@ pub fn draw(app: &mut App, ctx: &egui::Context) {
443447
.title_bar(false)
444448
.min_width(400.0)
445449
.show(ctx, |ui| {
446-
// 历史
450+
// 历史:一条消息固定渲染为单行,避免发送者名和正文在窄宽度下被拆行。
447451
egui::ScrollArea::vertical().max_height(200.0).stick_to_bottom(true).show(ui, |ui| {
448452
for msg in app.chat.recent(50) {
449-
ui.horizontal_wrapped(|ui| {
453+
ui.horizontal(|ui| {
450454
ui.label(egui::RichText::new(format!("{}: ", msg.from)).strong());
451-
ui.label(&msg.content);
455+
ui.add(egui::Label::new(&msg.content)
456+
.wrap_mode(egui::TextWrapMode::Extend));
452457
});
453458
}
454459
});

0 commit comments

Comments
 (0)