Match Ctrl+Arrow word jumps and improve cursor speech
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
// Maintainer-controlled web client version.
|
// Maintainer-controlled web client version.
|
||||||
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
// Format: YYYY.MM.DD Rn (example: 2026.02.20 R2)
|
||||||
window.CHGRID_WEB_VERSION = "2026.02.21 R93";
|
window.CHGRID_WEB_VERSION = "2026.02.21 R94";
|
||||||
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
|
// Optional display timezone for timestamps. Falls back to America/Detroit if unset/invalid.
|
||||||
window.CHGRID_TIME_ZONE = "America/Detroit";
|
window.CHGRID_TIME_ZONE = "America/Detroit";
|
||||||
|
|||||||
@@ -600,20 +600,49 @@ function mapTextInputKey(code: string, key: string): string {
|
|||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isWordCharacter(ch: string): boolean {
|
||||||
|
return /[A-Za-z0-9_]/.test(ch);
|
||||||
|
}
|
||||||
|
|
||||||
function moveCursorWordLeft(text: string, cursorPos: number): number {
|
function moveCursorWordLeft(text: string, cursorPos: number): number {
|
||||||
let pos = cursorPos;
|
if (cursorPos <= 0) return 0;
|
||||||
while (pos > 0 && /\s/.test(text[pos - 1])) pos -= 1;
|
let pos = cursorPos - 1;
|
||||||
while (pos > 0 && !/\s/.test(text[pos - 1])) pos -= 1;
|
while (pos > 0 && !isWordCharacter(text[pos])) pos -= 1;
|
||||||
|
while (pos > 0 && isWordCharacter(text[pos - 1])) pos -= 1;
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveCursorWordRight(text: string, cursorPos: number): number {
|
function moveCursorWordRight(text: string, cursorPos: number): number {
|
||||||
let pos = cursorPos;
|
let pos = cursorPos;
|
||||||
while (pos < text.length && /\s/.test(text[pos])) pos += 1;
|
while (pos < text.length && isWordCharacter(text[pos])) pos += 1;
|
||||||
while (pos < text.length && !/\s/.test(text[pos])) pos += 1;
|
while (pos < text.length && !isWordCharacter(text[pos])) pos += 1;
|
||||||
return pos;
|
return pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function wordAtCursor(text: string, cursorPos: number): string | null {
|
||||||
|
if (cursorPos < 0 || cursorPos >= text.length || !isWordCharacter(text[cursorPos])) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
let start = cursorPos;
|
||||||
|
while (start > 0 && isWordCharacter(text[start - 1])) start -= 1;
|
||||||
|
let end = cursorPos + 1;
|
||||||
|
while (end < text.length && isWordCharacter(text[end])) end += 1;
|
||||||
|
return text.slice(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
function announceCursorWordOrCharacter(text: string, cursorPos: number): void {
|
||||||
|
if (cursorPos === text.length) {
|
||||||
|
updateStatus('space');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const word = wordAtCursor(text, cursorPos);
|
||||||
|
if (word) {
|
||||||
|
updateStatus(word);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
announceCursorCharacter(text, cursorPos);
|
||||||
|
}
|
||||||
|
|
||||||
function applyTextInputEdit(code: string, key: string, maxLength: number, ctrlKey = false, allowReplaceOnNextType = false): void {
|
function applyTextInputEdit(code: string, key: string, maxLength: number, ctrlKey = false, allowReplaceOnNextType = false): void {
|
||||||
if (ctrlKey && code === 'KeyA') {
|
if (ctrlKey && code === 'KeyA') {
|
||||||
replaceTextOnNextType = true;
|
replaceTextOnNextType = true;
|
||||||
@@ -623,12 +652,12 @@ function applyTextInputEdit(code: string, key: string, maxLength: number, ctrlKe
|
|||||||
}
|
}
|
||||||
if (ctrlKey && code === 'ArrowLeft') {
|
if (ctrlKey && code === 'ArrowLeft') {
|
||||||
state.cursorPos = moveCursorWordLeft(state.nicknameInput, state.cursorPos);
|
state.cursorPos = moveCursorWordLeft(state.nicknameInput, state.cursorPos);
|
||||||
announceCursorCharacter(state.nicknameInput, state.cursorPos);
|
announceCursorWordOrCharacter(state.nicknameInput, state.cursorPos);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (ctrlKey && code === 'ArrowRight') {
|
if (ctrlKey && code === 'ArrowRight') {
|
||||||
state.cursorPos = moveCursorWordRight(state.nicknameInput, state.cursorPos);
|
state.cursorPos = moveCursorWordRight(state.nicknameInput, state.cursorPos);
|
||||||
announceCursorCharacter(state.nicknameInput, state.cursorPos);
|
announceCursorWordOrCharacter(state.nicknameInput, state.cursorPos);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -713,7 +742,11 @@ function getItemPropertyValue(item: WorldItem, key: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function announceCursorCharacter(text: string, cursorPos: number): void {
|
function announceCursorCharacter(text: string, cursorPos: number): void {
|
||||||
if (cursorPos < 0 || cursorPos >= text.length || text.length === 0) {
|
if (cursorPos < 0 || cursorPos > text.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (cursorPos === text.length) {
|
||||||
|
updateStatus('space');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
updateStatus(describeCharacter(text[cursorPos]));
|
updateStatus(describeCharacter(text[cursorPos]));
|
||||||
|
|||||||
Reference in New Issue
Block a user