fix(zen mode): issues when changing tape mode and other caret issues (@NadAlaba) (#5824)

* fix(zen mode): undefined word when changing tape mode during test (@NadAlaba)

* fix(zen mode): shrinking full-width-caret when changing tape mode during test (@NadAlaba)

* fix(zen mode): messed up caret in RTL languages (@NadAlaba)

because of the letter '_' that is added to the beginning of a word
in zen mode, the caret is getting positioned on the 2nd letter.

Also, since lastWordLetter is always undefined (because wordLen is
always 0) offsetHeight and offsetTop are getting the default values
regardless of font characteristics.

* fix caret staying in position in (blind + word tape + zen) mode

* refactor: combine last 2 solutions

* rename parameter
This commit is contained in:
Nad Alaba 2024-09-02 13:10:45 +03:00 committed by GitHub
parent 55496996de
commit 661c138812
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 21 additions and 16 deletions

View file

@ -126,7 +126,8 @@ function hide(clearModalChain = false): void {
clearModalChain,
afterAnimation: async () => {
addCommandlineBackground();
if (ActivePage.get() === "test") {
const isWordsFocused = $("#wordsInput").is(":focus");
if (ActivePage.get() === "test" && !isWordsFocused) {
focusWords();
}
},

View file

@ -49,6 +49,7 @@ function getTargetPositionLeft(
fullWidthCaret: boolean,
isLanguageRightToLeft: boolean,
activeWordElement: HTMLElement,
underscoreAdded: boolean,
currentWordNodeList: NodeListOf<Element>,
fullWidthCaretWidth: number,
wordLen: number,
@ -98,6 +99,8 @@ function getTargetPositionLeft(
}
}
result = activeWordElement.offsetLeft + positionOffsetToWord;
if (underscoreAdded && isLanguageRightToLeft)
result += activeWordElement.offsetWidth;
} else {
const wordsWrapperWidth =
$(document.querySelector("#wordsWrapper") as HTMLElement).width() ?? 0;
@ -129,10 +132,9 @@ export async function updatePosition(noAnim = false): Promise<void> {
Config.caretStyle
);
const wordLen = TestWords.words.getCurrent().length;
let wordLen = TestWords.words.getCurrent().length;
const inputLen = TestInput.input.current.length;
const letterIsInvisibleExtra =
(Config.blindMode || Config.hideExtraLetters) && inputLen > wordLen;
if (Config.mode === "zen") wordLen = inputLen;
const activeWordEl = document?.querySelector("#words .active") as HTMLElement;
//insert temporary character so the caret will work in zen mode
const activeWordEmpty = activeWordEl?.children.length === 0;
@ -153,28 +155,29 @@ export async function updatePosition(noAnim = false): Promise<void> {
| HTMLElement
| undefined;
const spaceWidth = getSpaceWidth(activeWordEl);
const currentLanguage = await JSONData.getCurrentLanguage(Config.language);
const isLanguageRightToLeft = currentLanguage.rightToLeft;
// in blind mode, and hide extra letters, extra letters have zero offsets
// offsetTop and offsetHeight is the same for all visible letters
const letterHeight =
currentLetter?.offsetHeight ||
lastWordLetter?.offsetHeight ||
Config.fontSize * Numbers.convertRemToPixels(1);
const letterPosTop = lastWordLetter?.offsetTop ?? 0;
const letterPosTop =
currentLetter?.offsetTop || lastWordLetter?.offsetTop || 0;
const diff = letterHeight - caret.offsetHeight;
let newTop = activeWordEl.offsetTop + letterPosTop + diff / 2;
if (Config.caretStyle === "underline") {
newTop = activeWordEl.offsetTop + letterPosTop - caret.offsetHeight / 2;
}
let letterWidth = currentLetter?.offsetWidth || spaceWidth;
if (currentLetter?.offsetWidth === 0 && !letterIsInvisibleExtra) {
// other than in extra letters in blind mode, it could be zero
// if current letter is a zero-width character e.g, diacritics)
let letterWidth = currentLetter?.offsetWidth;
if (letterWidth === undefined || activeWordEmpty) {
letterWidth = getSpaceWidth(activeWordEl);
} else if (letterWidth === 0) {
// current letter is a zero-width character e.g, diacritics)
letterWidth = 0;
for (let i = inputLen; i >= 0; i--) {
letterWidth = (currentWordNodeList[i] as HTMLElement)?.offsetWidth;
@ -187,6 +190,7 @@ export async function updatePosition(noAnim = false): Promise<void> {
fullWidthCaret,
isLanguageRightToLeft,
activeWordEl,
activeWordEmpty,
currentWordNodeList,
letterWidth,
wordLen,

View file

@ -422,6 +422,10 @@ export function showWords(): void {
}, 125);
updateWordWrapperClasses();
if (Config.mode === "zen") {
$(document.querySelector(".word") as Element).remove();
}
}
const posUpdateLangList = ["japanese", "chinese", "korean"];
@ -508,7 +512,7 @@ function updateWordsHeight(force = false): void {
CustomText.getLimitValue() !== 0
) {
// overflow-x should not be visible in tape mode, but since showAllLines can't
// be enabled simultaneously with tape mode we don' need to check it's off
// be enabled simultaneously with tape mode we don't need to check it's off
$("#words")
.css("height", "auto")
.css("overflow", "visible clip")
@ -587,10 +591,6 @@ function updateWordsHeight(force = false): void {
);
}, 0);
}
if (Config.mode === "zen") {
$(document.querySelector(".word") as Element).remove();
}
}
export function addWord(word: string): void {