Fix occasional broken RichLabels
This commit is contained in:
parent
2756afe74b
commit
a5c5ddbf04
|
@ -18,7 +18,6 @@ public class Tootle.Status {
|
||||||
public StatusVisibility visibility;
|
public StatusVisibility visibility;
|
||||||
public Status? reblog;
|
public Status? reblog;
|
||||||
public Mention[]? mentions;
|
public Mention[]? mentions;
|
||||||
public Tag[]? tags;
|
|
||||||
public Attachment[]? attachments;
|
public Attachment[]? attachments;
|
||||||
|
|
||||||
public Status(int64 id) {
|
public Status(int64 id) {
|
||||||
|
@ -66,15 +65,6 @@ public class Tootle.Status {
|
||||||
if (_mentions.length > 0)
|
if (_mentions.length > 0)
|
||||||
status.mentions = _mentions;
|
status.mentions = _mentions;
|
||||||
|
|
||||||
Tag[]? _tags = {};
|
|
||||||
obj.get_array_member ("tags").foreach_element ((array, i, node) => {
|
|
||||||
var object = node.get_object ();
|
|
||||||
if (object != null)
|
|
||||||
_tags += Tag.parse (object);
|
|
||||||
});
|
|
||||||
if (_tags.length > 0)
|
|
||||||
status.tags = _tags;
|
|
||||||
|
|
||||||
Attachment[]? _attachments = {};
|
Attachment[]? _attachments = {};
|
||||||
obj.get_array_member ("media_attachments").foreach_element ((array, i, node) => {
|
obj.get_array_member ("media_attachments").foreach_element ((array, i, node) => {
|
||||||
var object = node.get_object ();
|
var object = node.get_object ();
|
||||||
|
|
|
@ -1,20 +1,18 @@
|
||||||
public class Tootle.Desktop {
|
public class Tootle.Desktop {
|
||||||
// open a URI in the user's default browser
|
|
||||||
|
// Open a URI in the user's default browser
|
||||||
public static void open_url (string url) {
|
public static void open_url (string url) {
|
||||||
Gtk.show_uri (null, url, Gdk.CURRENT_TIME);
|
Gtk.show_uri (null, url, Gdk.CURRENT_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
// copy a string to the clipboard
|
// Copy a string to the clipboard
|
||||||
public static void copy (string str) {
|
public static void copy (string str) {
|
||||||
var display = Tootle.window.get_display ();
|
var display = window.get_display ();
|
||||||
var clipboard = Gtk.Clipboard.get_for_display (display, Gdk.SELECTION_CLIPBOARD);
|
var clipboard = Gtk.Clipboard.get_for_display (display, Gdk.SELECTION_CLIPBOARD);
|
||||||
var normalized = str
|
clipboard.set_text (RichLabel.restore_entities (str), -1);
|
||||||
.replace ("&", "&")
|
|
||||||
.replace ("'", "'");
|
|
||||||
clipboard.set_text (normalized, -1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// download a file from the web to a user's configured Downloads folder
|
// Download a file from the web to a user's configured Downloads folder
|
||||||
public static void download_file (string url) {
|
public static void download_file (string url) {
|
||||||
debug ("Downloading file: %s", url);
|
debug ("Downloading file: %s", url);
|
||||||
|
|
||||||
|
@ -23,7 +21,7 @@ public class Tootle.Desktop {
|
||||||
if (name == null)
|
if (name == null)
|
||||||
name = "unknown";
|
name = "unknown";
|
||||||
|
|
||||||
var dir_path = "%s/%s".printf (GLib.Environment.get_user_special_dir (UserDirectory.DOWNLOAD), Tootle.app.program_name);
|
var dir_path = "%s/%s".printf (GLib.Environment.get_user_special_dir (UserDirectory.DOWNLOAD), app.program_name);
|
||||||
var file_path = "%s/%s".printf (dir_path, name);
|
var file_path = "%s/%s".printf (dir_path, name);
|
||||||
|
|
||||||
var msg = new Soup.Message("GET", url);
|
var msg = new Soup.Message("GET", url);
|
||||||
|
@ -39,12 +37,13 @@ public class Tootle.Desktop {
|
||||||
FileOutputStream stream = file.create (FileCreateFlags.PRIVATE);
|
FileOutputStream stream = file.create (FileCreateFlags.PRIVATE);
|
||||||
stream.write (data);
|
stream.write (data);
|
||||||
}
|
}
|
||||||
Tootle.app.toast ("Media downloaded");
|
app.toast ("Media downloaded");
|
||||||
} catch (Error e) {
|
} catch (Error e) {
|
||||||
Tootle.app.toast (e.message);
|
app.toast (e.message);
|
||||||
warning ("Error: %s\n", e.message);
|
warning ("Error: %s\n", e.message);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Tootle.network.queue (msg);
|
network.queue (msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
public class Tootle.Html {
|
public class Tootle.Html {
|
||||||
|
|
||||||
public static string remove_tags (string content) {
|
public static string remove_tags (string content) {
|
||||||
var all_tags = new Regex("<(.|\n)*?>", RegexCompileFlags.CASELESS);
|
var all_tags = new Regex("<(.|\n)*?>", RegexCompileFlags.CASELESS);
|
||||||
return all_tags.replace(content, -1, 0, "");
|
return all_tags.replace(content, -1, 0, "");
|
||||||
|
@ -21,14 +22,9 @@ public class Tootle.Html {
|
||||||
return simplified;
|
return simplified;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static string escape_entities (string content) {
|
|
||||||
return content
|
|
||||||
.replace ("&", "&")
|
|
||||||
.replace ("'", "'");
|
|
||||||
}
|
|
||||||
|
|
||||||
public static string uri_encode (string content) {
|
public static string uri_encode (string content) {
|
||||||
var to_escape = ";&+";
|
var to_escape = ";&+";
|
||||||
return Soup.URI.encode (content, to_escape);
|
return Soup.URI.encode (content, to_escape);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,10 +10,10 @@ public class Tootle.AccountView : TimelineView {
|
||||||
Gtk.Grid header_image;
|
Gtk.Grid header_image;
|
||||||
Gtk.Box header_info;
|
Gtk.Box header_info;
|
||||||
Granite.Widgets.Avatar avatar;
|
Granite.Widgets.Avatar avatar;
|
||||||
Gtk.Label display_name;
|
RichLabel display_name;
|
||||||
Gtk.Label username;
|
Gtk.Label username;
|
||||||
Gtk.Label relationship;
|
Gtk.Label relationship;
|
||||||
Tootle.RichLabel note;
|
RichLabel note;
|
||||||
Gtk.Grid counters;
|
Gtk.Grid counters;
|
||||||
Gtk.Box actions;
|
Gtk.Box actions;
|
||||||
Gtk.Button button_follow;
|
Gtk.Button button_follow;
|
||||||
|
@ -115,11 +115,11 @@ public class Tootle.AccountView : TimelineView {
|
||||||
add_counter (_("Toots"), 1, account.statuses_count);
|
add_counter (_("Toots"), 1, account.statuses_count);
|
||||||
add_counter (_("Follows"), 2, account.following_count).clicked.connect (() => {
|
add_counter (_("Follows"), 2, account.following_count).clicked.connect (() => {
|
||||||
var view = new FollowingView (ref account);
|
var view = new FollowingView (ref account);
|
||||||
Tootle.window.open_view (view);
|
window.open_view (view);
|
||||||
});
|
});
|
||||||
add_counter (_("Followers"), 3, account.followers_count).clicked.connect (() => {
|
add_counter (_("Followers"), 3, account.followers_count).clicked.connect (() => {
|
||||||
var view = new FollowersView (ref account);
|
var view = new FollowersView (ref account);
|
||||||
Tootle.window.open_view (view);
|
window.open_view (view);
|
||||||
});
|
});
|
||||||
|
|
||||||
show_all ();
|
show_all ();
|
||||||
|
@ -141,11 +141,11 @@ public class Tootle.AccountView : TimelineView {
|
||||||
|
|
||||||
|
|
||||||
public void rebind (){
|
public void rebind (){
|
||||||
display_name.label = "<b>%s</b>".printf (Html.escape_entities(account.display_name));
|
display_name.set_label ("<b>%s</b>".printf (account.display_name));
|
||||||
username.label = "@" + account.acct;
|
username.label = "@" + account.acct;
|
||||||
note.label = Html.simplify (account.note);
|
note.set_label (Html.simplify (account.note));
|
||||||
button_follow.visible = !account.is_self ();
|
button_follow.visible = !account.is_self ();
|
||||||
Tootle.network.load_avatar (account.avatar, avatar, 128);
|
network.load_avatar (account.avatar, avatar, 128);
|
||||||
|
|
||||||
menu_edit.visible = account.is_self ();
|
menu_edit.visible = account.is_self ();
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ public class Tootle.AccountView : TimelineView {
|
||||||
if (page_next != null)
|
if (page_next != null)
|
||||||
return page_next;
|
return page_next;
|
||||||
|
|
||||||
var url = "%s/api/v1/accounts/%lld/statuses?limit=%i".printf (Tootle.accounts.formal.instance, account.id, this.limit);
|
var url = "%s/api/v1/accounts/%lld/statuses?limit=%i".printf (accounts.formal.instance, account.id, this.limit);
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +237,7 @@ public class Tootle.AccountView : TimelineView {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void open_from_id (int64 id){
|
public static void open_from_id (int64 id){
|
||||||
var url = "%s/api/v1/accounts/%lld".printf (Tootle.accounts.formal.instance, id);
|
var url = "%s/api/v1/accounts/%lld".printf (accounts.formal.instance, id);
|
||||||
var msg = new Soup.Message("GET", url);
|
var msg = new Soup.Message("GET", url);
|
||||||
msg.priority = Soup.MessagePriority.HIGH;
|
msg.priority = Soup.MessagePriority.HIGH;
|
||||||
network.queue (msg, (sess, mess) => {
|
network.queue (msg, (sess, mess) => {
|
||||||
|
@ -254,7 +254,7 @@ public class Tootle.AccountView : TimelineView {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void open_from_name (string name){
|
public static void open_from_name (string name){
|
||||||
var url = "%s/api/v1/accounts/search?limit=1&q=%s".printf (Tootle.accounts.formal.instance, name);
|
var url = "%s/api/v1/accounts/search?limit=1&q=%s".printf (accounts.formal.instance, name);
|
||||||
var msg = new Soup.Message("GET", url);
|
var msg = new Soup.Message("GET", url);
|
||||||
msg.priority = Soup.MessagePriority.HIGH;
|
msg.priority = Soup.MessagePriority.HIGH;
|
||||||
network.queue (msg, (sess, mess) => {
|
network.queue (msg, (sess, mess) => {
|
||||||
|
|
|
@ -5,11 +5,11 @@ public class Tootle.NotificationWidget : Gtk.Grid {
|
||||||
|
|
||||||
private Notification notification;
|
private Notification notification;
|
||||||
|
|
||||||
public Gtk.Separator? separator;
|
public Separator? separator;
|
||||||
private Gtk.Image image;
|
private Image image;
|
||||||
private Tootle.RichLabel label;
|
private RichLabel label;
|
||||||
private StatusWidget? status_widget;
|
private StatusWidget? status_widget;
|
||||||
private Gtk.Button dismiss;
|
private Button dismiss;
|
||||||
|
|
||||||
construct {
|
construct {
|
||||||
margin = 6;
|
margin = 6;
|
||||||
|
@ -37,7 +37,7 @@ public class Tootle.NotificationWidget : Gtk.Grid {
|
||||||
public NotificationWidget (Notification notification) {
|
public NotificationWidget (Notification notification) {
|
||||||
this.notification = notification;
|
this.notification = notification;
|
||||||
image.icon_name = notification.type.get_icon ();
|
image.icon_name = notification.type.get_icon ();
|
||||||
label.label = notification.type.get_desc (notification.account);
|
label.set_label (notification.type.get_desc (notification.account));
|
||||||
get_style_context ().add_class ("notification");
|
get_style_context ().add_class ("notification");
|
||||||
|
|
||||||
if (notification.status != null) {
|
if (notification.status != null) {
|
||||||
|
|
|
@ -5,11 +5,27 @@ public class Tootle.RichLabel : Gtk.Label {
|
||||||
public weak Mention[]? mentions;
|
public weak Mention[]? mentions;
|
||||||
|
|
||||||
public RichLabel (string text) {
|
public RichLabel (string text) {
|
||||||
label = text;
|
set_label (text);
|
||||||
set_use_markup (true);
|
set_use_markup (true);
|
||||||
activate_link.connect (open_link);
|
activate_link.connect (open_link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string escape_entities (string content) {
|
||||||
|
return content
|
||||||
|
.replace ("&", "&")
|
||||||
|
.replace ("'", "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string restore_entities (string content) {
|
||||||
|
return content
|
||||||
|
.replace ("&", "&")
|
||||||
|
.replace ("'", "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
public new void set_label (string text) {
|
||||||
|
base.set_markup (escape_entities (text));
|
||||||
|
}
|
||||||
|
|
||||||
public void wrap_words () {
|
public void wrap_words () {
|
||||||
halign = Gtk.Align.START;
|
halign = Gtk.Align.START;
|
||||||
single_line_mode = false;
|
single_line_mode = false;
|
||||||
|
|
|
@ -11,12 +11,12 @@ public class Tootle.StatusWidget : Gtk.EventBox {
|
||||||
public Gtk.Separator? separator;
|
public Gtk.Separator? separator;
|
||||||
public Gtk.Grid grid;
|
public Gtk.Grid grid;
|
||||||
public Granite.Widgets.Avatar avatar;
|
public Granite.Widgets.Avatar avatar;
|
||||||
public Gtk.Label title_user;
|
public RichLabel title_user;
|
||||||
public Gtk.Label title_date;
|
public Gtk.Label title_date;
|
||||||
public Gtk.Label title_acct;
|
public Gtk.Label title_acct;
|
||||||
public Gtk.Revealer revealer;
|
public Gtk.Revealer revealer;
|
||||||
public Tootle.RichLabel content_label;
|
public RichLabel content_label;
|
||||||
public Tootle.RichLabel? content_spoiler;
|
public RichLabel? content_spoiler;
|
||||||
public Gtk.Button? spoiler_button;
|
public Gtk.Button? spoiler_button;
|
||||||
public Gtk.Box title_box;
|
public Gtk.Box title_box;
|
||||||
public AttachmentBox attachments;
|
public AttachmentBox attachments;
|
||||||
|
@ -41,8 +41,7 @@ public class Tootle.StatusWidget : Gtk.EventBox {
|
||||||
title_box.margin_end = 12;
|
title_box.margin_end = 12;
|
||||||
title_box.margin_top = 6;
|
title_box.margin_top = 6;
|
||||||
|
|
||||||
title_user = new Gtk.Label ("");
|
title_user = new RichLabel ("");
|
||||||
title_user.use_markup = true;
|
|
||||||
title_box.pack_start (title_user, false, false, 0);
|
title_box.pack_start (title_user, false, false, 0);
|
||||||
|
|
||||||
title_acct = new Gtk.Label ("");
|
title_acct = new Gtk.Label ("");
|
||||||
|
@ -180,7 +179,7 @@ public class Tootle.StatusWidget : Gtk.EventBox {
|
||||||
separator.destroy ();
|
separator.destroy ();
|
||||||
});
|
});
|
||||||
|
|
||||||
Tootle.network.status_removed.connect (id => {
|
network.status_removed.connect (id => {
|
||||||
if (id == this.status.id)
|
if (id == this.status.id)
|
||||||
destroy ();
|
destroy ();
|
||||||
});
|
});
|
||||||
|
@ -200,7 +199,7 @@ public class Tootle.StatusWidget : Gtk.EventBox {
|
||||||
public void rebind () {
|
public void rebind () {
|
||||||
var formal = status.get_formal ();
|
var formal = status.get_formal ();
|
||||||
|
|
||||||
title_user.label = "<b>%s</b>".printf (Html.escape_entities (formal.account.display_name));
|
title_user.set_label ("<b>%s</b>".printf ((formal.account.display_name)));
|
||||||
title_acct.label = "@" + formal.account.acct;
|
title_acct.label = "@" + formal.account.acct;
|
||||||
content_label.label = formal.content;
|
content_label.label = formal.content;
|
||||||
content_label.mentions = formal.mentions;
|
content_label.mentions = formal.mentions;
|
||||||
|
@ -224,7 +223,7 @@ public class Tootle.StatusWidget : Gtk.EventBox {
|
||||||
reblog.tooltip_text = _("This post can't be boosted");
|
reblog.tooltip_text = _("This post can't be boosted");
|
||||||
}
|
}
|
||||||
|
|
||||||
Tootle.network.load_avatar (formal.account.avatar, avatar, get_avatar_size ());
|
network.load_avatar (formal.account.avatar, avatar, get_avatar_size ());
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool is_spoiler () {
|
public bool is_spoiler () {
|
||||||
|
@ -241,14 +240,14 @@ public class Tootle.StatusWidget : Gtk.EventBox {
|
||||||
|
|
||||||
public bool open_account () {
|
public bool open_account () {
|
||||||
var view = new AccountView (status.get_formal ().account);
|
var view = new AccountView (status.get_formal ().account);
|
||||||
Tootle.window.open_view (view);
|
window.open_view (view);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool open (EventButton ev) {
|
public bool open (EventButton ev) {
|
||||||
var formal = status.get_formal ();
|
var formal = status.get_formal ();
|
||||||
var view = new StatusView (ref formal);
|
var view = new StatusView (ref formal);
|
||||||
Tootle.window.open_view (view);
|
window.open_view (view);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue