mirror of
https://gitgud.io/BondageProjects/Bondage-College.git
synced 2025-04-25 17:59:34 +00:00
Merge branch 'chat-input' into 'master'
MAINT: Rewrite the chat input auto expansion logic and allow the chat reply DOM to take advantage of this See merge request BondageProjects/Bondage-College!5513
This commit is contained in:
commit
6d8edae80d
4 changed files with 104 additions and 71 deletions
BondageClub
|
@ -344,5 +344,5 @@ select:invalid:not(:disabled):not(:read-only) {
|
|||
}
|
||||
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
display: none !important;
|
||||
}
|
||||
|
|
|
@ -58,19 +58,18 @@
|
|||
|
||||
#chat-room-div {
|
||||
--button-size: min(8vh, 4vw);
|
||||
}
|
||||
|
||||
/* Do NOT use min-/max-content for grid rows, as this will cause serious lag related to layour recomputing once the chat log starts to fill up */
|
||||
display: grid;
|
||||
grid-template-rows: 89.6% 10%;
|
||||
gap: 0.4%;
|
||||
#chat-room-div > * {
|
||||
margin-bottom: max(3px, min(0.4vh, 0.2vw));
|
||||
}
|
||||
|
||||
#TextAreaChatLog {
|
||||
background-color: white;
|
||||
border: 1px solid black;
|
||||
word-wrap: break-word;
|
||||
padding: 0 !important;
|
||||
overflow-y: scroll;
|
||||
height: max-content;
|
||||
}
|
||||
|
||||
#chat-room-bot {
|
||||
|
@ -102,25 +101,30 @@
|
|||
border-left: min(0.2vh, 0.1vw) inset black;
|
||||
justify-self: center;
|
||||
}
|
||||
|
||||
#chat-room-reply-indicator-text {
|
||||
color: var(--base-font-color);
|
||||
text-overflow: ellipsis;
|
||||
text-wrap: nowrap;
|
||||
overflow: hidden;
|
||||
flex: 1;
|
||||
line-height: 1.6em;
|
||||
border: min(0.2vh, 0.1vw) solid black;
|
||||
border-right: none;
|
||||
user-select: none
|
||||
user-select: none;
|
||||
border-right: black solid max(3px, min(0.4vh, 0.2vw));
|
||||
padding-left: 4px;
|
||||
}
|
||||
#chat-room-reply-indicator:not(.hidden) {
|
||||
background-color: var(--base-color, #eee);
|
||||
position: absolute;
|
||||
transform: translateY(-105%);
|
||||
width: 100%;
|
||||
|
||||
#chat-room-reply-indicator {
|
||||
background-color: #eee;
|
||||
display: flex;
|
||||
height: 1.6em;
|
||||
}
|
||||
|
||||
#chat-room-reply-indicator-close {
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
||||
#chat-room-reply-indicator-close::before {
|
||||
content: "❌";
|
||||
}
|
||||
|
||||
#InputChat {
|
||||
grid-area: chat-input;
|
||||
min-height: var(--button-size);
|
||||
|
@ -132,15 +136,7 @@
|
|||
border: unset;
|
||||
outline: unset;
|
||||
}
|
||||
#chat-room-reply-indicator-close::before {
|
||||
content: "❌";
|
||||
}
|
||||
#chat-room-reply-indicator-close {
|
||||
background-color: var(--base-color, #eee);
|
||||
border: min(0.2vh, 0.1vw) solid black;
|
||||
cursor: pointer;
|
||||
aspect-ratio: 1;
|
||||
}
|
||||
|
||||
#InputChat:focus {
|
||||
scrollbar-width: auto;
|
||||
}
|
||||
|
@ -317,8 +313,10 @@
|
|||
--base-font-color: #eee;
|
||||
}
|
||||
|
||||
#TextAreaChatLog[data-colortheme="dark"]~#chat-room-bot,
|
||||
#TextAreaChatLog[data-colortheme="dark2"]~#chat-room-bot {
|
||||
#TextAreaChatLog[data-colortheme="dark"] ~ #chat-room-bot,
|
||||
#TextAreaChatLog[data-colortheme="dark2"] ~ #chat-room-bot,
|
||||
#TextAreaChatLog[data-colortheme="dark"] ~ #chat-room-reply-indicator,
|
||||
#TextAreaChatLog[data-colortheme="dark2"] ~ #chat-room-reply-indicator {
|
||||
--button-color: #eee;
|
||||
--base-color: #111;
|
||||
--base-font-color: #eee;
|
||||
|
@ -329,7 +327,7 @@
|
|||
|
||||
#TextAreaChatLog[data-colortheme="dark"]~#chat-room-buttons-div,
|
||||
#TextAreaChatLog[data-colortheme="dark2"]~#chat-room-buttons-div {
|
||||
|
||||
|
||||
border-left: min(0.2vh, 0.1vw) inset rgba(0, 0, 0, 0.25);
|
||||
}
|
||||
|
||||
|
|
|
@ -92,6 +92,12 @@ var ChatRoomChatLengthLabelRect = /** @type {never} */([1764, 970, 120, 82]);
|
|||
*/
|
||||
var ChatRoomDivRect = [1005, 60, 988, 940];
|
||||
|
||||
/**
|
||||
* The last approximate height (_i.e._ {@link HTMLElement.clientHeight} as opposed to {@link DOMRect.height}) of the `InputChat` element.
|
||||
* @type {number}
|
||||
*/
|
||||
let ChatRoomDivInputPrevHeight = NaN;
|
||||
|
||||
var ChatRoomChatHidden = false;
|
||||
/**
|
||||
* The chatroom characters that were drawn in the last frame.
|
||||
|
@ -1153,23 +1159,23 @@ function ChatRoomCreateElement() {
|
|||
attributes: { id: "TextAreaChatLog", role: "log" },
|
||||
classList: ["scroll-box"],
|
||||
},
|
||||
{
|
||||
tag: "div",
|
||||
attributes: {id: "chat-room-reply-indicator"},
|
||||
classList: ["hidden"],
|
||||
children: [
|
||||
{ tag: "span", attributes: { id: "chat-room-reply-indicator-text" }, children: [TextGet("ChatRoomReply")] },
|
||||
ElementButton.Create(
|
||||
"chat-room-reply-indicator-close",
|
||||
ChatRoomMessageReplyStop,
|
||||
{ noStyling: true },
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
tag: "div",
|
||||
attributes: { id: "chat-room-bot" },
|
||||
children: [
|
||||
{
|
||||
tag: "div",
|
||||
attributes: {id: "chat-room-reply-indicator"},
|
||||
classList: ["hidden"],
|
||||
children: [
|
||||
{ tag: "span", attributes: { id: "chat-room-reply-indicator-text" }, children: [TextGet("ChatRoomReply")] },
|
||||
ElementButton.Create(
|
||||
"chat-room-reply-indicator-close",
|
||||
ChatRoomMessageReplyStop,
|
||||
{ noStyling: true },
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
tag: "textarea",
|
||||
attributes: {
|
||||
|
@ -1181,7 +1187,8 @@ function ChatRoomCreateElement() {
|
|||
},
|
||||
eventListeners: {
|
||||
input: ChatRoomChatInputChangeHandler,
|
||||
keyup: (key) => {ChatRoomStatusUpdateTalk(key); ChatRoomStopReplyOnEscape(key);},
|
||||
keyup: ChatRoomStatusUpdateTalk,
|
||||
keydown: ChatRoomStopReplyOnEscape,
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -1358,6 +1365,7 @@ function ChatRoomClearAllElements() {
|
|||
} else {
|
||||
ElementRemove("chat-room-div");
|
||||
window.removeEventListener("resize", ChatRoomResizeManager.ChatRoomResizeEvent);
|
||||
ChatRoomDivInputPrevHeight = NaN;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1807,7 +1815,7 @@ function ChatRoomResize(load) {
|
|||
const chatInput = document.getElementById("InputChat");
|
||||
if (chatInput) {
|
||||
ElementPositionFix("chat-room-div", ChatRoomFontSize, ...ChatRoomDivRect);
|
||||
chatInput.dispatchEvent(new Event("input"));
|
||||
chatInput.dispatchEvent(new InputEvent("input"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2069,9 +2077,7 @@ function ChatRoomStatusUpdateTalk(Key) {
|
|||
*/
|
||||
function ChatRoomChatInputChangeHandler(event) {
|
||||
const label = document.getElementById("InputChatLength");
|
||||
const chatLog = document.getElementById("TextAreaChatLog");
|
||||
const parent = document.getElementById("chat-room-div");
|
||||
if (!label || !chatLog || !parent) return;
|
||||
if (!label) return;
|
||||
|
||||
const length = this.value.length;
|
||||
if (length <= ServerChatMessageMaxLength - 100) {
|
||||
|
@ -2088,24 +2094,45 @@ function ChatRoomChatInputChangeHandler(event) {
|
|||
this.style.height = "100%";
|
||||
this.style.height = `${this.scrollHeight}px`;
|
||||
|
||||
// Check if the text log + input completely fill the parent element (within a gap-accounting error marigin)
|
||||
// and then resize the text log + input accordingly
|
||||
const chatLogHeight = chatLog.getBoundingClientRect().height;
|
||||
const parentHeight = parent.getBoundingClientRect().height;
|
||||
const inputHeight = this.getBoundingClientRect().height;
|
||||
const ratio = (inputHeight + chatLogHeight) / parentHeight;
|
||||
const needsUpdate = ratio > 1.005 || ratio < 0.995;
|
||||
if (needsUpdate) {
|
||||
const percentage = 100 * (inputHeight / parentHeight);
|
||||
if (percentage >= 9 && percentage <= 35) {
|
||||
const isScrolledToEnd = ElementIsScrolledToEnd("TextAreaChatLog");
|
||||
const inputHeight = this.clientHeight;
|
||||
if (inputHeight === ChatRoomDivInputPrevHeight) {
|
||||
return;
|
||||
}
|
||||
ChatRoomInputResize(this);
|
||||
}
|
||||
|
||||
// At ~34% the maximum resize height has been reached and there is no point in trying to expand it any further
|
||||
parent.style.gridTemplateRows = `${100 - 0.4 - percentage}% ${percentage}%`;
|
||||
if (isScrolledToEnd) {
|
||||
ElementScrollToEnd("TextAreaChatLog");
|
||||
}
|
||||
/**
|
||||
* Manually adjust the size of `TextAreaChatLog` based on the (auto-expanded) `chatInput` height.
|
||||
*
|
||||
* Why manually? Because doing it automatically can get veeeery slow as the chat log grows in size.
|
||||
* @param {HTMLElement} chatInput
|
||||
*/
|
||||
function ChatRoomInputResize(chatInput) {
|
||||
const chatLog = document.getElementById("TextAreaChatLog");
|
||||
const parent = document.getElementById("chat-room-div");
|
||||
if (!chatLog || !parent) {
|
||||
return;
|
||||
}
|
||||
ChatRoomDivInputPrevHeight = chatInput.clientHeight;
|
||||
|
||||
const isScrolledToEnd = ElementIsScrolledToEnd("TextAreaChatLog");
|
||||
let height = parent.getBoundingClientRect().height;
|
||||
let nGaps = 0;
|
||||
for (const i of parent.children) {
|
||||
if (!ElementCheckVisibility(i, { checkVisibilityCSS: false })) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nGaps++;
|
||||
if (i !== chatLog) {
|
||||
height -= i.getBoundingClientRect().height;
|
||||
}
|
||||
}
|
||||
const gap = globalThis.getComputedStyle(chatLog).marginBottom;
|
||||
chatLog.style.height = `calc(${Math.max(0, height)}px - (${nGaps} * ${gap}))`;
|
||||
|
||||
if (isScrolledToEnd) {
|
||||
ElementScrollToEnd("TextAreaChatLog");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3083,7 +3110,7 @@ function ChatRoomSendChat() {
|
|||
ChatRoomSendEmote(msg);
|
||||
}
|
||||
inputChat.value = "";
|
||||
inputChat.dispatchEvent(new Event("input"));
|
||||
inputChat.dispatchEvent(new InputEvent("input"));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3111,7 +3138,7 @@ function ChatRoomSendChat() {
|
|||
|
||||
if (clearChat) {
|
||||
inputChat.value = "";
|
||||
inputChat.dispatchEvent(new Event("input"));
|
||||
inputChat.dispatchEvent(new InputEvent("input"));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4393,10 +4420,12 @@ function ChatRoomMessageGetType(msgId) {
|
|||
* Closes the reply.
|
||||
*/
|
||||
function ChatRoomMessageReplyStop() {
|
||||
const chatInput = /** @type {null | HTMLTextAreaElement} */(document.getElementById("InputChat"));
|
||||
const replyIndicator = document.getElementById("chat-room-reply-indicator");
|
||||
chatInput.removeAttribute("reply-id");
|
||||
replyIndicator.classList.add("hidden");
|
||||
const chatInput = document.getElementById("InputChat");
|
||||
document.getElementById("chat-room-reply-indicator")?.classList.add("hidden");
|
||||
if (chatInput) {
|
||||
chatInput.removeAttribute("reply-id");
|
||||
ChatRoomInputResize(chatInput);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4405,8 +4434,12 @@ function ChatRoomMessageReplyStop() {
|
|||
*/
|
||||
function ChatRoomMessageSetReply(msgId) {
|
||||
const chatInput = /** @type {null | HTMLTextAreaElement} */(document.getElementById("InputChat"));
|
||||
chatInput.setAttribute("reply-id", msgId);
|
||||
const replyMessage = ChatRoomMessageGetById(msgId);
|
||||
if (!chatInput || !replyMessage) {
|
||||
return;
|
||||
}
|
||||
|
||||
chatInput.setAttribute("reply-id", msgId);
|
||||
const type = ChatRoomMessageGetType(msgId);
|
||||
const isWhisper = type === "Whisper";
|
||||
if (isWhisper) {
|
||||
|
@ -4418,6 +4451,7 @@ function ChatRoomMessageSetReply(msgId) {
|
|||
const replyName = ChatRoomMessageGetReplyName(msgId, isWhisper);
|
||||
replyIndicatorText.textContent = `${TextGet("ChatRoomReply")}: ${replyName && `${replyName}` || "a message"}`;
|
||||
replyIndicator.classList.remove("hidden");
|
||||
ChatRoomInputResize(chatInput);
|
||||
chatInput.focus();
|
||||
}
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ function ElementValue(ID, Value) {
|
|||
return e.value.trim();
|
||||
|
||||
e.value = Value;
|
||||
e.dispatchEvent(new InputEvent("input"));
|
||||
return "";
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue