diff options
author | Patiga <dev@patiga.eu> | 2022-06-28 12:11:17 +0200 |
---|---|---|
committer | fiaxh <git@lightrise.org> | 2024-11-14 10:20:12 -0600 |
commit | aaf4542e6208460c305db4be36b15dc832ddc95a (patch) | |
tree | ec7b60b0f0ea74e21403788e8345336bd0f3939b /main/src/ui/conversation_content_view/file_preview_widget.vala | |
parent | 909f569318835d11703c49fba7dbe49996759f38 (diff) | |
download | dino-aaf4542e6208460c305db4be36b15dc832ddc95a.tar.gz dino-aaf4542e6208460c305db4be36b15dc832ddc95a.zip |
Implement XEP-0447: Stateless file sharing
Diffstat (limited to 'main/src/ui/conversation_content_view/file_preview_widget.vala')
-rw-r--r-- | main/src/ui/conversation_content_view/file_preview_widget.vala | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/main/src/ui/conversation_content_view/file_preview_widget.vala b/main/src/ui/conversation_content_view/file_preview_widget.vala new file mode 100644 index 00000000..e7cee93a --- /dev/null +++ b/main/src/ui/conversation_content_view/file_preview_widget.vala @@ -0,0 +1,90 @@ +using Gee; +using Gdk; +using Gtk; +using Xmpp; + +using Dino.Entities; + +namespace Dino.Ui { + + public class FilePreviewWidget : Box { + + private ScalingImage image; + FileDefaultWidget file_default_widget; + FileDefaultWidgetController file_default_widget_controller; + + public FilePreviewWidget() { + this.halign = Align.START; + + this.add_css_class("file-preview-widget"); + } + + public async void load_from_thumbnail(FileTransfer file_transfer, StreamInteractor stream_interactor, int MAX_WIDTH=600, int MAX_HEIGHT=300) throws GLib.Error { + Thread<ScalingImage?> thread = new Thread<ScalingImage?> (null, () => { + ScalingImage image = new ScalingImage() { halign=Align.START, visible = true, max_width = MAX_WIDTH, max_height = MAX_HEIGHT }; + Gdk.Pixbuf? pixbuf = null; + foreach (Xep.JingleContentThumbnails.Thumbnail thumbnail in file_transfer.thumbnails) { + pixbuf = ImageFileMetadataProvider.parse_thumbnail(thumbnail); + if (pixbuf != null) { + break; + } + } + if (pixbuf == null) { + warning("Can't load thumbnails of file %s", file_transfer.file_name); + Idle.add(load_from_thumbnail.callback); + throw new Error(-1, 0, "Error loading preview image"); + } + // TODO: should this be executed? If yes, before or after scaling + pixbuf = pixbuf.apply_embedded_orientation(); + + if (file_transfer.width > 0 && file_transfer.height > 0) { + pixbuf = pixbuf.scale_simple(file_transfer.width, file_transfer.height, InterpType.BILINEAR); + } else { + warning("Preview: Not scaling image, width: %d, height: %d\n", file_transfer.width, file_transfer.height); + } + if (pixbuf == null) { + warning("Can't scale thumbnail %s", file_transfer.file_name); + throw new Error(-1, 0, "Error scaling preview image"); + } + + image.load(pixbuf); + Idle.add(load_from_thumbnail.callback); + return image; + }); + yield; + this.image = thread.join(); + + file_default_widget = new FileDefaultWidget() { valign=Align.END, vexpand=false, visible=false }; + file_default_widget.image_stack.visible = false; + file_default_widget_controller = new FileDefaultWidgetController(file_default_widget); + file_default_widget_controller.set_file_transfer(file_transfer, stream_interactor); + + Overlay overlay = new Overlay(); + overlay.set_child(image); + overlay.add_overlay(file_default_widget); + overlay.set_measure_overlay(image, true); + overlay.set_clip_overlay(file_default_widget, true); + + EventControllerMotion this_motion_events = new EventControllerMotion(); + this.add_controller(this_motion_events); + this_motion_events.enter.connect(() => { + file_default_widget.visible = true; + }); + this_motion_events.leave.connect(() => { + if (file_default_widget.file_menu.popover != null && file_default_widget.file_menu.popover.visible) return; + + file_default_widget.visible = false; + }); + GestureClick gesture_click_controller = new GestureClick(); + gesture_click_controller.set_button(1); // listen for left clicks + this.add_controller(gesture_click_controller); + gesture_click_controller.pressed.connect((n_press, x, y) => { + // Check whether the click was inside the file menu. Otherwise, open the file. + this.file_default_widget.clicked(); + }); + + this.append(overlay); + } + } + +} |