Fix ui bugs:
All checks were successful
Android Build / publish (push) Successful in 47s
Linux Build / publish (push) Successful in 51s

- keyboard screen glitch
- multi-line messages
- missing styling
This commit is contained in:
olcxja 2026-06-03 00:56:29 +02:00
commit 005d2e2820
6 changed files with 94 additions and 30 deletions

View file

@ -1697,7 +1697,7 @@ document.addEventListener('touchstart', e => {
touchStartY = e.changedTouches[0].screenY;
touchMoved = false;
activeTouchButton = e.target.closest('button, input');
activeTouchButton = e.target.closest('button, input, textarea');
if (activeTouchButton) {
activeTouchButton.classList.add('is-pressed');
}
@ -1728,8 +1728,8 @@ document.addEventListener('touchend', e => {
activeTouchButton.classList.remove('is-pressed');
if (!touchMoved) {
if (activeTouchButton.tagName !== 'INPUT') {
if (document.activeElement && document.activeElement.tagName === 'INPUT') {
if (activeTouchButton.tagName !== 'INPUT' && activeTouchButton.tagName !== 'TEXTAREA') {
if (document.activeElement && document.activeElement.tagName === 'INPUT' && document.activeElement.tagName === 'TEXTAREA') {
document.activeElement.blur();
}
@ -1836,6 +1836,8 @@ async function renderDms(res) {
var currentDmId = null;
var currentDmKey = null; // AES key for encrypting/decrypting messages
var dmUsernameCache = {};
var dmPfpCache = {};
async function openDm(dmId, username, targetId) {
try {
@ -1939,10 +1941,16 @@ async function renderMessages(messages) {
let authorName = "Unknown";
let pfp = "assets/default_avatar.png";
if (msg.author !== "0") {
let fullUsername = await fetchAsync(`${url}/idtoname?id=${msg.author}`);
if (fullUsername && !fullUsername.startsWith("error:")) {
authorName = fullUsername.split(':')[0];
pfp = await getAvatarUrl(msg.author, fullUsername);
if (!dmUsernameCache[msg.author]) {
let fullUsername = await fetchAsync(`${url}/idtoname?id=${msg.author}`);
if (fullUsername && !fullUsername.startsWith("error:")) {
dmUsernameCache[msg.author] = fullUsername;
dmPfpCache[msg.author] = await getAvatarUrl(msg.author, fullUsername);
}
}
if (dmUsernameCache[msg.author]) {
authorName = dmUsernameCache[msg.author].split(':')[0];
pfp = dmPfpCache[msg.author];
}
}
@ -1953,7 +1961,7 @@ async function renderMessages(messages) {
html += `
<div class="chat-message ${extraClass}">
<img src="${showAvatar ? pfp : 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='}" class="chat-message-pfp">
${showAvatar ? `<img src="${pfp}" class="chat-message-pfp">` : `<div style="width: 2.5rem; flex-shrink: 0;"></div>`}
<div class="chat-message-content">
${showAvatar ? `<div class="chat-message-header">
<span class="chat-message-author">${authorName}</span>
@ -1966,8 +1974,21 @@ async function renderMessages(messages) {
}
}
const rem = parseFloat(getComputedStyle(document.documentElement).fontSize);
let wasAtBottom = (container.scrollHeight - container.scrollTop - container.clientHeight) < (1.5 * rem);
if (window.forceScrollToBottom) {
wasAtBottom = true;
window.forceScrollToBottom = false;
}
let oldScrollTop = container.scrollTop;
container.innerHTML = html;
container.scrollTop = container.scrollHeight;
if (wasAtBottom) {
container.scrollTop = container.scrollHeight;
} else {
container.scrollTop = oldScrollTop;
}
}
async function sendMessage() {
@ -1988,6 +2009,9 @@ async function sendMessage() {
};
input.value = "";
input.style.height = '2.5rem';
window.forceScrollToBottom = true;
let res = await fetchEncrypted("dm/message/send", JSON.stringify(msgPayload));
if (res && res.startsWith("error:")) {
@ -2001,6 +2025,16 @@ async function sendMessage() {
}
}
function handleChatInputResize(textarea) {
const rem = parseFloat(getComputedStyle(document.documentElement).fontSize);
textarea.style.transition = 'none';
textarea.style.height = '0rem';
let borderHeight = textarea.offsetHeight - textarea.clientHeight;
textarea.style.height = ((textarea.scrollHeight + borderHeight) / rem) + 'rem';
textarea.offsetHeight; // force reflow
textarea.style.transition = '';
}
function handleChatInputKey(event) {
if (event.key === "Enter" && !event.shiftKey) {
const isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);

View file

@ -134,7 +134,7 @@ var chatScreen = `
<div id="chat-messages" style="flex-grow: 1; overflow-y: auto; padding: 1rem; display: flex; flex-direction: column; gap: 0.5rem;">
</div>
<div style="padding: 1rem; border-top: var(--border-width) solid var(--light-border-color); display: flex; gap: 0.5rem;">
<textarea id="chat-input" class="forminput" style="flex-grow: 1; margin: 0; resize: none; min-height: 2.5rem; max-height: 8rem; padding: 0.5rem;" placeholder="{blah(placeholder.message.input)}" onkeydown="handleChatInputKey(event)"></textarea>
<textarea id="chat-input" class="forminput" style="flex-grow: 1; margin: 0; resize: none; min-height: 2.5rem; max-height: 8rem; padding: 0.5rem;" placeholder="{blah(placeholder.message.input)}" onkeydown="handleChatInputKey(event)" oninput="handleChatInputResize(this)"></textarea>
<button class="submit-button" onclick="sendMessage()" style="margin: 0; padding: 0; aspect-ratio: 1;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="-0.9 -0.5 15.6 16" fill="none" width="1.5rem">
<path stroke="var(--main-bg-color)" stroke-linecap="round" stroke-linejoin="round" d="m3.75 7.5 -1.875 5.625 11.25 -5.625L1.875 1.875l1.875 5.625zm0 0h3.75" stroke-width="1.1"></path>

View file

@ -630,13 +630,10 @@ space{
.chat-message-pfp {
width: 2.5rem;
height: 2.5rem;
border-radius: 0.6rem;
border-radius: 0.65rem;
object-fit: cover;
flex-shrink: 0;
opacity: 0; /* hidden by default for consecutive messages */
}
.chat-message.with-avatar .chat-message-pfp {
opacity: 1;
border: var(--border-width) solid rgba(255, 255, 255, 0.2);
}
.chat-message-content {
display: flex;
@ -664,6 +661,7 @@ space{
.chat-message-text {
line-height: 1.4;
word-break: break-word;
white-space: pre-wrap;
}
@media (hover: hover) {