35702-vm/index.php
Flatlogic Bot 36400880a5 PyCharm 2023.3.2 (Community Edition)
Build #PC-233
2025-11-14 07:40:28 +00:00

408 lines
16 KiB
PHP

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chatterly</title>
<meta name="description" content="Built with Flatlogic Generator">
<meta name="keywords" content="chatterly, chat app, messaging, instant messaging, mobile chat, group chat, media sharing, real-time communication, Built with Flatlogic Generator">
<meta property="og:title" content="Chatterly">
<meta property="og:description" content="Built with Flatlogic Generator">
<meta property="og:image" content="">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:image" content="">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<div class="mobile-chat-container">
<header class="chat-header">
<div class="d-flex align-items-center">
<a href="#" class="text-white me-3"><i class="bi bi-arrow-left"></i></a>
<img src="https://i.pravatar.cc/40?u=jane" alt="Avatar" class="avatar">
<div class="ms-3">
<h1 class="h6 mb-0">Jane Doe</h1>
<p class="small text-white-50 mb-0">online</p>
</div>
</div>
<div class="actions">
<a href="#" class="text-white"><i class="bi bi-camera-video"></i></a>
<a href="#" class="text-white ms-3"><i class="bi bi-telephone"></i></a>
<a href="#" class="text-white ms-3" id="settings-button"><i class="bi bi-gear"></i></a>
</div>
</header>
<main class="chat-body">
<div class="message-day-divider">
<span>Today</span>
</div>
<div class="message received">
<div class="message-bubble">
<p class="mb-0">Hey! How's it going?</p>
<span class="message-time">10:00 AM</span>
</div>
</div>
<div class="message sent">
<div class="message-bubble">
<p class="mb-0">Pretty good! Just working on a new project. You?</p>
<span class="message-time">10:01 AM</span>
</div>
</div>
<div class="message received">
<div class="message-bubble">
<p class="mb-0">Same here. This is a mockup of the chat interface.</p>
<span class="message-time">10:02 AM</span>
</div>
</div>
<div class="message received">
<div class="message-bubble">
<p class="mb-0">What do you think?</p>
<span class="message-time">10:02 AM</span>
</div>
</div>
<div class="message sent">
<div class="message-bubble">
<p class="mb-0">Looks great! The dark mode is really nice.</p>
<span class="message-time">10:03 AM</span>
</div>
</div>
<div class="message sent">
<div class="message-bubble">
<p class="mb-0">And the primary color #0D6EFD for my messages looks cool.</p>
<span class="message-time">10:03 AM</span>
</div>
</div>
<div class="message sent">
<div class="message-bubble voice-message">
<i class="bi bi-play-circle-fill"></i>
<div class="voice-progress"></div>
<span class="message-time">10:05 AM</span>
</div>
</div>
</main>
<div class="chat-footer">
<textarea id="message-input" class="form-control" placeholder="Type a message..."></textarea>
<button id="emoji-btn" class="btn btn-secondary"><i class="bi bi-emoji-smile"></i></button>
<button id="attachment-btn" class="btn btn-secondary"><i class="bi bi-paperclip"></i></button>
<input type="file" id="attachment-input" style="display: none;" accept="image/*,video/*">
<button id="mic-btn" class="btn btn-primary mic-button"><i class="bi bi-mic-fill"></i></button>
<button id="send-button" class="btn btn-primary send-button" style="display: none;"><i class="bi bi-send-fill"></i></button>
</div>
<div class="theme-panel" id="theme-panel">
<h5>Theme</h5>
<button class="btn btn-sm btn-light" id="light-theme-button">Light</button>
<button class="btn btn-sm btn-dark" id="dark-theme-button">Dark</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
// Theme switcher logic
const settingsButton = document.getElementById('settings-button');
const themePanel = document.getElementById('theme-panel');
const lightThemeButton = document.getElementById('light-theme-button');
const darkThemeButton = document.getElementById('dark-theme-button');
settingsButton.addEventListener('click', (e) => {
e.preventDefault();
themePanel.classList.toggle('show');
});
function setTheme(theme) {
document.body.dataset.theme = theme;
localStorage.setItem('theme', theme);
themePanel.classList.remove('show');
}
lightThemeButton.addEventListener('click', () => setTheme('light'));
darkThemeButton.addEventListener('click', () => setTheme('dark'));
// Apply saved theme on load
const savedTheme = localStorage.getItem('theme') || 'dark';
document.body.dataset.theme = savedTheme;
// Hide theme panel if clicked outside
document.addEventListener('click', (e) => {
if (!themePanel.contains(e.target) && !settingsButton.contains(e.target)) {
themePanel.classList.remove('show');
}
});
// Existing scripts for message input and voice recording
const messageInput = document.getElementById('message-input');
const sendButton = document.getElementById('send-button');
const micButton = document.getElementById('mic-btn');
messageInput.addEventListener('input', () => {
if (messageInput.value.trim() !== '') {
sendButton.style.display = 'block';
micButton.style.display = 'none';
} else {
sendButton.style.display = 'none';
micButton.style.display = 'block';
}
});
const chatBody = document.querySelector('.chat-body');
let mediaRecorder;
let audioChunks = [];
let voiceMessages = []; // To store voice message blobs
micButton.addEventListener('mousedown', async () => {
if (!navigator.mediaDevices || !navigator.mediaDevices.getUserMedia) {
alert('Your browser does not support audio recording.');
return;
}
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.start();
audioChunks = [];
mediaRecorder.addEventListener('dataavailable', event => {
audioChunks.push(event.data);
});
micButton.classList.add('recording');
} catch (err) {
console.error('Error accessing microphone:', err);
alert('Could not access your microphone. Please check your browser permissions.');
}
});
micButton.addEventListener('mouseup', () => {
if (mediaRecorder && mediaRecorder.state === 'recording') {
mediaRecorder.stop();
micButton.classList.remove('recording');
mediaRecorder.addEventListener('stop', () => {
const audioBlob = new Blob(audioChunks, { type: 'audio/webm' });
const audioUrl = URL.createObjectURL(audioBlob);
const voiceMessageId = voiceMessages.push(audioBlob) - 1;
const messageTime = new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
const voiceMessageHTML = `
<div class="message sent">
<div class="message-bubble voice-message" data-voice-id="${voiceMessageId}">
<audio src="${audioUrl}" style="display:none;"></audio>
<div class="voice-message-controls">
<button class="play-button btn"><i class="bi bi-play-circle-fill"></i></button>
<div class="voice-progress-container">
<div class="voice-progress"></div>
</div>
</div>
<button class="share-button btn"><i class="bi bi-share-fill"></i></button>
<span class="message-time">${messageTime}</span>
</div>
</div>
`;
chatBody.insertAdjacentHTML('beforeend', voiceMessageHTML);
});
}
});
chatBody.addEventListener('click', async (e) => {
const playButton = e.target.closest('.play-button');
const shareButton = e.target.closest('.share-button');
if (playButton) {
const voiceMessage = playButton.closest('.voice-message');
const audio = voiceMessage.querySelector('audio');
const playIcon = playButton.querySelector('i');
if (audio.paused) {
audio.play();
playIcon.classList.remove('bi-play-circle-fill');
playIcon.classList.add('bi-pause-circle-fill');
} else {
audio.pause();
playIcon.classList.remove('bi-pause-circle-fill');
playIcon.classList.add('bi-play-circle-fill');
}
audio.addEventListener('ended', () => {
playIcon.classList.remove('bi-pause-circle-fill');
playIcon.classList.add('bi-play-circle-fill');
voiceMessage.querySelector('.voice-progress').style.width = `0%`;
});
audio.addEventListener('timeupdate', () => {
const progress = (audio.currentTime / audio.duration) * 100;
voiceMessage.querySelector('.voice-progress').style.width = `${progress}%`;
});
}
if (shareButton) {
const voiceMessage = shareButton.closest('.voice-message');
const voiceId = voiceMessage.dataset.voiceId;
const audioBlob = voiceMessages[voiceId];
if (!audioBlob) {
alert('Could not find the audio to share.');
return;
}
const audioFile = new File([audioBlob], `chatterly-voice-${new Date().toISOString()}.webm`, {
type: audioBlob.type,
});
if (navigator.canShare && navigator.canShare({ files: [audioFile] })) {
try {
await navigator.share({
files: [audioFile],
title: 'Voice Message',
text: 'Listen to my voice message from Chatterly.',
});
} catch (error) {
console.error('Error sharing:', error);
}
} else {
// Fallback for browsers that don't support sharing files
const link = document.createElement('a');
link.href = URL.createObjectURL(audioBlob);
link.download = `chatterly-voice-${new Date().toISOString()}.webm`;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
}
});
// Emoji panel logic
const emojiBtn = document.getElementById('emoji-btn');
const emojiPanel = document.getElementById('emoji-panel');
const emojiGrid = document.getElementById('emojis');
const stickerGrid = document.getElementById('stickers');
const categoryBtns = document.querySelectorAll('.category-btn');
emojiBtn.addEventListener('click', () => {
emojiPanel.classList.toggle('show');
});
const emojis = ['πŸ˜€', 'πŸ˜‚', '😍', 'πŸ€”', 'πŸ‘', '❀️', 'πŸŽ‰', 'πŸ”₯', 'πŸ’―', 'πŸ™', '😎', '😒', '😑', '🀯', '😴', 'πŸ‘‹'];
emojis.forEach(emoji => {
const emojiEl = document.createElement('span');
emojiEl.textContent = emoji;
emojiGrid.appendChild(emojiEl);
});
const stickers = [
'https://picsum.photos/id/10/80/80',
'https://picsum.photos/id/20/80/80',
'https://picsum.photos/id/30/80/80',
'https://picsum.photos/id/40/80/80',
'https://picsum.photos/id/50/80/80',
'https://picsum.photos/id/60/80/80',
];
stickers.forEach(stickerUrl => {
const stickerEl = document.createElement('img');
stickerEl.src = stickerUrl;
stickerGrid.appendChild(stickerEl);
});
categoryBtns.forEach(btn => {
btn.addEventListener('click', () => {
categoryBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
if (btn.dataset.category === 'emojis') {
emojiGrid.classList.remove('hidden');
stickerGrid.classList.add('hidden');
} else {
emojiGrid.classList.add('hidden');
stickerGrid.classList.remove('hidden');
}
});
});
function sendMessage(content) {
const messageTime = new Date().toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit' });
const message = `
<div class="message sent">
<div class="message-bubble">
${content}
<span class="message-time">${messageTime}</span>
</div>
</div>
`;
chatBody.insertAdjacentHTML('beforeend', message);
chatBody.scrollTop = chatBody.scrollHeight;
emojiPanel.classList.remove('show');
}
emojiGrid.addEventListener('click', e => {
if (e.target.tagName === 'SPAN') {
sendMessage(`<p class="mb-0">${e.target.textContent}</p>`);
}
});
stickerGrid.addEventListener('click', e => {
if (e.target.tagName === 'IMG') {
sendMessage(`<img src="${e.target.src}" style="max-width: 100px; height: auto; display: block;">`);
}
});
</script>
<script>
const mediaBtn = document.querySelector('.media-btn');
const mediaInput = document.getElementById('media-input');
const chatMessages = document.querySelector('.chat-messages');
if (mediaBtn) {
mediaBtn.addEventListener('click', () => {
if (mediaInput) {
mediaInput.click();
}
});
}
if (mediaInput) {
mediaInput.addEventListener('change', (event) => {
const file = event.target.files[0];
if (file && file.type.startsWith('image/')) {
const reader = new FileReader();
reader.onload = (e) => {
const imageSrc = e.target.result;
createImageMessage(imageSrc);
};
reader.readAsDataURL(file);
}
});
}
function createImageMessage(imageSrc) {
const messageId = 'msg-' + new Date().getTime();
const messageHTML = `
<div class="message-bubble sent" id="${messageId}">
<div class="message-content image-message">
<img src="${imageSrc}" alt="Image message">
</div>
<div class="message-timestamp">${new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' })}</div>
</div>
`;
if (chatMessages) {
chatMessages.insertAdjacentHTML('beforeend', messageHTML);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
}
</script>
</body>
</html>