mirror of
https://github.com/AleziaKurdis/Overte-community-apps.git
synced 2025-08-21 12:24:03 +02:00
301 lines
10 KiB
HTML
301 lines
10 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<script src="https://cdn.jsdelivr.net/npm/node-forge@1.0.0/dist/forge.min.js"></script>
|
|
<link rel="stylesheet" href="index.css" />
|
|
|
|
<!-- Compact messages -->
|
|
<!-- <link id="compact-messages" rel="stylesheet" href="compact-messages.css" /> -->
|
|
</head>
|
|
<body>
|
|
<!-- The primary page. This is where people will chat -->
|
|
<div class="header">
|
|
<div class="left">
|
|
<button data-target="domain-chat" class="active">
|
|
<span><img src="./img/ui/world_white.png" /></span>
|
|
</button>
|
|
<button data-target="local-chat">
|
|
<span><img src="./img/ui/social_black.png" /></span>
|
|
</button>
|
|
<!-- <button data-target="pm-chat">
|
|
<span><img src="./img/ui/user_black.png" /></span>
|
|
</button> -->
|
|
</div>
|
|
<div class="right">
|
|
<button data-target="settings">
|
|
<span><img src="./img/ui/settings_black.png" /></span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<div id="domain-chat" class="page chat">
|
|
<div class="content message-list"></div>
|
|
</div>
|
|
|
|
<!-- Local Chat -->
|
|
<div id="local-chat" class="page hidden">
|
|
<div class="content message-list"></div>
|
|
</div>
|
|
|
|
<!-- DM page. -->
|
|
<div id="pm-chat" class="page hidden">
|
|
<div class="content">PM content</div>
|
|
</div>
|
|
|
|
<!-- Settings page. Adjust the chat here -->
|
|
<div id="settings" class="page hidden">
|
|
<div class="content settings">
|
|
<!-- <div class="setting setting-toggle">
|
|
<span>Show typing indicator</span>
|
|
<input id="typing-indicator-toggle" type="checkbox" />
|
|
</div> -->
|
|
|
|
<!-- <div class="setting setting-toggle">
|
|
<span>Show speech bubbles</span>
|
|
<input id="speech-bubble-toggle" type="checkbox" />
|
|
</div> -->
|
|
|
|
<div class="setting setting-toggle">
|
|
<span>Compact Mode</span>
|
|
<input id="compact-message-toggle" type="checkbox" />
|
|
</div>
|
|
<div class="setting setting-toggle">
|
|
<span>External Window</span>
|
|
<input id="external-window-toggle" type="checkbox" />
|
|
</div>
|
|
<div class="setting setting-button">
|
|
<span>Erase history</span>
|
|
<input id="erase-history" type="button" title="Clear" value="Clear" />
|
|
</div>
|
|
<div class="setting setting-value">
|
|
<span>Max history</span>
|
|
<input id="max-history" type="number" title="Maximum entires to store" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="footer text-entry">
|
|
<input id="message-entry" type="text" placeholder="Enter message here..." />
|
|
<button id="send-message">
|
|
<span><img src="./img/ui/send_black.png" /></span>
|
|
</button>
|
|
</div>
|
|
</body>
|
|
</html>
|
|
|
|
<script>
|
|
"use strict";
|
|
|
|
_emitEvent({ type: "initialized" }); // Tell the script we are ready
|
|
|
|
const qs = (target) => document.querySelector(target);
|
|
const qsa = (target) => document.querySelectorAll(target);
|
|
var scroll_distance = 100000; // The scroll distance for the chat window to automatically scroll down with.
|
|
var compact_mode = false; // Compact messages
|
|
var external_window = false;
|
|
|
|
// Start listening for new messages
|
|
EventBridge.scriptEventReceived.connect(_newScriptEvent);
|
|
|
|
// HTML Event listeners
|
|
qs("#send-message").addEventListener("click", _sendMessage);
|
|
qs("#message-entry").addEventListener("keyup", (event) => {
|
|
if (event.keyCode === 13) _sendMessage(); // Enter key, send message
|
|
});
|
|
|
|
// Add event listeners to all nav-buttons
|
|
qsa(".header button").forEach((button) => {
|
|
button.addEventListener("click", () => {
|
|
_switchPage(button.dataset.target, button);
|
|
if (button.dataset.target === "settings") {
|
|
qs(".footer.text-entry").classList.add("hidden");
|
|
} else {
|
|
qs(".footer.text-entry").classList.remove("hidden");
|
|
}
|
|
});
|
|
});
|
|
function _switchPage(target, button) {
|
|
// Hide all pages
|
|
qsa(".page").forEach((page) => page.classList.add("hidden"));
|
|
// Deactivate all nav-buttons
|
|
qsa(".header button").forEach((button) => deactivateButton(button));
|
|
|
|
// Show target page
|
|
qs(`#${target}`).classList.remove("hidden");
|
|
// Sets active for target button
|
|
activateButton(button);
|
|
|
|
function deactivateButton(button) {
|
|
button.querySelector("img").src = button.querySelector("img").src.replace("_white", "_black");
|
|
button.classList.remove("active");
|
|
}
|
|
function activateButton(button) {
|
|
button.querySelector("img").src = button.querySelector("img").src.replace("_black", "_white");
|
|
button.classList.add("active");
|
|
button.blur();
|
|
|
|
// Tell script where we are at
|
|
_emitEvent({ type: "page_update", page: button.dataset.target.replace("-chat", "") });
|
|
}
|
|
}
|
|
function _sendMessage() {
|
|
qs("#send-message").blur();
|
|
|
|
// Don't send empty messages.
|
|
if (qs("#message-entry").value.length === 0) return;
|
|
|
|
// Send what is in the text area as a message
|
|
_emitEvent({ type: "send_message", message: qs("#message-entry").value });
|
|
|
|
// Clear the message area
|
|
qs("#message-entry").value = "";
|
|
}
|
|
|
|
function _newScriptEvent(message) {
|
|
message = JSON.parse(message);
|
|
|
|
switch (message.type) {
|
|
case "show_message":
|
|
_showMessage(message);
|
|
break;
|
|
case "setting_update":
|
|
_newSetting(message);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Settings
|
|
qs("#compact-message-toggle").addEventListener("change", function () {
|
|
_toggleCompactMode();
|
|
_emitEvent({ type: "setting_update", setting_name: "compact_chat", setting_value: compact_mode });
|
|
});
|
|
|
|
function _toggleCompactMode() {
|
|
compact_mode = !compact_mode;
|
|
if (compact_mode) {
|
|
// Add the stylesheet to the head
|
|
document.head.insertAdjacentHTML("beforeend", '<link id="compact-messages-ss" rel="stylesheet" href="compact-messages.css" />');
|
|
} else {
|
|
// Remove the compact messages stylesheet
|
|
qs("#compact-messages-ss").remove();
|
|
}
|
|
}
|
|
|
|
qs("#external-window-toggle").addEventListener("change", function () {
|
|
external_window = !external_window;
|
|
_emitEvent({ type: "setting_update", setting_name: "external_window", setting_value: external_window });
|
|
});
|
|
|
|
qs("#erase-history").addEventListener("click", () => {
|
|
let response = confirm("Are you sure you want to erase all messages?");
|
|
if (response) _emitEvent({ type: "action", action: "clear_history" });
|
|
// _emitEvent({ type: "setting_update", setting_name: "max_history", setting_value: compact_mode });
|
|
});
|
|
|
|
qs("#max-history").addEventListener("change", () => {
|
|
_emitEvent({ type: "setting_update", setting_name: "max_history", setting_value: qs("#max-history").value });
|
|
});
|
|
|
|
// TODO: Limit embeds to 3.
|
|
function _showMessage(message) {
|
|
var target = message.channel + "-chat";
|
|
|
|
// Clone template message
|
|
let message_template = qs("#message-listing");
|
|
let message_clone = message_template.content.cloneNode(true);
|
|
let message_embeds = "";
|
|
message_clone.querySelector(".body").innerHTML = "";
|
|
message_clone.querySelector(".embeds").innerHTML = "";
|
|
|
|
// Youtube embeds
|
|
let yt_url = message.message.match(/(https?:\/\/)?(www\.)?(youtube\.com\/watch\?v=|youtu\.be\/)([^& \n<]+)(?:[^ \n<]+)?/g);
|
|
if (yt_url) {
|
|
yt_url.forEach((url) => {
|
|
message_embeds += `<iframe class="z-depth-2" width='420' height='236' src='https://www.youtube.com/embed/${url.toString().split("/")[3]}' frameborder='0'></iframe><br>`;
|
|
});
|
|
}
|
|
|
|
// Image embeds
|
|
let image_link = message.message.match(/.+.(png|jpg|jpeg|webp)/g);
|
|
if (image_link) {
|
|
image_link.forEach((image) => {
|
|
message_embeds += `<span class='image-container'><img src='${image}'></span><br>`;
|
|
});
|
|
}
|
|
|
|
// Linkify links
|
|
let link_url = message.message.match(/(?:^|\s)(https?:\/\/)?[\w.-]+(?:\.[\w\.-]+)+(?:\/[\w\-\._~:/?#[\]@!\$&'\(\)\*\+,;=.]*)?(?=\s|$)/g);
|
|
if (link_url) {
|
|
link_url.forEach((link) => {
|
|
message_embeds += `<a href='#' onclick='_emitEvent({type:"open_url", url: "${link}" })'>${link}</a><br>`;
|
|
message.message = message.message.replace(link, "");
|
|
});
|
|
}
|
|
|
|
// Update template data to message data
|
|
message_clone.querySelector(".name").innerText = message.displayName;
|
|
if (!message.timeString) {
|
|
message_clone.querySelector(".timestamp").innerText = new Date().toLocaleTimeString(undefined, { hour12: false });
|
|
message_clone.querySelector(".timestamp").title = new Date().toLocaleDateString(undefined, {
|
|
month: "long",
|
|
day: "numeric",
|
|
});
|
|
} else {
|
|
message_clone.querySelector(".timestamp").innerText = message.timeString;
|
|
message_clone.querySelector(".timestamp").title = message.dateString;
|
|
}
|
|
|
|
message_clone.querySelector(".embeds").innerHTML = message_embeds;
|
|
message_clone.querySelector(".body").innerText = message.message;
|
|
// Append to the message list
|
|
qs("#" + target + " .message-list").appendChild(message_clone);
|
|
// Scroll to the bottom of the page
|
|
qs("#" + target + " .message-list").scrollTop = scroll_distance;
|
|
// Increase scroll distance so it will continue to work for future messages.
|
|
scroll_distance = scroll_distance + 100000;
|
|
}
|
|
/**
|
|
* Called when the script is initialized and we are loading the user settings
|
|
*/
|
|
function _newSetting(message) {
|
|
switch (message.setting_name) {
|
|
case "compact_chat":
|
|
qs("#compact-message-toggle").checked = true;
|
|
_toggleCompactMode();
|
|
break;
|
|
|
|
case "external_window":
|
|
qs("#external-window-toggle").checked = true;
|
|
external_window = true;
|
|
break;
|
|
|
|
case "max_history":
|
|
qs(`#max-history`).value = message.setting_value;
|
|
break;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Emit a packet to the HTML front end. Easy communication!
|
|
* @param {Object} packet - The Object packet to emit to the HTML
|
|
* @param {("setting_update"|"send_message"|"page_update"|"open_url"|"initialized")} packet.type - The type of packet it is
|
|
*/
|
|
function _emitEvent(packet = { type: "" }) {
|
|
EventBridge.emitWebEvent(JSON.stringify(packet));
|
|
}
|
|
</script>
|
|
|
|
<template id="message-listing">
|
|
<div class="message">
|
|
<div class="pfp"><img src="./img/ui/user_white.png" /></div>
|
|
<div class="name">[NAME]</div>
|
|
<div class="timestamp" title="[DATE]">[TIMESTAMP]</div>
|
|
<div>
|
|
<div class="embeds">[EMBEDS]</div>
|
|
<div class="body">[CONTENT]</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<!-- <script src="encrpytion.js"></script> -->
|