overte-JulianGro/scripts/communityScripts/armored-chat/armored_chat.js
Armored Dragon eb84de84b4
Corrected case on variables.
Signed-off-by: Armored Dragon <publicmail@armoreddragon.com>
2024-06-08 08:41:53 -05:00

254 lines
8.6 KiB
JavaScript

//
// armored_chat.js
//
// Created by Armored Dragon, 2024.
// Copyright 2024 Overte e.V.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
(() => {
"use strict";
var appIsVisible = false;
var settings = {
external_window: false,
maximum_messages: 200,
};
// Global vars
var tablet;
var chatOverlayWindow;
var appButton;
var quickMessage;
const channels = ["domain", "local"];
var messageHistory = Settings.getValue("ArmoredChat-Messages", []) || [];
var maxLocalDistance = 20; // Maximum range for the local chat
var palData = AvatarManager.getPalData().data;
Controller.keyPressEvent.connect(keyPressEvent);
Messages.subscribe("chat");
Messages.messageReceived.connect(receivedMessage);
AvatarManager.avatarAddedEvent.connect((sessionId) => {
_avatarAction("connected", sessionId);
});
AvatarManager.avatarRemovedEvent.connect((sessionId) => {
_avatarAction("left", sessionId);
});
startup();
function startup() {
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
appButton = tablet.addButton({
icon: Script.resolvePath("./img/icon_white.png"),
activeIcon: Script.resolvePath("./img/icon_black.png"),
text: "CHAT",
isActive: appIsVisible,
});
// When script ends, remove itself from tablet
Script.scriptEnding.connect(function () {
console.log("Shutting Down");
tablet.removeButton(appButton);
chatOverlayWindow.close();
});
// Overlay button toggle
appButton.clicked.connect(toggleMainChatWindow);
quickMessage = new OverlayWindow({
source: Script.resolvePath("./armored_chat_quick_message.qml"),
});
_openWindow();
}
function toggleMainChatWindow() {
appIsVisible = !appIsVisible;
console.log(`App is now ${appIsVisible ? "visible" : "hidden"}`);
appButton.editProperties({ isActive: appIsVisible });
chatOverlayWindow.visible = appIsVisible;
// External window was closed; the window does not exist anymore
if (chatOverlayWindow.title == "" && appIsVisible) {
_openWindow();
}
}
function _openWindow() {
chatOverlayWindow = new Desktop.createWindow(
Script.resolvePath("./armored_chat.qml"),
{
title: "Chat",
size: { x: 550, y: 400 },
additionalFlags: Desktop.ALWAYS_ON_TOP,
visible: appIsVisible,
presentationMode: Desktop.PresentationMode.VIRTUAL,
}
);
chatOverlayWindow.closed.connect(toggleMainChatWindow);
chatOverlayWindow.fromQml.connect(fromQML);
quickMessage.fromQml.connect(fromQML);
}
function receivedMessage(channel, message) {
// Is the message a chat message?
channel = channel.toLowerCase();
if (channel !== "chat") return;
message = JSON.parse(message);
message.channel = message.channel.toLowerCase(); // Make sure the "local", "domain", etc. is formatted consistently
if (!channels.includes(message.channel)) return; // Check the channel
if (
message.channel == "local" &&
Vec3.distance(MyAvatar.position, message.position) >
maxLocalDistance
)
return; // If message is local, and if player is too far away from location, don't do anything
// Update qml view of to new message
_emitEvent({ type: "show_message", ...message });
Messages.sendLocalMessage(
"Floof-Notif",
JSON.stringify({
sender: message.displayName,
text: message.message,
})
);
// Save message to history
let savedMessage = message;
delete savedMessage.position;
savedMessage.timeString = new Date().toLocaleTimeString(undefined, {
hour12: false,
});
savedMessage.dateString = new Date().toLocaleDateString(undefined, {
year: "numeric",
month: "long",
day: "numeric",
});
messageHistory.push(savedMessage);
while (messageHistory.length > settings.maximum_messages) {
messageHistory.shift();
}
Settings.setValue("ArmoredChat-Messages", messageHistory);
}
function fromQML(event) {
switch (event.type) {
case "send_message":
_sendMessage(event.message, event.channel);
break;
case "setting_change":
settings[event.setting] = event.value; // Update local settings
_saveSettings(); // Save local settings
switch (event.setting) {
case "external_window":
chatOverlayWindow.presentationMode = event.value
? Desktop.PresentationMode.NATIVE
: Desktop.PresentationMode.VIRTUAL;
break;
case "maximum_messages":
// Do nothing
break;
}
break;
case "action":
switch (event.action) {
case "erase_history":
Settings.setValue("ArmoredChat-Messages", []);
_emitEvent({
type: "clear_messages",
});
break;
}
break;
case "initialized":
// https://github.com/overte-org/overte/issues/824
chatOverlayWindow.visible = appIsVisible; // The "visible" field in the Desktop.createWindow does not seem to work. Force set it to the initial state (false)
_loadSettings();
break;
}
}
function keyPressEvent(event) {
switch (JSON.stringify(event.key)) {
case "16777220": // Enter key
if (HMD.active) return; // Don't allow in VR
quickMessage.sendToQml({
type: "change_visibility",
value: true,
});
}
}
function _sendMessage(message, channel) {
if (message.length == 0) return;
Messages.sendMessage(
"chat",
JSON.stringify({
position: MyAvatar.position,
message: message,
displayName: MyAvatar.sessionDisplayName,
channel: channel,
action: "send_chat_message",
})
);
}
function _avatarAction(type, sessionId) {
Script.setTimeout(() => {
if (type == "connected") {
palData = AvatarManager.getPalData().data;
}
// Get the display name of the user
let displayName = "";
displayName =
AvatarManager.getPalData([sessionId])?.data[0]
?.sessionDisplayName || null;
if (displayName == null) {
for (let i = 0; i < palData.length; i++) {
if (palData[i].sessionUUID == sessionId) {
displayName = palData[i].sessionDisplayName;
}
}
}
// Format the packet
let message = {};
message.message = `${displayName} ${type}`;
_emitEvent({ type: "notification", ...message });
}, 1500);
}
function _loadSettings() {
settings = Settings.getValue("ArmoredChat-Config", settings);
if (messageHistory) {
// Load message history
messageHistory.forEach((message) => {
delete message.action;
_emitEvent({ type: "show_message", ...message });
});
}
// Send current settings to the app
_emitEvent({ type: "initial_settings", settings: settings });
}
function _saveSettings() {
console.log("Saving config");
Settings.setValue("ArmoredChat-Config", settings);
}
/**
* Emit a packet to the HTML front end. Easy communication!
* @param {Object} packet - The Object packet to emit to the HTML
* @param {("show_message"|"clear_messages"|"notification"|"initial_settings")} packet.type - The type of packet it is
*/
function _emitEvent(packet = { type: "" }) {
chatOverlayWindow.sendToQml(packet);
}
})();