overte/scripts/communityScripts/armored-chat/armored_chat.js
Armored Dragon 391a33d149
Fixed saved date on messages.
Hotfix for empty message_history setting.

Signed-off-by: Armored Dragon <publicmail@armoreddragon.com>
2024-05-21 16:46:41 -05:00

240 lines
8.2 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 app_is_visible = false;
var settings = {
external_window: false,
maximum_messages: 200,
};
// Global vars
var tablet;
var chat_overlay_window;
var app_button;
const channels = ["domain", "local"];
var message_history = Settings.getValue("ArmoredChat-Messages", []) || [];
var max_local_distance = 20; // Maximum range for the local chat
var pal_data = AvatarManager.getPalData().data;
Messages.subscribe("chat");
Messages.messageReceived.connect(receivedMessage);
AvatarManager.avatarAddedEvent.connect((session_id) => {
_avatarAction("connected", session_id);
});
AvatarManager.avatarRemovedEvent.connect((session_id) => {
_avatarAction("left", session_id);
});
startup();
function startup() {
tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
app_button = tablet.addButton({
icon: Script.resolvePath("./img/icon_white.png"),
activeIcon: Script.resolvePath("./img/icon_black.png"),
text: "CHAT",
isActive: app_is_visible,
});
// When script ends, remove itself from tablet
Script.scriptEnding.connect(function () {
console.log("Shutting Down");
tablet.removeButton(app_button);
chat_overlay_window.close();
});
// Overlay button toggle
app_button.clicked.connect(toggleMainChatWindow);
_openWindow();
}
function toggleMainChatWindow() {
app_is_visible = !app_is_visible;
console.log(`App is now ${app_is_visible ? "visible" : "hidden"}`);
app_button.editProperties({ isActive: app_is_visible });
chat_overlay_window.visible = app_is_visible;
// External window was closed; the window does not exist anymore
if (chat_overlay_window.title == "" && app_is_visible) {
_openWindow();
}
}
function _openWindow() {
chat_overlay_window = new Desktop.createWindow(
Script.resolvePath("./armored_chat.qml"),
{
title: "Chat",
size: { x: 550, y: 400 },
additionalFlags: Desktop.ALWAYS_ON_TOP,
visible: app_is_visible,
presentationMode: Desktop.PresentationMode.VIRTUAL,
}
);
chat_overlay_window.closed.connect(toggleMainChatWindow);
chat_overlay_window.fromQml.connect(fromQML);
}
function receivedMessage(channel, message) {
// Is the message a chat message?
channel = channel.toLowerCase();
if (channel !== "chat") return;
console.log(`Received message:\n${message}`);
var 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) >
max_local_distance
)
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 saved_message = message;
delete saved_message.position;
saved_message.timeString = new Date().toLocaleTimeString(undefined, {
hour12: false,
});
saved_message.dateString = new Date().toLocaleDateString(undefined, {
year: "numeric",
month: "long",
day: "numeric",
});
message_history.push(saved_message);
while (message_history.length > settings.maximum_messages) {
message_history.shift();
}
Settings.setValue("ArmoredChat-Messages", message_history);
}
function fromQML(event) {
console.log(`New QML event:\n${JSON.stringify(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":
chat_overlay_window.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
chat_overlay_window.visible = app_is_visible; // The "visible" field in the Desktop.createWindow does not seem to work. Force set it to the initial state (false)
_loadSettings();
break;
}
}
function _sendMessage(message, channel) {
Messages.sendMessage(
"chat",
JSON.stringify({
position: MyAvatar.position,
message: message,
displayName: MyAvatar.sessionDisplayName,
channel: channel,
action: "send_chat_message",
})
);
}
function _avatarAction(type, session_id) {
Script.setTimeout(() => {
if (type == "connected") {
pal_data = AvatarManager.getPalData().data;
}
// Get the display name of the user
let display_name = "";
display_name =
AvatarManager.getPalData([session_id])?.data[0]
?.sessionDisplayName || null;
if (display_name == null) {
for (let i = 0; i < pal_data.length; i++) {
if (pal_data[i].sessionUUID == session_id) {
display_name = pal_data[i].sessionDisplayName;
}
}
}
// Format the packet
let message = {};
message.message = `${display_name} ${type}`;
_emitEvent({ type: "avatar_connected", ...message });
}, 1500);
}
function _loadSettings() {
settings = Settings.getValue("ArmoredChat-Config", settings);
if (message_history) {
// Load message history
message_history.forEach((message) => {
delete message.action;
_emitEvent({ type: "show_message", ...message });
});
}
// Send current settings to the app
_emitEvent({ type: "initial_settings", settings: settings });
console.log(`\n\n\n` + JSON.stringify(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 {("setting_update"|"show_message")} packet.type - The type of packet it is
*/
function _emitEvent(packet = { type: "" }) {
chat_overlay_window.sendToQml(packet);
}
})();