From 6923c7e9b56a3961ee6bc88da3544dde76a31e6f Mon Sep 17 00:00:00 2001 From: Mark Qvist Date: Tue, 22 Nov 2022 19:47:13 +0100 Subject: [PATCH] Added paper message sharing on Android --- sbapp/main.py | 88 ++++++++++++++++++++++++++++++++++++- sbapp/sideband/core.py | 11 +++++ sbapp/ui/messages.py | 99 +++++++++++++++++++++++++++--------------- 3 files changed, 163 insertions(+), 35 deletions(-) diff --git a/sbapp/main.py b/sbapp/main.py index 7ea2f8a..3291184 100644 --- a/sbapp/main.py +++ b/sbapp/main.py @@ -1,4 +1,5 @@ -__debug_build__ = False +# TODO: Reset +__debug_build__ = True __disable_shaders__ = True __version__ = "0.4.0" __variant__ = "beta" @@ -271,6 +272,45 @@ class SidebandApp(MDApp): mActivity.startActivity(shareIntent) + def share_image(self, image, filename): + if RNS.vendor.platformutils.get_platform() == "android": + save_path = self.sideband.exports_dir + file_path = save_path+"/"+filename + + try: + if not os.path.isdir(save_path): + RNS.log("Creating directory: "+str(save_path)) + os.makedirs(save_path) + + Intent = autoclass("android.content.Intent") + Uri = autoclass("android.net.Uri") + File = autoclass("java.io.File") + FileProvider = autoclass("android.support.v4.content.FileProvider") + + image.save(file_path) + i_file = File(file_path) + image_uri = FileProvider.getUriForFile(mActivity, "io.unsigned.sideband.provider", i_file) + + shareIntent = Intent() + shareIntent.setAction(Intent.ACTION_SEND) + shareIntent.setType("image/png") + shareIntent.putExtra(Intent.EXTRA_STREAM, cast('android.os.Parcelable', image_uri)) + mActivity.startActivity(shareIntent) + + except Exception as e: + 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), + buttons=[ ok_button ], + ) + def dl_ok(s): + dialog.dismiss() + + ok_button.bind(on_release=dl_ok) + dialog.open() + + def on_pause(self): if self.sideband: if self.sideband.getstate("flag.focusfix_pause"): @@ -374,6 +414,52 @@ class SidebandApp(MDApp): self.check_permissions() + def check_storage_permission(self): + storage_permissions_ok = False + if android_api_version < 30: + if check_permission("android.permission.WRITE_EXTERNAL_STORAGE"): + storage_permissions_ok = True + else: + self.request_storage_permission() + + else: + Environment = autoclass('android.os.Environment') + + if Environment.isExternalStorageManager(): + storage_permissions_ok = True + else: + ok_button = MDRectangleFlatButton(text="OK",font_size=dp(18)) + dialog = MDDialog( + title="Storage Permission", + text="Sideband needs permission to write to external storage to export, share and print paper messages.\n\nOn this Android version, the Manage All Files permission is needed, since normal external storage permission is no longer supported.\n\nSideband will only ever read and write to files in the \"Sideband\" folder of your external storage, and does not read any other data from your system.", + buttons=[ ok_button ], + ) + def dl_ok(s): + dialog.dismiss() + self.request_storage_permission() + + ok_button.bind(on_release=dl_ok) + dialog.open() + + return storage_permissions_ok + + def request_storage_permission(self): + if RNS.vendor.platformutils.get_platform() == "android": + if android_api_version < 30: + if not check_permission("android.permission.WRITE_EXTERNAL_STORAGE"): + RNS.log("Requesting storage write permission", RNS.LOG_DEBUG) + request_permissions(["android.permission.WRITE_EXTERNAL_STORAGE"]) + + if not check_permission("android.permission.READ_EXTERNAL_STORAGE"): + RNS.log("Requesting storage read permission", RNS.LOG_DEBUG) + request_permissions(["android.permission.READ_EXTERNAL_STORAGE"]) + else: + Intent = autoclass('android.content.Intent') + Settings = autoclass('android.provider.Settings') + pIntent = Intent() + pIntent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION) + mActivity.startActivity(pIntent) + def request_bluetooth_permissions(self): if RNS.vendor.platformutils.get_platform() == "android": if not check_permission("android.permission.BLUETOOTH_CONNECT"): diff --git a/sbapp/sideband/core.py b/sbapp/sideband/core.py index baf3d68..13157e7 100644 --- a/sbapp/sideband/core.py +++ b/sbapp/sideband/core.py @@ -121,6 +121,7 @@ class SidebandCore(): self.db_path = self.app_dir+"/app_storage/sideband.db" self.lxmf_storage = self.app_dir+"/app_storage/" self.tmp_dir = self.app_dir+"/app_storage/tmp" + self.exports_dir = self.app_dir+"/exports" self.first_run = True @@ -135,6 +136,9 @@ class SidebandCore(): os.makedirs(self.tmp_dir) else: self.clear_tmp_dir() + + if os.path.isdir(self.exports_dir): + self.clear_exports_dir() except Exception as e: RNS.log("Error while configuring Sideband: "+str(e), RNS.LOG_ERROR) @@ -177,6 +181,13 @@ class SidebandCore(): fpath = self.tmp_dir+"/"+file os.unlink(fpath) + def clear_exports_dir(self): + if os.path.isdir(self.exports_dir): + for file in os.listdir(self.exports_dir): + fpath = self.exports_dir+"/"+file + RNS.log("Clearing "+str(fpath)) + os.unlink(fpath) + def __init_config(self): RNS.log("Creating new Sideband configuration...") if os.path.isfile(self.identity_path): diff --git a/sbapp/ui/messages.py b/sbapp/ui/messages.py index 310e756..50f4985 100644 --- a/sbapp/ui/messages.py +++ b/sbapp/ui/messages.py @@ -220,6 +220,11 @@ class Messages(): def gen_save_qr(lxm, item): if RNS.vendor.platformutils.is_android(): def x(): + qr_image = lxm.as_qr() + hash_str = RNS.hexrep(lxm.hash[-2:], delimit=False) + filename = "Paper_Message_"+time.strftime(file_ts_format, time.localtime(m["sent"]))+"_"+hash_str+".png" + # filename = "Paper_Message.png" + self.app.share_image(qr_image, filename) item.dmenu.dismiss() return x @@ -303,41 +308,67 @@ class Messages(): if m["method"] == LXMF.LXMessage.PAPER: if RNS.vendor.platformutils.is_android(): qr_save_text = "Share QR Code" - else: - qr_save_text = "Save QR Code" + dm_items = [ + { + "viewclass": "OneLineListItem", + "text": "Share QR Code", + "height": dp(40), + "on_release": gen_save_qr(m["lxm"], item) + }, + { + "viewclass": "OneLineListItem", + "text": "Copy LXM URI", + "height": dp(40), + "on_release": gen_copy_lxm_uri(m["lxm"], item) + }, + { + "viewclass": "OneLineListItem", + "text": "Copy message text", + "height": dp(40), + "on_release": gen_copy(m["content"].decode("utf-8"), item) + }, + { + "text": "Delete", + "viewclass": "OneLineListItem", + "height": dp(40), + "on_release": gen_del(m["hash"], item) + } + ] + + else: + dm_items = [ + { + "viewclass": "OneLineListItem", + "text": "Print QR Code", + "height": dp(40), + "on_release": gen_print_qr(m["lxm"], item) + }, + { + "viewclass": "OneLineListItem", + "text": "Save QR Code", + "height": dp(40), + "on_release": gen_save_qr(m["lxm"], item) + }, + { + "viewclass": "OneLineListItem", + "text": "Copy LXM URI", + "height": dp(40), + "on_release": gen_copy_lxm_uri(m["lxm"], item) + }, + { + "viewclass": "OneLineListItem", + "text": "Copy message text", + "height": dp(40), + "on_release": gen_copy(m["content"].decode("utf-8"), item) + }, + { + "text": "Delete", + "viewclass": "OneLineListItem", + "height": dp(40), + "on_release": gen_del(m["hash"], item) + } + ] - dm_items = [ - { - "viewclass": "OneLineListItem", - "text": "Print QR Code", - "height": dp(40), - "on_release": gen_print_qr(m["lxm"], item) - }, - { - "viewclass": "OneLineListItem", - "text": qr_save_text, - "height": dp(40), - "on_release": gen_save_qr(m["lxm"], item) - }, - { - "viewclass": "OneLineListItem", - "text": "Copy LXM URI", - "height": dp(40), - "on_release": gen_copy_lxm_uri(m["lxm"], item) - }, - { - "viewclass": "OneLineListItem", - "text": "Copy message text", - "height": dp(40), - "on_release": gen_copy(m["content"].decode("utf-8"), item) - }, - { - "text": "Delete", - "viewclass": "OneLineListItem", - "height": dp(40), - "on_release": gen_del(m["hash"], item) - } - ] else: dm_items = [ {