(function () { 'use strict'; var feed = document.getElementById('feed'); if (!feed) { return; } var loadMoreBtn = document.getElementById('load-more'); var emptyState = document.getElementById('feed-empty'); var spinner = loadMoreBtn ? loadMoreBtn.querySelector('.spinner-border') : null; var apiUrl = feed.dataset.api; var source = feed.dataset.source || ''; var range = feed.dataset.range || ''; var currentPage = parseInt(feed.dataset.page, 10) || 1; var hasMore = feed.dataset.hasMore === '1'; var loading = false; function timeAgo(iso) { var ts = Date.parse(iso); if (isNaN(ts)) { return ''; } var diff = Math.floor((Date.now() - ts) / 1000); if (diff < 60) { return 'just now'; } var units = [ [31536000, 'y'], [2592000, 'mo'], [604800, 'w'], [86400, 'd'], [3600, 'h'], [60, 'm'] ]; for (var i = 0; i < units.length; i++) { if (diff >= units[i][0]) { return Math.floor(diff / units[i][0]) + units[i][1] + ' ago'; } } return 'just now'; } function refreshTimes() { document.querySelectorAll('time[data-timestamp]').forEach(function (el) { var text = timeAgo(el.dataset.timestamp); if (text) { el.textContent = text; } }); } function setLoading(isLoading) { if (!loadMoreBtn) { return; } loadMoreBtn.disabled = isLoading; if (spinner) { spinner.classList.toggle('d-none', !isLoading); } } function updateButton() { if (!loadMoreBtn) { return; } loadMoreBtn.classList.toggle('d-none', !hasMore); } function loadMore() { if (loading || !hasMore) { return; } loading = true; setLoading(true); var params = new URLSearchParams({ page: String(currentPage + 1) }); if (source) { params.set('source', source); } if (range) { params.set('range', range); } fetch(apiUrl + '?' + params.toString(), { headers: { 'Accept': 'application/json' } }) .then(function (response) { if (!response.ok) { throw new Error('HTTP ' + response.status); } return response.json(); }) .then(function (data) { if (data.html) { feed.insertAdjacentHTML('beforeend', data.html); } currentPage = data.page; hasMore = Boolean(data.has_more); feed.dataset.page = String(currentPage); feed.dataset.hasMore = hasMore ? '1' : '0'; if (emptyState) { emptyState.classList.toggle('d-none', data.total > 0); } refreshTimes(); updateButton(); }) .catch(function (error) { console.error('Failed to load more items:', error); }) .finally(function () { loading = false; setLoading(false); }); } if (loadMoreBtn) { loadMoreBtn.addEventListener('click', loadMore); } refreshTimes(); window.setInterval(refreshTimes, 60000); })();