mirror of
https://github.com/open-webui/open-webui.git
synced 2025-12-12 12:25:20 +00:00
fix: fix Safari IME composition bug
This commit is contained in:
parent
0ea421ea20
commit
7b9dc69362
1 changed files with 32 additions and 26 deletions
|
|
@ -417,6 +417,30 @@
|
||||||
let recording = false;
|
let recording = false;
|
||||||
|
|
||||||
let isComposing = false;
|
let isComposing = false;
|
||||||
|
// Safari has a bug where compositionend is not triggered correctly #16615
|
||||||
|
// when using the virtual keyboard on iOS.
|
||||||
|
let compositionEndedAt = -2e8;
|
||||||
|
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
||||||
|
function inOrNearComposition(event: Event) {
|
||||||
|
if (isComposing) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// See https://www.stum.de/2016/06/24/handling-ime-events-in-javascript/.
|
||||||
|
// On Japanese input method editors (IMEs), the Enter key is used to confirm character
|
||||||
|
// selection. On Safari, when Enter is pressed, compositionend and keydown events are
|
||||||
|
// emitted. The keydown event triggers newline insertion, which we don't want.
|
||||||
|
// This method returns true if the keydown event should be ignored.
|
||||||
|
// We only ignore it once, as pressing Enter a second time *should* insert a newline.
|
||||||
|
// Furthermore, the keydown event timestamp must be close to the compositionEndedAt timestamp.
|
||||||
|
// This guards against the case where compositionend is triggered without the keyboard
|
||||||
|
// (e.g. character confirmation may be done with the mouse), and keydown is triggered
|
||||||
|
// afterwards- we wouldn't want to ignore the keydown event in this case.
|
||||||
|
if (isSafari && Math.abs(event.timeStamp - compositionEndedAt) < 500) {
|
||||||
|
compositionEndedAt = -2e8;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
let chatInputContainerElement;
|
let chatInputContainerElement;
|
||||||
let chatInputElement;
|
let chatInputElement;
|
||||||
|
|
@ -1169,19 +1193,9 @@
|
||||||
return res;
|
return res;
|
||||||
}}
|
}}
|
||||||
oncompositionstart={() => (isComposing = true)}
|
oncompositionstart={() => (isComposing = true)}
|
||||||
oncompositionend={() => {
|
oncompositionend={(e) => {
|
||||||
const isSafari = /^((?!chrome|android).)*safari/i.test(
|
compositionEndedAt = e.timeStamp;
|
||||||
navigator.userAgent
|
isComposing = false;
|
||||||
);
|
|
||||||
|
|
||||||
if (isSafari) {
|
|
||||||
// Safari has a bug where compositionend is not triggered correctly #16615
|
|
||||||
// when using the virtual keyboard on iOS.
|
|
||||||
// We use a timeout to ensure that the composition is ended after a short delay.
|
|
||||||
setTimeout(() => (isComposing = false));
|
|
||||||
} else {
|
|
||||||
isComposing = false;
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
on:keydown={async (e) => {
|
on:keydown={async (e) => {
|
||||||
e = e.detail.event;
|
e = e.detail.event;
|
||||||
|
|
@ -1290,7 +1304,7 @@
|
||||||
navigator.msMaxTouchPoints > 0
|
navigator.msMaxTouchPoints > 0
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
if (isComposing) {
|
if (inOrNearComposition(e)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1393,17 +1407,9 @@
|
||||||
command = getCommand();
|
command = getCommand();
|
||||||
}}
|
}}
|
||||||
on:compositionstart={() => (isComposing = true)}
|
on:compositionstart={() => (isComposing = true)}
|
||||||
on:compositionend={() => {
|
oncompositionend={(e) => {
|
||||||
const isSafari = /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
|
compositionEndedAt = e.timeStamp;
|
||||||
|
isComposing = false;
|
||||||
if (isSafari) {
|
|
||||||
// Safari has a bug where compositionend is not triggered correctly #16615
|
|
||||||
// when using the virtual keyboard on iOS.
|
|
||||||
// We use a timeout to ensure that the composition is ended after a short delay.
|
|
||||||
setTimeout(() => (isComposing = false));
|
|
||||||
} else {
|
|
||||||
isComposing = false;
|
|
||||||
}
|
|
||||||
}}
|
}}
|
||||||
on:keydown={async (e) => {
|
on:keydown={async (e) => {
|
||||||
const isCtrlPressed = e.ctrlKey || e.metaKey; // metaKey is for Cmd key on Mac
|
const isCtrlPressed = e.ctrlKey || e.metaKey; // metaKey is for Cmd key on Mac
|
||||||
|
|
@ -1523,7 +1529,7 @@
|
||||||
navigator.msMaxTouchPoints > 0
|
navigator.msMaxTouchPoints > 0
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
if (isComposing) {
|
if (inOrNearComposition(e)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue