Skip to content

Commit ea52a61

Browse files
authored
Merge branch 'main' into cli-interface
2 parents f849c1f + d90bbd6 commit ea52a61

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

128 files changed

+18753
-16708
lines changed

.github/workflows/flatpak.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ name: Build Flatpak
22
'on':
33
push:
44
branches:
5-
- master
5+
- main
66
jobs:
77
flatpak:
88
name: flatpak

ARCHITECTURE.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,13 @@ sequenceDiagram
3737
Application->>User:Initialize UI with data
3838
```
3939

40-
When the user opens the application, the `App.vala` runs `MainWindow.vala` to initialize the application. First the app starts the SQLite database and connects to it ([src/MainWindow.vala\#L156](https://github.com/alainm23/planify/blob/master/src/MainWindow.vala#L156)). The database will return the stored data, including any external data sources that the program should synchronize with. Then, the program will start the synchronization process for all connected external data sources ([src/MainWindow.vala\#L198](https://github.com/alainm23/planify/blob/master/src/MainWindow.vala#L198)). The data will be fetched asynchronously. Finally, the UI is populated with the loaded data and displayed to the user.
40+
When the user opens the application, the `App.vala` runs `MainWindow.vala` to initialize the application. First the app starts the SQLite database and connects to it ([src/MainWindow.vala\#L156](https://github.com/alainm23/planify/blob/main/src/MainWindow.vala#L156)). The database will return the stored data, including any external data sources that the program should synchronize with. Then, the program will start the synchronization process for all connected external data sources ([src/MainWindow.vala\#L198](https://github.com/alainm23/planify/blob/main/src/MainWindow.vala#L198)). The data will be fetched asynchronously. Finally, the UI is populated with the loaded data and displayed to the user.
4141

4242
## Switching pages
4343

4444
![](docs/image4.png)
4545

46-
The Planify app has three main Views. The label list ([src/Views/Label](https://github.com/alainm23/planify/tree/master/src/Views/Label)), the task list ([src/Views/Project/List.vala](https://github.com/alainm23/planify/blob/master/src/Views/Project/List.vala)), and the day list ([src/Views/Scheduled](https://github.com/alainm23/planify/tree/master/src/Views/Scheduled)). As the user, as you navigate around the application, you can transition between these different states, changing which view is in your main window. By using the Inbox, Today, Scheduled, and Labels buttons in the sidebar, you can transition between those modes, which have specific Views associated with them. For example, if you press the Labels button, that will open a label list view. If you click on a specific label, you will be transitioned to a task list view with all of the tasks with that label attached. From here, you could transition to the day list view by pressing the Scheduled button in the sidebar.
46+
The Planify app has three main Views. The label list ([src/Views/Label](https://github.com/alainm23/planify/tree/main/src/Views/Label)), the task list ([src/Views/Project/List.vala](https://github.com/alainm23/planify/blob/main/src/Views/Project/List.vala)), and the day list ([src/Views/Scheduled](https://github.com/alainm23/planify/tree/main/src/Views/Scheduled)). As the user, as you navigate around the application, you can transition between these different states, changing which view is in your main window. By using the Inbox, Today, Scheduled, and Labels buttons in the sidebar, you can transition between those modes, which have specific Views associated with them. For example, if you press the Labels button, that will open a label list view. If you click on a specific label, you will be transitioned to a task list view with all of the tasks with that label attached. From here, you could transition to the day list view by pressing the Scheduled button in the sidebar.
4747

4848
## Adding a new task
4949

@@ -75,13 +75,13 @@ For Todoist sources, it must retrieve a session token from the Todoist API. It m
7575
[core/Services/Todoist.vala\#L210](https://github.com/alainm23/planify/blob/4e40a7244c1d2b564e97e65508481f7c2e6ff038/core/Services/Todoist.vala#L210)
7676

7777
For CalDAV Sources, it retrieves the authentication bearer token from storage, authenticates, retrieves & parses the XML, and merges or deletes calendars/tasks as necessary.
78-
[core/Services/CalDAV/Core.vala\#L234](https://github.com/alainm23/planify/blob/master/core/Services/CalDAV/Core.vala#L234)
78+
[core/Services/CalDAV/Core.vala\#L234](https://github.com/alainm23/planify/blob/main/core/Services/CalDAV/Core.vala#L234)
7979

8080
`SyncButton.vala` has the ability to manually trigger a sync by broadcasting on its clicked signal. It also responds to events dispatched from the sources and updates its appearance accordingly when syncs start, fail, or finish.
81-
[src/Widgets/SyncButton.vala\#L73](https://github.com/alainm23/planify/blob/master/src/Widgets/SyncButton.vala#L73)
81+
[src/Widgets/SyncButton.vala\#L73](https://github.com/alainm23/planify/blob/main/src/Widgets/SyncButton.vala#L73)
8282

8383
## Reminders
8484

8585
![](docs/image3.png)
8686

87-
When a reminder is created in the UI or loaded from the database at startup, it will run `reminder_added()` in [Notification.vala](https://github.com/alainm23/planify/blob/master/src/Services/Notification.vala#L60). The code will first check if the time of the notification has already passed, and if it has, it will trigger the notification. If not, it will check whether or not the reminder is due today. If it is due today, it will set a timeout for the remaining time until the notification is due. If it is not due, it will not do anything. However, in [TimeMonitor.vala](https://github.com/alainm23/planify/blob/master/src/Services/TimeMonitor.vala), there is always a timeout set for midnight. At midnight, it will call `refresh()`, causing `Notification.vala` to rerun `reminder_added()` for all reminders. This in effect causes all reminders to check if they are due again, since it is now a new day. This loop continues until all reminders have been triggered.
87+
When a reminder is created in the UI or loaded from the database at startup, it will run `reminder_added()` in [Notification.vala](https://github.com/alainm23/planify/blob/main/src/Services/Notification.vala#L60). The code will first check if the time of the notification has already passed, and if it has, it will trigger the notification. If not, it will check whether or not the reminder is due today. If it is due today, it will set a timeout for the remaining time until the notification is due. If it is not due, it will not do anything. However, in [TimeMonitor.vala](https://github.com/alainm23/planify/blob/main/src/Services/TimeMonitor.vala), there is always a timeout set for midnight. At midnight, it will call `refresh()`, causing `Notification.vala` to rerun `reminder_added()` for all reminders. This in effect causes all reminders to check if they are due again, since it is now a new day. This loop continues until all reminders have been triggered.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
<h3 align="center">Never worry about forgetting things again</h3>
1111
</div>
1212

13-
![Planify Screenshot](https://raw.githubusercontent.com/alainm23/planify/master/data/resources/screenshot/screenshot-03.png)
13+
![Planify Screenshot](https://raw.githubusercontent.com/alainm23/planify/main/data/resources/screenshot/screenshot-03.png)
1414

1515
## ✨ Features
1616

core/Objects/Item.vala

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ public class Objects.Item : Objects.BaseObject {
6262
public Objects.DueDate due { get; set; default = new Objects.DueDate (); }
6363
public Gee.ArrayList<Objects.Label> labels { get; set; default = new Gee.ArrayList<Objects.Label> (); }
6464

65-
public Gee.ArrayList<Objects.Label> _get_labels () {
65+
public Gee.ArrayList<Objects.Label> get_labels_list () {
6666
Gee.ArrayList<Objects.Label> return_value = new Gee.ArrayList<Objects.Label> ();
6767

6868
foreach (Objects.Label label in labels) {
@@ -513,6 +513,10 @@ public class Objects.Item : Objects.BaseObject {
513513
ICal.Property ? related_to_property = ical_vtodo.get_first_property (ICal.PropertyKind.RELATEDTO_PROPERTY);
514514
if (related_to_property != null) {
515515
parent_id = related_to_property.get_relatedto ();
516+
if (parent_id == id) {
517+
warning ("Item/Task %s has a direct self-reference", id);
518+
parent_id = "";
519+
}
516520
} else {
517521
parent_id = "";
518522
}
@@ -601,7 +605,7 @@ public class Objects.Item : Objects.BaseObject {
601605
}
602606
}
603607

604-
foreach (var label in _get_labels ()) {
608+
foreach (var label in get_labels_list ()) {
605609
if (!new_labels.has_key (label.id)) {
606610
delete_item_label (label.id);
607611
}
@@ -945,6 +949,10 @@ public class Objects.Item : Objects.BaseObject {
945949
item_label_added (label);
946950
}
947951

952+
public void clean_labels () {
953+
labels.clear ();
954+
}
955+
948956
public Objects.Label ? delete_item_label (string id) {
949957
Objects.Label ? return_value = null;
950958
return_value = get_label (id);
@@ -1681,10 +1689,22 @@ public class Objects.Item : Objects.BaseObject {
16811689
}
16821690

16831691
public bool was_archived () {
1684-
if (has_parent) {
1692+
return was_archived_internal (new Gee.HashSet<string> ());
1693+
}
1694+
1695+
private bool was_archived_internal (Gee.Set<string> visited) {
1696+
// Prevent infinite recursion with circular references
1697+
if (visited.contains (id)) {
1698+
warning ("Item/Task %s has a circular reference", id);
1699+
return false;
1700+
}
1701+
1702+
visited.add (id);
1703+
1704+
if (has_parent && _parent_id != id) { // Check for direct self-reference
16851705
var parent_item = parent;
16861706
if (parent_item != null) {
1687-
return parent_item.was_archived ();
1707+
return parent_item.was_archived_internal (visited);
16881708
}
16891709
}
16901710

@@ -1836,7 +1856,7 @@ public class Objects.Item : Objects.BaseObject {
18361856
}
18371857
}
18381858

1839-
foreach (var label in _get_labels ()) {
1859+
foreach (var label in get_labels_list ()) {
18401860
if (!new_labels.has_key (label.id)) {
18411861
delete_item_label (label.id);
18421862
update = true;

core/Objects/Project.vala

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public class Objects.Project : Objects.BaseObject {
3838
public string sync_id { get; set; default = ""; }
3939
public string source_id { get; set; default = SourceType.LOCAL.to_string (); }
4040
public string calendar_url { get; set; default = ""; }
41-
public string calendar_source_uid { get; set; default = ""; }
41+
public string calendar_source_uid { get; set; default = ""; }
4242

4343
bool _show_completed = false;
4444
public bool show_completed {
@@ -119,7 +119,7 @@ public class Objects.Project : Objects.BaseObject {
119119
return _view_id;
120120
}
121121
}
122-
122+
123123
string _parent_id_string;
124124
public string parent_id_string {
125125
get {
@@ -535,7 +535,7 @@ public class Objects.Project : Objects.BaseObject {
535535
var related_items = new Gee.ArrayList<Objects.Item> ();
536536

537537
foreach (var item in items) {
538-
string? parent_id = Util.find_string_value ("RELATED-TO", item.calendar_data);
538+
string ? parent_id = Util.find_string_value ("RELATED-TO", item.calendar_data);
539539
if (parent_id != null && parent_id != "") {
540540
Objects.Item ? parent_item = Services.Store.instance ().get_item (parent_id);
541541
if (parent_item != null) {
@@ -772,7 +772,7 @@ public class Objects.Project : Objects.BaseObject {
772772
}
773773

774774
var project_items = Services.Store.instance ().get_items_by_project (this);
775-
775+
776776
int pending_tasks = 0;
777777
int items_total = 0;
778778
int items_checked = 0;
@@ -871,35 +871,35 @@ public class Objects.Project : Objects.BaseObject {
871871

872872
private void handle_project_deletion () {
873873
loading = true;
874-
874+
875875
if (source_type == SourceType.LOCAL) {
876876
Services.Store.instance ().delete_project.begin (this);
877877
return;
878878
}
879-
879+
880880
if (source_type == SourceType.TODOIST) {
881881
delete_from_todoist ();
882882
} else if (source_type == SourceType.CALDAV) {
883883
delete_from_caldav ();
884884
}
885885
}
886-
886+
887887
private void delete_from_todoist () {
888888
Services.Todoist.get_default ().delete.begin (this, (obj, res) => {
889889
handle_remote_delete_response (Services.Todoist.get_default ().delete.end (res));
890890
});
891891
}
892-
892+
893893
private void delete_from_caldav () {
894894
var caldav_client = Services.CalDAV.Core.get_default ().get_client (source);
895895
caldav_client.delete_project.begin (this, (obj, res) => {
896896
handle_remote_delete_response (caldav_client.delete_project.end (res));
897897
});
898898
}
899-
899+
900900
private void handle_remote_delete_response (HttpResponse response) {
901901
loading = false;
902-
902+
903903
if (response.status) {
904904
Services.Store.instance ().delete_project.begin (this);
905905
} else {

0 commit comments

Comments
 (0)