Skip to content

Commit 4c6649a

Browse files
committed
- improved chat screen when keyboard is displayed on iOS
- improved scroll to bottom
1 parent 227daec commit 4c6649a

File tree

4 files changed

+88
-37
lines changed

4 files changed

+88
-37
lines changed

Spixi/MauiProgram.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ public static MauiApp CreateMauiApp()
2424
//handlers.AddHandler(typeof(WebView), typeof(Spixi.Platforms.Android.Renderers.MyWebViewHandler));
2525
handlers.AddCompatibilityRenderer(typeof(WebView), typeof(Spixi.Platforms.Android.Renderers.SpixiWebviewRenderer2));
2626
#endif
27-
27+
#if IOS
28+
handlers.AddHandler(typeof(WebView), typeof(Spixi.Platforms.iOS.iOSWebViewHandler));
29+
#endif
2830
});
2931

3032
return builder.Build();

Spixi/Meta/Config.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ public class Config
3333
public static readonly int packetDataSize = 102400; // 100 Kb per packet for file transfers
3434
public static readonly long packetRequestTimeout = 60; // Time in seconds to re-request packets
3535

36-
public static readonly string version = "spixi-0.9.9-rc"; // Spixi version
36+
public static readonly string version = "spixi-0.9.9-rc2"; // Spixi version
3737

3838
public static readonly string checkVersionUrl = "https://resources.ixian.io/spixi-update.txt";
3939
public static readonly int checkVersionSeconds = 1 * 60 * 60; // 1 hour
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
using Microsoft.Maui.Handlers;
2+
using UIKit;
3+
using WebKit;
4+
5+
namespace Spixi.Platforms.iOS
6+
{
7+
public class iOSWebViewHandler : WebViewHandler
8+
{
9+
protected override void ConnectHandler(WKWebView platformView)
10+
{
11+
base.ConnectHandler(platformView);
12+
13+
platformView.ScrollView.ContentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentBehavior.Never;
14+
platformView.ScrollView.ScrollEnabled = false;
15+
platformView.ScrollView.Bounces = false;
16+
}
17+
}
18+
}

Spixi/Resources/Raw/html/js/chat.js

Lines changed: 66 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ var userAddress = "";
1313

1414
const attachBar = document.getElementById("attach-bar");
1515

16+
const messagesEl = document.getElementById("messages");
17+
const chatHolderEl = document.getElementById("chatholder");
18+
const wrapEl = document.getElementById("wrap");
19+
1620
function onChatScreenLoad() {
1721
document.getElementById("chat_input").focus();
1822

@@ -103,9 +107,9 @@ function setBotMode(bot, cost, costText, admin, botDescription, notificationsStr
103107
document.getElementsByClassName("spixi-channel-bar")[0].style.display = "table";
104108

105109
if (isPaid) {
106-
document.getElementById("messages").style.height = "calc(100vh - 175px)";
110+
messagesEl.style.height = "calc(100vh - 175px)";
107111
} else {
108-
document.getElementById("messages").style.height = "calc(100vh - 150px)";
112+
messagesEl.style.height = "calc(100vh - 150px)";
109113
}
110114

111115
} else {
@@ -159,6 +163,11 @@ function setInitialStickyDate() {
159163
}
160164

161165
function onChatScreenLoaded() {
166+
debouncedScrollToBottom();
167+
if (SL_Platform == "Xamarin-iOS") {
168+
debouncedIOSFixer();
169+
}
170+
162171
document.getElementById("chat_input").focus();
163172
updateChatInputPlaceholder();
164173

@@ -328,9 +337,8 @@ var chatInput = document.getElementById("chat_input");
328337

329338
function scrollToBottom() {
330339
if (shouldScroll()) {
331-
var messagesDiv = document.getElementById('messages');
332340
requestAnimationFrame(function () {
333-
messagesDiv.scrollTop = messagesDiv.scrollHeight;
341+
messagesEl.scrollTop = messagesEl.scrollHeight;
334342
});
335343
}
336344
}
@@ -343,12 +351,12 @@ $("#chat_input").focus(function (event) {
343351
if (shouldScroll()) {
344352
setTimeout(function () {
345353
//document.getElementById("chatholder").scrollIntoView(false);
346-
var messagesDiv = document.getElementById('messages');
347-
messagesDiv.scrollTop = messagesDiv.scrollHeight;
354+
var messagesEl = document.getElementById('messages');
355+
messagesEl.scrollTop = messagesEl.scrollHeight;
348356
// Hack for slow devices
349357
setTimeout(function () {
350358
//document.getElementById("chatholder").scrollIntoView(false);
351-
messagesDiv.scrollTop = messagesDiv.scrollHeight;
359+
messagesEl.scrollTop = messagesEl.scrollHeight;
352360
}, 800);
353361
}, 200);
354362
}*/
@@ -401,9 +409,6 @@ function clearInput() {
401409
document.getElementById("chat_send").className = "chatbar-sendbutton";
402410
}
403411

404-
var messagesEl = document.getElementById("messages");
405-
var chatHolderEl = document.getElementById("chatholder");
406-
407412
let scrollTimeout;
408413

409414
messagesEl.addEventListener("scroll", () => {
@@ -463,7 +468,6 @@ function addReactions(id, reactions) {
463468
reactionsEl.parentNode.removeChild(reactionsEl);
464469
}
465470

466-
const messagesEl = document.getElementById("messages");
467471
if (messagesEl) {
468472
messagesEl.scrollTop = messagesEl.scrollHeight;
469473
}
@@ -702,7 +706,6 @@ function addText(id, address, nick, avatar, text, time, className) {
702706

703707
// TODO: optimize and merge this function with addText
704708
function adjustLastestBubbles() {
705-
var messagesEl = document.getElementById("messages");
706709
var bubbles = messagesEl.querySelectorAll(".spixi-bubble");
707710

708711
if (bubbles.length < 2) {
@@ -868,7 +871,7 @@ function addCall(id, message, declined, time) {
868871

869872

870873
if (append) {
871-
document.getElementById("messages").appendChild(bubbleEl);
874+
messagesEl.appendChild(bubbleEl);
872875
}
873876

874877
scrollToBottom();
@@ -1777,40 +1780,68 @@ function getCaretPosition(editableDiv) {
17771780
}
17781781

17791782
// Fix for iOS toolbar offscreen issue when soft keyboard is shown
1780-
var initialOffset = window.outerHeight - window.innerHeight;
1781-
var msgHeight = document.getElementById("messages").style.height;
1783+
const initialOffset = window.outerHeight - window.innerHeight;
1784+
let updatedOffset = initialOffset;
1785+
let msgHeight = messagesEl.style.height || (window.innerHeight - 120) + "px";
17821786

1783-
function iosFixer() {
1784-
var newOffset = window.outerHeight - window.innerHeight;
1787+
function iosFixer(overshoot = 0) {
1788+
const newOffset = window.outerHeight - window.innerHeight;
17851789

1786-
if (newOffset > initialOffset) {
1787-
var diff = newOffset - initialOffset;
1788-
document.getElementById("wrap").style.maxHeight = "${window.innerHeight}px";
1789-
document.getElementById("wrap").style.top = diff + "px";
1790-
msgHeight = document.getElementById("messages").style.height;
1790+
if (newOffset >= updatedOffset) {
1791+
const diff = newOffset - initialOffset;
1792+
requestAnimationFrame(function () {
1793+
wrapEl.style.transition = "top 0.20s ease-out";
1794+
messagesEl.style.transition = "height 0.20s ease-out";
17911795

1792-
document.getElementById("messages").style.height = (window.innerHeight - 120) + "px"; // ${newDiff}px";// (msgHeight - diff + 20) + "px";
1796+
wrapEl.style.top = `${diff + overshoot}px`;
1797+
messagesEl.style.height = `${window.innerHeight - overshoot - 120}px`;
1798+
debouncedScrollToBottom();
1799+
});
1800+
} else if (newOffset < updatedOffset && wrapEl.style.top != "0px") {
1801+
requestAnimationFrame(function () {
1802+
wrapEl.style.transition = "top 0.20s ease-out";
1803+
messagesEl.style.transition = "height 0.20s ease-out";
17931804

1794-
scrollToBottom();
1795-
} else if (newOffset < initialOffset) {
1796-
document.getElementById("wrap").style.maxHeight = '';
1797-
document.getElementById("wrap").style.top = "0px";
1798-
document.getElementById("messages").style.height = msgHeight;
1805+
wrapEl.style.top = "0px";
1806+
messagesEl.style.height = msgHeight;
1807+
debouncedScrollToBottom();
1808+
});
17991809
}
1800-
initialOffset = newOffset;
1810+
updatedOffset = newOffset;
18011811
}
18021812

1813+
const throttle = (fn, delay) => {
1814+
let lastCall = 0;
1815+
return (...args) => {
1816+
const now = Date.now();
1817+
if (now - lastCall >= delay) {
1818+
lastCall = now;
1819+
fn(...args);
1820+
}
1821+
};
1822+
};
1823+
1824+
const debounce = (fn, delay) => {
1825+
let timeout;
1826+
return (...args) => {
1827+
clearTimeout(timeout);
1828+
timeout = setTimeout(() => fn(...args), delay);
1829+
};
1830+
};
1831+
1832+
const debouncedScrollToBottom = debounce(scrollToBottom, 200);
1833+
const debouncedIOSFixer = debounce(iosFixer, 25);
18031834

18041835
// Mobile only logic
18051836
if (SL_Platform != "Xamarin-WPF") {
1806-
18071837
if (SL_Platform == "Xamarin-iOS") {
18081838
window.visualViewport.addEventListener('resize', () => {
1809-
iosFixer();
1839+
debouncedIOSFixer();
1840+
debouncedScrollToBottom();
1841+
});
1842+
} else {
1843+
window.addEventListener('resize', function () {
1844+
debouncedScrollToBottom();
18101845
});
18111846
}
1812-
1813-
window.addEventListener('resize', function () {
1814-
scrollToBottom();
1815-
});
18161847
}

0 commit comments

Comments
 (0)