MarfinF's picture
- fix mic error
7eb1cbd
<!DOCTYPE html>
<html lang="en">
<head>
<title>🎶 Chattifin</title>
<style>
body {
font-family: Arial, sans-serif;
background: #121212;
color: white;
text-align: center;
}
#chat-container {
width: 50%;
margin: auto;
padding: 10px;
}
.message {
padding: 10px;
margin: 5px 0;
border-radius: 10px;
}
.user {
background: #007bff;
color: white;
text-align: right;
}
.bot {
background: #28a745;
color: white;
}
input,
button {
margin-top: 10px;
padding: 10px;
border: none;
border-radius: 5px;
}
input {
width: 40%;
}
button {
background: #ff9800;
color: white;
cursor: pointer;
}
audio {
margin-top: 10px;
width: 100%;
}
#chat-box {
display: flex;
flex-direction: column;
gap: 8px;
}
.message {
padding: 10px 15px;
border-radius: 10px;
max-width: 70%;
word-wrap: break-word;
}
.user-message {
align-self: flex-end;
background-color: #007bff;
color: white;
border-bottom-right-radius: 0;
}
.other-user-message {
align-self: flex-start;
background-color: #e0e0e0;
color: black;
border-bottom-left-radius: 0;
}
.recommendation-message {
align-self: center;
background-color: #28a745;
color: white;
font-weight: bold;
border-radius: 12px;
padding: 15px;
text-align: center;
box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.2);
}
/* MODAL STYLES */
.modal {
display: block;
/* Show on load */
position: fixed;
z-index: 1;
left: 0;
top: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.6);
display: flex;
justify-content: center;
align-items: center;
}
.modal-content {
background: white;
padding: 20px;
border-radius: 8px;
text-align: center;
color: black;
width: 300px;
}
.modal-content input {
width: 80%;
padding: 8px;
margin-top: 10px;
}
.modal-content button {
background: #007bff;
color: white;
padding: 8px 15px;
margin-top: 10px;
cursor: pointer;
border-radius: 5px;
border: none;
}
#voice-btn {
background: #d8e7f8;
color: black;
padding: 8px 15px;
margin-top: 10px;
cursor: pointer;
border-radius: 5px;
border: none;
}
#mic-bubble {
width: 60px;
height: 60px;
border-radius: 50%;
background-color: #555;
margin-left: 10px;
cursor: pointer;
transition: background-color 0.3s ease, transform 0.3s ease;
}
/* Saat recording aktif */
#mic-bubble.recording {
background-color: red;
animation: pulse-recording 1s infinite;
}
/* Saat suara terdeteksi (speechstart) */
#mic-bubble.voice-active {
background-color: #00e676;
box-shadow: 0 0 12px 4px rgba(0, 230, 118, 0.6);
animation: pulse-voice 0.5s ease-out;
}
#cafe-mode-btn {
background: linear-gradient(to right, #b47b48, #d5a679);
border: none;
color: white;
padding: 10px 20px;
margin-bottom: 20px;
border-radius: 25px;
font-size: 16px;
font-family: 'Courier New', Courier, monospace;
cursor: pointer;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
}
#cafe-mode-btn:hover {
transform: scale(1.05);
box-shadow: 0 6px 14px rgba(0, 0, 0, 0.25);
}
#voice-btn.recording {
animation: pulse 1s infinite;
background-color: red !important;
}
@keyframes pulse-recording {
0% {
box-shadow: 0 0 0 0 rgba(255, 0, 0, 0.4);
}
70% {
box-shadow: 0 0 0 15px rgba(255, 0, 0, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(255, 0, 0, 0);
}
}
@keyframes pulse-voice {
0% {
transform: scale(1);
}
50% {
transform: scale(1.2);
}
100% {
transform: scale(1);
}
}
</style>
</head>
<body>
<h1>🎵 Chattifin</h1>
<!-- Chat Box -->
<div id="chat-container">
<div id="user-list" style="margin-bottom: 10px; text-align: left;"></div>
<div id="chat-box"></div>
<br>
<input type="text" id="message" placeholder="Ketik pesanmu..." disabled>
<div id="mic-bubble" title="~"></div>
<button id="message-send" onclick="sendMessage(null)" disabled>Kirim</button>
<button id="voice-btn" onclick="toggleVoice()" disabled>🎙</button>
<audio hidden="true" id="music-player" controls></audio>
</div>
<!-- MODAL FOR USERNAME INPUT -->
<div id="username-modal" class="modal">
<div class="modal-content">
<h2>Masukkan Namamu...</h2>
<input type="text" id="username" placeholder="Your Name">
<br>
<button onclick="connectChat(false)">Join Chat</button>
<p>Atau</p>
<button id="cafe-mode-btn" onclick="connectChat(true)">Cafe Mode</button>
</div>
</div>
<script>
const chatBox = document.getElementById("chat-box");
const chatTyping = document.getElementById("message");
const chatSending = document.getElementById("message-send");
const chatVoice = document.getElementById("voice-btn")
const userListDiv = document.getElementById("user-list");
const dialogUserName = document.getElementById("username");
const dialog = document.getElementById("username-modal");
const micBubble = document.getElementById("mic-bubble");
const musicPlayer = document.getElementById("music-player");
let ws;
let username = "";
let musicStatus = "";
let delayedMusic = {
song: "",
genre: ""
};
let isCafe = false;
const SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition;
if (!SpeechRecognition) {
alert("Browser tidak mendukung Speech Recognition. Gunakan Google Chrome.");
}
const recognition = new SpeechRecognition();
function connectChat(pIsCafe) {
isCafe = pIsCafe;
username = dialogUserName.value.trim();
if (!username && isCafe == false) {
alert("Please enter a username!");
return;
}
console.log("location host")
console.log(location.host)
// ws = new WebSocket(`${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/chat/${username}`);
if (isCafe == true) {
userListDiv.innerHTML = "<strong>👥 Mulailah ngobrol dan kami sesuaikan alunan irama yang sesuai untuk anda 🎵</strong>"
chatTyping.style.display = "none"
chatSending.style.display = "none"
chatVoice.style.display = "none"
startRecognition()
username = "cafe"
} else {
micBubble.style.display = "none"
chatSending.disabled = false
chatVoice.disabled = false
}
// ws = new WebSocket(`ws://localhost:8000/chat/${username}`);
ws = new WebSocket(`${location.protocol === 'https:' ? 'wss' : 'ws'}://${location.host}/chat/${username}`);
musicPlayer.addEventListener("play", () => {
musicStatus = "playing"
});
musicPlayer.addEventListener("ended", () => {
musicStatus = "stop"
if (delayedMusic.song != "") playCurrentMusic(delayedMusic)
});
ws.onmessage = function (event) {
const data = JSON.parse(event.data);
if (data.type === "user_list") {
userListDiv.innerHTML = `<strong>👥 Online:</strong> ${data.users.join(", ")}`;
return;
}
if (data.username === username) {
// Udah di-render pas kirim, skip
return;
}
if (data.recommendations) {
if (musicStatus != "playing") {
console.log("data")
console.log(data)
playCurrentMusic({
song: data.recommendations[0],
genre: data.genre
})
} else {
delayedMusic = {
song: data.recommendations[0],
genre: data.genre
}
}
} else {
let messageDiv = document.createElement("div");
messageDiv.classList.add("message", "other-user-message");
messageDiv.innerHTML = `<strong>${data.username}</strong>: ${data.message}`;
chatBox.appendChild(messageDiv);
}
chatBox.scrollTop = chatBox.scrollHeight;
};
ws.onopen = function () {
chatTyping.disabled = false;
chatTyping.nextElementSibling.disabled = false;
// Hide modal
dialog.style.display = "none";
};
ws.onerror = function () {
alert("WebSocket connection error! Ensure server is running.");
};
ws.onclose = function () {
alert("Connection closed!");
};
}
function playCurrentMusic(recommendationSong) {
delayedMusic = {
song: "",
genre: ""
};
let recommendationDiv = document.createElement("div");
recommendationDiv.classList.add("recommendation-message");
recommendationDiv.innerHTML = `🎵 ${recommendationSong.genre}`;
chatBox.appendChild(recommendationDiv);
console.log("recommendation song")
console.log(recommendationSong)
musicPlayer.src = recommendationSong.song
musicPlayer.play()
}
function sendMessage(voiceChat) {
let inputField = chatTyping;
console.log("sending")
console.log(voiceChat)
let messageText = voiceChat == undefined || voiceChat == null ? inputField.value.trim() : voiceChat;
if (messageText === "" || !ws || ws.readyState !== WebSocket.OPEN) return;
// Send message to WebSocket server
ws.send(JSON.stringify({ username, message: messageText }));
// Show user message in chat
let messageDiv = document.createElement("div");
messageDiv.classList.add("message", "user-message");
messageDiv.innerHTML = `<strong>${username}</strong>: ${messageText}`;
chatBox.appendChild(messageDiv);
inputField.value = "";
chatBox.scrollTop = chatBox.scrollHeight;
}
function startRecognition() {
recognition.lang = 'id-ID';
recognition.interimResults = false;
recognition.maxAlternatives = 1;
recognition.start();
recognition.onstart = function () {
micBubble.classList.add("recording");
};
recognition.onspeechstart = function () {
micBubble.classList.add("voice-active");
};
recognition.onspeechend = function () {
micBubble.classList.remove("voice-active");
};
recognition.onend = function () {
micBubble.classList.remove("recording", "voice-active");
console.log("cafe")
console.log(isCafe)
if (isCafe == true) {
console.log("start ga sih")
startRecognition();
} else {
recognition.stop();
}
};
recognition.onresult = function (event) {
const transcript = event.results[0][0].transcript;
console.log("transcript")
console.log(transcript)
sendMessage(transcript)
};
recognition.onerror = function (event) {
micBubble.classList.remove("recording", "voice-active");
// alert('Terjadi kesalahan: ' + event.error);
};
}
</script>
</body>
</html>