diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 2a5377a1..9c5b06ff 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -111,7 +111,6 @@ SOURCES src/ui/conversation_summary/message_textview.vala src/ui/conversation_summary/slashme_message_display.vala src/ui/conversation_summary/subscription_notification.vala - src/ui/conversation_titlebar/file_entry.vala src/ui/conversation_titlebar/menu_entry.vala src/ui/conversation_titlebar/occupants_entry.vala src/ui/conversation_titlebar/view.vala diff --git a/main/data/theme.css b/main/data/theme.css index d2723d54..e7d58ffb 100644 --- a/main/data/theme.css +++ b/main/data/theme.css @@ -9,6 +9,14 @@ window.dino-main headerbar.dino-left label.title { color: transparent; } +window.dino-main .dino-conversation { + background: @theme_base_color; +} + +window.dino-main .dino-conversation undershoot { + background: none; +} + window.dino-main .dino-chatinput frame box { background: @theme_base_color; } diff --git a/main/src/ui/chat_input/view.vala b/main/src/ui/chat_input/view.vala index c9db730a..93f32fb7 100644 --- a/main/src/ui/chat_input/view.vala +++ b/main/src/ui/chat_input/view.vala @@ -7,12 +7,11 @@ using Xmpp; namespace Dino.Ui.ChatInput { -[GtkTemplate (ui = "/im/dino/Dino/chat_input.ui")] public class View : Box { - [GtkChild] private ScrolledWindow scrolled; - [GtkChild] private TextView text_input; - [GtkChild] private Box box; + private ScrolledWindow scrolled; + private TextView text_input; + private Box outer_box; public string text { owned get { return text_input.buffer.text; } @@ -26,20 +25,62 @@ public class View : Box { private OccupantsTabCompletor occupants_tab_completor; private SmileyConverter smiley_converter; private EditHistory edit_history; - private EncryptionButton encryption_widget = new EncryptionButton() { yalign=0, visible=true }; + private EncryptionButton encryption_widget; + private Button file_button = new Button.from_icon_name("mail-attachment-symbolic", IconSize.MENU) { margin_top=3, valign=Align.START, relief=ReliefStyle.NONE }; + private Separator file_separator = new Separator(Orientation.VERTICAL); public View(StreamInteractor stream_interactor) { this.stream_interactor = stream_interactor; - occupants_tab_completor = new OccupantsTabCompletor(stream_interactor, text_input); - smiley_converter = new SmileyConverter(stream_interactor, text_input); - edit_history = new EditHistory(text_input, GLib.Application.get_default()); - box.add(encryption_widget); + outer_box = new Box(Orientation.HORIZONTAL, 0) { visible=true }; + + file_button.get_style_context().add_class("dino-chatinput-button"); + file_button.clicked.connect(() => { + PreviewFileChooserNative chooser = new PreviewFileChooserNative("Select file", get_toplevel() as Gtk.Window, FileChooserAction.OPEN, "Select", "Cancel"); + + // long max_file_size = stream_interactor.get_module(Manager.IDENTITY).get_max_file_size(conversation.account); + // if (max_file_size != -1) { + // FileFilter filter = new FileFilter(); + // filter.add_custom(FileFilterFlags.URI, (filter_info) => { + // File file = File.new_for_uri(filter_info.uri); + // FileInfo file_info = file.query_info("*", FileQueryInfoFlags.NONE); + // return file_info.get_size() <= max_file_size; + // }); + // chooser.set_filter(filter); + // } + if (chooser.run() == Gtk.ResponseType.ACCEPT) { + string uri = chooser.get_filename(); + stream_interactor.get_module(FileManager.IDENTITY).send_file(uri, conversation); + } + }); + outer_box.add(file_button); + outer_box.add(file_separator); + + scrolled = new ScrolledWindow(null, null) { max_content_height=300, propagate_natural_height=true, visible=true }; + text_input = new TextView() { valign=Align.CENTER, wrap_mode=WrapMode.WORD_CHAR, margin=8, can_focus=true, hexpand=true, visible=true }; + + scrolled.add(text_input); + outer_box.add(scrolled); + + encryption_widget = new EncryptionButton() { margin_top=3, valign=Align.START, visible=true }; encryption_widget.get_style_context().add_class("dino-chatinput-button"); + outer_box.add(encryption_widget); + scrolled.get_vscrollbar().get_preferred_height(out vscrollbar_min_height, null); scrolled.vadjustment.notify["upper"].connect_after(on_upper_notify); text_input.key_press_event.connect(on_text_input_key_press); text_input.buffer.changed.connect(on_text_input_changed); + + Frame frame = new Frame(null) { margin=12, margin_top=0, visible=true }; + Util.force_css(frame, "* { border-radius: 3px; }"); + frame.add(outer_box); + this.add(frame); + + occupants_tab_completor = new OccupantsTabCompletor(stream_interactor, text_input); + smiley_converter = new SmileyConverter(stream_interactor, text_input); + edit_history = new EditHistory(text_input, GLib.Application.get_default()); + + stream_interactor.get_module(FileManager.IDENTITY).upload_available.connect(on_upload_available); } public void initialize_for_conversation(Conversation conversation) { @@ -50,6 +91,10 @@ public class View : Box { if (this.conversation != null) entry_cache[this.conversation] = text_input.buffer.text; this.conversation = conversation; + bool upload_available = stream_interactor.get_module(FileManager.IDENTITY).is_upload_available(conversation); + file_button.visible = upload_available; + file_separator.visible = upload_available; + text_input.buffer.changed.disconnect(on_text_input_changed); text_input.buffer.text = ""; if (entry_cache.has_key(conversation)) { @@ -135,6 +180,13 @@ public class View : Box { stream_interactor.get_module(ChatInteraction.IDENTITY).on_message_cleared(conversation); } } + + private void on_upload_available(Account account) { + if (conversation != null && conversation.account.equals(account)) { + file_button.visible = true; + file_separator.visible = true; + } + } } } diff --git a/main/src/ui/conversation_summary/conversation_view.vala b/main/src/ui/conversation_summary/conversation_view.vala index 03dbe554..fac53b7d 100644 --- a/main/src/ui/conversation_summary/conversation_view.vala +++ b/main/src/ui/conversation_summary/conversation_view.vala @@ -32,6 +32,7 @@ public class ConversationView : Box, Plugins.ConversationItemCollection { private Mutex reloading_mutex = Mutex(); private bool animate = false; + private bool firstLoad = true; public ConversationView(StreamInteractor stream_interactor) { this.stream_interactor = stream_interactor; @@ -59,7 +60,22 @@ public class ConversationView : Box, Plugins.ConversationItemCollection { Util.force_base_background(this); } + // Workaround GTK TextView issues: Delay first load of contents public void initialize_for_conversation(Conversation? conversation) { + if (firstLoad) { + int timeout = firstLoad ? 1000 : 0; + Timeout.add(timeout, () => { + initialize_for_conversation_(conversation); + return false; + }); + firstLoad = false; + } else { + initialize_for_conversation_(conversation); + } + + } + + private void initialize_for_conversation_(Conversation? conversation) { Dino.Application app = Dino.Application.get_default(); if (this.conversation != null) { foreach (Plugins.ConversationItemPopulator populator in app.plugin_registry.conversation_item_populators) { diff --git a/main/src/ui/conversation_titlebar/file_entry.vala b/main/src/ui/conversation_titlebar/file_entry.vala deleted file mode 100644 index fb6ac3a0..00000000 --- a/main/src/ui/conversation_titlebar/file_entry.vala +++ /dev/null @@ -1,71 +0,0 @@ -using Gtk; - -using Dino.Entities; - -namespace Dino.Ui { - -public class FileEntry : Plugins.ConversationTitlebarEntry, Object { - public string id { get { return "send_files"; } } - - StreamInteractor stream_interactor; - - public FileEntry(StreamInteractor stream_interactor) { - this.stream_interactor = stream_interactor; - } - - public double order { get { return 4; } } - public Plugins.ConversationTitlebarWidget? get_widget(Plugins.WidgetType type) { - if (type == Plugins.WidgetType.GTK) { - return new FileWidget(stream_interactor) { visible=true }; - } - return null; - } -} - -public class FileWidget : Button, Plugins.ConversationTitlebarWidget { - - private const int PREVIEW_SIZE = 180; - private const int PREVIEW_PADDING = 3; - - private Conversation? conversation; - private StreamInteractor stream_interactor; - - public FileWidget(StreamInteractor stream_interactor) { - this.stream_interactor = stream_interactor; - image = new Image.from_icon_name("mail-attachment-symbolic", IconSize.MENU); - clicked.connect(on_clicked); - stream_interactor.get_module(FileManager.IDENTITY).upload_available.connect(on_upload_available); - } - - public void on_clicked() { - PreviewFileChooserNative chooser = new PreviewFileChooserNative("Select file", get_toplevel() as Window, FileChooserAction.OPEN, "Select", "Cancel"); - -// long max_file_size = stream_interactor.get_module(Manager.IDENTITY).get_max_file_size(conversation.account); -// if (max_file_size != -1) { -// FileFilter filter = new FileFilter(); -// filter.add_custom(FileFilterFlags.URI, (filter_info) => { -// File file = File.new_for_uri(filter_info.uri); -// FileInfo file_info = file.query_info("*", FileQueryInfoFlags.NONE); -// return file_info.get_size() <= max_file_size; -// }); -// chooser.set_filter(filter); -// } - if (chooser.run() == Gtk.ResponseType.ACCEPT) { - string uri = chooser.get_filename(); - stream_interactor.get_module(FileManager.IDENTITY).send_file(uri, conversation); - } - } - - public void on_upload_available(Account account) { - if (conversation != null && conversation.account.equals(account)) { - visible = true; - } - } - - public new void set_conversation(Conversation conversation) { - this.conversation = conversation; - visible = stream_interactor.get_module(FileManager.IDENTITY).is_upload_available(conversation); - } -} - -} diff --git a/main/src/ui/conversation_titlebar/view.vala b/main/src/ui/conversation_titlebar/view.vala index baa036a8..d01cd9bb 100644 --- a/main/src/ui/conversation_titlebar/view.vala +++ b/main/src/ui/conversation_titlebar/view.vala @@ -23,7 +23,6 @@ public class ConversationTitlebar : Gtk.HeaderBar { Application app = GLib.Application.get_default() as Application; app.plugin_registry.register_contact_titlebar_entry(new MenuEntry(stream_interactor)); app.plugin_registry.register_contact_titlebar_entry(new OccupantsEntry(stream_interactor, window)); - app.plugin_registry.register_contact_titlebar_entry(new FileEntry(stream_interactor)); foreach(var e in app.plugin_registry.conversation_titlebar_entries) { Plugins.ConversationTitlebarWidget widget = e.get_widget(Plugins.WidgetType.GTK); diff --git a/main/src/ui/unified_window.vala b/main/src/ui/unified_window.vala index 5995ea64..ac069697 100644 --- a/main/src/ui/unified_window.vala +++ b/main/src/ui/unified_window.vala @@ -75,8 +75,8 @@ public class UnifiedWindow : Window { filterable_conversation_list = new ConversationSelector.View(stream_interactor) { visible=true }; Grid grid = new Grid() { orientation=Orientation.VERTICAL, visible=true }; + grid.get_style_context().add_class("dino-conversation"); grid.add(conversation_frame); - grid.add(new Separator(Orientation.HORIZONTAL) { visible=true }); grid.add(chat_input); paned.set_position(300); diff --git a/xmpp-vala/src/module/xep/0368_srv_records_tls.vala b/xmpp-vala/src/module/xep/0368_srv_records_tls.vala index a98e6769..8da8ba0c 100644 --- a/xmpp-vala/src/module/xep/0368_srv_records_tls.vala +++ b/xmpp-vala/src/module/xep/0368_srv_records_tls.vala @@ -45,7 +45,7 @@ public class TlsConnectionProvider : ConnectionProvider { } } - public override string get_id() { return "start_tls"; } + public override string get_id() { return "srv_records"; } } }