This commit is contained in:
2026-05-20 19:31:16 +02:00
parent 20f33f5694
commit 8b07e305f0
17 changed files with 1794 additions and 573 deletions

View File

@ -1,11 +1,12 @@
mod app;
mod crypto;
mod ipc;
mod models;
mod ui;
use app::{App, Mode};
use crossterm::{
event::{self, Event, KeyCode},
event::{self, Event, KeyCode, KeyModifiers},
execute,
terminal::{EnterAlternateScreen, LeaveAlternateScreen, disable_raw_mode, enable_raw_mode},
};
@ -26,85 +27,109 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
disable_raw_mode()?;
execute!(terminal.backend_mut(), LeaveAlternateScreen)?;
terminal.show_cursor()?;
if let Err(err) = res {
println!("{:?}", err);
eprintln!("{:?}", err);
}
Ok(())
}
fn run_app(terminal: &mut Terminal<CrosstermBackend<io::Stdout>>, app: &mut App) -> io::Result<()> {
let mut last_key_was_d = false;
let mut last_key_was_g = false;
let mut last_d = false;
let mut last_g = false;
loop {
terminal.draw(|f| ui::render(f, app))?;
app.tick_messages();
if event::poll(Duration::from_millis(500))? {
if event::poll(Duration::from_millis(250))? {
if let Event::Key(key) = event::read()? {
match app.mode {
Mode::Normal => match key.code {
KeyCode::Enter => {
if let Some(selected) = app.get_selected_item() {
crate::ipc::set_clipboard(selected.clone());
app.should_quit = true;
}
}
if key.modifiers.contains(KeyModifiers::CONTROL) {
match key.code {
KeyCode::Char('j') => {
app.next();
last_key_was_d = false;
app.scroll_preview_down();
continue;
}
KeyCode::Char('k') => {
app.previous();
last_key_was_d = false;
app.scroll_preview_up();
continue;
}
KeyCode::Char('d') => {
if last_key_was_d {
app.mode = Mode::ConfirmDelete;
last_key_was_d = false;
} else {
last_key_was_d = true;
_ => {}
}
}
match app.mode {
Mode::Normal => {
match key.code {
KeyCode::Char('d') | KeyCode::Char('g') => {}
_ => {
last_d = false;
last_g = false;
}
last_key_was_g = false;
}
KeyCode::Char('u') => {
app.undo_delete();
last_key_was_d = false;
}
KeyCode::Char('g') => {
if last_key_was_g {
match key.code {
KeyCode::Enter => app.paste_selected(),
KeyCode::Char('j') | KeyCode::Down => app.next(),
KeyCode::Char('k') | KeyCode::Up => app.previous(),
KeyCode::Char('G') => {
if !app.filtered_items.is_empty() {
app.list_state.select(Some(0));
let l = app.filtered_items.len() - 1;
app.list_state.select(Some(l));
app.update_preview();
}
last_key_was_g = false;
} else {
last_key_was_g = true;
}
last_key_was_d = false;
}
KeyCode::Char('G') => {
if !app.filtered_items.is_empty() {
app.list_state.select(Some(app.filtered_items.len() - 1));
KeyCode::Char('g') => {
if last_g {
if !app.filtered_items.is_empty() {
app.list_state.select(Some(0));
app.update_preview();
}
last_g = false;
} else {
last_g = true;
}
}
last_key_was_d = false;
KeyCode::Char('d') => {
if last_d {
app.mode = Mode::ConfirmDelete;
last_d = false;
} else {
last_d = true;
}
}
KeyCode::Char('u') => app.undo_delete(),
KeyCode::Char('e') => app.toggle_encrypt(),
KeyCode::Char('/') => {
app.mode = Mode::Search;
app.input_buffer.clear();
app.update_search();
}
KeyCode::Char(':') => {
app.mode = Mode::Command;
app.input_buffer.clear();
}
KeyCode::Char('q') => app.should_quit = true,
_ => {}
}
KeyCode::Char(':') => {
app.mode = Mode::Command;
app.input_buffer.clear();
last_key_was_d = false;
}
KeyCode::Char('/') => {
app.mode = Mode::Search;
}
Mode::Search => match key.code {
KeyCode::Esc => {
app.mode = Mode::Normal;
app.input_buffer.clear();
app.update_search();
last_key_was_d = false;
}
KeyCode::Char('q') => {
app.should_quit = true;
KeyCode::Enter => app.paste_selected(),
KeyCode::Down => app.next(),
KeyCode::Up => app.previous(),
KeyCode::Char(c) => {
app.input_buffer.push(c);
app.update_search();
}
_ => {
last_key_was_d = false;
KeyCode::Backspace => {
app.input_buffer.pop();
app.update_search();
}
_ => {}
},
Mode::Command => match key.code {
@ -118,42 +143,27 @@ fn run_app(terminal: &mut Terminal<CrosstermBackend<io::Stdout>>, app: &mut App)
app.input_buffer.pop();
}
KeyCode::Enter => {
if app.input_buffer == "q" {
app.should_quit = true;
}
app.mode = Mode::Normal;
let cmd = app.input_buffer.trim().to_string();
app.input_buffer.clear();
app.update_search();
app.mode = Mode::Normal;
match cmd.as_str() {
"q" | "quit" => app.should_quit = true,
"clear" => app.clear_history(),
// :p pour définir/changer le mot de passe
"p" | "password" => {
app.pending_action = None;
app.mode = Mode::PasswordInput;
}
_ => {}
}
}
_ => {}
},
Mode::Search => match key.code {
KeyCode::Esc => {
app.mode = Mode::Normal;
app.input_buffer.clear();
app.update_search();
}
KeyCode::Enter => {
if let Some(selected) = app.get_selected_item() {
crate::ipc::set_clipboard(selected.clone());
app.should_quit = true;
}
}
KeyCode::Char(c) => {
app.input_buffer.push(c);
app.update_search();
}
KeyCode::Backspace => {
app.input_buffer.pop();
app.update_search();
}
_ => {}
},
Mode::ConfirmDelete => match key.code {
KeyCode::Char('y') | KeyCode::Char('Y') | KeyCode::Enter => {
if let Some(selected) = app.get_selected_item() {
crate::ipc::delete_entry(selected.clone());
if let Some(item) = app.get_selected_item() {
ipc::delete_entry(item.content.clone());
app.delete_selected();
}
app.mode = Mode::Normal;
@ -163,9 +173,29 @@ fn run_app(terminal: &mut Terminal<CrosstermBackend<io::Stdout>>, app: &mut App)
}
_ => {}
},
Mode::PasswordInput => match key.code {
KeyCode::Esc => {
app.mode = Mode::Normal;
app.input_buffer.clear();
app.pending_action = None;
}
KeyCode::Char(c) => app.input_buffer.push(c),
KeyCode::Backspace => {
app.input_buffer.pop();
}
KeyCode::Enter => {
let pw = app.input_buffer.clone();
app.input_buffer.clear();
app.mode = Mode::Normal;
app.apply_password(pw);
}
_ => {}
},
}
}
} else {
// Idle : synchronisation avec le daemon
app.sync_with_daemon();
}