diff --git a/main/data/theme.css b/main/data/theme.css index d581cac2..b8def4e1 100644 --- a/main/data/theme.css +++ b/main/data/theme.css @@ -111,6 +111,27 @@ window.dino-main .call-box { margin: 12px 16px 12px 12px; } +window.dino-main .file-image-widget { + border: 1px solid alpha(@theme_fg_color, 0.1); + border-radius: 3px; +} + +window.dino-main .file-image-widget .file-box-outer { + color: #eee; + background: rgba(0, 0, 0, 0.5); +} + +window.dino-main .file-image-widget .file-box-outer button { + color: #eee; + background: transparent; + border: none; + box-shadow: none; +} + +window.dino-main .file-image-widget .file-box-outer button:hover { + background: rgba(100, 100, 100, 0.5); +} + window.dino-main .call-box-outer.incoming { border-color: alpha(@theme_selected_bg_color, 0.3); } diff --git a/main/src/ui/conversation_content_view/file_default_widget.vala b/main/src/ui/conversation_content_view/file_default_widget.vala index 9832e527..dc952b30 100644 --- a/main/src/ui/conversation_content_view/file_default_widget.vala +++ b/main/src/ui/conversation_content_view/file_default_widget.vala @@ -15,7 +15,7 @@ public class FileDefaultWidget : EventBox { [GtkChild] public unowned Image content_type_image; [GtkChild] public unowned Spinner spinner; [GtkChild] public unowned EventBox stack_event_box; - [GtkChild] public MenuButton file_menu; + [GtkChild] public unowned MenuButton file_menu; public ModelButton file_open_button; public ModelButton file_save_button; @@ -23,10 +23,10 @@ public class FileDefaultWidget : EventBox { private FileTransfer.State state; public FileDefaultWidget() { - this.enter_notify_event.connect(on_pointer_entered); - this.leave_notify_event.connect(on_pointer_left); + this.enter_notify_event.connect(on_pointer_entered_event); + this.leave_notify_event.connect(on_pointer_left_event); file_open_button = new ModelButton() { text=_("Open"), visible=true }; - file_save_button = new ModelButton() { text=_("Save as..."), visible=true }; + file_save_button = new ModelButton() { text=_("Save as…"), visible=true }; } public void update_file_info(string? mime_type, FileTransfer.State state, long size) { @@ -41,15 +41,19 @@ public class FileDefaultWidget : EventBox { case FileTransfer.State.COMPLETE: mime_label.label = mime_description; image_stack.set_visible_child_name("content_type_image"); + + // Create a menu Gtk.PopoverMenu popover_menu = new Gtk.PopoverMenu(); Box file_menu_box = new Box(Orientation.VERTICAL, 0) { margin=10, visible=true }; file_menu_box.add(file_open_button); file_menu_box.add(file_save_button); popover_menu.add(file_menu_box); file_menu.popover = popover_menu; - file_menu.clicked.connect(() => { + file_menu.button_release_event.connect(() => { popover_menu.visible = true; + return true; }); + popover_menu.closed.connect(on_pointer_left); break; case FileTransfer.State.IN_PROGRESS: mime_label.label = _("Downloading %s…").printf(get_size_string(size)); @@ -74,9 +78,7 @@ public class FileDefaultWidget : EventBox { } } - private bool on_pointer_entered(Gdk.EventCrossing event) { - if (event.detail == Gdk.NotifyType.INFERIOR) return false; - + private bool on_pointer_entered_event(Gdk.EventCrossing event) { event.get_window().set_cursor(new Cursor.for_display(Gdk.Display.get_default(), CursorType.HAND2)); content_type_image.opacity = 0.7; if (state == FileTransfer.State.NOT_STARTED) { @@ -88,17 +90,21 @@ public class FileDefaultWidget : EventBox { return false; } - private bool on_pointer_left(Gdk.EventCrossing event) { + private bool on_pointer_left_event(Gdk.EventCrossing event) { if (event.detail == Gdk.NotifyType.INFERIOR) return false; - if (file_menu.popover.visible == true) return false; + if (file_menu.popover != null && file_menu.popover.visible) return false; event.get_window().set_cursor(new Cursor.for_display(Gdk.Display.get_default(), CursorType.XTERM)); + on_pointer_left(); + return false; + } + + private void on_pointer_left() { content_type_image.opacity = 0.5; if (state == FileTransfer.State.NOT_STARTED) { image_stack.set_visible_child_name("content_type_image"); } file_menu.visible = false; - return false; } private static string get_file_icon_name(string? mime_type) { diff --git a/main/src/ui/conversation_content_view/file_image_widget.vala b/main/src/ui/conversation_content_view/file_image_widget.vala index f7841736..91eddd93 100644 --- a/main/src/ui/conversation_content_view/file_image_widget.vala +++ b/main/src/ui/conversation_content_view/file_image_widget.vala @@ -16,7 +16,7 @@ public class FileImageWidget : EventBox { this.halign = Align.START; this.events = EventMask.POINTER_MOTION_MASK; - Util.force_css(this, "* { border: 1px solid alpha(@theme_fg_color, 0.1); border-radius: 3px; }"); + this.get_style_context().add_class("file-image-widget"); } public async void load_from_file(File file, string file_name, int MAX_WIDTH=600, int MAX_HEIGHT=300) throws GLib.Error { @@ -52,20 +52,18 @@ public class FileImageWidget : EventBox { file_default_widget_controller = new FileDefaultWidgetController(file_default_widget); file_default_widget_controller.set_file(file, file_name, mime_type); - Util.force_css(file_default_widget, "* { color: #eee; }"); - Util.force_css(file_default_widget, "* { background-color: rgba(0, 0, 0, 0.5); }"); - Overlay overlay = new Overlay() { visible=true }; overlay.add(image); overlay.add_overlay(file_default_widget); this.enter_notify_event.connect((event) => { - if (event.detail == Gdk.NotifyType.INFERIOR) return false; file_default_widget.visible = true; return false; }); this.leave_notify_event.connect((event) => { if (event.detail == Gdk.NotifyType.INFERIOR) return false; + if (file_default_widget.file_menu.popover != null && file_default_widget.file_menu.popover.visible) return false; + file_default_widget.visible = false; return false; }); diff --git a/main/src/ui/conversation_content_view/file_widget.vala b/main/src/ui/conversation_content_view/file_widget.vala index d48185ec..0040db3c 100644 --- a/main/src/ui/conversation_content_view/file_widget.vala +++ b/main/src/ui/conversation_content_view/file_widget.vala @@ -123,6 +123,7 @@ public class FileDefaultWidgetController : Object { private StreamInteractor? stream_interactor; private string file_uri; + private string file_name; private FileTransfer.State state; public FileDefaultWidgetController(FileDefaultWidget widget) { @@ -136,7 +137,7 @@ public class FileDefaultWidgetController : Object { this.file_transfer = file_transfer; this.stream_interactor = stream_interactor; - widget.name_label.label = file_transfer.file_name; + widget.name_label.label = file_name = file_transfer.file_name; file_transfer.bind_property("path", this, "file-transfer-path"); file_transfer.bind_property("state", this, "file-transfer-state"); @@ -152,7 +153,7 @@ public class FileDefaultWidgetController : Object { public void set_file(File file, string file_name, string? mime_type) { file_uri = file.get_uri(); state = FileTransfer.State.COMPLETE; - widget.name_label.label = file_name; + widget.name_label.label = this.file_name = file_name; widget.update_file_info(mime_type, state, -1); } @@ -170,47 +171,27 @@ public class FileDefaultWidgetController : Object { } } - private void save_as(Gtk.Dialog dialog, int response_id) { - var save_dialog = dialog as Gtk.FileChooserDialog; - File file_src; - switch (response_id) { - case Gtk.ResponseType.ACCEPT: - file_src = GLib.File.new_for_uri(file_uri); - try{ - file_src.copy(save_dialog.get_file(), GLib.FileCopyFlags.OVERWRITE, null); - } catch (Error err) { - warning("Failed copy file %s - %s", file_uri, err.message); - } - break; - default: - break; - } - dialog.destroy(); - } - private void save_file() { - var save_dialog = new Gtk.FileChooserDialog("Save as...", this as Gtk.Window, Gtk.FileChooserAction.SAVE, Gtk.Stock.CANCEL, Gtk.ResponseType.CANCEL, Gtk.Stock.SAVE, Gtk.ResponseType.ACCEPT); + var save_dialog = new FileChooserNative(_("Save as…"), widget.get_toplevel() as Gtk.Window, FileChooserAction.SAVE, null, null); save_dialog.set_do_overwrite_confirmation(true); save_dialog.set_modal(true); - try { - (save_dialog as Gtk.FileChooser).set_current_name(GLib.Uri.escape_string(GLib.Path.get_basename(file_uri))); - (save_dialog as Gtk.FileChooser).set_uri(GLib.Uri.escape_string(GLib.Path.get_basename(GLib.Uri.unescape_string(file_uri)))); - } catch (GLib.Error error) { - warning("Faild to open save dialog: %s\n", error.message); + save_dialog.set_current_name(file_name); + + if (save_dialog.run() == Gtk.ResponseType.ACCEPT) { + try{ + GLib.File.new_for_uri(file_uri).copy(save_dialog.get_file(), GLib.FileCopyFlags.OVERWRITE, null); + } catch (Error err) { + warning("Failed copy file %s - %s", file_uri, err.message); + } } - save_dialog.response.connect(save_as); - save_dialog.show(); } private bool on_clicked(EventButton event_button) { switch (state) { case FileTransfer.State.COMPLETE: - if (event_button.button == 1 && this.widget.file_menu.popover.visible == false) { + if (event_button.button == 1) { open_file(); } - if (event_button.button == 3 && this.widget.file_menu.popover.visible == false) { - save_file(); - } break; case FileTransfer.State.NOT_STARTED: assert(stream_interactor != null && file_transfer != null);