Fix ui bugs:
- keyboard screen glitch - multi-line messages - missing styling
This commit is contained in:
parent
92edb123f3
commit
005d2e2820
6 changed files with 94 additions and 30 deletions
|
|
@ -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") {
|
||||
if (!dmUsernameCache[msg.author]) {
|
||||
let fullUsername = await fetchAsync(`${url}/idtoname?id=${msg.author}`);
|
||||
if (fullUsername && !fullUsername.startsWith("error:")) {
|
||||
authorName = fullUsername.split(':')[0];
|
||||
pfp = await getAvatarUrl(msg.author, fullUsername);
|
||||
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;
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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") {
|
||||
if (!dmUsernameCache[msg.author]) {
|
||||
let fullUsername = await fetchAsync(`${url}/idtoname?id=${msg.author}`);
|
||||
if (fullUsername && !fullUsername.startsWith("error:")) {
|
||||
authorName = fullUsername.split(':')[0];
|
||||
pfp = await getAvatarUrl(msg.author, fullUsername);
|
||||
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;
|
||||
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue