first attempt at audio messages

This commit is contained in:
Raven Scott 2024-06-13 03:53:23 -04:00
parent 060308ec92
commit 6b3f043332
3 changed files with 127 additions and 0 deletions

110
app.js
View File

@ -54,6 +54,7 @@ async function initialize() {
const removeRoomBtn = document.querySelector('#remove-room-btn'); const removeRoomBtn = document.querySelector('#remove-room-btn');
const attachFileButton = document.getElementById('attach-file'); const attachFileButton = document.getElementById('attach-file');
const fileInput = document.getElementById('file-input'); const fileInput = document.getElementById('file-input');
const talkButton = document.getElementById('talk-btn');
if (registerForm) { if (registerForm) {
registerForm.addEventListener('submit', registerUser); registerForm.addEventListener('submit', registerUser);
@ -87,6 +88,9 @@ async function initialize() {
if (fileInput) { if (fileInput) {
fileInput.addEventListener('change', handleFileInput); fileInput.addEventListener('change', handleFileInput);
} }
if (talkButton) {
setupTalkButton();
}
const configExists = fs.existsSync("./config.json"); const configExists = fs.existsSync("./config.json");
if (configExists) { if (configExists) {
@ -138,6 +142,12 @@ async function initialize() {
} }
} else if (messageObj.type === 'message') { } else if (messageObj.type === 'message') {
onMessageAdded(messageObj.name, messageObj.message, messageObj.avatar, messageObj.topic); onMessageAdded(messageObj.name, messageObj.message, messageObj.avatar, messageObj.topic);
} else if (messageObj.type === 'audio') {
const audioBuffer = b4a.from(messageObj.audio, 'base64');
const filePath = `/audio/${Date.now()}.webm`;
await drive.put(filePath, audioBuffer);
const audioUrl = `http://localhost:${servePort}${filePath}`;
addAudioMessage(messageObj.name, audioUrl, messageObj.avatar, messageObj.topic);
} else { } else {
console.error('Received unknown message type:', messageObj); console.error('Received unknown message type:', messageObj);
} }
@ -185,6 +195,68 @@ async function initialize() {
}); });
} }
function setupTalkButton() {
const talkButton = document.getElementById('talk-btn');
if (!talkButton) return;
let mediaRecorder;
let audioChunks = [];
talkButton.addEventListener('mousedown', async () => {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start();
mediaRecorder.addEventListener('dataavailable', event => {
audioChunks.push(event.data);
});
mediaRecorder.addEventListener('stop', async () => {
const audioBlob = new Blob(audioChunks);
audioChunks = [];
const arrayBuffer = await audioBlob.arrayBuffer();
const buffer = new Uint8Array(arrayBuffer);
const topic = document.querySelector('#chat-room-topic').innerText;
const filePath = `/audio/${Date.now()}.webm`;
await drive.put(filePath, buffer);
const audioUrl = `http://localhost:${servePort}${filePath}`;
const audioMessage = {
type: 'audio',
name: config.userName,
audio: b4a.toString(buffer, 'base64'),
audioType: audioBlob.type,
avatar: updatePortInUrl(config.userAvatar),
topic: topic
};
console.log('Sending audio message:', audioMessage); // Debugging log
const peers = [...swarm.connections];
for (const peer of peers) {
peer.write(JSON.stringify(audioMessage));
}
addAudioMessage(config.userName, audioUrl, config.userAvatar, topic);
});
});
talkButton.addEventListener('mouseup', () => {
if (mediaRecorder) {
mediaRecorder.stop();
}
});
talkButton.addEventListener('mouseleave', () => {
if (mediaRecorder && mediaRecorder.state === 'recording') {
mediaRecorder.stop();
}
});
}
function registerUser(e) { function registerUser(e) {
e.preventDefault(); e.preventDefault();
const regUsername = document.querySelector('#reg-username').value; const regUsername = document.querySelector('#reg-username').value;
@ -557,6 +629,44 @@ function onMessageAdded(from, message, avatar, topic) {
} }
} }
function addAudioMessage(from, audioUrl, avatar, topic) {
console.log('Adding audio message:', { from, audioUrl, avatar, topic }); // Debugging log
const $div = document.createElement('div');
$div.classList.add('message');
const $img = document.createElement('img');
$img.src = updatePortInUrl(avatar) || 'https://via.placeholder.com/40';
$img.classList.add('avatar');
$div.appendChild($img);
const $content = document.createElement('div');
$content.classList.add('message-content');
const $header = document.createElement('div');
$header.classList.add('message-header');
$header.textContent = from;
$content.appendChild($header);
const $audio = document.createElement('audio');
$audio.controls = true;
if (from !== config.userName) {
$audio.autoplay = true; // Add autoplay attribute for peers only
}
$audio.src = audioUrl;
$audio.classList.add('attached-audio');
$content.appendChild($audio);
$div.appendChild($content);
// Only render the message if it's for the current room
const currentTopic = document.querySelector('#chat-room-topic').innerText;
if (currentTopic === topic) {
document.querySelector('#messages').appendChild($div);
scrollToBottom();
} else {
console.log(`Message for topic ${topic} not rendered because current topic is ${currentTopic}`); // Debugging log
}
}
function truncateHash(hash) { function truncateHash(hash) {
return `${hash.slice(0, 6)}...${hash.slice(-6)}`; return `${hash.slice(0, 6)}...${hash.slice(-6)}`;
} }

View File

@ -62,6 +62,7 @@
<textarea id="message" rows="4"></textarea> <textarea id="message" rows="4"></textarea>
<input type="file" id="file-input" style="display:none;"> <input type="file" id="file-input" style="display:none;">
<button type="button" id="attach-file">Attach File</button> <button type="button" id="attach-file">Attach File</button>
<button type="button" id="talk-btn">Talk</button> <!-- New Talk button -->
<input type="submit" value="Send" /> <input type="submit" value="Send" />
</form> </form>
<button id="remove-room-btn">Leave Room</button> <button id="remove-room-btn">Leave Room</button>

View File

@ -268,6 +268,22 @@ textarea::placeholder {
margin-left: 0.5rem; /* Add margin between buttons */ margin-left: 0.5rem; /* Add margin between buttons */
} }
#talk-btn {
padding: 0.5rem 1rem; /* Add padding to the button */
margin-left: 0.5rem; /* Add margin between buttons */
font-size: 14px;
border-radius: 5px;
cursor: pointer;
}
#talk-btn:active {
color : #fff; /* White text when clicked */
background-color: #f04747; /* Red color when clicked */
}
#talk-btn:hover {
}
/* Main container styles */ /* Main container styles */
main { main {
display: flex; display: flex;