From af56178064f032b58cfbe97b556131877da93ff8 Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Sun, 17 Mar 2024 00:23:55 +0100 Subject: [PATCH] Added image and file attachment saving --- sbapp/main.py | 9 ++- sbapp/ui/messages.py | 166 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+), 2 deletions(-) diff --git a/sbapp/main.py b/sbapp/main.py index f2a109c..cf6ed91 100644 --- a/sbapp/main.py +++ b/sbapp/main.py @@ -470,7 +470,12 @@ class SidebandApp(MDApp): File = autoclass("java.io.File") FileProvider = autoclass("androidx.core.content.FileProvider") - image.save(file_path) + if isinstance(image, bytes): + with open(file_path, "wb") as export_file: + export_file.write(image) + else: + image.save(file_path) + i_file = File(file_path) image_uri = FileProvider.getUriForFile(mActivity, "io.unsigned.sideband.provider", i_file) @@ -484,7 +489,7 @@ class SidebandApp(MDApp): ok_button = MDRectangleFlatButton(text="OK",font_size=dp(18)) dialog = MDDialog( title="Export Error", - text="The QR-code could not be exported and shared:\n\n"+str(e), + text="The resource could not be exported and shared:\n\n"+str(e), buttons=[ ok_button ], ) def dl_ok(s): diff --git a/sbapp/ui/messages.py b/sbapp/ui/messages.py index 7f05497..97160c9 100644 --- a/sbapp/ui/messages.py +++ b/sbapp/ui/messages.py @@ -202,6 +202,9 @@ class Messages(): extra_telemetry = {} telemeter = None image_field = None + has_image = False + attachments_field = None + has_attachment = False force_markup = False signature_valid = False @@ -239,9 +242,18 @@ class Messages(): if "lxm" in m and m["lxm"] and m["lxm"].fields != None and LXMF.FIELD_IMAGE in m["lxm"].fields: try: image_field = m["lxm"].fields[LXMF.FIELD_IMAGE] + has_image = True except Exception as e: pass + if "lxm" in m and m["lxm"] and m["lxm"].fields != None and LXMF.FIELD_FILE_ATTACHMENTS in m["lxm"].fields: + if len(m["lxm"].fields[LXMF.FIELD_FILE_ATTACHMENTS]) > 0: + try: + attachments_field = m["lxm"].fields[LXMF.FIELD_FILE_ATTACHMENTS] + has_attachment = True + except Exception as e: + pass + rcvd_d_str = "" trcvd = telemeter.read("received") if telemeter else None @@ -331,14 +343,24 @@ class Messages(): pre_content += "[b]Warning![/b] The signature for this message could not be validated. [b]This message is likely to be fake[/b].\n\n" force_markup = True + if has_attachment: + heading_str += "\n[b]Attachments[/b] " + for attachment in attachments_field: + heading_str += str(attachment[0])+", " + heading_str = heading_str[:-2] + item = ListLXMessageCard( text=pre_content+message_markup.decode("utf-8")+extra_content, heading=heading_str, md_bg_color=msg_color, ) + if has_attachment: + item.attachments_field = attachments_field + if image_field != None: item.has_image = True + item.image_field = image_field img = item.ids.message_image img.source = "" img.texture = CoreImage(io.BytesIO(image_field[1]), ext=image_field[0]).texture @@ -425,6 +447,134 @@ class Messages(): return x + def gen_save_image(item): + if RNS.vendor.platformutils.is_android(): + def x(): + image_field = item.image_field + extension = str(image_field[0]).replace(".", "") + filename = time.strftime("LXM_%Y_%m_%d_%H_%M_%S", time.localtime(time.time()))+"."+str(extension) + + self.app.share_image(image_field[1], filename) + item.dmenu.dismiss() + return x + + else: + def x(): + image_field = item.image_field + try: + extension = str(image_field[0]).replace(".", "") + filename = time.strftime("LXM_%Y_%m_%d_%H_%M_%S", time.localtime(time.time()))+"."+str(extension) + if RNS.vendor.platformutils.is_darwin(): + save_path = str(plyer.storagepath.get_downloads_dir()+filename).replace("file://", "") + else: + save_path = plyer.storagepath.get_downloads_dir()+"/"+filename + + with open(save_path, "wb") as save_file: + save_file.write(image_field[1]) + + item.dmenu.dismiss() + + ok_button = MDRectangleFlatButton(text="OK",font_size=dp(18)) + dialog = MDDialog( + title="Image Saved", + text="The image has been saved to: "+save_path+"", + buttons=[ ok_button ], + # elevation=0, + ) + def dl_ok(s): + dialog.dismiss() + + ok_button.bind(on_release=dl_ok) + dialog.open() + + except Exception as e: + item.dmenu.dismiss() + ok_button = MDRectangleFlatButton(text="OK",font_size=dp(18)) + dialog = MDDialog( + title="Error", + text="Could not save the image:\n\n"+save_path+"\n\n"+str(e), + buttons=[ ok_button ], + # elevation=0, + ) + def dl_ok(s): + dialog.dismiss() + + ok_button.bind(on_release=dl_ok) + dialog.open() + + item.dmenu.dismiss() + + return x + + def gen_save_attachment(item): + def x(): + attachments_field = item.attachments_field + if isinstance(attachments_field, list): + try: + if RNS.vendor.platformutils.is_darwin(): + output_path = str(plyer.storagepath.get_downloads_dir()).replace("file://", "") + else: + output_path = plyer.storagepath.get_downloads_dir()+"/" + + if len(attachments_field) == 1: + saved_text = "The attached file has been saved to: "+output_path + saved_title = "Attachment Saved" + else: + saved_text = "The attached files have been saved to: "+output_path + saved_title = "Attachment Saved" + + for attachment in attachments_field: + filename = str(attachment[0]).replace("../", "").replace("..\\", "") + if RNS.vendor.platformutils.is_darwin(): + save_path = str(plyer.storagepath.get_downloads_dir()+filename).replace("file://", "") + else: + save_path = plyer.storagepath.get_downloads_dir()+"/"+filename + + name_counter = 1 + pre_count = save_path + while os.path.exists(save_path): + save_path = str(pre_count)+"."+str(name_counter) + name_counter += 1 + + saved_text = "The attached file has been saved to: "+save_path + + with open(save_path, "wb") as save_file: + save_file.write(attachment[1]) + + item.dmenu.dismiss() + + ok_button = MDRectangleFlatButton(text="OK",font_size=dp(18)) + dialog = MDDialog( + title=saved_title, + text=saved_text, + buttons=[ ok_button ], + # elevation=0, + ) + def dl_ok(s): + dialog.dismiss() + + ok_button.bind(on_release=dl_ok) + dialog.open() + + except Exception as e: + item.dmenu.dismiss() + ok_button = MDRectangleFlatButton(text="OK",font_size=dp(18)) + dialog = MDDialog( + title="Error", + text="Could not save the attachment:\n\n"+save_path+"\n\n"+str(e), + buttons=[ ok_button ], + # elevation=0, + ) + def dl_ok(s): + dialog.dismiss() + + ok_button.bind(on_release=dl_ok) + dialog.open() + + item.dmenu.dismiss() + + return x + def gen_copy_telemetry(telemeter, extra_telemetry, item): def x(): try: @@ -670,6 +820,22 @@ class Messages(): "on_release": gen_del(m["hash"], item) } ] + if has_image: + extra_item = { + "viewclass": "OneLineListItem", + "text": "Save image", + "height": dp(40), + "on_release": gen_save_image(item) + } + dm_items.append(extra_item) + if has_attachment: + extra_item = { + "viewclass": "OneLineListItem", + "text": "Save attachment", + "height": dp(40), + "on_release": gen_save_attachment(item) + } + dm_items.append(extra_item) item.dmenu = MDDropdownMenu( caller=item.ids.msg_submenu,