Implement blocking, muting and mentioning accounts

This commit is contained in:
bleakgrey 2018-05-01 16:16:07 +03:00
parent 2b1e0fa68c
commit 75afde71e4
4 changed files with 146 additions and 57 deletions

View File

@ -1,5 +1,7 @@
public class Tootle.Account{
public abstract signal void updated ();
public int64 id;
public string username;
public string acct;
@ -11,6 +13,8 @@ public class Tootle.Account{
public int64 followers_count;
public int64 following_count;
public int64 statuses_count;
public Relationship? rs;
public Account(int64 id){
this.id = id;
@ -28,8 +32,6 @@ public class Tootle.Account{
account.note = obj.get_string_member ("note");
account.avatar = obj.get_string_member ("avatar");
account.header = obj.get_string_member ("header");
if ("missing.png" in account.header)
account.header = "https://files.mastodon.social/accounts/headers/000/320/555/original/cebce998b571acf2.jpeg";
account.url = obj.get_string_member ("url");
account.followers_count = obj.get_int_member ("followers_count");
@ -38,5 +40,84 @@ public class Tootle.Account{
return account;
}
public bool is_self (){
return id == Tootle.accounts.current.id;
}
public Soup.Message get_relationship (){
var url = "%s/api/v1/accounts/relationships?id=%lld".printf (Tootle.settings.instance_url, id);
var msg = new Soup.Message("GET", url);
msg.priority = Soup.MessagePriority.HIGH;
Tootle.network.queue(msg, (sess, mess) => {
try{
var root = Tootle.network.parse_array (mess).get_object_element (0);
rs = Relationship.parse (root);
updated ();
}
catch (GLib.Error e) {
warning ("Can't get account relationship:");
warning (e.message);
}
});
return msg;
}
public Soup.Message set_following (bool follow = true){
var action = follow ? "follow" : "unfollow";
var url = "%s/api/v1/accounts/%lld/%s".printf (Tootle.settings.instance_url, id, action);
var msg = new Soup.Message("POST", url);
msg.priority = Soup.MessagePriority.HIGH;
Tootle.network.queue(msg, (sess, mess) => {
try{
var root = Tootle.network.parse (mess);
rs = Relationship.parse (root);
updated ();
}
catch (GLib.Error e) {
Tootle.app.error (_("Error"), e.message);
warning (e.message);
}
});
return msg;
}
public Soup.Message set_muted (bool mute = true){
var action = mute ? "mute" : "unmute";
var url = "%s/api/v1/accounts/%lld/%s".printf (Tootle.settings.instance_url, id, action);
var msg = new Soup.Message("POST", url);
msg.priority = Soup.MessagePriority.HIGH;
Tootle.network.queue(msg, (sess, mess) => {
try{
var root = Tootle.network.parse (mess);
rs = Relationship.parse (root);
updated ();
}
catch (GLib.Error e) {
Tootle.app.error (_("Error"), e.message);
warning (e.message);
}
});
return msg;
}
public Soup.Message set_blocked (bool block = true){
var action = block ? "block" : "unblock";
var url = "%s/api/v1/accounts/%lld/%s".printf (Tootle.settings.instance_url, id, action);
var msg = new Soup.Message("POST", url);
msg.priority = Soup.MessagePriority.HIGH;
Tootle.network.queue(msg, (sess, mess) => {
try{
var root = Tootle.network.parse (mess);
rs = Relationship.parse (root);
updated ();
}
catch (GLib.Error e) {
Tootle.app.error (_("Error"), e.message);
warning (e.message);
}
});
return msg;
}
}

View File

@ -97,13 +97,15 @@ public class Tootle.PostDialog : Gtk.Dialog {
counter.label = remain.to_string ();
}
public static void open (Gtk.Window? parent){
public static void open (Gtk.Window? parent, string? text = null){
if(dialog == null){
dialog = new PostDialog (parent);
dialog.destroy.connect (() => {
dialog = null;
});
dialog.show_all ();
if (text != null)
dialog.text.buffer.text = text;
}
}

View File

@ -20,7 +20,7 @@ public class Tootle.NetManager : GLib.Object{
session.ssl_strict = true;
session.ssl_use_system_ca_file = true;
session.timeout = 15;
session.timeout = 25;
}
public NetManager(){

View File

@ -4,7 +4,6 @@ using Granite;
public class Tootle.AccountView : Tootle.HomeView {
Account account;
Relationship? relationship;
Gtk.Grid header;
Gtk.Grid header_image;
@ -16,7 +15,14 @@ public class Tootle.AccountView : Tootle.HomeView {
Gtk.Grid counters;
Gtk.Box actions;
Gtk.Button button_follow;
Gtk.Button button_more;
Gtk.Menu menu;
Gtk.MenuItem menu_edit;
Gtk.MenuItem menu_mention;
Gtk.MenuItem menu_mute;
Gtk.MenuItem menu_block;
Gtk.MenuItem menu_report;
Gtk.MenuButton button_menu;
public override void pre_construct () {
header = new Gtk.Grid ();
@ -60,12 +66,33 @@ public class Tootle.AccountView : Tootle.HomeView {
header_image.get_style_context ().add_class ("header");
header.attach (header_image, 0, 0, 2, 2);
menu = new Gtk.Menu ();
menu_edit = new Gtk.MenuItem.with_label (_("Edit Profile"));
menu_mention = new Gtk.MenuItem.with_label (_("Mention"));
menu_report = new Gtk.MenuItem.with_label (_("Report"));
menu_mute = new Gtk.MenuItem.with_label (_("Mute"));
menu_block = new Gtk.MenuItem.with_label (_("Block"));
menu.add (menu_mention);
menu.add (new Gtk.SeparatorMenuItem ());
menu.add (menu_mute);
menu.add (menu_block);
//menu.add (menu_report); //TODO: Report users
menu.add (menu_edit); //TODO: Edit profile
menu.show_all ();
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);
button_menu = new Gtk.MenuButton ();
button_menu.image = new Gtk.Image.from_icon_name ("view-more-symbolic", Gtk.IconSize.LARGE_TOOLBAR);
button_menu.tooltip_text = _("menu Actions");
button_menu.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
button_menu.set_focus_on_click (false);
button_menu.can_default = false;
button_menu.can_focus = false;
button_menu.popup = menu;
actions.pack_end(button_menu, false, false, 0);
actions.pack_end(button_follow, false, false, 0);
button_menu.hide ();
button_follow.hide ();
header.attach (actions, 0, 0, 2, 2);
view.pack_start (header, false, false, 0);
@ -74,11 +101,7 @@ public class Tootle.AccountView : Tootle.HomeView {
public AccountView (Account acc) {
base ("account_"+acc.id.to_string ());
account = acc;
display_name.label = "<b>%s</b>".printf (account.display_name);
username.label = "@" + account.acct;
note.label = Utils.escape_html (account.note);
Tootle.cache.load_avatar (account.avatar, avatar, 128);
account.updated.connect(rebind);
add_counter (_("TOOTS"), 1, account.statuses_count);
add_counter (_("FOLLOWS"), 2, account.following_count);
@ -90,17 +113,28 @@ public class Tootle.AccountView : Tootle.HomeView {
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 ());
menu_mention.activate.connect (() => PostDialog.open (Tootle.window, "@%s ".printf (account.acct)));
menu_mute.activate.connect (() => account.set_muted (!account.rs.muting));
menu_block.activate.connect (() => account.set_blocked (!account.rs.blocking));
button_follow.clicked.connect (() => account.set_following (!account.rs.following));
request_relationship ();
rebind ();
account.get_relationship ();
request ();
}
public void rebind (){
if (relationship != null && !is_owned ()) {
display_name.label = "<b>%s</b>".printf (account.display_name);
username.label = "@" + account.acct;
note.label = Utils.escape_html (account.note);
button_follow.visible = !account.is_self ();
Tootle.cache.load_avatar (account.avatar, avatar, 128);
menu_edit.visible = account.is_self ();
if (account.rs != null && !account.is_self ()) {
button_follow.show ();
if (relationship.following) {
if (account.rs.following) {
button_follow.tooltip_text = _("Unfollow");
(button_follow.get_image () as Gtk.Image).icon_name = "close-symbolic";
}
@ -109,6 +143,13 @@ public class Tootle.AccountView : Tootle.HomeView {
(button_follow.get_image () as Gtk.Image).icon_name = "contact-new-symbolic";
}
}
if (account.rs != null){
button_menu.show ();
menu_block.label = account.rs.blocking ? _("Unblock") : _("Block");
menu_mute.label = account.rs.muting ? _("Unmute") : _("Mute");
menu_report.visible = menu_mute.visible = menu_block.visible = !account.is_self ();
}
}
private Gtk.Button add_counter (string name, int? i = null, int64? val = null) {
@ -132,10 +173,6 @@ public class Tootle.AccountView : Tootle.HomeView {
return btn;
}
public bool is_owned (){
return account.id == Tootle.accounts.current.id;
}
public override bool is_status_owned (Status status){
return status.get_formal ().account.id == account.id;
}
@ -150,42 +187,10 @@ 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);
msg.priority = Soup.MessagePriority.HIGH;
Tootle.network.queue(msg, (sess, mess) => {
try{
var root = Tootle.network.parse (mess);
@ -202,6 +207,7 @@ public class Tootle.AccountView : Tootle.HomeView {
public static void open_from_name (string name){
var url = "%s/api/v1/accounts/search?limit=1&q=%s".printf (Tootle.settings.instance_url, name);
var msg = new Soup.Message("GET", url);
msg.priority = Soup.MessagePriority.HIGH;
Tootle.network.queue(msg, (sess, mess) => {
try{
var node = Tootle.network.parse_array (mess).get_element (0);