aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorfiaxh <git@lightrise.org>2023-01-06 16:14:47 +0100
committerfiaxh <git@lightrise.org>2023-01-11 19:49:03 +0100
commitcb3b19b01deb8460627578b885339e7528411f6f (patch)
treee879305f4f43b0f88c44aeef4c02fde3f101b1e9
parent0c4aea96ffbc05d6efeb9a83424b872ce7f30d88 (diff)
downloaddino-cb3b19b01deb8460627578b885339e7528411f6f.tar.gz
dino-cb3b19b01deb8460627578b885339e7528411f6f.zip
Support replies and reactions to files
-rw-r--r--libdino/src/service/content_item_store.vala95
-rw-r--r--libdino/src/service/message_processor.vala51
-rw-r--r--libdino/src/service/message_storage.vala4
-rw-r--r--libdino/src/service/reactions.vala78
-rw-r--r--libdino/src/service/replies.vala17
-rw-r--r--libdino/src/service/util.vala1
-rw-r--r--main/src/ui/conversation_content_view/file_widget.vala33
-rw-r--r--main/src/ui/conversation_content_view/message_widget.vala4
-rw-r--r--main/src/ui/conversation_content_view/quote_widget.vala3
-rw-r--r--xmpp-vala/src/module/message/module.vala6
-rw-r--r--xmpp-vala/src/module/xep/0444_reactions.vala4
-rw-r--r--xmpp-vala/src/util.vala8
12 files changed, 202 insertions, 102 deletions
diff --git a/libdino/src/service/content_item_store.vala b/libdino/src/service/content_item_store.vala
index 6a9e691f..b3e32cf4 100644
--- a/libdino/src/service/content_item_store.vala
+++ b/libdino/src/service/content_item_store.vala
@@ -44,11 +44,8 @@ public class ContentItemStore : StreamInteractionModule, Object {
Gee.TreeSet<ContentItem> items = new Gee.TreeSet<ContentItem>(ContentItem.compare_func);
foreach (var row in select) {
- int id = row[db.content_item.id];
- int content_type = row[db.content_item.content_type];
- int foreign_id = row[db.content_item.foreign_id];
- DateTime time = new DateTime.from_unix_utc(row[db.content_item.time]);
- items.add(get_item(conversation, id, content_type, foreign_id, time));
+ ContentItem content_item = get_item_from_row(row, conversation);
+ items.add(content_item);
}
Gee.List<ContentItem> ret = new ArrayList<ContentItem>();
@@ -58,6 +55,14 @@ public class ContentItemStore : StreamInteractionModule, Object {
return ret;
}
+ private ContentItem get_item_from_row(Row row, Conversation conversation) throws Error {
+ int id = row[db.content_item.id];
+ int content_type = row[db.content_item.content_type];
+ int foreign_id = row[db.content_item.foreign_id];
+ DateTime time = new DateTime.from_unix_utc(row[db.content_item.time]);
+ return get_item(conversation, id, content_type, foreign_id, time);
+ }
+
private ContentItem get_item(Conversation conversation, int id, int content_type, int foreign_id, DateTime time) throws Error {
switch (content_type) {
case 1:
@@ -112,6 +117,86 @@ public class ContentItemStore : StreamInteractionModule, Object {
return item.size > 0 ? item[0] : null;
}
+ public string? get_message_id_for_content_item(Conversation conversation, ContentItem content_item) {
+ Message? message = get_message_for_content_item(conversation, content_item);
+ if (message == null) return null;
+
+ if (conversation.type_ == Conversation.Type.CHAT) {
+ return message.stanza_id;
+ } else {
+ return message.server_id;
+ }
+ }
+
+ public Jid? get_message_sender_for_content_item(Conversation conversation, ContentItem content_item) {
+ Message? message = get_message_for_content_item(conversation, content_item);
+ if (message == null) return null;
+ return message.from;
+ }
+
+ private Message? get_message_for_content_item(Conversation conversation, ContentItem content_item) {
+ FileItem? file_item = content_item as FileItem;
+ if (file_item != null) {
+ if (file_item.file_transfer.provider != 0 || file_item.file_transfer.info == null) return null;
+
+ int message_db_id = int.parse(file_item.file_transfer.info);
+ return stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_id(message_db_id, conversation);
+ }
+ MessageItem? message_item = content_item as MessageItem;
+ if (message_item != null) {
+ return message_item.message;
+ }
+ return null;
+ }
+
+ public ContentItem? get_content_item_for_message_id(Conversation conversation, string message_id) {
+ Row? row = get_content_item_row_for_message_id(conversation, message_id);
+ if (row != null) {
+ return get_item_from_row(row, conversation);
+ }
+ return null;
+ }
+
+ public int get_content_item_id_for_message_id(Conversation conversation, string message_id) {
+ Row? row = get_content_item_row_for_message_id(conversation, message_id);
+ if (row != null) {
+ return row[db.content_item.id];
+ }
+ return -1;
+ }
+
+ private Row? get_content_item_row_for_message_id(Conversation conversation, string message_id) {
+ var content_item_row = db.content_item.select();
+
+ Message? message = null;
+ if (conversation.type_ == Conversation.Type.CHAT) {
+ message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_stanza_id(message_id, conversation);
+ } else {
+ message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_server_id(message_id, conversation);
+ }
+ if (message == null) return null;
+
+ RowOption file_transfer_row = db.file_transfer.select()
+ .with(db.file_transfer.account_id, "=", conversation.account.id)
+ .with(db.file_transfer.counterpart_id, "=", db.get_jid_id(conversation.counterpart))
+ .with(db.file_transfer.info, "=", message.id.to_string())
+ .order_by(db.file_transfer.time, "DESC")
+ .single().row();
+
+ if (file_transfer_row.is_present()) {
+ content_item_row.with(db.content_item.foreign_id, "=", file_transfer_row[db.file_transfer.id])
+ .with(db.content_item.content_type, "=", 2);
+ } else {
+ content_item_row.with(db.content_item.foreign_id, "=", message.id)
+ .with(db.content_item.content_type, "=", 1);
+ }
+ RowOption content_item_row_option = content_item_row.single().row();
+ if (content_item_row_option.is_present()) {
+ return content_item_row_option.inner;
+ }
+ return null;
+ }
+
public ContentItem? get_latest(Conversation conversation) {
Gee.List<ContentItem> items = get_n_latest(conversation, 1);
if (items.size > 0) {
diff --git a/libdino/src/service/message_processor.vala b/libdino/src/service/message_processor.vala
index 8d544b45..770ae0a6 100644
--- a/libdino/src/service/message_processor.vala
+++ b/libdino/src/service/message_processor.vala
@@ -425,24 +425,8 @@ public class MessageProcessor : StreamInteractionModule, Object {
new_message.type_ = MessageStanza.TYPE_CHAT;
}
- if (message.quoted_item_id > 0) {
- ContentItem? content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_item_by_id(conversation, message.quoted_item_id);
- if (content_item != null && content_item.type_ == MessageItem.TYPE) {
- Message? quoted_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_id(((MessageItem) content_item).message.id, conversation);
- if (quoted_message != null) {
- Xep.Replies.set_reply_to(new_message, new Xep.Replies.ReplyTo(quoted_message.from, quoted_message.stanza_id));
-
- string body_with_fallback = "> " + Dino.message_body_without_reply_fallback(quoted_message);
- body_with_fallback = body_with_fallback.replace("\n", "\n> ");
- body_with_fallback += "\n";
- long fallback_length = body_with_fallback.length;
- body_with_fallback += message.body;
- new_message.body = body_with_fallback;
- var fallback_location = new Xep.FallbackIndication.FallbackLocation(0, (int)fallback_length);
- Xep.FallbackIndication.set_fallback(new_message, new Xep.FallbackIndication.Fallback(Xep.Replies.NS_URI, new Xep.FallbackIndication.FallbackLocation[] { fallback_location }));
- }
- }
- }
+ string? fallback = get_fallback_body_set_infos(message, new_message, conversation);
+ new_message.body = fallback == null ? message.body : fallback + message.body;
build_message_stanza(message, new_message, conversation);
pre_message_send(message, new_message, conversation);
@@ -487,6 +471,37 @@ public class MessageProcessor : StreamInteractionModule, Object {
}
});
}
+
+ public string? get_fallback_body_set_infos(Entities.Message message, MessageStanza new_stanza, Conversation conversation) {
+ if (message.quoted_item_id == 0) return null;
+
+ ContentItem? content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_item_by_id(conversation, message.quoted_item_id);
+ if (content_item == null) return null;
+
+ Jid? quoted_sender = stream_interactor.get_module(ContentItemStore.IDENTITY).get_message_sender_for_content_item(conversation, content_item);
+ string? quoted_stanza_id = stream_interactor.get_module(ContentItemStore.IDENTITY).get_message_id_for_content_item(conversation, content_item);
+ if (quoted_sender != null && quoted_stanza_id != null) {
+ Xep.Replies.set_reply_to(new_stanza, new Xep.Replies.ReplyTo(quoted_sender, quoted_stanza_id));
+ }
+
+ string fallback = "> ";
+
+ if (content_item.type_ == MessageItem.TYPE) {
+ Message? quoted_message = ((MessageItem) content_item).message;
+ fallback += Dino.message_body_without_reply_fallback(quoted_message);
+ fallback = fallback.replace("\n", "\n> ");
+ } else if (content_item.type_ == FileItem.TYPE) {
+ FileTransfer? quoted_file = ((FileItem) content_item).file_transfer;
+ fallback += quoted_file.file_name;
+ }
+ fallback += "\n";
+
+ long fallback_length = fallback.length;
+ var fallback_location = new Xep.FallbackIndication.FallbackLocation(0, (int)fallback_length);
+ Xep.FallbackIndication.set_fallback(new_stanza, new Xep.FallbackIndication.Fallback(Xep.Replies.NS_URI, new Xep.FallbackIndication.FallbackLocation[] { fallback_location }));
+
+ return fallback;
+ }
}
public abstract class MessageListener : Xmpp.OrderedListener {
diff --git a/libdino/src/service/message_storage.vala b/libdino/src/service/message_storage.vala
index fbdbcf8a..3dadab7b 100644
--- a/libdino/src/service/message_storage.vala
+++ b/libdino/src/service/message_storage.vala
@@ -116,9 +116,7 @@ public class MessageStorage : StreamInteractionModule, Object {
.outer_join_with(db.message_correction, db.message_correction.message_id, db.message.id)
.outer_join_with(db.reply, db.reply.message_id, db.message.id);
- if (conversation.counterpart.resourcepart == null) {
- query.with_null(db.message.counterpart_resource);
- } else {
+ if (conversation.counterpart.resourcepart != null) {
query.with(db.message.counterpart_resource, "=", conversation.counterpart.resourcepart);
}
diff --git a/libdino/src/service/reactions.vala b/libdino/src/service/reactions.vala
index fa273f39..f65394bb 100644
--- a/libdino/src/service/reactions.vala
+++ b/libdino/src/service/reactions.vala
@@ -10,7 +10,6 @@ public class Dino.Reactions : StreamInteractionModule, Object {
public string id { get { return IDENTITY.id; } }
public signal void reaction_added(Account account, int content_item_id, Jid jid, string reaction);
-// [Signal(detailed=true)]
public signal void reaction_removed(Account account, int content_item_id, Jid jid, string reaction);
private StreamInteractor stream_interactor;
@@ -35,15 +34,19 @@ public class Dino.Reactions : StreamInteractionModule, Object {
if (!reactions.contains(reaction)) {
reactions.add(reaction);
}
- send_reactions(conversation, content_item, reactions);
- reaction_added(conversation.account, content_item.id, conversation.account.bare_jid, reaction);
+ try {
+ send_reactions(conversation, content_item, reactions);
+ reaction_added(conversation.account, content_item.id, conversation.account.bare_jid, reaction);
+ } catch (SendError e) {}
}
public void remove_reaction(Conversation conversation, ContentItem content_item, string reaction) {
Gee.List<string> reactions = get_own_reactions(conversation, content_item);
reactions.remove(reaction);
- send_reactions(conversation, content_item, reactions);
- reaction_removed(conversation.account, content_item.id, conversation.account.bare_jid, reaction);
+ try {
+ send_reactions(conversation, content_item, reactions);
+ reaction_removed(conversation.account, content_item.id, conversation.account.bare_jid, reaction);
+ } catch (SendError e) {}
}
public Gee.List<ReactionUsers> get_item_reactions(Conversation conversation, ContentItem content_item) {
@@ -80,35 +83,28 @@ public class Dino.Reactions : StreamInteractionModule, Object {
return false;
}
- private void send_reactions(Conversation conversation, ContentItem content_item, Gee.List<string> reactions) {
- Message? message = null;
+ private void send_reactions(Conversation conversation, ContentItem content_item, Gee.List<string> reactions) throws SendError {
+ string? message_id = stream_interactor.get_module(ContentItemStore.IDENTITY).get_message_id_for_content_item(conversation, content_item);
+ if (message_id == null) throw new SendError.Misc("No message for content_item");
- FileItem? file_item = content_item as FileItem;
- if (file_item != null) {
- int message_id = int.parse(file_item.file_transfer.info);
- message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_id(message_id, conversation);
- }
- MessageItem? message_item = content_item as MessageItem;
- if (message_item != null) {
- message = message_item.message;
- }
+ XmppStream? stream = stream_interactor.get_stream(conversation.account);
+ if (stream == null) throw new SendError.NoStream("");
- if (message == null) {
- return;
- }
+ var reactions_module = stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY);
- XmppStream stream = stream_interactor.get_stream(conversation.account);
- if (conversation.type_ == Conversation.Type.GROUPCHAT || conversation.type_ == Conversation.Type.GROUPCHAT_PM) {
- if (conversation.type_ == Conversation.Type.GROUPCHAT) {
- stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY).send_reaction(stream, conversation.counterpart, "groupchat", message.server_id ?? message.stanza_id, reactions);
- } else if (conversation.type_ == Conversation.Type.GROUPCHAT_PM) {
- stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY).send_reaction(stream, conversation.counterpart, "chat", message.server_id ?? message.stanza_id, reactions);
- }
+ if (conversation.type_ == Conversation.Type.GROUPCHAT) {
+ reactions_module.send_reaction.begin(stream, conversation.counterpart, "groupchat", message_id, reactions);
// We save the reaction when it gets reflected back to us
+ } else if (conversation.type_ == Conversation.Type.GROUPCHAT_PM) {
+ reactions_module.send_reaction(stream, conversation.counterpart, "chat", message_id, reactions);
} else if (conversation.type_ == Conversation.Type.CHAT) {
- stream.get_module(Xmpp.Xep.Reactions.Module.IDENTITY).send_reaction(stream, conversation.counterpart, "chat", message.stanza_id, reactions);
int64 now_millis = GLib.get_real_time () / 1000;
- save_chat_reactions(conversation.account, conversation.account.bare_jid, content_item.id, now_millis, reactions);
+ reactions_module.send_reaction.begin(stream, conversation.counterpart, "chat", message_id, reactions, (_, res) => {
+ try {
+ reactions_module.send_reaction.end(res);
+ save_chat_reactions(conversation.account, conversation.account.bare_jid, content_item.id, now_millis, reactions);
+ } catch (SendError e) {}
+ });
}
}
@@ -251,11 +247,11 @@ public class Dino.Reactions : StreamInteractionModule, Object {
Message reaction_message = yield stream_interactor.get_module(MessageProcessor.IDENTITY).parse_message_stanza(account, stanza);
Conversation conversation = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation_for_message(reaction_message);
- Message? message = get_message_for_reaction(conversation, message_id);
+ int content_item_id = stream_interactor.get_module(ContentItemStore.IDENTITY).get_content_item_id_for_message_id(conversation, message_id);
var reaction_info = new ReactionInfo() { account=account, from_jid=from_jid, reactions=reactions, stanza=stanza, received_time=new DateTime.now() };
- if (message != null) {
- process_reaction_for_message(message.id, reaction_info);
+ if (content_item_id != -1) {
+ process_reaction_for_message(content_item_id, reaction_info);
return;
}
@@ -317,30 +313,12 @@ public class Dino.Reactions : StreamInteractionModule, Object {
}
}
- private void process_reaction_for_message(int message_db_id, ReactionInfo reaction_info) {
+ private void process_reaction_for_message(int content_item_id, ReactionInfo reaction_info) {
Account account = reaction_info.account;
MessageStanza stanza = reaction_info.stanza;
Jid from_jid = reaction_info.from_jid;
Gee.List<string> reactions = reaction_info.reactions;
- RowOption file_transfer_row = db.file_transfer.select()
- .with(db.file_transfer.account_id, "=", account.id)
- .with(db.file_transfer.info, "=", message_db_id.to_string())
- .single().row(); // TODO better
-
- var content_item_row = db.content_item.select();
-
- if (file_transfer_row.is_present()) {
- content_item_row.with(db.content_item.foreign_id, "=", file_transfer_row[db.file_transfer.id])
- .with(db.content_item.content_type, "=", 2);
- } else {
- content_item_row.with(db.content_item.foreign_id, "=", message_db_id)
- .with(db.content_item.content_type, "=", 1);
- }
- var content_item_row_opt = content_item_row.single().row();
- if (!content_item_row_opt.is_present()) return;
- int content_item_id = content_item_row_opt[db.content_item.id];
-
// Get reaction time
DateTime? reaction_time = null;
DelayedDelivery.MessageFlag? delayed_message_flag = DelayedDelivery.MessageFlag.get_flag(stanza);
diff --git a/libdino/src/service/replies.vala b/libdino/src/service/replies.vala
index 6a9bced4..97db70ee 100644
--- a/libdino/src/service/replies.vala
+++ b/libdino/src/service/replies.vala
@@ -77,22 +77,7 @@ public class Dino.Replies : StreamInteractionModule, Object {
Xep.Replies.ReplyTo? reply_to = Xep.Replies.get_reply_to(stanza);
if (reply_to == null) return;
- Message? quoted_message = null;
- if (conversation.type_ == Conversation.Type.GROUPCHAT) {
- quoted_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_server_id(reply_to.to_message_id, conversation);
- } else {
- quoted_message = stream_interactor.get_module(MessageStorage.IDENTITY).get_message_by_stanza_id(reply_to.to_message_id, conversation);
- }
- if (quoted_message == null) {
- db.reply.upsert()
- .value(db.reply.message_id, message.id, true)
- .value(db.reply.quoted_message_stanza_id, reply_to.to_message_id)
- .value(db.reply.quoted_message_from, reply_to.to_jid.to_string())
- .perform();
- return;
- }
-
- ContentItem? quoted_content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_item_by_foreign(conversation, 1, quoted_message.id);
+ ContentItem? quoted_content_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_content_item_for_message_id(conversation, reply_to.to_message_id);
if (quoted_content_item == null) return;
set_message_is_reply_to(message, quoted_content_item);
diff --git a/libdino/src/service/util.vala b/libdino/src/service/util.vala
index 3cbb48d9..1d04ffcf 100644
--- a/libdino/src/service/util.vala
+++ b/libdino/src/service/util.vala
@@ -1,4 +1,5 @@
using Dino.Entities;
+using Qlite;
namespace Dino {
diff --git a/main/src/ui/conversation_content_view/file_widget.vala b/main/src/ui/conversation_content_view/file_widget.vala
index 8dbc3dc8..52a26f33 100644
--- a/main/src/ui/conversation_content_view/file_widget.vala
+++ b/main/src/ui/conversation_content_view/file_widget.vala
@@ -10,19 +10,44 @@ namespace Dino.Ui {
public class FileMetaItem : ConversationSummary.ContentMetaItem {
private StreamInteractor stream_interactor;
+ private FileItem file_item;
+ private FileTransfer file_transfer;
public FileMetaItem(ContentItem content_item, StreamInteractor stream_interactor) {
base(content_item);
this.stream_interactor = stream_interactor;
+ this.file_item = content_item as FileItem;
+ this.file_transfer = file_item.file_transfer;
}
public override Object? get_widget(Plugins.ConversationItemWidgetInterface outer, Plugins.WidgetType type) {
- FileItem file_item = content_item as FileItem;
- FileTransfer transfer = file_item.file_transfer;
- return new FileWidget(stream_interactor, transfer);
+ return new FileWidget(stream_interactor, file_transfer);
}
- public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) { return null; }
+ public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) {
+ if (file_transfer.provider != 0 || file_transfer.info == null) return null;
+
+ Gee.List<Plugins.MessageAction> actions = new ArrayList<Plugins.MessageAction>();
+
+ if (stream_interactor.get_module(ContentItemStore.IDENTITY).get_message_id_for_content_item(file_item.conversation, content_item) != null) {
+ Plugins.MessageAction reply_action = new Plugins.MessageAction();
+ reply_action.icon_name = "mail-reply-sender-symbolic";
+ reply_action.callback = (button, content_meta_item_activated, widget) => {
+ GLib.Application.get_default().activate_action("quote", new GLib.Variant.tuple(new GLib.Variant[] { new GLib.Variant.int32(file_item.conversation.id), new GLib.Variant.int32(content_item.id) }));
+ };
+ actions.add(reply_action);
+
+ Plugins.MessageAction action2 = new Plugins.MessageAction();
+ action2.icon_name = "dino-emoticon-add-symbolic";
+ EmojiChooser chooser = new EmojiChooser();
+ chooser.emoji_picked.connect((emoji) => {
+ stream_interactor.get_module(Reactions.IDENTITY).add_reaction(file_item.conversation, content_item, emoji);
+ });
+ action2.popover = chooser;
+ actions.add(action2);
+ }
+ return actions;
+ }
}
public class FileWidget : SizeRequestBox {
diff --git a/main/src/ui/conversation_content_view/message_widget.vala b/main/src/ui/conversation_content_view/message_widget.vala
index f4e1d22c..fb4ba162 100644
--- a/main/src/ui/conversation_content_view/message_widget.vala
+++ b/main/src/ui/conversation_content_view/message_widget.vala
@@ -198,7 +198,7 @@ public class MessageMetaItem : ContentMetaItem {
if (quoted_content_item != null) {
var quote_model = new Quote.Model.from_content_item(quoted_content_item, message_item.conversation, stream_interactor);
quote_model.jump_to.connect(() => {
- GLib.Application.get_default().activate_action("jump-to-conversation-message", new GLib.Variant.tuple(new GLib.Variant[] { new GLib.Variant.int32(message_item.conversation.id), new GLib.Variant.int32(message_item.id) }));
+ GLib.Application.get_default().activate_action("jump-to-conversation-message", new GLib.Variant.tuple(new GLib.Variant[] { new GLib.Variant.int32(message_item.conversation.id), new GLib.Variant.int32(quoted_content_item.id) }));
});
var quote_widget = Quote.get_widget(quote_model);
outer.set_widget(quote_widget, Plugins.WidgetType.GTK4, 1);
@@ -226,7 +226,7 @@ public class MessageMetaItem : ContentMetaItem {
Plugins.MessageAction reply_action = new Plugins.MessageAction();
reply_action.icon_name = "mail-reply-sender-symbolic";
reply_action.callback = (button, content_meta_item_activated, widget) => {
- GLib.Application.get_default().activate_action("quote", new GLib.Variant.tuple(new GLib.Variant[] { new GLib.Variant.int32(message_item.conversation.id), new GLib.Variant.int32(message_item.id) }));
+ GLib.Application.get_default().activate_action("quote", new GLib.Variant.tuple(new GLib.Variant[] { new GLib.Variant.int32(message_item.conversation.id), new GLib.Variant.int32(content_item.id) }));
};
actions.add(reply_action);
diff --git a/main/src/ui/conversation_content_view/quote_widget.vala b/main/src/ui/conversation_content_view/quote_widget.vala
index f627c852..cfe2f153 100644
--- a/main/src/ui/conversation_content_view/quote_widget.vala
+++ b/main/src/ui/conversation_content_view/quote_widget.vala
@@ -27,7 +27,8 @@ namespace Dino.Ui.Quote {
var message = ((MessageItem) content_item).message;
this.message = Dino.message_body_without_reply_fallback(message);
} else if (content_item.type_ == FileItem.TYPE) {
- this.message = "[File]";
+ var file_transfer = ((FileItem) content_item).file_transfer;
+ this.message = _("File") + ": " + file_transfer.file_name;
}
this.message_time = content_item.time;
diff --git a/xmpp-vala/src/module/message/module.vala b/xmpp-vala/src/module/message/module.vala
index 2eced5c1..ef39a663 100644
--- a/xmpp-vala/src/module/message/module.vala
+++ b/xmpp-vala/src/module/message/module.vala
@@ -17,7 +17,11 @@ namespace Xmpp {
public async void send_message(XmppStream stream, MessageStanza message) throws IOStreamError {
yield send_pipeline.run(stream, message);
- yield stream.write_async(message.stanza);
+ try {
+ yield stream.write_async(message.stanza);
+ } catch (IOStreamError e) {
+ throw new SendError.IO(e.message);
+ }
}
public async void received_message_stanza_async(XmppStream stream, StanzaNode node) {
diff --git a/xmpp-vala/src/module/xep/0444_reactions.vala b/xmpp-vala/src/module/xep/0444_reactions.vala
index 3501ca42..8e8a1706 100644
--- a/xmpp-vala/src/module/xep/0444_reactions.vala
+++ b/xmpp-vala/src/module/xep/0444_reactions.vala
@@ -11,7 +11,7 @@ public class Module : XmppStreamModule {
private ReceivedPipelineListener received_pipeline_listener = new ReceivedPipelineListener();
- public void send_reaction(XmppStream stream, Jid jid, string stanza_type, string message_id, Gee.List<string> reactions) {
+ public async void send_reaction(XmppStream stream, Jid jid, string stanza_type, string message_id, Gee.List<string> reactions) throws SendError {
StanzaNode reactions_node = new StanzaNode.build("reactions", NS_URI).add_self_xmlns();
reactions_node.put_attribute("id", message_id);
foreach (string reaction in reactions) {
@@ -25,7 +25,7 @@ public class Module : XmppStreamModule {
MessageProcessingHints.set_message_hint(message, MessageProcessingHints.HINT_STORE);
- stream.get_module(MessageModule.IDENTITY).send_message.begin(stream, message);
+ yield stream.get_module(MessageModule.IDENTITY).send_message(stream, message);
}
public override void attach(XmppStream stream) {
diff --git a/xmpp-vala/src/util.vala b/xmpp-vala/src/util.vala
index 6c0d0c9b..fda21f88 100644
--- a/xmpp-vala/src/util.vala
+++ b/xmpp-vala/src/util.vala
@@ -38,3 +38,11 @@ public long from_hex(string numeral) {
}
}
+
+namespace Xmpp {
+ public errordomain SendError {
+ IO,
+ NoStream,
+ Misc
+ }
+}