From 8d49d83b3b45ab22d7b9d945c4b32296b07cb49e Mon Sep 17 00:00:00 2001 From: fiaxh Date: Fri, 14 Aug 2026 11:45:08 +0200 Subject: Add initial support for multi-file transfers --- .../content_populator.vala | 2 + .../file_default_widget.vala | 40 ++++--- .../file_group_widget.vala | 120 +++++++++++++++++++++ .../file_image_widget.vala | 105 ++++++++++++------ .../file_transmission_progress.vala | 6 +- .../ui/conversation_content_view/file_widget.vala | 71 +----------- 6 files changed, 229 insertions(+), 115 deletions(-) create mode 100644 main/src/ui/conversation_content_view/file_group_widget.vala (limited to 'main/src/ui/conversation_content_view') diff --git a/main/src/ui/conversation_content_view/content_populator.vala b/main/src/ui/conversation_content_view/content_populator.vala index ef859bde..4d1b8c90 100644 --- a/main/src/ui/conversation_content_view/content_populator.vala +++ b/main/src/ui/conversation_content_view/content_populator.vala @@ -70,6 +70,8 @@ public class ContentProvider : ContentItemCollection, Object { return new FileMetaItem(content_item, stream_interactor); } else if (content_item.type_ == CallItem.TYPE) { return new CallMetaItem(content_item, stream_interactor); + } else if (content_item.type_ == FileGroupItem.TYPE) { + return new FileGroupMetaItem(content_item, stream_interactor); } critical("Got unknown content item type %s", content_item.type_); return null; 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 a21e2afb..1ad3d6c2 100644 --- a/main/src/ui/conversation_content_view/file_default_widget.vala +++ b/main/src/ui/conversation_content_view/file_default_widget.vala @@ -51,13 +51,13 @@ public class FileDefaultWidget : Box { mime_label.label = content_type != null ? content_type.get_description() : null; } - public void update_file_info(Xmpp.FileContentType? content_type, FileTransfer.State state, bool direction, int64 size, int64 transferred_bytes) { - this.state = state; + public void update_file_info(FileTransfer file_transfer) { + this.state = file_transfer.state; spinner.stop(); // A hidden spinning spinner still uses CPU. Deactivate asap - content_type_image.icon_name = get_file_icon_name(content_type); - string? mime_description = content_type != null ? content_type.get_description() : null; + content_type_image.icon_name = get_file_icon_name(file_transfer.content_type); + string? mime_description = file_transfer.content_type != null ? file_transfer.content_type.get_description() : null; switch (state) { case FileTransfer.State.COMPLETE: @@ -66,23 +66,31 @@ public class FileDefaultWidget : Box { // Create a menu Menu menu_model = new Menu(); - menu_model.append(_("Open"), "file.open"); - menu_model.append(_("Save as…"), "file.save_as"); + + MenuItem open_file_item = new MenuItem(_("Open"), "app.file_open_externally"); + open_file_item.set_action_and_target_value("app.file_open_externally", new Variant.int32(file_transfer.id)); + + MenuItem save_as_item = new MenuItem(_("Save as…"), "app.file_save_as"); + save_as_item.set_action_and_target_value("app.file_open_save_dialog", new Variant.int32(file_transfer.id)); + + menu_model.append_item(open_file_item); + menu_model.append_item(save_as_item); + Gtk.PopoverMenu popover_menu = new Gtk.PopoverMenu.from_model(menu_model); file_menu.popover = popover_menu; popover_menu.closed.connect(on_pointer_left); break; case FileTransfer.State.IN_PROGRESS: - if (direction == FileTransfer.DIRECTION_RECEIVED) { - if (size > 0) { - int64 progress = transferred_bytes * 100 / size; - mime_label.label = _("Downloading %s… (%u%%)").printf(get_size_string(size), progress); + if (file_transfer.direction == FileTransfer.DIRECTION_RECEIVED) { + if (file_transfer.size > 0) { + int64 progress = file_transfer.transferred_bytes * 100 / file_transfer.size; + mime_label.label = _("Downloading %s… (%u%%)").printf(get_size_string(file_transfer.size), progress); } else { - mime_label.label = _("Downloading %s…").printf(get_size_string(size)); + mime_label.label = _("Downloading %s…").printf(get_size_string(file_transfer.size)); } } else { - int64 progress = transferred_bytes * 100 / size; - mime_label.label = _("Uploading %s… (%u%%)").printf(get_size_string(size), progress); + int64 progress = file_transfer.transferred_bytes * 100 / file_transfer.size; + mime_label.label = _("Uploading %s… (%u%%)").printf(get_size_string(file_transfer.size), progress); } spinner.start(); image_stack.set_visible_child_name("spinner"); @@ -96,9 +104,9 @@ public class FileDefaultWidget : Box { break; case FileTransfer.State.NOT_STARTED: if (mime_description != null) { - mime_label.label = _("%s offered: %s").printf(mime_description, get_size_string(size)); - } else if (size != -1) { - mime_label.label = _("File offered: %s").printf(get_size_string(size)); + mime_label.label = _("%s offered: %s").printf(mime_description, get_size_string(file_transfer.size)); + } else if (file_transfer.size != -1) { + mime_label.label = _("File offered: %s").printf(get_size_string(file_transfer.size)); } else { mime_label.label = _("File offered"); } diff --git a/main/src/ui/conversation_content_view/file_group_widget.vala b/main/src/ui/conversation_content_view/file_group_widget.vala new file mode 100644 index 00000000..80c41a7a --- /dev/null +++ b/main/src/ui/conversation_content_view/file_group_widget.vala @@ -0,0 +1,120 @@ +using Gee; +using Gdk; +using Gtk; +using Pango; +using Xmpp; + +using Dino.Entities; + +namespace Dino.Ui { + + public class FileGroupMetaItem : ConversationSummary.ContentMetaItem { + + private StreamInteractor stream_interactor; + private FileGroupItem file_group_item; + + public FileGroupMetaItem(ContentItem content_item, StreamInteractor stream_interactor) { + base(content_item); + this.stream_interactor = stream_interactor; + this.file_group_item = content_item as FileGroupItem; + } + + public override Object? get_widget(Plugins.ConversationItemWidgetInterface outer, Plugins.WidgetType type) { + var file_transfers = file_group_item.file_group.file_transfers; + + if (file_transfers.size > 1 && all_files_images(file_transfers)) { + return new ImageGroupWidget(file_transfers); + } else { + Box box = new Box(Orientation.VERTICAL, 6); + foreach (FileTransfer file_transfer in file_transfers) { + FileWidget widget = new FileWidget(file_transfer) { halign = Align.START }; + widget.add_css_class("file-image-widget"); + FileWidgetController widget_controller = new FileWidgetController(widget, file_transfer, stream_interactor); + box.append(widget); + } + return box; + } + } + + public override Gee.List? get_item_actions(Plugins.WidgetType type) { + Gee.List actions = new ArrayList(); + return actions; + } + } + + public class ImageGroupWidget : Box { + + private Gee.ArrayList file_transfers; + + public ImageGroupWidget(Gee.ArrayList file_transfers) { + this.file_transfers = file_transfers; + + if (file_transfers.size == 3) { + Box box = new Box(Orientation.HORIZONTAL, 4) { + overflow = Overflow.HIDDEN, + halign = Align.START + }; + box.add_css_class("image-group"); + + var picture1 = new FileImageWidget.from_file_transfer(file_transfers[0], 200); + box.append(picture1); + + Box box1 = new Box(Orientation.VERTICAL, 4); + + var picture2 = new FileImageWidget.from_file_transfer(file_transfers[1], 100); + box1.append(picture2); + var picture3 = new FileImageWidget.from_file_transfer(file_transfers[2], 100); + box1.append(picture3); + box.append(box1); + + this.append(box); + } else { + Box box = new Box(Orientation.VERTICAL, 4) { + overflow = Overflow.HIDDEN, + halign = Align.START + }; + box.add_css_class("image-group"); + + Box row_upper_row = new Box(Orientation.HORIZONTAL, 4); + + var picture1 = new FileImageWidget.from_file_transfer(file_transfers[0], 150); + row_upper_row.append(picture1); + + var picture2 = new FileImageWidget.from_file_transfer(file_transfers[1], 150); + row_upper_row.append(picture2); + box.append(row_upper_row); + + if (file_transfers.size >= 4) { + + int size = 150; + if (file_transfers.size == 5) size = 99; + + Box row_lower_row = new Box(Orientation.HORIZONTAL, 4); + + var picture3 = new FileImageWidget.from_file_transfer(file_transfers[2], size); + row_lower_row.append(picture3); + + var picture4 = new FileImageWidget.from_file_transfer(file_transfers[3], size); + row_lower_row.append(picture4); + + if (file_transfers.size == 5) { + var picture5 = new FileImageWidget.from_file_transfer(file_transfers[4], size); + row_lower_row.append(picture5); + } + + box.append(row_lower_row); + } + this.append(box); + } + } + } + + public static bool all_files_images(Gee.ArrayList file_transfers) { + foreach (FileTransfer file_transfer in file_transfers) { + if (!Dino.Util.is_pixbuf_supported_content_type(file_transfer.content_type)) { + return false; + } + } + return true; + } +} \ No newline at end of file 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 e936ca25..9f12f892 100644 --- a/main/src/ui/conversation_content_view/file_image_widget.vala +++ b/main/src/ui/conversation_content_view/file_image_widget.vala @@ -22,6 +22,8 @@ public class FileImageWidget : Widget { 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 }; + private int size = -1; + private FileTransfer file_transfer; private FileTransmissionProgress transmission_progress = new FileTransmissionProgress() { halign=Align.CENTER, valign=Align.CENTER, visible=false }; @@ -34,22 +36,6 @@ public class FileImageWidget : Widget { public FileImageWidget(int MAX_WIDTH=600, int MAX_HEIGHT=300) { this.halign = Align.START; - this.add_css_class("file-image-widget"); - - // Setup menu button overlay - MenuButton button = new MenuButton(); - button.icon_name = "dino-view-more"; - Menu menu_model = new Menu(); - menu_model.append(_("Open"), "file.open"); - 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("compact-card-toolbar"); - image_overlay_toolbar.set_cursor_from_name("default"); - file_size_label.add_css_class("file-details"); overlay.set_child(stack); @@ -65,12 +51,65 @@ public class FileImageWidget : Widget { gesture_click_controller.button = 1; // listen for left clicks gesture_click_controller.released.connect(on_image_clicked); stack.add_controller(gesture_click_controller); + } + + public FileImageWidget.from_file_transfer(FileTransfer file_transfer, int size = -1) { + this(); + + this.file_transfer = file_transfer; + this.size = size; + + this.file_transfer.bind_property("size", file_size_label, "label", BindingFlags.SYNC_CREATE, file_size_label_transform); + this.file_transfer.bind_property("size", transmission_progress, "file-size", BindingFlags.SYNC_CREATE); + this.file_transfer.bind_property("transferred-bytes", transmission_progress, "transferred-size"); + + setup_signals(transmission_progress, file_transfer); + setup_menu_button(); + + file_transfer.notify["state"].connect(refresh_state); + file_transfer.sources_changed.connect(refresh_state); + refresh_state(); + } + + private static void setup_signals(FileTransmissionProgress transmission_progress, FileTransfer file_transfer) { + var file_transfer_id = file_transfer.id; + + transmission_progress.start_download.connect(() => { + Dino.Application.get_default().activate_action("file_start_download", new Variant.int32(file_transfer_id)); + }); + transmission_progress.cancel_transfer.connect(() => { + Dino.Application.get_default().activate_action("file_cancel_transfer", new Variant.int32(file_transfer_id)); + }); + } + + private void setup_menu_button() { + MenuButton button = new MenuButton(); + button.icon_name = "dino-view-more"; + Menu menu_model = new Menu(); + + MenuItem open_file_item = new MenuItem(_("Open"), "app.file_open_externally"); + open_file_item.set_action_and_target_value("app.file_open_externally", new Variant.int32(file_transfer.id)); + + MenuItem save_as_item = new MenuItem(_("Save as…"), "app.file_save_as"); + save_as_item.set_action_and_target_value("app.file_open_save_dialog", new Variant.int32(file_transfer.id)); + + menu_model.append_item(open_file_item); + menu_model.append_item(save_as_item); + + 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("compact-card-toolbar"); + image_overlay_toolbar.set_cursor_from_name("default"); EventControllerMotion this_motion_events = new EventControllerMotion(); this.add_controller(this_motion_events); this_motion_events.enter.connect((controller, x, y) => { (controller.widget as FileImageWidget).on_motion_event_enter(); }); + attach_on_motion_event_leave(this_motion_events, button); } @@ -88,18 +127,6 @@ public class FileImageWidget : Widget { 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; } - 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, file_size_label_transform); - 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 static bool file_size_label_transform(Binding binding, Value from_value, ref Value to_value) { to_value = FileDefaultWidget.get_size_string((int64) from_value); return true; @@ -153,7 +180,7 @@ public class FileImageWidget : Widget { } 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 }; + FixedRatioPicture image = create_picture(); FileInputStream file_stream = null; try { @@ -201,7 +228,7 @@ public class FileImageWidget : Widget { 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 }; + FixedRatioPicture image = create_picture(); image.paintable = Texture.for_pixbuf(pixbuf); stack.add_child(image); stack.set_visible_child(image); @@ -216,12 +243,12 @@ public class FileImageWidget : Widget { if (n_press == 1) { image_overlay_toolbar.visible = !image_overlay_toolbar.visible; } else if (n_press == 2) { - this.activate_action("file.open", null); + Dino.Application.get_default().activate_action("file_open_externally", new Variant.int32(file_transfer.id)); image_overlay_toolbar.visible = false; } break; default: - this.activate_action("file.open", null); + Dino.Application.get_default().activate_action("file_open_externally", new Variant.int32(file_transfer.id)); image_overlay_toolbar.visible = false; break; } @@ -237,6 +264,20 @@ public class FileImageWidget : Widget { (file_transfer.state == FileTransfer.State.COMPLETE || file_transfer.thumbnails.size > 0); } + private FixedRatioPicture create_picture() { + if (size == -1) { + return new FixedRatioPicture() { + min_width=100, max_width=600, + min_height=100, max_height=300 + }; + } else { + return new FixedRatioPicture() { + height_request = size, width_request = size, + content_fit = ContentFit.COVER, halign = Align.START + }; + } + } + public override void dispose() { if (overlay != null && overlay.parent != null) overlay.unparent(); base.dispose(); diff --git a/main/src/ui/conversation_content_view/file_transmission_progress.vala b/main/src/ui/conversation_content_view/file_transmission_progress.vala index e3f33448..43885c1b 100644 --- a/main/src/ui/conversation_content_view/file_transmission_progress.vala +++ b/main/src/ui/conversation_content_view/file_transmission_progress.vala @@ -9,6 +9,9 @@ namespace Dino.Ui { public class FileTransmissionProgress : Adw.Bin { + public signal void start_download(); + public signal void cancel_transfer(); + public enum State { UNKNOWN_SOURCE, DOWNLOAD_NOT_STARTED, @@ -124,11 +127,12 @@ namespace Dino.Ui { break; case DOWNLOAD_NOT_STARTED_FAILED_BEFORE: case DOWNLOAD_NOT_STARTED: + start_download(); this.activate_action("file.download", null); break; case DOWNLOADING: case UPLOADING: - this.activate_action("file.cancel", null); + cancel_transfer(); break; } } diff --git a/main/src/ui/conversation_content_view/file_widget.vala b/main/src/ui/conversation_content_view/file_widget.vala index ecc2d3e9..04185343 100644 --- a/main/src/ui/conversation_content_view/file_widget.vala +++ b/main/src/ui/conversation_content_view/file_widget.vala @@ -57,18 +57,6 @@ public class FileWidget : SizeRequestBin { private FileDefaultWidgetController default_widget_controller; private Widget? content = null; - public signal void open_file(); - public signal void save_file_as(); - public signal void start_download(); - public signal void cancel_download(); - - class construct { - install_action("file.open", null, (widget, action_name) => { ((FileWidget) widget).open_file(); }); - install_action("file.save_as", null, (widget, action_name) => { ((FileWidget) widget).save_file_as(); }); - install_action("file.download", null, (widget, action_name) => { ((FileWidget) widget).start_download(); }); - install_action("file.cancel", null, (widget, action_name) => { ((FileWidget) widget).cancel_download(); }); - } - construct { margin_top = 4; size_request_mode = SizeRequestMode.HEIGHT_FOR_WIDTH; @@ -79,11 +67,6 @@ public class FileWidget : SizeRequestBin { this.file_transfer = file_transfer; update_widget.begin(); -// size_allocate.connect((allocation) => { -// if (allocation.height > parent.get_allocated_height()) { -// Idle.add(() => { parent.queue_resize(); return false; }); -// } -// }); file_transfer.bind_property("state", this, "file-transfer-state"); file_transfer.bind_property("content-type", this, "file-transfer-content-type"); @@ -100,8 +83,8 @@ public class FileWidget : SizeRequestBin { FileImageWidget file_image_widget = null; try { - file_image_widget = new FileImageWidget(); - yield file_image_widget.set_file_transfer(file_transfer); + file_image_widget = new FileImageWidget.from_file_transfer(file_transfer); + file_image_widget.add_css_class("file-image-widget"); // If the widget changed in the meanwhile, stop if (content != content_bak) return; @@ -152,50 +135,6 @@ public class FileWidgetController : Object { }); this.file_transfer = file_transfer; this.stream_interactor = stream_interactor; - - widget.open_file.connect(open_file); - widget.save_file_as.connect(save_file); - widget.start_download.connect(start_download); - widget.cancel_download.connect(cancel_download); - } - - private void open_file() { - try{ - AppInfo.launch_default_for_uri(file_transfer.get_file().get_uri(), null); - } catch (Error err) { - warning("Failed to open %s - %s", file_transfer.get_file().get_uri(), err.message); - } - } - - private void save_file() { - var save_dialog = new FileChooserNative(_("Save as…"), widget.get_root() as Gtk.Window, FileChooserAction.SAVE, null, null); - save_dialog.set_modal(true); - save_dialog.set_current_name(file_transfer.file_name); - - save_dialog.response.connect(() => { - File? target_file = save_dialog.get_file(); - if (target_file == null) { - warning("No file returned from save dialog."); - return; - } - try { - file_transfer.get_file().copy(save_dialog.get_file(), GLib.FileCopyFlags.OVERWRITE, null); - } catch (Error err) { - warning("Failed copy file %s - %s", file_transfer.get_file().get_uri(), err.message); - } - }); - - save_dialog.show(); - } - - private void start_download() { - if (stream_interactor != null) { - stream_interactor.get_module(FileManager.IDENTITY).download_file.begin(file_transfer); - } - } - - private void cancel_download() { - file_transfer.cancellable.cancel(); } } @@ -234,16 +173,16 @@ public class FileDefaultWidgetController : Object { private void update_file_info() { state = file_transfer.state; - widget.update_file_info(file_transfer.content_type, file_transfer.state, file_transfer.direction, file_transfer.size, file_transfer.transferred_bytes); + widget.update_file_info(file_transfer); } private void on_clicked() { switch (state) { case FileTransfer.State.COMPLETE: - widget.activate_action("file.open", null); + Dino.Application.get_default().activate_action("file_open_externally", new GLib.Variant.int32(file_transfer.id)); break; case FileTransfer.State.NOT_STARTED: - widget.activate_action("file.download", null); + Dino.Application.get_default().activate_action("file_start_download", new GLib.Variant.int32(file_transfer.id)); break; default: // Clicking doesn't do anything in FAILED and IN_PROGRESS states -- cgit v1.3 From 2413442905e31f34cb0f77c9167003b3725760fe Mon Sep 17 00:00:00 2001 From: Marvin W Date: Sat, 3 Oct 2026 16:05:51 +0200 Subject: Drop supported for outdated dependency versions --- libdino/meson.build | 3 -- libdino/src/service/stream_interactor.vala | 5 --- main/meson.build | 29 +-------------- .../file_transmission_progress.vala | 13 ------- main/src/ui/util/helper.vala | 11 ------ main/src/ui/widgets/avatar_picture.vala | 4 -- main/src/ui/widgets/fixed_ratio_picture.vala | 2 - main/src/windows/conversation_details.vala | 4 -- meson.build | 29 ++++++++------- .../omemo/src/ui/encryption_preferences_entry.vala | 5 --- plugins/openpgp/meson.build | 3 -- plugins/rtp/meson.build | 9 ----- plugins/rtp/src/codec_util.vala | 2 - plugins/rtp/src/plugin.vala | 2 - plugins/rtp/src/stream.vala | 43 +++------------------- plugins/rtp/src/video_widget.vala | 15 -------- xmpp-vala/meson.build | 3 -- xmpp-vala/src/core/direct_tls_xmpp_stream.vala | 2 - xmpp-vala/src/core/module_flag.vala | 10 ----- 19 files changed, 22 insertions(+), 172 deletions(-) (limited to 'main/src/ui/conversation_content_view') diff --git a/libdino/meson.build b/libdino/meson.build index e680b662..a3430200 100644 --- a/libdino/meson.build +++ b/libdino/meson.build @@ -119,9 +119,6 @@ c_args = vala_c_args + [ vala_args = [ '--vapidir', meson.current_source_dir() / 'vapi', ] -if meson.get_compiler('vala').version().version_compare('=0.56.11') - vala_args += ['-D', 'VALA_0_56_11'] -endif lib_dino = library('libdino', sources, c_args: c_args, vala_args: vala_args, include_directories: include_directories('src'), dependencies: dependencies, name_prefix: '', version: '0.0', install: true, install_dir: [true, true, true], install_rpath: default_install_rpath) dep_dino = declare_dependency(link_with: lib_dino, include_directories: include_directories('.', 'src')) diff --git a/libdino/src/service/stream_interactor.vala b/libdino/src/service/stream_interactor.vala index 2ac13103..2cd0c45c 100644 --- a/libdino/src/service/stream_interactor.vala +++ b/libdino/src/service/stream_interactor.vala @@ -100,12 +100,7 @@ public class ModuleIdentity : Object { } public T? cast(StreamInteractionModule module) { -#if VALA_0_56_11 - // We can't typecheck due to compiler bug - return (T) module; -#else return module.get_type().is_a(typeof(T)) ? (T?) module : null; -#endif } public bool matches(StreamInteractionModule module) { diff --git a/main/meson.build b/main/meson.build index 3c15db32..fbe78573 100644 --- a/main/meson.build +++ b/main/meson.build @@ -47,6 +47,7 @@ sources = files( 'src/ui/conversation_content_view/date_separator_populator.vala', 'src/ui/conversation_content_view/file_default_widget.vala', 'src/ui/conversation_content_view/file_image_widget.vala', + 'src/ui/conversation_content_view/file_transmission_progress.c', 'src/ui/conversation_content_view/file_transmission_progress.vala', 'src/ui/conversation_content_view/file_group_widget.vala', 'src/ui/conversation_content_view/file_widget.vala', @@ -113,34 +114,6 @@ c_args = vala_c_args + [ vala_args = [ '--vapidir', meson.current_source_dir() / 'vapi', ] -if dep_gtk4.version() == 'unknown' or dep_gtk4.version().version_compare('>=4.6') - vala_args += ['-D', 'GTK_4_6'] -endif -if dep_gtk4.version() == 'unknown' or dep_gtk4.version().version_compare('>=4.8') - vala_args += ['-D', 'GTK_4_8'] -endif -if dep_gtk4.version() == 'unknown' or dep_gtk4.version().version_compare('>=4.12') - vala_args += ['-D', 'GTK_4_12'] -endif -if dep_gtk4.version() == 'unknown' or dep_gtk4.version().version_compare('>=4.14') - vala_args += ['-D', 'GTK_4_14'] - sources += files('src/ui/conversation_content_view/file_transmission_progress.c') -endif -if dep_libadwaita.version() == 'unknown' or dep_libadwaita.version().version_compare('>=1.4') - vala_args += ['-D', 'Adw_1_4'] -endif -if meson.get_compiler('vala').version().version_compare('>=0.56.5') and meson.get_compiler('vala').version().version_compare('<0.58') - vala_args += ['-D', 'VALA_0_56_GREATER_5'] -endif -if meson.get_compiler('vala').version().version_compare('>=0.56.11') and meson.get_compiler('vala').version().version_compare('<0.58') - vala_args += ['-D', 'VALA_0_56_GREATER_11'] -endif -if meson.get_compiler('vala').version().version_compare('=0.56.11') - vala_args += ['-D', 'VALA_0_56_11'] -endif -if meson.get_compiler('vala').version().version_compare('=0.56.12') - vala_args += ['-D', 'VALA_0_56_12'] -endif exe_dino = executable('dino', sources, c_args: c_args, vala_args: vala_args, dependencies: dependencies, install: true, install_rpath: default_install_rpath) install_data('data/icons/scalable/apps/im.dino.Dino-symbolic.svg', install_dir: get_option('datadir') / 'icons/hicolor/symbolic/apps') diff --git a/main/src/ui/conversation_content_view/file_transmission_progress.vala b/main/src/ui/conversation_content_view/file_transmission_progress.vala index 43885c1b..3d893f52 100644 --- a/main/src/ui/conversation_content_view/file_transmission_progress.vala +++ b/main/src/ui/conversation_content_view/file_transmission_progress.vala @@ -84,9 +84,7 @@ namespace Dino.Ui { } } -#if GTK_4_14 private static extern Gsk.Path create_progress_arc(Gsk.Path circle, float percentage); -#endif public override void snapshot(Gtk.Snapshot snapshot) { base.snapshot(snapshot); @@ -97,7 +95,6 @@ namespace Dino.Ui { float line_width = (float) LINE_WIDTH; snapshot.translate({get_width() / 2, get_height() / 2}); -#if GTK_4_14 var fg_color = get_color(); get_style_context().lookup_color("accent_color", out fg_color); var builder = new Gsk.PathBuilder(); @@ -107,16 +104,6 @@ namespace Dino.Ui { stroke.set_line_cap(Gsk.LineCap.ROUND); var arc_path = create_progress_arc(circle_path, (float) progress_animation.value); snapshot.append_stroke(arc_path, stroke, fg_color); -#else - var fg_color = get_style_context().get_color(); - get_style_context().lookup_color("accent_color", out fg_color); - var context = snapshot.append_cairo({{-radius, -radius}, {radius*2, radius*2}}); - context.set_line_cap(Cairo.LineCap.ROUND); - context.set_line_width(line_width); - context.set_source_rgba(fg_color.red, fg_color.green, fg_color.blue, fg_color.alpha); - context.arc(0, 0, radius - line_width / 2, -0.5 * Math.PI, (progress_animation.value - 0.25) * 2 * Math.PI); - context.stroke(); -#endif } } diff --git a/main/src/ui/util/helper.vala b/main/src/ui/util/helper.vala index e9035be0..a126a196 100644 --- a/main/src/ui/util/helper.vala +++ b/main/src/ui/util/helper.vala @@ -415,18 +415,7 @@ public bool use_tooltips() { } public static void menu_button_set_icon_with_size(MenuButton menu_button, string icon_name, int pixel_size) { -#if GTK_4_6 && VALA_0_52 menu_button.set_child(new Image.from_icon_name(icon_name) { pixel_size=pixel_size }); -#else - menu_button.set_icon_name(icon_name); - var button = menu_button.get_first_child() as Button; - if (button == null) return; - var box = button.child as Box; - if (box == null) return; - var image = box.get_first_child() as Image; - if (image == null) return; - image.pixel_size = pixel_size; -#endif } } diff --git a/main/src/ui/widgets/avatar_picture.vala b/main/src/ui/widgets/avatar_picture.vala index 155c9440..12c635aa 100644 --- a/main/src/ui/widgets/avatar_picture.vala +++ b/main/src/ui/widgets/avatar_picture.vala @@ -455,11 +455,7 @@ public class Dino.Ui.AvatarPicture : Gtk.Widget { label.insert_after(this, null); label.attributes = new Pango.AttrList(); label.attributes.insert(Pango.attr_foreground_new(uint16.MAX, uint16.MAX, uint16.MAX)); -#if GTK_4_8 && (VALA_0_56_GREATER_5 || VALA_0_58) picture.content_fit = Gtk.ContentFit.COVER; -#elif GTK_4_8 - picture.@set("content-fit", 2); -#endif picture.insert_after(this, label); this.notify["model"].connect(on_model_changed); check_widget_leak(this); diff --git a/main/src/ui/widgets/fixed_ratio_picture.vala b/main/src/ui/widgets/fixed_ratio_picture.vala index 6b04ea61..1898efa7 100644 --- a/main/src/ui/widgets/fixed_ratio_picture.vala +++ b/main/src/ui/widgets/fixed_ratio_picture.vala @@ -8,9 +8,7 @@ class Dino.Ui.FixedRatioPicture : Gtk.Widget { public int max_height { get; set; default = int.MAX; } public File file { get { return inner.file; } set { inner.file = value; } } public Gdk.Paintable paintable { get { return inner.paintable; } set { inner.paintable = value; } } -#if GTK_4_8 && (VALA_0_56_GREATER_5 || VALA_0_58) public Gtk.ContentFit content_fit { get { return inner.content_fit; } set { inner.content_fit = value; } } -#endif private Gtk.Picture inner = new Gtk.Picture(); construct { diff --git a/main/src/windows/conversation_details.vala b/main/src/windows/conversation_details.vala index e1f3061f..8ec3125b 100644 --- a/main/src/windows/conversation_details.vala +++ b/main/src/windows/conversation_details.vala @@ -160,11 +160,7 @@ namespace Dino.Ui.ConversationDetails { } private void create_members() { -#if GTK_4_8 && (VALA_0_56_GREATER_5 || VALA_0_58) if (model.members_sorted.n_items == 0) return; -#else - if (model.members_sorted.model.get_n_items() == 0) return; -#endif var selection_model = new NoSelection(model.members_sorted); var item_factory = new BuilderListItemFactory.from_resource(null, "/im/dino/Dino/muc_member_list_row.ui"); diff --git a/meson.build b/meson.build index ad0f7e4e..7752f7d0 100644 --- a/meson.build +++ b/meson.build @@ -17,6 +17,12 @@ gnome = import('gnome') i18n = import('i18n') cc = meson.get_compiler('c') +vala_version_required = '0.56.14' +vala = meson.get_compiler('vala') +if not vala.version().version_compare('>= @0@'.format(vala_version_required)) + error('valac >= @0@ required!'.format(vala_version_required)) +endif + # Trigger recomnfiguration on version change version_stamp = configure_file( command: [ @@ -74,23 +80,23 @@ endif dep_gdk_pixbuf = dependency('gdk-pixbuf-2.0') dep_gee = dependency('gee-0.8') dep_gio = dependency('gio-2.0') -dep_glib = dependency('glib-2.0') +dep_glib = dependency('glib-2.0', version: '>=2.66') dep_gmodule = dependency('gmodule-2.0') dep_gpgme = dependency('gpgme', disabler: true, required: get_option('plugin-openpgp')) -dep_gstreamer = dependency('gstreamer-1.0', disabler: true, required: get_option('plugin-rtp')) -dep_gstreamer_app = dependency('gstreamer-app-1.0', disabler: true, required: get_option('plugin-rtp')) -dep_gstreamer_audio = dependency('gstreamer-audio-1.0', disabler: true, required: get_option('plugin-rtp')) -dep_gstreamer_rtp = dependency('gstreamer-rtp-1.0', disabler: true, required: get_option('plugin-rtp')) -dep_gstreamer_video = dependency('gstreamer-video-1.0', disabler: true, required: get_option('plugin-rtp')) -dep_gtk4 = dependency('gtk4') +dep_gstreamer = dependency('gstreamer-1.0', version: '>=1.20') +dep_gstreamer_app = dependency('gstreamer-app-1.0', version: '>=1.20') +dep_gstreamer_audio = dependency('gstreamer-audio-1.0', version: '>=1.20') +dep_gstreamer_rtp = dependency('gstreamer-rtp-1.0', version: '>=1.20') +dep_gstreamer_video = dependency('gstreamer-video-1.0', version: '>=1.20') +dep_gtk4 = dependency('gtk4', version: '>=4.14') dep_icu_uc = dependency('icu-uc') dep_libadwaita = dependency('libadwaita-1', version: '>=1.5') dep_libcanberra = dependency('libcanberra', disabler: true, required: get_option('plugin-notification-sound')) dep_libqrencode = dependency('libqrencode', disabler: true, required: get_option('plugin-omemo')) -dep_libsrtp2 = dependency('libsrtp2', disabler: true, required: true) +dep_libsrtp2 = dependency('libsrtp2') dep_libomemo_c = dependency('libomemo-c', disabler: true, required: get_option('plugin-omemo')) dep_libsoup = dependency('libsoup-3.0') -dep_nice = dependency('nice', version: '>=0.1.15', disabler: true, required: get_option('plugin-ice')) +dep_nice = dependency('nice', version: '>=0.1.15') dep_m = meson.get_compiler('c').find_library('m', required: false) dep_sqlite3 = dependency('sqlite3', version: '>=3.24') @@ -99,10 +105,7 @@ if not dep_webrtc_audio_processing.found() dep_webrtc_audio_processing = dependency('webrtc-audio-processing', version: ['>=0.2'], required: false) endif if not dep_webrtc_audio_processing.found() - dep_webrtc_audio_processing = dependency('webrtc-audio-processing-2', required: false) -endif -if not dep_webrtc_audio_processing.found() - dep_webrtc_audio_processing = disabler() + dep_webrtc_audio_processing = dependency('webrtc-audio-processing-2', required: false, disabler: true) endif default_install_rpath = '' diff --git a/plugins/omemo/src/ui/encryption_preferences_entry.vala b/plugins/omemo/src/ui/encryption_preferences_entry.vala index cea856bb..cb14978b 100644 --- a/plugins/omemo/src/ui/encryption_preferences_entry.vala +++ b/plugins/omemo/src/ui/encryption_preferences_entry.vala @@ -166,12 +166,7 @@ public class OmemoPreferencesWidget : Adw.PreferencesGroup { // Create and set QR code popover int sid = plugin.db.identity.row_with(plugin.db.identity.account_id, account.id)[plugin.db.identity.device_id]; var iri_query = @"omemo-sid-$(sid)=$(fingerprint)"; -#if GLIB_2_66 && VALA_0_50 string iri = GLib.Uri.join(UriFlags.NONE, "xmpp", null, null, 0, jid.to_string(), iri_query, null); -#else - var iri_path_seg = escape_for_iri_path_segment(jid.to_string()); - var iri = @"xmpp:$(iri_path_seg)?$(iri_query)"; -#endif const int QUIET_ZONE_MODULES = 4; // MUST be at least 4 const int MODULE_SIZE_PX = 4; // arbitrary diff --git a/plugins/openpgp/meson.build b/plugins/openpgp/meson.build index 56bc9d0c..78641012 100644 --- a/plugins/openpgp/meson.build +++ b/plugins/openpgp/meson.build @@ -38,9 +38,6 @@ c_args = vala_c_args + [ vala_args = [ '--vapidir', meson.current_source_dir() / 'vapi', ] -if dep_libadwaita.version() == 'unknown' or dep_libadwaita.version().version_compare('>=1.4') - vala_args += ['-D', 'Adw_1_4'] -endif lib_openpgp = shared_library('openpgp', sources, name_prefix: '', c_args: c_args, vala_args: vala_args, include_directories: include_directories('src'), dependencies: dependencies, install: true, install_dir: get_option('libdir') / get_option('plugindir'), install_rpath: default_install_rpath) dep_openpgp = declare_dependency(link_with: lib_openpgp, include_directories: include_directories('.')) summary('End-to-end encryption using PGP (openpgp)', dep_openpgp.found(), bool_yn: true, section: 'Plugins') diff --git a/plugins/rtp/meson.build b/plugins/rtp/meson.build index 2772ad88..f10fbc25 100644 --- a/plugins/rtp/meson.build +++ b/plugins/rtp/meson.build @@ -52,15 +52,6 @@ if dep_webrtc_audio_processing.found() and get_option('plugin-rtp-webrtc-audio-p elif get_option('plugin-rtp-webrtc-audio-processing').enabled() error('No compatible webrtc-audio-processing found, but plugin-rtp-webrtc-audio-processing option set.') endif -if dep_gstreamer_rtp.version() == 'unknown' or dep_gstreamer_rtp.version().version_compare('>=1.16') - vala_args += ['-D', 'GST_1_16'] -endif -if dep_gstreamer_rtp.version() == 'unknown' or dep_gstreamer_rtp.version().version_compare('>=1.18') - vala_args += ['-D', 'GST_1_18'] -endif -if dep_gstreamer_rtp.version() == 'unknown' or dep_gstreamer_rtp.version().version_compare('>=1.20') - vala_args += ['-D', 'GST_1_20'] -endif if meson.get_compiler('vala').version().version_compare('<0.56.1') vala_args += ['--vapidir', meson.current_source_dir() / 'vapi'] endif diff --git a/plugins/rtp/src/codec_util.vala b/plugins/rtp/src/codec_util.vala index 12fcfed7..9f21f5a6 100644 --- a/plugins/rtp/src/codec_util.vala +++ b/plugins/rtp/src/codec_util.vala @@ -280,9 +280,7 @@ public class Dino.Plugins.Rtp.CodecUtil { } public static string? get_depay_args(string media, string codec, string encode, JingleRtp.PayloadType? payload_type) { -#if GST_1_18 if (codec == "vp8") return " wait-for-keyframe=true"; -#endif return null; } diff --git a/plugins/rtp/src/plugin.vala b/plugins/rtp/src/plugin.vala index a94c0ba0..d09b7edf 100644 --- a/plugins/rtp/src/plugin.vala +++ b/plugins/rtp/src/plugin.vala @@ -243,13 +243,11 @@ public class Dino.Plugins.Rtp.Plugin : RootInterface, VideoCallPlugin, Object { device = new Device(this, gst_device); devices.add(device); break; -#if GST_1_16 case Gst.MessageType.DEVICE_CHANGED: message.parse_device_changed(out gst_device, out old_gst_device); device = devices.first_match((it) => it.matches(old_gst_device)); if (device != null) device.update(gst_device); break; -#endif case Gst.MessageType.DEVICE_REMOVED: message.parse_device_removed(out gst_device); device = devices.first_match((it) => it.matches(gst_device)); diff --git a/plugins/rtp/src/stream.vala b/plugins/rtp/src/stream.vala index aa2b080d..9a46d9ff 100644 --- a/plugins/rtp/src/stream.vala +++ b/plugins/rtp/src/stream.vala @@ -102,9 +102,7 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream { send_rtp.drop = true; send_rtp.wait_on_eos = false; send_rtp.new_sample.connect(on_new_sample); -#if GST_1_20 send_rtp.new_serialized_event.connect(on_new_event); -#endif send_rtp.connect("signal::eos", on_eos_static, this); pipe.add(send_rtp); @@ -299,7 +297,7 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream { bool flip = false; uint8 rotation = 0; -#if GST_1_20 + private bool on_new_event(Gst.App.Sink sink) { if (sink == null || sink != send_rtp) { return false; @@ -349,7 +347,7 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream { } return false; } -#endif + private Gst.FlowReturn on_new_sample(Gst.App.Sink sink) { if (sink == null) { @@ -373,14 +371,11 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream { next_timestamp_offset_stamp = get_monotonic_time(); rtp_buffer.unmap(); } -#if GLIB_2_64 if (our_ssrc != buffer_ssrc) { warning_once("Sending RTP %s buffer seq %u with SSRC %u when our ssrc is %u", media, buffer_seq, buffer_ssrc, our_ssrc); } -#endif } -#if GST_1_20 if (sink == send_rtp) { Xmpp.Xep.JingleRtp.HeaderExtension? ext = header_extensions.first_match((it) => it.uri == "urn:3gpp:video-orientation"); if (ext != null) { @@ -396,7 +391,6 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream { } } } -#endif prepare_local_crypto(); @@ -574,18 +568,7 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream { on_recv_rtcp_data(bytes); return; } -#if GST_1_16 - { - Gst.Buffer buffer = new Gst.Buffer.wrapped_bytes(bytes); - Gst.RTP.Buffer rtp_buffer; - uint buffer_ssrc = 0, buffer_seq = 0; - if (Gst.RTP.Buffer.map(buffer, Gst.MapFlags.READ, out rtp_buffer)) { - buffer_ssrc = rtp_buffer.get_ssrc(); - buffer_seq = rtp_buffer.get_seq(); - rtp_buffer.unmap(); - } - } -#endif + if (push_recv_data) { prepare_remote_crypto(); @@ -598,15 +581,13 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream { return; } } else { -#if GST_1_16 buffer = new Gst.Buffer.wrapped_bytes(bytes); -#else - buffer = new Gst.Buffer.wrapped(bytes.get_data()); -#endif } Gst.RTP.Buffer rtp_buffer; if (Gst.RTP.Buffer.map(buffer, Gst.MapFlags.READ, out rtp_buffer)) { + uint buffer_ssrc = rtp_buffer.get_ssrc(); + uint buffer_seq = rtp_buffer.get_seq(); if (rtp_buffer.get_extension()) { Xmpp.Xep.JingleRtp.HeaderExtension? ext = header_extensions.first_match((it) => it.uri == "urn:3gpp:video-orientation"); if (ext != null) { @@ -632,12 +613,7 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream { rtp_buffer.unmap(); } -#if VALA_0_50 recv_rtp.push_buffer((owned) buffer); -#else - Gst.FlowReturn ret; - GLib.Signal.emit_by_name(recv_rtp, "push-buffer", buffer, out ret); -#endif } } @@ -654,19 +630,10 @@ public class Dino.Plugins.Rtp.Stream : Xmpp.Xep.JingleRtp.Stream { return; } } else { -#if GST_1_16 buffer = new Gst.Buffer.wrapped_bytes(bytes); -#else - buffer = new Gst.Buffer.wrapped(bytes.get_data()); -#endif } -#if VALA_0_50 recv_rtcp.push_buffer((owned) buffer); -#else - Gst.FlowReturn ret; - GLib.Signal.emit_by_name(recv_rtcp, "push-buffer", buffer, out ret); -#endif } } diff --git a/plugins/rtp/src/video_widget.vala b/plugins/rtp/src/video_widget.vala index 5557ec76..af6eb14e 100644 --- a/plugins/rtp/src/video_widget.vala +++ b/plugins/rtp/src/video_widget.vala @@ -75,17 +75,10 @@ public class Dino.Plugins.Rtp.Sink : Gst.Video.Sink { set_drop_out_of_segment(false); } -#if GST_1_20 public override bool set_info(Gst.Caps caps, Gst.Video.Info info) { this.info = info; return true; } -#else - public override bool set_caps(Gst.Caps caps) { - base.set_caps(caps); - return info.from_caps(caps); - } -#endif public override void get_times(Gst.Buffer buffer, out Gst.ClockTime start, out Gst.ClockTime end) { if (buffer.pts != -1) { @@ -250,21 +243,13 @@ public class Dino.Plugins.Rtp.VideoWidget : Gtk.Widget, Dino.Plugins.VideoCallWi if (connected_device == null) return; plugin.pause(); pipe.add(sink); -#if GST_1_20 prepare = Gst.parse_bin_from_description(@"videoflip video-direction=auto name=video_widget_$(id)_orientation ! videoflip method=horizontal-flip name=video_widget_$(id)_flip ! videoconvert name=video_widget_$(id)_convert", true); -#else - prepare = Gst.parse_bin_from_description(@"videoflip method=horizontal-flip name=video_widget_$(id)_flip ! videoconvert name=video_widget_$(id)_convert", true); -#endif prepare.name = @"video_widget_$(id)_prepare"; -#if GST_1_20 if (prepare is Gst.Bin) { ((Gst.Bin) prepare).get_by_name(@"video_widget_$(id)_flip").get_static_pad("sink").notify["caps"].connect(input_caps_changed); } else { -#endif prepare.get_static_pad("sink").notify["caps"].connect(input_caps_changed); -#if GST_1_20 } -#endif pipe.add(prepare); connected_device_element = connected_device.link_source(); connected_device_element.link(prepare); diff --git a/xmpp-vala/meson.build b/xmpp-vala/meson.build index 971f77fa..210526a5 100644 --- a/xmpp-vala/meson.build +++ b/xmpp-vala/meson.build @@ -147,9 +147,6 @@ c_args = vala_c_args + [ vala_args = [ '--vapidir', meson.current_source_dir() / 'vapi', ] -if meson.get_compiler('vala').version().version_compare('=0.56.11') - vala_args += ['-D', 'VALA_0_56_11'] -endif lib_xmpp_vala = library('xmpp-vala', sources, c_args: c_args, vala_args: vala_args, dependencies: dependencies, version: '0.1', install: true, install_dir: [true, true, true], install_rpath: default_install_rpath) dep_xmpp_vala = declare_dependency(link_with: lib_xmpp_vala, include_directories: include_directories('.')) diff --git a/xmpp-vala/src/core/direct_tls_xmpp_stream.vala b/xmpp-vala/src/core/direct_tls_xmpp_stream.vala index 2f159ab6..55488eb5 100644 --- a/xmpp-vala/src/core/direct_tls_xmpp_stream.vala +++ b/xmpp-vala/src/core/direct_tls_xmpp_stream.vala @@ -19,9 +19,7 @@ public class Xmpp.DirectTlsXmppStream : TlsXmppStream { debug("Connecting to %s:%i (tls)", host, port); IOStream? io_stream = yield client.connect_to_host_async(host, port, cancellable); TlsConnection tls_connection = TlsClientConnection.new(io_stream, new NetworkAddress(remote_name.to_string(), port)); -#if GLIB_2_60 tls_connection.set_advertised_protocols(ADVERTISED_PROTOCOLS); -#endif tls_connection.accept_certificate.connect(on_invalid_certificate); tls_connection.accept_certificate.connect((cert, flags) => on_invalid_cert.func(cert, flags)); reset_stream(tls_connection); diff --git a/xmpp-vala/src/core/module_flag.vala b/xmpp-vala/src/core/module_flag.vala index 76ae4dc1..95547852 100644 --- a/xmpp-vala/src/core/module_flag.vala +++ b/xmpp-vala/src/core/module_flag.vala @@ -10,12 +10,7 @@ namespace Xmpp { } public T? cast(XmppStreamFlag flag) { -#if VALA_0_56_11 - // We can't typecheck due to compiler bug - return (T) module; -#else return flag.get_type().is_a(typeof(T)) ? (T?) flag : null; -#endif } public bool matches(XmppStreamFlag module) { @@ -39,12 +34,7 @@ namespace Xmpp { } public T? cast(XmppStreamModule module) { -#if VALA_0_56_11 - // We can't typecheck due to compiler bug - return (T) module; -#else return module.get_type().is_a(typeof(T)) ? (T?) module : null; -#endif } public bool matches(XmppStreamModule module) { -- cgit v1.3