Compare commits
9 Commits
084cb02a11
...
main
Author | SHA1 | Date | |
---|---|---|---|
4ae2f4cbe8 | |||
7c874fab21 | |||
f125cad87c | |||
cb88b16606 | |||
94ea9b6840 | |||
7eddd45f79 | |||
70bc69ddea | |||
aa70e42fdc | |||
c530a8d69c |
33
app.js
33
app.js
@ -7,6 +7,22 @@ import Corestore from 'corestore';
|
|||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import handleCommand from './commands.js';
|
import handleCommand from './commands.js';
|
||||||
|
import MarkdownIt from 'markdown-it';
|
||||||
|
import hljs from 'highlight.js';
|
||||||
|
import DOMPurify from 'dompurify';
|
||||||
|
|
||||||
|
const md = new MarkdownIt({
|
||||||
|
highlight: function (str, lang) {
|
||||||
|
if (lang && hljs.getLanguage(lang)) {
|
||||||
|
try {
|
||||||
|
return '<pre class="hljs"><code>' +
|
||||||
|
hljs.highlight(str, { language: lang }).value +
|
||||||
|
'</code></pre>';
|
||||||
|
} catch (__) {}
|
||||||
|
}
|
||||||
|
return '<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const agentAvatarPath = './assets/agent.png';
|
const agentAvatarPath = './assets/agent.png';
|
||||||
let agentAvatar = '';
|
let agentAvatar = '';
|
||||||
@ -156,9 +172,10 @@ async function initialize() {
|
|||||||
hljs.highlightAll();
|
hljs.highlightAll();
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('createGuild', (event) => {
|
document.addEventListener('createGuild', async (event) => {
|
||||||
const { guildName } = event.detail;
|
const { guildName } = event.detail;
|
||||||
createGuild(guildName);
|
createGuild(guildName);
|
||||||
|
await joinAllGuilds(); // Ensure the app joins all guilds on startup
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('addRoomToGuild', (event) => {
|
document.addEventListener('addRoomToGuild', (event) => {
|
||||||
@ -1076,6 +1093,10 @@ function addAudioMessage(name, audioUrl, avatar, topic) {
|
|||||||
const audioElement = document.createElement('audio');
|
const audioElement = document.createElement('audio');
|
||||||
audioElement.src = audioUrl;
|
audioElement.src = audioUrl;
|
||||||
audioElement.controls = true;
|
audioElement.controls = true;
|
||||||
|
// Autoplay only if the message is from a peer
|
||||||
|
if (name !== config.userName) {
|
||||||
|
audioElement.autoplay = true;
|
||||||
|
}
|
||||||
audioElement.classList.add('message-audio');
|
audioElement.classList.add('message-audio');
|
||||||
|
|
||||||
messageContent.appendChild(senderName);
|
messageContent.appendChild(senderName);
|
||||||
@ -1116,7 +1137,7 @@ function addMessage(name, message, avatar, topic) {
|
|||||||
|
|
||||||
const messageText = document.createElement('div');
|
const messageText = document.createElement('div');
|
||||||
messageText.classList.add('message-text');
|
messageText.classList.add('message-text');
|
||||||
messageText.innerHTML = message;
|
messageText.innerHTML = DOMPurify.sanitize(md.render(message));
|
||||||
|
|
||||||
messageContent.appendChild(senderName);
|
messageContent.appendChild(senderName);
|
||||||
messageContent.appendChild(messageText);
|
messageContent.appendChild(messageText);
|
||||||
@ -1127,6 +1148,7 @@ function addMessage(name, message, avatar, topic) {
|
|||||||
if (topic === currentTopic()) {
|
if (topic === currentTopic()) {
|
||||||
container.scrollTop = container.scrollHeight;
|
container.scrollTop = container.scrollHeight;
|
||||||
}
|
}
|
||||||
|
hljs.highlightAll(); // Re-highlight all code blocks
|
||||||
}
|
}
|
||||||
|
|
||||||
async function updateIcon(username, avatarBuffer) {
|
async function updateIcon(username, avatarBuffer) {
|
||||||
@ -1141,7 +1163,6 @@ async function updateIcon(username, avatarBuffer) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function clearMessages() {
|
function clearMessages() {
|
||||||
const messagesContainer = document.querySelector('#messages');
|
const messagesContainer = document.querySelector('#messages');
|
||||||
while (messagesContainer.firstChild) {
|
while (messagesContainer.firstChild) {
|
||||||
@ -1162,8 +1183,7 @@ async function sendMessage(e) {
|
|||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
|
|
||||||
console.log("Sending message to current topic:", topic); // Add logging
|
console.log("Sending message to current topic:", topic); // Add logging
|
||||||
|
if (message.startsWith('>')) {
|
||||||
if (message.startsWith('~')) {
|
|
||||||
await handleCommand(message, {
|
await handleCommand(message, {
|
||||||
eventEmitter,
|
eventEmitter,
|
||||||
currentTopic: topic, // Pass the current topic as a string
|
currentTopic: topic, // Pass the current topic as a string
|
||||||
@ -1173,7 +1193,8 @@ async function sendMessage(e) {
|
|||||||
leaveRoom,
|
leaveRoom,
|
||||||
createRoom,
|
createRoom,
|
||||||
listFiles,
|
listFiles,
|
||||||
deleteFile
|
deleteFile,
|
||||||
|
servePort
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
65
commands.js
65
commands.js
@ -11,7 +11,7 @@ if (fs.existsSync(agentAvatarPath)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export default async function handleCommand(command, context) {
|
export default async function handleCommand(command, context) {
|
||||||
const { eventEmitter, currentTopic, clearMessages, addMessage, joinRoom, leaveRoom, createRoom, listFiles } = context;
|
const { eventEmitter, currentTopic, clearMessages, addMessage, joinRoom, leaveRoom, createRoom, listFiles, deleteFile, servePort } = context;
|
||||||
|
|
||||||
console.log("Context received in handleCommand:", context); // Add logging
|
console.log("Context received in handleCommand:", context); // Add logging
|
||||||
|
|
||||||
@ -23,39 +23,82 @@ export default async function handleCommand(command, context) {
|
|||||||
console.log("Current topic:", currentTopic); // Add logging to check the current topic
|
console.log("Current topic:", currentTopic); // Add logging to check the current topic
|
||||||
|
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case '~clear':
|
case '>clear':
|
||||||
clearMessages(currentTopic);
|
clearMessages(currentTopic);
|
||||||
break;
|
break;
|
||||||
case '~ping':
|
case '>ping':
|
||||||
addMessage('LinkUp', 'pong', agentAvatar, currentTopic);
|
addMessage('LinkUp', 'pong', agentAvatar, currentTopic);
|
||||||
break;
|
break;
|
||||||
case '~help':
|
case '>help':
|
||||||
addMessage('LinkUp', 'Available commands:\n- ~clear\n- ~ping\n- ~help\n- ~join [topic]\n- ~leave\n- ~create [alias]\n- ~list-files', agentAvatar, currentTopic);
|
addMessage('LinkUp', 'Available commands:\n- >clear\n- >ping\n- >help\n- >join [topic]\n- >leave\n- >create [alias]\n- >list-files', agentAvatar, currentTopic);
|
||||||
break;
|
break;
|
||||||
case '~join':
|
case '>join':
|
||||||
if (restArgs) {
|
if (restArgs) {
|
||||||
await joinRoom(currentTopic, restArgs);
|
await joinRoom(currentTopic, restArgs);
|
||||||
} else {
|
} else {
|
||||||
addMessage('LinkUp', 'Usage: ~join [topic]', agentAvatar, currentTopic);
|
addMessage('LinkUp', 'Usage: >join [topic]', agentAvatar, currentTopic);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '~leave':
|
case '>leave':
|
||||||
leaveRoom(currentTopic);
|
leaveRoom(currentTopic);
|
||||||
break;
|
break;
|
||||||
case '~create':
|
case '>create':
|
||||||
if (restArgs) {
|
if (restArgs) {
|
||||||
await createRoom(currentTopic, restArgs);
|
await createRoom(currentTopic, restArgs);
|
||||||
} else {
|
} else {
|
||||||
addMessage('LinkUp', 'Usage: ~create [alias]', agentAvatar, currentTopic);
|
addMessage('LinkUp', 'Usage: >create [alias]', agentAvatar, currentTopic);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '~list-files':
|
case '>list-files':
|
||||||
const files = await listFiles();
|
const files = await listFiles();
|
||||||
const fileList = files.length > 0 ? files.map(file => `- ${file}`).join('\n') : 'No files available';
|
const fileList = files.length > 0 ? files.map(file => `- ${file}`).join('\n') : 'No files available';
|
||||||
addMessage('LinkUp', `Available files:\n${fileList}`, agentAvatar, currentTopic);
|
addMessage('LinkUp', `Available files:\n${fileList}`, agentAvatar, currentTopic);
|
||||||
|
|
||||||
|
// Render the file list with delete buttons
|
||||||
|
renderFileList(files, deleteFile, servePort);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
addMessage('LinkUp', `Unknown command: ${cmd}`, agentAvatar, currentTopic);
|
addMessage('LinkUp', `Unknown command: ${cmd}`, agentAvatar, currentTopic);
|
||||||
console.log('Unknown command:', command);
|
console.log('Unknown command:', command);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function renderFileList(files, deleteFile, servePort) {
|
||||||
|
const container = document.querySelector('#messages');
|
||||||
|
if (!container) {
|
||||||
|
console.error('Element #messages not found');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileList = document.createElement('ul');
|
||||||
|
|
||||||
|
files.forEach(file => {
|
||||||
|
const listItem = document.createElement('li');
|
||||||
|
const fileButton = document.createElement('button');
|
||||||
|
fileButton.textContent = file.trim();
|
||||||
|
fileButton.onclick = () => downloadFile(file.trim(), servePort);
|
||||||
|
|
||||||
|
const deleteButton = document.createElement('button');
|
||||||
|
deleteButton.textContent = 'Delete';
|
||||||
|
deleteButton.onclick = async () => {
|
||||||
|
await deleteFile(file);
|
||||||
|
listItem.remove();
|
||||||
|
};
|
||||||
|
|
||||||
|
listItem.appendChild(fileButton);
|
||||||
|
listItem.appendChild(deleteButton);
|
||||||
|
fileList.appendChild(listItem);
|
||||||
|
});
|
||||||
|
|
||||||
|
container.appendChild(fileList);
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadFile(filename, servePort) {
|
||||||
|
const url = `http://localhost:${servePort}/files/${filename}`;
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = filename;
|
||||||
|
document.body.appendChild(link);
|
||||||
|
link.click();
|
||||||
|
document.body.removeChild(link);
|
||||||
|
}
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 251 KiB After Width: | Height: | Size: 55 KiB |
@ -11,7 +11,8 @@
|
|||||||
"minWidth": 955,
|
"minWidth": 955,
|
||||||
"minHeight": 547,
|
"minHeight": 547,
|
||||||
"width": 955
|
"width": 955
|
||||||
}
|
},
|
||||||
|
"links": ["http://127.0.0.1", "http://localhost", "https://ka-f.fontawesome.com", "https://cdn.jsdelivr.net", "https://cdnjs.cloudflare.com"]
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -24,12 +25,15 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"b4a": "^1.6.6",
|
"b4a": "^1.6.6",
|
||||||
"corestore": "^6.18.2",
|
"corestore": "^6.18.2",
|
||||||
|
"dompurify": "^3.1.6",
|
||||||
"dotenv": "^16.4.5",
|
"dotenv": "^16.4.5",
|
||||||
"electron": "^30.0.8",
|
"electron": "^30.0.8",
|
||||||
|
"highlight.js": "^11.10.0",
|
||||||
"hypercore-crypto": "^3.4.1",
|
"hypercore-crypto": "^3.4.1",
|
||||||
"hyperdrive": "^11.8.1",
|
"hyperdrive": "^11.8.1",
|
||||||
"hyperswarm": "^4.7.14",
|
"hyperswarm": "^4.7.14",
|
||||||
"localdrive": "^1.11.4",
|
"localdrive": "^1.11.4",
|
||||||
|
"markdown-it": "^14.1.0",
|
||||||
"marked": "^12.0.2",
|
"marked": "^12.0.2",
|
||||||
"serve-drive": "^5.0.8"
|
"serve-drive": "^5.0.8"
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user