mirror of
https://github.com/pdxlocations/contact.git
synced 2026-08-07 01:13:19 +02:00
current state
This commit is contained in:
@@ -38,6 +38,9 @@ config_folder = os.path.join(locals_dir, "node-configs")
|
||||
# Load translations
|
||||
field_mapping, help_text = parse_ini_file(translation_file)
|
||||
|
||||
# Aliases
|
||||
Segment = tuple[str, str, bool, bool]
|
||||
WrappedLine = list[Segment]
|
||||
|
||||
def display_menu(state: MenuState) -> tuple[object, object]: # curses.window or pad types
|
||||
|
||||
@@ -183,7 +186,7 @@ def get_wrapped_help_text(
|
||||
selected_option: str | None,
|
||||
width: int,
|
||||
max_lines: int
|
||||
):
|
||||
) -> list[WrappedLine]:
|
||||
"""Fetches and formats help text for display, ensuring it fits within the allowed lines."""
|
||||
|
||||
full_help_key = '.'.join(transformed_path + [selected_option]) if selected_option else None
|
||||
@@ -202,7 +205,7 @@ def get_wrapped_help_text(
|
||||
r'\\033\[4m(.*?)\\033\[0m': ('settings_default', False, True) # Underline
|
||||
}
|
||||
|
||||
def extract_ansi_segments(text):
|
||||
def extract_ansi_segments(text: str) -> list[Segment]:
|
||||
"""Extracts and replaces ANSI color codes, ensuring spaces are preserved."""
|
||||
matches = []
|
||||
last_pos = 0
|
||||
@@ -232,7 +235,7 @@ def get_wrapped_help_text(
|
||||
|
||||
return matches
|
||||
|
||||
def wrap_ansi_text(segments, wrap_width):
|
||||
def wrap_ansi_text(segments: list[Segment], wrap_width: int) -> list[WrappedLine]:
|
||||
"""Wraps text while preserving ANSI formatting and spaces."""
|
||||
wrapped_lines = []
|
||||
line_buffer = []
|
||||
@@ -275,7 +278,17 @@ def get_wrapped_help_text(
|
||||
return wrapped_help
|
||||
|
||||
|
||||
def move_highlight(old_idx, options, menu_win, menu_pad, help_win, help_text, max_help_lines, state):
|
||||
def move_highlight(
|
||||
old_idx: int,
|
||||
options: list[str],
|
||||
menu_win: object,
|
||||
menu_pad: object,
|
||||
help_win: object,
|
||||
help_text: dict[str, str],
|
||||
max_help_lines: int,
|
||||
state: MenuState
|
||||
) -> None:
|
||||
|
||||
if old_idx == state.selected_index: # No-op
|
||||
return
|
||||
|
||||
@@ -323,7 +336,12 @@ def move_highlight(old_idx, options, menu_win, menu_pad, help_win, help_text, ma
|
||||
draw_arrows(menu_win, visible_height, max_index, state)
|
||||
|
||||
|
||||
def draw_arrows(win, visible_height, max_index, state):
|
||||
def draw_arrows(
|
||||
win: object,
|
||||
visible_height: int,
|
||||
max_index: int,
|
||||
state: MenuState
|
||||
) -> None:
|
||||
|
||||
# vh = visible_height + (1 if show_save_option else 0)
|
||||
mi = max_index - (2 if state.show_save_option else 0)
|
||||
@@ -340,7 +358,7 @@ def draw_arrows(win, visible_height, max_index, state):
|
||||
win.addstr(visible_height + 3, 2, " ", get_color("settings_default"))
|
||||
|
||||
|
||||
def settings_menu(stdscr, interface):
|
||||
def settings_menu(stdscr: object, interface: object) -> None:
|
||||
curses.update_lines_cols()
|
||||
|
||||
menu = generate_menu_from_protobuf(interface)
|
||||
@@ -674,7 +692,7 @@ def settings_menu(stdscr, interface):
|
||||
menu_win.refresh()
|
||||
break
|
||||
|
||||
def set_region(interface):
|
||||
def set_region(interface: object) -> None:
|
||||
node = interface.getNode('^local')
|
||||
device_config = node.localConfig
|
||||
lora_descriptor = device_config.lora.DESCRIPTOR
|
||||
|
||||
@@ -11,11 +11,11 @@ json_file_path = os.path.join(parent_dir, "config.json")
|
||||
log_file_path = os.path.join(parent_dir, "client.log")
|
||||
db_file_path = os.path.join(parent_dir, "client.db")
|
||||
|
||||
def format_json_single_line_arrays(data, indent=4):
|
||||
def format_json_single_line_arrays(data: dict[str, object], indent: int = 4) -> str:
|
||||
"""
|
||||
Formats JSON with arrays on a single line while keeping other elements properly indented.
|
||||
"""
|
||||
def format_value(value, current_indent):
|
||||
def format_value(value: object, current_indent: int) -> str:
|
||||
if isinstance(value, dict):
|
||||
items = []
|
||||
for key, val in value.items():
|
||||
@@ -31,7 +31,7 @@ def format_json_single_line_arrays(data, indent=4):
|
||||
return format_value(data, indent)
|
||||
|
||||
# Recursive function to check and update nested dictionaries
|
||||
def update_dict(default, actual):
|
||||
def update_dict(default: dict[str, object], actual: dict[str, object]) -> bool:
|
||||
updated = False
|
||||
for key, value in default.items():
|
||||
if key not in actual:
|
||||
@@ -42,7 +42,7 @@ def update_dict(default, actual):
|
||||
updated = update_dict(value, actual[key]) or updated
|
||||
return updated
|
||||
|
||||
def initialize_config():
|
||||
def initialize_config() -> dict[str, object]:
|
||||
COLOR_CONFIG_DARK = {
|
||||
"default": ["white", "black"],
|
||||
"background": [" ", "black"],
|
||||
@@ -161,7 +161,7 @@ def initialize_config():
|
||||
|
||||
return loaded_config
|
||||
|
||||
def assign_config_variables(loaded_config):
|
||||
def assign_config_variables(loaded_config: dict[str, object]) -> None:
|
||||
# Assign values to local variables
|
||||
|
||||
global db_file_path, log_file_path, message_prefix, sent_message_prefix
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import curses
|
||||
from contact.ui.colors import get_color
|
||||
|
||||
def dialog(stdscr, title, message):
|
||||
def dialog(stdscr: curses.window, title: str, message: str) -> None:
|
||||
height, width = stdscr.getmaxyx()
|
||||
|
||||
# Calculate dialog dimensions
|
||||
|
||||
+17
-6
@@ -1,19 +1,27 @@
|
||||
from collections import OrderedDict
|
||||
from meshtastic.protobuf import config_pb2, module_config_pb2, channel_pb2
|
||||
import logging
|
||||
import base64
|
||||
import logging
|
||||
import os
|
||||
from collections import OrderedDict
|
||||
|
||||
from typing import Any
|
||||
|
||||
from google.protobuf.message import Message
|
||||
from meshtastic.protobuf import channel_pb2, config_pb2, module_config_pb2
|
||||
|
||||
|
||||
locals_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
translation_file = os.path.join(locals_dir, "localisations", "en.ini")
|
||||
|
||||
def encode_if_bytes(value):
|
||||
def encode_if_bytes(value: Any) -> str | Any:
|
||||
"""Encode byte values to base64 string."""
|
||||
if isinstance(value, bytes):
|
||||
return base64.b64encode(value).decode('utf-8')
|
||||
return value
|
||||
|
||||
def extract_fields(message_instance, current_config=None):
|
||||
def extract_fields(
|
||||
message_instance: Message,
|
||||
current_config: Message | dict[str, Any] | None = None
|
||||
) -> dict[str, Any]:
|
||||
if isinstance(current_config, dict): # Handle dictionaries
|
||||
return {key: (None, encode_if_bytes(current_config.get(key, "Not Set"))) for key in current_config}
|
||||
|
||||
@@ -47,7 +55,10 @@ def extract_fields(message_instance, current_config=None):
|
||||
menu[field.name] = (field, encode_if_bytes(current_value))
|
||||
return menu
|
||||
|
||||
def generate_menu_from_protobuf(interface):
|
||||
def generate_menu_from_protobuf(interface: object) -> dict[str, Any]:
|
||||
"""
|
||||
Builds the full settings menu structure from the protobuf definitions.
|
||||
"""
|
||||
menu_structure = {"Main Menu": {}}
|
||||
|
||||
# Add User Settings
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import curses
|
||||
from contact.ui.colors import get_color
|
||||
|
||||
def draw_splash(stdscr):
|
||||
def draw_splash(stdscr: object) -> None:
|
||||
curses.curs_set(0)
|
||||
|
||||
stdscr.clear()
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import os
|
||||
import json
|
||||
import curses
|
||||
from typing import Any
|
||||
from contact.ui.colors import get_color, setup_colors, COLOR_MAP
|
||||
from contact.ui.default_config import format_json_single_line_arrays, loaded_config
|
||||
from contact.utilities.input_handlers import get_list_input
|
||||
@@ -9,8 +10,7 @@ width = 80
|
||||
save_option = "Save Changes"
|
||||
sensitive_settings = []
|
||||
|
||||
def edit_color_pair(key, current_value):
|
||||
|
||||
def edit_color_pair(key: str, current_value: list[str]) -> list[str]:
|
||||
"""
|
||||
Allows the user to select a foreground and background color for a key.
|
||||
"""
|
||||
@@ -20,7 +20,7 @@ def edit_color_pair(key, current_value):
|
||||
|
||||
return [fg_color, bg_color]
|
||||
|
||||
def edit_value(key, current_value, state):
|
||||
def edit_value(key: str, current_value: str) -> str:
|
||||
|
||||
height = 10
|
||||
input_width = width - 16 # Allow space for "New Value: "
|
||||
@@ -96,7 +96,7 @@ def edit_value(key, current_value, state):
|
||||
return user_input if user_input else current_value
|
||||
|
||||
|
||||
def display_menu(state):
|
||||
def display_menu(state: Any) -> tuple[Any, Any, list[str]]:
|
||||
"""
|
||||
Render the configuration menu with a Save button directly added to the window.
|
||||
"""
|
||||
@@ -167,7 +167,14 @@ def display_menu(state):
|
||||
return menu_win, menu_pad, options
|
||||
|
||||
|
||||
def move_highlight(old_idx, options, menu_win, menu_pad, state):
|
||||
def move_highlight(
|
||||
old_idx: int,
|
||||
options: list[str],
|
||||
menu_win: curses.window,
|
||||
menu_pad: curses.window,
|
||||
state: Any
|
||||
) -> None:
|
||||
|
||||
if old_idx == state.selected_index: # No-op
|
||||
return
|
||||
|
||||
@@ -209,7 +216,12 @@ def move_highlight(old_idx, options, menu_win, menu_pad, state):
|
||||
draw_arrows(menu_win, visible_height, max_index, state)
|
||||
|
||||
|
||||
def draw_arrows(win, visible_height, max_index, state):
|
||||
def draw_arrows(
|
||||
win: curses.window,
|
||||
visible_height: int,
|
||||
max_index: int,
|
||||
state: any
|
||||
) -> None:
|
||||
|
||||
mi = max_index - (2 if state.show_save_option else 0)
|
||||
|
||||
@@ -225,7 +237,7 @@ def draw_arrows(win, visible_height, max_index, state):
|
||||
win.addstr(visible_height + 3, 2, " ", get_color("settings_default"))
|
||||
|
||||
|
||||
def json_editor(stdscr, state):
|
||||
def json_editor(stdscr: curses.window, state: Any) -> None:
|
||||
|
||||
state.selected_index = 0 # Track the selected option
|
||||
|
||||
@@ -351,13 +363,13 @@ def json_editor(stdscr, state):
|
||||
break
|
||||
|
||||
|
||||
def save_json(file_path, data):
|
||||
def save_json(file_path: str, data: dict[str, Any]) -> None:
|
||||
formatted_json = format_json_single_line_arrays(data)
|
||||
with open(file_path, "w", encoding="utf-8") as f:
|
||||
f.write(formatted_json)
|
||||
setup_colors(reinit=True)
|
||||
|
||||
def main(stdscr):
|
||||
def main(stdscr: curses.window) -> None:
|
||||
from contact.ui.ui_state import MenuState
|
||||
|
||||
state = MenuState()
|
||||
|
||||
Reference in New Issue
Block a user