mirror of
https://github.com/pdxlocations/contact.git
synced 2026-03-28 17:12:35 +01:00
Merge remote-tracking branch 'origin/main' into pr/rfschmid/111
This commit is contained in:
@@ -101,7 +101,7 @@ def load_messages_from_db():
|
||||
channel = int(channel) if channel.isdigit() else channel
|
||||
|
||||
# Add the channel to globals.channel_list if not already present
|
||||
if channel not in globals.channel_list:
|
||||
if channel not in globals.channel_list and not is_chat_archived(channel):
|
||||
globals.channel_list.append(channel)
|
||||
|
||||
# Ensure the channel exists in globals.all_messages
|
||||
@@ -189,7 +189,7 @@ def maybe_store_nodeinfo_in_db(packet):
|
||||
logging.error(f"Unexpected error in maybe_store_nodeinfo_in_db: {e}")
|
||||
|
||||
|
||||
def update_node_info_in_db(user_id, long_name=None, short_name=None, hw_model=None, is_licensed=None, role=None, public_key=None):
|
||||
def update_node_info_in_db(user_id, long_name=None, short_name=None, hw_model=None, is_licensed=None, role=None, public_key=None, chat_archived=None):
|
||||
"""Update or insert node information into the database, preserving unchanged fields."""
|
||||
try:
|
||||
ensure_node_table_exists() # Ensure the table exists before any operation
|
||||
@@ -198,12 +198,18 @@ def update_node_info_in_db(user_id, long_name=None, short_name=None, hw_model=No
|
||||
db_cursor = db_connection.cursor()
|
||||
table_name = f'"{globals.myNodeNum}_nodedb"' # Quote in case of numeric names
|
||||
|
||||
|
||||
table_columns = [i[1] for i in db_cursor.execute(f'PRAGMA table_info({table_name})')]
|
||||
if "chat_archived" not in table_columns:
|
||||
update_table_query = f"ALTER TABLE {table_name} ADD COLUMN chat_archived INTEGER"
|
||||
db_cursor.execute(update_table_query)
|
||||
|
||||
# Fetch existing values to preserve unchanged fields
|
||||
db_cursor.execute(f'SELECT * FROM {table_name} WHERE user_id = ?', (user_id,))
|
||||
existing_record = db_cursor.fetchone()
|
||||
|
||||
if existing_record:
|
||||
existing_long_name, existing_short_name, existing_hw_model, existing_is_licensed, existing_role, existing_public_key = existing_record[1:]
|
||||
existing_long_name, existing_short_name, existing_hw_model, existing_is_licensed, existing_role, existing_public_key, existing_chat_archived = existing_record[1:]
|
||||
|
||||
long_name = long_name if long_name is not None else existing_long_name
|
||||
short_name = short_name if short_name is not None else existing_short_name
|
||||
@@ -211,20 +217,22 @@ def update_node_info_in_db(user_id, long_name=None, short_name=None, hw_model=No
|
||||
is_licensed = is_licensed if is_licensed is not None else existing_is_licensed
|
||||
role = role if role is not None else existing_role
|
||||
public_key = public_key if public_key is not None else existing_public_key
|
||||
chat_archived = chat_archived if chat_archived is not None else existing_chat_archived
|
||||
|
||||
# Upsert logic
|
||||
upsert_query = f'''
|
||||
INSERT INTO {table_name} (user_id, long_name, short_name, hw_model, is_licensed, role, public_key)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?)
|
||||
INSERT INTO {table_name} (user_id, long_name, short_name, hw_model, is_licensed, role, public_key, chat_archived)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(user_id) DO UPDATE SET
|
||||
long_name = excluded.long_name,
|
||||
short_name = excluded.short_name,
|
||||
hw_model = excluded.hw_model,
|
||||
is_licensed = excluded.is_licensed,
|
||||
role = excluded.role,
|
||||
public_key = excluded.public_key
|
||||
public_key = excluded.public_key,
|
||||
chat_archived = excluded.chat_archived
|
||||
'''
|
||||
db_cursor.execute(upsert_query, (user_id, long_name, short_name, hw_model, is_licensed, role, public_key))
|
||||
db_cursor.execute(upsert_query, (user_id, long_name, short_name, hw_model, is_licensed, role, public_key, chat_archived))
|
||||
db_connection.commit()
|
||||
|
||||
except sqlite3.Error as e:
|
||||
@@ -243,7 +251,8 @@ def ensure_node_table_exists():
|
||||
hw_model TEXT,
|
||||
is_licensed TEXT,
|
||||
role TEXT,
|
||||
public_key TEXT
|
||||
public_key TEXT,
|
||||
chat_archived INTEGER
|
||||
'''
|
||||
ensure_table_exists(table_name, schema)
|
||||
|
||||
@@ -294,4 +303,25 @@ def get_name_from_database(user_id, type="long"):
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Unexpected error in get_name_from_database: {e}")
|
||||
return "Unknown"
|
||||
return "Unknown"
|
||||
|
||||
def is_chat_archived(user_id):
|
||||
try:
|
||||
with sqlite3.connect(config.db_file_path) as db_connection:
|
||||
db_cursor = db_connection.cursor()
|
||||
table_name = f"{str(globals.myNodeNum)}_nodedb"
|
||||
nodeinfo_table = f'"{table_name}"'
|
||||
query = f"SELECT chat_archived FROM {nodeinfo_table} WHERE user_id = ?"
|
||||
db_cursor.execute(query, (user_id,))
|
||||
result = db_cursor.fetchone()
|
||||
|
||||
return result[0] if result else 0
|
||||
|
||||
except sqlite3.Error as e:
|
||||
logging.error(f"SQLite error in is_chat_archived: {e}")
|
||||
return "Unknown"
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"Unexpected error in is_chat_archived: {e}")
|
||||
return "Unknown"
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ interface = None
|
||||
display_log = False
|
||||
all_messages = {}
|
||||
channel_list = []
|
||||
notifications = set()
|
||||
notifications = []
|
||||
packet_buffer = []
|
||||
node_list = []
|
||||
myNodeNum = 0
|
||||
|
||||
@@ -3,7 +3,7 @@ import time
|
||||
from utilities.utils import refresh_node_list
|
||||
from datetime import datetime
|
||||
from ui.curses_ui import draw_packetlog_win, draw_node_list, draw_messages_window, draw_channel_list, add_notification
|
||||
from db_handler import save_message_to_db, maybe_store_nodeinfo_in_db, get_name_from_database
|
||||
from db_handler import save_message_to_db, maybe_store_nodeinfo_in_db, get_name_from_database, update_node_info_in_db
|
||||
import default_config as config
|
||||
import globals
|
||||
|
||||
@@ -50,7 +50,9 @@ def on_receive(packet, interface):
|
||||
pass
|
||||
else:
|
||||
globals.channel_list.append(packet['from'])
|
||||
globals.all_messages[packet['from']] = []
|
||||
if(packet['from'] not in globals.all_messages):
|
||||
globals.all_messages[packet['from']] = []
|
||||
update_node_info_in_db(packet['from'], chat_archived=False)
|
||||
refresh_channels = True
|
||||
|
||||
channel_number = globals.channel_list.index(packet['from'])
|
||||
|
||||
@@ -4,7 +4,7 @@ from utilities.utils import get_channels, get_readable_duration, get_time_ago, r
|
||||
from settings import settings_menu
|
||||
from message_handlers.tx_handler import send_message, send_traceroute
|
||||
from ui.colors import setup_colors, get_color
|
||||
from db_handler import get_name_from_database
|
||||
from db_handler import get_name_from_database, update_node_info_in_db, is_chat_archived
|
||||
import default_config as config
|
||||
import ui.dialog
|
||||
import globals
|
||||
@@ -50,16 +50,16 @@ def draw_node_details():
|
||||
])
|
||||
|
||||
for s in node_details_list:
|
||||
if len(nodestr) + len(s) < width:
|
||||
if len(nodestr) + len(s) < width - 2:
|
||||
nodestr = nodestr + s
|
||||
|
||||
draw_centered_text_field(function_win, nodestr, 0, get_color("commands"))
|
||||
|
||||
def draw_function_win():
|
||||
cmds = ["↑→↓← = Select", " ENTER = Send", " ` = Settings", " ^P = Packet Log", " ESC = Quit"]
|
||||
cmds = ["↑→↓← = Select", " ENTER = Send", " ` = Settings", " ^P = Packet Log", " ESC = Quit", " ^t = Traceroute", " ^d = Archive Chat"]
|
||||
function_str = ""
|
||||
for s in cmds:
|
||||
if(len(function_str) + len(s) < function_win.getmaxyx()[1]):
|
||||
if(len(function_str) + len(s) < function_win.getmaxyx()[1] - 2):
|
||||
function_str += s
|
||||
|
||||
draw_centered_text_field(function_win, function_str, 0, get_color("commands"))
|
||||
@@ -113,7 +113,7 @@ def highlight_line(highlight, window, line):
|
||||
pad.chgat(line, 1, select_len, nd_color | curses.A_REVERSE if highlight else nd_color)
|
||||
|
||||
if(window == 0):
|
||||
channel = list(globals.all_messages.keys())[line]
|
||||
channel = globals.channel_list[line]
|
||||
win_width = channel_box.getmaxyx()[1]
|
||||
|
||||
if(isinstance(channel, int)):
|
||||
@@ -126,10 +126,12 @@ def highlight_line(highlight, window, line):
|
||||
pad.chgat(line, 1, select_len, ch_color | curses.A_REVERSE if highlight else ch_color)
|
||||
|
||||
def add_notification(channel_number):
|
||||
globals.notifications.add(channel_number)
|
||||
if channel_number not in globals.notifications:
|
||||
globals.notifications.append(channel_number)
|
||||
|
||||
def remove_notification(channel_number):
|
||||
globals.notifications.discard(channel_number)
|
||||
if channel_number in globals.notifications:
|
||||
globals.notifications.remove(channel_number)
|
||||
|
||||
def draw_text_field(win, text, color):
|
||||
win.border()
|
||||
@@ -180,24 +182,28 @@ def draw_channel_list():
|
||||
|
||||
channel_pad.resize(len(globals.all_messages), channel_box.getmaxyx()[1])
|
||||
|
||||
for i, channel in enumerate(list(globals.all_messages.keys())):
|
||||
idx = 0
|
||||
for channel in globals.channel_list:
|
||||
# Convert node number to long name if it's an integer
|
||||
if isinstance(channel, int):
|
||||
if is_chat_archived(channel):
|
||||
continue
|
||||
channel = get_name_from_database(channel, type='long')
|
||||
|
||||
# Determine whether to add the notification
|
||||
notification = " " + config.notification_symbol if i in globals.notifications else ""
|
||||
notification = " " + config.notification_symbol if idx in globals.notifications else ""
|
||||
|
||||
# Truncate the channel name if it's too long to fit in the window
|
||||
truncated_channel = channel[:win_width - 5] + '-' if len(channel) > win_width - 5 else channel
|
||||
if i == globals.selected_channel:
|
||||
if idx == globals.selected_channel:
|
||||
if globals.current_window == 0:
|
||||
channel_pad.addstr(i, 1, truncated_channel + notification, get_color("channel_list", reverse=True))
|
||||
channel_pad.addstr(idx, 1, truncated_channel + notification, get_color("channel_list", reverse=True))
|
||||
remove_notification(globals.selected_channel)
|
||||
else:
|
||||
channel_pad.addstr(i, 1, truncated_channel + notification, get_color("channel_selected"))
|
||||
channel_pad.addstr(idx, 1, truncated_channel + notification, get_color("channel_selected"))
|
||||
else:
|
||||
channel_pad.addstr(i, 1, truncated_channel + notification, get_color("channel_list"))
|
||||
channel_pad.addstr(idx, 1, truncated_channel + notification, get_color("channel_list"))
|
||||
idx += 1
|
||||
|
||||
channel_box.attrset(get_color("window_frame_selected") if globals.current_window == 0 else get_color("window_frame"))
|
||||
channel_box.box()
|
||||
@@ -477,10 +483,6 @@ def main_ui(stdscr):
|
||||
elif globals.current_window == 2:
|
||||
scroll_nodes(-1)
|
||||
|
||||
elif char == curses.KEY_RESIZE:
|
||||
input_text = ""
|
||||
handle_resize(stdscr, False)
|
||||
|
||||
elif char == curses.KEY_DOWN:
|
||||
if globals.current_window == 0:
|
||||
scroll_channels(1)
|
||||
@@ -591,9 +593,15 @@ def main_ui(stdscr):
|
||||
node_list = globals.node_list
|
||||
if node_list[globals.selected_node] not in globals.channel_list:
|
||||
globals.channel_list.append(node_list[globals.selected_node])
|
||||
if(node_list[globals.selected_node] not in globals.all_messages):
|
||||
globals.all_messages[node_list[globals.selected_node]] = []
|
||||
|
||||
|
||||
globals.selected_channel = globals.channel_list.index(node_list[globals.selected_node])
|
||||
|
||||
if(is_chat_archived(globals.channel_list[globals.selected_channel])):
|
||||
update_node_info_in_db(globals.channel_list[globals.selected_channel], chat_archived=False)
|
||||
|
||||
globals.selected_node = 0
|
||||
globals.current_window = 0
|
||||
|
||||
@@ -635,6 +643,28 @@ def main_ui(stdscr):
|
||||
globals.display_log = False
|
||||
packetlog_win.erase()
|
||||
draw_messages_window(True)
|
||||
|
||||
elif char == curses.KEY_RESIZE:
|
||||
input_text = ""
|
||||
handle_resize(stdscr, False)
|
||||
|
||||
# ^D
|
||||
elif char == chr(4):
|
||||
if(globals.current_window == 0):
|
||||
if(isinstance(globals.channel_list[globals.selected_channel], int)):
|
||||
update_node_info_in_db(globals.channel_list[globals.selected_channel], chat_archived=True)
|
||||
|
||||
# Shift notifications up to account for deleted item
|
||||
for i in range(len(globals.notifications)):
|
||||
if globals.notifications[i] > globals.selected_channel:
|
||||
globals.notifications[i] -= 1
|
||||
|
||||
del globals.channel_list[globals.selected_channel]
|
||||
globals.selected_channel = min(globals.selected_channel, len(globals.channel_list) - 1)
|
||||
select_channel(globals.selected_channel)
|
||||
draw_channel_list()
|
||||
draw_messages_window()
|
||||
|
||||
else:
|
||||
# Append typed character to input text
|
||||
if(isinstance(char, str)):
|
||||
|
||||
Reference in New Issue
Block a user