fix(asset-ai): refine mobile viewport and operating query scope
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
shishengliang
2026-09-23 18:49:26 +08:00
parent 5be6240bbf
commit 6de77adb47
11 changed files with 145 additions and 23 deletions
+39 -10
View File
@@ -92,18 +92,47 @@ export default function AssetAssistant({
const page = useRef<HTMLElement>(null);
useLayoutEffect(() => {
const viewport = window.visualViewport;
const mobile = window.matchMedia('(max-width: 767px)');
let frame = 0;
let unlock: (() => void) | undefined;
const updateViewport = () => {
frame = 0;
if (!mobile.matches || (viewport && viewport.scale !== 1)) return;
page.current?.style.setProperty('--aq-viewport-height', `${viewport?.height ?? window.innerHeight}px`);
page.current?.style.setProperty('--aq-viewport-top', `${viewport?.offsetTop ?? 0}px`);
};
updateViewport();
viewport?.addEventListener('resize', updateViewport);
viewport?.addEventListener('scroll', updateViewport);
window.addEventListener('resize', updateViewport);
const scheduleViewport = () => {
if (!frame) frame = requestAnimationFrame(updateViewport);
};
const syncMobile = () => {
unlock?.();
unlock = undefined;
if (mobile.matches) {
const scrollY = window.scrollY;
const body = document.body;
const previous = body.style.top;
body.style.top = `${-scrollY}px`;
body.classList.add('aq-mobile-open');
unlock = () => {
body.classList.remove('aq-mobile-open');
body.style.top = previous;
window.scrollTo({ top: scrollY, behavior: 'instant' });
};
}
updateViewport();
};
syncMobile();
mobile.addEventListener('change', syncMobile);
viewport?.addEventListener('resize', scheduleViewport);
viewport?.addEventListener('scroll', scheduleViewport);
window.addEventListener('resize', scheduleViewport);
return () => {
viewport?.removeEventListener('resize', updateViewport);
viewport?.removeEventListener('scroll', updateViewport);
window.removeEventListener('resize', updateViewport);
cancelAnimationFrame(frame);
mobile.removeEventListener('change', syncMobile);
viewport?.removeEventListener('resize', scheduleViewport);
viewport?.removeEventListener('scroll', scheduleViewport);
window.removeEventListener('resize', scheduleViewport);
unlock?.();
};
}, []);
const [theme, setTheme] = useState(appearance);
@@ -214,7 +243,7 @@ export default function AssetAssistant({
setActiveResult(undefined);
sessionRef.current = undefined;
setIndependent(true);
composer.current?.focus();
composer.current?.focus({ preventScroll: true });
};
useEffect(
() => () => {
@@ -360,7 +389,7 @@ export default function AssetAssistant({
setTurns([]);
setExpandedTurns(new Set());
setDraft("");
composer.current?.focus();
composer.current?.focus({ preventScroll: true });
};
useEffect(() => {
reset();
@@ -390,7 +419,7 @@ export default function AssetAssistant({
className="aq-nav-active"
onClick={() => {
scroller.current?.scrollTo({ top: 0 });
composer.current?.focus();
composer.current?.focus({ preventScroll: true });
}}
>
<MessageSquare size={16} />