Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions toki-tui/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ Current variables:
TOKI_TUI_API_URL="http://localhost:8080"
TOKI_TUI_GIT_DEFAULT_PREFIX="Development"
TOKI_TUI_TASK_FILTER="+work project:Toki"
TOKI_TUI_AUTO_RESIZE_TIMER=true
```

Environment variables override values from `config.toml`.
Expand All @@ -60,6 +61,11 @@ git_default_prefix = "Utveckling"
# Leave empty to show all pending tasks.
# Example: "+work project:Toki"
task_filter = ""

# Whether to automatically resize the timer widget when the timer starts/stops.
# When true (default), the timer grows large when running and shrinks when stopped.
# Set to false to keep the timer at a fixed (normal) size at all times.
auto_resize_timer = true
```

### Example: local dev setup
Expand Down
25 changes: 19 additions & 6 deletions toki-tui/src/app/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ pub struct App {
// Config values used at runtime
pub task_filter: String,
pub git_default_prefix: String,
pub auto_resize_timer: bool,
}

impl App {
Expand Down Expand Up @@ -175,6 +176,7 @@ impl App {
milltime_reauth: None,
task_filter: cfg.task_filter.clone(),
git_default_prefix: cfg.git_default_prefix.clone(),
auto_resize_timer: cfg.auto_resize_timer,
}
}

Expand Down Expand Up @@ -273,24 +275,35 @@ impl App {
}

/// Start a new timer
pub fn start_timer(&mut self) {
pub fn start_timer(&mut self, auto_resize: bool) {
self.timer_state = TimerState::Running;
self.absolute_start = Some(OffsetDateTime::now_utc());
self.local_start = Some(Instant::now());
self.timer_size = TimerSize::Large;
if auto_resize {
self.timer_size = TimerSize::Large;
}
// Shift focus: running timer row is inserted at index 0, pushing DB entries up by 1
if let Some(idx) = self.focused_this_week_index {
self.focused_this_week_index = Some(idx + 1);
}
}

/// Stop the timer (without saving)
#[allow(dead_code)]
pub fn stop_timer(&mut self) {
/// Stop the timer (without saving).
pub fn stop_timer(&mut self, auto_resize: bool) {
self.timer_state = TimerState::Stopped;
self.timer_size = TimerSize::Normal;
if auto_resize {
self.timer_size = TimerSize::Normal;
}
self.absolute_start = None;
self.local_start = None;
// Shift focus back: running timer row at index 0 is removed, pushing DB entries down by 1
if let Some(idx) = self.focused_this_week_index {
self.focused_this_week_index = if idx == 0 {
None
} else {
Some(idx.saturating_sub(1))
};
}
}

pub fn set_status(&mut self, message: String) {
Expand Down
10 changes: 10 additions & 0 deletions toki-tui/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ pub struct TokiConfig {
/// when no conventional commit prefix or ticket number is found.
#[serde(default = "default_git_prefix")]
pub git_default_prefix: String,
/// Whether to automatically resize the timer to Large when started
/// and back to Normal when stopped. Default: true.
#[serde(default = "default_auto_resize_timer")]
pub auto_resize_timer: bool,
}

fn default_api_url() -> String {
Expand All @@ -25,12 +29,17 @@ fn default_git_prefix() -> String {
"Utveckling".to_string()
}

fn default_auto_resize_timer() -> bool {
true
}

impl Default for TokiConfig {
fn default() -> Self {
Self {
api_url: default_api_url(),
task_filter: String::new(),
git_default_prefix: default_git_prefix(),
auto_resize_timer: default_auto_resize_timer(),
}
}
}
Expand Down Expand Up @@ -68,6 +77,7 @@ impl TokiConfig {
.set_default("api_url", default_api_url())?
.set_default("task_filter", "")?
.set_default("git_default_prefix", default_git_prefix())?
.set_default("auto_resize_timer", default_auto_resize_timer())?
.add_source(config::File::from(path.clone()).required(false))
.add_source(
config::Environment::with_prefix("TOKI_TUI")
Expand Down
28 changes: 12 additions & 16 deletions toki-tui/src/runtime/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@ pub(crate) fn restore_active_timer(app: &mut App, timer: crate::types::ActiveTim
app.absolute_start = Some(timer.start_time);
app.local_start = Some(Instant::now() - Duration::from_secs(elapsed_secs));
app.timer_state = app::TimerState::Running;
app.timer_size = app::TimerSize::Large;
if app.auto_resize_timer {
app.timer_size = app::TimerSize::Large;
}
if let (Some(id), Some(name)) = (timer.project_id, timer.project_name) {
app.selected_project = Some(crate::types::Project { id, name });
}
Expand Down Expand Up @@ -149,7 +151,8 @@ pub(super) async fn handle_start_timer(app: &mut App, client: &mut ApiClient) ->
}
return Ok(());
}
app.start_timer();
let auto_resize = app.auto_resize_timer;
app.start_timer(auto_resize);
app.clear_status();
}
app::TimerState::Running => {
Expand Down Expand Up @@ -388,7 +391,8 @@ async fn resume_entry(entry: types::TimeEntry, app: &mut App, client: &mut ApiCl
Ok(()) => {
// Only mutate local state after confirmed server success
app.copy_entry_fields(&entry);
app.start_timer(); // sets TimerState::Running + TimerSize::Large + local_start
let auto_resize = app.auto_resize_timer;
app.start_timer(auto_resize); // sets TimerState::Running + TimerSize::Large + local_start
app.set_status(format!(
"Resumed: {}: {}",
entry.project_name, entry.activity_name
Expand Down Expand Up @@ -459,7 +463,8 @@ pub(super) async fn handle_save_timer_with_action(
{
app.set_status(format!("Saved but could not restart timer: {}", e));
} else {
app.start_timer();
let auto_resize = app.auto_resize_timer;
app.start_timer(auto_resize);
app.set_status(format!(
"Saved {} to {} / {}",
duration_str, project_display, activity_display
Expand All @@ -475,25 +480,16 @@ pub(super) async fn handle_save_timer_with_action(
if let Err(e) = client.start_timer(None, None, None, None, None).await {
app.set_status(format!("Saved but could not restart timer: {}", e));
} else {
app.start_timer();
let auto_resize = app.auto_resize_timer;
app.start_timer(auto_resize);
app.set_status(format!(
"Saved {}. Timer started. Press P to select project.",
duration_str
));
}
}
app::SaveAction::SaveAndStop => {
app.timer_state = app::TimerState::Stopped;
app.timer_size = app::TimerSize::Normal;
app.absolute_start = None;
app.local_start = None;
if let Some(idx) = app.focused_this_week_index {
app.focused_this_week_index = if idx == 0 {
None
} else {
Some(idx.saturating_sub(1))
};
}
app.stop_timer(app.auto_resize_timer);
app.set_status(format!(
"Saved {} to {} / {}",
duration_str, project_display, activity_display
Expand Down
Loading