Potential fixes to progress bar. Better handling of punctuation while reading.
This commit is contained in:
parent
b0ac6e1409
commit
83cb330d34
@ -57,7 +57,7 @@ class command():
|
||||
# Don't control speech - progress monitor is beep-only
|
||||
|
||||
def detectProgress(self, text):
|
||||
if not self.env['runtime']['progressMonitoring']:
|
||||
if not self.env['commandBuffer']['progressMonitoring']:
|
||||
return
|
||||
|
||||
# Skip progress detection if current screen looks like a prompt
|
||||
@ -70,10 +70,10 @@ class command():
|
||||
percentMatch = re.search(r'(\d+(?:\.\d+)?)\s*%', text)
|
||||
if percentMatch:
|
||||
percentage = float(percentMatch.group(1))
|
||||
if percentage != self.env['runtime']['lastProgressValue']:
|
||||
if percentage != self.env['commandBuffer']['lastProgressValue']:
|
||||
self.playProgressTone(percentage)
|
||||
self.env['runtime']['lastProgressValue'] = percentage
|
||||
self.env['runtime']['lastProgressTime'] = currentTime
|
||||
self.env['commandBuffer']['lastProgressValue'] = percentage
|
||||
self.env['commandBuffer']['lastProgressTime'] = currentTime
|
||||
return
|
||||
|
||||
# Pattern 2: Fraction (15/100, 3 of 10, etc.)
|
||||
@ -83,10 +83,10 @@ class command():
|
||||
total = int(fractionMatch.group(2))
|
||||
if total > 0:
|
||||
percentage = (current / total) * 100
|
||||
if percentage != self.env['runtime']['lastProgressValue']:
|
||||
if percentage != self.env['commandBuffer']['lastProgressValue']:
|
||||
self.playProgressTone(percentage)
|
||||
self.env['runtime']['lastProgressValue'] = percentage
|
||||
self.env['runtime']['lastProgressTime'] = currentTime
|
||||
self.env['commandBuffer']['lastProgressValue'] = percentage
|
||||
self.env['commandBuffer']['lastProgressTime'] = currentTime
|
||||
return
|
||||
|
||||
# Pattern 3: Progress bars ([#### ], [====> ], etc.)
|
||||
@ -99,19 +99,19 @@ class command():
|
||||
# Require at least 2 progress chars total and unfilled portion must be spaces/dots
|
||||
if total >= 2 and (not barMatch.group(2) or re.match(r'^[\s\.]*$', barMatch.group(2))):
|
||||
percentage = (filled / total) * 100
|
||||
if percentage != self.env['runtime']['lastProgressValue']:
|
||||
if percentage != self.env['commandBuffer']['lastProgressValue']:
|
||||
self.playProgressTone(percentage)
|
||||
self.env['runtime']['lastProgressValue'] = percentage
|
||||
self.env['runtime']['lastProgressTime'] = currentTime
|
||||
self.env['commandBuffer']['lastProgressValue'] = percentage
|
||||
self.env['commandBuffer']['lastProgressTime'] = currentTime
|
||||
return
|
||||
|
||||
# Pattern 4: Generic activity indicators (Loading..., Working..., etc.)
|
||||
activityPattern = re.search(r'(loading|processing|working|installing|downloading|compiling|building).*\.{2,}', text, re.IGNORECASE)
|
||||
if activityPattern:
|
||||
# Play a steady beep every 2 seconds for ongoing activity
|
||||
if currentTime - self.env['runtime']['lastProgressTime'] >= 2.0:
|
||||
if currentTime - self.env['commandBuffer']['lastProgressTime'] >= 2.0:
|
||||
self.playActivityBeep()
|
||||
self.env['runtime']['lastProgressTime'] = currentTime
|
||||
self.env['commandBuffer']['lastProgressTime'] = currentTime
|
||||
|
||||
def playProgressTone(self, percentage):
|
||||
# Map 0-100% to 400-1200Hz frequency range
|
||||
|
@ -22,7 +22,7 @@ class command():
|
||||
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \
|
||||
char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
|
||||
char_utils.presentCharForReview(self.env, currChar, interrupt=True, announceCapital=True, flush=False)
|
||||
# is has attribute it enabled?
|
||||
if self.env['runtime']['settingsManager'].getSettingAsBool('general', 'hasAttributes'):
|
||||
cursorPos = self.env['screen']['newCursorReview']
|
||||
|
@ -28,7 +28,7 @@ class command():
|
||||
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], currChar = \
|
||||
char_utils.getCurrentChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(currChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
|
||||
char_utils.presentCharForReview(self.env, currChar, interrupt=True, announceCapital=True, flush=False)
|
||||
self.env['runtime']['outputManager'].presentText(_("first character in line indent {0}").format(str(len(currLine) - len(currLine.lstrip()))), interrupt=False)
|
||||
|
||||
def setCallback(self, callback):
|
||||
|
@ -22,7 +22,7 @@ class command():
|
||||
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], lastChar = \
|
||||
char_utils.getLastCharInLine(self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(lastChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
|
||||
char_utils.presentCharForReview(self.env, lastChar, interrupt=True, announceCapital=True, flush=False)
|
||||
self.env['runtime']['outputManager'].presentText(_("last character in line"), interrupt=False)
|
||||
|
||||
def setCallback(self, callback):
|
||||
|
@ -21,7 +21,7 @@ class command():
|
||||
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], nextChar, endOfScreen, lineBreak = \
|
||||
char_utils.getNextChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(nextChar, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
|
||||
char_utils.presentCharForReview(self.env, nextChar, interrupt=True, announceCapital=True, flush=False)
|
||||
if endOfScreen:
|
||||
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'):
|
||||
self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen')
|
||||
|
@ -24,7 +24,7 @@ class command():
|
||||
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], prevChar, endOfScreen, lineBreak = \
|
||||
char_utils.getPrevChar(self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(prevChar, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
|
||||
char_utils.presentCharForReview(self.env, prevChar, interrupt=True, announceCapital=True, flush=False)
|
||||
if endOfScreen:
|
||||
if self.env['runtime']['settingsManager'].getSettingAsBool('review', 'endOfScreen'):
|
||||
self.env['runtime']['outputManager'].presentText(_('end of screen'), interrupt=True, soundIcon='EndOfScreen')
|
||||
|
@ -22,7 +22,7 @@ class command():
|
||||
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], lastChar = \
|
||||
char_utils.getLastCharInLine(self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(lastChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
|
||||
char_utils.presentCharForReview(self.env, lastChar, interrupt=True, announceCapital=True, flush=False)
|
||||
self.env['runtime']['outputManager'].presentText(_("first character in screen"), interrupt=False)
|
||||
|
||||
def setCallback(self, callback):
|
||||
|
@ -22,7 +22,7 @@ class command():
|
||||
self.env['screen']['newCursorReview']['x'], self.env['screen']['newCursorReview']['y'], lastChar = \
|
||||
char_utils.getLastCharInLine(self.env['screen']['newCursorReview']['y'], self.env['screen']['newContentText'])
|
||||
|
||||
self.env['runtime']['outputManager'].presentText(lastChar ,interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
|
||||
char_utils.presentCharForReview(self.env, lastChar, interrupt=True, announceCapital=True, flush=False)
|
||||
self.env['runtime']['outputManager'].presentText(_("last character in screen"), interrupt=False)
|
||||
|
||||
def setCallback(self, callback):
|
||||
|
@ -5,6 +5,7 @@
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
from fenrirscreenreader.utils import char_utils
|
||||
from fenrirscreenreader.utils import word_utils
|
||||
|
||||
class command():
|
||||
def __init__(self):
|
||||
@ -43,7 +44,13 @@ class command():
|
||||
if self.env['screen']['newCursor']['x'] == x:
|
||||
return
|
||||
x, y, currChar = char_utils.getCurrentChar(self.env['screen']['newCursor']['x'], self.env['screen']['newCursor']['y'], self.env['screen']['newContentText'])
|
||||
if not currChar.isspace():
|
||||
if currChar.isspace():
|
||||
# Only announce spaces during pure navigation (arrow keys)
|
||||
# Check if this is really navigation by looking at input history
|
||||
if (self.env['runtime']['inputManager'].getShortcutType() in ['KEY'] and
|
||||
self.env['runtime']['inputManager'].getLastDeepestInput()[0] in ['KEY_LEFT', 'KEY_RIGHT', 'KEY_UP', 'KEY_DOWN']):
|
||||
char_utils.presentCharForReview(self.env, currChar, interrupt=True, announceCapital=True, flush=False)
|
||||
else:
|
||||
self.env['runtime']['outputManager'].presentText(currChar, interrupt=True, ignorePunctuation=True, announceCapital=True, flush=False)
|
||||
def setCallback(self, callback):
|
||||
pass
|
||||
|
@ -23,8 +23,11 @@ class command():
|
||||
# Only run if progress monitoring is enabled
|
||||
try:
|
||||
if 'progressMonitoring' in self.env['commandBuffer'] and self.env['commandBuffer']['progressMonitoring']:
|
||||
# Check if current line is a prompt - if so, reset progress state
|
||||
if self.isCurrentLinePrompt():
|
||||
self.resetProgressState()
|
||||
# Only check new incoming text (newDelta), but filter out screen changes
|
||||
if self.env['screen']['newDelta'] and self.isRealProgressUpdate():
|
||||
elif self.env['screen']['newDelta'] and self.isRealProgressUpdate():
|
||||
self.detectProgress(self.env['screen']['newDelta'])
|
||||
except Exception as e:
|
||||
# Silently ignore errors to avoid disrupting normal operation
|
||||
@ -55,6 +58,12 @@ class command():
|
||||
|
||||
return True
|
||||
|
||||
def resetProgressState(self):
|
||||
"""Reset progress state when a prompt is detected, allowing new progress operations to start fresh"""
|
||||
self.env['runtime']['debug'].writeDebugOut("Resetting progress state due to prompt detection", debug.debugLevel.INFO)
|
||||
self.env['commandBuffer']['lastProgressValue'] = -1
|
||||
self.env['commandBuffer']['lastProgressTime'] = 0
|
||||
|
||||
def detectProgress(self, text):
|
||||
import re
|
||||
import time
|
||||
|
@ -4,5 +4,5 @@
|
||||
# Fenrir TTY screen reader
|
||||
# By Chrys, Storm Dragon, and contributers.
|
||||
|
||||
version = "2025.06.09"
|
||||
version = "2025.06.10"
|
||||
codeName = "testing"
|
||||
|
@ -120,3 +120,14 @@ def getPhonetic(currChar):
|
||||
except:
|
||||
return currChar
|
||||
|
||||
def presentCharForReview(env, char, interrupt=True, announceCapital=True, flush=False):
|
||||
"""Present a character for explicit review commands only"""
|
||||
if char == ' ':
|
||||
if ' ' in env['punctuation']['PUNCTDICT']:
|
||||
announceChar = env['punctuation']['PUNCTDICT'][' ']
|
||||
else:
|
||||
announceChar = 'space'
|
||||
env['runtime']['outputManager'].presentText(announceChar, interrupt=interrupt, flush=flush)
|
||||
else:
|
||||
env['runtime']['outputManager'].presentText(char, interrupt=interrupt, ignorePunctuation=True, announceCapital=announceCapital, flush=flush)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user