feat(tui/greeting): time-based greeting placeholder for composer, welcome, and history cells

This commit is contained in:
James Peter
2025-09-06 20:11:05 +10:00
parent 2e64668ee7
commit 26b6d3c573
5 changed files with 26 additions and 4 deletions
@@ -41,7 +41,7 @@ use std::thread;
use std::time::Duration;
use std::time::Instant;
const BASE_PLACEHOLDER_TEXT: &str = "Welcome to Code — What are we coding today? Type / to see commands";
// Dynamic placeholder rendered when the composer is empty.
/// If the pasted content exceeds this number of characters, replace it with a
/// placeholder in the UI.
const LARGE_PASTE_CHAR_THRESHOLD: usize = 1000;
@@ -1608,7 +1608,8 @@ impl WidgetRef for ChatComposer {
StatefulWidgetRef::render_ref(&(&self.textarea), padded_textarea_rect, buf, &mut state);
// Only show placeholder if there's no chat history AND no text typed
if !self.typed_anything && self.textarea.text().is_empty() {
Line::from(BASE_PLACEHOLDER_TEXT)
let placeholder = crate::greeting::greeting_placeholder();
Line::from(placeholder)
.style(Style::default().dim())
.render_ref(padded_textarea_rect, buf);
}
+20
View File
@@ -0,0 +1,20 @@
use chrono::Local;
use chrono::Timelike;
/// Build a time-aware placeholder like
/// "What can I code for you this morning?".
pub(crate) fn greeting_placeholder() -> String {
let hour = Local::now().hour();
let when = if (5..=11).contains(&hour) {
"this morning"
} else if (12..=16).contains(&hour) {
"this afternoon"
} else if (17..=20).contains(&hour) {
"this evening"
} else {
// Late night and very early hours
"tonight"
};
format!("What can I code for you {when}?")
}
+1 -1
View File
@@ -2453,7 +2453,7 @@ impl HistoryCell for AnimatedWelcomeCell {
vec![
Line::from(""),
Line::from("Welcome to Code"),
Line::from("What can I code for you today?"),
Line::from(crate::greeting::greeting_placeholder()),
Line::from(""),
]
}
+1
View File
@@ -69,6 +69,7 @@ mod user_approval_widget;
mod height_manager;
mod transcript_app;
mod clipboard_paste;
mod greeting;
// Upstream introduced a standalone status indicator widget. Our fork renders
// status within the composer title; keep the module private unless tests need it.
mod status_indicator_widget;
+1 -1
View File
@@ -30,7 +30,7 @@ impl WidgetRef for &WelcomeWidget {
if area.height > 1 {
let line2 = Line::from(vec![
Span::raw(" "), // Indent to align with text after ">_ "
Span::raw("What can I code for you today?"),
Span::raw(crate::greeting::greeting_placeholder()),
]);
let line2_area = Rect {
x: area.x,