Delete & Redraft (close #61)

This commit is contained in:
bleakgrey 2018-10-24 15:01:32 +03:00
parent adb44697bf
commit 474f67b5a5
7 changed files with 101 additions and 53 deletions

View File

@ -11,7 +11,7 @@ public class Tootle.Status {
public int64 replies_count;
public int64 reblogs_count;
public int64 favourites_count;
public string created_at;
public string created_at;
public bool reblogged = false;
public bool favorited = false;
public bool sensitive = false;
@ -30,7 +30,7 @@ public class Tootle.Status {
return reblog != null ? reblog : this;
}
public static Status parse(Json.Object obj) {
public static Status parse (Json.Object obj) {
var id = int64.parse (obj.get_string_member ("id"));
var status = new Status (id);
@ -108,7 +108,7 @@ public class Tootle.Status {
return result;
}
public void set_reblogged (bool rebl = true){
public void set_reblogged (bool rebl = true) {
var action = rebl ? "reblog" : "unreblog";
var msg = new Soup.Message ("POST", "%s/api/v1/statuses/%lld/%s".printf (accounts.formal.instance, id, action));
msg.priority = Soup.MessagePriority.HIGH;
@ -123,7 +123,7 @@ public class Tootle.Status {
network.queue (msg);
}
public void set_favorited (bool fav = true){
public void set_favorited (bool fav = true) {
var action = fav ? "favourite" : "unfavourite";
var msg = new Soup.Message ("POST", "%s/api/v1/statuses/%lld/%s".printf (accounts.formal.instance, id, action));
msg.priority = Soup.MessagePriority.HIGH;
@ -138,7 +138,7 @@ public class Tootle.Status {
network.queue (msg);
}
public void set_muted (bool mute = true){
public void set_muted (bool mute = true) {
var action = mute ? "mute" : "unmute";
var msg = new Soup.Message ("POST", "%s/api/v1/statuses/%lld/%s".printf (accounts.formal.instance, id, action));
msg.priority = Soup.MessagePriority.HIGH;
@ -153,7 +153,7 @@ public class Tootle.Status {
network.queue (msg);
}
public void set_pinned (bool pin = true){
public void set_pinned (bool pin = true) {
var action = pin ? "pin" : "unpin";
var msg = new Soup.Message ("POST", "%s/api/v1/statuses/%lld/%s".printf (accounts.formal.instance, id, action));
msg.priority = Soup.MessagePriority.HIGH;
@ -168,14 +168,16 @@ public class Tootle.Status {
network.queue (msg);
}
public void poof (){
public Soup.Message poof (bool show_toast = true) {
var msg = new Soup.Message ("DELETE", "%s/api/v1/statuses/%lld".printf (accounts.formal.instance, id));
msg.priority = Soup.MessagePriority.HIGH;
msg.finished.connect (() => {
app.toast (_("Poof!"));
if (show_toast)
app.toast (_("Poof!"));
network.status_removed (id);
});
network.queue (msg);
return msg;
}
}

View File

@ -2,7 +2,7 @@ using Gtk;
using Tootle;
public class Tootle.PostDialog : Gtk.Dialog {
private static PostDialog dialog;
protected TextView text;
@ -13,25 +13,29 @@ public class Tootle.PostDialog : Gtk.Dialog {
private Button attach;
private Button cancel;
private Button publish;
private AttachmentBox attachments;
protected AttachmentBox attachments;
private Revealer spoiler_revealer;
private Entry spoiler_text;
protected Status? in_reply_to;
protected Status? replying_to;
protected Status? redrafting;
protected StatusVisibility visibility_opt = StatusVisibility.PUBLIC;
protected int char_limit;
public PostDialog (Status? status = null) {
public PostDialog (Status? _replying_to = null, Status? _redrafting = null) {
border_width = 6;
deletable = false;
resizable = true;
title = _("Toot");
transient_for = window;
char_limit = settings.char_limit;
in_reply_to = status;
if (in_reply_to != null)
visibility_opt = in_reply_to.visibility;
replying_to = _replying_to;
redrafting = _redrafting;
if (replying_to != null)
visibility_opt = replying_to.visibility;
if (redrafting != null)
visibility_opt = redrafting.visibility;
var actions = get_action_area ().get_parent () as Gtk.Box;
var content = get_content_area ();
@ -42,15 +46,15 @@ public class Tootle.PostDialog : Gtk.Dialog {
visibility.get_style_context ().add_class (Gtk.STYLE_CLASS_FLAT);
visibility.get_style_context ().remove_class ("image-button");
visibility.can_default = false;
(visibility as Gtk.Widget).set_focus_on_click (false);
(visibility as Widget).set_focus_on_click (false);
attach = new Gtk.Button.from_icon_name ("mail-attachment-symbolic");
attach = new Button.from_icon_name ("mail-attachment-symbolic");
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;
(attach as Gtk.Widget).set_focus_on_click (false);
(attach as Widget).set_focus_on_click (false);
attach.clicked.connect (() => attachments.select ());
spoiler = new ImageToggleButton ("image-red-eye-symbolic");
@ -61,13 +65,19 @@ public class Tootle.PostDialog : Gtk.Dialog {
validate ();
});
cancel = add_button(_("Cancel"), 5) as Gtk.Button;
cancel.clicked.connect(() => this.destroy ());
publish = add_button(_("Toot!"), 5) as Gtk.Button;
publish.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION);
publish.clicked.connect (() => {
publish_post ();
});
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);
}
spoiler_text = new Gtk.Entry ();
spoiler_text.margin_start = 6;
@ -78,14 +88,14 @@ public class Tootle.PostDialog : Gtk.Dialog {
spoiler_revealer = new Gtk.Revealer ();
spoiler_revealer.add (spoiler_text);
text = new Gtk.TextView ();
text = new TextView ();
text.get_style_context ().add_class ("toot-text");
text.wrap_mode = Gtk.WrapMode.WORD;
text.accepts_tab = false;
text.vexpand = true;
text.buffer.changed.connect (validate);
scroll = new Gtk.ScrolledWindow (null, null);
scroll = new ScrolledWindow (null, null);
scroll.hscrollbar_policy = Gtk.PolicyType.NEVER;
scroll.min_content_height = 120;
scroll.vexpand = true;
@ -96,7 +106,7 @@ public class Tootle.PostDialog : Gtk.Dialog {
scroll.show_all ();
attachments = new AttachmentBox (true);
counter = new Gtk.Label ("");
counter = new Label ("");
actions.pack_start (counter, false, false, 6);
actions.pack_end (spoiler, false, false, 6);
@ -107,11 +117,18 @@ public class Tootle.PostDialog : Gtk.Dialog {
content.pack_start (attachments, false, false, 6);
content.set_size_request (350, 120);
if (in_reply_to != null) {
spoiler.active = in_reply_to.sensitive;
var status_spoiler_text = in_reply_to.spoiler_text != null ? in_reply_to.spoiler_text : "";
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 : "";
spoiler_text.set_text (status_spoiler_text);
}
destroy.connect (() => dialog = null);
show_all ();
attachments.hide ();
@ -162,7 +179,7 @@ public class Tootle.PostDialog : Gtk.Dialog {
public static void open (string? text = null, Status? reply_to = null) {
if (dialog == null){
dialog = new PostDialog (reply_to);
dialog.destroy.connect (() => dialog = null);
if (text != null)
dialog.text.buffer.text = text;
}
@ -170,19 +187,34 @@ public class Tootle.PostDialog : Gtk.Dialog {
dialog.text.buffer.text += text;
}
public static void open_reply (Status reply_to) {
if(dialog != null)
public static void reply (Status status) {
if (dialog != null)
return;
open (null, reply_to);
dialog.text.buffer.text = reply_to.get_reply_mentions ();
open (null, status);
dialog.text.buffer.text = status.get_reply_mentions ();
}
public void publish_post () {
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);
dialog.text.buffer.text = content;
}
private void publish_post () {
var pars = "?status=%s&visibility=%s".printf (Html.uri_encode (text.buffer.text), visibility_opt.to_string ());
pars += attachments.get_uri_array ();
if (in_reply_to != null)
pars += "&in_reply_to_id=%s".printf (in_reply_to.id.to_string ());
if (replying_to != null)
pars += "&in_reply_to_id=%s".printf (replying_to.id.to_string ());
if (spoiler.active) {
pars += "&sensitive=true";
@ -191,12 +223,12 @@ public class Tootle.PostDialog : Gtk.Dialog {
var url = "%s/api/v1/statuses%s".printf (accounts.formal.instance, pars);
var msg = new Soup.Message ("POST", url);
network.queue(msg, (sess, mess) => {
network.queue (msg, (sess, mess) => {
try {
var root = network.parse (mess);
var status = Status.parse (root);
debug ("Posted: %s", status.id.to_string ()); //TODO: Live updates
this.destroy ();
destroy ();
}
catch (GLib.Error e) {
warning ("Can't publish post.");
@ -204,5 +236,9 @@ public class Tootle.PostDialog : Gtk.Dialog {
}
});
}
private void redraft_post () {
redrafting.poof ().finished.connect (publish_post);
}
}

View File

@ -10,7 +10,9 @@ public abstract class Tootle.AbstractView : ScrolledWindow {
construct {
view = new Box (Orientation.VERTICAL, 0);
view.valign = Align.START;
add (view);
hscrollbar_policy = PolicyType.NEVER;
edge_reached.connect(pos => {
if (pos == PositionType.BOTTOM)

View File

@ -52,7 +52,7 @@ public class Tootle.TimelineView : AbstractView {
if (empty != null)
empty.destroy ();
var separator = new Gtk.Separator (Gtk.Orientation.HORIZONTAL);
var separator = new Separator (Orientation.HORIZONTAL);
separator.show ();
var widget = new StatusWidget (status);
@ -65,8 +65,8 @@ public class Tootle.TimelineView : AbstractView {
if (first || status.pinned) {
var new_index = header == null ? 1 : 0;
view.reorder_child (widget, new_index);
view.reorder_child (separator, new_index);
view.reorder_child (widget, new_index);
}
}

View File

@ -24,7 +24,8 @@ public class Tootle.AttachmentBox : Gtk.ScrolledWindow {
}
public void append (Attachment attachment) {
var widget = new AttachmentWidget (attachment);
show ();
var widget = new AttachmentWidget (attachment, edit_mode);
box.add (widget);
}

View File

@ -4,7 +4,7 @@ using Gdk;
public class Tootle.AttachmentWidget : Gtk.EventBox {
public Attachment? attachment;
private bool editable = false;
private bool editable;
private const int PREVIEW_SIZE = 350;
private const int SMALL_SIZE = 64;
@ -34,8 +34,9 @@ public class Tootle.AttachmentWidget : Gtk.EventBox {
});
}
public AttachmentWidget (Attachment att) {
public AttachmentWidget (Attachment att, bool _editable = false) {
attachment = att;
editable = _editable;
rebind ();
}

View File

@ -98,7 +98,7 @@ public class Tootle.StatusWidget : Gtk.EventBox {
reply.tooltip_text = _("Reply");
reply.toggled.connect (() => {
reply.set_active (false);
PostDialog.open_reply (status.get_formal ());
PostDialog.reply (status.get_formal ());
});
counters = new Box (Orientation.HORIZONTAL, 6);
@ -189,7 +189,7 @@ public class Tootle.StatusWidget : Gtk.EventBox {
});
network.status_removed.connect (id => {
if (id == this.status.id)
if (id == status.id)
destroy ();
});
@ -286,10 +286,6 @@ public class Tootle.StatusWidget : Gtk.EventBox {
var item_muting = new Gtk.MenuItem.with_label (is_muted ? _("Unmute Conversation") : _("Mute Conversation"));
item_muting.activate.connect (() => status.set_muted (!is_muted));
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));
var item_delete = new Gtk.MenuItem.with_label (_("Delete"));
item_delete.activate.connect (() => status.poof ());
var item_open_link = new Gtk.MenuItem.with_label (_("Open in Browser"));
item_open_link.activate.connect (() => Desktop.open_uri (status.get_formal ().url));
var item_copy_link = new Gtk.MenuItem.with_label (_("Copy Link"));
@ -301,8 +297,18 @@ public class Tootle.StatusWidget : Gtk.EventBox {
});
if (this.status.is_owned ()) {
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));
menu.add (item_pin);
var item_delete = new Gtk.MenuItem.with_label (_("Delete"));
item_delete.activate.connect (() => status.poof ());
menu.add (item_delete);
var item_redraft = new Gtk.MenuItem.with_label (_("Redraft"));
item_redraft.activate.connect (() => PostDialog.redraft (status.get_formal ()));
menu.add (item_redraft);
menu.add (new Gtk.SeparatorMenuItem ());
}