94 lines
3.1 KiB
Python
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
|