Message media embedding.

This commit is contained in:
armored-dragon 2024-12-17 18:13:49 -06:00
parent e340741dce
commit 907e977508
No known key found for this signature in database
GPG key ID: C7207ACC3382AD8B
2 changed files with 63 additions and 12 deletions

View file

@ -94,7 +94,7 @@
chatOverlayWindow.fromQml.connect(fromQML); chatOverlayWindow.fromQml.connect(fromQML);
quickMessage.fromQml.connect(fromQML); quickMessage.fromQml.connect(fromQML);
} }
function receivedMessage(channel, message) { async function receivedMessage(channel, message) {
// Is the message a chat message? // Is the message a chat message?
channel = channel.toLowerCase(); channel = channel.toLowerCase();
if (channel !== "chat") return; if (channel !== "chat") return;
@ -114,9 +114,8 @@
message.timeString = timeArray[0]; message.timeString = timeArray[0];
message.dateString = timeArray[1]; message.dateString = timeArray[1];
let formattedMessage = _parseMessage(message.message); // Format the message for viewing
let formattedMessagePacket = { ...message }; let formattedMessagePacket = { ...message };
formattedMessagePacket.message = formattedMessage formattedMessagePacket.message = await _parseMessage(message.message)
_emitEvent({ type: "show_message", ...formattedMessagePacket }); // Update qml view of to new message. _emitEvent({ type: "show_message", ...formattedMessagePacket }); // Update qml view of to new message.
_notificationCoreMessage(message.displayName, message.message) // Show a new message on screen. _notificationCoreMessage(message.displayName, message.message) // Show a new message on screen.
@ -238,23 +237,22 @@
_emitEvent({ type: "notification", ...message }); _emitEvent({ type: "notification", ...message });
}, 1500); }, 1500);
} }
function _loadSettings() { async function _loadSettings() {
settings = Settings.getValue("ArmoredChat-Config", settings); settings = Settings.getValue("ArmoredChat-Config", settings);
if (messageHistory) { if (messageHistory) {
// Load message history // Load message history
messageHistory.forEach((message) => { for (message of messageHistory) {
const timeArray = _formatTimestamp(_getTimestamp()); const timeArray = _formatTimestamp(_getTimestamp());
messagePacket = { ...message }; messagePacket = { ...message };
messagePacket.timeString = timeArray[0]; messagePacket.timeString = timeArray[0];
messagePacket.dateString = timeArray[1]; messagePacket.dateString = timeArray[1];
let formattedMessage = _parseMessage(messagePacket.message); let formattedMessagePacket = {...messagePacket};
let formattedMessagePacket = messagePacket; formattedMessagePacket.message = await _parseMessage(messagePacket.message);
formattedMessagePacket.message = formattedMessage;
_emitEvent({ type: "show_message", ...formattedMessagePacket }); _emitEvent({ type: "show_message", ...formattedMessagePacket });
}); }
} }
// Send current settings to the app // Send current settings to the app
@ -288,7 +286,7 @@
JSON.stringify({ sender: displayName, text: message }) JSON.stringify({ sender: displayName, text: message })
); );
} }
function _parseMessage(message){ async function _parseMessage(message){
const urlRegex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/; const urlRegex = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/;
const mentionRegex = /@(\w+)/; // FIXME: Remove - devcode const mentionRegex = /@(\w+)/; // FIXME: Remove - devcode
const overteLocationRegex = /hifi:\/\/[a-zA-Z0-9_-]+\/[-+]?\d*\.?\d+,[+-]?\d*\.?\d+,[+-]?\d*\.?\d+\/[-+]?\d*\.?\d+,[+-]?\d*\.?\d+,[+-]?\d*\.?\d+,[+-]?\d*\.?\d+/; const overteLocationRegex = /hifi:\/\/[a-zA-Z0-9_-]+\/[-+]?\d*\.?\d+,[+-]?\d*\.?\d+,[+-]?\d*\.?\d+\/[-+]?\d*\.?\d+,[+-]?\d*\.?\d+,[+-]?\d*\.?\d+,[+-]?\d*\.?\d+/;
@ -309,7 +307,9 @@
if (firstMatch == null) { if (firstMatch == null) {
// If there was not any matches found in the entire message, format the whole message as a single text entry. // If there was not any matches found in the entire message, format the whole message as a single text entry.
messageArray.push({type: 'text', value: runningMessage}); if (messageArray.length == 0) {
messageArray.push({type: 'text', value: runningMessage});
}
// Append a final 'fill width' to the message text. // Append a final 'fill width' to the message text.
messageArray.push({type: 'messageEnd'}); messageArray.push({type: 'messageEnd'});
@ -319,6 +319,20 @@
_formatMessage(firstMatch); _formatMessage(firstMatch);
} }
for (dataChunk of messageArray){
if (dataChunk.type == 'url'){
let url = dataChunk.value;
const res = await fetch(url, {method: 'GET'}); // TODO: Replace with 'HEAD' method. https://github.com/overte-org/overte/issues/1273
const contentType = res.getResponseHeader("content-type");
// TODO: Add support for other media types
if (contentType.startsWith('image/')) {
messageArray.push({type: 'imageEmbed', value: url});
}
}
}
return messageArray; return messageArray;
function _formatMessage(firstMatch){ function _formatMessage(firstMatch){
@ -361,4 +375,28 @@
function _emitEvent(packet = { type: "" }) { function _emitEvent(packet = { type: "" }) {
chatOverlayWindow.sendToQml(packet); chatOverlayWindow.sendToQml(packet);
} }
function fetch(url, options = {method: "GET"}) {
return new Promise((resolve, reject) => {
let req = new XMLHttpRequest();
req.onreadystatechange = function () {
if (req.readyState === req.DONE) {
if (req.status === 200) {
console.log("Content type:", req.getResponseHeader("content-type"));
resolve(req);
} else {
console.log("Error", req.status, req.statusText);
reject();
}
}
};
req.open(options.method, url);
req.send();
});
}
})(); })();

View file

@ -510,7 +510,7 @@ Rectangle {
} }
Text { Text {
text: model.value.split('hifi://')[1].split('/')[0]; text: model.type === 'overteLocation' ? model.value.split('hifi://')[1].split('/')[0] : '';
color: "black" color: "black"
font.pointSize: 12 font.pointSize: 12
x: parent.children[0].width + 5; x: parent.children[0].width + 5;
@ -533,6 +533,18 @@ Rectangle {
Layout.fillWidth: true Layout.fillWidth: true
visible: model.type === 'messageEnd' visible: model.type === 'messageEnd'
} }
Item {
visible: model.type === 'imageEmbed';
width: messageBoxFlow.width;
height: 200
Image {
source: model.type === 'imageEmbed' ? model.value : ''
sourceSize.width: 400
sourceSize.height: 200
}
}
} }
} }
} }
@ -653,6 +665,7 @@ Rectangle {
// last_message_user = username; // last_message_user = username;
// last_message_time = new Date(); // last_message_time = new Date();
channel.append({ text: message, username: username, date: date, type: type }); channel.append({ text: message, username: username, date: date, type: type });
load_scroll_timer.running = true; load_scroll_timer.running = true;
} }