Added service split for Android and notifications on Android and Linux

This commit is contained in:
Mark Qvist 2022-10-02 01:14:29 +02:00
parent e58c8a96be
commit 7ee0171ec7
8 changed files with 336 additions and 103 deletions

View File

@ -72,8 +72,6 @@ class SidebandApp(MDApp):
self.android_service = None
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":
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.flag_new_conversations = False
self.flag_unread_conversations = False
self.flag_new_announces = False
self.lxmf_sync_dialog_open = False
self.sync_dialog = None
Window.softinput_mode = "below_target"
self.icon = self.sideband.asset_dir+"/icon.png"
self.notification_icon = self.sideband.asset_dir+"/notification_icon.png"
self.check_permissions()
def start_core(self, dt):
self.start_service()
self.open_conversations()
Clock.schedule_interval(self.jobs, 1)
def dismiss_splash(dt):
@ -105,8 +99,15 @@ class SidebandApp(MDApp):
if RNS.vendor.platformutils.get_platform() == "android":
Clock.schedule_once(dismiss_splash, 0)
if self.sideband.first_run:
self.guide_action()
self.sideband.setstate("app.loaded", True)
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
@ -125,8 +126,6 @@ class SidebandApp(MDApp):
time.sleep(7)
# Start local core instance
# TODO: Remove log
RNS.log("Starting local core")
self.sideband.start()
else:
@ -150,14 +149,20 @@ class SidebandApp(MDApp):
mActivity.startActivity(shareIntent)
def on_pause(self):
self.sideband.setstate("app.running", True)
self.sideband.setstate("app.foreground", False)
self.app_state = SidebandApp.PAUSED
self.sideband.should_persist_data()
return True
def on_resume(self):
self.sideband.setstate("app.running", True)
self.sideband.setstate("app.foreground", True)
self.app_state = SidebandApp.ACTIVE
def on_stop(self):
self.sideband.setstate("app.running", False)
self.sideband.setstate("app.foreground", False)
self.app_state = SidebandApp.STOPPING
def is_in_foreground(self):
@ -166,25 +171,27 @@ class SidebandApp(MDApp):
else:
return False
def notify(self, title, content):
notifications_enabled = True
if notifications_enabled:
if RNS.vendor.platformutils.get_platform() == "android":
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"])
def check_permissions(self):
if RNS.vendor.platformutils.get_platform() == "android":
if check_permission("android.permission.POST_NOTIFICATIONS"):
RNS.log("Have notification permissions")
self.sideband.setpersistent("permissions.notifications", True)
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:
if RNS.vendor.platformutils.get_platform() == "android":
plyer.notification.notify(title, content, notification_icon=self.notification_icon)
else:
plyer.notification.notify(title, content)
def request_permissions(self):
self.request_notifications_permission()
def request_notifications_permission(self):
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):
FONT_PATH = self.sideband.asset_dir+"/fonts"
@ -201,22 +208,22 @@ class SidebandApp(MDApp):
self.message_area_detect()
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")
if self.conversations_view != None:
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")
if self.conversations_view != None:
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_status.text = self.sideband.get_sync_status()
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")
if self.announces_view != None:
self.announces_view.update()
@ -304,6 +311,9 @@ class SidebandApp(MDApp):
self.root.ids.nav_drawer.set_state("closed")
self.sideband.should_persist_data()
self.sideband.setstate("app.running", False)
self.sideband.setstate("app.foreground", False)
def final_exit(dt):
RNS.exit()
MDApp.get_running_app().stop()
@ -328,13 +338,6 @@ class SidebandApp(MDApp):
yes_button.bind(on_release=dl_yes)
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 #
@ -372,13 +375,15 @@ class SidebandApp(MDApp):
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_scrollview.active_conversation = context_dest
self.sideband.setstate("app.active_conversation", context_dest)
self.root.ids.nokeys_text.text = ""
self.message_area_detect()
self.update_message_widgets()
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)
def close_messages_action(self, sender=None):
@ -480,6 +485,7 @@ class SidebandApp(MDApp):
self.root.ids.screen_manager.current = "conversations_screen"
self.root.ids.messages_scrollview.active_conversation = None
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)
def connectivity_status(self, sender):
hs = dp(22)
@ -567,18 +573,12 @@ class SidebandApp(MDApp):
)
dialog.d_content = dialog_content
def dl_close(s):
self.lxmf_sync_dialog_open = False
self.sideband.setstate("app.flags.lxmf_sync_dialog_open", False)
dialog.dismiss()
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)
# stop_button.bind(on_release=dl_stop)
self.lxmf_sync_dialog_open = True
self.sideband.setstate("app.flags.lxmf_sync_dialog_open", True)
self.sync_dialog = dialog_content
dialog.open()
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.current = "information_screen"
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):
self.open_conversations(direction="right")
@ -743,6 +744,7 @@ class SidebandApp(MDApp):
self.root.ids.screen_manager.current = "settings_screen"
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):
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.current = "connectivity_screen"
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):
@ -875,6 +878,7 @@ class SidebandApp(MDApp):
self.root.ids.announces_scrollview.add_widget(self.announces_view.get_widget())
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):
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.current = "keys_screen"
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):
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.current = "guide_screen"
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.current = "map_screen"
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 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.current = "broadcasts_screen"
self.root.ids.nav_drawer.set_state("closed")
self.sideband.setstate("app.displaying", self.root.ids.screen_manager.current)

View File

@ -130,20 +130,22 @@ public class PythonService extends Service implements Runnable {
} else {
// for android 8+ we need to create our own channel
// 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 channelName = "Background Service"; //TODO: make this configurable
String NOTIFICATION_CHANNEL_ID = "io.unsigned.sideband.reticulum";
String channelName = "Background Service";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName,
NotificationManager.IMPORTANCE_NONE);
chan.setLightColor(Color.BLUE);
chan.setLockscreenVisibility(Notification.VISIBILITY_PRIVATE);
chan.setLockscreenVisibility(Notification.VISIBILITY_SECRET);
chan.setShowBadge(false);
NotificationManager manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
manager.createNotificationChannel(chan);
Notification.Builder builder = new Notification.Builder(context, NOTIFICATION_CHANNEL_ID);
builder.setContentTitle("Sideband");
builder.setContentText("Reticulum Running");
builder.setContentTitle("Sideband Active");
// builder.setContentText("Reticulum Active");
builder.setContentIntent(pIntent);
// builder.setOngoing(true);
// TODO: Generalise this
Bitmap icon_bitmap = BitmapFactory.decodeFile("/data/user/0/io.unsigned.sideband/files/app/assets/notification_icon.png");

View File

@ -46,7 +46,7 @@ class Notification:
'''
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.
@ -84,7 +84,7 @@ class Notification:
self._notify(
title=title, message=message,
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

View File

@ -180,6 +180,7 @@ class AndroidNotification(Notification):
)
icon = kwargs.get('app_icon')
notification_icon = kwargs.get('notification_icon')
context_override = kwargs.get('context_override')
# decide whether toast only or proper notification
if kwargs.get('toast'):

View File

@ -9,7 +9,18 @@ Logger.setLevel(LOG_LEVELS["debug"])
if RNS.vendor.platformutils.get_platform() == "android":
from jnius import autoclass, cast
from android import python_act
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
else:
@ -20,6 +31,64 @@ class AppProxy():
pass
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):
self.argument = environ.get('PYTHON_SERVICE_ARGUMENT', '')
@ -34,15 +103,20 @@ class SidebandService():
self.app_context = 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":
self.android_service = autoclass('org.kivy.android.PythonService').mService
self.app_context = self.android_service.getApplication().getApplicationContext()
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.service_context = self.android_service
self.sideband.owner_service = self
self.sideband.start()
def start(self):
@ -76,8 +150,4 @@ class SidebandService():
self.release_locks()
sbs = SidebandService()
sbs.start()
# TODO: Remove
print("SBS: Service thread done")
RNS.log("Service thread done")
sbs.start()

View File

@ -8,6 +8,9 @@ import sqlite3
import RNS.vendor.umsgpack as msgpack
if RNS.vendor.platformutils.get_platform() == "android":
from jnius import autoclass, cast
class PropagationNodeDetector():
EMITTED_DELTA_GRACE = 300
EMITTED_DELTA_IGNORE = 10
@ -60,6 +63,8 @@ class SidebandCore():
MAX_ANNOUNCES = 48
JOB_INTERVAL = 1
aspect_filter = "lxmf.delivery"
def received_announce(self, destination_hash, announced_identity, app_data):
# Add the announce to the directory announce
@ -75,12 +80,6 @@ class SidebandCore():
else:
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.reticulum = None
@ -90,16 +89,23 @@ class SidebandCore():
if RNS.vendor.platformutils.get_platform() == "android":
self.app_dir = android_app_dir+"/io.unsigned.sideband/files/"
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"):
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.identity_path = self.app_dir+"/app_storage/primary_identity"
self.db_path = self.app_dir+"/app_storage/sideband.db"
self.lxmf_storage = self.app_dir+"/app_storage/"
self.first_run = True
try:
@ -195,6 +201,9 @@ class SidebandCore():
if not os.path.isfile(self.db_path):
self.__db_init()
else:
self._db_initstate()
self._db_initpersistent()
def __save_config(self):
@ -222,11 +231,32 @@ class SidebandCore():
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):
try:
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.owner_app.flag_new_announces = True
self.setstate("app.flags.new_announces", True)
except Exception as e:
RNS.log("Exception while decoding LXMF destination announce data:"+str(e))
@ -345,6 +375,27 @@ class SidebandCore():
else:
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):
pass
@ -364,6 +415,100 @@ class SidebandCore():
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("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.close()
@ -687,7 +832,11 @@ class SidebandCore():
db.close()
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):
try:
@ -710,11 +859,21 @@ class SidebandCore():
RNS.log("Error while querying for key: "+str(e), RNS.LOG_ERROR)
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):
if self.config["start_announce"]:
# TODO: (Service) Handle this in service
self.lxmf_destination.announce()
self.lxmf_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):
# TODO: Reset loglevel
self.reticulum = RNS.Reticulum(configdir=self.rns_configdir, loglevel=7)
@ -828,19 +987,14 @@ class SidebandCore():
RNS.log("Error while adding I2P Interface. The contained exception was: "+str(e))
self.interface_i2p = None
if self.is_service or self.is_standalone:
RNS.log("Reticulum started, activating LXMF...")
self.message_router = LXMF.LXMRouter(identity = self.identity, storagepath = self.lxmf_storage, autopeer = True)
self.message_router.register_delivery_callback(self.lxmf_delivery)
RNS.log("Reticulum started, activating LXMF...")
self.message_router = LXMF.LXMRouter(identity = self.identity, storagepath = self.lxmf_storage, autopeer = True)
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.set_default_app_data(self.get_display_name_bytes)
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.rns_dir = RNS.Reticulum.configdir
else:
self.message_router = self.serviceproxy
self.lxmf_destination = self.serviceproxy
self.rns_dir = RNS.Reticulum.configdir
if self.config["lxmf_propagation_node"] != None and 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:
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.owner_app.root.ids.messages_scrollview.active_conversation != context_dest:
if self.gui_display() == "messages_screen":
if self.gui_conversation() != context_dest:
self.unread_conversation(context_dest)
self.owner_app.flag_unread_conversations = True
self.setstate("app.flags.unread_conversations", True)
else:
if self.owner_app.is_in_foreground():
if self.gui_foreground():
should_notify = False
else:
self.unread_conversation(context_dest)
self.owner_app.flag_unread_conversations = True
self.setstate("app.flags.unread_conversations", True)
try:
self.owner_app.conversation_update(context_dest)
except Exception as e:
RNS.log("Error in conversation update callback: "+str(e))
if self.is_client:
should_notify = False
if should_notify:
nlen = 128
@ -966,7 +1118,7 @@ class SidebandCore():
if len(text) > nlen:
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):
@ -976,6 +1128,8 @@ class SidebandCore():
thread = threading.Thread(target=self.__start_jobs_deferred)
thread.setDaemon(True)
thread.start()
self._db_setstate("core.started", True)
RNS.log("Sideband Core "+str(self)+" started")
def request_lxmf_sync(self, limit = None):

View File

@ -39,10 +39,8 @@ class Announces():
def update(self):
self.clear_list()
self.announces = self.app.sideband.list_announces()
self.update_widget()
self.app.flag_new_announces = False
self.app.sideband.setstate("app.flags.new_announces", False)
def update_widget(self):
if self.list == None:

View File

@ -45,14 +45,14 @@ class Conversations():
self.added_item_dests = []
def update(self):
if self.app.flag_unread_conversations:
if self.app.sideband.getstate("app.flags.unread_conversations"):
self.clear_list()
self.context_dests = self.app.sideband.list_conversations()
self.update_widget()
self.app.flag_new_conversations = False
self.app.flag_unread_conversations = False
self.app.sideband.setstate("app.flags.unread_conversations", False)
self.app.sideband.setstate("app.flags.new_conversations", False)
def update_widget(self):
if self.list == None: