2018-04-14 14:09:06 +02:00
|
|
|
using Gtk;
|
2018-05-21 17:23:31 +02:00
|
|
|
using Gdk;
|
2018-04-14 14:09:06 +02:00
|
|
|
using Granite;
|
|
|
|
|
2018-04-25 13:45:50 +02:00
|
|
|
public class Tootle.StatusWidget : Gtk.EventBox {
|
2018-04-14 14:09:06 +02:00
|
|
|
|
2018-04-16 20:22:42 +02:00
|
|
|
public Status status;
|
2018-05-22 15:18:39 +02:00
|
|
|
public bool is_notification = false;
|
2018-06-02 11:27:19 +02:00
|
|
|
public const int AVATAR_SIZE = 32;
|
2018-04-16 20:22:42 +02:00
|
|
|
|
2018-10-24 12:50:40 +02:00
|
|
|
public Separator? separator;
|
2018-04-14 14:09:06 +02:00
|
|
|
public Granite.Widgets.Avatar avatar;
|
2018-10-24 12:50:40 +02:00
|
|
|
protected Grid grid;
|
|
|
|
protected RichLabel title_user;
|
|
|
|
protected Label title_date;
|
|
|
|
protected Label title_acct;
|
|
|
|
protected Revealer revealer;
|
|
|
|
protected RichLabel content_label;
|
|
|
|
protected RichLabel? content_spoiler;
|
|
|
|
protected Button? spoiler_button;
|
|
|
|
protected Box title_box;
|
|
|
|
protected AttachmentBox attachments;
|
|
|
|
protected Image pin_indicator;
|
|
|
|
|
|
|
|
protected Box counters;
|
|
|
|
protected Label replies;
|
|
|
|
protected Label reblogs;
|
|
|
|
protected Label favorites;
|
|
|
|
protected ImageToggleButton reblog;
|
|
|
|
protected ImageToggleButton favorite;
|
|
|
|
protected ImageToggleButton reply;
|
2018-04-14 14:09:06 +02:00
|
|
|
|
|
|
|
construct {
|
2018-10-24 12:50:40 +02:00
|
|
|
grid = new Grid ();
|
2018-05-18 23:14:12 +02:00
|
|
|
|
2018-06-02 11:27:19 +02:00
|
|
|
avatar = new Granite.Widgets.Avatar.with_default_icon (AVATAR_SIZE);
|
2018-10-24 12:50:40 +02:00
|
|
|
avatar.valign = Align.START;
|
2018-05-01 18:37:45 +02:00
|
|
|
avatar.margin_top = 6;
|
|
|
|
avatar.margin_start = 6;
|
2018-04-14 14:09:06 +02:00
|
|
|
avatar.margin_end = 6;
|
2018-05-02 14:00:43 +02:00
|
|
|
|
2018-10-24 12:50:40 +02:00
|
|
|
title_box = new Box (Gtk.Orientation.HORIZONTAL, 6);
|
2018-05-02 14:00:43 +02:00
|
|
|
title_box.hexpand = true;
|
|
|
|
title_box.margin_end = 12;
|
|
|
|
title_box.margin_top = 6;
|
|
|
|
|
2018-06-06 16:19:11 +02:00
|
|
|
title_user = new RichLabel ("");
|
2018-05-02 14:00:43 +02:00
|
|
|
title_box.pack_start (title_user, false, false, 0);
|
|
|
|
|
|
|
|
title_acct = new Gtk.Label ("");
|
|
|
|
title_acct.opacity = 0.5;
|
2018-05-04 23:33:52 +02:00
|
|
|
title_acct.ellipsize = Pango.EllipsizeMode.END;
|
2018-05-02 14:00:43 +02:00
|
|
|
title_box.pack_start (title_acct, false, false, 0);
|
|
|
|
|
|
|
|
title_date = new Gtk.Label ("");
|
2018-05-15 18:33:49 +02:00
|
|
|
title_date.opacity = 0.5;
|
2018-05-02 14:00:43 +02:00
|
|
|
title_date.ellipsize = Pango.EllipsizeMode.END;
|
|
|
|
title_box.pack_end (title_date, false, false, 0);
|
|
|
|
title_box.show_all ();
|
2018-04-23 19:02:21 +02:00
|
|
|
|
2018-10-24 11:29:36 +02:00
|
|
|
pin_indicator = new Image.from_icon_name ("view-pin-symbolic", IconSize.MENU);
|
|
|
|
pin_indicator.opacity = 0.5;
|
|
|
|
title_box.pack_end (pin_indicator, false, false, 0);
|
|
|
|
|
2018-05-04 22:57:31 +02:00
|
|
|
content_label = new RichLabel ("");
|
|
|
|
content_label.wrap_words ();
|
2018-04-14 14:09:06 +02:00
|
|
|
|
2018-05-09 16:20:40 +02:00
|
|
|
attachments = new AttachmentBox ();
|
2018-05-15 18:33:49 +02:00
|
|
|
|
2018-10-24 12:50:40 +02:00
|
|
|
var revealer_box = new Box (Orientation.VERTICAL, 6);
|
2018-05-15 18:33:49 +02:00
|
|
|
revealer_box.margin_end = 12;
|
2018-10-24 12:50:40 +02:00
|
|
|
revealer_box.add (content_label);
|
|
|
|
revealer_box.add (attachments);
|
2018-05-15 18:33:49 +02:00
|
|
|
revealer = new Revealer ();
|
|
|
|
revealer.reveal_child = true;
|
|
|
|
revealer.add (revealer_box);
|
2018-05-09 16:20:40 +02:00
|
|
|
|
2018-10-24 12:50:40 +02:00
|
|
|
reblogs = new Label ("0");
|
|
|
|
favorites = new Label ("0");
|
|
|
|
replies = new Label ("0");
|
2018-04-16 20:22:42 +02:00
|
|
|
|
2018-06-01 19:48:13 +02:00
|
|
|
reblog = new ImageToggleButton ("media-playlist-repeat-symbolic");
|
2018-05-11 13:28:49 +02:00
|
|
|
reblog.set_action ();
|
2018-04-30 18:04:22 +02:00
|
|
|
reblog.tooltip_text = _("Boost");
|
2018-04-16 20:22:42 +02:00
|
|
|
reblog.toggled.connect (() => {
|
|
|
|
if (reblog.sensitive)
|
2018-05-18 23:14:12 +02:00
|
|
|
this.status.get_formal ().set_reblogged (reblog.get_active ());
|
2018-04-16 20:22:42 +02:00
|
|
|
});
|
2018-05-11 13:28:49 +02:00
|
|
|
favorite = new ImageToggleButton ("help-about-symbolic");
|
|
|
|
favorite.set_action ();
|
2018-04-30 18:04:22 +02:00
|
|
|
favorite.tooltip_text = _("Favorite");
|
2018-04-16 20:22:42 +02:00
|
|
|
favorite.toggled.connect (() => {
|
|
|
|
if (favorite.sensitive)
|
2018-05-18 23:14:12 +02:00
|
|
|
this.status.get_formal ().set_favorited (favorite.get_active ());
|
2018-04-16 20:22:42 +02:00
|
|
|
});
|
2018-06-01 19:48:13 +02:00
|
|
|
reply = new ImageToggleButton ("mail-reply-sender-symbolic");
|
2018-05-11 13:28:49 +02:00
|
|
|
reply.set_action ();
|
2018-04-30 18:04:22 +02:00
|
|
|
reply.tooltip_text = _("Reply");
|
2018-04-24 16:50:38 +02:00
|
|
|
reply.toggled.connect (() => {
|
|
|
|
reply.set_active (false);
|
2018-10-24 14:01:32 +02:00
|
|
|
PostDialog.reply (status.get_formal ());
|
2018-04-24 16:50:38 +02:00
|
|
|
});
|
2018-05-04 22:57:31 +02:00
|
|
|
|
2018-10-24 12:50:40 +02:00
|
|
|
counters = new Box (Orientation.HORIZONTAL, 6);
|
2018-04-14 14:09:06 +02:00
|
|
|
counters.margin_top = 6;
|
2018-05-01 18:37:45 +02:00
|
|
|
counters.margin_bottom = 6;
|
2018-04-24 12:11:10 +02:00
|
|
|
counters.add (reblog);
|
|
|
|
counters.add (reblogs);
|
|
|
|
counters.add (favorite);
|
|
|
|
counters.add (favorites);
|
2018-04-24 16:50:38 +02:00
|
|
|
counters.add (reply);
|
2018-10-24 12:50:40 +02:00
|
|
|
counters.add (replies);
|
2018-04-14 14:09:06 +02:00
|
|
|
counters.show_all ();
|
|
|
|
|
2018-05-18 23:14:12 +02:00
|
|
|
add (grid);
|
2018-04-25 13:45:50 +02:00
|
|
|
grid.attach (avatar, 1, 1, 1, 4);
|
2018-05-02 14:00:43 +02:00
|
|
|
grid.attach (title_box, 2, 2, 1, 1);
|
2018-04-25 13:45:50 +02:00
|
|
|
grid.attach (revealer, 2, 4, 1, 1);
|
|
|
|
grid.attach (counters, 2, 5, 1, 1);
|
2018-05-04 22:57:31 +02:00
|
|
|
show_all ();
|
2018-05-21 17:23:31 +02:00
|
|
|
|
2018-10-23 12:22:43 +02:00
|
|
|
button_press_event.connect (on_clicked);
|
2018-04-14 14:09:06 +02:00
|
|
|
}
|
|
|
|
|
2018-10-23 12:05:24 +02:00
|
|
|
public StatusWidget (Status status) {
|
2018-04-16 20:22:42 +02:00
|
|
|
this.status = status;
|
2018-05-18 23:14:12 +02:00
|
|
|
this.status.updated.connect (rebind);
|
2018-04-18 11:13:22 +02:00
|
|
|
|
2018-05-18 23:14:12 +02:00
|
|
|
if (this.status.reblog != null) {
|
2018-10-24 12:50:40 +02:00
|
|
|
var image = new Image.from_icon_name("media-playlist-repeat-symbolic", IconSize.BUTTON);
|
|
|
|
image.halign = Align.END;
|
2018-05-01 18:37:45 +02:00
|
|
|
image.margin_end = 6;
|
|
|
|
image.margin_top = 6;
|
2018-04-21 11:21:03 +02:00
|
|
|
image.show ();
|
|
|
|
|
2018-05-18 23:14:12 +02:00
|
|
|
var label_text = _("<a href=\"%s\"><b>%s</b></a> boosted").printf (this.status.account.url, this.status.account.display_name);
|
2018-04-28 18:27:10 +02:00
|
|
|
var label = new RichLabel (label_text);
|
2018-10-24 12:50:40 +02:00
|
|
|
label.halign = Align.START;
|
2018-05-01 18:37:45 +02:00
|
|
|
label.margin_top = 6;
|
2018-04-21 11:21:03 +02:00
|
|
|
label.show ();
|
|
|
|
|
2018-04-25 13:45:50 +02:00
|
|
|
grid.attach (image, 1, 0, 1, 1);
|
|
|
|
grid.attach (label, 2, 0, 2, 1);
|
2018-04-21 11:21:03 +02:00
|
|
|
}
|
|
|
|
|
2018-05-05 17:38:01 +02:00
|
|
|
if (is_spoiler ()) {
|
2018-04-23 19:02:21 +02:00
|
|
|
revealer.reveal_child = false;
|
2018-10-24 12:50:40 +02:00
|
|
|
var spoiler_box = new Box (Orientation.HORIZONTAL, 6);
|
2018-05-04 22:57:31 +02:00
|
|
|
spoiler_box.margin_end = 12;
|
2018-04-23 19:02:21 +02:00
|
|
|
|
2018-05-04 22:57:31 +02:00
|
|
|
var spoiler_button_text = _("Toggle content");
|
|
|
|
if (status.sensitive && status.attachments != null) {
|
|
|
|
spoiler_button = new Button.from_icon_name ("mail-attachment-symbolic", Gtk.IconSize.BUTTON);
|
|
|
|
spoiler_button.label = spoiler_button_text;
|
|
|
|
spoiler_button.always_show_image = true;
|
|
|
|
content_label.margin_top = 6;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
spoiler_button = new Button.with_label (spoiler_button_text);
|
|
|
|
}
|
2018-06-01 19:08:00 +02:00
|
|
|
spoiler_button.hexpand = true;
|
2018-10-24 12:50:40 +02:00
|
|
|
spoiler_button.halign = Align.END;
|
2018-04-23 19:02:21 +02:00
|
|
|
spoiler_button.clicked.connect (() => revealer.set_reveal_child (!revealer.child_revealed));
|
2018-05-04 22:57:31 +02:00
|
|
|
|
|
|
|
var spoiler_text = _("[ This post contains sensitive content ]");
|
|
|
|
if (status.spoiler_text != null)
|
|
|
|
spoiler_text = status.spoiler_text;
|
|
|
|
content_spoiler = new RichLabel (spoiler_text);
|
|
|
|
content_spoiler.wrap_words ();
|
|
|
|
|
|
|
|
spoiler_box.add (content_spoiler);
|
|
|
|
spoiler_box.add (spoiler_button);
|
|
|
|
spoiler_box.show_all ();
|
2018-04-25 13:45:50 +02:00
|
|
|
grid.attach (spoiler_box, 2, 3, 1, 1);
|
2018-04-23 18:43:29 +02:00
|
|
|
}
|
|
|
|
|
2018-05-15 18:33:49 +02:00
|
|
|
if (status.get_formal ().attachments != null) {
|
2018-05-09 16:20:40 +02:00
|
|
|
attachments.clear ();
|
2018-05-15 18:33:49 +02:00
|
|
|
foreach (Attachment attachment in status.get_formal ().attachments)
|
2018-05-09 16:20:40 +02:00
|
|
|
attachments.append (attachment);
|
2018-05-04 22:57:31 +02:00
|
|
|
}
|
2018-05-09 16:20:40 +02:00
|
|
|
else
|
|
|
|
attachments.destroy ();
|
2018-05-04 22:57:31 +02:00
|
|
|
|
2018-04-18 11:13:22 +02:00
|
|
|
destroy.connect (() => {
|
2018-06-02 11:27:19 +02:00
|
|
|
avatar.show_default (AVATAR_SIZE);
|
2018-10-24 12:50:40 +02:00
|
|
|
if (separator != null)
|
2018-04-18 11:13:22 +02:00
|
|
|
separator.destroy ();
|
|
|
|
});
|
2018-05-04 22:57:31 +02:00
|
|
|
|
2018-06-06 16:19:11 +02:00
|
|
|
network.status_removed.connect (id => {
|
2018-10-24 14:01:32 +02:00
|
|
|
if (id == status.id)
|
2018-05-16 13:23:48 +02:00
|
|
|
destroy ();
|
|
|
|
});
|
|
|
|
|
2018-05-01 15:53:46 +02:00
|
|
|
rebind ();
|
2018-04-14 14:09:06 +02:00
|
|
|
}
|
|
|
|
|
2018-05-05 17:38:01 +02:00
|
|
|
public void highlight () {
|
2018-05-01 18:37:45 +02:00
|
|
|
grid.get_style_context ().add_class ("card");
|
|
|
|
grid.margin_bottom = 6;
|
2018-04-22 13:35:25 +02:00
|
|
|
}
|
|
|
|
|
2018-06-02 11:27:19 +02:00
|
|
|
public int get_avatar_size () {
|
|
|
|
return AVATAR_SIZE * get_style_context ().get_scale ();
|
|
|
|
}
|
|
|
|
|
2018-05-05 17:38:01 +02:00
|
|
|
public void rebind () {
|
2018-05-15 18:33:49 +02:00
|
|
|
var formal = status.get_formal ();
|
|
|
|
|
2018-06-06 16:19:11 +02:00
|
|
|
title_user.set_label ("<b>%s</b>".printf ((formal.account.display_name)));
|
2018-05-15 18:33:49 +02:00
|
|
|
title_acct.label = "@" + formal.account.acct;
|
|
|
|
content_label.label = formal.content;
|
|
|
|
content_label.mentions = formal.mentions;
|
2018-10-24 11:29:36 +02:00
|
|
|
pin_indicator.visible = status.pinned;
|
2018-05-17 18:09:10 +02:00
|
|
|
|
|
|
|
var datetime = parse_date_iso8601 (formal.created_at);
|
|
|
|
title_date.label = Granite.DateTime.get_relative_datetime (datetime);
|
2018-04-14 14:09:06 +02:00
|
|
|
|
2018-05-15 18:33:49 +02:00
|
|
|
reblogs.label = formal.reblogs_count.to_string ();
|
|
|
|
favorites.label = formal.favourites_count.to_string ();
|
2018-10-24 12:50:40 +02:00
|
|
|
replies.label = formal.replies_count.to_string ();
|
2018-04-14 14:09:06 +02:00
|
|
|
|
2018-04-30 18:04:22 +02:00
|
|
|
reblog.sensitive = false;
|
2018-05-15 18:33:49 +02:00
|
|
|
reblog.active = formal.reblogged;
|
2018-04-16 20:22:42 +02:00
|
|
|
reblog.sensitive = true;
|
2018-04-30 18:04:22 +02:00
|
|
|
favorite.sensitive = false;
|
2018-05-15 18:33:49 +02:00
|
|
|
favorite.active = formal.favorited;
|
2018-04-16 20:22:42 +02:00
|
|
|
favorite.sensitive = true;
|
|
|
|
|
2018-05-15 18:33:49 +02:00
|
|
|
if (formal.visibility == StatusVisibility.DIRECT) {
|
2018-05-11 13:28:49 +02:00
|
|
|
reblog.sensitive = false;
|
2018-05-15 18:33:49 +02:00
|
|
|
reblog.icon.icon_name = formal.visibility.get_icon ();
|
2018-05-11 13:28:49 +02:00
|
|
|
reblog.tooltip_text = _("This post can't be boosted");
|
|
|
|
}
|
|
|
|
|
2018-06-06 16:19:11 +02:00
|
|
|
network.load_avatar (formal.account.avatar, avatar, get_avatar_size ());
|
2018-04-25 15:16:57 +02:00
|
|
|
}
|
2018-05-04 22:57:31 +02:00
|
|
|
|
2018-05-05 17:38:01 +02:00
|
|
|
public bool is_spoiler () {
|
2018-05-18 23:14:12 +02:00
|
|
|
return this.status.get_formal ().spoiler_text != null || this.status.get_formal ().sensitive;
|
2018-05-04 22:57:31 +02:00
|
|
|
}
|
2018-04-25 15:16:57 +02:00
|
|
|
|
2018-05-17 18:09:10 +02:00
|
|
|
private GLib.DateTime? parse_date_iso8601 (string date) {
|
2018-05-21 12:40:49 +02:00
|
|
|
var timeval = GLib.TimeVal ();
|
|
|
|
if (timeval.from_iso8601 (date))
|
2018-05-17 18:09:10 +02:00
|
|
|
return new GLib.DateTime.from_timeval_local (timeval);
|
2018-05-21 12:40:49 +02:00
|
|
|
|
2018-05-17 18:09:10 +02:00
|
|
|
return null;
|
2018-05-02 14:00:43 +02:00
|
|
|
}
|
|
|
|
|
2018-10-23 12:54:32 +02:00
|
|
|
public bool open_account (EventButton ev) {
|
|
|
|
if (ev.button == 8)
|
|
|
|
return false;
|
|
|
|
|
2018-04-29 12:58:45 +02:00
|
|
|
var view = new AccountView (status.get_formal ().account);
|
2018-06-06 16:19:11 +02:00
|
|
|
window.open_view (view);
|
2018-04-25 15:16:57 +02:00
|
|
|
return true;
|
2018-04-14 14:09:06 +02:00
|
|
|
}
|
2018-04-16 20:22:42 +02:00
|
|
|
|
2018-05-21 17:23:31 +02:00
|
|
|
public bool open (EventButton ev) {
|
2018-10-23 12:22:43 +02:00
|
|
|
if (ev.button == 8)
|
|
|
|
return false;
|
|
|
|
|
2018-05-18 23:14:12 +02:00
|
|
|
var formal = status.get_formal ();
|
2018-10-23 12:05:24 +02:00
|
|
|
var view = new StatusView (formal);
|
2018-06-06 16:19:11 +02:00
|
|
|
window.open_view (view);
|
2018-05-21 17:23:31 +02:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private bool on_clicked (EventButton ev) {
|
2018-10-23 12:22:43 +02:00
|
|
|
if (ev.button == 8)
|
|
|
|
return false;
|
|
|
|
|
2018-05-21 17:23:31 +02:00
|
|
|
if (ev.button == 3)
|
|
|
|
return open_menu (ev.button, ev.time);
|
|
|
|
else
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-05-21 17:27:03 +02:00
|
|
|
public virtual bool open_menu (uint button, uint32 time) {
|
2018-05-21 17:23:31 +02:00
|
|
|
var menu = new Gtk.Menu ();
|
|
|
|
|
2018-05-22 15:18:39 +02:00
|
|
|
var is_muted = status.muted;
|
2018-10-24 11:00:40 +02:00
|
|
|
var is_pinned = status.pinned;
|
2018-10-24 11:29:36 +02:00
|
|
|
|
2018-05-22 15:18:39 +02:00
|
|
|
var item_muting = new Gtk.MenuItem.with_label (is_muted ? _("Unmute Conversation") : _("Mute Conversation"));
|
|
|
|
item_muting.activate.connect (() => status.set_muted (!is_muted));
|
2018-05-21 17:23:31 +02:00
|
|
|
var item_open_link = new Gtk.MenuItem.with_label (_("Open in Browser"));
|
2018-07-08 02:47:35 +02:00
|
|
|
item_open_link.activate.connect (() => Desktop.open_uri (status.get_formal ().url));
|
2018-05-21 17:23:31 +02:00
|
|
|
var item_copy_link = new Gtk.MenuItem.with_label (_("Copy Link"));
|
2018-07-08 02:47:35 +02:00
|
|
|
item_copy_link.activate.connect (() => Desktop.copy (status.get_formal ().url));
|
2018-05-21 17:23:31 +02:00
|
|
|
var item_copy = new Gtk.MenuItem.with_label (_("Copy Text"));
|
|
|
|
item_copy.activate.connect (() => {
|
2018-07-08 02:47:35 +02:00
|
|
|
var sanitized = Html.remove_tags (status.get_formal ().content);
|
2018-05-30 21:49:16 +02:00
|
|
|
Desktop.copy (sanitized);
|
2018-05-21 17:23:31 +02:00
|
|
|
});
|
2018-05-22 14:47:25 +02:00
|
|
|
|
|
|
|
if (this.status.is_owned ()) {
|
2018-10-24 14:01:32 +02:00
|
|
|
var item_pin = new Gtk.MenuItem.with_label (is_pinned ? _("Unpin from Profile") : _("Pin on Profile"));
|
|
|
|
item_pin.activate.connect (() => status.set_pinned (!is_pinned));
|
2018-10-24 11:00:40 +02:00
|
|
|
menu.add (item_pin);
|
2018-10-24 14:01:32 +02:00
|
|
|
|
|
|
|
var item_delete = new Gtk.MenuItem.with_label (_("Delete"));
|
|
|
|
item_delete.activate.connect (() => status.poof ());
|
2018-05-22 14:47:25 +02:00
|
|
|
menu.add (item_delete);
|
2018-10-24 14:01:32 +02:00
|
|
|
|
|
|
|
var item_redraft = new Gtk.MenuItem.with_label (_("Redraft"));
|
|
|
|
item_redraft.activate.connect (() => PostDialog.redraft (status.get_formal ()));
|
|
|
|
menu.add (item_redraft);
|
|
|
|
|
2018-05-22 14:47:25 +02:00
|
|
|
menu.add (new Gtk.SeparatorMenuItem ());
|
|
|
|
}
|
|
|
|
|
2018-05-22 15:18:39 +02:00
|
|
|
if (this.is_notification)
|
|
|
|
menu.add (item_muting);
|
2018-10-23 12:54:32 +02:00
|
|
|
|
2018-05-21 17:27:03 +02:00
|
|
|
menu.add (item_open_link);
|
|
|
|
menu.add (new Gtk.SeparatorMenuItem ());
|
|
|
|
menu.add (item_copy_link);
|
|
|
|
menu.add (item_copy);
|
2018-05-21 17:23:31 +02:00
|
|
|
|
|
|
|
menu.show_all ();
|
|
|
|
menu.attach_widget = this;
|
2018-10-23 12:54:32 +02:00
|
|
|
menu.popup_at_pointer ();
|
2018-05-21 17:23:31 +02:00
|
|
|
return true;
|
2018-04-26 16:05:03 +02:00
|
|
|
}
|
2018-04-14 14:09:06 +02:00
|
|
|
|
|
|
|
}
|