use crate::app::InputMode;
use crate::integrations::IntegrationKind;
pub fn get_active_text_and_cursor(mode: &mut InputMode) -> Option<(&mut String, &mut usize)> {
match mode {
InputMode::Creating {
description, start_time, end_time, issue_key,
current_field, cursor_pos, ..
} => {
let text = match *current_field {
0 => description,
1 => start_time,
2 => end_time,
3 => issue_key,
_ => return None,
};
Some((text, cursor_pos))
}
InputMode::Editing {
description, start_time, end_time, issue_key,
current_field, cursor_pos, ..
} => {
let text = match *current_field {
0 => description,
1 => start_time,
2 => end_time,
3 => issue_key,
_ => return None,
};
Some((text, cursor_pos))
}
InputMode::EditingDay {
start_time, end_time, current_field, cursor_pos, ..
} => {
let text = match *current_field {
0 => start_time,
1 => end_time,
_ => return None,
};
Some((text, cursor_pos))
}
InputMode::Triggers {
urls, bodies, current_field, cursor_pos, ..
} => {
let event = *current_field / 3;
let text = match *current_field % 3 {
1 => &mut urls[event],
2 => &mut bodies[event],
_ => return None, };
Some((text, cursor_pos))
}
InputMode::Settings {
integration, open_command, open_worklog_command,
jira_url_setting, jira_email, jira_api_token, date_format,
current_field, cursor_pos, ..
} => {
let text = match integration {
IntegrationKind::CustomCommands => match *current_field {
1 => open_command,
2 => open_worklog_command,
3 => date_format,
_ => return None,
},
IntegrationKind::Jira => match *current_field {
1 => jira_url_setting,
2 => jira_email,
3 => jira_api_token,
4 => date_format,
_ => return None,
},
};
Some((text, cursor_pos))
}
InputMode::PassphrasePrompt {
passphrase, cursor_pos, ..
} => {
Some((passphrase, cursor_pos))
}
InputMode::PassphraseChange {
old_passphrase, new_passphrase, confirm_passphrase,
current_field, cursor_pos, is_initial_setup, ..
} => {
let text = if *is_initial_setup {
match *current_field {
0 => new_passphrase,
1 => confirm_passphrase,
_ => return None,
}
} else {
match *current_field {
0 => old_passphrase,
1 => new_passphrase,
2 => confirm_passphrase,
_ => return None,
}
};
Some((text, cursor_pos))
}
_ => None,
}
}
pub fn cursor_left(mode: &mut InputMode) {
if let Some((_, cursor_pos)) = get_active_text_and_cursor(mode) {
if *cursor_pos > 0 {
*cursor_pos -= 1;
}
}
}
pub fn cursor_right(mode: &mut InputMode) {
if let Some((text, cursor_pos)) = get_active_text_and_cursor(mode) {
if *cursor_pos < text.chars().count() {
*cursor_pos += 1;
}
}
}
pub fn insert_char(mode: &mut InputMode, c: char) {
if let Some((text, cursor_pos)) = get_active_text_and_cursor(mode) {
let byte_pos: usize = text.chars().take(*cursor_pos).map(|ch| ch.len_utf8()).sum();
text.insert(byte_pos, c);
*cursor_pos += 1;
}
}
pub fn delete_char(mode: &mut InputMode) {
if let Some((text, cursor_pos)) = get_active_text_and_cursor(mode) {
if *cursor_pos > 0 {
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;
}
}
}
pub fn reset_cursor_to_end(mode: &mut InputMode) {
if let Some((text, cursor_pos)) = get_active_text_and_cursor(mode) {
*cursor_pos = text.chars().count();
}
}
pub fn insert_str(mode: &mut InputMode, s: &str) {
if let Some((text, cursor_pos)) = get_active_text_and_cursor(mode) {
let byte_pos: usize = text.chars().take(*cursor_pos).map(|ch| ch.len_utf8()).sum();
text.insert_str(byte_pos, s);
*cursor_pos += s.chars().count();
}
}
pub fn render_with_cursor(text: &str, cursor_pos: usize, is_active: bool) -> String {
if !is_active {
return text.to_string();
}
let millis = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap_or_default()
.as_millis();
let cursor_visible = (millis / 500) % 2 == 0;
let before: String = text.chars().take(cursor_pos).collect();
let after: String = text.chars().skip(cursor_pos).collect();
if cursor_visible {
format!("{}|{}", before, after)
} else {
format!("{} {}", before, after)
}
}