mirror of
https://github.com/liberatedsystems/Sideband_CE.git
synced 2024-09-03 04:13:27 +02:00
Added service split for Android and notifications on Android and Linux
This commit is contained in:
parent
e58c8a96be
commit
7ee0171ec7
102
sbapp/main.py
102
sbapp/main.py
@ -72,8 +72,6 @@ class SidebandApp(MDApp):
|
|||||||
self.android_service = None
|
self.android_service = None
|
||||||
|
|
||||||
self.app_dir = plyer.storagepath.get_application_dir()
|
self.app_dir = plyer.storagepath.get_application_dir()
|
||||||
# TODO: Remove
|
|
||||||
RNS.log("Application directory is: "+str(self.app_dir))
|
|
||||||
|
|
||||||
if RNS.vendor.platformutils.get_platform() == "android":
|
if RNS.vendor.platformutils.get_platform() == "android":
|
||||||
self.sideband = SidebandCore(self, is_client=True, android_app_dir=self.app_dir)
|
self.sideband = SidebandCore(self, is_client=True, android_app_dir=self.app_dir)
|
||||||
@ -82,20 +80,16 @@ class SidebandApp(MDApp):
|
|||||||
|
|
||||||
self.conversations_view = None
|
self.conversations_view = None
|
||||||
|
|
||||||
self.flag_new_conversations = False
|
|
||||||
self.flag_unread_conversations = False
|
|
||||||
self.flag_new_announces = False
|
|
||||||
self.lxmf_sync_dialog_open = False
|
|
||||||
self.sync_dialog = None
|
self.sync_dialog = None
|
||||||
|
|
||||||
Window.softinput_mode = "below_target"
|
Window.softinput_mode = "below_target"
|
||||||
self.icon = self.sideband.asset_dir+"/icon.png"
|
self.icon = self.sideband.asset_dir+"/icon.png"
|
||||||
self.notification_icon = self.sideband.asset_dir+"/notification_icon.png"
|
self.notification_icon = self.sideband.asset_dir+"/notification_icon.png"
|
||||||
|
self.check_permissions()
|
||||||
|
|
||||||
def start_core(self, dt):
|
def start_core(self, dt):
|
||||||
self.start_service()
|
self.start_service()
|
||||||
|
|
||||||
self.open_conversations()
|
|
||||||
Clock.schedule_interval(self.jobs, 1)
|
Clock.schedule_interval(self.jobs, 1)
|
||||||
|
|
||||||
def dismiss_splash(dt):
|
def dismiss_splash(dt):
|
||||||
@ -105,8 +99,15 @@ class SidebandApp(MDApp):
|
|||||||
if RNS.vendor.platformutils.get_platform() == "android":
|
if RNS.vendor.platformutils.get_platform() == "android":
|
||||||
Clock.schedule_once(dismiss_splash, 0)
|
Clock.schedule_once(dismiss_splash, 0)
|
||||||
|
|
||||||
if self.sideband.first_run:
|
self.sideband.setstate("app.loaded", True)
|
||||||
self.guide_action()
|
self.sideband.setstate("app.running", True)
|
||||||
|
self.sideband.setstate("app.foreground", True)
|
||||||
|
|
||||||
|
if self.sideband.first_run:
|
||||||
|
self.guide_action()
|
||||||
|
self.request_notifications_permission()
|
||||||
|
else:
|
||||||
|
self.open_conversations()
|
||||||
|
|
||||||
self.app_state = SidebandApp.ACTIVE
|
self.app_state = SidebandApp.ACTIVE
|
||||||
|
|
||||||
@ -125,8 +126,6 @@ class SidebandApp(MDApp):
|
|||||||
time.sleep(7)
|
time.sleep(7)
|
||||||
|
|
||||||
# Start local core instance
|
# Start local core instance
|
||||||
# TODO: Remove log
|
|
||||||
RNS.log("Starting local core")
|
|
||||||
self.sideband.start()
|
self.sideband.start()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -150,14 +149,20 @@ class SidebandApp(MDApp):
|
|||||||
mActivity.startActivity(shareIntent)
|
mActivity.startActivity(shareIntent)
|
||||||
|
|
||||||
def on_pause(self):
|
def on_pause(self):
|
||||||
|
self.sideband.setstate("app.running", True)
|
||||||
|
self.sideband.setstate("app.foreground", False)
|
||||||
self.app_state = SidebandApp.PAUSED
|
self.app_state = SidebandApp.PAUSED
|
||||||
self.sideband.should_persist_data()
|
self.sideband.should_persist_data()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def on_resume(self):
|
def on_resume(self):
|
||||||
|
self.sideband.setstate("app.running", True)
|
||||||
|
self.sideband.setstate("app.foreground", True)
|
||||||
self.app_state = SidebandApp.ACTIVE
|
self.app_state = SidebandApp.ACTIVE
|
||||||
|
|
||||||
def on_stop(self):
|
def on_stop(self):
|
||||||
|
self.sideband.setstate("app.running", False)
|
||||||
|
self.sideband.setstate("app.foreground", False)
|
||||||
self.app_state = SidebandApp.STOPPING
|
self.app_state = SidebandApp.STOPPING
|
||||||
|
|
||||||
def is_in_foreground(self):
|
def is_in_foreground(self):
|
||||||
@ -166,25 +171,27 @@ class SidebandApp(MDApp):
|
|||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def notify(self, title, content):
|
def check_permissions(self):
|
||||||
notifications_enabled = True
|
if RNS.vendor.platformutils.get_platform() == "android":
|
||||||
|
if check_permission("android.permission.POST_NOTIFICATIONS"):
|
||||||
if notifications_enabled:
|
RNS.log("Have notification permissions")
|
||||||
if RNS.vendor.platformutils.get_platform() == "android":
|
self.sideband.setpersistent("permissions.notifications", True)
|
||||||
notifications_permitted = False
|
|
||||||
if check_permission("android.permission.POST_NOTIFICATIONS"):
|
|
||||||
notifications_permitted = True
|
|
||||||
else:
|
|
||||||
RNS.log("Requesting notification permission")
|
|
||||||
request_permissions(["android.permission.POST_NOTIFICATIONS"])
|
|
||||||
else:
|
else:
|
||||||
notifications_permitted = True
|
RNS.log("Do not have notification permissions")
|
||||||
|
self.sideband.setpersistent("permissions.notifications", False)
|
||||||
|
else:
|
||||||
|
self.sideband.setpersistent("permissions.notifications", True)
|
||||||
|
|
||||||
if notifications_permitted:
|
def request_permissions(self):
|
||||||
if RNS.vendor.platformutils.get_platform() == "android":
|
self.request_notifications_permission()
|
||||||
plyer.notification.notify(title, content, notification_icon=self.notification_icon)
|
|
||||||
else:
|
def request_notifications_permission(self):
|
||||||
plyer.notification.notify(title, content)
|
if RNS.vendor.platformutils.get_platform() == "android":
|
||||||
|
if not check_permission("android.permission.POST_NOTIFICATIONS"):
|
||||||
|
RNS.log("Requesting notification permission")
|
||||||
|
request_permissions(["android.permission.POST_NOTIFICATIONS"])
|
||||||
|
|
||||||
|
self.check_permissions()
|
||||||
|
|
||||||
def build(self):
|
def build(self):
|
||||||
FONT_PATH = self.sideband.asset_dir+"/fonts"
|
FONT_PATH = self.sideband.asset_dir+"/fonts"
|
||||||
@ -201,22 +208,22 @@ class SidebandApp(MDApp):
|
|||||||
self.message_area_detect()
|
self.message_area_detect()
|
||||||
|
|
||||||
elif self.root.ids.screen_manager.current == "conversations_screen":
|
elif self.root.ids.screen_manager.current == "conversations_screen":
|
||||||
if self.flag_new_conversations:
|
if self.sideband.getstate("app.flags.new_conversations"):
|
||||||
RNS.log("Updating because of new conversations flag")
|
RNS.log("Updating because of new conversations flag")
|
||||||
if self.conversations_view != None:
|
if self.conversations_view != None:
|
||||||
self.conversations_view.update()
|
self.conversations_view.update()
|
||||||
|
|
||||||
if self.flag_unread_conversations:
|
if self.sideband.getstate("app.flags.unread_conversations"):
|
||||||
RNS.log("Updating because of unread messages flag")
|
RNS.log("Updating because of unread messages flag")
|
||||||
if self.conversations_view != None:
|
if self.conversations_view != None:
|
||||||
self.conversations_view.update()
|
self.conversations_view.update()
|
||||||
|
|
||||||
if self.lxmf_sync_dialog_open and self.sync_dialog != None:
|
if self.sideband.getstate("app.flags.lxmf_sync_dialog_open") and self.sync_dialog != None:
|
||||||
self.sync_dialog.ids.sync_progress.value = self.sideband.get_sync_progress()*100
|
self.sync_dialog.ids.sync_progress.value = self.sideband.get_sync_progress()*100
|
||||||
self.sync_dialog.ids.sync_status.text = self.sideband.get_sync_status()
|
self.sync_dialog.ids.sync_status.text = self.sideband.get_sync_status()
|
||||||
|
|
||||||
elif self.root.ids.screen_manager.current == "announces_screen":
|
elif self.root.ids.screen_manager.current == "announces_screen":
|
||||||
if self.flag_new_announces:
|
if self.sideband.getstate("app.flags.new_announces"):
|
||||||
RNS.log("Updating because of new announces flag")
|
RNS.log("Updating because of new announces flag")
|
||||||
if self.announces_view != None:
|
if self.announces_view != None:
|
||||||
self.announces_view.update()
|
self.announces_view.update()
|
||||||
@ -304,6 +311,9 @@ class SidebandApp(MDApp):
|
|||||||
self.root.ids.nav_drawer.set_state("closed")
|
self.root.ids.nav_drawer.set_state("closed")
|
||||||
self.sideband.should_persist_data()
|
self.sideband.should_persist_data()
|
||||||
|
|
||||||
|
self.sideband.setstate("app.running", False)
|
||||||
|
self.sideband.setstate("app.foreground", False)
|
||||||
|
|
||||||
def final_exit(dt):
|
def final_exit(dt):
|
||||||
RNS.exit()
|
RNS.exit()
|
||||||
MDApp.get_running_app().stop()
|
MDApp.get_running_app().stop()
|
||||||
@ -328,13 +338,6 @@ class SidebandApp(MDApp):
|
|||||||
yes_button.bind(on_release=dl_yes)
|
yes_button.bind(on_release=dl_yes)
|
||||||
dialog.open()
|
dialog.open()
|
||||||
|
|
||||||
def conversation_update(self, context_dest):
|
|
||||||
pass
|
|
||||||
# if self.root.ids.messages_scrollview.active_conversation == context_dest:
|
|
||||||
# self.messages_view.update_widget()
|
|
||||||
# else:
|
|
||||||
# RNS.log("Not updating since context_dest does not match active")
|
|
||||||
|
|
||||||
|
|
||||||
#################################################
|
#################################################
|
||||||
# Screens #
|
# Screens #
|
||||||
@ -372,12 +375,14 @@ class SidebandApp(MDApp):
|
|||||||
self.root.ids.messages_scrollview.scroll_y = 0
|
self.root.ids.messages_scrollview.scroll_y = 0
|
||||||
self.root.ids.messages_toolbar.title = self.sideband.peer_display_name(context_dest)
|
self.root.ids.messages_toolbar.title = self.sideband.peer_display_name(context_dest)
|
||||||
self.root.ids.messages_scrollview.active_conversation = context_dest
|
self.root.ids.messages_scrollview.active_conversation = context_dest
|
||||||
|
self.sideband.setstate("app.active_conversation", context_dest)
|
||||||
|
|
||||||
self.root.ids.nokeys_text.text = ""
|
self.root.ids.nokeys_text.text = ""
|
||||||
self.message_area_detect()
|
self.message_area_detect()
|
||||||
self.update_message_widgets()
|
self.update_message_widgets()
|
||||||
|
|
||||||
self.root.ids.screen_manager.current = "messages_screen"
|
self.root.ids.screen_manager.current = "messages_screen"
|
||||||
|
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
|
||||||
|
|
||||||
self.sideband.read_conversation(context_dest)
|
self.sideband.read_conversation(context_dest)
|
||||||
|
|
||||||
@ -480,6 +485,7 @@ class SidebandApp(MDApp):
|
|||||||
|
|
||||||
self.root.ids.screen_manager.current = "conversations_screen"
|
self.root.ids.screen_manager.current = "conversations_screen"
|
||||||
self.root.ids.messages_scrollview.active_conversation = None
|
self.root.ids.messages_scrollview.active_conversation = None
|
||||||
|
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
|
||||||
|
|
||||||
def connectivity_status(self, sender):
|
def connectivity_status(self, sender):
|
||||||
hs = dp(22)
|
hs = dp(22)
|
||||||
@ -567,18 +573,12 @@ class SidebandApp(MDApp):
|
|||||||
)
|
)
|
||||||
dialog.d_content = dialog_content
|
dialog.d_content = dialog_content
|
||||||
def dl_close(s):
|
def dl_close(s):
|
||||||
self.lxmf_sync_dialog_open = False
|
self.sideband.setstate("app.flags.lxmf_sync_dialog_open", False)
|
||||||
dialog.dismiss()
|
dialog.dismiss()
|
||||||
self.sideband.cancel_lxmf_sync()
|
self.sideband.cancel_lxmf_sync()
|
||||||
|
|
||||||
# def dl_stop(s):
|
|
||||||
# self.lxmf_sync_dialog_open = False
|
|
||||||
# dialog.dismiss()
|
|
||||||
# self.sideband.cancel_lxmf_sync()
|
|
||||||
|
|
||||||
close_button.bind(on_release=dl_close)
|
close_button.bind(on_release=dl_close)
|
||||||
# stop_button.bind(on_release=dl_stop)
|
self.sideband.setstate("app.flags.lxmf_sync_dialog_open", True)
|
||||||
self.lxmf_sync_dialog_open = True
|
|
||||||
self.sync_dialog = dialog_content
|
self.sync_dialog = dialog_content
|
||||||
dialog.open()
|
dialog.open()
|
||||||
dialog_content.ids.sync_progress.value = self.sideband.get_sync_progress()*100
|
dialog_content.ids.sync_progress.value = self.sideband.get_sync_progress()*100
|
||||||
@ -652,6 +652,7 @@ class SidebandApp(MDApp):
|
|||||||
self.root.ids.screen_manager.transition.direction = "left"
|
self.root.ids.screen_manager.transition.direction = "left"
|
||||||
self.root.ids.screen_manager.current = "information_screen"
|
self.root.ids.screen_manager.current = "information_screen"
|
||||||
self.root.ids.nav_drawer.set_state("closed")
|
self.root.ids.nav_drawer.set_state("closed")
|
||||||
|
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
|
||||||
|
|
||||||
def close_information_action(self, sender=None):
|
def close_information_action(self, sender=None):
|
||||||
self.open_conversations(direction="right")
|
self.open_conversations(direction="right")
|
||||||
@ -743,6 +744,7 @@ class SidebandApp(MDApp):
|
|||||||
|
|
||||||
self.root.ids.screen_manager.current = "settings_screen"
|
self.root.ids.screen_manager.current = "settings_screen"
|
||||||
self.root.ids.nav_drawer.set_state("closed")
|
self.root.ids.nav_drawer.set_state("closed")
|
||||||
|
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
|
||||||
|
|
||||||
def close_settings_action(self, sender=None):
|
def close_settings_action(self, sender=None):
|
||||||
self.open_conversations(direction="right")
|
self.open_conversations(direction="right")
|
||||||
@ -852,6 +854,7 @@ class SidebandApp(MDApp):
|
|||||||
self.root.ids.screen_manager.transition.direction = "left"
|
self.root.ids.screen_manager.transition.direction = "left"
|
||||||
self.root.ids.screen_manager.current = "connectivity_screen"
|
self.root.ids.screen_manager.current = "connectivity_screen"
|
||||||
self.root.ids.nav_drawer.set_state("closed")
|
self.root.ids.nav_drawer.set_state("closed")
|
||||||
|
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
|
||||||
|
|
||||||
|
|
||||||
def close_connectivity_action(self, sender=None):
|
def close_connectivity_action(self, sender=None):
|
||||||
@ -875,6 +878,7 @@ class SidebandApp(MDApp):
|
|||||||
self.root.ids.announces_scrollview.add_widget(self.announces_view.get_widget())
|
self.root.ids.announces_scrollview.add_widget(self.announces_view.get_widget())
|
||||||
|
|
||||||
self.root.ids.screen_manager.current = "announces_screen"
|
self.root.ids.screen_manager.current = "announces_screen"
|
||||||
|
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
|
||||||
|
|
||||||
def close_announces_action(self, sender=None):
|
def close_announces_action(self, sender=None):
|
||||||
self.open_conversations(direction="right")
|
self.open_conversations(direction="right")
|
||||||
@ -900,6 +904,7 @@ class SidebandApp(MDApp):
|
|||||||
self.root.ids.screen_manager.transition.direction = "left"
|
self.root.ids.screen_manager.transition.direction = "left"
|
||||||
self.root.ids.screen_manager.current = "keys_screen"
|
self.root.ids.screen_manager.current = "keys_screen"
|
||||||
self.root.ids.nav_drawer.set_state("closed")
|
self.root.ids.nav_drawer.set_state("closed")
|
||||||
|
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
|
||||||
|
|
||||||
def close_keys_action(self, sender=None):
|
def close_keys_action(self, sender=None):
|
||||||
self.open_conversations(direction="right")
|
self.open_conversations(direction="right")
|
||||||
@ -1031,6 +1036,7 @@ Thank you very much for using Free Communications Systems.
|
|||||||
self.root.ids.screen_manager.transition.direction = "left"
|
self.root.ids.screen_manager.transition.direction = "left"
|
||||||
self.root.ids.screen_manager.current = "guide_screen"
|
self.root.ids.screen_manager.current = "guide_screen"
|
||||||
self.root.ids.nav_drawer.set_state("closed")
|
self.root.ids.nav_drawer.set_state("closed")
|
||||||
|
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
|
||||||
|
|
||||||
|
|
||||||
#################################################
|
#################################################
|
||||||
@ -1049,6 +1055,7 @@ Thank you very much for using Free Communications Systems.
|
|||||||
self.root.ids.screen_manager.transition.direction = "left"
|
self.root.ids.screen_manager.transition.direction = "left"
|
||||||
self.root.ids.screen_manager.current = "map_screen"
|
self.root.ids.screen_manager.current = "map_screen"
|
||||||
self.root.ids.nav_drawer.set_state("closed")
|
self.root.ids.nav_drawer.set_state("closed")
|
||||||
|
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
|
||||||
|
|
||||||
def broadcasts_action(self, sender=None):
|
def broadcasts_action(self, sender=None):
|
||||||
def link_exec(sender=None, event=None):
|
def link_exec(sender=None, event=None):
|
||||||
@ -1062,6 +1069,7 @@ Thank you very much for using Free Communications Systems.
|
|||||||
self.root.ids.screen_manager.transition.direction = "left"
|
self.root.ids.screen_manager.transition.direction = "left"
|
||||||
self.root.ids.screen_manager.current = "broadcasts_screen"
|
self.root.ids.screen_manager.current = "broadcasts_screen"
|
||||||
self.root.ids.nav_drawer.set_state("closed")
|
self.root.ids.nav_drawer.set_state("closed")
|
||||||
|
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -130,20 +130,22 @@ public class PythonService extends Service implements Runnable {
|
|||||||
} else {
|
} else {
|
||||||
// for android 8+ we need to create our own channel
|
// for android 8+ we need to create our own channel
|
||||||
// https://stackoverflow.com/questions/47531742/startforeground-fail-after-upgrade-to-android-8-1
|
// https://stackoverflow.com/questions/47531742/startforeground-fail-after-upgrade-to-android-8-1
|
||||||
String NOTIFICATION_CHANNEL_ID = "org.kivy.p4a"; //TODO: make this configurable
|
String NOTIFICATION_CHANNEL_ID = "io.unsigned.sideband.reticulum";
|
||||||
String channelName = "Background Service"; //TODO: make this configurable
|
String channelName = "Background Service";
|
||||||
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName,
|
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName,
|
||||||
NotificationManager.IMPORTANCE_NONE);
|
NotificationManager.IMPORTANCE_NONE);
|
||||||
|
|
||||||
chan.setLightColor(Color.BLUE);
|
chan.setLightColor(Color.BLUE);
|
||||||
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
|
chan.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
|
||||||
|
chan.setShowBadge(false);
|
||||||
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
manager.createNotificationChannel(chan);
|
manager.createNotificationChannel(chan);
|
||||||
|
|
||||||
Notification.Builder builder = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID);
|
Notification.Builder builder = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID);
|
||||||
builder.setContentTitle("Sideband");
|
builder.setContentTitle("Sideband Active");
|
||||||
builder.setContentText("Reticulum Running");
|
// builder.setContentText("Reticulum Active");
|
||||||
builder.setContentIntent(pIntent);
|
builder.setContentIntent(pIntent);
|
||||||
|
// builder.setOngoing(true);
|
||||||
|
|
||||||
// TODO: Generalise this
|
// TODO: Generalise this
|
||||||
Bitmap icon_bitmap = BitmapFactory.decodeFile("/data/user/0/io.unsigned.sideband/files/app/assets/notification_icon.png");
|
Bitmap icon_bitmap = BitmapFactory.decodeFile("/data/user/0/io.unsigned.sideband/files/app/assets/notification_icon.png");
|
||||||
|
@ -46,7 +46,7 @@ class Notification:
|
|||||||
'''
|
'''
|
||||||
|
|
||||||
def notify(self, title='', message='', app_name='', app_icon='', notification_icon=None,
|
def notify(self, title='', message='', app_name='', app_icon='', notification_icon=None,
|
||||||
timeout=10, ticker='', toast=False, hints={}):
|
timeout=10, ticker='', toast=False, hints={}, context_override=None):
|
||||||
'''
|
'''
|
||||||
Send a notification.
|
Send a notification.
|
||||||
|
|
||||||
@ -84,7 +84,7 @@ class Notification:
|
|||||||
self._notify(
|
self._notify(
|
||||||
title=title, message=message,
|
title=title, message=message,
|
||||||
app_icon=app_icon, app_name=app_name, notification_icon=notification_icon,
|
app_icon=app_icon, app_name=app_name, notification_icon=notification_icon,
|
||||||
timeout=timeout, ticker=ticker, toast=toast, hints=hints
|
timeout=timeout, ticker=ticker, toast=toast, hints=hints, context_override=context_override
|
||||||
)
|
)
|
||||||
|
|
||||||
# private
|
# private
|
||||||
|
@ -180,6 +180,7 @@ class AndroidNotification(Notification):
|
|||||||
)
|
)
|
||||||
icon = kwargs.get('app_icon')
|
icon = kwargs.get('app_icon')
|
||||||
notification_icon = kwargs.get('notification_icon')
|
notification_icon = kwargs.get('notification_icon')
|
||||||
|
context_override = kwargs.get('context_override')
|
||||||
|
|
||||||
# decide whether toast only or proper notification
|
# decide whether toast only or proper notification
|
||||||
if kwargs.get('toast'):
|
if kwargs.get('toast'):
|
||||||
|
@ -9,7 +9,18 @@ Logger.setLevel(LOG_LEVELS["debug"])
|
|||||||
|
|
||||||
if RNS.vendor.platformutils.get_platform() == "android":
|
if RNS.vendor.platformutils.get_platform() == "android":
|
||||||
from jnius import autoclass, cast
|
from jnius import autoclass, cast
|
||||||
|
from android import python_act
|
||||||
Context = autoclass('android.content.Context')
|
Context = autoclass('android.content.Context')
|
||||||
|
Intent = autoclass('android.content.Intent')
|
||||||
|
BitmapFactory = autoclass('android.graphics.BitmapFactory')
|
||||||
|
Icon = autoclass("android.graphics.drawable.Icon")
|
||||||
|
PendingIntent = autoclass('android.app.PendingIntent')
|
||||||
|
AndroidString = autoclass('java.lang.String')
|
||||||
|
NotificationManager = autoclass('android.app.NotificationManager')
|
||||||
|
Context = autoclass('android.content.Context')
|
||||||
|
NotificationBuilder = autoclass('android.app.Notification$Builder')
|
||||||
|
NotificationChannel = autoclass('android.app.NotificationChannel')
|
||||||
|
|
||||||
from sideband.core import SidebandCore
|
from sideband.core import SidebandCore
|
||||||
|
|
||||||
else:
|
else:
|
||||||
@ -20,6 +31,64 @@ class AppProxy():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
class SidebandService():
|
class SidebandService():
|
||||||
|
def android_notification(self, title="", content="", ticker="", group=None, context_id=None):
|
||||||
|
package_name = "io.unsigned.sideband"
|
||||||
|
|
||||||
|
if not self.notification_service:
|
||||||
|
self.notification_service = cast(NotificationManager, self.app_context.getSystemService(
|
||||||
|
Context.NOTIFICATION_SERVICE
|
||||||
|
))
|
||||||
|
|
||||||
|
channel_id = package_name
|
||||||
|
group_id = ""
|
||||||
|
if group != None:
|
||||||
|
channel_id += "."+str(group)
|
||||||
|
group_id += str(group)
|
||||||
|
if context_id != None:
|
||||||
|
channel_id += "."+str(context_id)
|
||||||
|
group_id += "."+str(context_id)
|
||||||
|
|
||||||
|
if not title or title == "":
|
||||||
|
channel_name = "Sideband"
|
||||||
|
else:
|
||||||
|
channel_name = title
|
||||||
|
|
||||||
|
self.notification_channel = NotificationChannel(channel_id, channel_name, NotificationManager.IMPORTANCE_DEFAULT)
|
||||||
|
self.notification_channel.enableVibration(True)
|
||||||
|
self.notification_channel.setShowBadge(True)
|
||||||
|
self.notification_service.createNotificationChannel(self.notification_channel)
|
||||||
|
|
||||||
|
notification = NotificationBuilder(self.app_context, channel_id)
|
||||||
|
notification.setContentTitle(title)
|
||||||
|
notification.setContentText(AndroidString(content))
|
||||||
|
|
||||||
|
# if group != None:
|
||||||
|
# notification.setGroup(group_id)
|
||||||
|
|
||||||
|
if not self.notification_small_icon:
|
||||||
|
path = self.sideband.notification_icon
|
||||||
|
bitmap = BitmapFactory.decodeFile(path)
|
||||||
|
self.notification_small_icon = Icon.createWithBitmap(bitmap)
|
||||||
|
|
||||||
|
notification.setSmallIcon(self.notification_small_icon)
|
||||||
|
|
||||||
|
# large_icon_path = self.sideband.icon
|
||||||
|
# bitmap_icon = BitmapFactory.decodeFile(large_icon_path)
|
||||||
|
# notification.setLargeIcon(bitmap_icon)
|
||||||
|
|
||||||
|
if not self.notification_intent:
|
||||||
|
notification_intent = Intent(self.app_context, python_act)
|
||||||
|
notification_intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
||||||
|
notification_intent.setAction(Intent.ACTION_MAIN)
|
||||||
|
notification_intent.addCategory(Intent.CATEGORY_LAUNCHER)
|
||||||
|
|
||||||
|
self.notification_intent = PendingIntent.getActivity(self.app_context, 0, notification_intent, 0)
|
||||||
|
|
||||||
|
notification.setContentIntent(self.notification_intent)
|
||||||
|
notification.setAutoCancel(True)
|
||||||
|
|
||||||
|
built_notification = notification.build()
|
||||||
|
self.notification_service.notify(0, built_notification)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.argument = environ.get('PYTHON_SERVICE_ARGUMENT', '')
|
self.argument = environ.get('PYTHON_SERVICE_ARGUMENT', '')
|
||||||
@ -34,15 +103,20 @@ class SidebandService():
|
|||||||
self.app_context = None
|
self.app_context = None
|
||||||
self.wifi_manager = None
|
self.wifi_manager = None
|
||||||
|
|
||||||
|
self.notification_service = None
|
||||||
|
self.notification_channel = None
|
||||||
|
self.notification_intent = None
|
||||||
|
self.notification_small_icon = None
|
||||||
|
|
||||||
if RNS.vendor.platformutils.get_platform() == "android":
|
if RNS.vendor.platformutils.get_platform() == "android":
|
||||||
self.android_service = autoclass('org.kivy.android.PythonService').mService
|
self.android_service = autoclass('org.kivy.android.PythonService').mService
|
||||||
self.app_context = self.android_service.getApplication().getApplicationContext()
|
self.app_context = self.android_service.getApplication().getApplicationContext()
|
||||||
self.wifi_manager = self.app_context.getSystemService(Context.WIFI_SERVICE)
|
self.wifi_manager = self.app_context.getSystemService(Context.WIFI_SERVICE)
|
||||||
# The returned instance is an android.net.wifi.WifiManager
|
# The returned instance /\ is an android.net.wifi.WifiManager
|
||||||
|
|
||||||
# TODO: Remove?
|
|
||||||
RNS.log("Sideband background service created, starting core...", RNS.LOG_DEBUG)
|
|
||||||
self.sideband = SidebandCore(self.app_proxy, is_service=True, android_app_dir=self.app_dir)
|
self.sideband = SidebandCore(self.app_proxy, is_service=True, android_app_dir=self.app_dir)
|
||||||
|
self.sideband.service_context = self.android_service
|
||||||
|
self.sideband.owner_service = self
|
||||||
self.sideband.start()
|
self.sideband.start()
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
@ -77,7 +151,3 @@ class SidebandService():
|
|||||||
|
|
||||||
sbs = SidebandService()
|
sbs = SidebandService()
|
||||||
sbs.start()
|
sbs.start()
|
||||||
|
|
||||||
# TODO: Remove
|
|
||||||
print("SBS: Service thread done")
|
|
||||||
RNS.log("Service thread done")
|
|
@ -8,6 +8,9 @@ import sqlite3
|
|||||||
|
|
||||||
import RNS.vendor.umsgpack as msgpack
|
import RNS.vendor.umsgpack as msgpack
|
||||||
|
|
||||||
|
if RNS.vendor.platformutils.get_platform() == "android":
|
||||||
|
from jnius import autoclass, cast
|
||||||
|
|
||||||
class PropagationNodeDetector():
|
class PropagationNodeDetector():
|
||||||
EMITTED_DELTA_GRACE = 300
|
EMITTED_DELTA_GRACE = 300
|
||||||
EMITTED_DELTA_IGNORE = 10
|
EMITTED_DELTA_IGNORE = 10
|
||||||
@ -60,6 +63,8 @@ class SidebandCore():
|
|||||||
|
|
||||||
MAX_ANNOUNCES = 48
|
MAX_ANNOUNCES = 48
|
||||||
|
|
||||||
|
JOB_INTERVAL = 1
|
||||||
|
|
||||||
aspect_filter = "lxmf.delivery"
|
aspect_filter = "lxmf.delivery"
|
||||||
def received_announce(self, destination_hash, announced_identity, app_data):
|
def received_announce(self, destination_hash, announced_identity, app_data):
|
||||||
# Add the announce to the directory announce
|
# Add the announce to the directory announce
|
||||||
@ -75,12 +80,6 @@ class SidebandCore():
|
|||||||
else:
|
else:
|
||||||
self.is_standalone = False
|
self.is_standalone = False
|
||||||
|
|
||||||
if self.is_client:
|
|
||||||
from .serviceproxy import ServiceProxy
|
|
||||||
self.serviceproxy = ServiceProxy(self)
|
|
||||||
else:
|
|
||||||
self.serviceproxy = None
|
|
||||||
|
|
||||||
self.owner_app = owner_app
|
self.owner_app = owner_app
|
||||||
self.reticulum = None
|
self.reticulum = None
|
||||||
|
|
||||||
@ -90,11 +89,18 @@ class SidebandCore():
|
|||||||
if RNS.vendor.platformutils.get_platform() == "android":
|
if RNS.vendor.platformutils.get_platform() == "android":
|
||||||
self.app_dir = android_app_dir+"/io.unsigned.sideband/files/"
|
self.app_dir = android_app_dir+"/io.unsigned.sideband/files/"
|
||||||
self.rns_configdir = self.app_dir+"/app_storage/reticulum"
|
self.rns_configdir = self.app_dir+"/app_storage/reticulum"
|
||||||
|
self.asset_dir = self.app_dir+"/app/assets"
|
||||||
|
else:
|
||||||
|
self.asset_dir = plyer.storagepath.get_application_dir()+"/sbapp/assets"
|
||||||
|
|
||||||
|
self.icon = self.asset_dir+"/icon.png"
|
||||||
|
self.icon_48 = self.asset_dir+"/icon_48.png"
|
||||||
|
self.icon_32 = self.asset_dir+"/icon_32.png"
|
||||||
|
self.notification_icon = self.asset_dir+"/notification_icon.png"
|
||||||
|
|
||||||
if not os.path.isdir(self.app_dir+"/app_storage"):
|
if not os.path.isdir(self.app_dir+"/app_storage"):
|
||||||
os.makedirs(self.app_dir+"/app_storage")
|
os.makedirs(self.app_dir+"/app_storage")
|
||||||
|
|
||||||
self.asset_dir = self.app_dir+"/app/assets"
|
|
||||||
self.config_path = self.app_dir+"/app_storage/sideband_config"
|
self.config_path = self.app_dir+"/app_storage/sideband_config"
|
||||||
self.identity_path = self.app_dir+"/app_storage/primary_identity"
|
self.identity_path = self.app_dir+"/app_storage/primary_identity"
|
||||||
self.db_path = self.app_dir+"/app_storage/sideband.db"
|
self.db_path = self.app_dir+"/app_storage/sideband.db"
|
||||||
@ -195,6 +201,9 @@ class SidebandCore():
|
|||||||
|
|
||||||
if not os.path.isfile(self.db_path):
|
if not os.path.isfile(self.db_path):
|
||||||
self.__db_init()
|
self.__db_init()
|
||||||
|
else:
|
||||||
|
self._db_initstate()
|
||||||
|
self._db_initpersistent()
|
||||||
|
|
||||||
|
|
||||||
def __save_config(self):
|
def __save_config(self):
|
||||||
@ -222,11 +231,32 @@ class SidebandCore():
|
|||||||
RNS.log("Error while setting LXMF propagation node: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Error while setting LXMF propagation node: "+str(e), RNS.LOG_ERROR)
|
||||||
|
|
||||||
|
|
||||||
|
def notify(self, title, content, group=None, context_id=None):
|
||||||
|
notifications_enabled = True
|
||||||
|
|
||||||
|
if notifications_enabled:
|
||||||
|
if RNS.vendor.platformutils.get_platform() == "android":
|
||||||
|
if self.getpersistent("permissions.notifications"):
|
||||||
|
notifications_permitted = True
|
||||||
|
else:
|
||||||
|
notifications_permitted = False
|
||||||
|
else:
|
||||||
|
notifications_permitted = True
|
||||||
|
|
||||||
|
if notifications_permitted:
|
||||||
|
if RNS.vendor.platformutils.get_platform() == "android":
|
||||||
|
if self.is_service:
|
||||||
|
self.owner_service.android_notification(title, content, group=group, context_id=context_id)
|
||||||
|
else:
|
||||||
|
plyer.notification.notify(title, content, notification_icon=self.notification_icon, context_override=None)
|
||||||
|
else:
|
||||||
|
plyer.notification.notify(title, content, app_icon=self.icon_32)
|
||||||
|
|
||||||
def log_announce(self, dest, app_data, dest_type):
|
def log_announce(self, dest, app_data, dest_type):
|
||||||
try:
|
try:
|
||||||
RNS.log("Received "+str(dest_type)+" announce for "+RNS.prettyhexrep(dest)+" with data: "+app_data.decode("utf-8"))
|
RNS.log("Received "+str(dest_type)+" announce for "+RNS.prettyhexrep(dest)+" with data: "+app_data.decode("utf-8"))
|
||||||
self._db_save_announce(dest, app_data, dest_type)
|
self._db_save_announce(dest, app_data, dest_type)
|
||||||
self.owner_app.flag_new_announces = True
|
self.setstate("app.flags.new_announces", True)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
RNS.log("Exception while decoding LXMF destination announce data:"+str(e))
|
RNS.log("Exception while decoding LXMF destination announce data:"+str(e))
|
||||||
@ -345,6 +375,27 @@ class SidebandCore():
|
|||||||
else:
|
else:
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def gui_foreground(self):
|
||||||
|
return self._db_getstate("app.foreground")
|
||||||
|
|
||||||
|
def gui_display(self):
|
||||||
|
return self._db_getstate("app.displaying")
|
||||||
|
|
||||||
|
def gui_conversation(self):
|
||||||
|
return self._db_getstate("app.active_conversation")
|
||||||
|
|
||||||
|
def setstate(self, prop, val):
|
||||||
|
self._db_setstate(prop, val)
|
||||||
|
|
||||||
|
def getstate(self, prop):
|
||||||
|
return self._db_getstate(prop)
|
||||||
|
|
||||||
|
def setpersistent(self, prop, val):
|
||||||
|
self._db_setpersistent(prop, val)
|
||||||
|
|
||||||
|
def getpersistent(self, prop):
|
||||||
|
return self._db_getpersistent(prop)
|
||||||
|
|
||||||
def __event_conversations_changed(self):
|
def __event_conversations_changed(self):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -364,6 +415,100 @@ class SidebandCore():
|
|||||||
dbc.execute("DROP TABLE IF EXISTS announce")
|
dbc.execute("DROP TABLE IF EXISTS announce")
|
||||||
dbc.execute("CREATE TABLE announce (id PRIMARY KEY, received INTEGER, source BLOB, data BLOB, dest_type BLOB)")
|
dbc.execute("CREATE TABLE announce (id PRIMARY KEY, received INTEGER, source BLOB, data BLOB, dest_type BLOB)")
|
||||||
|
|
||||||
|
dbc.execute("DROP TABLE IF EXISTS state")
|
||||||
|
dbc.execute("CREATE TABLE state (property BLOB PRIMARY KEY, value BLOB)")
|
||||||
|
|
||||||
|
dbc.execute("DROP TABLE IF EXISTS persistent")
|
||||||
|
dbc.execute("CREATE TABLE persistent (property BLOB PRIMARY KEY, value BLOB)")
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
def _db_initstate(self):
|
||||||
|
db = sqlite3.connect(self.db_path)
|
||||||
|
dbc = db.cursor()
|
||||||
|
|
||||||
|
dbc.execute("DROP TABLE IF EXISTS state")
|
||||||
|
dbc.execute("CREATE TABLE state (property BLOB PRIMARY KEY, value BLOB)")
|
||||||
|
self._db_setstate("database_ready", True)
|
||||||
|
|
||||||
|
def _db_getstate(self, prop):
|
||||||
|
db = sqlite3.connect(self.db_path)
|
||||||
|
dbc = db.cursor()
|
||||||
|
|
||||||
|
query = "select * from state where property=:uprop"
|
||||||
|
dbc.execute(query, {"uprop": prop.encode("utf-8")})
|
||||||
|
result = dbc.fetchall()
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
if len(result) < 1:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
entry = result[0]
|
||||||
|
val = msgpack.unpackb(entry[1])
|
||||||
|
return val
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log("Could not unpack state value from database for property \""+str(prop)+"\". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _db_setstate(self, prop, val):
|
||||||
|
db = sqlite3.connect(self.db_path)
|
||||||
|
dbc = db.cursor()
|
||||||
|
uprop = prop.encode("utf-8")
|
||||||
|
bval = msgpack.packb(val)
|
||||||
|
|
||||||
|
if self._db_getstate(prop) == None:
|
||||||
|
query = "INSERT INTO state (property, value) values (?, ?)"
|
||||||
|
data = (uprop, bval)
|
||||||
|
dbc.execute(query, data)
|
||||||
|
else:
|
||||||
|
query = "UPDATE state set value=:bval where property=:uprop;"
|
||||||
|
dbc.execute(query, {"bval": bval, "uprop": uprop})
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
def _db_initpersistent(self):
|
||||||
|
db = sqlite3.connect(self.db_path)
|
||||||
|
dbc = db.cursor()
|
||||||
|
|
||||||
|
dbc.execute("CREATE TABLE IF NOT EXISTS persistent (property BLOB PRIMARY KEY, value BLOB)")
|
||||||
|
|
||||||
|
def _db_getpersistent(self, prop):
|
||||||
|
db = sqlite3.connect(self.db_path)
|
||||||
|
dbc = db.cursor()
|
||||||
|
|
||||||
|
query = "select * from persistent where property=:uprop"
|
||||||
|
dbc.execute(query, {"uprop": prop.encode("utf-8")})
|
||||||
|
result = dbc.fetchall()
|
||||||
|
db.close()
|
||||||
|
|
||||||
|
if len(result) < 1:
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
entry = result[0]
|
||||||
|
val = msgpack.unpackb(entry[1])
|
||||||
|
return val
|
||||||
|
except Exception as e:
|
||||||
|
RNS.log("Could not unpack persistent value from database for property \""+str(prop)+"\". The contained exception was: "+str(e), RNS.LOG_ERROR)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _db_setpersistent(self, prop, val):
|
||||||
|
db = sqlite3.connect(self.db_path)
|
||||||
|
dbc = db.cursor()
|
||||||
|
uprop = prop.encode("utf-8")
|
||||||
|
bval = msgpack.packb(val)
|
||||||
|
|
||||||
|
if self._db_getpersistent(prop) == None:
|
||||||
|
query = "INSERT INTO persistent (property, value) values (?, ?)"
|
||||||
|
data = (uprop, bval)
|
||||||
|
dbc.execute(query, data)
|
||||||
|
else:
|
||||||
|
query = "UPDATE persistent set value=:bval where property=:uprop;"
|
||||||
|
dbc.execute(query, {"bval": bval, "uprop": uprop})
|
||||||
|
|
||||||
db.commit()
|
db.commit()
|
||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
@ -687,7 +832,11 @@ class SidebandCore():
|
|||||||
db.close()
|
db.close()
|
||||||
|
|
||||||
def lxmf_announce(self):
|
def lxmf_announce(self):
|
||||||
self.lxmf_destination.announce()
|
if self.is_standalone or self.is_service:
|
||||||
|
self.lxmf_destination.announce()
|
||||||
|
self.setstate("wants.announce", False)
|
||||||
|
else:
|
||||||
|
self.setstate("wants.announce", True)
|
||||||
|
|
||||||
def is_known(self, dest_hash):
|
def is_known(self, dest_hash):
|
||||||
try:
|
try:
|
||||||
@ -710,10 +859,20 @@ class SidebandCore():
|
|||||||
RNS.log("Error while querying for key: "+str(e), RNS.LOG_ERROR)
|
RNS.log("Error while querying for key: "+str(e), RNS.LOG_ERROR)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def _service_jobs(self):
|
||||||
|
if self.is_service:
|
||||||
|
while True:
|
||||||
|
time.sleep(SidebandCore.JOB_INTERVAL)
|
||||||
|
if self.getstate("wants.announce"):
|
||||||
|
self.lxmf_announce()
|
||||||
|
|
||||||
def __start_jobs_deferred(self):
|
def __start_jobs_deferred(self):
|
||||||
if self.config["start_announce"]:
|
if self.config["start_announce"]:
|
||||||
# TODO: (Service) Handle this in service
|
self.lxmf_announce()
|
||||||
self.lxmf_destination.announce()
|
|
||||||
|
if self.is_service:
|
||||||
|
self.service_thread = threading.Thread(target=self._service_jobs, daemon=True)
|
||||||
|
self.service_thread.start()
|
||||||
|
|
||||||
def __start_jobs_immediate(self):
|
def __start_jobs_immediate(self):
|
||||||
# TODO: Reset loglevel
|
# TODO: Reset loglevel
|
||||||
@ -828,19 +987,14 @@ class SidebandCore():
|
|||||||
RNS.log("Error while adding I2P Interface. The contained exception was: "+str(e))
|
RNS.log("Error while adding I2P Interface. The contained exception was: "+str(e))
|
||||||
self.interface_i2p = None
|
self.interface_i2p = None
|
||||||
|
|
||||||
if self.is_service or self.is_standalone:
|
RNS.log("Reticulum started, activating LXMF...")
|
||||||
RNS.log("Reticulum started, activating LXMF...")
|
self.message_router = LXMF.LXMRouter(identity = self.identity, storagepath = self.lxmf_storage, autopeer = True)
|
||||||
self.message_router = LXMF.LXMRouter(identity = self.identity, storagepath = self.lxmf_storage, autopeer = True)
|
self.message_router.register_delivery_callback(self.lxmf_delivery)
|
||||||
self.message_router.register_delivery_callback(self.lxmf_delivery)
|
|
||||||
|
|
||||||
self.lxmf_destination = self.message_router.register_delivery_identity(self.identity, display_name=self.config["display_name"])
|
self.lxmf_destination = self.message_router.register_delivery_identity(self.identity, display_name=self.config["display_name"])
|
||||||
self.lxmf_destination.set_default_app_data(self.get_display_name_bytes)
|
self.lxmf_destination.set_default_app_data(self.get_display_name_bytes)
|
||||||
|
|
||||||
self.rns_dir = RNS.Reticulum.configdir
|
self.rns_dir = RNS.Reticulum.configdir
|
||||||
|
|
||||||
else:
|
|
||||||
self.message_router = self.serviceproxy
|
|
||||||
self.lxmf_destination = self.serviceproxy
|
|
||||||
|
|
||||||
if self.config["lxmf_propagation_node"] != None and self.config["lxmf_propagation_node"] != "":
|
if self.config["lxmf_propagation_node"] != None and self.config["lxmf_propagation_node"] != "":
|
||||||
self.set_active_propagation_node(self.config["lxmf_propagation_node"])
|
self.set_active_propagation_node(self.config["lxmf_propagation_node"])
|
||||||
@ -941,23 +1095,21 @@ class SidebandCore():
|
|||||||
|
|
||||||
if self._db_conversation(context_dest) == None:
|
if self._db_conversation(context_dest) == None:
|
||||||
self._db_create_conversation(context_dest)
|
self._db_create_conversation(context_dest)
|
||||||
self.owner_app.flag_new_conversations = True
|
self.setstate("app.flags.new_conversations", True)
|
||||||
|
|
||||||
if self.owner_app.root.ids.screen_manager.current == "messages_screen":
|
if self.gui_display() == "messages_screen":
|
||||||
if self.owner_app.root.ids.messages_scrollview.active_conversation != context_dest:
|
if self.gui_conversation() != context_dest:
|
||||||
self.unread_conversation(context_dest)
|
self.unread_conversation(context_dest)
|
||||||
self.owner_app.flag_unread_conversations = True
|
self.setstate("app.flags.unread_conversations", True)
|
||||||
else:
|
else:
|
||||||
if self.owner_app.is_in_foreground():
|
if self.gui_foreground():
|
||||||
should_notify = False
|
should_notify = False
|
||||||
else:
|
else:
|
||||||
self.unread_conversation(context_dest)
|
self.unread_conversation(context_dest)
|
||||||
self.owner_app.flag_unread_conversations = True
|
self.setstate("app.flags.unread_conversations", True)
|
||||||
|
|
||||||
try:
|
if self.is_client:
|
||||||
self.owner_app.conversation_update(context_dest)
|
should_notify = False
|
||||||
except Exception as e:
|
|
||||||
RNS.log("Error in conversation update callback: "+str(e))
|
|
||||||
|
|
||||||
if should_notify:
|
if should_notify:
|
||||||
nlen = 128
|
nlen = 128
|
||||||
@ -966,7 +1118,7 @@ class SidebandCore():
|
|||||||
if len(text) > nlen:
|
if len(text) > nlen:
|
||||||
text += "..."
|
text += "..."
|
||||||
|
|
||||||
self.owner_app.notify(title="Message from "+self.peer_display_name(context_dest), content=notification_content)
|
self.notify(title=self.peer_display_name(context_dest), content=notification_content, group="LXM", context_id=RNS.hexrep(context_dest, delimit=False))
|
||||||
|
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
@ -976,6 +1128,8 @@ class SidebandCore():
|
|||||||
thread = threading.Thread(target=self.__start_jobs_deferred)
|
thread = threading.Thread(target=self.__start_jobs_deferred)
|
||||||
thread.setDaemon(True)
|
thread.setDaemon(True)
|
||||||
thread.start()
|
thread.start()
|
||||||
|
|
||||||
|
self._db_setstate("core.started", True)
|
||||||
RNS.log("Sideband Core "+str(self)+" started")
|
RNS.log("Sideband Core "+str(self)+" started")
|
||||||
|
|
||||||
def request_lxmf_sync(self, limit = None):
|
def request_lxmf_sync(self, limit = None):
|
||||||
|
@ -39,10 +39,8 @@ class Announces():
|
|||||||
def update(self):
|
def update(self):
|
||||||
self.clear_list()
|
self.clear_list()
|
||||||
self.announces = self.app.sideband.list_announces()
|
self.announces = self.app.sideband.list_announces()
|
||||||
|
|
||||||
self.update_widget()
|
self.update_widget()
|
||||||
|
self.app.sideband.setstate("app.flags.new_announces", False)
|
||||||
self.app.flag_new_announces = False
|
|
||||||
|
|
||||||
def update_widget(self):
|
def update_widget(self):
|
||||||
if self.list == None:
|
if self.list == None:
|
||||||
|
@ -45,14 +45,14 @@ class Conversations():
|
|||||||
self.added_item_dests = []
|
self.added_item_dests = []
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
if self.app.flag_unread_conversations:
|
if self.app.sideband.getstate("app.flags.unread_conversations"):
|
||||||
self.clear_list()
|
self.clear_list()
|
||||||
|
|
||||||
self.context_dests = self.app.sideband.list_conversations()
|
self.context_dests = self.app.sideband.list_conversations()
|
||||||
self.update_widget()
|
self.update_widget()
|
||||||
|
|
||||||
self.app.flag_new_conversations = False
|
self.app.sideband.setstate("app.flags.unread_conversations", False)
|
||||||
self.app.flag_unread_conversations = False
|
self.app.sideband.setstate("app.flags.new_conversations", False)
|
||||||
|
|
||||||
def update_widget(self):
|
def update_widget(self):
|
||||||
if self.list == None:
|
if self.list == None:
|
||||||
|
Loading…
Reference in New Issue
Block a user