2018-04-25 15:16:57 +02:00
|
|
|
using Gtk;
|
|
|
|
using Granite;
|
|
|
|
|
2018-05-19 14:21:03 +02:00
|
|
|
public class Tootle.AccountView : TimelineView {
|
2018-04-25 15:16:57 +02:00
|
|
|
|
2018-06-02 11:27:19 +02:00
|
|
|
const int AVATAR_SIZE = 128;
|
2018-04-25 15:16:57 +02:00
|
|
|
Account account;
|
|
|
|
|
2018-04-25 16:30:44 +02:00
|
|
|
Gtk.Grid header;
|
|
|
|
Gtk.Grid header_image;
|
2018-04-28 19:16:23 +02:00
|
|
|
Gtk.Box header_info;
|
2018-04-25 15:16:57 +02:00
|
|
|
Granite.Widgets.Avatar avatar;
|
2018-06-06 16:19:11 +02:00
|
|
|
RichLabel display_name;
|
2018-04-25 15:16:57 +02:00
|
|
|
Gtk.Label username;
|
2018-05-09 17:59:58 +02:00
|
|
|
Gtk.Label relationship;
|
2018-06-06 16:19:11 +02:00
|
|
|
RichLabel note;
|
2018-04-25 16:30:44 +02:00
|
|
|
Gtk.Grid counters;
|
2018-04-30 19:56:02 +02:00
|
|
|
Gtk.Box actions;
|
|
|
|
Gtk.Button button_follow;
|
2018-05-01 15:16:07 +02:00
|
|
|
|
|
|
|
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;
|
2018-04-25 15:16:57 +02:00
|
|
|
|
2018-04-26 16:05:03 +02:00
|
|
|
public override void pre_construct () {
|
2018-04-25 16:30:44 +02:00
|
|
|
header = new Gtk.Grid ();
|
2018-04-28 19:16:23 +02:00
|
|
|
header_info = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
|
2018-05-09 17:59:58 +02:00
|
|
|
header_info.margin = 12;
|
2018-04-30 19:56:02 +02:00
|
|
|
actions = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0);
|
|
|
|
actions.hexpand = false;
|
|
|
|
actions.halign = Gtk.Align.END;
|
|
|
|
actions.vexpand = false;
|
|
|
|
actions.valign = Gtk.Align.START;
|
2018-05-09 17:59:58 +02:00
|
|
|
actions.margin = 12;
|
|
|
|
|
|
|
|
relationship = new Gtk.Label ("");
|
|
|
|
relationship.get_style_context ().add_class ("relationship");
|
|
|
|
relationship.halign = Gtk.Align.START;
|
|
|
|
relationship.valign = Gtk.Align.START;
|
|
|
|
relationship.margin = 12;
|
|
|
|
header.attach (relationship, 0, 0, 1, 1);
|
2018-04-28 19:16:23 +02:00
|
|
|
|
2018-06-02 11:27:19 +02:00
|
|
|
avatar = new Granite.Widgets.Avatar.with_default_icon (AVATAR_SIZE);
|
2018-04-25 16:30:44 +02:00
|
|
|
avatar.hexpand = true;
|
2018-05-09 17:59:58 +02:00
|
|
|
avatar.margin_bottom = 6;
|
2018-04-28 19:16:23 +02:00
|
|
|
header_info.pack_start(avatar, false, false, 0);
|
2018-04-25 15:16:57 +02:00
|
|
|
|
2018-04-28 18:27:10 +02:00
|
|
|
display_name = new RichLabel ("");
|
2018-04-25 15:16:57 +02:00
|
|
|
display_name.get_style_context ().add_class (Granite.STYLE_CLASS_H2_LABEL);
|
2018-04-28 19:16:23 +02:00
|
|
|
header_info.pack_start(display_name, false, false, 0);
|
2018-04-25 16:30:44 +02:00
|
|
|
|
2018-04-25 15:16:57 +02:00
|
|
|
username = new Gtk.Label ("");
|
2018-04-28 19:16:23 +02:00
|
|
|
header_info.pack_start(username, false, false, 0);
|
2018-04-25 16:30:44 +02:00
|
|
|
|
2018-04-28 18:27:10 +02:00
|
|
|
note = new RichLabel ("");
|
2018-04-30 19:56:02 +02:00
|
|
|
note.set_line_wrap (true);
|
|
|
|
note.selectable = true;
|
2018-05-09 17:59:58 +02:00
|
|
|
note.margin_top = 12;
|
2018-04-30 19:56:02 +02:00
|
|
|
note.can_focus = false;
|
2018-04-25 15:16:57 +02:00
|
|
|
note.justify = Gtk.Justification.CENTER;
|
2018-04-28 19:16:23 +02:00
|
|
|
header_info.pack_start(note, false, false, 0);
|
|
|
|
header_info.show_all ();
|
|
|
|
header.attach (header_info, 0, 0, 1, 1);
|
2018-04-25 16:30:44 +02:00
|
|
|
|
|
|
|
counters = new Gtk.Grid ();
|
|
|
|
counters.column_homogeneous = true;
|
2018-04-28 19:16:23 +02:00
|
|
|
counters.get_style_context ().add_class ("header-counters");
|
|
|
|
header.attach (counters, 0, 1, 1, 1);
|
2018-04-25 16:30:44 +02:00
|
|
|
|
|
|
|
header_image = new Gtk.Grid ();
|
|
|
|
header_image.get_style_context ().add_class ("header");
|
2018-04-28 19:16:23 +02:00
|
|
|
header.attach (header_image, 0, 0, 2, 2);
|
2018-04-25 15:16:57 +02:00
|
|
|
|
2018-05-01 15:16:07 +02:00
|
|
|
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);
|
2018-05-31 14:13:21 +02:00
|
|
|
//menu.add (new Gtk.SeparatorMenuItem ());
|
2018-05-01 15:16:07 +02:00
|
|
|
menu.add (menu_mute);
|
|
|
|
menu.add (menu_block);
|
|
|
|
//menu.add (menu_report); //TODO: Report users
|
2018-05-31 14:13:21 +02:00
|
|
|
//menu.add (menu_edit); //TODO: Edit profile
|
2018-05-01 15:16:07 +02:00
|
|
|
menu.show_all ();
|
|
|
|
|
2018-04-30 19:56:02 +02:00
|
|
|
button_follow = add_counter ("contact-new-symbolic");
|
2018-05-01 15:16:07 +02:00
|
|
|
button_menu = new Gtk.MenuButton ();
|
|
|
|
button_menu.image = new Gtk.Image.from_icon_name ("view-more-symbolic", Gtk.IconSize.LARGE_TOOLBAR);
|
2018-05-09 17:59:58 +02:00
|
|
|
button_menu.tooltip_text = _("More Actions");
|
2018-05-01 15:16:07 +02:00
|
|
|
button_menu.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
|
2018-10-23 12:28:42 +02:00
|
|
|
(button_menu as Gtk.Widget).set_focus_on_click (false);
|
2018-05-01 15:16:07 +02:00
|
|
|
button_menu.can_default = false;
|
|
|
|
button_menu.can_focus = false;
|
|
|
|
button_menu.popup = menu;
|
|
|
|
actions.pack_end(button_menu, false, false, 0);
|
2018-04-30 19:56:02 +02:00
|
|
|
actions.pack_end(button_follow, false, false, 0);
|
2018-05-01 15:16:07 +02:00
|
|
|
button_menu.hide ();
|
|
|
|
button_follow.hide ();
|
2018-04-30 19:56:02 +02:00
|
|
|
header.attach (actions, 0, 0, 2, 2);
|
|
|
|
|
2018-04-25 15:16:57 +02:00
|
|
|
view.pack_start (header, false, false, 0);
|
|
|
|
}
|
|
|
|
|
2018-04-26 16:05:03 +02:00
|
|
|
public AccountView (Account acc) {
|
2018-05-19 14:21:03 +02:00
|
|
|
base ("");
|
2018-04-25 15:16:57 +02:00
|
|
|
account = acc;
|
2018-05-01 15:16:07 +02:00
|
|
|
account.updated.connect(rebind);
|
2018-04-25 16:30:44 +02:00
|
|
|
|
2018-05-31 14:13:21 +02:00
|
|
|
add_counter (_("Toots"), 1, account.statuses_count);
|
|
|
|
add_counter (_("Follows"), 2, account.following_count).clicked.connect (() => {
|
2018-10-23 12:05:24 +02:00
|
|
|
var view = new FollowingView (account);
|
2018-06-06 16:19:11 +02:00
|
|
|
window.open_view (view);
|
2018-05-19 14:21:03 +02:00
|
|
|
});
|
2018-05-31 14:13:21 +02:00
|
|
|
add_counter (_("Followers"), 3, account.followers_count).clicked.connect (() => {
|
2018-10-23 12:05:24 +02:00
|
|
|
var view = new FollowersView (account);
|
2018-06-06 16:19:11 +02:00
|
|
|
window.open_view (view);
|
2018-05-19 14:21:03 +02:00
|
|
|
});
|
2018-04-30 19:56:02 +02:00
|
|
|
|
2018-04-25 16:30:44 +02:00
|
|
|
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);
|
2018-04-26 16:05:03 +02:00
|
|
|
|
2018-05-11 13:28:49 +02:00
|
|
|
menu_mention.activate.connect (() => PostDialog.open ("@%s ".printf (account.acct)));
|
2018-05-01 15:16:07 +02:00
|
|
|
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));
|
2018-04-30 19:56:02 +02:00
|
|
|
|
2018-05-01 15:16:07 +02:00
|
|
|
rebind ();
|
|
|
|
account.get_relationship ();
|
2018-04-26 16:05:03 +02:00
|
|
|
request ();
|
2018-04-25 16:30:44 +02:00
|
|
|
}
|
|
|
|
|
2018-06-02 11:27:19 +02:00
|
|
|
|
|
|
|
|
2018-04-30 19:56:02 +02:00
|
|
|
public void rebind (){
|
2018-06-06 16:19:11 +02:00
|
|
|
display_name.set_label ("<b>%s</b>".printf (account.display_name));
|
2018-05-01 15:16:07 +02:00
|
|
|
username.label = "@" + account.acct;
|
2018-06-06 16:19:11 +02:00
|
|
|
note.set_label (Html.simplify (account.note));
|
2018-05-01 15:16:07 +02:00
|
|
|
button_follow.visible = !account.is_self ();
|
2018-06-06 16:19:11 +02:00
|
|
|
network.load_avatar (account.avatar, avatar, 128);
|
2018-05-01 15:16:07 +02:00
|
|
|
|
|
|
|
menu_edit.visible = account.is_self ();
|
|
|
|
|
|
|
|
if (account.rs != null && !account.is_self ()) {
|
2018-04-30 19:56:02 +02:00
|
|
|
button_follow.show ();
|
2018-05-01 15:16:07 +02:00
|
|
|
if (account.rs.following) {
|
2018-04-30 19:56:02 +02:00
|
|
|
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";
|
|
|
|
}
|
|
|
|
}
|
2018-05-01 15:16:07 +02:00
|
|
|
|
|
|
|
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 ();
|
2018-05-09 17:59:58 +02:00
|
|
|
|
|
|
|
var rs_label = get_relationship_label ();
|
|
|
|
if (rs_label != null) {
|
|
|
|
relationship.label = rs_label;
|
|
|
|
relationship.show ();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
relationship.hide ();
|
2018-05-01 15:16:07 +02:00
|
|
|
}
|
2018-05-09 17:59:58 +02:00
|
|
|
else
|
|
|
|
relationship.hide ();
|
2018-04-30 19:56:02 +02:00
|
|
|
}
|
|
|
|
|
2018-10-23 12:05:24 +02:00
|
|
|
public override bool is_status_owned (Status status) {
|
2018-05-31 14:13:21 +02:00
|
|
|
return status.is_owned ();
|
2018-05-21 17:23:31 +02:00
|
|
|
}
|
|
|
|
|
2018-04-30 19:56:02 +02:00
|
|
|
private Gtk.Button add_counter (string name, int? i = null, int64? val = null) {
|
|
|
|
Gtk.Button btn;
|
|
|
|
if (val != null){
|
|
|
|
btn = new Gtk.Button ();
|
2018-05-31 14:13:21 +02:00
|
|
|
var label = new Gtk.Label ("<b>%s</b>\n%s".printf (name.up (), val.to_string ()));
|
2018-04-30 19:56:02 +02:00
|
|
|
label.justify = Gtk.Justification.CENTER;
|
2018-05-31 14:13:21 +02:00
|
|
|
label.use_markup = true;
|
|
|
|
label.margin = 8;
|
2018-04-30 19:56:02 +02:00
|
|
|
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);
|
2018-10-23 12:28:42 +02:00
|
|
|
(btn as Gtk.Widget).set_focus_on_click (false);
|
2018-04-30 19:56:02 +02:00
|
|
|
btn.can_default = false;
|
|
|
|
btn.can_focus = false;
|
|
|
|
|
|
|
|
if (i != null)
|
|
|
|
counters.attach (btn, i, 1, 1, 1);
|
|
|
|
return btn;
|
|
|
|
}
|
|
|
|
|
2018-05-19 15:55:41 +02:00
|
|
|
public override bool is_empty () {
|
|
|
|
return view.get_children ().length () <= 2;
|
|
|
|
}
|
|
|
|
|
2018-05-05 17:38:01 +02:00
|
|
|
public override string get_url () {
|
2018-05-19 14:21:03 +02:00
|
|
|
if (page_next != null)
|
|
|
|
return page_next;
|
2018-04-26 16:05:03 +02:00
|
|
|
|
2018-06-06 16:19:11 +02:00
|
|
|
var url = "%s/api/v1/accounts/%lld/statuses?limit=%i".printf (accounts.formal.instance, account.id, this.limit);
|
2018-04-26 16:05:03 +02:00
|
|
|
return url;
|
|
|
|
}
|
|
|
|
|
2018-05-09 17:59:58 +02:00
|
|
|
public override void request () {
|
2018-05-05 17:38:01 +02:00
|
|
|
if(account != null)
|
|
|
|
base.request ();
|
|
|
|
}
|
|
|
|
|
2018-05-09 17:59:58 +02:00
|
|
|
private string? get_relationship_label () {
|
|
|
|
if (account.rs.requested)
|
|
|
|
return _("Sent follow request");
|
|
|
|
else if (account.rs.blocking)
|
|
|
|
return _("Blocked");
|
|
|
|
else if (account.rs.followed_by)
|
|
|
|
return _("Follows you");
|
|
|
|
else if (account.rs.domain_blocking)
|
|
|
|
return _("Blocking this instance");
|
|
|
|
else
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2018-04-28 18:27:10 +02:00
|
|
|
public static void open_from_id (int64 id){
|
2018-06-06 16:19:11 +02:00
|
|
|
var url = "%s/api/v1/accounts/%lld".printf (accounts.formal.instance, id);
|
2018-04-28 18:27:10 +02:00
|
|
|
var msg = new Soup.Message("GET", url);
|
2018-05-01 15:16:07 +02:00
|
|
|
msg.priority = Soup.MessagePriority.HIGH;
|
2018-06-02 10:37:28 +02:00
|
|
|
network.queue (msg, (sess, mess) => {
|
2018-04-28 18:27:10 +02:00
|
|
|
try{
|
2018-06-02 10:37:28 +02:00
|
|
|
var root = network.parse (mess);
|
2018-04-28 18:27:10 +02:00
|
|
|
var acc = Account.parse (root);
|
2018-05-05 17:38:01 +02:00
|
|
|
Tootle.window.open_view (new AccountView (acc));
|
2018-04-28 18:27:10 +02:00
|
|
|
}
|
|
|
|
catch (GLib.Error e) {
|
|
|
|
warning ("Can't update feed");
|
|
|
|
warning (e.message);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-04-28 18:41:35 +02:00
|
|
|
public static void open_from_name (string name){
|
2018-06-06 16:19:11 +02:00
|
|
|
var url = "%s/api/v1/accounts/search?limit=1&q=%s".printf (accounts.formal.instance, name);
|
2018-04-28 18:41:35 +02:00
|
|
|
var msg = new Soup.Message("GET", url);
|
2018-05-01 15:16:07 +02:00
|
|
|
msg.priority = Soup.MessagePriority.HIGH;
|
2018-06-02 10:37:28 +02:00
|
|
|
network.queue (msg, (sess, mess) => {
|
2018-04-28 18:41:35 +02:00
|
|
|
try{
|
2018-06-02 10:37:28 +02:00
|
|
|
var node = network.parse_array (mess).get_element (0);
|
2018-04-28 18:41:35 +02:00
|
|
|
var object = node.get_object ();
|
|
|
|
if (object != null){
|
|
|
|
var acc = Account.parse(object);
|
2018-06-02 10:37:28 +02:00
|
|
|
window.open_view (new AccountView (acc));
|
2018-04-28 18:41:35 +02:00
|
|
|
}
|
|
|
|
else
|
2018-06-02 10:37:28 +02:00
|
|
|
app.toast (_("User not found"));
|
2018-04-28 18:41:35 +02:00
|
|
|
}
|
|
|
|
catch (GLib.Error e) {
|
|
|
|
warning (e.message);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2018-04-25 15:16:57 +02:00
|
|
|
}
|