mirror of
https://github.com/AstrBotDevs/AstrBot
synced 2026-07-15 17:30:13 +08:00
fix: resolve mobile chat input freeze and multiline attachment button alignment (#9202)
* fix: resolve mobile chat input freeze caused by autoResize oscillation
The autoResize() function in ChatInput.vue used minHeight + 8 as the
threshold to decide whether to switch from multi-line (textarea) back
to single-line (input). On mobile viewports (max-width: 768px), the
textarea's 2-line scrollHeight is below minHeight + 8 due to smaller
line-height and padding, causing an infinite oscillation loop between
<input> and <textarea> that freezes the browser.
Fix: compute the actual single-line content height from
getComputedStyle (line-height + vertical padding) and use that as the
wrapping threshold instead of the hardcoded minHeight + 8 offset.
Also temporarily set min-height to 0 during scrollHeight measurement
to avoid the CSS min-height: 52px inflating the value.
* fix: align mobile multiline attachment button to the left
The mobile multiline grid used a 2-column layout (1fr auto) with
'left right' areas, causing the left actions area to span the full
remaining width and centering the + button via justify-content: center.
Switch to the same 3-column layout (auto 1fr auto) with 'left . right'
areas used on desktop, so the + button sits at the left edge.
* fix: use !important to override min-height during scrollHeight measurement
el.style.minHeight = '0' cannot override the CSS min-height: 52px
!important rule, leaving scrollHeight inflated and preventing the
textarea from switching back to single-line for short text.
Use setProperty('min-height', '0', 'important') to force the override,
and removeProperty to restore. Also add a fontSize * 1.2 fallback when
getComputedStyle returns 'normal' for line-height, so the threshold is
always computable.
This commit is contained in:
@@ -656,9 +656,19 @@ function autoResize() {
|
||||
return;
|
||||
}
|
||||
el.style.height = "auto";
|
||||
el.style.setProperty("min-height", "0", "important");
|
||||
const measuredHeight = el.scrollHeight;
|
||||
el.style.removeProperty("min-height");
|
||||
const computed = getComputedStyle(el);
|
||||
let lineHeight = parseFloat(computed.lineHeight);
|
||||
if (!Number.isFinite(lineHeight)) {
|
||||
lineHeight = parseFloat(computed.fontSize) * 1.2;
|
||||
}
|
||||
const paddingVertical =
|
||||
parseFloat(computed.paddingTop) + parseFloat(computed.paddingBottom);
|
||||
const shouldUseMultiline =
|
||||
localPrompt.value.includes("\n") || measuredHeight > minHeight + 8;
|
||||
localPrompt.value.includes("\n") ||
|
||||
measuredHeight > lineHeight + paddingVertical + 0.5;
|
||||
if (inputIsMultiline.value !== shouldUseMultiline) {
|
||||
const cursor = el.selectionStart ?? localPrompt.value.length;
|
||||
inputIsMultiline.value = shouldUseMultiline;
|
||||
@@ -1624,10 +1634,10 @@ defineExpose({
|
||||
}
|
||||
|
||||
.input-container.is-multiline .composer-row {
|
||||
grid-template-columns: minmax(0, 1fr) auto;
|
||||
grid-template-columns: auto minmax(0, 1fr) auto;
|
||||
grid-template-areas:
|
||||
"field field"
|
||||
"left right";
|
||||
"field field field"
|
||||
"left . right";
|
||||
min-height: auto;
|
||||
row-gap: 4px;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user