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);
|
||||
}
|
||||
}
|
||||
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
|
||||
$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
|
||||
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
|
||||
$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;
|
||||
}
|
||||
|
||||
.chat-msg-item.is-me .chat-msg-time {
|
||||
.chat-msg-item.is-me .chat-msg-time {
|
||||
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 {
|
||||
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í -->
|
||||
<div style="opacity: 0.5; font-size: 0.9rem; text-align: center; margin-top: 2rem;">Cargando mensajes...</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;">
|
||||
<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;">
|
||||
@ -2876,7 +2969,17 @@ $twitter_link = "https://twitter.com/";
|
||||
setTimeout(() => {
|
||||
document.body.style.animation = 'shake 0.5s cubic-bezier(.36,.07,.19,.97) both';
|
||||
}, 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 isLike = msg.message.includes('❤️');
|
||||
@ -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) => {
|
||||
if (e.key === 'Enter') sendChatMessage();
|
||||
});
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user