Files
fenrir/src/fenrirscreenreader/commands/onScreenUpdate/70000-incoming.py

94 lines
3.1 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.
import time
from fenrirscreenreader.core.i18n import _
class command:
def __init__(self):
pass
def initialize(self, environment):
self.env = environment
def shutdown(self):
pass
def get_description(self):
return _("Announces incoming text changes")
def _was_handled_by_tab_completion(self, delta_text):
"""Check if this delta was already handled by tab completion to avoid duplicates"""
if "tabCompletion" not in self.env["commandBuffer"]:
return False
tab_state = self.env["commandBuffer"]["tabCompletion"]
# Check if this exact delta was processed recently by tab completion
if (tab_state.get("lastProcessedDelta") == delta_text and
tab_state.get("lastProcessedTime")):
# Only suppress if processed within the last 50ms to avoid stale suppression
# Reduced from 100ms to minimize false positives with rapid multi-line updates
time_since_processed = time.time() - tab_state["lastProcessedTime"]
if time_since_processed <= 0.05:
return True
return False
def run(self):
if not self.env["runtime"]["SettingsManager"].get_setting_as_bool(
"speech", "auto_read_incoming"
):
return
# is there something to read?
if not self.env["runtime"]["ScreenManager"].is_delta(ignoreSpace=True):
return
delta_text = self.env["screen"]["new_delta"]
# Skip if tab completion already handled this delta
if self._was_handled_by_tab_completion(delta_text):
return
# Flood protection: skip if too many lines to prevent system slowdown
# Get threshold from settings, default to 500 lines
flood_threshold = self.env["runtime"]["SettingsManager"].get_setting_as_int(
"speech", "flood_protection_lines"
)
if flood_threshold <= 0:
flood_threshold = 500 # Fallback default
line_count = delta_text.count('\n') + 1
if line_count > flood_threshold:
# Too much text - skip to prevent system slowdown
return
# this must be a keyecho or something
# if len(self.env['screen']['new_delta'].strip(' \n\t')) <= 1:
x_move = abs(
self.env["screen"]["new_cursor"]["x"]
- self.env["screen"]["old_cursor"]["x"]
)
y_move = abs(
self.env["screen"]["new_cursor"]["y"]
- self.env["screen"]["old_cursor"]["y"]
)
if (x_move >= 1) and x_move == len(delta_text):
# if len(self.env['screen']['new_delta'].strip(' \n\t0123456789'))
# <= 2:
if "\n" not in delta_text:
return
# print(x_move, y_move, len(self.env['screen']['new_delta']), len(self.env['screen']['newNegativeDelta']))
self.env["runtime"]["OutputManager"].present_text(
delta_text, interrupt=False, flush=False
)
def set_callback(self, callback):
pass