aboutsummaryrefslogtreecommitdiff
path: root/main/src
diff options
context:
space:
mode:
authorfiaxh <git@lightrise.org>2024-11-02 22:24:59 +0100
committerfiaxh <git@lightrise.org>2024-11-15 14:40:08 -0600
commit79f792e090330a05753f9edb27332a946eb0840d (patch)
tree5a6f1ad3ac0af0beea44ca9e83e7a9b052263025 /main/src
parentaaf4542e6208460c305db4be36b15dc832ddc95a (diff)
downloaddino-79f792e090330a05753f9edb27332a946eb0840d.tar.gz
dino-79f792e090330a05753f9edb27332a946eb0840d.zip
Fix and improve stateless file-sharing
Diffstat (limited to 'main/src')
-rw-r--r--main/src/ui/conversation_content_view/file_default_widget.vala4
-rw-r--r--main/src/ui/conversation_content_view/file_image_widget.vala253
-rw-r--r--main/src/ui/conversation_content_view/file_preview_widget.vala90
-rw-r--r--main/src/ui/conversation_content_view/file_transmission_progress.vala120
-rw-r--r--main/src/ui/conversation_content_view/file_widget.vala55
-rw-r--r--main/src/ui/widgets/avatar_picture.vala2
6 files changed, 343 insertions, 181 deletions
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 352c8d7a..02249b3f 100644
--- a/main/src/ui/conversation_content_view/file_default_widget.vala
+++ b/main/src/ui/conversation_content_view/file_default_widget.vala
@@ -39,7 +39,7 @@ public class FileDefaultWidget : Box {
});
}
- public void update_file_info(string? mime_type, FileTransfer.State state, long size) {
+ public void update_file_info(string? mime_type, FileTransfer.State state, int64 size) {
this.state = state;
spinner.stop(); // A hidden spinning spinner still uses CPU. Deactivate asap
@@ -132,7 +132,7 @@ public class FileDefaultWidget : Box {
}
}
- private static string get_size_string(long size) {
+ public static string get_size_string(int64 size) {
if (size < 1024) {
return @"$(size) B";
} else if (size < 1000 * 1000) {
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 a3579185..d5415f31 100644
--- a/main/src/ui/conversation_content_view/file_image_widget.vala
+++ b/main/src/ui/conversation_content_view/file_image_widget.vala
@@ -1,51 +1,37 @@
using Gee;
using Gdk;
using Gtk;
+using Xmpp;
using Dino.Entities;
namespace Dino.Ui {
public class FileImageWidget : Box {
+ enum State {
+ EMPTY,
+ PREVIEW,
+ IMAGE
+ }
+ private State state = State.EMPTY;
- public FileImageWidget() {
- this.halign = Align.START;
+ private Stack stack = new Stack() { transition_duration=600, transition_type=StackTransitionType.CROSSFADE };
+ private Overlay overlay = new Overlay();
- this.add_css_class("file-image-widget");
- this.set_cursor_from_name("zoom-in");
- }
+ private bool show_image_overlay_toolbar = false;
+ private Gtk.Box image_overlay_toolbar = new Gtk.Box(Orientation.VERTICAL, 0) { halign=Align.END, valign=Align.START, margin_top=10, margin_start=10, margin_end=10, margin_bottom=10, vexpand=false, visible=false };
+ private Label file_size_label = new Label(null) { halign=Align.START, valign=Align.END, margin_bottom=4, margin_start=4, visible=false };
- public async void load_from_file(File file, string file_name, int MAX_WIDTH=600, int MAX_HEIGHT=300) throws GLib.Error {
- Gtk.Box image_overlay_toolbar = new Gtk.Box(Orientation.HORIZONTAL, 0) { halign=Gtk.Align.END, valign=Gtk.Align.START, margin_top=10, margin_start=10, margin_end=10, margin_bottom=10, vexpand=false, visible=false };
- image_overlay_toolbar.add_css_class("card");
- image_overlay_toolbar.add_css_class("toolbar");
- image_overlay_toolbar.add_css_class("overlay-toolbar");
- image_overlay_toolbar.set_cursor_from_name("default");
+ private FileTransfer file_transfer;
- FixedRatioPicture image = new FixedRatioPicture() { min_width=100, min_height=100, max_width=MAX_WIDTH, max_height=MAX_HEIGHT, file=file };
- GestureClick gesture_click_controller = new GestureClick();
- gesture_click_controller.button = 1; // listen for left clicks
- gesture_click_controller.released.connect((n_press, x, y) => {
- switch (gesture_click_controller.get_device().source) {
- case Gdk.InputSource.TOUCHSCREEN:
- case Gdk.InputSource.PEN:
- if (n_press == 1) {
- image_overlay_toolbar.visible = !image_overlay_toolbar.visible;
- } else if (n_press == 2) {
- this.activate_action("file.open", null);
- image_overlay_toolbar.visible = false;
- }
- break;
- default:
- this.activate_action("file.open", null);
- image_overlay_toolbar.visible = false;
- break;
- }
- });
- image.add_controller(gesture_click_controller);
+ private FileTransmissionProgress transmission_progress = new FileTransmissionProgress() { halign=Align.CENTER, valign=Align.CENTER, visible=false };
+
+ public FileImageWidget(int MAX_WIDTH=600, int MAX_HEIGHT=300) {
+ this.halign = Align.START;
- FileInfo file_info = file.query_info("*", FileQueryInfoFlags.NONE);
+ this.add_css_class("file-image-widget");
+ // Setup menu button overlay
MenuButton button = new MenuButton();
button.icon_name = "view-more";
Menu menu_model = new Menu();
@@ -53,27 +39,216 @@ public class FileImageWidget : Box {
menu_model.append(_("Save as…"), "file.save_as");
Gtk.PopoverMenu popover_menu = new Gtk.PopoverMenu.from_model(menu_model);
button.popover = popover_menu;
-
image_overlay_toolbar.append(button);
+ image_overlay_toolbar.add_css_class("card");
+ image_overlay_toolbar.add_css_class("toolbar");
+ image_overlay_toolbar.add_css_class("overlay-toolbar");
+ image_overlay_toolbar.set_cursor_from_name("default");
- Overlay overlay = new Overlay();
- overlay.set_child(image);
+ file_size_label.add_css_class("file-details");
+
+ overlay.set_child(stack);
+ overlay.set_measure_overlay(stack, true);
+ overlay.add_overlay(file_size_label);
+ overlay.add_overlay(transmission_progress);
overlay.add_overlay(image_overlay_toolbar);
- overlay.set_measure_overlay(image, true);
overlay.set_clip_overlay(image_overlay_toolbar, true);
+ this.append(overlay);
+
+ GestureClick gesture_click_controller = new GestureClick();
+ gesture_click_controller.button = 1; // listen for left clicks
+ gesture_click_controller.released.connect(on_image_clicked);
+ stack.add_controller(gesture_click_controller);
+
EventControllerMotion this_motion_events = new EventControllerMotion();
this.add_controller(this_motion_events);
this_motion_events.enter.connect(() => {
- image_overlay_toolbar.visible = true;
+ image_overlay_toolbar.visible = show_image_overlay_toolbar;
+ file_size_label.visible = file_transfer != null && file_transfer.direction == FileTransfer.DIRECTION_RECEIVED && file_transfer.state == FileTransfer.State.NOT_STARTED && !file_transfer.sfs_sources.is_empty;
});
this_motion_events.leave.connect(() => {
if (button.popover != null && button.popover.visible) return;
image_overlay_toolbar.visible = false;
+ file_size_label.visible = false;
});
+ }
- this.append(overlay);
+ public async void set_file_transfer(FileTransfer file_transfer) {
+ this.file_transfer = file_transfer;
+
+ this.file_transfer.bind_property("size", file_size_label, "label", BindingFlags.SYNC_CREATE, (_, from_value, ref to_value) => {
+ to_value = FileDefaultWidget.get_size_string((int64) from_value);
+ return true;
+ });
+ this.file_transfer.bind_property("size", transmission_progress, "file-size", BindingFlags.SYNC_CREATE);
+ this.file_transfer.bind_property("transferred-bytes", transmission_progress, "transferred-size");
+
+ file_transfer.notify["state"].connect(refresh_state);
+ file_transfer.sources_changed.connect(refresh_state);
+ refresh_state();
+ }
+
+ private void refresh_state() {
+ if ((state == EMPTY || state == PREVIEW) && file_transfer.path != null) {
+ if (state == EMPTY) {
+ load_from_file.begin(file_transfer.get_file(), file_transfer.file_name);
+ show_image_overlay_toolbar = true;
+ } if (state == PREVIEW) {
+ Timeout.add(500, () => {
+ load_from_file.begin(file_transfer.get_file(), file_transfer.file_name);
+ show_image_overlay_toolbar = true;
+ return false;
+ });
+ }
+ this.set_cursor_from_name("zoom-in");
+
+ state = IMAGE;
+ } else if (state == EMPTY && file_transfer.thumbnails.size > 0) {
+ load_from_thumbnail.begin(file_transfer);
+
+ transmission_progress.visible = true;
+ show_image_overlay_toolbar = false;
+
+ state = PREVIEW;
+ }
+
+ if (file_transfer.state == IN_PROGRESS || file_transfer.state == NOT_STARTED || file_transfer.state == FAILED) {
+ transmission_progress.visible = true;
+ show_image_overlay_toolbar = false;
+ } else if (transmission_progress.visible) {
+ Timeout.add(500, () => {
+ transmission_progress.transferred_size = transmission_progress.file_size;
+ transmission_progress.visible = false;
+ show_image_overlay_toolbar = true;
+ return false;
+ });
+ }
+
+ if (file_transfer.state == FileTransfer.State.IN_PROGRESS) {
+ if (file_transfer.direction == FileTransfer.DIRECTION_RECEIVED) {
+ transmission_progress.state = FileTransmissionProgress.State.DOWNLOADING;
+ } else {
+ transmission_progress.state = FileTransmissionProgress.State.UPLOADING;
+ }
+ } else if (file_transfer.sfs_sources.is_empty) {
+ transmission_progress.state = UNKNOWN_SOURCE;
+ } else if (file_transfer.state == NOT_STARTED && file_transfer.direction == FileTransfer.DIRECTION_RECEIVED) {
+ transmission_progress.state = DOWNLOAD_NOT_STARTED;
+ } else if (file_transfer.state == FileTransfer.State.FAILED) {
+ transmission_progress.state = DOWNLOAD_NOT_STARTED_FAILED_BEFORE;
+ }
+ }
+
+ public async void load_from_file(File file, string file_name) throws GLib.Error {
+ FixedRatioPicture image = new FixedRatioPicture() { min_width=100, min_height=100, max_width=600, max_height=300 };
+ image.file = file;
+ stack.add_child(image);
+ stack.set_visible_child(image);
+ }
+
+ public async void load_from_thumbnail(FileTransfer file_transfer) throws GLib.Error {
+ this.file_transfer = file_transfer;
+
+ Gdk.Pixbuf? pixbuf = null;
+ foreach (Xep.JingleContentThumbnails.Thumbnail thumbnail in file_transfer.thumbnails) {
+ pixbuf = parse_thumbnail(thumbnail);
+ if (pixbuf != null) {
+ break;
+ }
+ }
+ if (pixbuf == null) {
+ warning("Can't load thumbnails of file %s", file_transfer.file_name);
+ 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");
+ }
+
+ FixedRatioPicture image = new FixedRatioPicture() { min_width=100, min_height=100, max_width=600, max_height=300 };
+ image.paintable = Texture.for_pixbuf(pixbuf);
+ stack.add_child(image);
+ stack.set_visible_child(image);
+ }
+
+ public void on_image_clicked(GestureClick gesture_click_controller, int n_press, double x, double y) {
+ if (this.file_transfer.state != COMPLETE) return;
+
+ switch (gesture_click_controller.get_device().source) {
+ case Gdk.InputSource.TOUCHSCREEN:
+ case Gdk.InputSource.PEN:
+ if (n_press == 1) {
+ image_overlay_toolbar.visible = !image_overlay_toolbar.visible;
+ } else if (n_press == 2) {
+ this.activate_action("file.open", null);
+ image_overlay_toolbar.visible = false;
+ }
+ break;
+ default:
+ this.activate_action("file.open", null);
+ image_overlay_toolbar.visible = false;
+ break;
+ }
+ }
+
+ public static Pixbuf? parse_thumbnail(Xep.JingleContentThumbnails.Thumbnail thumbnail) {
+ string[] splits = thumbnail.uri.split(":", 2);
+ if (splits.length != 2) {
+ warning("Thumbnail parsing error: ':' not found");
+ return null;
+ }
+ if (splits[0] != "data") {
+ warning("Unsupported thumbnail: unimplemented uri type\n");
+ return null;
+ }
+ splits = splits[1].split(";", 2);
+ if (splits.length != 2) {
+ warning("Thumbnail parsing error: ';' not found");
+ return null;
+ }
+ if (splits[0] != "image/png") {
+ warning("Unsupported thumbnail: unsupported mime-type\n");
+ return null;
+ }
+ splits = splits[1].split(",", 2);
+ if (splits.length != 2) {
+ warning("Thumbnail parsing error: ',' not found");
+ return null;
+ }
+ if (splits[0] != "base64") {
+ warning("Unsupported thumbnail: data is not base64 encoded\n");
+ return null;
+ }
+ uint8[] data = Base64.decode(splits[1]);
+ MemoryInputStream input_stream = new MemoryInputStream.from_data(data);
+ Pixbuf pixbuf = new Pixbuf.from_stream(input_stream);
+ return pixbuf;
+ }
+
+ public static bool can_display(FileTransfer file_transfer) {
+ return file_transfer.mime_type != null && is_pixbuf_supported_mime_type(file_transfer.mime_type) &&
+ (file_transfer.state == FileTransfer.State.COMPLETE || file_transfer.thumbnails.size > 0);
+ }
+
+ public static bool is_pixbuf_supported_mime_type(string mime_type) {
+ if (mime_type == null) return false;
+
+ foreach (PixbufFormat pixbuf_format in Pixbuf.get_formats()) {
+ foreach (string pixbuf_mime in pixbuf_format.get_mime_types()) {
+ if (pixbuf_mime == mime_type) return true;
+ }
+ }
+ return false;
}
}
diff --git a/main/src/ui/conversation_content_view/file_preview_widget.vala b/main/src/ui/conversation_content_view/file_preview_widget.vala
deleted file mode 100644
index e7cee93a..00000000
--- a/main/src/ui/conversation_content_view/file_preview_widget.vala
+++ /dev/null
@@ -1,90 +0,0 @@
-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);
- }
- }
-
-}
diff --git a/main/src/ui/conversation_content_view/file_transmission_progress.vala b/main/src/ui/conversation_content_view/file_transmission_progress.vala
new file mode 100644
index 00000000..bf3f377b
--- /dev/null
+++ b/main/src/ui/conversation_content_view/file_transmission_progress.vala
@@ -0,0 +1,120 @@
+using Gee;
+using Gdk;
+using Gtk;
+using Xmpp;
+
+using Dino.Entities;
+
+namespace Dino.Ui {
+
+ public class FileTransmissionProgress : Adw.Bin {
+
+ public enum State {
+ UNKNOWN_SOURCE,
+ DOWNLOAD_NOT_STARTED,
+ DOWNLOAD_NOT_STARTED_FAILED_BEFORE,
+ DOWNLOADING,
+ UPLOADING
+ }
+
+ public int64 file_size { get; set; }
+ public int64 transferred_size { get; set; }
+ public State state { get; set; }
+
+ private CssProvider css_provider = new CssProvider();
+ private Button button = new Button();
+
+ private uint64 next_update_time = 0;
+ private int64 last_progress_percent = 0;
+ private uint update_progress_timeout_id = -1;
+
+ construct {
+ add_css_class("circular-loading-indicator");
+
+ button.add_css_class("circular");
+ Adw.Bin holder = new Adw.Bin();
+ holder.set_child(button);
+ this.set_child(holder);
+
+ this.button.clicked.connect(on_button_clicked);
+
+ this.notify["transferred-size"].connect(on_transferred_size_update);
+ this.notify["state"].connect(on_state_changed);
+ on_state_changed();
+ }
+
+ private void on_transferred_size_update() {
+ if (update_progress_timeout_id == -1) {
+ int64 progress_percent = transferred_size * 100 / file_size;
+ if (progress_percent != last_progress_percent) {
+ uint64 time_now = get_monotonic_time() / 1000;
+ if (next_update_time > time_now) {
+ update_progress_timeout_id = Timeout.add((uint) (next_update_time - time_now), () => {
+ update_progress();
+ update_progress_timeout_id = -1;
+ return Source.REMOVE;
+ });
+ } else {
+ update_progress();
+ }
+ }
+ }
+ }
+
+ private void on_state_changed() {
+ sensitive = state != UNKNOWN_SOURCE;
+
+ switch (this.state) {
+ case UNKNOWN_SOURCE:
+ case DOWNLOAD_NOT_STARTED:
+ button.icon_name = "document-save-symbolic";
+ break;
+ case DOWNLOADING:
+ case UPLOADING:
+ button.icon_name = "small-x-symbolic";
+ break;
+ case DOWNLOAD_NOT_STARTED_FAILED_BEFORE:
+ button.icon_name = "dialog-warning-symbolic";
+ break;
+ }
+ }
+
+ private void update_progress() {
+ this.get_style_context().remove_provider(css_provider);
+ css_provider = new CssProvider();
+ int64 progress_percent = transferred_size * 100 / file_size;
+
+ css_provider.load_from_string(@"
+ .circular-loading-indicator {
+ background-image: conic-gradient(@accent_color $(progress_percent)%, transparent $(progress_percent)%);
+ }
+ ");
+
+ this.get_style_context().add_provider(css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
+ next_update_time = get_monotonic_time() / 1000 + 500;
+ last_progress_percent = progress_percent;
+ }
+
+ private void on_button_clicked() {
+ switch (this.state) {
+ case UNKNOWN_SOURCE:
+ break;
+ case DOWNLOAD_NOT_STARTED_FAILED_BEFORE:
+ case DOWNLOAD_NOT_STARTED:
+ this.activate_action("file.download", null);
+ break;
+ case DOWNLOADING:
+ case UPLOADING:
+ this.activate_action("file.cancel", null);
+ break;
+ }
+ }
+
+ public override void dispose() {
+ if (update_progress_timeout_id != -1) {
+ Source.remove(update_progress_timeout_id);
+ update_progress_timeout_id = -1;
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/main/src/ui/conversation_content_view/file_widget.vala b/main/src/ui/conversation_content_view/file_widget.vala
index 69781f30..583609d2 100644
--- a/main/src/ui/conversation_content_view/file_widget.vala
+++ b/main/src/ui/conversation_content_view/file_widget.vala
@@ -27,7 +27,7 @@ public class FileMetaItem : ConversationSummary.ContentMetaItem {
}
public override Gee.List<Plugins.MessageAction>? get_item_actions(Plugins.WidgetType type) {
- if (file_transfer.provider != 0 || file_transfer.info == null) return null;
+ if ((file_transfer.provider != FileManager.HTTP_PROVIDER_ID && file_transfer.provider != FileManager.SFS_PROVIDER_ID) || file_transfer.info == null) return null;
Gee.List<Plugins.MessageAction> actions = new ArrayList<Plugins.MessageAction>();
@@ -43,7 +43,6 @@ public class FileWidget : SizeRequestBox {
enum State {
IMAGE,
- IMAGE_PREVIEW,
DEFAULT
}
@@ -90,13 +89,15 @@ public class FileWidget : SizeRequestBox {
}
private async void update_widget() {
- if (show_image() && state != State.IMAGE) {
+ bool show_image = FileImageWidget.can_display(file_transfer);
+
+ if (show_image && state != State.IMAGE) {
var content_bak = content;
FileImageWidget file_image_widget = null;
try {
file_image_widget = new FileImageWidget();
- yield file_image_widget.load_from_file(file_transfer.get_file(), file_transfer.file_name);
+ yield file_image_widget.set_file_transfer(file_transfer);
// If the widget changed in the meanwhile, stop
if (content != content_bak) return;
@@ -109,26 +110,7 @@ public class FileWidget : SizeRequestBox {
} catch (Error e) { }
}
- if (show_preview() && state != State.IMAGE_PREVIEW) {
- var content_bak = content;
-
- FilePreviewWidget file_preview_widget = null;
- try {
- file_preview_widget = new FilePreviewWidget() { visible=true };
- yield file_preview_widget.load_from_thumbnail(file_transfer, stream_interactor);
-
- // If the widget changed in the meanwhile, stop
- if (content != content_bak) return;
-
- if (content != null) this.remove(content);
- content = file_preview_widget;
- state = State.IMAGE_PREVIEW;
- this.append(content);
- return;
- } catch (Error e) { }
- }
-
- if (!show_image() && state != State.DEFAULT && state != State.IMAGE_PREVIEW) {
+ if (!show_image && state != State.DEFAULT) {
if (content != null) this.remove(content);
FileDefaultWidget default_file_widget = new FileDefaultWidget();
default_widget_controller = new FileDefaultWidgetController(default_file_widget);
@@ -139,31 +121,6 @@ public class FileWidget : SizeRequestBox {
}
}
- private bool show_image() {
- if (file_transfer.mime_type == null) return false;
-
- // If the image is being sent by this client, we already have the file
- bool in_progress_from_us = file_transfer.direction == FileTransfer.DIRECTION_SENT &&
- file_transfer.ourpart.equals(file_transfer.account.full_jid) &&
- file_transfer.state == FileTransfer.State.IN_PROGRESS;
- if (file_transfer.state != FileTransfer.State.COMPLETE && !in_progress_from_us) {
- return false;
- }
-
- foreach (PixbufFormat pixbuf_format in Pixbuf.get_formats()) {
- foreach (string mime_type in pixbuf_format.get_mime_types()) {
- if (mime_type == file_transfer.mime_type) {
- return true;
- }
- }
- }
- return false;
- }
-
- private bool show_preview() {
- return !this.file_transfer.thumbnails.is_empty;
- }
-
public override void dispose() {
if (default_widget_controller != null) default_widget_controller.dispose();
default_widget_controller = null;
diff --git a/main/src/ui/widgets/avatar_picture.vala b/main/src/ui/widgets/avatar_picture.vala
index fb254915..ef1462ae 100644
--- a/main/src/ui/widgets/avatar_picture.vala
+++ b/main/src/ui/widgets/avatar_picture.vala
@@ -285,7 +285,7 @@ public class Dino.Ui.CompatAvatarDrawer {
private Cairo.Surface sub_surface_idx(Cairo.Context ctx, int idx, int width, int height, int font_factor = 1) {
ViewModel.AvatarPictureTileModel tile = (ViewModel.AvatarPictureTileModel) this.model.tiles.get_item(idx);
- Gdk.Pixbuf? avatar = new Gdk.Pixbuf.from_file(tile.image_file.get_path());
+ Gdk.Pixbuf? avatar = tile.image_file != null ? new Gdk.Pixbuf.from_file(tile.image_file.get_path()) : null;
string? name = idx >= 0 ? tile.display_text : "";
Gdk.RGBA hex_color = tile.background_color;
return sub_surface(ctx, font_family, avatar, name, hex_color, width, height, font_factor);