2018-04-14 14:09:06 +02:00
|
|
|
using Gtk;
|
2018-04-15 13:29:55 +02:00
|
|
|
using Tootle;
|
2018-04-14 14:09:06 +02:00
|
|
|
|
2018-04-19 21:03:28 +02:00
|
|
|
public class Tootle.PostDialog : Gtk.Dialog {
|
2018-10-24 14:01:32 +02:00
|
|
|
|
2018-04-19 21:03:28 +02:00
|
|
|
private static PostDialog dialog;
|
2018-10-23 12:05:24 +02:00
|
|
|
|
|
|
|
protected TextView text;
|
|
|
|
private ScrolledWindow scroll;
|
|
|
|
private Label counter;
|
2018-05-19 19:27:30 +02:00
|
|
|
private ImageToggleButton spoiler;
|
2018-10-23 12:05:24 +02:00
|
|
|
private MenuButton visibility;
|
|
|
|
private Button attach;
|
|
|
|
private Button cancel;
|
|
|
|
private Button publish;
|
2018-10-24 14:01:32 +02:00
|
|
|
protected AttachmentBox attachments;
|
2018-10-23 12:05:24 +02:00
|
|
|
private Revealer spoiler_revealer;
|
|
|
|
private Entry spoiler_text;
|
2018-05-19 19:27:30 +02:00
|
|
|
|
2018-10-24 14:01:32 +02:00
|
|
|
protected Status? replying_to;
|
|
|
|
protected Status? redrafting;
|
2018-05-15 13:10:19 +02:00
|
|
|
protected StatusVisibility visibility_opt = StatusVisibility.PUBLIC;
|
2018-06-09 22:50:27 +02:00
|
|
|
protected int char_limit;
|
2018-04-14 14:09:06 +02:00
|
|
|
|
2018-10-24 14:01:32 +02:00
|
|
|
public PostDialog (Status? _replying_to = null, Status? _redrafting = null) {
|
2018-10-23 12:05:24 +02:00
|
|
|
border_width = 6;
|
|
|
|
deletable = false;
|
|
|
|
resizable = true;
|
|
|
|
title = _("Toot");
|
|
|
|
transient_for = window;
|
2018-06-09 22:50:27 +02:00
|
|
|
char_limit = settings.char_limit;
|
2018-10-24 14:01:32 +02:00
|
|
|
replying_to = _replying_to;
|
|
|
|
redrafting = _redrafting;
|
|
|
|
|
|
|
|
if (replying_to != null)
|
|
|
|
visibility_opt = replying_to.visibility;
|
|
|
|
if (redrafting != null)
|
|
|
|
visibility_opt = redrafting.visibility;
|
2018-04-15 13:29:55 +02:00
|
|
|
|
|
|
|
var actions = get_action_area ().get_parent () as Gtk.Box;
|
|
|
|
var content = get_content_area ();
|
2018-05-09 16:20:40 +02:00
|
|
|
get_action_area ().hexpand = false;
|
2018-04-14 14:09:06 +02:00
|
|
|
|
2018-04-15 13:29:55 +02:00
|
|
|
visibility = get_visibility_btn ();
|
2018-05-09 16:20:40 +02:00
|
|
|
visibility.tooltip_text = _("Post Visibility");
|
|
|
|
visibility.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
|
2018-05-15 13:10:19 +02:00
|
|
|
visibility.get_style_context ().remove_class ("image-button");
|
2018-05-09 16:20:40 +02:00
|
|
|
visibility.can_default = false;
|
2018-10-24 14:01:32 +02:00
|
|
|
(visibility as Widget).set_focus_on_click (false);
|
2018-05-19 19:27:30 +02:00
|
|
|
|
2018-10-24 14:01:32 +02:00
|
|
|
attach = new Button.from_icon_name ("mail-attachment-symbolic");
|
2018-05-09 16:20:40 +02:00
|
|
|
attach.tooltip_text = _("Add Media");
|
|
|
|
attach.valign = Gtk.Align.CENTER;
|
|
|
|
attach.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
|
|
|
|
attach.get_style_context ().remove_class ("image-button");
|
|
|
|
attach.can_default = false;
|
2018-10-24 14:01:32 +02:00
|
|
|
(attach as Widget).set_focus_on_click (false);
|
2018-05-09 16:20:40 +02:00
|
|
|
attach.clicked.connect (() => attachments.select ());
|
|
|
|
|
2018-05-19 19:27:30 +02:00
|
|
|
spoiler = new ImageToggleButton ("image-red-eye-symbolic");
|
2018-05-19 19:32:19 +02:00
|
|
|
spoiler.tooltip_text = _("Spoiler Warning");
|
2018-05-19 19:27:30 +02:00
|
|
|
spoiler.set_action ();
|
|
|
|
spoiler.toggled.connect (() => {
|
|
|
|
spoiler_revealer.reveal_child = spoiler.active;
|
|
|
|
validate ();
|
|
|
|
});
|
|
|
|
|
2018-10-24 14:01:32 +02:00
|
|
|
cancel = add_button (_("Cancel"), 5) as Button;
|
|
|
|
cancel.clicked.connect(() => destroy ());
|
|
|
|
|
|
|
|
if (redrafting != null) {
|
|
|
|
publish = add_button (_("Redraft"), 5) as Button;
|
|
|
|
publish.get_style_context ().add_class (Gtk.STYLE_CLASS_DESTRUCTIVE_ACTION);
|
|
|
|
publish.clicked.connect (redraft_post);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
publish = add_button (_("Toot!"), 5) as Button;
|
|
|
|
publish.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION);
|
|
|
|
publish.clicked.connect (publish_post);
|
|
|
|
}
|
2018-04-14 14:09:06 +02:00
|
|
|
|
2018-05-19 19:27:30 +02:00
|
|
|
spoiler_text = new Gtk.Entry ();
|
|
|
|
spoiler_text.margin_start = 6;
|
|
|
|
spoiler_text.margin_end = 6;
|
|
|
|
spoiler_text.placeholder_text = _("Write your warning here");
|
2018-06-01 15:10:47 +02:00
|
|
|
spoiler_text.changed.connect (validate);
|
2018-05-19 19:27:30 +02:00
|
|
|
|
|
|
|
spoiler_revealer = new Gtk.Revealer ();
|
|
|
|
spoiler_revealer.add (spoiler_text);
|
|
|
|
|
2018-10-24 14:01:32 +02:00
|
|
|
text = new TextView ();
|
2018-04-14 14:09:06 +02:00
|
|
|
text.get_style_context ().add_class ("toot-text");
|
|
|
|
text.wrap_mode = Gtk.WrapMode.WORD;
|
2018-05-19 19:27:30 +02:00
|
|
|
text.accepts_tab = false;
|
2018-10-23 12:05:24 +02:00
|
|
|
text.vexpand = true;
|
2018-05-19 19:27:30 +02:00
|
|
|
text.buffer.changed.connect (validate);
|
2018-04-14 14:09:06 +02:00
|
|
|
|
2018-10-24 14:01:32 +02:00
|
|
|
scroll = new ScrolledWindow (null, null);
|
2018-05-04 16:23:26 +02:00
|
|
|
scroll.hscrollbar_policy = Gtk.PolicyType.NEVER;
|
2018-05-19 19:27:30 +02:00
|
|
|
scroll.min_content_height = 120;
|
2018-10-23 12:05:24 +02:00
|
|
|
scroll.vexpand = true;
|
|
|
|
scroll.propagate_natural_height = true;
|
2018-05-04 16:23:26 +02:00
|
|
|
scroll.margin_start = 6;
|
|
|
|
scroll.margin_end = 6;
|
|
|
|
scroll.add (text);
|
|
|
|
scroll.show_all ();
|
|
|
|
|
2018-05-09 16:20:40 +02:00
|
|
|
attachments = new AttachmentBox (true);
|
2018-10-24 14:01:32 +02:00
|
|
|
counter = new Label ("");
|
2018-04-14 14:09:06 +02:00
|
|
|
|
|
|
|
actions.pack_start (counter, false, false, 6);
|
2018-05-19 19:27:30 +02:00
|
|
|
actions.pack_end (spoiler, false, false, 6);
|
2018-05-09 16:20:40 +02:00
|
|
|
actions.pack_end (visibility, false, false, 0);
|
|
|
|
actions.pack_end (attach, false, false, 6);
|
2018-05-19 19:27:30 +02:00
|
|
|
content.pack_start (spoiler_revealer, false, false, 6);
|
2018-05-09 16:20:40 +02:00
|
|
|
content.pack_start (scroll, false, false, 6);
|
|
|
|
content.pack_start (attachments, false, false, 6);
|
2018-05-19 19:27:30 +02:00
|
|
|
content.set_size_request (350, 120);
|
|
|
|
|
2018-10-24 14:01:32 +02:00
|
|
|
if (replying_to != null) {
|
|
|
|
spoiler.active = replying_to.sensitive;
|
|
|
|
var status_spoiler_text = replying_to.spoiler_text != null ? replying_to.spoiler_text : "";
|
|
|
|
spoiler_text.set_text (status_spoiler_text);
|
|
|
|
}
|
|
|
|
if (redrafting != null) {
|
|
|
|
spoiler.active = redrafting.sensitive;
|
|
|
|
var status_spoiler_text = redrafting.spoiler_text != null ? redrafting.spoiler_text : "";
|
2018-05-19 19:27:30 +02:00
|
|
|
spoiler_text.set_text (status_spoiler_text);
|
|
|
|
}
|
2018-05-09 16:20:40 +02:00
|
|
|
|
2018-10-24 14:01:32 +02:00
|
|
|
destroy.connect (() => dialog = null);
|
|
|
|
|
2018-05-09 16:20:40 +02:00
|
|
|
show_all ();
|
|
|
|
attachments.hide ();
|
2018-05-19 19:27:30 +02:00
|
|
|
text.grab_focus ();
|
2018-06-09 22:50:27 +02:00
|
|
|
validate ();
|
2018-04-14 14:09:06 +02:00
|
|
|
}
|
|
|
|
|
2018-05-09 16:20:40 +02:00
|
|
|
private Gtk.MenuButton get_visibility_btn () {
|
2018-04-15 13:29:55 +02:00
|
|
|
var button = new Gtk.MenuButton ();
|
|
|
|
var menu = new Gtk.Popover (null);
|
|
|
|
var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 6);
|
2018-10-23 12:05:24 +02:00
|
|
|
box.margin = 12;
|
2018-04-15 13:29:55 +02:00
|
|
|
menu.add (box);
|
|
|
|
button.direction = Gtk.ArrowType.DOWN;
|
2018-05-15 13:10:19 +02:00
|
|
|
button.image = new Gtk.Image.from_icon_name (visibility_opt.get_icon (), Gtk.IconSize.BUTTON);
|
2018-04-15 13:29:55 +02:00
|
|
|
|
2018-10-23 12:05:24 +02:00
|
|
|
Gtk.RadioButton? first = null;
|
|
|
|
foreach (StatusVisibility opt in StatusVisibility.get_all ()){
|
2018-04-15 13:29:55 +02:00
|
|
|
var item = new Gtk.RadioButton.with_label_from_widget (first, opt.get_desc ());
|
2018-05-15 13:10:19 +02:00
|
|
|
if (first == null)
|
2018-04-15 13:29:55 +02:00
|
|
|
first = item;
|
|
|
|
|
|
|
|
item.toggled.connect (() => {
|
|
|
|
visibility_opt = opt;
|
2018-05-15 13:10:19 +02:00
|
|
|
(button.image as Gtk.Image).icon_name = visibility_opt.get_icon ();
|
2018-04-15 13:29:55 +02:00
|
|
|
});
|
2018-05-15 13:10:19 +02:00
|
|
|
item.active = visibility_opt == opt;
|
2018-04-15 13:29:55 +02:00
|
|
|
box.pack_start (item, false, false, 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
box.show_all ();
|
|
|
|
button.use_popover = true;
|
|
|
|
button.popover = menu;
|
|
|
|
button.valign = Gtk.Align.CENTER;
|
|
|
|
button.show ();
|
|
|
|
return button;
|
|
|
|
}
|
|
|
|
|
2018-05-19 19:27:30 +02:00
|
|
|
private void validate () {
|
2018-06-09 22:50:27 +02:00
|
|
|
var remain = char_limit - text.buffer.text.length;
|
2018-06-01 15:10:47 +02:00
|
|
|
if (spoiler.active)
|
|
|
|
remain -= spoiler_text.buffer.text.length;
|
2018-04-14 14:09:06 +02:00
|
|
|
|
2018-04-15 14:28:23 +02:00
|
|
|
counter.label = remain.to_string ();
|
2018-05-19 19:27:30 +02:00
|
|
|
publish.sensitive = remain >= 0;
|
2018-04-14 14:09:06 +02:00
|
|
|
}
|
|
|
|
|
2018-05-15 13:10:19 +02:00
|
|
|
public static void open (string? text = null, Status? reply_to = null) {
|
|
|
|
if (dialog == null){
|
|
|
|
dialog = new PostDialog (reply_to);
|
2018-10-24 14:01:32 +02:00
|
|
|
|
2018-05-01 15:16:07 +02:00
|
|
|
if (text != null)
|
|
|
|
dialog.text.buffer.text = text;
|
2018-04-14 14:09:06 +02:00
|
|
|
}
|
2018-05-15 13:10:19 +02:00
|
|
|
else if (text != null)
|
2018-06-06 16:49:13 +02:00
|
|
|
dialog.text.buffer.text += text;
|
2018-04-14 14:09:06 +02:00
|
|
|
}
|
2018-04-15 14:28:23 +02:00
|
|
|
|
2018-10-24 14:01:32 +02:00
|
|
|
public static void reply (Status status) {
|
|
|
|
if (dialog != null)
|
2018-05-15 13:10:19 +02:00
|
|
|
return;
|
|
|
|
|
2018-10-24 14:01:32 +02:00
|
|
|
open (null, status);
|
|
|
|
dialog.text.buffer.text = status.get_reply_mentions ();
|
2018-04-24 16:50:38 +02:00
|
|
|
}
|
|
|
|
|
2018-10-24 14:01:32 +02:00
|
|
|
public static void redraft (Status status) {
|
|
|
|
if (dialog != null)
|
|
|
|
return;
|
|
|
|
dialog = new PostDialog (null, status);
|
|
|
|
|
|
|
|
if (status.attachments != null) {
|
|
|
|
foreach (Attachment attachment in status.attachments)
|
|
|
|
dialog.attachments.append (attachment);
|
|
|
|
}
|
|
|
|
|
|
|
|
var content = Html.simplify (status.content);
|
|
|
|
content = Html.remove_tags (content);
|
2018-10-30 18:40:47 +01:00
|
|
|
content = RichLabel.restore_entities (content);
|
2018-10-24 14:01:32 +02:00
|
|
|
dialog.text.buffer.text = content;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void publish_post () {
|
2018-05-30 21:49:16 +02:00
|
|
|
var pars = "?status=%s&visibility=%s".printf (Html.uri_encode (text.buffer.text), visibility_opt.to_string ());
|
2018-10-23 12:05:24 +02:00
|
|
|
pars += attachments.get_uri_array ();
|
2018-10-24 14:01:32 +02:00
|
|
|
if (replying_to != null)
|
|
|
|
pars += "&in_reply_to_id=%s".printf (replying_to.id.to_string ());
|
2018-05-09 16:20:40 +02:00
|
|
|
|
2018-05-19 19:27:30 +02:00
|
|
|
if (spoiler.active) {
|
|
|
|
pars += "&sensitive=true";
|
2018-05-30 21:49:16 +02:00
|
|
|
pars += "&spoiler_text=" + Html.uri_encode (spoiler_text.buffer.text);
|
2018-05-19 19:27:30 +02:00
|
|
|
}
|
|
|
|
|
2018-10-23 12:05:24 +02:00
|
|
|
var url = "%s/api/v1/statuses%s".printf (accounts.formal.instance, pars);
|
|
|
|
var msg = new Soup.Message ("POST", url);
|
2018-10-24 14:01:32 +02:00
|
|
|
network.queue (msg, (sess, mess) => {
|
2018-05-09 16:20:40 +02:00
|
|
|
try {
|
2018-10-23 12:05:24 +02:00
|
|
|
var root = network.parse (mess);
|
2018-04-15 14:28:23 +02:00
|
|
|
var status = Status.parse (root);
|
2018-05-15 13:10:19 +02:00
|
|
|
debug ("Posted: %s", status.id.to_string ()); //TODO: Live updates
|
2018-10-24 14:01:32 +02:00
|
|
|
destroy ();
|
2018-04-15 14:28:23 +02:00
|
|
|
}
|
|
|
|
catch (GLib.Error e) {
|
|
|
|
warning ("Can't publish post.");
|
|
|
|
warning (e.message);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
2018-10-24 14:01:32 +02:00
|
|
|
|
|
|
|
private void redraft_post () {
|
2018-10-27 11:21:34 +02:00
|
|
|
redrafting.poof (false).finished.connect (publish_post);
|
2018-10-24 14:01:32 +02:00
|
|
|
}
|
2018-04-14 14:09:06 +02:00
|
|
|
|
|
|
|
}
|