Added message attachments from sharing intent on Android and drag-and-drop on desktop

This commit is contained in:
Mark Qvist 2024-11-23 17:23:12 +01:00
parent a9269f20d4
commit 0cbd4c71ab
3 changed files with 146 additions and 11 deletions

View File

@ -1,6 +1,6 @@
__debug_build__ = False __debug_build__ = False
__disable_shaders__ = False __disable_shaders__ = False
__version__ = "1.1.3" __version__ = "1.1.4"
__variant__ = "" __variant__ = ""
import sys import sys
@ -306,9 +306,11 @@ class SidebandApp(MDApp):
self.service_last_available = 0 self.service_last_available = 0
self.closing_app = False self.closing_app = False
self.file_manager = None
self.attach_path = None self.attach_path = None
self.attach_type = None self.attach_type = None
self.attach_dialog = None self.attach_dialog = None
self.shared_attach_dialog = None
self.rec_dialog = None self.rec_dialog = None
self.last_msg_audio = None self.last_msg_audio = None
self.msg_sound = None self.msg_sound = None
@ -892,6 +894,37 @@ class SidebandApp(MDApp):
if data.lower().startswith(LXMF.LXMessage.URI_SCHEMA): if data.lower().startswith(LXMF.LXMessage.URI_SCHEMA):
action = "lxm_uri" action = "lxm_uri"
if intent_action == "android.intent.action.SEND":
try:
Intent = autoclass("android.content.Intent")
extras = intent.getExtras()
target = extras.get(Intent.EXTRA_STREAM)
mime_types = extras.get(Intent.EXTRA_MIME_TYPES)
target_uri = target.toString()
target_path = target.getPath()
target_filename = target.getLastPathSegment()
RNS.log(f"Received share intent: {target_uri} / {target_path} / {target_filename}", RNS.LOG_DEBUG)
for cf in os.listdir(self.sideband.share_cache):
rt = os.path.join(self.sideband.share_cache, cf)
os.unlink(rt)
RNS.log("Removed previously cached data: "+str(rt), RNS.LOG_DEBUG)
ContentResolver = autoclass("android.content.ContentResolver")
cr = mActivity.getContentResolver()
cache_path = os.path.join(self.sideband.share_cache, target_filename)
input_stream = cr.openInputStream(target)
with open(cache_path, "wb") as cache_file:
cache_file.write(bytes(input_stream.readAllBytes()))
RNS.log("Cached shared data from Android intent", RNS.LOG_DEBUG)
action = "shared_data"
data = {"filename": target_filename, "data_path": cache_path}
except Exception as e:
RNS.log(f"Error while getting intent action data: {e}", RNS.LOG_ERROR)
RNS.trace_exception(e)
if action != None: if action != None:
self.handle_action(action, data) self.handle_action(action, data)
@ -899,6 +932,16 @@ class SidebandApp(MDApp):
if action == "lxm_uri": if action == "lxm_uri":
self.ingest_lxm_uri(data) self.ingest_lxm_uri(data)
if action == "shared_data":
RNS.log("Got shared data: "+str(data))
def cb(dt):
try:
self.shared_attachment_action(data)
except Exception as e:
RNS.log("Error while handling external message attachment", RNS.LOG_ERROR)
RNS.trace_exception(e)
Clock.schedule_once(cb, 0.1)
def ingest_lxm_uri(self, lxm_uri): def ingest_lxm_uri(self, lxm_uri):
RNS.log("Ingesting LXMF paper message from URI: "+str(lxm_uri), RNS.LOG_DEBUG) RNS.log("Ingesting LXMF paper message from URI: "+str(lxm_uri), RNS.LOG_DEBUG)
self.sideband.lxm_ingest_uri(lxm_uri) self.sideband.lxm_ingest_uri(lxm_uri)
@ -1086,6 +1129,9 @@ class SidebandApp(MDApp):
self.quit_action(None) self.quit_action(None)
return True return True
def file_dropped(self, window, file_path, x, y, *args):
self.shared_attachment_action({"data_path": file_path.decode("utf-8")})
def on_start(self): def on_start(self):
self.last_exit_event = time.time() self.last_exit_event = time.time()
self.root.ids.screen_manager.transition = self.slide_transition self.root.ids.screen_manager.transition = self.slide_transition
@ -1096,6 +1142,7 @@ class SidebandApp(MDApp):
EventLoop.window.bind(on_key_down=self.keydown_event) EventLoop.window.bind(on_key_down=self.keydown_event)
EventLoop.window.bind(on_key_up=self.keyup_event) EventLoop.window.bind(on_key_up=self.keyup_event)
Window.bind(on_request_close=self.close_requested) Window.bind(on_request_close=self.close_requested)
Window.bind(on_drop_file=self.file_dropped)
if __variant__ != "": if __variant__ != "":
variant_str = " "+__variant__ variant_str = " "+__variant__
@ -1701,6 +1748,7 @@ class SidebandApp(MDApp):
def message_fm_exited(self, *args): def message_fm_exited(self, *args):
self.manager_open = False self.manager_open = False
if self.file_manager != None:
self.file_manager.close() self.file_manager.close()
def message_select_file_action(self, sender=None): def message_select_file_action(self, sender=None):
@ -1716,11 +1764,20 @@ class SidebandApp(MDApp):
if perm_ok and path != None: if perm_ok and path != None:
try: try:
if self.attach_type in ["lbimg", "defimg", "hqimg"]:
self.file_manager = MDFileManager( self.file_manager = MDFileManager(
exit_manager=self.message_fm_exited, exit_manager=self.message_fm_exited,
select_path=self.message_fm_got_path, select_path=self.message_fm_got_path,
) # Current KivyMD preview implementation is too slow to be reliable on Android
# self.file_manager.ext = ["*"] preview=False)
else:
self.file_manager = MDFileManager(
exit_manager=self.message_fm_exited,
select_path=self.message_fm_got_path,
preview=False)
# self.file_manager.ext = []
# self.file_manager.search = "all"
self.file_manager.show(path) self.file_manager.show(path)
except Exception as e: except Exception as e:
@ -2197,6 +2254,65 @@ class SidebandApp(MDApp):
ate_dialog.open() ate_dialog.open()
def shared_attachment_action(self, attachment_data):
if not self.root.ids.screen_manager.current == "messages_screen":
if RNS.vendor.platformutils.is_android():
toast("Please select a conversation first")
else:
ok_button = MDRectangleFlatButton(text="OK",font_size=dp(18))
ate_dialog = MDDialog(
title="No active conversation",
text="To drop files as attachments, please open a conversation first",
buttons=[ ok_button ],
)
ok_button.bind(on_release=ate_dialog.dismiss)
ate_dialog.open()
else:
self.rec_dialog_is_open = False
def a_img_lb(sender):
self.attach_type="lbimg"
self.shared_attach_dialog.dismiss()
self.shared_attach_dialog.att_exc()
def a_img_def(sender):
self.attach_type="defimg"
self.shared_attach_dialog.dismiss()
self.shared_attach_dialog.att_exc()
def a_img_hq(sender):
self.attach_type="hqimg"
self.shared_attach_dialog.dismiss()
self.shared_attach_dialog.att_exc()
def a_file(sender):
self.attach_type="file"
self.shared_attach_dialog.dismiss()
self.shared_attach_dialog.att_exc()
if self.shared_attach_dialog == None:
ss = int(dp(18))
cancel_button = MDRectangleFlatButton(text="Cancel", font_size=dp(18))
ad_items = [
DialogItem(IconLeftWidget(icon="message-image-outline", on_release=a_img_lb), text="[size="+str(ss)+"]Low-bandwidth Image[/size]", on_release=a_img_lb),
DialogItem(IconLeftWidget(icon="file-image", on_release=a_img_def), text="[size="+str(ss)+"]Medium Image[/size]", on_release=a_img_def),
DialogItem(IconLeftWidget(icon="image-outline", on_release=a_img_hq), text="[size="+str(ss)+"]High-res Image[/size]", on_release=a_img_hq),
DialogItem(IconLeftWidget(icon="file-outline", on_release=a_file), text="[size="+str(ss)+"]File Attachment[/size]", on_release=a_file)]
self.shared_attach_dialog = MDDialog(
title="Add Attachment",
type="simple",
text="Select how you want to attach this data to the next message sent\n",
items=ad_items,
buttons=[ cancel_button ],
width_offset=dp(32),
)
cancel_button.bind(on_release=self.shared_attach_dialog.dismiss)
def att_exc():
self.message_fm_got_path(attachment_data["data_path"])
self.shared_attach_dialog.att_exc = att_exc
self.shared_attach_dialog.open()
def update_message_widgets(self): def update_message_widgets(self):
toolbar_items = self.messages_view.ids.messages_toolbar.ids.right_actions.children toolbar_items = self.messages_view.ids.messages_toolbar.ids.right_actions.children
mode_item = toolbar_items[1] mode_item = toolbar_items[1]

View File

@ -18,6 +18,17 @@
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter> </intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED" <meta-data android:name="android.hardware.usb.action.USB_DEVICE_ATTACHED"
android:resource="@xml/device_filter" /> android:resource="@xml/device_filter" />

View File

@ -203,6 +203,10 @@ class SidebandCore():
if not os.path.isdir(self.rec_cache): if not os.path.isdir(self.rec_cache):
os.makedirs(self.rec_cache) os.makedirs(self.rec_cache)
self.share_cache = self.cache_dir+"/share"
if not os.path.isdir(self.share_cache):
os.makedirs(self.share_cache)
self.icon = self.asset_dir+"/icon.png" self.icon = self.asset_dir+"/icon.png"
self.icon_48 = self.asset_dir+"/icon_48.png" self.icon_48 = self.asset_dir+"/icon_48.png"
self.icon_32 = self.asset_dir+"/icon_32.png" self.icon_32 = self.asset_dir+"/icon_32.png"
@ -4369,6 +4373,10 @@ class SidebandCore():
if not originator and LXMF.FIELD_AUDIO in message.fields and ptt_enabled: if not originator and LXMF.FIELD_AUDIO in message.fields and ptt_enabled:
self.ptt_event(message) self.ptt_event(message)
if self.gui_conversation() != context_dest:
if not RNS.vendor.platformutils.is_android():
should_notify = True
else:
should_notify = False should_notify = False
if self.is_client: if self.is_client: