Added objects view. Added ability to display icon styles from everyone.

This commit is contained in:
Mark Qvist 2024-05-31 23:35:42 +02:00
parent d72f74699d
commit 132e02685b
5 changed files with 227 additions and 33 deletions

View File

@ -199,6 +199,8 @@ class SidebandApp(MDApp):
self.dark_theme_text_color = dark_theme_text_color
self.conversations_view = None
self.include_conversations = True
self.include_objects = False
self.messages_view = None
self.map = None
self.map_layer = None
@ -1158,10 +1160,15 @@ class SidebandApp(MDApp):
def open_conversation(self, context_dest, direction="left"):
self.outbound_mode_paper = False
self.outbound_mode_command = False
if self.sideband.config["propagation_by_default"]:
self.outbound_mode_propagation = True
self.outbound_mode_propagation = False
if self.include_objects and not self.include_conversations:
if self.sideband.config["propagation_by_default"]:
self.outbound_mode_propagation = True
else:
self.outbound_mode_command = True
else:
self.outbound_mode_propagation = False
if self.sideband.config["propagation_by_default"]:
self.outbound_mode_propagation = True
self.root.ids.screen_manager.transition.direction = direction
self.messages_view = Messages(self, context_dest)
@ -1570,6 +1577,28 @@ class SidebandApp(MDApp):
### Conversations screen
######################################
def conversations_action(self, sender=None, direction="left", no_transition=False):
if self.include_objects:
self.include_conversations = True
self.include_objects = False
self.conversations_view.update()
if no_transition:
self.root.ids.screen_manager.transition = self.no_transition
else:
self.root.ids.screen_manager.transition = self.slide_transition
self.root.ids.screen_manager.transition.direction = direction
self.open_conversations(direction=direction)
if no_transition:
self.root.ids.screen_manager.transition = self.slide_transition
def objects_action(self, sender=None, direction="left", no_transition=False):
if self.include_conversations:
self.include_conversations = False
self.include_objects = True
self.conversations_view.update()
if no_transition:
self.root.ids.screen_manager.transition = self.no_transition
else:
@ -2016,8 +2045,6 @@ class SidebandApp(MDApp):
if sender != self.settings_screen.ids.settings_lang_hebrew:
self.settings_screen.ids.settings_lang_hebrew.active = False
RNS.log("Sender: "+str(sender))
if self.settings_screen.ids.settings_lang_default.active:
self.sideband.config["input_language"] = None
self.settings_screen.ids.settings_display_name.font_name = ""
@ -2059,6 +2086,11 @@ class SidebandApp(MDApp):
self.sideband.save_configuration()
self.sideband.setstate("wants.viewupdate.conversations", True)
def save_display_style_from_trusted_only(sender=None, event=None):
self.sideband.config["display_style_from_all"] = not self.settings_screen.ids.display_style_from_trusted_only.active
self.sideband.save_configuration()
self.sideband.setstate("wants.viewupdate.conversations", True)
def save_advanced_stats(sender=None, event=None):
self.sideband.config["advanced_stats"] = self.settings_screen.ids.settings_advanced_statistics.active
self.sideband.save_configuration()
@ -2175,6 +2207,9 @@ class SidebandApp(MDApp):
self.settings_screen.ids.display_style_in_contact_list.active = self.sideband.config["display_style_in_contact_list"]
self.settings_screen.ids.display_style_in_contact_list.bind(active=save_display_style_in_contact_list)
self.settings_screen.ids.display_style_from_trusted_only.active = not self.sideband.config["display_style_from_all"]
self.settings_screen.ids.display_style_from_trusted_only.bind(active=save_display_style_from_trusted_only)
self.settings_screen.ids.settings_advanced_statistics.active = self.sideband.config["advanced_stats"]
self.settings_screen.ids.settings_advanced_statistics.bind(active=save_advanced_stats)
@ -4629,22 +4664,22 @@ class SidebandApp(MDApp):
def close_sub_map_action(self, sender=None):
self.map_action(direction="right")
def object_details_action(self, sender=None, from_conv=False, from_telemetry=False, source_dest=None, direction="left"):
def object_details_action(self, sender=None, from_conv=False, from_objects=False, from_telemetry=False, source_dest=None, direction="left"):
if self.root.ids.screen_manager.has_screen("object_details_screen"):
self.object_details_open(sender=sender, from_conv=from_conv, from_telemetry=from_telemetry, source_dest=source_dest, direction=direction)
self.object_details_open(sender=sender, from_conv=from_conv, from_objects=from_objects, from_telemetry=from_telemetry, source_dest=source_dest, direction=direction)
else:
self.loader_action(direction=direction)
def final(dt):
self.object_details_init()
def o(dt):
self.object_details_open(sender=sender, from_conv=from_conv, from_telemetry=from_telemetry, source_dest=source_dest, no_transition=True)
self.object_details_open(sender=sender, from_conv=from_conv, from_objects=from_objects, from_telemetry=from_telemetry, source_dest=source_dest, no_transition=True)
Clock.schedule_once(o, ll_ot)
Clock.schedule_once(final, ll_ft)
def object_details_init(self):
self.object_details_screen = ObjectDetails(self)
def object_details_open(self, sender=None, from_conv=False, from_telemetry=False, source_dest=None, direction="left", no_transition=False):
def object_details_open(self, sender=None, from_conv=False, from_objects=False, from_telemetry=False, source_dest=None, direction="left", no_transition=False):
if no_transition:
self.root.ids.screen_manager.transition = self.no_transition
else:
@ -4665,10 +4700,13 @@ class SidebandApp(MDApp):
self.root.ids.nav_drawer.set_state("closed")
if telemetry_source == None:
self.conversations_action(direction="right")
if self.include_objects and not self.include_conversations:
self.objects_action(direction="right")
else:
self.conversations_action(direction="right")
else:
Clock.schedule_once(lambda dt: self.object_details_screen.set_source(telemetry_source, from_conv=from_conv, from_telemetry=from_telemetry), 0.0)
Clock.schedule_once(lambda dt: self.object_details_screen.set_source(telemetry_source, from_conv=from_conv, from_objects=from_objects, from_telemetry=from_telemetry), 0.0)
def vj(dt):
self.root.ids.screen_manager.current = "object_details_screen"

View File

@ -564,6 +564,8 @@ class SidebandCore():
self.config["telemetry_send_appearance"] = False
if not "telemetry_display_trusted_only" in self.config:
self.config["telemetry_display_trusted_only"] = False
if not "display_style_from_all" in self.config:
self.config["display_style_from_all"] = False
if not "telemetry_receive_trusted_only" in self.config:
self.config["telemetry_receive_trusted_only"] = False
@ -809,8 +811,8 @@ class SidebandCore():
except Exception as e:
RNS.log("Exception while decoding LXMF destination announce data:"+str(e))
def list_conversations(self):
result = self._db_conversations()
def list_conversations(self, conversations=True, objects=False):
result = self._db_conversations(conversations, objects)
if result != None:
return result
else:
@ -849,10 +851,33 @@ class SidebandCore():
RNS.log("Error while checking trust for "+RNS.prettyhexrep(context_dest)+": "+str(e), RNS.LOG_ERROR)
return False
def should_send_telemetry(self, context_dest):
def is_object(self, context_dest, conv_data = None):
try:
if conv_data == None:
existing_conv = self._db_conversation(context_dest)
else:
existing_conv = conv_data
if existing_conv != None:
data_dict = existing_conv["data"]
if data_dict != None:
if "is_object" in data_dict:
return data_dict["is_object"]
return False
except Exception as e:
RNS.log("Error while checking trust for "+RNS.prettyhexrep(context_dest)+": "+str(e), RNS.LOG_ERROR)
return False
def should_send_telemetry(self, context_dest, conv_data=None):
try:
if self.config["telemetry_enabled"]:
existing_conv = self._db_conversation(context_dest)
if conv_data == None:
existing_conv = self._db_conversation(context_dest)
else:
existing_conv = conv_data
if existing_conv != None:
cd = existing_conv["data"]
if cd != None and "telemetry" in cd and cd["telemetry"] == True:
@ -887,9 +912,13 @@ class SidebandCore():
RNS.log("Error while checking request permissions for "+RNS.prettyhexrep(context_dest)+": "+str(e), RNS.LOG_ERROR)
return False
def requests_allowed_from(self, context_dest):
def requests_allowed_from(self, context_dest, conv_data=None):
try:
existing_conv = self._db_conversation(context_dest)
if conv_data == None:
existing_conv = self._db_conversation(context_dest)
else:
existing_conv = conv_data
if existing_conv != None:
cd = existing_conv["data"]
if cd != None and "allow_requests" in cd and cd["allow_requests"] == True:
@ -992,6 +1021,9 @@ class SidebandCore():
def untrusted_conversation(self, context_dest):
self._db_conversation_set_trusted(context_dest, False)
def conversation_set_object(self, context_dest, is_object):
self._db_conversation_set_object(context_dest, is_object)
def send_telemetry_in_conversation(self, context_dest):
self._db_conversation_set_telemetry(context_dest, True)
@ -1954,6 +1986,24 @@ class SidebandCore():
result = dbc.fetchall()
db.commit()
def _db_conversation_set_object(self, context_dest, is_object=False):
conv = self._db_conversation(context_dest)
data_dict = conv["data"]
if data_dict == None:
data_dict = {}
data_dict["is_object"] = is_object
packed_dict = msgpack.packb(data_dict)
db = self.__db_connect()
dbc = db.cursor()
query = "UPDATE conv set data = ? where dest_context = ?"
data = (packed_dict, context_dest)
dbc.execute(query, data)
result = dbc.fetchall()
db.commit()
def _db_conversation_set_trusted(self, context_dest, trusted):
db = self.__db_connect()
dbc = db.cursor()
@ -1973,7 +2023,7 @@ class SidebandCore():
result = dbc.fetchall()
db.commit()
def _db_conversations(self):
def _db_conversations(self, conversations=True, objects=False):
db = self.__db_connect()
dbc = db.cursor()
@ -1985,12 +2035,15 @@ class SidebandCore():
else:
convs = []
for entry in result:
is_object = False
last_rx = entry[1]
last_tx = entry[2]
last_activity = max(last_rx, last_tx)
data = None
try:
data = msgpack.unpackb(entry[7])
if "is_object" in data:
is_object = data["is_object"]
except:
pass
@ -2003,7 +2056,14 @@ class SidebandCore():
"trust": entry[5],
"data": data,
}
convs.append(conv)
should_add = False
if conversations and not is_object:
should_add = True
if objects and is_object:
should_add = True
if should_add:
convs.append(conv)
return sorted(convs, key=lambda c: c["last_activity"], reverse=True)

View File

@ -35,6 +35,7 @@ class ConvSettings(BoxLayout):
trusted = BooleanProperty()
telemetry = BooleanProperty()
allow_requests = BooleanProperty()
is_object = BooleanProperty()
class Conversations():
def __init__(self, app):
@ -72,7 +73,16 @@ class Conversations():
# if self.app.sideband.getstate("app.flags.unread_conversations"):
# self.clear_list()
self.context_dests = self.app.sideband.list_conversations()
self.context_dests = self.app.sideband.list_conversations(conversations=self.app.include_conversations, objects=self.app.include_objects)
view_title = "Conversations"
if self.app.include_conversations:
if self.app.include_objects:
view_title = "Conversations & Objects"
elif self.app.include_objects:
view_title = "Objects"
self.screen.ids.conversations_bar.title = view_title
self.update_widget()
self.app.sideband.setstate("app.flags.unread_conversations", False)
@ -83,12 +93,12 @@ class Conversations():
context_dest = conv["dest"]
unread = conv["unread"]
appearance = self.app.sideband.peer_appearance(context_dest, conv=conv)
# is_trusted = self.app.sideband.is_trusted(context_dest)
is_trusted = conv["trust"] == 1
appearance_from_all = self.app.sideband.config["display_style_from_all"]
trust_icon = "account-question"
da = self.app.sideband.DEFAULT_APPEARANCE
if is_trusted and self.app.sideband.config["display_style_in_contact_list"] and appearance != None and appearance != da:
if (is_trusted or appearance_from_all) and self.app.sideband.config["display_style_in_contact_list"] and appearance != None and appearance != da:
if unread:
trust_icon = "email"
else:
@ -123,6 +133,7 @@ class Conversations():
last_activity = conv["last_activity"]
trusted = conv["trust"] == 1
appearance = self.app.sideband.peer_appearance(context_dest, conv=conv)
is_object = self.app.sideband.is_object(context_dest, conv_data=conv)
da = self.app.sideband.DEFAULT_APPEARANCE
ic_s = 24; ic_p = 14
@ -135,10 +146,21 @@ class Conversations():
else:
ti_color = None
if is_object:
def gen_rel_func():
def x(ws):
self.app.object_details_action(sender=ws, from_objects=True)
return x
rel_func = gen_rel_func()
else:
rel_func = self.app.conversation_action
iconl = IconLeftWidget(
icon=conv_icon, theme_icon_color=ti_color,
icon_color=fg, md_bg_color=bg,
on_release=self.app.conversation_action)
on_release=rel_func)
iconl.source_dest = context_dest
iconl._default_icon_pad = dp(ic_p)
iconl.icon_size = dp(ic_s)
@ -154,7 +176,7 @@ class Conversations():
remove_widgets = []
for w in self.list.children:
if not w.sb_uid in [e["dest"] for e in self.context_dests]:
RNS.log("Should remove "+RNS.prettyhexrep(w.sb_uid)+" from list")
RNS.log("Should remove "+RNS.prettyhexrep(w.sb_uid)+" from list", RNS.LOG_DEBUG)
remove_widgets.append(w)
self.added_item_dests.remove(w.sb_uid)
@ -169,7 +191,9 @@ class Conversations():
last_activity = conv["last_activity"]
peer_disp_name = multilingual_markup(escape_markup(str(self.app.sideband.peer_display_name(context_dest))).encode("utf-8")).decode("utf-8")
if not context_dest in self.added_item_dests:
if not context_dest in self.added_item_dests:
existing_conv = self.app.sideband._db_conversation(context_dest)
is_object = self.app.sideband.is_object(context_dest, conv_data=existing_conv)
iconl = self.get_icon(conv)
item = OneLineAvatarIconListItem(text=peer_disp_name, on_release=self.app.conversation_action)
item.add_widget(iconl)
@ -184,14 +208,18 @@ class Conversations():
t_s = time.time()
dest = self.conversation_dropdown.context_dest
try:
cd = self.app.sideband._db_conversation(dest)
disp_name = self.app.sideband.raw_display_name(dest)
is_trusted = self.app.sideband.is_trusted(dest)
send_telemetry = self.app.sideband.should_send_telemetry(dest)
allow_requests = self.app.sideband.requests_allowed_from(dest)
is_trusted = self.app.sideband.is_trusted(dest, conv_data=cd)
is_object = self.app.sideband.is_object(dest, conv_data=cd)
send_telemetry = self.app.sideband.should_send_telemetry(dest, conv_data=cd)
allow_requests = self.app.sideband.requests_allowed_from(dest, conv_data=cd)
RNS.log("is_object: "+str(is_object))
yes_button = MDRectangleFlatButton(text="Save",font_size=dp(18), theme_text_color="Custom", line_color=self.app.color_accept, text_color=self.app.color_accept)
no_button = MDRectangleFlatButton(text="Cancel",font_size=dp(18))
dialog_content = ConvSettings(disp_name=disp_name, context_dest=RNS.hexrep(dest, delimit=False), trusted=is_trusted, telemetry=send_telemetry, allow_requests=allow_requests)
dialog_content = ConvSettings(disp_name=disp_name, context_dest=RNS.hexrep(dest, delimit=False), trusted=is_trusted,
telemetry=send_telemetry, allow_requests=allow_requests, is_object=is_object)
if self.app.sideband.config["input_language"] != None:
dialog_content.ids.name_field.font_name = self.app.sideband.config["input_language"]
else:
@ -212,6 +240,7 @@ class Conversations():
trusted = dialog.d_content.ids["trusted_switch"].active
telemetry = dialog.d_content.ids["telemetry_switch"].active
allow_requests = dialog.d_content.ids["allow_requests_switch"].active
conv_is_object = dialog.d_content.ids["is_object_switch"].active
if trusted:
self.app.sideband.trusted_conversation(dest)
else:
@ -227,6 +256,11 @@ class Conversations():
else:
self.app.sideband.disallow_requests_from(dest)
if conv_is_object:
self.app.sideband.conversation_set_object(dest, True)
else:
self.app.sideband.conversation_set_object(dest, False)
self.app.sideband.named_conversation(name, dest)
except Exception as e:
@ -326,6 +360,13 @@ class Conversations():
self.delete_dialog.open()
return x
# def gen_move_to(item):
# def x():
# item.dmenu.dismiss()
# self.app.sideband.conversation_set_object(self.conversation_dropdown.context_dest, not self.app.sideband.is_object(self.conversation_dropdown.context_dest))
# self.app.conversations_view.update()
# return x
def gen_copy_addr(item):
def x():
Clipboard.copy(RNS.hexrep(self.conversation_dropdown.context_dest, delimit=False))
@ -335,6 +376,7 @@ class Conversations():
item.iconr = IconRightWidget(icon="dots-vertical");
if self.conversation_dropdown == None:
obj_str = "conversations" if is_object else "objects"
dmi_h = 40
dm_items = [
{
@ -349,6 +391,12 @@ class Conversations():
"height": dp(dmi_h),
"on_release": gen_copy_addr(item)
},
# {
# "text": "Move to objects",
# "viewclass": "OneLineListItem",
# "height": dp(dmi_h),
# "on_release": gen_move_to(item)
# },
{
"text": "Clear Messages",
"viewclass": "OneLineListItem",
@ -393,7 +441,7 @@ class Conversations():
item.add_widget(item.iconr)
item.trusted = self.app.sideband.is_trusted(context_dest)
item.trusted = self.app.sideband.is_trusted(context_dest, conv_data=existing_conv)
self.added_item_dests.append(context_dest)
self.list.add_widget(item)
@ -440,6 +488,7 @@ MDScreen:
MDTopAppBar:
title: "Conversations"
id: conversations_bar
anchor_title: "left"
elevation: 0
left_action_items:
@ -561,6 +610,21 @@ Builder.load_string("""
pos_hint: {"center_y": 0.43}
active: root.allow_requests
MDBoxLayout:
orientation: "horizontal"
size_hint_y: None
padding: [0,0,dp(8),0]
height: dp(32)
MDLabel:
id: is_object_label
text: "Is Object"
font_style: "H6"
MDSwitch:
id: is_object_switch
pos_hint: {"center_y": 0.43}
active: root.is_object
<MsgSync>
orientation: "vertical"
spacing: "24dp"

View File

@ -61,6 +61,16 @@ MDNavigationLayout:
on_release: root.ids.screen_manager.app.conversations_action(self)
OneLineIconListItem:
text: "Objects"
on_release: root.ids.screen_manager.app.objects_action(self)
# _no_ripple_effect: True
IconLeftWidget:
icon: "devices"
on_release: root.ids.screen_manager.app.objects_action(self)
OneLineIconListItem:
text: "Situation Map"
on_release: root.ids.screen_manager.app.map_action(self)
@ -1402,7 +1412,7 @@ MDScreen:
height: dp(48)
MDLabel:
text: "Display styles in conversation list"
text: "Show user icons in conversation list"
font_style: "H6"
MDSwitch:
@ -1410,6 +1420,21 @@ MDScreen:
pos_hint: {"center_y": 0.3}
active: False
MDBoxLayout:
orientation: "horizontal"
size_hint_y: None
padding: [0,0,dp(24),dp(0)]
height: dp(48)
MDLabel:
text: "Only show user icons from trusted"
font_style: "H6"
MDSwitch:
id: display_style_from_trusted_only
pos_hint: {"center_y": 0.3}
active: False
MDBoxLayout:
orientation: "horizontal"
size_hint_y: None

View File

@ -41,6 +41,7 @@ class ObjectDetails():
self.raw_telemetry = None
self.from_telemetry = False
self.from_conv = False
self.from_objects = False
self.viewing_self = False
self.delete_dialog = None
@ -84,6 +85,8 @@ class ObjectDetails():
else:
if self.from_conv:
self.app.open_conversation(self.object_hash, direction="right")
elif self.from_objects:
self.app.objects_action(direction="right")
else:
self.app.close_sub_map_action()
@ -117,11 +120,11 @@ class ObjectDetails():
def reload_telemetry(self, sender=None, notoast=False):
if self.object_hash != None:
self.set_source(self.object_hash, from_conv=self.from_conv, from_telemetry=self.from_telemetry)
self.set_source(self.object_hash, from_conv=self.from_conv, from_objects=self.from_objects, from_telemetry=self.from_telemetry)
if not notoast:
toast("Reloaded telemetry for object")
def set_source(self, source_dest, from_conv=False, from_telemetry=False, prefetched=None):
def set_source(self, source_dest, from_conv=False, from_objects=False, from_telemetry=False, prefetched=None):
try:
self.object_hash = source_dest
own_address = self.app.sideband.lxmf_destination.hash
@ -140,6 +143,10 @@ class ObjectDetails():
self.from_conv = True
else:
self.from_conv = False
if from_objects:
self.from_objects = True
else:
self.from_objects = False
self.coords = None
self.telemetry_list.data = []