Fix task edit border and rename some symbols
This commit is contained in:
parent
fc237b9f29
commit
da10719250
16
src/app.rs
16
src/app.rs
@ -57,25 +57,25 @@ impl Default for Project {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum NewTaskFocus {
|
pub enum TaskEditFocus {
|
||||||
Title,
|
Title,
|
||||||
Description,
|
Description,
|
||||||
CreateBtn,
|
CreateBtn,
|
||||||
CancelBtn
|
CancelBtn
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NewTask<'a> {
|
pub struct TaskState<'a> {
|
||||||
pub title: TextArea<'a>,
|
pub title: TextArea<'a>,
|
||||||
pub description: TextArea<'a>,
|
pub description: TextArea<'a>,
|
||||||
pub focus: NewTaskFocus
|
pub focus: TaskEditFocus
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for NewTask<'_> {
|
impl Default for TaskState<'_> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
NewTask {
|
TaskState {
|
||||||
title: TextArea::default(),
|
title: TextArea::default(),
|
||||||
description: TextArea::default(),
|
description: TextArea::default(),
|
||||||
focus: NewTaskFocus::Title
|
focus: TaskEditFocus::Title
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,14 +84,14 @@ pub struct AppState<'a> {
|
|||||||
pub project: Project,
|
pub project: Project,
|
||||||
pub quit: bool,
|
pub quit: bool,
|
||||||
pub columns: Vec<Column>,
|
pub columns: Vec<Column>,
|
||||||
pub new_task_state: Option<NewTask<'a>>,
|
pub task_edit_state: Option<TaskState<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AppState<'_> {
|
impl AppState<'_> {
|
||||||
pub fn new(project: Project) -> Self {
|
pub fn new(project: Project) -> Self {
|
||||||
AppState {
|
AppState {
|
||||||
quit: false,
|
quit: false,
|
||||||
new_task_state: None,
|
task_edit_state: None,
|
||||||
project,
|
project,
|
||||||
columns: vec![],
|
columns: vec![],
|
||||||
}
|
}
|
||||||
|
41
src/input.rs
41
src/input.rs
@ -1,7 +1,7 @@
|
|||||||
#![allow(unused_imports)]
|
#![allow(unused_imports)]
|
||||||
use crossterm::event;
|
use crossterm::event;
|
||||||
use crossterm::event::{Event, KeyCode};
|
use crossterm::event::{Event, KeyCode};
|
||||||
use crate::app::{NewTask, AppState, NewTaskFocus};
|
use crate::app::{TaskState, AppState, TaskEditFocus};
|
||||||
use std::io::{stdout, Write};
|
use std::io::{stdout, Write};
|
||||||
use tui_textarea::TextArea;
|
use tui_textarea::TextArea;
|
||||||
|
|
||||||
@ -9,45 +9,45 @@ pub fn handle_input(state: &mut AppState) -> Result<(), std::io::Error> {
|
|||||||
let project = &mut state.project;
|
let project = &mut state.project;
|
||||||
let column = project.get_selected_column_mut();
|
let column = project.get_selected_column_mut();
|
||||||
if let Event::Key(key) = event::read()? {
|
if let Event::Key(key) = event::read()? {
|
||||||
match &mut state.new_task_state {
|
match &mut state.task_edit_state {
|
||||||
Some(task) => {
|
Some(task) => {
|
||||||
// TODO: Extract this code to a separate function to avoid nesting
|
// TODO: Extract this code to a separate function to avoid nesting
|
||||||
match task.focus {
|
match task.focus {
|
||||||
// TODO: Handle wrapping around the enum rather than doing it manually
|
// TODO: Handle wrapping around the enum rather than doing it manually
|
||||||
NewTaskFocus::Title => {
|
TaskEditFocus::Title => {
|
||||||
match key.code {
|
match key.code {
|
||||||
KeyCode::Tab => task.focus = NewTaskFocus::Description,
|
KeyCode::Tab => task.focus = TaskEditFocus::Description,
|
||||||
KeyCode::BackTab => task.focus = NewTaskFocus::CancelBtn,
|
KeyCode::BackTab => task.focus = TaskEditFocus::CancelBtn,
|
||||||
KeyCode::Enter => (),
|
KeyCode::Enter => (),
|
||||||
_ => { task.title.input(key); }
|
_ => { task.title.input(key); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NewTaskFocus::Description => {
|
TaskEditFocus::Description => {
|
||||||
match key.code {
|
match key.code {
|
||||||
KeyCode::Tab => task.focus = NewTaskFocus::CreateBtn,
|
KeyCode::Tab => task.focus = TaskEditFocus::CreateBtn,
|
||||||
KeyCode::BackTab => task.focus = NewTaskFocus::Title,
|
KeyCode::BackTab => task.focus = TaskEditFocus::Title,
|
||||||
_ => { task.description.input(key); }
|
_ => { task.description.input(key); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NewTaskFocus::CreateBtn => {
|
TaskEditFocus::CreateBtn => {
|
||||||
match key.code {
|
match key.code {
|
||||||
KeyCode::Tab => task.focus = NewTaskFocus::CancelBtn,
|
KeyCode::Tab => task.focus = TaskEditFocus::CancelBtn,
|
||||||
KeyCode::BackTab => task.focus = NewTaskFocus::Description,
|
KeyCode::BackTab => task.focus = TaskEditFocus::Description,
|
||||||
KeyCode::Enter => {
|
KeyCode::Enter => {
|
||||||
let title = task.title.clone().into_lines().join("\n");
|
let title = task.title.clone().into_lines().join("\n");
|
||||||
let description = task.description.clone().into_lines().clone().join("\n");
|
let description = task.description.clone().into_lines().clone().join("\n");
|
||||||
column.add_task(title, description);
|
column.add_task(title, description);
|
||||||
state.new_task_state = None
|
state.task_edit_state = None
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NewTaskFocus::CancelBtn => {
|
TaskEditFocus::CancelBtn => {
|
||||||
match key.code {
|
match key.code {
|
||||||
KeyCode::Tab => task.focus = NewTaskFocus::Title,
|
KeyCode::Tab => task.focus = TaskEditFocus::Title,
|
||||||
KeyCode::BackTab => task.focus = NewTaskFocus::CreateBtn,
|
KeyCode::BackTab => task.focus = TaskEditFocus::CreateBtn,
|
||||||
KeyCode::Enter => {
|
KeyCode::Enter => {
|
||||||
state.new_task_state = None
|
state.task_edit_state = None
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
@ -73,10 +73,11 @@ pub fn handle_input(state: &mut AppState) -> Result<(), std::io::Error> {
|
|||||||
KeyCode::Char('J') => project.move_task_down(),
|
KeyCode::Char('J') => project.move_task_down(),
|
||||||
KeyCode::Char('-') |
|
KeyCode::Char('-') |
|
||||||
KeyCode::Char('K') => project.move_task_up(),
|
KeyCode::Char('K') => project.move_task_up(),
|
||||||
KeyCode::Char('p') => {
|
KeyCode::Char('n') => state.task_edit_state = Some(TaskState::default()),
|
||||||
match state.new_task_state {
|
KeyCode::Char('e') => {
|
||||||
None => state.new_task_state = Some(NewTask::default()),
|
match state.task_edit_state {
|
||||||
Some(_) => state.new_task_state = None,
|
None => state.task_edit_state = Some(TaskState::default()),
|
||||||
|
Some(_) => state.task_edit_state = None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeyCode::Char('D') => column.remove_task(),
|
KeyCode::Char('D') => column.remove_task(),
|
||||||
|
175
src/ui.rs
175
src/ui.rs
@ -89,101 +89,98 @@ fn centered_rect_for_popup(percent_x: u16, percent_y: u16, r: Rect) -> Rect {
|
|||||||
.split(popup_layout[1])[1]
|
.split(popup_layout[1])[1]
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw_new_task_popup<B: Backend>(f: &mut Frame<B>, state: &mut AppState) {
|
pub fn draw_task_popup<B: Backend>(f: &mut Frame<B>, state: &mut AppState, popup_title: &str) {
|
||||||
let area = centered_rect_for_popup(45, 60, f.size());
|
let area = centered_rect_for_popup(45, 60, f.size());
|
||||||
|
let block = Block::default()
|
||||||
|
.title(popup_title)
|
||||||
|
.title_alignment(Alignment::Center)
|
||||||
|
.borders(Borders::ALL);
|
||||||
f.render_widget(Clear, area);
|
f.render_widget(Clear, area);
|
||||||
match &mut state.new_task_state {
|
f.render_widget(Paragraph::new("").block(block.clone()), area);
|
||||||
None => {}
|
if let Some(task) = &mut state.task_edit_state {
|
||||||
Some(task) => {
|
let block_inner = block.inner(area);
|
||||||
let block = Block::default()
|
let layout = Layout::default()
|
||||||
.title("Add Task")
|
.direction(Direction::Vertical)
|
||||||
.title_alignment(Alignment::Center)
|
.constraints(
|
||||||
.borders(Borders::ALL);
|
[
|
||||||
let block_inner = block.inner(area);
|
Constraint::Length(3),
|
||||||
// let main = Paragraph::new(task.description.clone()).block(block);
|
Constraint::Max(100),
|
||||||
let layout = Layout::default()
|
Constraint::Length(1),
|
||||||
.direction(Direction::Vertical)
|
Constraint::Length(2),
|
||||||
.constraints(
|
]
|
||||||
[
|
.as_ref(),
|
||||||
Constraint::Length(3),
|
)
|
||||||
Constraint::Max(100),
|
.split(block_inner);
|
||||||
Constraint::Length(3),
|
|
||||||
Constraint::Length(2),
|
|
||||||
]
|
|
||||||
.as_ref(),
|
|
||||||
)
|
|
||||||
.split(block_inner);
|
|
||||||
|
|
||||||
let buttons = Layout::default()
|
let buttons = Layout::default()
|
||||||
.direction(Direction::Horizontal)
|
.direction(Direction::Horizontal)
|
||||||
.constraints(
|
.constraints(
|
||||||
[
|
[
|
||||||
Constraint::Percentage(80),
|
Constraint::Percentage(80),
|
||||||
Constraint::Min(10),
|
Constraint::Min(10),
|
||||||
Constraint::Min(10)
|
Constraint::Min(10)
|
||||||
]
|
]
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
)
|
)
|
||||||
.split(layout[2]);
|
.split(layout[2]);
|
||||||
|
|
||||||
let create_style;
|
let create_style;
|
||||||
let create_txt;
|
let create_txt;
|
||||||
let cancel_style;
|
let cancel_style;
|
||||||
let cancel_txt;
|
let cancel_txt;
|
||||||
match task.focus {
|
match task.focus {
|
||||||
NewTaskFocus::CreateBtn => {
|
TaskEditFocus::CreateBtn => {
|
||||||
create_style = Style::default().fg(Color::Yellow);
|
create_style = Style::default().fg(Color::Yellow);
|
||||||
cancel_style = Style::default();
|
cancel_style = Style::default();
|
||||||
create_txt = "[Create]";
|
create_txt = "[Confirm]";
|
||||||
cancel_txt = " Cancel ";
|
cancel_txt = " Cancel ";
|
||||||
}
|
|
||||||
NewTaskFocus::CancelBtn => {
|
|
||||||
create_style = Style::default();
|
|
||||||
cancel_style = Style::default().fg(Color::Yellow);
|
|
||||||
create_txt = " Create ";
|
|
||||||
cancel_txt = "[Cancel]";
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
create_style = Style::default();
|
|
||||||
cancel_style = Style::default();
|
|
||||||
create_txt = " Create ";
|
|
||||||
cancel_txt = " Cancel ";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
let create_btn = Paragraph::new(create_txt).style(create_style);
|
TaskEditFocus::CancelBtn => {
|
||||||
let cancel_btn = Paragraph::new(cancel_txt).style(cancel_style);
|
create_style = Style::default();
|
||||||
f.render_widget(create_btn, buttons[1]);
|
cancel_style = Style::default().fg(Color::Yellow);
|
||||||
f.render_widget(cancel_btn, buttons[2]);
|
create_txt = " Confirm ";
|
||||||
|
cancel_txt = "[Cancel]";
|
||||||
let b1 = Block::default().title("Title").borders(Borders::ALL);
|
|
||||||
let b2 = Block::default().title("Description").borders(Borders::ALL);
|
|
||||||
let b3 = Block::default().title("Keys").borders(Borders::TOP);
|
|
||||||
task.title.set_cursor_line_style(Style::default());
|
|
||||||
task.description.set_cursor_line_style(Style::default());
|
|
||||||
|
|
||||||
task.title.set_block(b1);
|
|
||||||
if let NewTaskFocus::Title = task.focus {
|
|
||||||
task.title.set_style(Style::default().fg(Color::Yellow));
|
|
||||||
task.title.set_cursor_style(Style::default().add_modifier(Modifier::REVERSED));
|
|
||||||
} else {
|
|
||||||
task.title.set_style(Style::default());
|
|
||||||
task.title.set_cursor_style(Style::default());
|
|
||||||
}
|
}
|
||||||
f.render_widget(task.title.widget(), layout[0]);
|
_ => {
|
||||||
|
create_style = Style::default();
|
||||||
task.description.set_block(b2);
|
cancel_style = Style::default();
|
||||||
if let NewTaskFocus::Description = task.focus {
|
create_txt = " Confirm ";
|
||||||
task.description.set_style(Style::default().fg(Color::Yellow));
|
cancel_txt = " Cancel ";
|
||||||
task.description.set_cursor_style(Style::default().add_modifier(Modifier::REVERSED));
|
|
||||||
} else {
|
|
||||||
task.description.set_style(Style::default());
|
|
||||||
task.description.set_cursor_style(Style::default());
|
|
||||||
}
|
}
|
||||||
f.render_widget(task.description.widget(), layout[1]);
|
|
||||||
|
|
||||||
let footer = Paragraph::new("Tab/Backtab : Cycle").block(b3);
|
|
||||||
f.render_widget(footer, layout[3]);
|
|
||||||
}
|
}
|
||||||
|
let create_btn = Paragraph::new(create_txt).style(create_style);
|
||||||
|
let cancel_btn = Paragraph::new(cancel_txt).style(cancel_style);
|
||||||
|
f.render_widget(create_btn, buttons[1]);
|
||||||
|
f.render_widget(cancel_btn, buttons[2]);
|
||||||
|
|
||||||
|
let b1 = Block::default().title("Title").borders(Borders::ALL);
|
||||||
|
let b2 = Block::default().title("Description").borders(Borders::ALL);
|
||||||
|
let b3 = Block::default().title("Keys").borders(Borders::TOP);
|
||||||
|
task.title.set_cursor_line_style(Style::default());
|
||||||
|
task.description.set_cursor_line_style(Style::default());
|
||||||
|
|
||||||
|
task.title.set_block(b1);
|
||||||
|
if let TaskEditFocus::Title = task.focus {
|
||||||
|
task.title.set_style(Style::default().fg(Color::Yellow));
|
||||||
|
task.title.set_cursor_style(Style::default().add_modifier(Modifier::REVERSED));
|
||||||
|
} else {
|
||||||
|
task.title.set_style(Style::default());
|
||||||
|
task.title.set_cursor_style(Style::default());
|
||||||
|
}
|
||||||
|
f.render_widget(task.title.widget(), layout[0]);
|
||||||
|
|
||||||
|
task.description.set_block(b2);
|
||||||
|
if let TaskEditFocus::Description = task.focus {
|
||||||
|
task.description.set_style(Style::default().fg(Color::Yellow));
|
||||||
|
task.description.set_cursor_style(Style::default().add_modifier(Modifier::REVERSED));
|
||||||
|
} else {
|
||||||
|
task.description.set_style(Style::default());
|
||||||
|
task.description.set_cursor_style(Style::default());
|
||||||
|
}
|
||||||
|
f.render_widget(task.description.widget(), layout[1]);
|
||||||
|
|
||||||
|
let footer = Paragraph::new("Tab/Backtab : Cycle").block(b3);
|
||||||
|
f.render_widget(footer, layout[3]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +211,7 @@ pub fn draw<B: Backend>(f: &mut Frame<B>, state: &mut AppState) {
|
|||||||
let footer = Paragraph::new(foot_txt).block(block);
|
let footer = Paragraph::new(foot_txt).block(block);
|
||||||
f.render_widget(footer, main_layout[3]);
|
f.render_widget(footer, main_layout[3]);
|
||||||
|
|
||||||
if state.new_task_state.is_some() {
|
if state.task_edit_state.is_some() {
|
||||||
draw_new_task_popup(f, state);
|
draw_task_popup(f, state, "Create Task");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user