Auto commit: 2026-02-19T20:18:39.606Z
This commit is contained in:
parent
d9d6f803b0
commit
0a7bcfc414
@ -18,7 +18,7 @@ if ($method === 'GET') {
|
|||||||
unlink($path);
|
unlink($path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
db()->query("DELETE FROM messages WHERE type = 'image' AND created_at < DATE_SUB(NOW(), INTERVAL 5 SECOND)");
|
db()->query("DELETE FROM messages WHERE (type = 'image' OR type = 'reaction') AND created_at < DATE_SUB(NOW(), INTERVAL 5 SECOND)");
|
||||||
|
|
||||||
// Limpiar otros mensajes y archivos de más de 7 días
|
// Limpiar otros mensajes y archivos de más de 7 días
|
||||||
$oldImages = db()->prepare("SELECT message FROM messages WHERE type = 'image' AND created_at < DATE_SUB(NOW(), INTERVAL 7 DAY)");
|
$oldImages = db()->prepare("SELECT message FROM messages WHERE type = 'image' AND created_at < DATE_SUB(NOW(), INTERVAL 7 DAY)");
|
||||||
@ -117,7 +117,8 @@ if ($method === 'GET') {
|
|||||||
|
|
||||||
// Award points to the fan based on chat activity
|
// Award points to the fan based on chat activity
|
||||||
require_once __DIR__ . '/../includes/points_helper.php';
|
require_once __DIR__ . '/../includes/points_helper.php';
|
||||||
$newPoints = awardPoints($username, 5); // 5 points per message instead of 10 to balance
|
$pts = ($type === 'reaction') ? 1 : 5;
|
||||||
|
$newPoints = awardPoints($username, $pts);
|
||||||
|
|
||||||
// Auto-update Fan of the Month if this user has the highest points
|
// Auto-update Fan of the Month if this user has the highest points
|
||||||
$maxPointsStmt = db()->query("SELECT MAX(points) as max_p FROM fans");
|
$maxPointsStmt = db()->query("SELECT MAX(points) as max_p FROM fans");
|
||||||
|
|||||||
164
index.php
164
index.php
@ -1635,10 +1635,93 @@ $twitter_link = "https://twitter.com/";
|
|||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
.chat-msg-item.is-me .chat-msg-time {
|
.chat-msg-item.is-me .chat-msg-time {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Flying Emojis Animation */
|
||||||
|
.flying-emoji {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 20px;
|
||||||
|
font-size: 2.5rem;
|
||||||
|
user-select: none;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 10000;
|
||||||
|
animation: flyUp var(--duration) ease-out forwards;
|
||||||
|
filter: drop-shadow(0 0 10px rgba(0,0,0,0.3));
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes flyUp {
|
||||||
|
0% {
|
||||||
|
transform: translateY(0) translateX(0) scale(0.5) rotate(0deg);
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
10% {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(-20px) translateX(var(--drift)) scale(1.2) rotate(var(--rot));
|
||||||
|
}
|
||||||
|
100% {
|
||||||
|
transform: translateY(-100vh) translateX(calc(var(--drift) * 2)) scale(1) rotate(calc(var(--rot) * 2));
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reaction Buttons Container */
|
||||||
|
.reaction-buttons {
|
||||||
|
display: flex;
|
||||||
|
gap: 12px;
|
||||||
|
margin-top: 15px;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 10px;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
border-radius: 50px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
animation: slideUpFade 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideUpFade {
|
||||||
|
0% { transform: translateY(20px); opacity: 0; }
|
||||||
|
100% { transform: translateY(0); opacity: 1; }
|
||||||
|
}
|
||||||
|
|
||||||
|
.reaction-btn {
|
||||||
|
background: rgba(255, 255, 255, 0.1);
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 45px;
|
||||||
|
height: 45px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||||
|
backdrop-filter: blur(5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reaction-btn:hover {
|
||||||
|
transform: scale(1.2) translateY(-5px);
|
||||||
|
background: rgba(255, 255, 255, 0.2);
|
||||||
|
border-color: var(--primary-color);
|
||||||
|
box-shadow: 0 0 15px var(--primary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reaction-btn:active {
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
.reaction-overlay-active {
|
||||||
|
animation: pulse-reaction 1s infinite;
|
||||||
|
border: 2px solid #facc15 !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse-reaction {
|
||||||
|
0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(250, 204, 21, 0.7); }
|
||||||
|
70% { transform: scale(1.1); box-shadow: 0 0 0 15px rgba(250, 204, 21, 0); }
|
||||||
|
100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(250, 204, 21, 0); }
|
||||||
|
}
|
||||||
|
|
||||||
/* Top Listener Banner */
|
/* Top Listener Banner */
|
||||||
.top-listener-banner {
|
.top-listener-banner {
|
||||||
background: linear-gradient(135deg, rgba(250, 204, 21, 0.2), rgba(245, 158, 11, 0.3));
|
background: linear-gradient(135deg, rgba(250, 204, 21, 0.2), rgba(245, 158, 11, 0.3));
|
||||||
@ -2011,6 +2094,16 @@ $twitter_link = "https://twitter.com/";
|
|||||||
<!-- Mensajes se cargarán aquí -->
|
<!-- Mensajes se cargarán aquí -->
|
||||||
<div style="opacity: 0.5; font-size: 0.9rem; text-align: center; margin-top: 2rem;">Cargando mensajes...</div>
|
<div style="opacity: 0.5; font-size: 0.9rem; text-align: center; margin-top: 2rem;">Cargando mensajes...</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div id="dj-reaction-area" class="reaction-buttons" style="display: none; flex-direction: column; align-items: center; margin-bottom: 15px; border-radius: 20px; padding: 12px;">
|
||||||
|
<span style="font-size: 0.65rem; font-weight: 800; color: #facc15; text-transform: uppercase; margin-bottom: 8px; letter-spacing: 1px; opacity: 0.9;">¡Celebra con el DJ! 👇</span>
|
||||||
|
<div style="display: flex; gap: 12px;">
|
||||||
|
<button class="reaction-btn" onclick="sendReaction('❤️')" title="¡Me encanta!">❤️</button>
|
||||||
|
<button class="reaction-btn" onclick="sendReaction('🔥')" title="¡Fuego!">🔥</button>
|
||||||
|
<button class="reaction-btn" onclick="sendReaction('🎉')" title="¡Celebrar!">🎉</button>
|
||||||
|
<button class="reaction-btn" onclick="sendReaction('🎧')" title="¡Ese DJ!">🎧</button>
|
||||||
|
<button class="reaction-btn" onclick="sendReaction('🙌')" title="¡Subidón!">🙌</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="chat-input-area" style="display: flex; gap: 0.5rem; position: relative;">
|
<div class="chat-input-area" style="display: flex; gap: 0.5rem; position: relative;">
|
||||||
<input type="hidden" id="chat-user">
|
<input type="hidden" id="chat-user">
|
||||||
<button onclick="toggleEmojiPicker()" style="background: rgba(255,255,255,0.1); border: none; border-radius: 8px; color: white; padding: 0 0.5rem; cursor: pointer;">
|
<button onclick="toggleEmojiPicker()" style="background: rgba(255,255,255,0.1); border: none; border-radius: 8px; color: white; padding: 0 0.5rem; cursor: pointer;">
|
||||||
@ -2876,8 +2969,18 @@ $twitter_link = "https://twitter.com/";
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
document.body.style.animation = 'shake 0.5s cubic-bezier(.36,.07,.19,.97) both';
|
document.body.style.animation = 'shake 0.5s cubic-bezier(.36,.07,.19,.97) both';
|
||||||
}, 10);
|
}, 10);
|
||||||
|
|
||||||
|
// Trigger reaction buttons visibility
|
||||||
|
showReactionButtons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trigger flying emoji for reaction messages
|
||||||
|
if (msg.type === 'reaction' && index >= lastMessageCount && lastMessageCount > 0) {
|
||||||
|
spawnReactionEmoji(msg.message);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg.type === 'reaction') return;
|
||||||
|
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
const isLike = msg.message.includes('❤️');
|
const isLike = msg.message.includes('❤️');
|
||||||
const isMe = msg.username.toLowerCase() === currentUserName.toLowerCase();
|
const isMe = msg.username.toLowerCase() === currentUserName.toLowerCase();
|
||||||
@ -2986,6 +3089,65 @@ $twitter_link = "https://twitter.com/";
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function spawnReactionEmoji(emoji) {
|
||||||
|
const container = document.body;
|
||||||
|
const emojiEl = document.createElement('div');
|
||||||
|
emojiEl.className = 'flying-emoji';
|
||||||
|
emojiEl.innerText = emoji;
|
||||||
|
|
||||||
|
const startX = Math.random() * 80 + 10;
|
||||||
|
const drift = (Math.random() - 0.5) * 200;
|
||||||
|
const rotation = (Math.random() - 0.5) * 90;
|
||||||
|
const duration = 2 + Math.random() * 2;
|
||||||
|
|
||||||
|
emojiEl.style.left = `${startX}%`;
|
||||||
|
emojiEl.style.setProperty('--drift', `${drift}px`);
|
||||||
|
emojiEl.style.setProperty('--rot', `${rotation}deg`);
|
||||||
|
emojiEl.style.setProperty('--duration', `${duration}s`);
|
||||||
|
|
||||||
|
container.appendChild(emojiEl);
|
||||||
|
setTimeout(() => { emojiEl.remove(); }, duration * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
async function sendReaction(emoji) {
|
||||||
|
const userName = document.getElementById('user-name').value.trim() || 'Anónimo';
|
||||||
|
try {
|
||||||
|
await fetch('api/chat.php', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
username: userName,
|
||||||
|
message: emoji,
|
||||||
|
type: 'reaction'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
// Optimistic UI
|
||||||
|
spawnReactionEmoji(emoji);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error sending reaction:', error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showReactionButtons() {
|
||||||
|
const container = document.getElementById('dj-reaction-area');
|
||||||
|
if (container) {
|
||||||
|
container.style.display = 'flex';
|
||||||
|
container.style.opacity = '1';
|
||||||
|
container.classList.add('reaction-overlay-active');
|
||||||
|
|
||||||
|
if (window.reactionTimeout) clearTimeout(window.reactionTimeout);
|
||||||
|
|
||||||
|
window.reactionTimeout = setTimeout(() => {
|
||||||
|
container.classList.remove('reaction-overlay-active');
|
||||||
|
container.style.transition = 'opacity 1s ease';
|
||||||
|
container.style.opacity = '0';
|
||||||
|
setTimeout(() => {
|
||||||
|
if (container.style.opacity === '0') container.style.display = 'none';
|
||||||
|
}, 1000);
|
||||||
|
}, 20000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
chatMsg.addEventListener('keypress', (e) => {
|
chatMsg.addEventListener('keypress', (e) => {
|
||||||
if (e.key === 'Enter') sendChatMessage();
|
if (e.key === 'Enter') sendChatMessage();
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user