1
0
forked from iarv/contact

Compare commits

...

7 Commits

Author SHA1 Message Date
pdxlocations
8b05072786 bump version 2025-06-13 15:33:57 -07:00
pdxlocations
4455781e6c fix types and returns 2025-06-12 16:38:05 -07:00
pdxlocations
0c8aaee415 Merge pull request #197 from rfschmid/redirect-sound-player-output-to-dev-null
Redirect sound player output to dev null
2025-06-12 16:10:26 -07:00
pdxlocations
b97d9f4649 Merge pull request #196 from rfschmid/only-clear-input-text-on-enter-if-sending-message
Only clear input on enter when sending message
2025-06-12 16:09:44 -07:00
Russell Schmidt
4152fb6a21 Redirect sound player output to dev null
On my linux system, the sound playing code goes to aplay. When called,
aplay outputs a message about the file it is playing to stderr, which
causes it to be printed on the input line, which can't be easily
cleared. Redirect output from the audio player executable to dev/null.
Deduplicate sound playing code a bit so we only need one call to
subprocess.run, so I don't have to make this change in three places.
2025-06-12 17:28:30 -05:00
Russell Schmidt
384e36dac2 Only clear input on enter when sending message
We should only clear the input field when the user presses enter if the
user actually sent the message. If selecting a different node to send
to, don't clear input.
2025-06-12 17:23:03 -05:00
pdxlocations
65bca84fe6 minor refactor 2025-06-10 23:24:11 -07:00
4 changed files with 35 additions and 29 deletions

View File

@@ -53,22 +53,25 @@ logging.basicConfig(
app_state.lock = threading.Lock()
# ------------------------------------------------------------------------------
# Main Program Logic
# ------------------------------------------------------------------------------
def prompt_region_if_unset(args: object) -> None:
"""Prompt user to set region if it is unset."""
confirmation = get_list_input("Your region is UNSET. Set it now?", "Yes", ["Yes", "No"])
if confirmation == "Yes":
set_region(interface_state.interface)
interface_state.interface.close()
interface_state.interface = initialize_interface(args)
def initialize_globals(args) -> None:
def initialize_globals(args: object) -> None:
"""Initializes interface and shared globals."""
interface_state.interface = initialize_interface(args)
# Prompt for region if unset
if interface_state.interface.localNode.localConfig.lora.region == 0:
confirmation = get_list_input("Your region is UNSET. Set it now?", "Yes", ["Yes", "No"])
if confirmation == "Yes":
set_region(interface_state.interface)
interface_state.interface.close()
interface_state.interface = initialize_interface(args)
prompt_region_if_unset(args)
interface_state.myNodeNum = get_nodeNum()
ui_state.channel_list = get_channels()

View File

@@ -29,34 +29,36 @@ from contact.utilities.singleton import ui_state, interface_state, app_state
def play_sound():
try:
system = platform.system()
sound_path = ""
executable = ""
if system == "Darwin": # macOS
if system == "Darwin": #macOS
sound_path = "/System/Library/Sounds/Ping.aiff"
if os.path.exists(sound_path):
subprocess.run(["afplay", sound_path], check=True)
return
else:
logging.warning(f"macOS sound file not found: {sound_path}")
executable = "afplay"
elif system == "Linux":
sound_path = "/usr/share/sounds/freedesktop/stereo/complete.oga"
if(shutil.which("paplay")):
executable = "paplay"
else:
executable = "aplay"
if executable != "" and sound_path != "":
if os.path.exists(sound_path):
if shutil.which("paplay"):
subprocess.run(["paplay", sound_path], check=True)
return
elif shutil.which("aplay"):
subprocess.run(["aplay", sound_path], check=True)
if shutil.which(executable):
subprocess.run([executable, sound_path], check=True,
stdout=subprocess.DEVNULL, stderr = subprocess.DEVNULL)
return
else:
logging.warning("No sound player found (paplay/aplay)")
logging.warning("No sound player found (afplay/paplay/aplay)")
else:
logging.warning(f"Linux sound file not found: {sound_path}")
logging.warning(f"Sound file not found: {sound_path}")
except subprocess.CalledProcessError as e:
logging.error(f"Sound playback failed: {e}")
except Exception as e:
logging.error(f"Unexpected error: {e}")
# Final fallback: terminal beep
print("\a")

View File

@@ -108,7 +108,7 @@ def main_ui(stdscr: curses.window) -> None:
handle_resize(stdscr, True)
while True:
draw_text_field(entry_win, f"Input: {input_text[-(stdscr.getmaxyx()[1] - 10):]}", get_color("input"))
draw_text_field(entry_win, f"Input: {(input_text or '')[-(stdscr.getmaxyx()[1] - 10):]}", get_color("input"))
# Get user input from entry window
char = entry_win.get_wch()
@@ -137,8 +137,7 @@ def main_ui(stdscr: curses.window) -> None:
handle_leftright(char)
elif char in (chr(curses.KEY_ENTER), chr(10), chr(13)):
handle_enter(input_text)
input_text = ""
input_text = handle_enter(input_text)
elif char == chr(20): # Ctrl + t for Traceroute
handle_ctrl_t(stdscr)
@@ -298,7 +297,7 @@ def handle_leftright(char: int) -> None:
refresh_pad(2)
def handle_enter(input_text: str) -> None:
def handle_enter(input_text: str) -> str:
"""Handle Enter key events to send messages or select channels."""
if ui_state.current_window == 2:
node_list = ui_state.node_list
@@ -318,6 +317,7 @@ def handle_enter(input_text: str) -> None:
draw_node_list()
draw_channel_list()
draw_messages_window(True)
return input_text
elif len(input_text) > 0:
# Enter key pressed, send user input as message
@@ -325,8 +325,9 @@ def handle_enter(input_text: str) -> None:
draw_messages_window(True)
# Clear entry window and reset input text
input_text = ""
entry_win.erase()
return ""
return input_text
def handle_ctrl_t(stdscr: curses.window) -> None:
@@ -342,7 +343,7 @@ def handle_ctrl_t(stdscr: curses.window) -> None:
handle_resize(stdscr, False)
def handle_backspace(entry_win: curses.window, input_text: str) -> None:
def handle_backspace(entry_win: curses.window, input_text: str) -> str:
"""Handle backspace key events to remove the last character from input text."""
if input_text:
input_text = input_text[:-1]

View File

@@ -1,6 +1,6 @@
[project]
name = "contact"
version = "1.3.13"
version = "1.3.14"
description = "This Python curses client for Meshtastic is a terminal-based client designed to manage device settings, enable mesh chat communication, and handle configuration backups and restores."
authors = [
{name = "Ben Lipsey",email = "ben@pdxlocations.com"}