aboutsummaryrefslogtreecommitdiff
path: root/src/app/input.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-03-28 21:13:41 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-03-28 21:13:41 +0300
commitfa1adf1a26033fc50a2920d96045e76aba93bddb (patch)
tree383bd48d0c6bcad7ccf1d5c907f78fd7eee1797f /src/app/input.rs
parentd05ba2ea9f1ab2379f5be5ef7fc3898a03f5dce1 (diff)
feat: add onboarding and toast notification preferences
Diffstat (limited to 'src/app/input.rs')
-rw-r--r--src/app/input.rs103
1 files changed, 103 insertions, 0 deletions
diff --git a/src/app/input.rs b/src/app/input.rs
index 590e9548..7d2e709e 100644
--- a/src/app/input.rs
+++ b/src/app/input.rs
@@ -18,6 +18,7 @@ use super::App;
impl App {
pub(super) async fn handle_key(&mut self, key: KeyEvent) {
match self.state.mode {
+ Mode::Onboarding => self.handle_onboarding_key(key),
Mode::Navigate => handle_navigate_key(&mut self.state, key),
Mode::Terminal => self.handle_terminal_key(key).await,
Mode::RenameSession => handle_rename_key(&mut self.state, key),
@@ -49,6 +50,39 @@ impl App {
}
}
+ fn handle_onboarding_key(&mut self, key: KeyEvent) {
+ match self.state.onboarding_step {
+ 0 => match key.code {
+ KeyCode::Enter | KeyCode::Right | KeyCode::Char('l') => {
+ self.state.onboarding_step = 1;
+ }
+ KeyCode::Char('q') => self.state.should_quit = true,
+ _ => {}
+ },
+ _ => match key.code {
+ KeyCode::Up | KeyCode::Char('k') => {
+ if self.state.onboarding_selected > 0 {
+ self.state.onboarding_selected -= 1;
+ }
+ }
+ KeyCode::Down | KeyCode::Char('j') => {
+ if self.state.onboarding_selected < 3 {
+ self.state.onboarding_selected += 1;
+ }
+ }
+ KeyCode::Left | KeyCode::Esc | KeyCode::Char('h') => {
+ self.state.onboarding_step = 0;
+ }
+ KeyCode::Char(c) if ('1'..='4').contains(&c) => {
+ self.state.onboarding_selected = (c as usize) - ('1' as usize);
+ }
+ KeyCode::Enter => self.complete_onboarding(),
+ KeyCode::Char('q') => self.state.should_quit = true,
+ _ => {}
+ },
+ }
+ }
+
async fn handle_terminal_key(&mut self, key: KeyEvent) {
self.state.clear_selection();
self.state.update_dismissed = true;
@@ -338,7 +372,76 @@ fn handle_context_menu_key(state: &mut AppState, key: KeyEvent) {
// ---------------------------------------------------------------------------
impl AppState {
+ fn onboarding_full_area(&self) -> ratatui::layout::Rect {
+ self.view.sidebar_rect.union(self.view.terminal_area)
+ }
+
+ fn onboarding_modal_inner(&self, popup_w: u16, popup_h: u16) -> Option<ratatui::layout::Rect> {
+ let area = self.onboarding_full_area();
+ let popup_w = popup_w.min(area.width.saturating_sub(4));
+ let popup_h = popup_h.min(area.height.saturating_sub(2));
+ if popup_w < 4 || popup_h < 4 {
+ return None;
+ }
+ let popup_x = area.x + (area.width.saturating_sub(popup_w)) / 2;
+ let popup_y = area.y + (area.height.saturating_sub(popup_h)) / 2;
+ let popup = ratatui::layout::Rect::new(popup_x, popup_y, popup_w, popup_h);
+ let block = ratatui::widgets::Block::default().borders(ratatui::widgets::Borders::ALL);
+ Some(block.inner(popup))
+ }
+
+ fn handle_onboarding_mouse(&mut self, mouse: MouseEvent) {
+ if mouse.kind != MouseEventKind::Down(MouseButton::Left) {
+ return;
+ }
+
+ match self.onboarding_step {
+ 0 => {
+ let Some(inner) = self.onboarding_modal_inner(64, 15) else {
+ return;
+ };
+ let footer_y = inner.y + 9;
+ let button_x = inner.x;
+ let button_w = 14;
+ if mouse.row == footer_y
+ && mouse.column >= button_x
+ && mouse.column < button_x + button_w
+ {
+ self.onboarding_step = 1;
+ }
+ }
+ _ => {
+ let Some(inner) = self.onboarding_modal_inner(52, 10) else {
+ return;
+ };
+ let options_start_y = inner.y + 2;
+ if mouse.row >= options_start_y && mouse.row < options_start_y + 4 {
+ self.onboarding_selected = (mouse.row - options_start_y) as usize;
+ return;
+ }
+
+ let footer_y = inner.y + 6;
+ let back_x = inner.x;
+ let back_w = 10;
+ let save_x = inner.x + 12;
+ let save_w = 10;
+ if mouse.row == footer_y {
+ if mouse.column >= back_x && mouse.column < back_x + back_w {
+ self.onboarding_step = 0;
+ } else if mouse.column >= save_x && mouse.column < save_x + save_w {
+ self.request_complete_onboarding = true;
+ }
+ }
+ }
+ }
+ }
+
pub(crate) fn handle_mouse(&mut self, mouse: MouseEvent) {
+ if self.mode == Mode::Onboarding {
+ self.handle_onboarding_mouse(mouse);
+ return;
+ }
+
let sidebar = self.view.sidebar_rect;
let in_sidebar = mouse.column >= sidebar.x
&& mouse.column < sidebar.x + sidebar.width