diff --git a/src/templates/chat.html b/src/templates/chat.html
index f323017..af21582 100644
--- a/src/templates/chat.html
+++ b/src/templates/chat.html
@@ -148,20 +148,32 @@
if (diff > 150) { // Keyboard is likely open
if (messagesWrapper) {
- messagesWrapper.style.paddingBottom = '120px'; // More padding for mobile keyboard
- // Auto-scroll when keyboard opens, with multiple attempts for reliability
- userScrolled = false; // Reset scroll state when keyboard opens
+ messagesWrapper.style.paddingBottom = '140px'; // Even more padding for mobile keyboard
+ // Reset scroll state and aggressively scroll to bottom
+ userScrolled = false;
+
+ // Multiple scroll attempts with increasing delays
setTimeout(() => {
- scrollToBottom(false);
- }, 200);
- // iOS often needs multiple scroll attempts
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 150;
+ }, 100);
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 150;
+ }, 250);
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 150;
+ }, 400);
+
+ // iOS often needs even more attempts
if (isIOS) {
setTimeout(() => {
- messagesWrapper.scrollTop = messagesWrapper.scrollHeight;
- }, 400);
- setTimeout(() => {
- messagesWrapper.scrollTop = messagesWrapper.scrollHeight;
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 200;
}, 600);
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 200;
+ }, 800);
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 200;
+ }, 1000);
}
}
} else {
@@ -170,9 +182,14 @@
// Scroll to bottom when keyboard closes too
setTimeout(() => {
if (!userScrolled) {
- scrollToBottom(false);
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 100;
}
}, 200);
+ setTimeout(() => {
+ if (!userScrolled) {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 100;
+ }
+ }, 400);
}
}
}
@@ -199,9 +216,16 @@
setTimeout(() => {
const messagesWrapper = document.getElementById('messagesWrapper');
if (messagesWrapper) {
- messagesWrapper.scrollTop = messagesWrapper.scrollHeight;
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 200;
}
}, 800);
+ // Additional scroll attempt for stubborn mobile browsers
+ setTimeout(() => {
+ const messagesWrapper = document.getElementById('messagesWrapper');
+ if (messagesWrapper) {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 250;
+ }
+ }, 1200);
}
});
@@ -230,11 +254,27 @@
if (messagesWrapper) {
// On mobile, especially iOS, direct scrollTop assignment is more reliable
if (isMobile) {
- messagesWrapper.scrollTop = messagesWrapper.scrollHeight;
- // Double-check scroll position after a short delay for mobile
+ // Force scroll to absolute bottom with extra padding
+ const targetScroll = messagesWrapper.scrollHeight + 100;
+ messagesWrapper.scrollTop = targetScroll;
+
+ // Multiple aggressive scroll attempts for mobile reliability
setTimeout(() => {
- messagesWrapper.scrollTop = messagesWrapper.scrollHeight;
- }, 100);
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 100;
+ }, 50);
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 100;
+ }, 150);
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 100;
+ }, 300);
+
+ // Final iOS-specific attempt
+ if (isIOS) {
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 200;
+ }, 500);
+ }
} else {
if (smooth) {
messagesWrapper.scrollTo({
@@ -334,11 +374,26 @@
// Only auto-scroll if user hasn't manually scrolled up
if (!userScrolled) {
- // Longer delay for mobile to ensure proper rendering
- const delay = isMobile ? 200 : 50;
- setTimeout(() => {
- scrollToBottom(false); // Always instant scroll on mobile
- }, delay);
+ // Multiple scroll attempts for mobile with extra padding
+ const messagesWrapper = document.getElementById('messagesWrapper');
+ if (messagesWrapper) {
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 150;
+ }, 100);
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 150;
+ }, 250);
+ if (isMobile) {
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 200;
+ }, 400);
+ if (isIOS) {
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 200;
+ }, 600);
+ }
+ }
+ }
}
}
}
@@ -346,19 +401,28 @@
// Force scroll with mobile optimizations
function forceScrollToBottom() {
userScrolled = false;
- const delay = isMobile ? 300 : 100;
- setTimeout(() => {
- scrollToBottom(false);
- // iOS double-check
+ const messagesWrapper = document.getElementById('messagesWrapper');
+ if (messagesWrapper) {
+ // Immediate aggressive scroll
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 150;
+
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 150;
+ }, 100);
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 200;
+ }, 300);
+
+ // Extra attempts for iOS
if (isIOS) {
setTimeout(() => {
- const messagesWrapper = document.getElementById('messagesWrapper');
- if (messagesWrapper) {
- messagesWrapper.scrollTop = messagesWrapper.scrollHeight;
- }
- }, 100);
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 250;
+ }, 500);
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 250;
+ }, 700);
}
- }, delay);
+ }
}
// Mobile-optimized mutation observer
@@ -376,10 +440,20 @@
);
if (hasNewMessage && !userScrolled) {
- const delay = isMobile ? 250 : 50;
- setTimeout(() => {
- scrollToBottom(false); // Instant scroll for reliability
- }, delay);
+ const messagesWrapper = document.getElementById('messagesWrapper');
+ if (messagesWrapper) {
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 150;
+ }, 100);
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 200;
+ }, 300);
+ if (isMobile) {
+ setTimeout(() => {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight + 250;
+ }, 500);
+ }
+ }
}
}
});