diff --git a/.gitignore b/.gitignore index 05abb2779..6db483f2c 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ builddir/ build-aux/build-dir build-aux/flatpak_build build-aux/.flatpak-builder -build-aux/io.github.alainm23.planify.Devel.flatpak .flatpak-builder/ subprojects/gxml diff --git a/build-aux/io.github.alainm23.planify.Devel.flatpak b/build-aux/io.github.alainm23.planify.Devel.flatpak new file mode 100644 index 000000000..93d120cf8 Binary files /dev/null and b/build-aux/io.github.alainm23.planify.Devel.flatpak differ diff --git a/build-aux/io.github.alainm23.planify.Devel.json b/build-aux/io.github.alainm23.planify.Devel.json index b8ceea746..faef13c90 100644 --- a/build-aux/io.github.alainm23.planify.Devel.json +++ b/build-aux/io.github.alainm23.planify.Devel.json @@ -1,12 +1,10 @@ { - "app-id" : "io.github.alainm23.planify.Devel", - "runtime" : "org.gnome.Platform", + "app-id": "io.github.alainm23.planify.Devel", + "runtime": "org.gnome.Platform", "runtime-version": "45", - "sdk" : "org.gnome.Sdk", - "command" : "io.github.alainm23.planify.Devel", - "tags" : [ - "devel" - ], + "sdk": "org.gnome.Sdk", + "command": "io.github.alainm23.planify.Devel", + "tags": ["devel"], "finish-args": [ "--device=dri", "--share=ipc", @@ -31,10 +29,10 @@ "*.la", "*.a" ], - "modules" : [ + "modules": [ { "name": "intltool", - "cleanup": [ "*" ], + "cleanup": ["*"], "sources": [ { "type": "archive", @@ -57,9 +55,7 @@ { "name": "libical", "buildsystem": "cmake-ninja", - "cleanup": [ - "/lib/cmake" - ], + "cleanup": ["/lib/cmake"], "config-opts": [ "-DCMAKE_BUILD_TYPE=Release", "-DCMAKE_INSTALL_LIBDIR=/app/lib", @@ -153,13 +149,10 @@ ] }, { - "name" : "planify", - "builddir" : true, - "buildsystem" : "meson", - "config-opts" : [ - "-Dtracing=true", - "-Dprofile=development" - ], + "name": "planify", + "builddir": true, + "buildsystem": "meson", + "config-opts": ["-Dtracing=true", "-Dprofile=development"], "sources": [ { "type": "dir", diff --git a/core/Objects/Item.vala b/core/Objects/Item.vala index 96c610c1f..16380f346 100644 --- a/core/Objects/Item.vala +++ b/core/Objects/Item.vala @@ -329,8 +329,8 @@ public class Objects.Item : Objects.BaseObject { description = ical.get_description (); } - if (Util.get_default ().find_string_value ("PRIORITY", data) != "") { - int _priority = int.parse (Util.get_default ().find_string_value ("PRIORITY", data)); + if (Util.find_string_value ("PRIORITY", data) != "") { + int _priority = int.parse (Util.find_string_value ("PRIORITY", data)); if (_priority <= 0) { priority = Constants.PRIORITY_4; } else if (_priority >= 1 && _priority <= 4) { @@ -345,16 +345,29 @@ public class Objects.Item : Objects.BaseObject { } if (!ical.get_due ().is_null_time ()) { - due.date = Util.get_default ().ical_to_date_time_local (ical.get_due ()).to_string (); + due.date = Util.ical_to_date_time_local (ical.get_due ()).to_string (); } - string _parent_id = Util.get_default ().find_string_value ("RELATED-TO", data); + string _parent_id = Util.find_string_value ("RELATED-TO", data); if (_parent_id != "") { parent_id = _parent_id; } - pinned = Util.get_default ().find_boolean_value ("X-PINNED", data); - extra_data = Util.get_default ().generate_extra_data (Util.get_default ().get_task_id_from_url (element), etag, ical.as_ical_string ()); + if (ical.get_status () == ICal.PropertyStatus.COMPLETED) { + checked = true; + var completed_datetime = ical.get_first_property (ICal.PropertyKind.COMPLETED_PROPERTY); + if (completed_datetime != null) { + completed_at = Util.ical_to_date_time_local (completed_datetime.get_completed ()).to_string (); + } else { + completed_at = Util.get_default ().get_format_date (new GLib.DateTime.now_local ()).to_string (); + } + } else { + checked = false; + completed_at = ""; + } + + pinned = Util.find_boolean_value ("X-PINNED", data); + extra_data = Util.generate_extra_data (Util.get_task_id_from_url (element), etag, ical.as_ical_string ()); } public void update_from_json (Json.Node node) { @@ -872,7 +885,7 @@ public class Objects.Item : Objects.BaseObject { return generator.to_data (null); } - public string to_vtodo (bool update = false) { + public string to_vtodo () { ICal.Component ical = new ICal.Component.vtodo (); ical.set_uid (id); @@ -887,10 +900,18 @@ public class Objects.Item : Objects.BaseObject { } if (has_due) { - var task_tz = ical.get_due ().get_timezone (); - ICal.Time new_icaltime = Util.get_default ().datetimes_to_icaltime (due.datetime, due.datetime, null); + // var task_tz = ical.get_due ().get_timezone (); + ICal.Time new_icaltime = Util.datetimes_to_icaltime (due.datetime, due.datetime, null); ical.set_due (new_icaltime); } + + if (checked) { + ical.set_status (ICal.PropertyStatus.COMPLETED); + ical.add_property (new ICal.Property.percentcomplete (100)); + ical.add_property (new ICal.Property.completed (new ICal.Time.today ())); + } else { + ical.set_status (ICal.PropertyStatus.NEEDSACTION); + } var _priority = 0; if (priority == Constants.PRIORITY_4) { diff --git a/core/Objects/Section.vala b/core/Objects/Section.vala index dab0fad9f..d911257d9 100644 --- a/core/Objects/Section.vala +++ b/core/Objects/Section.vala @@ -29,6 +29,7 @@ public class Objects.Section : Objects.BaseObject { public bool is_archived { get; set; default = false; } public string color { get; set; default = ""; } public string description { get; set; default = ""; } + public bool hidded { get; set; default = false; } // Tmp public bool activate_name_editable { get; set; default = false; } diff --git a/core/Services/CalDAV.vala b/core/Services/CalDAV.vala index 40b4a712b..379c09db9 100644 --- a/core/Services/CalDAV.vala +++ b/core/Services/CalDAV.vala @@ -250,9 +250,6 @@ public class Services.CalDAV : GLib.Object { - - - @@ -392,7 +389,7 @@ public class Services.CalDAV : GLib.Object { GXml.DomHTMLCollection response = doc.get_elements_by_tag_name ("d:response"); foreach (GXml.DomElement element in response) { Objects.Item? item = Services.Database.get_default ().get_item ( - Util.get_default ().get_task_uid (element) + Util.get_task_uid (element) ); if (item != null) { @@ -403,9 +400,15 @@ public class Services.CalDAV : GLib.Object { item.update_from_caldav_xml (element); Services.Database.get_default ().update_item (item); + // TODO: Fix moved if (old_parent_id != item.parent_id) { Services.EventBus.get_default ().item_moved (item, old_project_id, old_section_id, old_parent_id); } + + bool old_checked = item.checked; + if (old_checked != item.checked) { + Services.Database.get_default ().checked_toggled (item, old_checked); + } } else { add_item_if_not_exists (element, project); } @@ -416,7 +419,7 @@ public class Services.CalDAV : GLib.Object { } private void add_item_if_not_exists (GXml.DomElement element, Objects.Project project) { - string parent_id = Util.get_default ().get_related_to_uid (element); + string parent_id = Util.get_related_to_uid (element); if (parent_id != "") { Objects.Item? parent_item = Services.Database.get_default ().get_item (parent_id); if (parent_item != null) { @@ -570,13 +573,10 @@ public class Services.CalDAV : GLib.Object { var ics = update ? item.ics : "%s.ics".printf (item.id); - print ("%s\n".printf (item.to_vtodo (update))); - var url = "%s/remote.php/dav/calendars/%s/%s/%s".printf (server_url, username, item.project.id, ics); - print ("URL: %s\n".printf (url)); var message = new Soup.Message ("PUT", url); message.request_headers.append ("Authorization", "Basic %s".printf (credential)); - message.set_request_body_from_bytes ("application/xml", new Bytes (item.to_vtodo (update).data)); + message.set_request_body_from_bytes ("application/xml", new Bytes (item.to_vtodo ().data)); HttpResponse response = new HttpResponse (); @@ -585,7 +585,7 @@ public class Services.CalDAV : GLib.Object { if (update ? message.status_code == 204 : message.status_code == 201) { response.status = true; - item.extra_data = Util.get_default ().generate_extra_data (ics, "", item.to_vtodo (update)); + item.extra_data = Util.generate_extra_data (ics, "", item.to_vtodo ()); } } catch (Error e) { debug (e.message); @@ -623,6 +623,35 @@ public class Services.CalDAV : GLib.Object { return response; } + public async HttpResponse complete_item (Objects.Item item) { + var server_url = Services.Settings.get_default ().settings.get_string ("caldav-server-url"); + var username = Services.Settings.get_default ().settings.get_string ("caldav-username"); + var credential = Services.Settings.get_default ().settings.get_string ("caldav-credential"); + + var ics = item.ics; + var body = item.to_vtodo (); + + var url = "%s/remote.php/dav/calendars/%s/%s/%s".printf (server_url, username, item.project.id, ics); + var message = new Soup.Message ("PUT", url); + message.request_headers.append ("Authorization", "Basic %s".printf (credential)); + message.set_request_body_from_bytes ("application/xml", new Bytes (body.data)); + + HttpResponse response = new HttpResponse (); + + try { + yield session.send_and_read_async (message, GLib.Priority.HIGH, null); + + if (message.status_code == 204) { + response.status = true; + item.extra_data = Util.generate_extra_data (ics, "", body); + } + } catch (Error e) { + debug (e.message); + } + + return response; + } + public void remove_items () { Services.Settings.get_default ().settings.set_string ("caldav-server-url", ""); Services.Settings.get_default ().settings.set_string ("caldav-username", ""); diff --git a/core/Services/Database.vala b/core/Services/Database.vala index 33c333bff..6d116cfdd 100644 --- a/core/Services/Database.vala +++ b/core/Services/Database.vala @@ -187,7 +187,8 @@ public class Services.Database : GLib.Object { * - Add extra data column to Items */ - add_text_column ("Items", "extra_data", ""); + add_text_column ("Items", "extra_data", ""); + add_int_column ("Sections", "hidded", 0); } private void create_tables () { @@ -252,6 +253,7 @@ public class Services.Database : GLib.Object { is_archived INTEGER, color TEXT, description TEXT, + hidded INTEGER, FOREIGN KEY (project_id) REFERENCES Projects (id) ON DELETE CASCADE ); """; @@ -789,8 +791,7 @@ public class Services.Database : GLib.Object { } } - public Objects.Label get_label_by_name (string name, bool lowercase = false, BackendType backend_type) { - Objects.Label? return_value = null; + public Objects.Label? get_label_by_name (string name, bool lowercase = false, BackendType backend_type) { lock (_labels) { string compare_name = lowercase ? name.down () : name; @@ -901,9 +902,9 @@ public class Services.Database : GLib.Object { sql = """ INSERT OR IGNORE INTO Sections (id, name, archived_at, added_at, project_id, section_order, - collapsed, is_deleted, is_archived, color, description) + collapsed, is_deleted, is_archived, color, description, hidded) VALUES ($id, $name, $archived_at, $added_at, $project_id, $section_order, - $collapsed, $is_deleted, $is_archived, $color, $description); + $collapsed, $is_deleted, $is_archived, $color, $description, $hidded); """; db.prepare_v2 (sql, sql.length, out stmt); @@ -918,6 +919,7 @@ public class Services.Database : GLib.Object { set_parameter_bool (stmt, "$is_archived", section.is_archived); set_parameter_str (stmt, "$color", section.color); set_parameter_str (stmt, "$description", section.description); + set_parameter_bool (stmt, "$hidded", section.hidded); if (stmt.step () == Sqlite.DONE) { sections.add (section); @@ -985,6 +987,7 @@ public class Services.Database : GLib.Object { return_value.is_archived = get_parameter_bool (stmt, 8); return_value.color = stmt.column_text (9); return_value.description = stmt.column_text (10); + return_value.hidded = get_parameter_bool (stmt, 11); return return_value; } @@ -1016,8 +1019,9 @@ public class Services.Database : GLib.Object { sql = """ UPDATE Sections SET name=$name, archived_at=$archived_at, added_at=$added_at, - project_id=$project_id, section_order=$section_order, collapsed=$collapsed, - is_deleted=$is_deleted, is_archived=$is_archived, color=$color, description=$description + project_id=$project_id, section_order=$section_order, collapsed=$collapsed, + is_deleted=$is_deleted, is_archived=$is_archived, color=$color, description=$description, + hidded=$hidded WHERE id=$id; """; @@ -1032,6 +1036,7 @@ public class Services.Database : GLib.Object { set_parameter_bool (stmt, "$is_archived", section.is_archived); set_parameter_str (stmt, "$color", section.color); set_parameter_str (stmt, "$description", section.description); + set_parameter_bool (stmt, "$hidded", section.hidded); set_parameter_str (stmt, "$id", section.id); if (stmt.step () == Sqlite.DONE) { @@ -2001,7 +2006,7 @@ public class Services.Database : GLib.Object { warning ("Error: %d: %s", db.errcode (), db.errmsg ()); } - stmt.reset (); + stmt.reset(); } public void clear_queue () { diff --git a/core/Services/Todoist.vala b/core/Services/Todoist.vala index 0239833c7..7c69ed0dc 100644 --- a/core/Services/Todoist.vala +++ b/core/Services/Todoist.vala @@ -1391,7 +1391,7 @@ public class HttpResponse { public void from_error_xml (GXml.DomDocument doc, int error_code) { status = false; - error_code = error_code; + this.error_code = error_code; http_code = error_code; error = doc.get_elements_by_tag_name ("o:hint").get_element (0).text_content; } diff --git a/core/Util/Util.vala b/core/Util/Util.vala index d9c3e00dd..1e96e1e3f 100644 --- a/core/Util/Util.vala +++ b/core/Util/Util.vala @@ -1143,7 +1143,7 @@ We hope you’ll enjoy using Planify!"""); GXml.DomElement propstat = element.get_elements_by_tag_name ("d:propstat").get_element (0); GXml.DomElement prop = propstat.get_elements_by_tag_name ("d:prop").get_element (0); string data = prop.get_elements_by_tag_name ("cal:calendar-data").get_element (0).text_content; - string etag = prop.get_elements_by_tag_name ("d:getetag").get_element (0).text_content; + // string etag = prop.get_elements_by_tag_name ("d:getetag").get_element (0).text_content; ICal.Component ical = new ICal.Component.from_string (data); return ical.get_uid (); @@ -1153,7 +1153,7 @@ We hope you’ll enjoy using Planify!"""); GXml.DomElement propstat = element.get_elements_by_tag_name ("d:propstat").get_element (0); GXml.DomElement prop = propstat.get_elements_by_tag_name ("d:prop").get_element (0); string data = prop.get_elements_by_tag_name ("cal:calendar-data").get_element (0).text_content; - return Util.get_default ().find_string_value ("RELATED-TO", data); + return Util.find_string_value ("RELATED-TO", data); } public static string find_string_value (string key, string data) { diff --git a/data/resources/stylesheet/stylesheet.css b/data/resources/stylesheet/stylesheet.css index 4fdbc40a6..04af6b5e2 100644 --- a/data/resources/stylesheet/stylesheet.css +++ b/data/resources/stylesheet/stylesheet.css @@ -587,4 +587,9 @@ checkbutton.theme-selector radio:checked { .banner-text { color: #333; +} + +.active-switch slider { + min-height: 16px; + min-width: 16px; } \ No newline at end of file diff --git a/src/Dialogs/ManageSectionOrder.vala b/src/Dialogs/ManageSectionOrder.vala index d6a8e65e0..ce7797b17 100644 --- a/src/Dialogs/ManageSectionOrder.vala +++ b/src/Dialogs/ManageSectionOrder.vala @@ -22,7 +22,6 @@ public class Dialogs.ManageSectionOrder : Adw.Window { public Objects.Project project { get; construct; } private Gtk.ListBox listbox; - private Gtk.DropControllerMotion drop_motion_ctrl; private Widgets.ScrolledWindow scrolled_window; public ManageSectionOrder (Objects.Project project) { @@ -31,7 +30,7 @@ public class Dialogs.ManageSectionOrder : Adw.Window { deletable: true, resizable: true, modal: true, - title: _("Manage Section Order"), + title: _("Manage Sections"), width_request: 320, height_request: 450, transient_for: (Gtk.Window) Planify.instance.main_window diff --git a/src/Dialogs/Preferences/PreferencesWindow.vala b/src/Dialogs/Preferences/PreferencesWindow.vala index 643c87528..ccb19b5a6 100644 --- a/src/Dialogs/Preferences/PreferencesWindow.vala +++ b/src/Dialogs/Preferences/PreferencesWindow.vala @@ -723,9 +723,7 @@ public class Dialogs.Preferences.PreferencesWindow : Adw.PreferencesWindow { margin_end = 6, valign = Gtk.Align.CENTER, halign = Gtk.Align.CENTER, - child = new Widgets.DynamicIcon.from_icon_name ("planner-settings") { - size = 24 - }, + child = new Widgets.DynamicIcon.from_icon_name ("planner-settings"), css_classes = { Granite.STYLE_CLASS_FLAT } }; @@ -1410,15 +1408,6 @@ public class Dialogs.Preferences.PreferencesWindow : Adw.PreferencesWindow { return page; } - private bool is_valid_url (string uri) { - var scheme = Uri.parse_scheme (uri); - if (scheme == null) { - return false; - } - - return scheme.has_prefix ("http"); - } - private Adw.NavigationPage get_backups_page () { var backup_page = new Dialogs.Preferences.Pages.Backup (); var page = new Adw.NavigationPage (backup_page, "backups-page"); diff --git a/src/Dialogs/ProjectPicker/SectionPickerRow.vala b/src/Dialogs/ProjectPicker/SectionPickerRow.vala index eb095fbb4..ab6c28c3b 100644 --- a/src/Dialogs/ProjectPicker/SectionPickerRow.vala +++ b/src/Dialogs/ProjectPicker/SectionPickerRow.vala @@ -25,7 +25,6 @@ public class Dialogs.ProjectPicker.SectionPickerRow : Gtk.ListBoxRow { private Gtk.Label name_label; private Gtk.Grid handle_grid; - private Gtk.Revealer main_revealer; public SectionPickerRow (Objects.Section section, string widget_type = "picker") { Object ( @@ -59,10 +58,12 @@ public class Dialogs.ProjectPicker.SectionPickerRow : Gtk.ListBoxRow { selected_revealer.child = selected_icon; - var order_icon = new Widgets.DynamicIcon () { - hexpand = true, - halign = Gtk.Align.END + var hidded_switch = new Gtk.Switch () { + css_classes = { "active-switch" }, + active = !section.hidded }; + + var order_icon = new Widgets.DynamicIcon (); order_icon.size = 16; order_icon.update_icon_name ("menu"); @@ -76,7 +77,14 @@ public class Dialogs.ProjectPicker.SectionPickerRow : Gtk.ListBoxRow { content_box.append (name_label); if (widget_type == "order") { - content_box.append (order_icon); + var box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12) { + hexpand = true, + halign = Gtk.Align.END + }; + box.append (hidded_switch); + box.append (order_icon); + + content_box.append (box); } if (widget_type == "picker") { @@ -93,7 +101,7 @@ public class Dialogs.ProjectPicker.SectionPickerRow : Gtk.ListBoxRow { if (widget_type == "picker") { var select_gesture = new Gtk.GestureClick (); add_controller (select_gesture); - + select_gesture.pressed.connect (() => { Services.EventBus.get_default ().section_picker_changed (section.id); }); @@ -105,6 +113,11 @@ public class Dialogs.ProjectPicker.SectionPickerRow : Gtk.ListBoxRow { if (widget_type == "order") { reorder_child.build_drag_and_drop (); + + hidded_switch.notify["active"].connect (() => { + section.hidded = !hidded_switch.active; + Services.Database.get_default ().update_section (section); + }); } } } diff --git a/src/Layouts/HeaderBar.vala b/src/Layouts/HeaderBar.vala index e4276df77..96c6704e7 100644 --- a/src/Layouts/HeaderBar.vala +++ b/src/Layouts/HeaderBar.vala @@ -23,6 +23,7 @@ public class Layouts.HeaderBar : Adw.Bin { private Adw.HeaderBar headerbar; private Gtk.Label title_label; private Gtk.Revealer back_button_revealer; + private Gtk.Box start_box; private string _title; public string title { @@ -68,7 +69,8 @@ public class Layouts.HeaderBar : Adw.Bin { // Back Button var back_button = new Gtk.Button () { valign = Gtk.Align.CENTER, - child = new Widgets.DynamicIcon.from_icon_name ("go-previous-symbolic") + child = new Widgets.DynamicIcon.from_icon_name ("go-previous-symbolic"), + margin_end = 6 }; back_button.add_css_class (Granite.STYLE_CLASS_FLAT); @@ -84,15 +86,18 @@ public class Layouts.HeaderBar : Adw.Bin { use_markup = true, css_classes = { "font-bold" } }; - + + start_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 4); + start_box.append (sidebar_button); + start_box.append (back_button_revealer); + start_box.append (title_label); + headerbar = new Adw.HeaderBar () { hexpand = true, show_title = false }; - headerbar.pack_start (sidebar_button); - headerbar.pack_start (back_button_revealer); - headerbar.pack_start (title_label); + headerbar.pack_start (start_box); child = headerbar; @@ -105,7 +110,7 @@ public class Layouts.HeaderBar : Adw.Bin { back_activated (); }); } - + public void pack_end (Gtk.Widget widget) { headerbar.pack_end (widget); } diff --git a/src/Layouts/ItemBoard.vala b/src/Layouts/ItemBoard.vala index d4d6133cb..8c229854f 100644 --- a/src/Layouts/ItemBoard.vala +++ b/src/Layouts/ItemBoard.vala @@ -52,7 +52,6 @@ public class Layouts.ItemBoard : Layouts.ItemBase { private Gtk.Revealer select_revealer; public uint complete_timeout { get; set; default = 0; } - Gee.HashMap labels = new Gee.HashMap (); private bool _is_loading; public bool is_loading { diff --git a/src/Layouts/ItemRow.vala b/src/Layouts/ItemRow.vala index 0e294ee98..aef64a8ac 100644 --- a/src/Layouts/ItemRow.vala +++ b/src/Layouts/ItemRow.vala @@ -1113,19 +1113,7 @@ public class Layouts.ItemRow : Layouts.ItemBase { item.checked = false; item.completed_at = ""; - if (item.project.backend_type == BackendType.TODOIST) { - checked_button.sensitive = false; - is_loading = true; - Services.Todoist.get_default ().complete_item.begin (item, (obj, res) => { - if (Services.Todoist.get_default ().complete_item.end (res).status) { - Services.Database.get_default ().checked_toggled (item, old_checked); - is_loading = false; - checked_button.sensitive = true; - } - }); - } else if (item.project.backend_type == BackendType.LOCAL) { - Services.Database.get_default ().checked_toggled (item, old_checked); - } + _complete_item (old_checked); } } } @@ -1158,28 +1146,39 @@ public class Layouts.ItemRow : Layouts.ItemBase { item.completed_at = Util.get_default ().get_format_date ( new GLib.DateTime.now_local ()).to_string (); - if (item.project.backend_type == BackendType.TODOIST) { - checked_button.sensitive = false; - is_loading = true; - Services.Todoist.get_default ().complete_item.begin (item, (obj, res) => { - if (Services.Todoist.get_default ().complete_item.end (res).status) { - Services.Database.get_default ().checked_toggled (item, old_checked); - is_loading = false; - checked_button.sensitive = true; - } else { - is_loading = false; - checked_button.sensitive = true; - } - }); - } else if (item.project.backend_type == BackendType.LOCAL) { - Services.Database.get_default ().checked_toggled (item, old_checked); - } + _complete_item (old_checked); } return GLib.Source.REMOVE; }); } + private void _complete_item (bool old_checked) { + if (item.project.backend_type == BackendType.LOCAL) { + Services.Database.get_default ().checked_toggled (item, old_checked); + } else if (item.project.backend_type == BackendType.TODOIST) { + checked_button.sensitive = false; + is_loading = true; + Services.Todoist.get_default ().complete_item.begin (item, (obj, res) => { + if (Services.Todoist.get_default ().complete_item.end (res).status) { + Services.Database.get_default ().checked_toggled (item, old_checked); + is_loading = false; + checked_button.sensitive = true; + } + }); + } else if (item.project.backend_type == BackendType.CALDAV) { + checked_button.sensitive = false; + is_loading = true; + Services.CalDAV.get_default ().complete_item.begin (item, (obj, res) => { + if (Services.CalDAV.get_default ().complete_item.end (res).status) { + Services.Database.get_default ().checked_toggled (item, old_checked); + is_loading = false; + checked_button.sensitive = true; + } + }); + } + } + public void update_content (string content = "") { content_textview.buffer.text = content; } diff --git a/src/Layouts/ProjectRow.vala b/src/Layouts/ProjectRow.vala index 01470a3a6..a746d42f9 100644 --- a/src/Layouts/ProjectRow.vala +++ b/src/Layouts/ProjectRow.vala @@ -199,7 +199,7 @@ public class Layouts.ProjectRow : Gtk.ListBoxRow { Services.Settings.get_default ().settings.bind ("show-tasks-count", count_revealer, "reveal_child", GLib.SettingsBindFlags.DEFAULT); if (drag_n_drop) { - build_drag_and_drop (); + build_drag_and_drop.begin (); } if (show_subprojects) { diff --git a/src/Layouts/SectionRow.vala b/src/Layouts/SectionRow.vala index ce3e1c5de..6b421d34f 100644 --- a/src/Layouts/SectionRow.vala +++ b/src/Layouts/SectionRow.vala @@ -34,8 +34,6 @@ public class Layouts.SectionRow : Gtk.ListBoxRow { private Gtk.Label count_label; private Gtk.Revealer count_revealer; private Gtk.Revealer placeholder_revealer; - private Gtk.Grid drop_widget; - private Gtk.Revealer drop_widget_revealer; public bool is_inbox_section { get { @@ -422,10 +420,6 @@ public class Layouts.SectionRow : Gtk.ListBoxRow { }); } - private void check_drop_widget () { - drop_widget_revealer.reveal_child = items.size <= 0; - } - private void show_completed_changed () { if (section.project.show_completed) { add_completed_items (); diff --git a/src/Views/Project/Board.vala b/src/Views/Project/Board.vala index 7654d545c..4b87dc0e5 100644 --- a/src/Views/Project/Board.vala +++ b/src/Views/Project/Board.vala @@ -65,6 +65,16 @@ public class Views.Board : Adw.Bin { return item1.section.section_order - item2.section.section_order; }); + flowbox.set_filter_func ((child) => { + Layouts.SectionBoard item = ((Layouts.SectionBoard) child); + + if (item.is_inbox_section) { + return false; + } + + return !item.section.hidded; + }); + var flowbox_grid = new Adw.Bin () { vexpand = true, margin_top = 12, @@ -103,6 +113,7 @@ public class Views.Board : Adw.Bin { project.section_sort_order_changed.connect (() => { flowbox.invalidate_sort (); + flowbox.invalidate_filter (); }); Services.Database.get_default ().section_moved.connect ((section, old_project_id) => { diff --git a/src/Views/Project/List.vala b/src/Views/Project/List.vala index 63f05a79e..0aa3eae6c 100644 --- a/src/Views/Project/List.vala +++ b/src/Views/Project/List.vala @@ -285,12 +285,10 @@ public class Views.List : Gtk.Grid { due_box.append (due_label); var due_date_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) { - margin_top = 6, - margin_end = 6 + margin_start = 21 }; due_date_box.append (due_box); - due_date_box.add_css_class ("description-box"); var due_revealer = new Gtk.Revealer () { transition_type = Gtk.RevealerTransitionType.SLIDE_DOWN diff --git a/src/Views/Project/Project.vala b/src/Views/Project/Project.vala index 59d472007..92e8ce6e5 100644 --- a/src/Views/Project/Project.vala +++ b/src/Views/Project/Project.vala @@ -218,6 +218,7 @@ public class Views.Project : Gtk.Grid { var schedule_item = new Widgets.ContextMenu.MenuItem (_("When?"), "planner-calendar"); var add_section_item = new Widgets.ContextMenu.MenuItem (_("Add Section"), "planner-section"); add_section_item.secondary_text = "S"; + var manage_item = new Widgets.ContextMenu.MenuItem (_("Manage Sections"), "ordered-list"); var filter_by_tags = new Widgets.ContextMenu.MenuItem (_("Filter by Labels"), "planner-tag"); var select_item = new Widgets.ContextMenu.MenuItem (_("Select"), "unordered-list"); @@ -235,6 +236,7 @@ public class Views.Project : Gtk.Grid { } menu_box.append (add_section_item); + menu_box.append (manage_item); menu_box.append (new Widgets.ContextMenu.MenuSeparator ()); menu_box.append (select_item); menu_box.append (paste_item); @@ -294,6 +296,12 @@ public class Views.Project : Gtk.Grid { prepare_new_section (); }); + manage_item.clicked.connect (() => { + popover.popdown (); + var dialog = new Dialogs.ManageSectionOrder (project); + dialog.show (); + }); + paste_item.clicked.connect (() => { popover.popdown (); Gdk.Clipboard clipboard = Gdk.Display.get_default ().get_clipboard (); diff --git a/src/Widgets/MultiSelectToolbar.vala b/src/Widgets/MultiSelectToolbar.vala index 906d34bd5..948b88f50 100644 --- a/src/Widgets/MultiSelectToolbar.vala +++ b/src/Widgets/MultiSelectToolbar.vala @@ -156,7 +156,7 @@ public class Widgets.MultiSelectToolbar : Adw.Bin { unselect_all (); } else if (project.backend_type == BackendType.TODOIST) { done_button.is_loading = true; - Services.Todoist.get_default ().update_items (objects, (obj, res) => { + Services.Todoist.get_default ().update_items.begin (objects, (obj, res) => { Services.Todoist.get_default ().update_items.end (res); foreach (Objects.Item item in objects) {