diff --git a/data/ui/menus.ui b/data/ui/menus.ui index 6e734c3..18d9013 100644 --- a/data/ui/menus.ui +++ b/data/ui/menus.ui @@ -94,13 +94,13 @@ - Copy + Share - Profile Handle + Copy Profile Handle view.copy_handle - Profile Link + Copy Profile Link view.copy_handle diff --git a/meson.build b/meson.build index 73b228a..78e2aae 100644 --- a/meson.build +++ b/meson.build @@ -1,4 +1,4 @@ -project('com.github.bleakgrey.tootle', 'vala', 'c', version: '2.0-alpha1') +project('com.github.bleakgrey.tootle', 'vala', 'c', version: '2.0-alpha2') add_global_arguments([ '-DGETTEXT_PACKAGE="@0@"'.format(meson.project_name()), @@ -71,6 +71,7 @@ sources = files( 'src/Widgets/Attachment/Image.vala', 'src/Widgets/LockableToggleButton.vala', 'src/Widgets/StatusActionButton.vala', + 'src/Widgets/RelationshipButton.vala', 'src/Widgets/MarkupView.vala', 'src/Dialogs/Saveable.vala', 'src/Dialogs/NewAccount.vala', diff --git a/src/API/Entity.vala b/src/API/Entity.vala index fdfd693..59f3ccb 100644 --- a/src/API/Entity.vala +++ b/src/API/Entity.vala @@ -26,6 +26,7 @@ public class Tootle.Entity : GLib.Object, Widgetizable, Json.Serializable { } public void patch_specs (GLib.Object obj, ParamSpec[] specs) { + freeze_notify (); foreach (ParamSpec spec in specs) { var name = spec.get_name (); var defined = get_class ().find_property (name) != null; @@ -35,6 +36,7 @@ public class Tootle.Entity : GLib.Object, Widgetizable, Json.Serializable { base.set_property (name, val); } } + thaw_notify (); } public static Entity from_json (Type type, Json.Node node) throws Error { diff --git a/src/API/Relationship.vala b/src/API/Relationship.vala index 9302e18..4b480fa 100644 --- a/src/API/Relationship.vala +++ b/src/API/Relationship.vala @@ -1,5 +1,7 @@ public class Tootle.API.Relationship : Entity { + public signal void invalidated (); + public string id { get; set; default = ""; } public bool following { get; set; default = false; } public bool followed_by { get; set; default = false; } @@ -10,10 +12,6 @@ public class Tootle.API.Relationship : Entity { public bool blocking { get; set; default = false; } public bool domain_blocking { get; set; default = false; } - public static Relationship from (Json.Node node) throws Error { - return Entity.from_json (typeof (API.Relationship), node) as API.Relationship; - } - public Relationship.for_account (API.Account acc) { Object (id: acc.id); request (); @@ -32,9 +30,9 @@ public class Tootle.API.Relationship : Entity { } void invalidate (Json.Node node) throws Error { - var rs = Relationship.from (node); + var rs = Entity.from_json (typeof (API.Relationship), node) as API.Relationship; patch (rs); - notify_property ("id"); + invalidated (); } public void modify (string operation, string? param = null, string? val = null) { diff --git a/src/Views/ContentBase.vala b/src/Views/ContentBase.vala index 26c65a3..a7b57c2 100644 --- a/src/Views/ContentBase.vala +++ b/src/Views/ContentBase.vala @@ -6,9 +6,7 @@ public class Tootle.Views.ContentBase : Views.Base { protected ListBox content; public bool empty { - get { - return model.get_n_items () <= 0; - } + get { return model.get_n_items () <= 0; } } construct { diff --git a/src/Views/Profile.vala b/src/Views/Profile.vala index 74069f6..f6d4159 100644 --- a/src/Views/Profile.vala +++ b/src/Views/Profile.vala @@ -10,8 +10,7 @@ public class Tootle.Views.Profile : Views.Timeline { protected Cover cover; protected MenuButton menu_button; - protected Button rs_button; - protected SourceFunc? rs_button_action; + protected Widgets.RelationshipButton rs_button; protected SimpleAction media_action; protected SimpleAction replies_action; @@ -24,24 +23,6 @@ public class Tootle.Views.Profile : Views.Timeline { construct { cover = build_cover (); column_view.prepend (cover); - - // column_view.pack_start (hdr, false, false, 0); - // column_view.reorder_child (hdr, 0); - - // var handle = builder.get_object ("handle") as Widgets.RichLabel; - // profile.bind_property ("display-name", handle, "text", BindingFlags.SYNC_CREATE); - - // note_row = builder.get_object ("note_row") as ListBoxRow; - // var note = builder.get_object ("note") as Widgets.MarkupView; - // profile.bind_property ("note", note, "content", BindingFlags.SYNC_CREATE, (b, src, ref target) => { - // var text = (string) src; - // target.set_string (text); - // note_row.visible = text != ""; - // return true; - // }); - - // relationship = builder.get_object ("relationship") as Label; - // rs.notify["id"].connect (on_rs_updated); } public Profile (API.Account acc) { @@ -94,21 +75,6 @@ public class Tootle.Views.Profile : Views.Timeline { protected override void build_header () { base.build_header (); - // rs_button = new Widgets.AdaptiveButton (); - // rs_button.clicked.connect (() => { - // if (rs_button_action != null) { - // rs_button.sensitive = false; - // rs_button_action (); - // } - // }); - - // if (profile.id != accounts.active.id) - // header.pack_end (rs_button); - - // TODO: RS button - // var a = new Button (); - // a.label = _("Follow"); - // header.pack_start (a); menu_button = new MenuButton (); var menu_builder = new Builder.from_resource (@"$(Build.RESOURCES)ui/menus.ui"); @@ -117,6 +83,12 @@ public class Tootle.Views.Profile : Views.Timeline { menu_button.popover.width_request = 250; menu_button.icon_name = "view-more-symbolic"; header.pack_end (menu_button); + + rs_button = new Widgets.RelationshipButton () { + rs = this.rs + }; + if (profile.id != accounts.active.id) + header.pack_end (rs_button); } protected virtual Cover build_cover () { @@ -191,6 +163,7 @@ public class Tootle.Views.Profile : Views.Timeline { var block = v.get_boolean (); var q = block ? _("Block \"%s\"?") : _("Unblock \"%s\"?"); var yes = app.question (q.printf (profile.handle)); + warning (q); if (yes) rs.modify (block ? "block" : "unblock"); @@ -201,6 +174,7 @@ public class Tootle.Views.Profile : Views.Timeline { domain_blocking_action.change_state.connect (v => { var block = v.get_boolean (); var q = block ? _("Block Entire \"%s\"?") : _("Unblock Entire \"%s\"?"); + warning (q); var yes = app.question ( q.printf (profile.domain), _("Blocking a domain will:\n\n• Remove its public posts and notifications from your timelines\n• Remove its followers from your account\n• Prevent you from following its users") @@ -239,7 +213,8 @@ public class Tootle.Views.Profile : Views.Timeline { } } - void on_rs_updated () { + // TODO: RS badges + void on_rs_updated () { // var label = ""; // if (rs_button.sensitive = rs != null) { // if (rs.requested) @@ -264,40 +239,6 @@ public class Tootle.Views.Profile : Views.Timeline { invalidate_actions (false); } - void get_rs_button_state (ref string label, ref string icon_name, ref SourceFunc? fn) { - if (rs == null) return; - - if (rs.blocking) { - label = _("Unblock"); - icon_name = "view-reveal-symbolic"; - fn = () => { - blocking_action.change_state (false); - // rs_button.sensitive = true; - return true; - }; - return; - } - else if (rs.following || rs.requested) { - label = _("Unfollow"); - icon_name = "list-remove-symbolic"; - fn = () => { - rs.modify ("unfollow"); - return true; - }; - return; - } - else if (!rs.following) { - label = _("Follow"); - icon_name = "list-add-symbolic"; - fn = () => { - rs.modify ("follow"); - return true; - }; - return; - } - - } - public override Request append_params (Request req) { if (page_next == null && source == "statuses") { req.with_param ("exclude_replies", @"$(!include_replies)"); diff --git a/src/Widgets/Avatar.vala b/src/Widgets/Avatar.vala index 3571c6d..e734b82 100644 --- a/src/Widgets/Avatar.vala +++ b/src/Widgets/Avatar.vala @@ -14,8 +14,6 @@ public class Tootle.Widgets.Avatar : Button { } construct { - // construct_disposable (); - child = new Adw.Avatar (48, null, true); halign = valign = Align.CENTER; add_css_class ("flat"); diff --git a/src/Widgets/RelationshipButton.vala b/src/Widgets/RelationshipButton.vala new file mode 100644 index 0000000..28f909b --- /dev/null +++ b/src/Widgets/RelationshipButton.vala @@ -0,0 +1,76 @@ +using Gtk; + +public class Tootle.Widgets.RelationshipButton : Button { + + public API.Relationship? rs { get; set; } + protected SourceFunc? fn = null; + + construct { + notify["rs"].connect (on_bound); + clicked.connect (on_clicked); + } + + protected void on_bound () { + if (rs != null) { + rs.invalidated.connect (invalidate); + rs.request (); + } + invalidate (); + } + + public void on_clicked () { + if (fn != null) { + fn (); + fn = null; + } + } + + public void invalidate () { + if (rs == null) { + sensitive = false; + label = _("Follow"); + fn = null; + return; + } + + sensitive = true; + remove_css_class ("suggested-action"); + remove_css_class ("destructive-action"); + + if (rs.blocking || rs.domain_blocking) { + label = _("Unblock"); + // icon_name = "changes-allow-symbolic"; + fn = () => { + if (rs.domain_blocking) + activate_action ("domain_blocking", null); + else if (rs.blocking) + activate_action ("view.blocking", null); + return true; + }; + add_css_class ("destructive-action"); + return; + } + else if (rs.following || rs.requested) { + label = _("Unfollow"); + // icon_name = "list-remove-symbolic"; + fn = () => { + rs.modify ("unfollow"); + return true; + }; + add_css_class ("destructive-action"); + return; + } + else if (!rs.following) { + label = _("Follow"); + // icon_name = "list-add-symbolic"; + fn = () => { + rs.modify ("follow"); + return true; + }; + add_css_class ("suggested-action"); + return; + } + + } + +}