92b60deac0
Da Android 15 (API 35+) l'edge-to-edge e' forzato e adjustResize non ridimensiona piu' la finestra: la tastiera si limita a coprire la BlazorWebView. Con il layout rigido (html overflow:hidden, #app 100vh, page/main height:100% overflow:hidden) nemmeno il browser riesce a portare in vista il campo col focus. - MainActivity: WindowSoftInputMode AdjustResize|StateHidden e listener sugli WindowInsets che applica al content view il padding bottom pari all'inset IME (meno quello delle system bars, gia' coperto da SafeAreaEdges in MainPage), cosi' il 100vh si ricalcola. - main.js: su focusin e visualViewport resize porta il campo attivo al centro con scrollIntoView, necessario per i contenitori scrollabili. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
133 lines
4.4 KiB
JavaScript
133 lines
4.4 KiB
JavaScript
// Funzione goBack
|
|
window.goBack = function () {
|
|
console.log("goBack");
|
|
history.back();
|
|
};
|
|
|
|
// Funzione per monitorare bottom-sheet-container e gestire la navbar
|
|
function monitorBottomSheetClass(mutations) {
|
|
const bottomSheet = document.querySelector(".bottom-sheet-container");
|
|
const navbar = document.querySelector(".animated-navbar");
|
|
|
|
if (!bottomSheet || !navbar) return;
|
|
|
|
mutations.forEach(function (mutation) {
|
|
if (mutation.type === 'attributes' && mutation.attributeName === 'class' && mutation.target === bottomSheet) {
|
|
if (bottomSheet.classList.contains("show")) {
|
|
navbar.classList.remove("show-nav");
|
|
navbar.classList.add("hide-nav");
|
|
console.log("Navbar nascosta (hide-nav)");
|
|
} else {
|
|
navbar.classList.remove("hide-nav");
|
|
navbar.classList.add("show-nav");
|
|
console.log("Navbar mostrata (show-nav)");
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Observer combinato per tutte le funzionalità
|
|
const observer = new MutationObserver((mutations) => {
|
|
// Monitora bottom-sheet-container
|
|
monitorBottomSheetClass(mutations);
|
|
});
|
|
|
|
// Osserva sia i cambiamenti nel DOM che gli attributi
|
|
observer.observe(document.body, {
|
|
childList: true,
|
|
subtree: true,
|
|
attributes: true,
|
|
attributeFilter: ['class']
|
|
});
|
|
|
|
// Sync iniziale per la navbar (nel caso la pagina parte già con .show)
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
const bottomSheet = document.querySelector(".bottom-sheet-container");
|
|
const navbar = document.querySelector(".animated-navbar");
|
|
|
|
if (bottomSheet && navbar) {
|
|
if (bottomSheet.classList.contains("show")) {
|
|
navbar.classList.remove("show-nav");
|
|
navbar.classList.add("hide-nav");
|
|
} else {
|
|
navbar.classList.remove("hide-nav");
|
|
navbar.classList.add("show-nav");
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
(function () {
|
|
// Ascoltiamo l'evento 'mousedown' su tutto il documento
|
|
document.addEventListener('mousedown', function (event) {
|
|
|
|
// Cerca se l'elemento cliccato (o un suo genitore) ha la classe .ripple-container
|
|
const target = event.target.closest('.ripple-container');
|
|
|
|
if (target) {
|
|
createRipple(event, target);
|
|
}
|
|
});
|
|
|
|
function createRipple(event, element) {
|
|
const circle = document.createElement("span");
|
|
const diameter = Math.max(element.clientWidth, element.clientHeight);
|
|
const radius = diameter / 2;
|
|
|
|
const rect = element.getBoundingClientRect();
|
|
|
|
circle.style.width = circle.style.height = `${diameter}px`;
|
|
circle.style.left = `${event.clientX - rect.left - radius}px`;
|
|
circle.style.top = `${event.clientY - rect.top - radius}px`;
|
|
circle.classList.add("ripple");
|
|
|
|
// Rimuovi l'elemento dal DOM alla fine dell'animazione per non intasare la memoria
|
|
const ripple = element.getElementsByClassName("ripple")[0];
|
|
if (ripple) {
|
|
ripple.remove();
|
|
}
|
|
|
|
element.appendChild(circle);
|
|
|
|
// Pulizia automatica dopo 600ms (durata animazione CSS)
|
|
setTimeout(() => {
|
|
circle.remove();
|
|
}, 600);
|
|
}
|
|
})();
|
|
|
|
|
|
// Tastiera: porta il campo attivo dentro l'area visibile.
|
|
// Il layout e' a 100vh con overflow:hidden, quindi quando l'host riduce la
|
|
// WebView per la tastiera il browser non scrolla da solo sul campo col focus.
|
|
(function () {
|
|
const SELECTOR = 'input, textarea, [contenteditable="true"]';
|
|
let pending = null;
|
|
|
|
function scrollFocusedIntoView() {
|
|
const el = document.activeElement;
|
|
if (!el || !el.matches || !el.matches(SELECTOR)) return;
|
|
el.scrollIntoView({block: 'center', behavior: 'smooth'});
|
|
}
|
|
|
|
function schedule() {
|
|
clearTimeout(pending);
|
|
// attende la fine dell'animazione di apertura della tastiera e del relayout
|
|
pending = setTimeout(scrollFocusedIntoView, 300);
|
|
}
|
|
|
|
document.addEventListener('focusin', function (event) {
|
|
if (event.target && event.target.matches && event.target.matches(SELECTOR)) {
|
|
schedule();
|
|
}
|
|
});
|
|
|
|
// Il resize arriva quando la tastiera si apre/chiude o cambia altezza
|
|
// (es. passaggio a tastiera emoji o suggerimenti).
|
|
if (window.visualViewport) {
|
|
window.visualViewport.addEventListener('resize', schedule);
|
|
} else {
|
|
window.addEventListener('resize', schedule);
|
|
}
|
|
})();
|