Profile: add relationship button

This commit is contained in:
Bleak Grey 2021-07-25 18:35:51 +03:00
parent 45e6de7342
commit f774eb977e
8 changed files with 99 additions and 85 deletions

View File

@ -94,13 +94,13 @@
<!-- <section> -->
<submenu id="copy-menu">
<attribute name="label" translatable="yes">Copy</attribute>
<attribute name="label" translatable="yes">Share</attribute>
<item>
<attribute name="label" translatable="yes">Profile Handle</attribute>
<attribute name="label" translatable="yes">Copy Profile Handle</attribute>
<attribute name="action">view.copy_handle</attribute>
</item>
<item>
<attribute name="label" translatable="yes">Profile Link</attribute>
<attribute name="label" translatable="yes">Copy Profile Link</attribute>
<attribute name="action">view.copy_handle</attribute>
</item>
</submenu>

View File

@ -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',

View File

@ -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 {

View File

@ -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) {

View File

@ -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 {

View File

@ -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)");

View File

@ -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");

View File

@ -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;
}
}
}