// ============================================ // 1. UTILITY FUNCTIONS // ============================================ // Function to shuffle array (Fisher-Yates) function shuffleArray(array) { const shuffled = [...array]; for (let i = shuffled.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]]; } return shuffled; } // Artist filter list const allowedArtists = [ 'εΎ’ Setto γ‚»γƒƒγƒˆ', 'Settoshi Tonami', 'Sethy Bowoy' ]; // Function to check if a track is by an allowed artist function isAllowedArtist(artist) { if (!artist) return false; const normalizedArtist = artist.trim().toLowerCase(); return allowedArtists.some(allowed => { const normalizedAllowed = allowed.trim().toLowerCase(); return normalizedArtist.includes(normalizedAllowed) || normalizedAllowed.includes(normalizedArtist); }); } // ============================================ // 2. CUSTOM LIGHTBOX // ============================================ let currentPhotos = []; let currentIndex = 0; // Build photo array from DOM function buildPhotoArray() { const photoItems = document.querySelectorAll('.photo-item'); currentPhotos = []; photoItems.forEach(item => { const image = item.querySelector('img'); // FIX: Use dataset values directly const date = item.dataset.date || ''; const pubkey = item.dataset.pubkey || ''; const alt = item.dataset.alt || ''; if (image) { currentPhotos.push({ url: image.src, alt: alt || image.alt || '', date: date, pubkey: pubkey }); } }); } // Open lightbox function openLightbox(index) { const lightbox = document.getElementById('customLightbox'); const lightboxImage = document.getElementById('lightboxImage'); const lightboxCaption = document.getElementById('lightboxCaption'); const lightboxMeta = document.getElementById('lightboxMeta'); const lightboxCounter = document.getElementById('lightboxCounter'); if (!lightbox || !lightboxImage || currentPhotos.length === 0) return; if (index < 0) index = currentPhotos.length - 1; if (index >= currentPhotos.length) index = 0; currentIndex = index; const photo = currentPhotos[currentIndex]; lightboxImage.src = photo.url; lightboxImage.alt = photo.alt; lightboxCaption.textContent = photo.alt; // FIX: Show date and pubkey in the meta let metaText = ''; if (photo.date) metaText += `πŸ“… ${photo.date}`; lightboxMeta.textContent = metaText || 'πŸ“… No date available'; lightboxCounter.textContent = `${currentIndex + 1} / ${currentPhotos.length}`; lightbox.classList.add('active'); document.body.style.overflow = 'hidden'; } // Close lightbox function closeLightbox() { const lightbox = document.getElementById('customLightbox'); if (!lightbox) return; lightbox.classList.remove('active'); document.body.style.overflow = ''; } // Navigate function prevPhoto() { openLightbox(currentIndex - 1); } function nextPhoto() { openLightbox(currentIndex + 1); } // Initialize lightbox event listeners function initLightbox() { const lightbox = document.getElementById('customLightbox'); const lightboxClose = document.getElementById('lightboxClose'); const lightboxPrev = document.getElementById('lightboxPrev'); const lightboxNext = document.getElementById('lightboxNext'); if (!lightbox) return; buildPhotoArray(); // Photo click listeners document.querySelectorAll('.photo-item img').forEach((img, index) => { img.removeEventListener('click', img._lightboxClick); img._lightboxClick = function(e) { e.preventDefault(); openLightbox(index); }; img.addEventListener('click', img._lightboxClick); }); // Control listeners lightboxClose.removeEventListener('click', closeLightbox); lightboxClose.addEventListener('click', closeLightbox); lightboxPrev.removeEventListener('click', prevPhoto); lightboxPrev.addEventListener('click', prevPhoto); lightboxNext.removeEventListener('click', nextPhoto); lightboxNext.addEventListener('click', nextPhoto); // Keyboard controls document.removeEventListener('keydown', handleLightboxKeydown); document.addEventListener('keydown', handleLightboxKeydown); // Click outside to close lightbox.removeEventListener('click', handleLightboxClick); lightbox.addEventListener('click', handleLightboxClick); } function handleLightboxKeydown(e) { const lightbox = document.getElementById('customLightbox'); if (!lightbox || !lightbox.classList.contains('active')) return; if (e.key === 'Escape') closeLightbox(); else if (e.key === 'ArrowLeft') prevPhoto(); else if (e.key === 'ArrowRight') nextPhoto(); } function handleLightboxClick(e) { const lightbox = document.getElementById('customLightbox'); if (e.target === lightbox) closeLightbox(); } // ============================================ // 3. MUSIC RENDERER // ============================================ function renderMusicTracks(tracks, containerId) { const container = document.getElementById(containerId); if (!container) return; const filteredTracks = tracks.filter(track => { let artist = ''; if (track.tags) { track.tags.forEach(tag => { if (tag[0] === 'artist') artist = tag[1]; }); } return isAllowedArtist(artist); }); if (filteredTracks.length === 0) { container.innerHTML = '

No tracks found for the selected artists.

'; return; } const shuffled = shuffleArray(filteredTracks); const selected = shuffled.slice(0, 6); container.innerHTML = ''; selected.forEach(track => { let title = '', url = '', image = '', artist = '', album = '', trackNumber = '', duration = '', released = '', language = '', tags = [], alt = '', content = ''; if (track.tags) { track.tags.forEach(tag => { if (tag[0] === 'title') title = tag[1]; else if (tag[0] === 'url') url = tag[1]; else if (tag[0] === 'image') image = tag[1]; else if (tag[0] === 'artist') artist = tag[1]; else if (tag[0] === 'album') album = tag[1]; else if (tag[0] === 'track_number') trackNumber = tag[1]; else if (tag[0] === 'duration') duration = tag[1]; else if (tag[0] === 'released') released = tag[1]; else if (tag[0] === 'language') language = tag[1]; else if (tag[0] === 't') tags.push(tag[1]); else if (tag[0] === 'alt') alt = tag[1]; }); } content = track.content || ''; const card = document.createElement('div'); card.className = 'music-card'; let cardHTML = ` ${image ? `${title}` : ''}

${title || 'Untitled'}

${artist ? `

${artist}

` : ''} ${album ? `

${album}

` : ''}
${url ? `` : ''}
${trackNumber ? `Track ${trackNumber}` : ''} ${duration ? `${duration}s` : ''} ${released ? `${released}` : ''} ${language ? `${language}` : ''}
${tags.map(t => `${t}`).join('')}
${content ? ` ` : ''} `; card.innerHTML = cardHTML; container.appendChild(card); }); initMusicEventListeners(); } function initMusicEventListeners() { document.querySelectorAll('.lyrics-toggle').forEach(button => { button.removeEventListener('click', handleLyricsToggle); button.addEventListener('click', handleLyricsToggle); }); } function handleLyricsToggle() { const lyrics = this.nextElementSibling; if (lyrics && lyrics.classList.contains('lyrics')) { if (lyrics.style.display === 'none') { lyrics.style.display = 'block'; this.innerHTML = 'Hide Info'; } else { lyrics.style.display = 'none'; this.innerHTML = 'Show Info'; } } } // ============================================ // 4. PICTURES RENDERER // ============================================ // Render random pictures (6 max) function renderRandomPictures(picturesData, containerId) { const container = document.getElementById(containerId); if (!container) return; const shuffled = shuffleArray(picturesData); const selected = shuffled.slice(0, 6); container.innerHTML = ''; selected.forEach(picture => { let imageUrl = ''; let alt = picture.content || ''; if (picture.tags) { picture.tags.forEach(tag => { if (tag[0] === 'imeta') { const imetaStr = tag[1]; const urlMatch = imetaStr.match(/url ([^\s]+)/); if (urlMatch) imageUrl = urlMatch[1]; const altMatch = imetaStr.match(/alt ([^\s]+)/); if (altMatch) alt = altMatch[1]; } }); } const item = document.createElement('div'); item.className = 'photo-item'; item.dataset.image = imageUrl; item.dataset.alt = alt; // FIX: Set the date in the dataset const date = new Date(picture.created_at * 1000); const dateStr = date.toLocaleDateString('en-US', { year: 'numeric', month: 'short', day: 'numeric' }); item.dataset.date = dateStr; item.dataset.pubkey = picture.pubkey || ''; item.innerHTML = ` ${imageUrl ? `${alt}` : ''}
πŸ“… ${dateStr}
`; container.appendChild(item); }); initLightbox(); } // ============================================ // 5. VIDEOS RENDERER // ============================================ function renderRandomVideos(videosData, containerId) { const container = document.getElementById(containerId); if (!container) return; const shuffled = shuffleArray(videosData); const selected = shuffled.slice(0, 2); container.innerHTML = ''; const posterImage = '/images/videoposter.png'; selected.forEach(video => { let videoUrl = '', mimeType = 'video/mp4', alt = video.content || '', dim = ''; let isVertical = false; if (video.tags) { video.tags.forEach(tag => { if (tag[0] === 'imeta') { const imetaStr = tag[1]; const urlMatch = imetaStr.match(/url ([^\s]+)/); if (urlMatch) videoUrl = urlMatch[1]; const mimeMatch = imetaStr.match(/m ([^\s]+)/); if (mimeMatch) mimeType = mimeMatch[1]; const altMatch = imetaStr.match(/alt ([^\s]+)/); if (altMatch) alt = altMatch[1]; const dimMatch = imetaStr.match(/dim ([^\s]+)/); if (dimMatch) { dim = dimMatch[1]; const [width, height] = dim.split('x').map(Number); if (height > width) isVertical = true; } } }); } const date = new Date(video.created_at * 1000); const dateStr = date.toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' }); const wrapperStyle = isVertical ? 'style="position:relative;padding-bottom:177.78%;height:0;overflow:hidden;background:var(--accent-black);"' : ''; const videoStyle = isVertical ? 'style="position:absolute;top:0;left:0;width:100%;height:100%;object-fit:cover;"' : 'style="width:100%;"'; const html = `
${videoUrl ? `
` : ''}

${alt}

πŸ“… ${dateStr} ${dim ? `πŸ“ ${dim}` : ''}
`; container.insertAdjacentHTML('beforeend', html); }); } // ============================================ // 6. REFRESH FUNCTIONS // ============================================ function refreshMusic() { if (window.allMusicData) renderMusicTracks(window.allMusicData, 'musicGrid'); } function refreshPictures() { if (window.allPicturesData) renderRandomPictures(window.allPicturesData, 'photoGrid'); } function refreshVideos() { if (window.allVideosData) renderRandomVideos(window.allVideosData, 'videoGrid'); } // ============================================ // 7. DOM CONTENT LOADED // ============================================ document.addEventListener('DOMContentLoaded', function() { // Sticky Navigation const stickyNav = document.getElementById('stickyNav'); const mainHeader = document.querySelector('.main-header'); let lastScrollY = window.scrollY; let ticking = false; function updateStickyNav() { const scrollY = window.scrollY; const headerHeight = mainHeader ? mainHeader.offsetHeight : 400; if (scrollY > headerHeight - 100) { stickyNav.classList.add('visible'); } else { stickyNav.classList.remove('visible'); } lastScrollY = scrollY; } window.addEventListener('scroll', function() { if (!ticking) { window.requestAnimationFrame(function() { updateStickyNav(); ticking = false; }); ticking = true; } }); setTimeout(updateStickyNav, 100); // Read More toggle for blog posts document.querySelectorAll('.read-more-toggle').forEach(button => { button.addEventListener('click', function() { const content = this.nextElementSibling; if (content.style.display === 'none') { content.style.display = 'block'; this.innerHTML = 'Read Less'; } else { content.style.display = 'none'; this.innerHTML = 'Read More'; } }); }); // Smooth scrolling for navigation links document.querySelectorAll('nav a').forEach(link => { link.addEventListener('click', function(e) { e.preventDefault(); const targetId = this.getAttribute('href'); const targetElement = document.querySelector(targetId); if (targetElement) { const navHeight = stickyNav.offsetHeight; const targetPosition = targetElement.getBoundingClientRect().top + window.pageYOffset - navHeight - 20; window.scrollTo({ top: targetPosition, behavior: 'smooth' }); } }); }); // Initialize Music if (window.allMusicData && window.allMusicData.length > 0) { renderMusicTracks(window.allMusicData, 'musicGrid'); } // Initialize Pictures if (window.allPicturesData && window.allPicturesData.length > 0) { renderRandomPictures(window.allPicturesData, 'photoGrid'); } else { initLightbox(); } // Initialize Videos if (window.allVideosData && window.allVideosData.length > 0) { renderRandomVideos(window.allVideosData, 'videoGrid'); } }); console.log('βœ… Site initialized successfully!');