use anyhow::Result;
use crossterm::event::{KeyCode, KeyEvent};
use crate::app::{App, InputMode};
pub fn handle_passphrase_prompt_input(app: &mut App, key: KeyEvent) -> Result<bool> {
match key.code {
KeyCode::Enter => {
let passphrase = if let InputMode::PassphrasePrompt { passphrase, .. } = &app.input_mode {
passphrase.clone()
} else {
return Ok(false);
};
match app.secrets.unlock(&passphrase) {
Ok(()) => {
app.input_mode = InputMode::Normal;
app.check_version()?;
Ok(false)
}
Err(_) => {
if let InputMode::PassphrasePrompt {
passphrase,
cursor_pos,
error_message,
confirm_delete,
} = &mut app.input_mode
{
*error_message = Some("Wrong passphrase".to_string());
passphrase.clear();
*cursor_pos = 0;
*confirm_delete = false;
}
Ok(false)
}
}
}
KeyCode::Esc => Ok(true), KeyCode::Delete => {
if let InputMode::PassphrasePrompt {
confirm_delete,
error_message,
..
} = &mut app.input_mode
{
if *confirm_delete {
app.secrets.delete_secrets_file()?;
app.input_mode = InputMode::Normal;
app.check_version()?;
} else {
*confirm_delete = true;
*error_message = Some("Press Delete again to confirm removal".to_string());
}
}
Ok(false)
}
KeyCode::Char(c) => {
if let InputMode::PassphrasePrompt {
passphrase,
cursor_pos,
error_message,
confirm_delete,
} = &mut app.input_mode
{
*error_message = None;
*confirm_delete = false;
let byte_pos: usize = passphrase.chars().take(*cursor_pos).map(|ch| ch.len_utf8()).sum();
passphrase.insert(byte_pos, c);
*cursor_pos += 1;
}
Ok(false)
}
KeyCode::Backspace => {
if let InputMode::PassphrasePrompt {
passphrase,
cursor_pos,
confirm_delete,
..
} = &mut app.input_mode
{
*confirm_delete = false;
if *cursor_pos > 0 {
let char_idx = *cursor_pos - 1;
let byte_pos: usize = passphrase.chars().take(char_idx).map(|ch| ch.len_utf8()).sum();
let removed_len = passphrase.chars().nth(char_idx).map(|ch| ch.len_utf8()).unwrap_or(0);
passphrase.replace_range(byte_pos..byte_pos + removed_len, "");
*cursor_pos -= 1;
}
}
Ok(false)
}
KeyCode::Left => {
if let InputMode::PassphrasePrompt { cursor_pos, .. } = &mut app.input_mode {
if *cursor_pos > 0 {
*cursor_pos -= 1;
}
}
Ok(false)
}
KeyCode::Right => {
if let InputMode::PassphrasePrompt { passphrase, cursor_pos, .. } = &mut app.input_mode {
if *cursor_pos < passphrase.chars().count() {
*cursor_pos += 1;
}
}
Ok(false)
}
_ => Ok(false),
}
}
pub fn handle_passphrase_change_input(app: &mut App, key: KeyEvent) -> Result<bool> {
match key.code {
KeyCode::Tab => {
app.next_field();
Ok(false)
}
KeyCode::Up => {
app.previous_field();
Ok(false)
}
KeyCode::Down => {
app.next_field();
Ok(false)
}
KeyCode::Enter => {
let (old_pass, new_pass, confirm_pass, is_initial) =
if let InputMode::PassphraseChange {
old_passphrase,
new_passphrase,
confirm_passphrase,
is_initial_setup,
..
} = &app.input_mode
{
(
old_passphrase.clone(),
new_passphrase.clone(),
confirm_passphrase.clone(),
*is_initial_setup,
)
} else {
return Ok(false);
};
if new_pass.is_empty() {
if let InputMode::PassphraseChange { error_message, .. } = &mut app.input_mode {
*error_message = Some("Passphrase cannot be empty".to_string());
}
return Ok(false);
}
if new_pass != confirm_pass {
if let InputMode::PassphraseChange { error_message, .. } = &mut app.input_mode {
*error_message = Some("Passphrases do not match".to_string());
}
return Ok(false);
}
let result = if is_initial {
app.secrets.set_passphrase(&new_pass)
} else {
app.secrets.change_passphrase(&old_pass, &new_pass)
};
match result {
Ok(()) => {
if let Some(token) = app.pending_api_token.take() {
app.secrets.set("jira_api_token", &token)?;
}
app.input_mode = InputMode::Normal;
Ok(false)
}
Err(e) => {
if let InputMode::PassphraseChange { error_message, .. } = &mut app.input_mode {
*error_message = Some(e.to_string());
}
Ok(false)
}
}
}
KeyCode::Esc => {
app.pending_api_token = None;
app.input_mode = InputMode::Normal;
Ok(false)
}
KeyCode::Char(c) => {
passphrase_change_insert_char(app, c);
Ok(false)
}
KeyCode::Backspace => {
passphrase_change_delete_char(app);
Ok(false)
}
KeyCode::Left => {
if let InputMode::PassphraseChange { cursor_pos, .. } = &mut app.input_mode {
if *cursor_pos > 0 {
*cursor_pos -= 1;
}
}
Ok(false)
}
KeyCode::Right => {
if let InputMode::PassphraseChange {
old_passphrase,
new_passphrase,
confirm_passphrase,
current_field,
cursor_pos,
is_initial_setup,
..
} = &mut app.input_mode
{
let text = get_passphrase_change_field(
old_passphrase, new_passphrase, confirm_passphrase,
*current_field, *is_initial_setup,
);
if *cursor_pos < text.chars().count() {
*cursor_pos += 1;
}
}
Ok(false)
}
_ => Ok(false),
}
}
fn get_passphrase_change_field<'a>(
old: &'a str, new: &'a str, confirm: &'a str,
current_field: usize, is_initial_setup: bool,
) -> &'a str {
if is_initial_setup {
match current_field {
0 => new,
1 => confirm,
_ => "",
}
} else {
match current_field {
0 => old,
1 => new,
2 => confirm,
_ => "",
}
}
}
fn passphrase_change_insert_char(app: &mut App, c: char) {
if let InputMode::PassphraseChange {
old_passphrase,
new_passphrase,
confirm_passphrase,
current_field,
cursor_pos,
is_initial_setup,
error_message,
} = &mut app.input_mode
{
*error_message = None;
let text = if *is_initial_setup {
match *current_field {
0 => new_passphrase,
1 => confirm_passphrase,
_ => return,
}
} else {
match *current_field {
0 => old_passphrase,
1 => new_passphrase,
2 => confirm_passphrase,
_ => return,
}
};
let byte_pos: usize = text.chars().take(*cursor_pos).map(|ch| ch.len_utf8()).sum();
text.insert(byte_pos, c);
*cursor_pos += 1;
}
}
fn passphrase_change_delete_char(app: &mut App) {
if let InputMode::PassphraseChange {
old_passphrase,
new_passphrase,
confirm_passphrase,
current_field,
cursor_pos,
is_initial_setup,
..
} = &mut app.input_mode
{
if *cursor_pos == 0 {
return;
}
let text = if *is_initial_setup {
match *current_field {
0 => new_passphrase,
1 => confirm_passphrase,
_ => return,
}
} else {
match *current_field {
0 => old_passphrase,
1 => new_passphrase,
2 => confirm_passphrase,
_ => return,
}
};
let char_idx = *cursor_pos - 1;
let byte_pos: usize = text.chars().take(char_idx).map(|ch| ch.len_utf8()).sum();
let removed_len = text.chars().nth(char_idx).map(|ch| ch.len_utf8()).unwrap_or(0);
text.replace_range(byte_pos..byte_pos + removed_len, "");
*cursor_pos -= 1;
}
}