修复手机键盘弹出时页面位移与焦点跳转
This commit is contained in:
+46
-11
@@ -6,6 +6,11 @@ const sendBtn = document.getElementById("send-button");
|
||||
const uploadBtn = document.getElementById("upload-btn");
|
||||
const uploadInput = document.getElementById("upload-input");
|
||||
const composerStatus = document.getElementById("composer-status");
|
||||
function focusComposer(force){
|
||||
if(force || !isNarrow() || document.activeElement === inputDom){
|
||||
inputDom.focus({preventScroll:true});
|
||||
}
|
||||
}
|
||||
let uploadPending = false;
|
||||
let uploadVersion = 0;
|
||||
let uploadController = null;
|
||||
@@ -121,12 +126,12 @@ uploadInput.onchange = function(){
|
||||
remove.className = "attachment-remove";
|
||||
remove.textContent = "×";
|
||||
remove.setAttribute("aria-label", t("removeAttachment"));
|
||||
remove.onclick = function(){ clearAttachment(); inputDom.focus(); };
|
||||
remove.onclick = function(){ clearAttachment(); focusComposer(true); };
|
||||
prev.append(copy, remove);
|
||||
var area = document.querySelector(".input-area");
|
||||
area.before(prev);
|
||||
setComposerStatus("");
|
||||
inputDom.focus();
|
||||
focusComposer();
|
||||
}
|
||||
})
|
||||
.catch(function(error){
|
||||
@@ -1140,7 +1145,7 @@ async function returnToAI(){
|
||||
stopHumanMode();
|
||||
setComposerStatus('');
|
||||
addMsg(t('humanClosed'), false);
|
||||
inputDom.focus();
|
||||
focusComposer();
|
||||
}catch(error){
|
||||
if(version === conversationVersion) setComposerStatus(t('humanReturnFailed'), true);
|
||||
}finally{
|
||||
@@ -1166,7 +1171,7 @@ async function sendHumanMessage(content){
|
||||
if(inputDom.value === draft){ inputDom.value = ''; autoGrow(); }
|
||||
if(window.__pendingImg === attachment) clearAttachment();
|
||||
setComposerStatus(t(humanStatus === 'active' ? 'humanSent' : 'humanWaiting'));
|
||||
inputDom.focus();
|
||||
focusComposer();
|
||||
return true;
|
||||
}catch(error){
|
||||
if(version !== conversationVersion || humanSendingToken !== token) return;
|
||||
@@ -1471,7 +1476,7 @@ async function doSend(retryText){
|
||||
var tag = window.__pendingTag || "[图片]";
|
||||
const draft = inputDom.value, attachmentVersion = uploadVersion;
|
||||
if(!sendWord && !imgUrl){
|
||||
inputDom.focus();
|
||||
focusComposer(true);
|
||||
return;
|
||||
}
|
||||
if(uploadPending){ setComposerStatus(t("uploading")); return; }
|
||||
@@ -1504,7 +1509,7 @@ async function doSend(retryText){
|
||||
addMsg(fullContent, true);
|
||||
if(inputDom.value === draft){ inputDom.value = ""; autoGrow(); }
|
||||
if(attachmentVersion === uploadVersion) clearAttachment();
|
||||
inputDom.focus();
|
||||
focusComposer();
|
||||
}
|
||||
|
||||
const aiBubble = addMsg(t("thinking"), false);
|
||||
@@ -1537,7 +1542,6 @@ async function doSend(retryText){
|
||||
setBusy(false);
|
||||
aiBubble.classList.remove("typing");
|
||||
if(activeBubble === aiBubble) activeBubble = null;
|
||||
inputDom.focus();
|
||||
|
||||
let raw = aiBubble.dataset.raw || "";
|
||||
// 模型有时会把卡片标记原样输出,这里兜底转成时间轴
|
||||
@@ -1719,7 +1723,10 @@ function autoGrow(){
|
||||
return;
|
||||
}
|
||||
inputDom.style.height = "auto";
|
||||
inputDom.style.height = Math.min(inputDom.scrollHeight, 140) + "px";
|
||||
const viewport = window.visualViewport;
|
||||
const height = viewport && viewport.scale === 1 ? viewport.height : window.innerHeight;
|
||||
const limit = isNarrow() && height > 0 ? Math.min(140, Math.max(44, Math.floor(height / 4))) : 140;
|
||||
inputDom.style.height = Math.min(inputDom.scrollHeight, limit) + "px";
|
||||
}
|
||||
inputDom.addEventListener("input", autoGrow);
|
||||
|
||||
@@ -1777,12 +1784,30 @@ renderSidebar();
|
||||
|
||||
function syncChatViewport(){
|
||||
const viewport = window.visualViewport;
|
||||
chatContainer.style.height = viewport && isNarrow() && viewport.scale === 1
|
||||
? Math.round(viewport.height) + 'px' : '';
|
||||
const narrow = isNarrow();
|
||||
const unzoomed = !viewport || Math.abs(viewport.scale - 1) < 0.01;
|
||||
if(narrow && unzoomed){
|
||||
const height = viewport ? viewport.height : window.innerHeight;
|
||||
if(Number.isFinite(height) && height > 0){
|
||||
chatContainer.style.height = Math.round(height) + 'px';
|
||||
// Keyboard focus may pan the visual viewport without changing its height.
|
||||
chatContainer.style.top = Math.max(0, Math.round(viewport && viewport.offsetTop || 0)) + 'px';
|
||||
}
|
||||
}else{
|
||||
chatContainer.style.height = '';
|
||||
chatContainer.style.top = '';
|
||||
}
|
||||
chatContainer.classList.toggle('is-composing', narrow && document.activeElement === inputDom);
|
||||
autoGrow();
|
||||
if(!chatDom.querySelector('.ai-welcome-card')) scrollChatToEnd();
|
||||
updateToBottom();
|
||||
}
|
||||
let viewportSyncQueued = false;
|
||||
function scheduleChatViewport(){
|
||||
if(viewportSyncQueued) return;
|
||||
viewportSyncQueued = true;
|
||||
requestAnimationFrame(function(){ viewportSyncQueued = false; syncChatViewport(); });
|
||||
}
|
||||
|
||||
toggleBtn.onclick = function(){
|
||||
sideOpen = !sideOpen;
|
||||
@@ -1810,7 +1835,17 @@ window.addEventListener("resize", function(){
|
||||
renderSidebar();
|
||||
syncChatViewport();
|
||||
});
|
||||
if(window.visualViewport) window.visualViewport.addEventListener('resize', syncChatViewport);
|
||||
if(window.visualViewport){
|
||||
window.visualViewport.addEventListener('resize', scheduleChatViewport);
|
||||
window.visualViewport.addEventListener('scroll', scheduleChatViewport);
|
||||
}
|
||||
window.addEventListener('pageshow', scheduleChatViewport);
|
||||
inputDom.addEventListener('focus', scheduleChatViewport);
|
||||
inputDom.addEventListener('blur', scheduleChatViewport);
|
||||
// Keep an already open keyboard while tapping Send; keyboard navigation is unchanged.
|
||||
sendBtn.addEventListener('pointerdown', function(event){
|
||||
if(event.button === 0 && document.activeElement === inputDom) event.preventDefault();
|
||||
});
|
||||
syncChatViewport();
|
||||
|
||||
voiceInput = ChatVoice.create({
|
||||
|
||||
+1
-1
@@ -168,7 +168,7 @@ var ChatVoice = {
|
||||
toggle.onclick = function(){
|
||||
if(!mode && !supported()) return;
|
||||
setMode(!mode);
|
||||
if(!mode) input.focus();
|
||||
if(!mode) input.focus({preventScroll:true});
|
||||
};
|
||||
if(window.PointerEvent){
|
||||
hold.addEventListener('pointerdown', function(event){
|
||||
|
||||
Reference in New Issue
Block a user