Implement account following

This commit is contained in:
bleakgrey 2018-04-30 20:56:02 +03:00
parent 51433abab8
commit 2b1e0fa68c
7 changed files with 132 additions and 19 deletions

View File

@ -22,7 +22,7 @@
.header{
background-size: cover;
background-position: 50%;
opacity: 0.2;
opacity: 0.15;
}
.header-counters{
background:rgba(255,255,255,.4);

View File

@ -26,6 +26,7 @@ executable(
'src/CacheManager.vala',
'src/Utils.vala',
'src/API/Account.vala',
'src/API/Relationship.vala',
'src/API/Mention.vala',
'src/API/Tag.vala',
'src/API/Status.vala',

29
src/API/Relationship.vala Normal file
View File

@ -0,0 +1,29 @@
public class Tootle.Relationship{
public int64 id;
public bool following;
public bool followed_by;
public bool blocking;
public bool muting;
public bool muting_notifications;
public bool requested;
public bool domain_blocking;
public Relationship(int64 id){
this.id = id;
}
public static Relationship parse (Json.Object obj){
var id = int64.parse (obj.get_string_member ("id"));
var relationship = new Relationship (id);
relationship.following = obj.get_boolean_member ("following");
relationship.followed_by = obj.get_boolean_member ("followed_by");
relationship.blocking = obj.get_boolean_member ("blocking");
relationship.muting = obj.get_boolean_member ("muting");
relationship.muting_notifications = obj.get_boolean_member ("muting_notifications");
relationship.requested = obj.get_boolean_member ("requested");
relationship.domain_blocking = obj.get_boolean_member ("domain_blocking");
return relationship;
}
}

View File

@ -6,7 +6,7 @@ public class Tootle.AccountManager : Object{
public abstract signal void added(Account account);
public abstract signal void removed(Account account);
private static Account current;
public Account current;
public AccountManager(){
Object();

View File

@ -2,9 +2,9 @@ using Gtk;
public class Tootle.MainWindow: Gtk.Window {
Tootle.HeaderBar header;
Gtk.Overlay overlay;
Granite.Widgets.Toast toast;
public Tootle.HeaderBar header;
public Stack primary_stack;
public Stack secondary_stack;

View File

@ -4,6 +4,7 @@ using Granite;
public class Tootle.AccountView : Tootle.HomeView {
Account account;
Relationship? relationship;
Gtk.Grid header;
Gtk.Grid header_image;
@ -13,16 +14,24 @@ public class Tootle.AccountView : Tootle.HomeView {
Gtk.Label username;
Tootle.RichLabel note;
Gtk.Grid counters;
Gtk.Box actions;
Gtk.Button button_follow;
Gtk.Button button_more;
public override void pre_construct () {
header = new Gtk.Grid ();
header_info = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
header_info.margin = 16;
actions = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0);
actions.hexpand = false;
actions.halign = Gtk.Align.END;
actions.vexpand = false;
actions.valign = Gtk.Align.START;
actions.margin = 16;
avatar = new Granite.Widgets.Avatar.with_default_icon (128);
avatar.hexpand = true;
avatar.margin = 16;
avatar.margin_bottom = 8;
header_info.pack_start(avatar, false, false, 0);
display_name = new RichLabel ("");
@ -30,14 +39,13 @@ public class Tootle.AccountView : Tootle.HomeView {
header_info.pack_start(display_name, false, false, 0);
username = new Gtk.Label ("");
username.get_style_context ().add_class (Granite.STYLE_CLASS_H3_LABEL);
header_info.pack_start(username, false, false, 0);
note = new RichLabel ("");
note.set_line_wrap (true);
note.selectable = true;
note.margin_top = 16;
note.get_style_context ().add_class (Granite.STYLE_CLASS_H3_LABEL);
note.set_line_wrap (true);
note.selectable = true;
note.margin_top = 16;
note.can_focus = false;
note.justify = Gtk.Justification.CENTER;
header_info.pack_start(note, false, false, 0);
header_info.show_all ();
@ -52,6 +60,14 @@ public class Tootle.AccountView : Tootle.HomeView {
header_image.get_style_context ().add_class ("header");
header.attach (header_image, 0, 0, 2, 2);
button_follow = add_counter ("contact-new-symbolic");
button_follow.hide ();
button_more = add_counter ("view-more-symbolic");
button_more.tooltip_text = _("More Actions");
actions.pack_end(button_more, false, false, 0);
actions.pack_end(button_follow, false, false, 0);
header.attach (actions, 0, 0, 2, 2);
view.pack_start (header, false, false, 0);
}
@ -67,24 +83,57 @@ public class Tootle.AccountView : Tootle.HomeView {
add_counter (_("TOOTS"), 1, account.statuses_count);
add_counter (_("FOLLOWS"), 2, account.following_count);
add_counter (_("FOLLOWERS"), 3, account.followers_count);
show_all ();
var stylesheet = ".header{background-image: url(\"%s\")}".printf (account.header);
var css_provider = Granite.Widgets.Utils.get_css_provider (stylesheet);
header_image.get_style_context ().add_provider (css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
button_follow.visible = !is_owned ();
button_follow.clicked.connect (() => toggle_follow ());
request_relationship ();
request ();
}
private void add_counter (string name, int i, int64 val) {
var label_name = new Gtk.Label (name);
label_name.margin_top = 8;
label_name.get_style_context ().add_class (Granite.STYLE_CLASS_H3_LABEL);
var label_val = new Gtk.Label (val.to_string ());
label_val.get_style_context ().add_class (Granite.STYLE_CLASS_H3_LABEL);
label_val.margin_bottom = 8;
counters.attach (label_name, i, 1, 1, 1);
counters.attach (label_val, i, 2, 1, 1);
public void rebind (){
if (relationship != null && !is_owned ()) {
button_follow.show ();
if (relationship.following) {
button_follow.tooltip_text = _("Unfollow");
(button_follow.get_image () as Gtk.Image).icon_name = "close-symbolic";
}
else{
button_follow.tooltip_text = _("Follow");
(button_follow.get_image () as Gtk.Image).icon_name = "contact-new-symbolic";
}
}
}
private Gtk.Button add_counter (string name, int? i = null, int64? val = null) {
Gtk.Button btn;
if (val != null){
btn = new Gtk.Button ();
var label = new Gtk.Label (name + "\n" + val.to_string ());
label.justify = Gtk.Justification.CENTER;
btn.add (label);
}
else
btn = new Gtk.Button.from_icon_name (name, Gtk.IconSize.LARGE_TOOLBAR);
btn.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
btn.set_focus_on_click (false);
btn.can_default = false;
btn.can_focus = false;
if (i != null)
counters.attach (btn, i, 1, 1, 1);
return btn;
}
public bool is_owned (){
return account.id == Tootle.accounts.current.id;
}
public override bool is_status_owned (Status status){
@ -101,6 +150,39 @@ public class Tootle.AccountView : Tootle.HomeView {
return url;
}
public void request_relationship (){
var url = "%s/api/v1/accounts/relationships?id=%lld".printf (Tootle.settings.instance_url, account.id);
var msg = new Soup.Message("GET", url);
Tootle.network.queue(msg, (sess, mess) => {
try{
var root = Tootle.network.parse_array (mess).get_object_element (0);
relationship = Relationship.parse (root);
rebind ();
}
catch (GLib.Error e) {
warning ("Can't get relationship:");
warning (e.message);
}
});
}
public void toggle_follow (){
var action = relationship.following ? "unfollow" : "follow";
var url = "%s/api/v1/accounts/%lld/%s".printf (Tootle.settings.instance_url, account.id, action);
var msg = new Soup.Message("POST", url);
Tootle.network.queue(msg, (sess, mess) => {
try{
var root = Tootle.network.parse (mess);
relationship = Relationship.parse (root);
rebind ();
}
catch (GLib.Error e) {
Tootle.app.error (_("Error"), e.message);
warning (e.message);
}
});
}
public static void open_from_id (int64 id){
var url = "%s/api/v1/accounts/%lld".printf (Tootle.settings.instance_url, id);
var msg = new Soup.Message("GET", url);

View File

@ -167,6 +167,7 @@ public class Tootle.StatusWidget : Gtk.EventBox {
var icon = new Gtk.Image.from_icon_name (icon_path, Gtk.IconSize.SMALL_TOOLBAR);
var button = new Gtk.ToggleButton ();
button.can_default = false;
button.set_focus_on_click (false);
button.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
button.add (icon);
return button;