Compare commits

...

12 Commits

Author SHA1 Message Date
7eddd45f79 Only auto play on peers 2024-07-07 22:49:15 -04:00
70bc69ddea auto play audio messages 2024-07-07 22:45:55 -04:00
aa70e42fdc change internal agent prefix 2024-07-07 22:40:22 -04:00
c530a8d69c Add back file menu 2024-07-07 22:39:31 -04:00
084cb02a11 fix icon message 2024-07-07 22:00:13 -04:00
a0c7eb1561 fix 2024-07-07 21:52:57 -04:00
43e9890235 readd updateIcon 2024-07-07 21:49:13 -04:00
ed4625275d init all guild topics on start 2024-07-07 21:40:52 -04:00
55875f468c more test 2024-07-07 21:30:09 -04:00
e0ad9c7067 more test 2024-07-07 21:21:55 -04:00
d423031cfb more test 2024-07-07 21:14:17 -04:00
181d011b8d more test 2024-07-07 21:08:30 -04:00
3 changed files with 154 additions and 23 deletions

104
app.js
View File

@ -141,6 +141,7 @@ async function initialize() {
loadConfigFromFile();
renderGuildList();
await connectToAllRooms();
await joinAllGuilds(); // Ensure the app joins all guilds on startup
}
if (!configExists) {
@ -179,11 +180,22 @@ async function initialize() {
console.log('Event switchRoom with roomTopic:', roomTopic);
switchRoom(guildTopic, roomTopic);
});
document.addEventListener('joinGuildRequest', (event) => {
const { guildTopic } = event.detail;
joinGuildRequest(guildTopic);
});
} catch (error) {
console.error('Error during initialization:', error);
}
}
async function joinAllGuilds() {
for (const guildTopic in config.guilds) {
await joinGuildRequest(guildTopic);
}
}
function setupEventListeners() {
const registerForm = document.querySelector('#register-form');
const selectAvatarButton = document.querySelector('#select-avatar');
@ -195,6 +207,7 @@ function setupEventListeners() {
const attachFileButton = document.getElementById('attach-file');
const fileInput = document.getElementById('file-input');
const talkButton = document.getElementById('talk-btn');
const joinGuildBtn = document.getElementById('join-guild');
if (registerForm) {
registerForm.addEventListener('submit', registerUser);
@ -234,6 +247,14 @@ function setupEventListeners() {
if (talkButton) {
setupTalkButton();
}
if (joinGuildBtn) {
joinGuildBtn.addEventListener('click', () => {
const guildTopic = document.getElementById('join-guild-topic').value.trim();
if (guildTopic) {
joinGuildRequest(guildTopic);
}
});
}
// Add event listeners only for room items
document.querySelectorAll('.room-item').forEach(item => {
@ -249,7 +270,7 @@ function setupEventListeners() {
});
}
function handleIncomingMessage(messageObj) {
function handleIncomingMessage(messageObj, connection) {
console.log('Received message:', messageObj); // Debugging log
if (messageObj.type === 'icon') {
@ -347,6 +368,24 @@ function handleIncomingMessage(messageObj) {
renderGuildList();
joinGuild(guildTopic);
}
} else if (messageObj.type === 'guildRequest') {
const guildTopic = messageObj.guildTopic;
const guild = config.guilds[guildTopic];
if (guild) {
const guildResponseMessage = JSON.stringify({
type: 'guildResponse',
guildData: JSON.stringify({
guildTopic,
guildAlias: guild.alias,
rooms: guild.rooms,
owner: guild.owner
})
});
connection.write(guildResponseMessage);
}
} else if (messageObj.type === 'guildResponse') {
const guildData = messageObj.guildData;
processGuild(guildData);
} else {
console.error('Received unknown message type:', messageObj);
}
@ -360,7 +399,7 @@ async function handleConnection(connection, info) {
if (iconBuffer) {
const iconMessage = JSON.stringify({
type: 'icon',
username: config.userName,
name: config.userName,
avatar: b4a.toString(iconBuffer, 'base64'),
timestamp: Date.now()
});
@ -399,7 +438,7 @@ async function handleConnection(connection, info) {
connection.write(guildJoinMessage);
}
} else {
eventEmitter.emit('onMessage', messageObj);
eventEmitter.emit('onMessage', messageObj, connection);
}
});
@ -1008,7 +1047,6 @@ function addFileMessage(name, fileName, fileUrl, fileType, avatar, topic) {
container.scrollTop = container.scrollHeight;
}
}
function addAudioMessage(name, audioUrl, avatar, topic) {
const container = document.querySelector('#messages');
if (!container) {
@ -1037,6 +1075,10 @@ function addAudioMessage(name, audioUrl, avatar, topic) {
const audioElement = document.createElement('audio');
audioElement.src = audioUrl;
audioElement.controls = true;
// Autoplay only if the message is from a peer
if (name !== config.userName) {
audioElement.autoplay = true;
}
audioElement.classList.add('message-audio');
messageContent.appendChild(senderName);
@ -1050,6 +1092,7 @@ function addAudioMessage(name, audioUrl, avatar, topic) {
}
}
function addMessage(name, message, avatar, topic) {
const container = document.querySelector('#messages');
if (!container) {
@ -1077,6 +1120,7 @@ function addMessage(name, message, avatar, topic) {
const messageText = document.createElement('div');
messageText.classList.add('message-text');
messageText.innerHTML = message;
messageContent.appendChild(senderName);
@ -1090,6 +1134,19 @@ function addMessage(name, message, avatar, topic) {
}
}
async function updateIcon(username, avatarBuffer) {
const userIcon = document.querySelector(`img[src*="${username}.png"]`);
if (userIcon) {
const avatarBlob = new Blob([avatarBuffer], { type: 'image/png' });
const avatarUrl = URL.createObjectURL(avatarBlob);
userIcon.src = updatePortInUrl(avatarUrl);
config.userAvatar = avatarUrl;
writeConfigToFile("./config.json");
}
}
function clearMessages() {
const messagesContainer = document.querySelector('#messages');
while (messagesContainer.firstChild) {
@ -1110,8 +1167,7 @@ async function sendMessage(e) {
const timestamp = Date.now();
console.log("Sending message to current topic:", topic); // Add logging
if (message.startsWith('~')) {
if (message.startsWith('>')) {
await handleCommand(message, {
eventEmitter,
currentTopic: topic, // Pass the current topic as a string
@ -1121,7 +1177,8 @@ async function sendMessage(e) {
leaveRoom,
createRoom,
listFiles,
deleteFile
deleteFile,
servePort
});
return;
}
@ -1133,7 +1190,7 @@ async function sendMessage(e) {
const messageObj = JSON.stringify({
type: 'message',
name: config.userName,
avatar: config.userAvatar,
avatar: updatePortInUrl(config.userAvatar),
topic: topic,
timestamp: timestamp,
message
@ -1207,4 +1264,35 @@ function handleFileInput(event) {
}
}
async function joinGuildRequest(guildTopic) {
const guildTopicBuffer = b4a.from(guildTopic, 'hex');
if (!activeRooms.some(room => room.topic === guildTopic)) {
try {
const swarm = new Hyperswarm();
const discovery = swarm.join(guildTopicBuffer, { client: true, server: true });
await discovery.flushed();
swarm.on('connection', (connection, info) => {
handleConnection(connection, info);
// Request guild information from peers
const guildRequestMessage = JSON.stringify({
type: 'guildRequest',
guildTopic
});
connection.write(guildRequestMessage);
});
activeRooms.push({ topic: guildTopic, swarm, discovery });
console.log('Joined guild topic:', guildTopic); // Debugging log
updatePeerCount();
} catch (error) {
console.error('Error joining swarm for guild topic:', guildTopic, error);
}
}
}
window.joinGuildRequest = joinGuildRequest;
initialize();

View File

@ -11,7 +11,7 @@ if (fs.existsSync(agentAvatarPath)) {
}
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
@ -23,39 +23,82 @@ export default async function handleCommand(command, context) {
console.log("Current topic:", currentTopic); // Add logging to check the current topic
switch (cmd) {
case '~clear':
case '>clear':
clearMessages(currentTopic);
break;
case '~ping':
case '>ping':
addMessage('LinkUp', 'pong', agentAvatar, currentTopic);
break;
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);
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);
break;
case '~join':
case '>join':
if (restArgs) {
await joinRoom(currentTopic, restArgs);
} else {
addMessage('LinkUp', 'Usage: ~join [topic]', agentAvatar, currentTopic);
addMessage('LinkUp', 'Usage: >join [topic]', agentAvatar, currentTopic);
}
break;
case '~leave':
case '>leave':
leaveRoom(currentTopic);
break;
case '~create':
case '>create':
if (restArgs) {
await createRoom(currentTopic, restArgs);
} else {
addMessage('LinkUp', 'Usage: ~create [alias]', agentAvatar, currentTopic);
addMessage('LinkUp', 'Usage: >create [alias]', agentAvatar, currentTopic);
}
break;
case '~list-files':
case '>list-files':
const files = await listFiles();
const fileList = files.length > 0 ? files.map(file => `- ${file}`).join('\n') : 'No files available';
addMessage('LinkUp', `Available files:\n${fileList}`, agentAvatar, currentTopic);
// Render the file list with delete buttons
renderFileList(files, deleteFile, servePort);
break;
default:
addMessage('LinkUp', `Unknown command: ${cmd}`, agentAvatar, currentTopic);
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);
}

View File

@ -185,7 +185,7 @@
joinGuildBtn.addEventListener('click', async (event) => {
const guildTopic = document.getElementById('join-guild-topic').value.trim();
if (guildTopic) {
await processGuild(guildTopic);
await joinGuildRequest(guildTopic);
}
});