aboutsummaryrefslogtreecommitdiff
path: root/main/src/ui/chat_input
diff options
context:
space:
mode:
Diffstat (limited to 'main/src/ui/chat_input')
-rw-r--r--main/src/ui/chat_input/chat_input_controller.vala72
-rw-r--r--main/src/ui/chat_input/chat_text_view.vala2
-rw-r--r--main/src/ui/chat_input/view.vala99
3 files changed, 154 insertions, 19 deletions
diff --git a/main/src/ui/chat_input/chat_input_controller.vala b/main/src/ui/chat_input/chat_input_controller.vala
index 660f29bb..c93a9e22 100644
--- a/main/src/ui/chat_input/chat_input_controller.vala
+++ b/main/src/ui/chat_input/chat_input_controller.vala
@@ -27,6 +27,10 @@ public class ChatInputController : Object {
private ChatTextViewController chat_text_view_controller;
private ContentItem? quoted_content_item = null;
+ private ArrayList<File> files_to_send = new ArrayList<File>();
+
+ private HashMap<Conversation, string> message_cache = new HashMap<Conversation, string>(Conversation.hash_func, Conversation.equals_func);
+ private HashMap<Conversation, ArrayList<File>> file_cache = new HashMap<Conversation, ArrayList<File>>(Conversation.hash_func, Conversation.equals_func);
public ChatInputController(ChatInput.View chat_input, StreamInteractor stream_interactor) {
this.chat_input = chat_input;
@@ -45,7 +49,12 @@ public class ChatInputController : Object {
chat_input.chat_text_view.text_view.paste_clipboard.connect(() => clipboard_pasted());
chat_input.chat_text_view.text_view.buffer.changed.connect(on_text_input_changed);
- chat_text_view_controller.send_text.connect(send_text);
+ chat_text_view_controller.send_text.connect(send_message);
+ chat_input.send_button.clicked.connect(send_message);
+
+ chat_input.file_removed.connect((file) => {
+ remove_file_transfer(file);
+ });
chat_input.encryption_widget.encryption_changed.connect(on_encryption_changed);
@@ -84,12 +93,33 @@ public class ChatInputController : Object {
}
public void set_conversation(Conversation conversation) {
- reset_input_field_status();
- this.quoted_content_item = null;
- chat_input.unset_quoted_message();
+ Conversation? previous_conversation = this.conversation;
+
+ // Save state of the previous conversation and unset it
+ if (previous_conversation != null) {
+ message_cache[previous_conversation] = chat_input.chat_text_view.text_view.buffer.text;
+ file_cache[previous_conversation] = files_to_send;
+
+ chat_input.chat_text_view.text_view.buffer.text = "";
+ reset_input_field_status();
+ this.files_to_send = new ArrayList<File>();
+ this.quoted_content_item = null;
+ chat_input.unset_quoted_message();
+ chat_input.clear_files();
+ }
+ // Set the new conversation
this.conversation = conversation;
+ if (message_cache.has_key(conversation)) chat_input.chat_text_view.text_view.buffer.text = message_cache[conversation];
+ if (file_cache.has_key(conversation)) {
+ foreach (File file in file_cache[conversation]) chat_input.add_file(file);
+ files_to_send = file_cache[conversation];
+ }
+
+ message_cache.unset(conversation);
+ file_cache.unset(conversation);
+
chat_input.encryption_widget.set_conversation(conversation);
chat_input.initialize_for_conversation(conversation);
@@ -98,6 +128,16 @@ public class ChatInputController : Object {
update_moderated_input_status(conversation.account);
}
+ public void add_file_transfer(File file) {
+ files_to_send.add(file);
+ chat_input.add_file(file);
+ }
+
+ private void remove_file_transfer(File file) {
+ files_to_send.remove(file);
+ chat_input.remove_file(file);
+ }
+
public void set_file_upload_active(bool active) {
chat_input.set_file_upload_active(active);
}
@@ -129,12 +169,6 @@ public class ChatInputController : Object {
}
private void send_text() {
- // Don't do anything if we're in a NO_SEND state. Don't clear the chat input, don't send.
- if (input_field_status.input_state == Plugins.InputFieldStatus.InputState.NO_SEND) {
- chat_input.highlight_state_description();
- return;
- }
-
string text = chat_input.chat_text_view.text_view.buffer.text;
ContentItem? quoted_content_item_bak = quoted_content_item;
var markups = chat_input.chat_text_view.get_markups();
@@ -200,6 +234,24 @@ public class ChatInputController : Object {
Dino.send_message(conversation, text, quoted_content_item_bak != null ? quoted_content_item_bak.id : 0, null, markups);
}
+ public void send_message() {
+ // Don't do anything if we're in a NO_SEND state. Don't clear the chat input, don't send.
+ if (input_field_status.input_state == Plugins.InputFieldStatus.InputState.NO_SEND) {
+ chat_input.highlight_state_description();
+ return;
+ }
+
+ if (chat_input.chat_text_view.text_view.buffer.text.strip() != "") {
+ send_text();
+ }
+
+ foreach (File file in files_to_send) {
+ stream_interactor.get_module(FileManager.IDENTITY).send_file.begin(file, conversation);
+ }
+ files_to_send = new ArrayList<File>();
+ chat_input.clear_files();
+ }
+
private void on_text_input_changed() {
if (chat_input.chat_text_view.text_view.buffer.text != "") {
stream_interactor.get_module(ChatInteraction.IDENTITY).on_message_entered(conversation);
diff --git a/main/src/ui/chat_input/chat_text_view.vala b/main/src/ui/chat_input/chat_text_view.vala
index 201b60ac..5f072e9a 100644
--- a/main/src/ui/chat_input/chat_text_view.vala
+++ b/main/src/ui/chat_input/chat_text_view.vala
@@ -150,7 +150,7 @@ public class ChatTextView : Box {
if ((state & ModifierType.SHIFT_MASK) > 0) {
// Let the default handler normally insert a newline if shift was hold
return false;
- } else if (text_view.buffer.text.strip() != "") {
+ } else {
send_text();
}
return true;
diff --git a/main/src/ui/chat_input/view.vala b/main/src/ui/chat_input/view.vala
index 8b57a08d..24a40033 100644
--- a/main/src/ui/chat_input/view.vala
+++ b/main/src/ui/chat_input/view.vala
@@ -10,6 +10,8 @@ namespace Dino.Ui.ChatInput {
[GtkTemplate (ui = "/im/dino/Dino/chat_input.ui")]
public class View : Box {
+ public signal void file_removed(File file);
+
public string text {
owned get { return chat_text_view.text_view.buffer.text; }
set { chat_text_view.text_view.buffer.text = value; }
@@ -17,13 +19,16 @@ public class View : Box {
private StreamInteractor stream_interactor;
private Conversation? conversation;
- private HashMap<Conversation, string> entry_cache = new HashMap<Conversation, string>(Conversation.hash_func, Conversation.equals_func);
+
+ private HashMap<File, Widget> file_widgets = new HashMap<File, Widget>();
[GtkChild] public unowned Box quote_box;
+ [GtkChild] public unowned Box file_box;
[GtkChild] public unowned ChatTextView chat_text_view;
[GtkChild] public unowned Button file_button;
[GtkChild] public unowned MenuButton emoji_button;
[GtkChild] public unowned MenuButton encryption_button;
+ [GtkChild] public unowned Button send_button;
[GtkChild] public unowned Separator file_separator;
[GtkChild] public unowned Label chat_input_status;
[GtkChild] public unowned Box unavailable_box;
@@ -54,20 +59,78 @@ public class View : Box {
return this;
}
+ public void add_file(File file) {
+ FileInfo file_info;
+ try {
+ file_info = file.query_info("*", FileQueryInfoFlags.NONE);
+ } catch (Error e) {
+ warning("Failed querying info for file %s", file.get_path());
+ return;
+ }
+ var content_type = new Xmpp.FileContentType.from_file_info(file_info);
+
+ bool is_image = Dino.Util.is_pixbuf_supported_content_type(content_type);
+
+ Widget? widget = null;
+ if (is_image) {
+ var picture = new FixedRatioPicture() {
+ file = file,
+ height_request = 64,
+ width_request = 64,
+ content_fit = ContentFit.COVER,
+ halign = Align.START,
+ margin_top = 8,
+ margin_end = 8,
+ margin_bottom = 4
+ };
+ picture.add_css_class("image-round-corners");
+
+ widget = picture;
+ } else {
+ FileInputWidget file_widget = new FileInputWidget() { margin_top = 8, margin_end = 8, margin_bottom = 4 };
+ file_widget.set_info(file_info, content_type);
+ widget = file_widget;
+ }
+
+ Button remove_button = new Button.from_icon_name("dino-window-close-symbolic") { halign=Align.END, valign=Align.START };
+ remove_button.add_css_class("file-remove-button");
+ remove_button.add_css_class("circular");
+ remove_button.add_css_class("opaque");
+
+ remove_button.clicked.connect(() => {
+ this.file_removed(file);
+ });
+
+ Overlay overlay = new Overlay() { margin_end = 2, halign = Align.START, valign = Align.CENTER };
+ overlay.add_css_class("file-share-wrap");
+ overlay.add_overlay(remove_button);
+ overlay.set_child(widget);
+
+ file_box.append(overlay);
+
+ file_widgets[file] = overlay;
+ }
+
+ public void remove_file(File file) {
+ Widget? file_widget = file_widgets[file];
+
+ if (file_widget == null) {
+ warning("Trying to remove file that doesn't have a widget");
+ return;
+ }
+
+ file_box.remove(file_widget);
+ file_widgets.unset(file);
+ }
+
public void set_file_upload_active(bool active) {
file_button.visible = active;
file_separator.visible = active;
}
public void initialize_for_conversation(Conversation conversation) {
- if (this.conversation != null) entry_cache[this.conversation] = chat_text_view.text_view.buffer.text;
this.conversation = conversation;
- chat_text_view.text_view.buffer.text = "";
- if (entry_cache.has_key(conversation)) {
- chat_text_view.text_view.buffer.text = entry_cache[conversation];
- }
-
update_unavailable_message();
do_focus();
@@ -203,9 +266,29 @@ public class View : Box {
quote_box.visible = false;
}
+ public void clear_files() {
+ Widget? file_child = file_box.get_first_child();
+ while (file_child != null) {
+ file_box.remove(file_child);
+ file_child = file_box.get_first_child();
+ }
+ }
+
public void do_focus() {
chat_text_view.text_view.grab_focus();
}
}
-
}
+
+[GtkTemplate (ui = "/im/dino/Dino/file_input_widget.ui")]
+public class Dino.Ui.FileInputWidget : Box {
+ [GtkChild] public unowned Label name_label;
+ [GtkChild] public unowned Label mime_label;
+ [GtkChild] public unowned Image content_type_image;
+
+ public void set_info(FileInfo file_info, Xmpp.FileContentType? content_type) {
+ name_label.label = file_info.get_name();
+ content_type_image.icon_name = Dino.Ui.FileDefaultWidget.get_file_icon_name(content_type);
+ mime_label.label = content_type != null ? content_type.get_description() : null;
+ }
+} \ No newline at end of file