Skip to content
Draft
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
12 changes: 12 additions & 0 deletions data/io.github.focustimerhq.FocusTimer.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,18 @@
<summary>Pause Pomodoro when screen is locked</summary>
</key>

<!-- Tasks -->
<key name="current-task" type="s">
<default>''</default>
<summary>Current task</summary>
<description>Name of the task time is currently tracked against. An empty string means no task.</description>
</key>
<key name="task-history" type="as">
<default>[]</default>
<summary>Recently used tasks</summary>
<description>Recently used task names, most recent first.</description>
</key>

<!-- Notifications -->
<key name="announce-about-to-end" type="b">
<default>true</default>
Expand Down
2 changes: 2 additions & 0 deletions po/POTFILES
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ src/ui/main/stats/widgets/stats-card.ui
src/ui/main/stats/widgets/stats-card.vala
src/ui/main/stats/widgets/stats-date-popover.ui
src/ui/main/stats/widgets/stats-date-popover.vala
src/ui/main/stats/widgets/task-breakdown.vala
src/ui/main/stats/widgets/week-chooser.ui
src/ui/main/stats/widgets/week-chooser.vala
src/ui/main/timer/compact-timer-view.ui
Expand All @@ -139,6 +140,7 @@ src/ui/main/timer/menus.ui
src/ui/main/timer/timer-view.ui
src/ui/main/timer/timer-view.vala
src/ui/main/timer/widgets/session-progress-bar.vala
src/ui/main/timer/widgets/task-button.vala
src/ui/main/timer/widgets/timer-control-buttons.ui
src/ui/main/timer/widgets/timer-control-buttons.vala
src/ui/main/timer/widgets/timer-label.ui
Expand Down
2 changes: 1 addition & 1 deletion src/core/database.vala
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ using GLib;

namespace Ft.Database
{
private const uint VERSION = 3;
private const uint VERSION = 4;
private const string MIGRATIONS_URI = "resource:///io/github/focustimerhq/FocusTimer/migrations";
private const string DATE_FORMAT = "%Y-%m-%d";

Expand Down
75 changes: 75 additions & 0 deletions src/core/session-manager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ namespace Ft
*/
private const int64 OVERDUE_TIMEOUT = Ft.Interval.HOUR;

/**
* Number of recently used task names kept for suggestions.
*/
private const uint TASK_HISTORY_LIMIT = 10;

private static Ft.SessionManager? instance = null;

public Ft.Timer timer {
Expand Down Expand Up @@ -158,13 +163,46 @@ namespace Ft
}
}

/**
* Name of the task time is tracked against. An empty string means no task.
*
* The task is stamped onto pomodoro time-blocks as they start. Changing it
* mid-pomodoro re-assigns the whole current time-block to the new task.
*/
[CCode (notify = false)]
public string current_task {
get {
return this._current_task;
}
set {
var task = value != null ? value.strip () : "";

if (this._current_task == task) {
return;
}

this._current_task = task;

if (this._current_time_block != null &&
this._current_time_block.state == Ft.State.POMODORO)
{
this._current_time_block.set_task (task);
this.save.begin ();
}

this.store_current_task ();
this.notify_property ("current-task");
}
}

private Ft.Timer _timer;
private Ft.Scheduler _scheduler;
private Ft.Session? _current_session = null;
private Ft.TimeBlock? _current_time_block = null;
private Ft.Gap? _current_gap = null;
private Ft.State _current_state = Ft.State.STOPPED;
private bool _has_uniform_breaks = false;
private string _current_task = "";
private Ft.Session? next_session = null;
private Ft.TimeBlock? next_time_block = null;
private Ft.IdleMonitor? idle_monitor = null;
Expand Down Expand Up @@ -217,13 +255,42 @@ namespace Ft
this.timezone_monitor = new Ft.TimeZoneMonitor ();
this.timezone_history = new Ft.TimezoneHistory ();
this.save_callbacks = {};
this._current_task = this.settings.get_string ("current-task").strip ();

this.settings.changed.connect (this.on_settings_changed);
this.timezone_monitor.changed.connect (this.on_timezone_changed);

this.update_session_template ();
}

/**
* Persist the current task and keep a list of recently used tasks
* for suggestions.
*/
private void store_current_task ()
{
this.settings.set_string ("current-task", this._current_task);

if (this._current_task == "") {
return;
}

string[] task_history = { this._current_task };

foreach (unowned var task in this.settings.get_strv ("task-history"))
{
if (task != this._current_task && task != "") {
task_history += task;
}

if (task_history.length >= TASK_HISTORY_LIMIT) {
break;
}
}

this.settings.set_strv ("task-history", task_history);
}

/**
* Sets a default `SessionManager`.
*
Expand Down Expand Up @@ -736,6 +803,13 @@ namespace Ft
this._current_gap = gap;
this._current_state = state;

if (time_block != null &&
time_block.state == Ft.State.POMODORO &&
time_block.get_task () == "")
{
time_block.set_task (this._current_task);
}

this.notify_property ("current-time-block");

if (state != previous_state) {
Expand Down Expand Up @@ -1323,6 +1397,7 @@ namespace Ft
time_block.set_time_range (time_block_entry.start_time, time_block_entry.end_time);
time_block.set_status (Ft.TimeBlockStatus.from_string (time_block_entry.status));
time_block.set_intended_duration (time_block_entry.intended_duration);
time_block.set_task (time_block_entry.task ?? "");
time_block.entry = time_block_entry;

time_blocks_by_id.insert (time_block_entry.id, time_block);
Expand Down
4 changes: 3 additions & 1 deletion src/core/stats-entry.vala
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace Ft
public int64 duration { get; set; }
public string category { get; set; }
public int64 source_id { get; set; default = 0; }
public string task { get; set; default = ""; }

static construct
{
Expand All @@ -42,7 +43,8 @@ namespace Ft
offset: this.offset,
duration: this.duration,
category: this.category,
source_id: this.source_id);
source_id: this.source_id,
task: this.task);
}
}

Expand Down
17 changes: 13 additions & 4 deletions src/core/stats-manager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ namespace Ft
{
public string category;
public int64 source_id;
public string task;
public Segment[] segments;
}

Expand Down Expand Up @@ -285,6 +286,7 @@ namespace Ft
{
var category = item.category;
var source_id = item.source_id;
var task = item.task;
var segments = item.segments;

var repository = Ft.Database.get_repository ();
Expand Down Expand Up @@ -331,7 +333,8 @@ namespace Ft
entry_index++;

if (entry.time == segment.timestamp &&
entry.duration == segment.duration)
entry.duration == segment.duration &&
entry.task == task)
{
continue;
}
Expand All @@ -353,6 +356,7 @@ namespace Ft
entry.offset = offset;
entry.duration = segment.duration;
entry.source_id = source_id;
entry.task = task;

to_save.append (entry);
to_save_count++;
Expand Down Expand Up @@ -418,6 +422,7 @@ namespace Ft

private void track_internal (string category,
int64 source_id,
string task,
owned Segment[] segments)
{
if (segments.length == 0) {
Expand All @@ -428,6 +433,7 @@ namespace Ft
Item () {
category = category,
source_id = source_id,
task = task,
segments = segments
});

Expand All @@ -437,15 +443,16 @@ namespace Ft
public void track (string category,
int64 timestamp,
int64 duration,
int64 source_id = 0)
int64 source_id = 0,
string task = "")
{
if (Ft.Timestamp.is_undefined (timestamp) || duration <= 0) {
return;
}

var segments = this.split (timestamp, duration);

this.track_internal (category, source_id, segments);
this.track_internal (category, source_id, task, segments);
}

/**
Expand Down Expand Up @@ -566,7 +573,9 @@ namespace Ft
segments,
this.split (time_block.start_time, time_block.duration));

this.track_internal (category, time_block_entry.id, segments);
var task = category == "pomodoro" ? time_block.get_task () : "";

this.track_internal (category, time_block_entry.id, task, segments);
}

public void track_gap (Ft.Gap gap)
Expand Down
1 change: 1 addition & 0 deletions src/core/time-block-entry.vala
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace Ft
public string state { get; set; }
public string status { get; set; }
public int64 intended_duration { get; set; }
public string task { get; set; default = ""; }

internal ulong version = 0;

Expand Down
18 changes: 18 additions & 0 deletions src/core/time-block.vala
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ namespace Ft
private int changed_freeze_count = 0;
private bool changed_is_pending = false;
private Ft.TimeBlockMeta meta;
private string task = "";

construct
{
Expand Down Expand Up @@ -722,6 +723,22 @@ namespace Ft
}
}

public string get_task ()
{
return this.task;
}

/**
* A task does not affect scheduling, so it does not emit `changed`.
*/
public void set_task (string task)
{
if (this.task != task) {
this.task = task;
this.version++;
}
}


/*
* Database
Expand Down Expand Up @@ -765,6 +782,7 @@ namespace Ft
this.entry.state = this._state.to_string ();
this.entry.status = this.meta.status.to_string ();
this.entry.intended_duration = this.meta.intended_duration;
this.entry.task = this.task;
this.entry.version = this.version;

return this.entry;
Expand Down
1 change: 1 addition & 0 deletions src/io.github.focustimerhq.FocusTimer.gresource.xml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<file compressed="true">migrations/version-1.sql</file>
<file compressed="true">migrations/version-2.sql</file>
<file compressed="true">migrations/version-3.sql</file>
<file compressed="true">migrations/version-4.sql</file>

<!-- UI -->
<file compressed="true" preprocess="xml-stripblanks">ui/log/log-window.ui</file>
Expand Down
2 changes: 2 additions & 0 deletions src/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,15 @@ libft_ui_sources = files(
'ui/main/stats/widgets/month-chooser.vala',
'ui/main/stats/widgets/stats-card.vala',
'ui/main/stats/widgets/stats-date-popover.vala',
'ui/main/stats/widgets/task-breakdown.vala',
'ui/main/stats/widgets/week-chooser.vala',
'ui/main/stats/stats-day-page.vala',
'ui/main/stats/stats-month-page.vala',
'ui/main/stats/stats-page.vala',
'ui/main/stats/stats-view.vala',
'ui/main/stats/stats-week-page.vala',
'ui/main/timer/widgets/session-progress-bar.vala',
'ui/main/timer/widgets/task-button.vala',
'ui/main/timer/widgets/timer-control-buttons.vala',
'ui/main/timer/widgets/timer-label.vala',
'ui/main/timer/widgets/timer-progress-bar.vala',
Expand Down
7 changes: 7 additions & 0 deletions src/migrations/version-4.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
-- Add a task name to time-blocks and stats entries.
-- Tasks are identified by their name. An empty string means no task.

ALTER TABLE "timeblocks" ADD COLUMN "task" TEXT NOT NULL DEFAULT '';
ALTER TABLE "stats" ADD COLUMN "task" TEXT NOT NULL DEFAULT '';

CREATE INDEX "stats-date-task" ON "stats" ("date", "task") WHERE "task" != '';
29 changes: 29 additions & 0 deletions src/ui/main/stats/stats-day-page.ui
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,35 @@
</child>
</object><!-- flow-box -->
</child>
<child>
<object class="FtTaskBreakdown" id="task_breakdown"/>
</child>
<child>
<object class="GtkBox" id="history_box">
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<property name="visible">false</property>
<property name="margin-bottom">12</property>
<child>
<object class="GtkLabel">
<property name="label" translatable="yes">History</property>
<property name="halign">start</property>
<property name="xalign">0</property>
<style>
<class name="heading"/>
</style>
</object>
</child>
<child>
<object class="GtkListBox" id="history_listbox">
<property name="selection-mode">none</property>
<style>
<class name="boxed-list"/>
</style>
</object>
</child>
</object>
</child>
</object><!-- box -->
</property>
</template>
Expand Down
Loading