Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions ios/Flutter/ephemeral/flutter_lldb_helper.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#
# Generated file, do not edit.
#

import lldb

def handle_new_rx_page(frame: lldb.SBFrame, bp_loc, extra_args, intern_dict):
"""Intercept NOTIFY_DEBUGGER_ABOUT_RX_PAGES and touch the pages."""
base = frame.register["x0"].GetValueAsAddress()
page_len = frame.register["x1"].GetValueAsUnsigned()

# Note: NOTIFY_DEBUGGER_ABOUT_RX_PAGES will check contents of the
# first page to see if handled it correctly. This makes diagnosing
# misconfiguration (e.g. missing breakpoint) easier.
data = bytearray(page_len)
data[0:8] = b'IHELPED!'

error = lldb.SBError()
frame.GetThread().GetProcess().WriteMemory(base, data, error)
if not error.Success():
print(f'Failed to write into {base}[+{page_len}]', error)
return

def __lldb_init_module(debugger: lldb.SBDebugger, _):
target = debugger.GetDummyTarget()
# Caveat: must use BreakpointCreateByRegEx here and not
# BreakpointCreateByName. For some reasons callback function does not
# get carried over from dummy target for the later.
bp = target.BreakpointCreateByRegex("^NOTIFY_DEBUGGER_ABOUT_RX_PAGES$")
bp.SetScriptCallbackFunction('{}.handle_new_rx_page'.format(__name__))
bp.SetAutoContinue(True)
print("-- LLDB integration loaded --")
5 changes: 5 additions & 0 deletions ios/Flutter/ephemeral/flutter_lldbinit
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#
# Generated file, do not edit.
#

command script import --relative-to-command-file flutter_lldb_helper.py
21 changes: 16 additions & 5 deletions lib/services/ui/attachments_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import 'package:exif/exif.dart';
import 'package:file_picker/file_picker.dart' hide PlatformFile;
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:get/get.dart';
import 'package:image_size_getter/file_input.dart';
Expand All @@ -26,6 +27,7 @@ import 'package:vcf_dart/vcf_dart.dart';
import 'package:video_thumbnail/video_thumbnail.dart';

AttachmentsService as = Get.isRegistered<AttachmentsService>() ? Get.find<AttachmentsService>() : Get.put(AttachmentsService());
const MethodChannel _desktopMediaChannel = MethodChannel('com.bluebubbles.messaging');

class AttachmentsService extends GetxService {

Expand Down Expand Up @@ -346,19 +348,28 @@ class AttachmentsService extends GetxService {
}

// Handle getting heic and tiff images
if (attachment.mimeType!.contains('image/hei') && !kIsDesktop) {
if (attachment.mimeType!.contains('image/hei')) {
if (await File("$filePath.png").exists()) {
originalFile = File("$filePath.png");
} else {
try {
if (onlyFetchData) {
if (kIsDesktop && Platform.isLinux) {
await _desktopMediaChannel.invokeMethod("decode-heif", {
"file": filePath,
"output": "$filePath.png",
});
originalFile = File("$filePath.png");
if (onlyFetchData) {
return await originalFile.readAsBytes();
}
} else if (!kIsDesktop && onlyFetchData) {
return await FlutterImageCompress.compressWithFile(
filePath,
format: CompressFormat.png,
keepExif: true,
quality: isPreview ? 25 : 100,
);
} else {
} else if (!kIsDesktop) {
final file = await FlutterImageCompress.compressAndGetFile(
filePath,
"$filePath.png",
Expand Down Expand Up @@ -422,7 +433,7 @@ class AttachmentsService extends GetxService {
}
} else if (attachment.mimeStart == "image") {
try {
Size size = await getImageSizing(filePath, attachment);
Size size = await getImageSizing(originalFile.path, attachment);
if (size.width != 0 && size.height != 0) {
attachment.width = size.width.toInt();
attachment.height = size.height.toInt();
Expand Down Expand Up @@ -451,4 +462,4 @@ class AttachmentsService extends GetxService {

return previewData;
}
}
}
2 changes: 1 addition & 1 deletion linux/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ endif()
# of modifying this function.
function(APPLY_STANDARD_SETTINGS TARGET)
target_compile_features(${TARGET} PUBLIC cxx_std_14)
target_compile_options(${TARGET} PRIVATE -Wall -Werror)
target_compile_options(${TARGET} PRIVATE -Wall -Werror -Wno-error=deprecated-declarations)
target_compile_options(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:-O3>")
target_compile_definitions(${TARGET} PRIVATE "$<$<NOT:$<CONFIG:Debug>>:NDEBUG>")
endfunction()
Expand Down
69 changes: 69 additions & 0 deletions linux/my_application.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#include "my_application.h"

#include <flutter_linux/flutter_linux.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <cstring>
#ifdef GDK_WINDOWING_X11
#include <gdk/gdkx.h>
#endif
Expand All @@ -12,10 +14,68 @@
struct _MyApplication {
GtkApplication parent_instance;
char** dart_entrypoint_arguments;
FlMethodChannel* channel;
};

G_DEFINE_TYPE(MyApplication, my_application, GTK_TYPE_APPLICATION)

static void respond_with_error(FlMethodCall* method_call,
const gchar* code,
const gchar* message) {
g_autoptr(FlMethodResponse) response = FL_METHOD_RESPONSE(
fl_method_error_response_new(code, message, nullptr));
fl_method_call_respond(method_call, response, nullptr);
}

static void method_call_cb(FlMethodChannel* channel,
FlMethodCall* method_call,
gpointer user_data) {
(void)channel;
(void)user_data;
const gchar* method = fl_method_call_get_name(method_call);

if (strcmp(method, "decode-heif") != 0) {
g_autoptr(FlMethodResponse) response = FL_METHOD_RESPONSE(
fl_method_not_implemented_response_new());
fl_method_call_respond(method_call, response, nullptr);
return;
}

FlValue* args = fl_method_call_get_args(method_call);
if (args == nullptr || fl_value_get_type(args) != FL_VALUE_TYPE_MAP) {
respond_with_error(method_call, "bad-args", "Expected argument map");
return;
}

FlValue* file_value = fl_value_lookup_string(args, "file");
FlValue* output_value = fl_value_lookup_string(args, "output");
if (file_value == nullptr || output_value == nullptr ||
fl_value_get_type(file_value) != FL_VALUE_TYPE_STRING ||
fl_value_get_type(output_value) != FL_VALUE_TYPE_STRING) {
respond_with_error(method_call, "bad-args", "Missing file or output path");
return;
}

const gchar* input_path = fl_value_get_string(file_value);
const gchar* output_path = fl_value_get_string(output_value);

g_autoptr(GError) error = nullptr;
g_autoptr(GdkPixbuf) pixbuf = gdk_pixbuf_new_from_file(input_path, &error);
if (pixbuf == nullptr) {
respond_with_error(method_call, "decode-failed", error->message);
return;
}

if (!gdk_pixbuf_save(pixbuf, output_path, "png", &error, nullptr)) {
respond_with_error(method_call, "encode-failed", error->message);
return;
}

g_autoptr(FlMethodResponse) response =
FL_METHOD_RESPONSE(fl_method_success_response_new(nullptr));
fl_method_call_respond(method_call, response, nullptr);
}

// Implements GApplication::activate.
static void my_application_activate(GApplication* application) {
MyApplication* self = MY_APPLICATION(application);
Expand Down Expand Up @@ -63,6 +123,14 @@ static void my_application_activate(GApplication* application) {

fl_register_plugins(FL_PLUGIN_REGISTRY(view));

FlEngine* engine = fl_view_get_engine(view);
FlBinaryMessenger* messenger = fl_engine_get_binary_messenger(engine);
g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new();
self->channel = fl_method_channel_new(
messenger, "com.bluebubbles.messaging", FL_METHOD_CODEC(codec));
fl_method_channel_set_method_call_handler(self->channel, method_call_cb,
self, nullptr);

gtk_widget_grab_focus(GTK_WIDGET(view));
}

Expand All @@ -89,6 +157,7 @@ static gboolean my_application_local_command_line(GApplication* application, gch
static void my_application_dispose(GObject* object) {
MyApplication* self = MY_APPLICATION(object);
g_clear_pointer(&self->dart_entrypoint_arguments, g_strfreev);
g_clear_object(&self->channel);
G_OBJECT_CLASS(my_application_parent_class)->dispose(object);
}

Expand Down
Loading