hip
This commit is contained in:
+423
-62
@@ -3476,7 +3476,15 @@ window.cancelAnimFrame = (function () {
|
||||
}
|
||||
const locEl = document.querySelector('.location');
|
||||
if (locEl && !locEl.textContent.includes('#')) {
|
||||
locEl.textContent = locEl.textContent.replace(/#.*$/, '') + '#' + initialHash;
|
||||
const lastLink = locEl.querySelector('a:last-of-type');
|
||||
if (lastLink) {
|
||||
lastLink.textContent = lastLink.textContent.replace(/#.*$/, '') + '#' + initialHash;
|
||||
if (lastLink.href) {
|
||||
lastLink.href = lastLink.href.replace(/#.*$/, '') + '#' + initialHash;
|
||||
}
|
||||
} else {
|
||||
locEl.textContent = locEl.textContent.replace(/#.*$/, '') + '#' + initialHash;
|
||||
}
|
||||
}
|
||||
const foundIdx = albumData.findIndex(item =>
|
||||
String(item.slug || '') === initialHash ||
|
||||
@@ -3600,7 +3608,15 @@ window.cancelAnimFrame = (function () {
|
||||
}
|
||||
const locEl = document.querySelector('.location');
|
||||
if (locEl && subKey) {
|
||||
locEl.textContent = locEl.textContent.replace(/#.*$/, '') + '#' + subKey;
|
||||
const lastLink = locEl.querySelector('a:last-of-type');
|
||||
if (lastLink) {
|
||||
lastLink.textContent = lastLink.textContent.replace(/#.*$/, '') + '#' + subKey;
|
||||
if (lastLink.href) {
|
||||
lastLink.href = lastLink.href.replace(/#.*$/, '') + '#' + subKey;
|
||||
}
|
||||
} else {
|
||||
locEl.textContent = locEl.textContent.replace(/#.*$/, '') + '#' + subKey;
|
||||
}
|
||||
}
|
||||
|
||||
// Pause any playing audio or video
|
||||
@@ -11023,6 +11039,50 @@ window.cancelAnimFrame = (function () {
|
||||
if (_navEl && window.ResizeObserver) {
|
||||
new ResizeObserver(window.syncNavbarHeight).observe(_navEl);
|
||||
}
|
||||
const _existingNavbarLogo = document.getElementById('navbar-logo');
|
||||
if (_existingNavbarLogo && !_existingNavbarLogo.complete) {
|
||||
_existingNavbarLogo.addEventListener('load', window.syncNavbarHeight);
|
||||
}
|
||||
|
||||
window.updateBrandImage = (url) => {
|
||||
const logos = document.querySelectorAll('#navbar-logo');
|
||||
if (url) {
|
||||
window.f0ckBrandImages = [url];
|
||||
if (logos.length > 0) {
|
||||
logos.forEach(el => {
|
||||
el.src = url;
|
||||
el.style.display = '';
|
||||
el.onload = () => { if (window.syncNavbarHeight) window.syncNavbarHeight(); };
|
||||
});
|
||||
} else {
|
||||
document.querySelectorAll('a.navbar-brand').forEach(brandLink => {
|
||||
brandLink.querySelectorAll('.f0ck').forEach(s => s.style.display = 'none');
|
||||
const img = document.createElement('img');
|
||||
img.id = 'navbar-logo';
|
||||
img.src = url;
|
||||
img.alt = window.f0ckDomain || document.title;
|
||||
img.style.cssText = 'max-height:40px;vertical-align:middle;max-width:180px;width:auto;';
|
||||
img.onload = () => { if (window.syncNavbarHeight) window.syncNavbarHeight(); };
|
||||
brandLink.prepend(img);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
window.f0ckBrandImages = [];
|
||||
logos.forEach(el => el.remove());
|
||||
document.querySelectorAll('a.navbar-brand').forEach(brandLink => {
|
||||
const f0ckSpan = brandLink.querySelector('.f0ck');
|
||||
if (f0ckSpan) {
|
||||
f0ckSpan.style.display = '';
|
||||
} else {
|
||||
const span = document.createElement('span');
|
||||
span.className = 'f0ck';
|
||||
span.textContent = window.f0ckCustomBrandText || window.f0ckDomain || '';
|
||||
brandLink.appendChild(span);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (window.syncNavbarHeight) window.syncNavbarHeight();
|
||||
};
|
||||
|
||||
// Sidebar state init — apply persisted hidden/visible state on load
|
||||
window.initSidebarRightToggle = () => {
|
||||
@@ -11152,7 +11212,10 @@ window.cancelAnimFrame = (function () {
|
||||
const itemIdMatch = url.match(/\/([a-zA-Z0-9_-]{11}|\d+)(?:\?.*|#.*)?$/);
|
||||
if (itemIdMatch) {
|
||||
const itemId = itemIdMatch[1];
|
||||
document.querySelectorAll(`a.thumb.has-notif[href$="/${itemId}"], a.thumb.has-notif[data-item-id="${itemId}"]`).forEach(el => {
|
||||
if (window.NotificationSystemInstance) {
|
||||
window.NotificationSystemInstance.markItemRead(itemId);
|
||||
}
|
||||
document.querySelectorAll(`a.thumb.has-notif[href$="/${itemId}"], a.thumb.has-notif[data-item-id="${itemId}"], a.lazy-thumb.has-notif[data-item-id="${itemId}"]`).forEach(el => {
|
||||
el.classList.remove('has-notif');
|
||||
});
|
||||
}
|
||||
@@ -11265,11 +11328,12 @@ window.cancelAnimFrame = (function () {
|
||||
|
||||
// Restore scroll position
|
||||
requestAnimationFrame(() => {
|
||||
window.scrollTo(0, 0);
|
||||
document.documentElement.scrollTop = 0;
|
||||
document.body.scrollTop = 0;
|
||||
const ic = document.querySelector('.index-container');
|
||||
if (ic && cache.scroll !== undefined) {
|
||||
ic.scrollTo(0, cache.scroll);
|
||||
} else {
|
||||
window.scrollTo(0, cache.scroll || 0);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -11283,8 +11347,9 @@ window.cancelAnimFrame = (function () {
|
||||
window.updateVisitIndicators();
|
||||
window.initLazyLoading();
|
||||
if (window.initSidebarRightToggle) window.initSidebarRightToggle();
|
||||
if (window.syncNavbarHeight) window.syncNavbarHeight();
|
||||
window.NotificationSystemInstance?.pollDebounced?.();
|
||||
if (window.NotificationSystemInstance) {
|
||||
window.NotificationSystemInstance.poll();
|
||||
}
|
||||
window._onaraCurrentGridUrl = urlObj.pathname + urlObj.search;
|
||||
isNavigating = false;
|
||||
return; // SKIP FETCH
|
||||
@@ -11342,6 +11407,11 @@ window.cancelAnimFrame = (function () {
|
||||
indexWrapper.className = 'index-layout-wrapper';
|
||||
indexWrapper.innerHTML = '<div class="index-container"><div class="posts grid-transition"></div></div>';
|
||||
|
||||
// Reset window scroll to 0 before appending indexWrapper so :has(.index-container) doesn't lock a scrolled offset
|
||||
window.scrollTo(0, 0);
|
||||
document.documentElement.scrollTop = 0;
|
||||
document.body.scrollTop = 0;
|
||||
|
||||
main.innerHTML = '';
|
||||
main.appendChild(indexWrapper);
|
||||
|
||||
@@ -11764,7 +11834,10 @@ window.cancelAnimFrame = (function () {
|
||||
// SCROLL TO TOP ON EVERY NEW NAVIGATION
|
||||
if (!options.skipScroll) {
|
||||
window.scrollTo(0, 0);
|
||||
document.documentElement.scrollTop = 0;
|
||||
document.body.scrollTop = 0;
|
||||
}
|
||||
if (window.syncNavbarHeight) window.syncNavbarHeight();
|
||||
|
||||
// Re-init activity feed if applicable
|
||||
if (document.getElementById('activity-container')) {
|
||||
@@ -11891,15 +11964,20 @@ window.cancelAnimFrame = (function () {
|
||||
if (options.skipPush && history.state && history.state.scroll !== undefined) {
|
||||
// Back/Forward Navigation: Restore saved scroll position
|
||||
requestAnimationFrame(() => {
|
||||
window.scrollTo(0, 0);
|
||||
document.documentElement.scrollTop = 0;
|
||||
document.body.scrollTop = 0;
|
||||
const ic = document.querySelector('.index-container');
|
||||
if (ic) ic.scrollTo(0, history.state.scroll);
|
||||
else window.scrollTo(0, history.state.scroll);
|
||||
});
|
||||
} else if (replace) {
|
||||
// New Navigation: Reset to top
|
||||
window.scrollTo(0, 0);
|
||||
document.documentElement.scrollTop = 0;
|
||||
document.body.scrollTop = 0;
|
||||
const ic = document.querySelector('.index-container');
|
||||
if (ic) ic.scrollTo(0, 0);
|
||||
else window.scrollTo(0, 0);
|
||||
}
|
||||
|
||||
// Trigger fade-in
|
||||
@@ -11981,6 +12059,7 @@ window.cancelAnimFrame = (function () {
|
||||
// Notify extensions and re-init systems (e.g. CommentSystem)
|
||||
document.dispatchEvent(new Event('f0ck:contentLoaded'));
|
||||
if (window.initSidebarRightToggle) window.initSidebarRightToggle();
|
||||
if (window.syncNavbarHeight) window.syncNavbarHeight();
|
||||
// Sync has-notif highlights after grid loads — handles PWA where visibilitychange doesn't fire
|
||||
window.NotificationSystemInstance?.pollDebounced?.();
|
||||
window._onaraCurrentGridUrl = urlObj.pathname + urlObj.search;
|
||||
@@ -12237,6 +12316,14 @@ window.cancelAnimFrame = (function () {
|
||||
return;
|
||||
}
|
||||
const itemid = keySegments.pop();
|
||||
if (itemid) {
|
||||
if (window.NotificationSystemInstance) {
|
||||
window.NotificationSystemInstance.markItemRead(itemid);
|
||||
}
|
||||
document.querySelectorAll(`a.thumb.has-notif[data-item-id="${itemid}"], a.thumb.has-notif[href$="/${itemid}"], a.lazy-thumb.has-notif[data-item-id="${itemid}"]`).forEach(el => {
|
||||
el.classList.remove('has-notif');
|
||||
});
|
||||
}
|
||||
|
||||
// Extract context from Target URL first
|
||||
let tag = null, user = null, isFavs = false, mime = null, hall = null, userHall = null, userHallOwner = null, tagger = null;
|
||||
@@ -12427,6 +12514,11 @@ window.cancelAnimFrame = (function () {
|
||||
const _ic = main.querySelector('.index-container');
|
||||
const _ntc = _iw || _ic;
|
||||
if (_ntc && _isIndexPage) {
|
||||
if (itemid) {
|
||||
_ntc.querySelectorAll(`a.thumb.has-notif[data-item-id="${itemid}"], a.thumb.has-notif[href$="/${itemid}"], a.lazy-thumb.has-notif[data-item-id="${itemid}"]`).forEach(el => {
|
||||
el.classList.remove('has-notif');
|
||||
});
|
||||
}
|
||||
const _ck = window.location.pathname + window.location.search;
|
||||
const _pw = document.querySelector('.pagination-wrapper');
|
||||
gridCacheMap.set(_ck, { node: _ntc, scroll: currentScroll, pagination: _pw ? _pw.innerHTML : '' });
|
||||
@@ -12707,6 +12799,11 @@ window.cancelAnimFrame = (function () {
|
||||
const nodeToCache = indexWrapper || indexContainer;
|
||||
|
||||
if (nodeToCache && isIndexPage) {
|
||||
if (itemid) {
|
||||
nodeToCache.querySelectorAll(`a.thumb.has-notif[data-item-id="${itemid}"], a.thumb.has-notif[href$="/${itemid}"], a.lazy-thumb.has-notif[data-item-id="${itemid}"]`).forEach(el => {
|
||||
el.classList.remove('has-notif');
|
||||
});
|
||||
}
|
||||
const cacheKey = window.location.pathname + window.location.search;
|
||||
const paginationWrapper = document.querySelector('.pagination-wrapper');
|
||||
gridCacheMap.set(cacheKey, {
|
||||
@@ -13021,6 +13118,13 @@ window.cancelAnimFrame = (function () {
|
||||
const thumbnail = target.closest('.posts > a:not(.notif-item)');
|
||||
if (thumbnail && !e.ctrlKey && !e.shiftKey && !e.altKey && !e.metaKey) {
|
||||
e.preventDefault();
|
||||
if (thumbnail.classList.contains('has-notif')) {
|
||||
thumbnail.classList.remove('has-notif');
|
||||
}
|
||||
const clickedId = thumbnail.dataset.itemId || thumbnail.getAttribute('data-item-id') || thumbnail.getAttribute('href')?.match(/\/([a-zA-Z0-9_-]{11}|\d+)(?:[?#]|$)/)?.[1];
|
||||
if (clickedId && window.NotificationSystemInstance) {
|
||||
window.NotificationSystemInstance.markItemRead(clickedId);
|
||||
}
|
||||
if (isOnaraActive()) {
|
||||
const wasOpen = document.body.classList.contains('onara-modal-open');
|
||||
document.querySelectorAll('.onara-active').forEach(el => el.classList.remove('onara-active'));
|
||||
@@ -13459,10 +13563,13 @@ window.cancelAnimFrame = (function () {
|
||||
|
||||
const ratingGroup = modal.querySelector('#chan-rehost-rating-group');
|
||||
let selectedRating = 'untagged';
|
||||
let userSelectedRating = false;
|
||||
let userEditedTags = false;
|
||||
|
||||
ratingGroup.addEventListener('click', (e) => {
|
||||
const pill = e.target.closest('.chan-rehost-pill');
|
||||
if (!pill) return;
|
||||
userSelectedRating = true;
|
||||
ratingGroup.querySelectorAll('.chan-rehost-pill').forEach(b => b.classList.remove('active'));
|
||||
pill.classList.add('active');
|
||||
selectedRating = pill.dataset.rating;
|
||||
@@ -13471,19 +13578,23 @@ window.cancelAnimFrame = (function () {
|
||||
const tagsInput = modal.querySelector('#chan-rehost-tags-input');
|
||||
const commentInput = modal.querySelector('#chan-rehost-comment-input');
|
||||
|
||||
// Pre-fill current rating and tags if available
|
||||
tagsInput.addEventListener('input', () => {
|
||||
userEditedTags = true;
|
||||
});
|
||||
|
||||
// Pre-fill current rating and tags if available (don't overwrite if user already interacted)
|
||||
fetch(`/api/v2/scroller/rehost/details/${itemId}`)
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data && data.success) {
|
||||
if (data.rating) {
|
||||
if (data.rating && data.rating !== 'untagged' && !userSelectedRating) {
|
||||
selectedRating = data.rating;
|
||||
ratingGroup.querySelectorAll('.chan-rehost-pill').forEach(b => {
|
||||
b.classList.toggle('active', b.dataset.rating === data.rating);
|
||||
});
|
||||
}
|
||||
if (data.tags && data.tags.length) {
|
||||
tagsInput.value = data.tags.join(', ');
|
||||
if (data.tags && data.tags.length && !userEditedTags && !tagsInput.value) {
|
||||
tagsInput.value = data.tags.map(t => (typeof t === 'string' ? t : t.tag)).join(', ');
|
||||
}
|
||||
}
|
||||
}).catch(() => {});
|
||||
@@ -13507,6 +13618,122 @@ window.cancelAnimFrame = (function () {
|
||||
if (e.target === modal) closeModal();
|
||||
};
|
||||
|
||||
const updateDomAfterSave = (resData) => {
|
||||
try {
|
||||
const finalRating = resData.rating || selectedRating || 'untagged';
|
||||
const finalTags = Array.isArray(resData.tags) ? resData.tags : [];
|
||||
|
||||
// 1. Update #tags container
|
||||
const tagsContainer = document.querySelector('#tags');
|
||||
if (tagsContainer) {
|
||||
tagsContainer.dataset.itemId = itemId;
|
||||
tagsContainer.dataset.canManage = 'true';
|
||||
|
||||
const ratingBadges = {
|
||||
sfw: { cls: 'badge-success is-sfw', label: 'SFW' },
|
||||
nsfw: { cls: 'badge-warning is-nsfw', label: 'NSFW' },
|
||||
nsfl: { cls: 'badge-danger is-nsfl', label: 'NSFL' },
|
||||
untagged: { cls: 'badge-untagged is-untagged', label: '?' }
|
||||
};
|
||||
const rMeta = ratingBadges[finalRating] || ratingBadges.untagged;
|
||||
|
||||
let ratingEl = tagsContainer.querySelector('.rating-tag');
|
||||
if (!ratingEl) {
|
||||
ratingEl = document.createElement('span');
|
||||
tagsContainer.prepend(ratingEl);
|
||||
}
|
||||
ratingEl.className = `badge ${rMeta.cls} rating-tag can-cycle`;
|
||||
ratingEl.dataset.itemId = itemId;
|
||||
ratingEl.dataset.rating = finalRating;
|
||||
ratingEl.innerHTML = `<span class="rating-label">${rMeta.label}</span>`;
|
||||
|
||||
// Remove previous tag badges and re-render new ones
|
||||
tagsContainer.querySelectorAll('.tag-badge').forEach(el => el.remove());
|
||||
finalTags.forEach(t => {
|
||||
const tagName = typeof t === 'string' ? t : (t.tag || '');
|
||||
const tagNorm = typeof t === 'string' ? tagName.toLowerCase().replace(/[^a-z0-9_-]/g, '') : (t.normalized || tagName);
|
||||
const tagBadge = (typeof t === 'object' && t.badge) ? t.badge : 'badge-light';
|
||||
const tagId = (typeof t === 'object' && t.id) ? t.id : '';
|
||||
|
||||
const span = document.createElement('span');
|
||||
span.className = `badge ${tagBadge} tag-badge`;
|
||||
if (tagId) span.dataset.tagId = tagId;
|
||||
span.dataset.tag = tagName;
|
||||
span.dataset.tagNormalized = tagNorm;
|
||||
|
||||
const a = document.createElement('a');
|
||||
a.href = `/tag/${encodeURIComponent(tagNorm)}`;
|
||||
a.className = 'tag-name';
|
||||
a.textContent = tagName;
|
||||
span.appendChild(a);
|
||||
|
||||
tagsContainer.appendChild(span);
|
||||
});
|
||||
}
|
||||
|
||||
// 2. Update .item-layout-container
|
||||
const layoutContainer = document.querySelector('.item-layout-container');
|
||||
if (layoutContainer) {
|
||||
layoutContainer.dataset.itemId = itemId;
|
||||
}
|
||||
|
||||
// 3. Update .media-object mode
|
||||
const mediaObj = document.querySelector('.media-object');
|
||||
if (mediaObj) {
|
||||
mediaObj.dataset.mode = finalRating;
|
||||
}
|
||||
|
||||
// 4. Update .location breadcrumb
|
||||
const locEl = document.querySelector('.location');
|
||||
if (locEl && !locEl.querySelector('.is-rehosted')) {
|
||||
const sep = document.createElement('span');
|
||||
sep.className = 'location-sep';
|
||||
sep.style.cssText = 'opacity: 0.6; margin: 0 4px;';
|
||||
sep.textContent = '→';
|
||||
|
||||
const a = document.createElement('a');
|
||||
a.href = `/${itemId}`;
|
||||
a.className = 'location-link is-rehosted';
|
||||
a.title = `View rehosted post #${itemId} on f0ckm`;
|
||||
a.style.cssText = 'color: #4ade80; font-weight: 700;';
|
||||
a.innerHTML = `<i class="fa-solid fa-check"></i> #${itemId}`;
|
||||
|
||||
locEl.appendChild(sep);
|
||||
locEl.appendChild(a);
|
||||
}
|
||||
|
||||
// 5. Update #a_favo
|
||||
const favBtn = document.querySelector('#a_favo');
|
||||
if (favBtn) {
|
||||
favBtn.dataset.itemId = itemId;
|
||||
favBtn.dataset.localId = itemId;
|
||||
}
|
||||
|
||||
// 6. Update #chan-item-rehost-btn if present
|
||||
const rehostBtn = document.querySelector('#chan-item-rehost-btn');
|
||||
if (rehostBtn) {
|
||||
rehostBtn.outerHTML = `
|
||||
<span class="chan-rehost-btn-group" style="display:inline-flex;gap:4px;align-items:center;">
|
||||
<a href="/${itemId}" class="chan-rehost-action-btn rehosted" title="View Post #${itemId}" style="display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:4px 12px;border-radius:6px;font-size:0.8rem;background:rgba(74,222,128,0.2);color:#4ade80;border:1px solid rgba(74,222,128,0.4);text-decoration:none;font-weight:600;white-space:nowrap;flex-shrink:0;">
|
||||
<i class="fa-solid fa-check"></i> #${itemId}
|
||||
</a>
|
||||
<button type="button" class="chan-rehost-edit-btn" data-item-id="${itemId}" title="Edit rating, tags & comment" style="display:inline-flex;align-items:center;padding:3px 7px;border-radius:6px;font-size:0.8rem;background:rgba(255,255,255,0.1);color:#fff;border:1px solid rgba(255,255,255,0.2);cursor:pointer;">
|
||||
<i class="fa-solid fa-pen"></i>
|
||||
</button>
|
||||
</span>
|
||||
`;
|
||||
}
|
||||
|
||||
// 7. Invalidate caches
|
||||
if (typeof window.invalidateItemCache === 'function') {
|
||||
window.invalidateItemCache(itemId);
|
||||
window.invalidateItemCache(window.location.pathname);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[REHOST-MODAL] DOM update error:', err);
|
||||
}
|
||||
};
|
||||
|
||||
const saveDetails = async (andView = false) => {
|
||||
const saveBtn = modal.querySelector('.chan-rehost-modal-save');
|
||||
const saveViewBtn = modal.querySelector('.chan-rehost-modal-save-view');
|
||||
@@ -13535,12 +13762,13 @@ window.cancelAnimFrame = (function () {
|
||||
window.showToast('Details saved for #' + itemId + '!');
|
||||
}
|
||||
closeModal();
|
||||
updateDomAfterSave(resData);
|
||||
if (typeof onSave === 'function') {
|
||||
onSave(resData);
|
||||
}
|
||||
if (andView) {
|
||||
if (typeof window.loadItemAjax === 'function') {
|
||||
window.loadItemAjax('/' + itemId);
|
||||
window.loadItemAjax('/' + itemId, true, { skipCache: true });
|
||||
} else {
|
||||
window.location.href = '/' + itemId;
|
||||
}
|
||||
@@ -13602,9 +13830,19 @@ window.cancelAnimFrame = (function () {
|
||||
if (data.success && data.item_id) {
|
||||
btn.classList.remove('loading');
|
||||
btn.classList.add('rehosted');
|
||||
|
||||
const timeEl = document.querySelector('time.timeago');
|
||||
if (timeEl) {
|
||||
const nowIso = new Date().toISOString();
|
||||
timeEl.dataset.iso = nowIso;
|
||||
const fullDate = typeof window.f0ckFormatDateFull === 'function' ? window.f0ckFormatDateFull(nowIso) : new Date().toLocaleString();
|
||||
timeEl.setAttribute('tooltip', fullDate);
|
||||
timeEl.textContent = (window.f0ckTimeAgo ? window.f0ckTimeAgo(nowIso) : (window.f0ckI18n?.timeago_just_now || 'just now'));
|
||||
}
|
||||
|
||||
btn.outerHTML = `
|
||||
<span class="chan-rehost-btn-group" style="display:inline-flex;gap:4px;align-items:center;">
|
||||
<a href="/${data.item_id}" class="chan-rehost-action-btn rehosted" title="View Post #${data.item_id}" style="display:inline-flex;align-items:center;gap:5px;padding:3px 9px;border-radius:6px;font-size:0.8rem;background:rgba(74,222,128,0.2);color:#4ade80;border:1px solid rgba(74,222,128,0.4);text-decoration:none;font-weight:600;">
|
||||
<a href="/${data.item_id}" class="chan-rehost-action-btn rehosted" title="View Post #${data.item_id}" style="display:inline-flex;align-items:center;justify-content:center;gap:6px;padding:4px 12px;border-radius:6px;font-size:0.8rem;background:rgba(74,222,128,0.2);color:#4ade80;border:1px solid rgba(74,222,128,0.4);text-decoration:none;font-weight:600;white-space:nowrap;flex-shrink:0;">
|
||||
<i class="fa-solid fa-check"></i> #${data.item_id}
|
||||
</a>
|
||||
<button type="button" class="chan-rehost-edit-btn" data-item-id="${data.item_id}" title="Edit rating, tags & comment" style="display:inline-flex;align-items:center;padding:3px 7px;border-radius:6px;font-size:0.8rem;background:rgba(255,255,255,0.1);color:#fff;border:1px solid rgba(255,255,255,0.2);cursor:pointer;">
|
||||
@@ -14146,6 +14384,10 @@ window.cancelAnimFrame = (function () {
|
||||
loadPageAjax(url, true, { skipPush: true });
|
||||
} else {
|
||||
document.title = window._onaraReturnTitle || window.f0ckDomain || 'f0ck';
|
||||
if (window.updateVisitIndicators) window.updateVisitIndicators();
|
||||
if (window.NotificationSystemInstance) {
|
||||
window.NotificationSystemInstance.poll();
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
@@ -17723,31 +17965,9 @@ class NotificationSystem {
|
||||
document.dispatchEvent(new CustomEvent('f0ck:global_chat_presence', { detail: data.data }));
|
||||
} else if (data.type === 'brand_image') {
|
||||
window.f0ckDebug(`[SSE] Brand image update received:`, data.data?.url);
|
||||
if (data.data?.url) {
|
||||
const src = data.data.url;
|
||||
// Update the randomizeLogo pool so clicking the brand always uses the current image
|
||||
window.f0ckBrandImages = [src];
|
||||
const logos = document.querySelectorAll('#navbar-logo');
|
||||
if (logos.length > 0) {
|
||||
logos.forEach(el => { el.src = src; el.style.display = ''; });
|
||||
} else {
|
||||
// Logo element doesn't exist yet (no image was set before) — create it
|
||||
document.querySelectorAll('a.navbar-brand').forEach(brandLink => {
|
||||
const textNode = Array.from(brandLink.childNodes).find(n => n.nodeType === Node.TEXT_NODE);
|
||||
const img = document.createElement('img');
|
||||
img.id = 'navbar-logo';
|
||||
img.src = src;
|
||||
img.alt = document.title;
|
||||
img.style.cssText = 'max-height:40px;vertical-align:middle;max-width:180px;width:auto;';
|
||||
if (textNode) brandLink.insertBefore(img, textNode);
|
||||
else brandLink.prepend(img);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
window.f0ckBrandImages = [];
|
||||
document.querySelectorAll('#navbar-logo').forEach(el => el.remove());
|
||||
if (window.updateBrandImage) {
|
||||
window.updateBrandImage(data.data?.url || null);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('SSE data parse error', err);
|
||||
@@ -18053,7 +18273,12 @@ class NotificationSystem {
|
||||
};
|
||||
|
||||
document.addEventListener('f0ck:contentLoaded', reapplyOwnBanner);
|
||||
window.addEventListener('pageshow', (e) => { if (e.persisted) reapplyOwnBanner(); });
|
||||
window.addEventListener('pageshow', (e) => {
|
||||
if (e.persisted) {
|
||||
reapplyOwnBanner();
|
||||
this.poll();
|
||||
}
|
||||
});
|
||||
|
||||
// Poll fresh display_name from DB — used on tab focus to catch missed SSE events
|
||||
this.syncDisplayName = async () => {
|
||||
@@ -18218,6 +18443,12 @@ class NotificationSystem {
|
||||
|
||||
|
||||
// Handle "Mark as Read"
|
||||
const notifTargetItemId = link.dataset.itemId || link.getAttribute('data-item-id') || link.getAttribute('href')?.match(/\/([a-zA-Z0-9_-]{11}|\d+)(?:[?#]|$)/)?.[1];
|
||||
const notifTargetItemSlug = link.dataset.itemSlug || link.getAttribute('data-item-slug');
|
||||
if (notifTargetItemId || notifTargetItemSlug) {
|
||||
this.markItemRead(notifTargetItemId, notifTargetItemSlug);
|
||||
}
|
||||
|
||||
if (link.dataset.id && link.classList.contains('unread')) {
|
||||
window.f0ckDebug(`[NotificationSystem] Marking ${link.dataset.id} as read...`);
|
||||
// Fire and forget (keepalive ensures it survives navigation)
|
||||
@@ -18226,8 +18457,8 @@ class NotificationSystem {
|
||||
keepalive: true
|
||||
}).catch(err => console.error("Failed to mark read", err));
|
||||
|
||||
// Decrement badge count
|
||||
if (this.countBadge) {
|
||||
// Decrement badge count if not already decremented by markItemRead
|
||||
if (!notifTargetItemId && !notifTargetItemSlug && this.countBadge) {
|
||||
let count = parseInt(this.countBadge.textContent) || 0;
|
||||
if (count > 0) {
|
||||
count--;
|
||||
@@ -18521,21 +18752,32 @@ class NotificationSystem {
|
||||
const unreadItemIds = new Set();
|
||||
notifications.forEach(n => {
|
||||
if (!n.is_read && n.item_id) {
|
||||
unreadItemIds.add(String(n.item_id));
|
||||
if (currentPath === `/${n.item_id}` || currentPath === `/${n.item_id}/`) return;
|
||||
document.querySelectorAll(`a.thumb[href$="/${n.item_id}"], a.lazy-thumb[href$="/${n.item_id}"]`).forEach(el => {
|
||||
const idStr = String(n.item_id);
|
||||
unreadItemIds.add(idStr);
|
||||
if (n.item_slug) unreadItemIds.add(String(n.item_slug));
|
||||
if (n.slug) unreadItemIds.add(String(n.slug));
|
||||
if (currentPath === `/${n.item_id}` || currentPath === `/${n.item_id}/` || (n.item_slug && currentPath === `/${n.item_slug}`)) return;
|
||||
document.querySelectorAll(`a.thumb[data-item-id="${idStr}"], a.lazy-thumb[data-item-id="${idStr}"], a.thumb[href$="/${idStr}"], a.lazy-thumb[href$="/${idStr}"]`).forEach(el => {
|
||||
el.classList.add('has-notif');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Remove .has-notif from any thumb whose item is no longer in the unread set.
|
||||
document.querySelectorAll('a.thumb.has-notif, a.lazy-thumb.has-notif').forEach(el => {
|
||||
const match = el.getAttribute('href')?.match(/\/(\d+)$/);
|
||||
if (match && !unreadItemIds.has(match[1])) {
|
||||
el.classList.remove('has-notif');
|
||||
}
|
||||
});
|
||||
const removeStaleHasNotif = (root = document) => {
|
||||
root.querySelectorAll('a.thumb.has-notif, a.lazy-thumb.has-notif').forEach(el => {
|
||||
const id = el.dataset.itemId || el.getAttribute('data-item-id') || el.getAttribute('href')?.match(/\/([a-zA-Z0-9_-]{11}|\d+)(?:[?#]|$)/)?.[1];
|
||||
if (id && !unreadItemIds.has(String(id))) {
|
||||
el.classList.remove('has-notif');
|
||||
}
|
||||
});
|
||||
};
|
||||
removeStaleHasNotif(document);
|
||||
if (typeof gridCacheMap !== 'undefined' && gridCacheMap) {
|
||||
gridCacheMap.forEach(cacheEntry => {
|
||||
if (cacheEntry?.node) removeStaleHasNotif(cacheEntry.node);
|
||||
});
|
||||
}
|
||||
|
||||
// Render the active tab
|
||||
this._renderActiveTab();
|
||||
@@ -18592,7 +18834,7 @@ class NotificationSystem {
|
||||
const userLabel = isDeleted ? (i18n.notif_moderation || 'Moderation') : (i18n.notif_system || 'System');
|
||||
const itemLink = `/${itemKey}`;
|
||||
return `
|
||||
<a href="${itemLink}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}">
|
||||
<a href="${itemLink}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}" data-item-id="${n.item_id || ''}" data-item-slug="${n.item_slug || n.slug || ''}">
|
||||
<div class="notif-thumb"${n.item_mode ? ` data-mode="${n.item_mode}"` : ''}><img src="/mod/deleted/t/${n.item_id}.webp" alt="thumb" onerror="this.onerror=null;this.src='/t/${n.item_id}.webp';this.onerror=function(){this.style.display='none';}"></div>
|
||||
<div class="notif-content">
|
||||
<div class="notif-user"><strong>${userLabel}</strong></div>
|
||||
@@ -18644,7 +18886,7 @@ class NotificationSystem {
|
||||
let thumbSrc, thumbOnerror;
|
||||
if (n.type === 'warning') {
|
||||
return `
|
||||
<div class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}">
|
||||
<div class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}" data-item-id="${n.item_id || ''}" data-item-slug="${n.item_slug || n.slug || ''}">
|
||||
<div class="notif-thumb" style="display:flex;align-items:center;justify-content:center;background:var(--bg-lighter);color:var(--danger);font-size:1.5em;"><i class="fa-solid fa-triangle-exclamation"></i></div>
|
||||
<div class="notif-content">
|
||||
<div class="notif-user"><strong ${n.username_color ? `style="color: ${n.username_color}"` : ''}>${user}</strong></div>
|
||||
@@ -18662,7 +18904,7 @@ class NotificationSystem {
|
||||
}
|
||||
const thumb = n.item_id ? `<div class="notif-thumb"${n.item_mode ? ` data-mode="${n.item_mode}"` : ''}><img src="${thumbSrc}" alt="thumb" onerror="${thumbOnerror}"></div>` : '';
|
||||
return `
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}">
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}" data-item-id="${n.item_id || ''}" data-item-slug="${n.item_slug || n.slug || ''}">
|
||||
${thumb}
|
||||
<div class="notif-content">
|
||||
<div class="notif-user"><strong ${n.username_color ? `style="color: ${n.username_color}"` : ''}>${user}</strong></div>
|
||||
@@ -18678,7 +18920,7 @@ class NotificationSystem {
|
||||
if (n.type === 'approve') {
|
||||
const link = `/${itemKey}`;
|
||||
return `
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}">
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}" data-item-id="${n.item_id || ''}" data-item-slug="${n.item_slug || n.slug || ''}">
|
||||
<div class="notif-thumb"${n.item_mode ? ` data-mode="${n.item_mode}"` : ''}><img src="/t/${n.item_id}.webp" alt="thumb" onerror="this.onerror=null;this.src='/mod/pending/t/${n.item_id}.webp';this.onerror=function(){this.onerror=null;this.src='/mod/deleted/t/${n.item_id}.webp';this.onerror=function(){this.style.display='none';};}"></div>
|
||||
<div class="notif-content">
|
||||
<div>
|
||||
@@ -18693,7 +18935,7 @@ class NotificationSystem {
|
||||
if (n.type === 'upload_success') {
|
||||
const link = `/${itemKey}`;
|
||||
return `
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}">
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}" data-item-id="${n.item_id || ''}" data-item-slug="${n.item_slug || n.slug || ''}">
|
||||
<div class="notif-thumb"${n.item_mode ? ` data-mode="${n.item_mode}"` : ''}><img src="/t/${n.item_id}.webp" alt="thumb" onerror="this.style.display='none';"></div>
|
||||
<div class="notif-content">
|
||||
<div>
|
||||
@@ -18712,7 +18954,7 @@ class NotificationSystem {
|
||||
const urlDisplay = url ? `<div style="font-size: 0.8em; opacity: 0.7; margin-top: 4px; word-break: break-all; max-height: 3.2em; overflow: hidden;">${url}</div>` : '';
|
||||
const link = n.item_id ? `/${itemKey}` : '#';
|
||||
return `
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'}" data-id="${n.id}">
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'}" data-id="${n.id}" data-item-id="${n.item_id || ''}" data-item-slug="${n.item_slug || n.slug || ''}">
|
||||
<div class="notif-content">
|
||||
<div>
|
||||
<strong>${(window.f0ckI18n && window.f0ckI18n.notif_upload_error) || 'Your background upload failed.'}</strong>
|
||||
@@ -18730,7 +18972,7 @@ class NotificationSystem {
|
||||
const label = isDeleted ? ((window.f0ckI18n && window.f0ckI18n.notif_upload_deleted) || 'A moderator deleted your upload') : ((window.f0ckI18n && window.f0ckI18n.notif_upload_denied) || 'Your upload was denied');
|
||||
const link = `/notifications#notif-${n.id}`;
|
||||
return `
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}" data-notif-nav="true">
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}" data-item-id="${n.item_id || ''}" data-item-slug="${n.item_slug || n.slug || ''}" data-notif-nav="true">
|
||||
<div class="notif-thumb"${n.item_mode ? ` data-mode="${n.item_mode}"` : ''}><img src="/mod/deleted/t/${n.item_id}.webp" alt="thumb" onerror="this.onerror=null;this.src='/t/${n.item_id}.webp';this.onerror=function(){this.style.display='none';}"></div>
|
||||
<div class="notif-content">
|
||||
<div>
|
||||
@@ -18746,7 +18988,7 @@ class NotificationSystem {
|
||||
if (n.type === 'admin_pending') {
|
||||
const link = '/mod/approve';
|
||||
return `
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}">
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}" data-item-id="${n.item_id || ''}" data-item-slug="${n.item_slug || n.slug || ''}">
|
||||
<div class="notif-thumb"${n.item_mode ? ` data-mode="${n.item_mode}"` : ''}><img src="/mod/pending/t/${n.item_id}.webp" alt="thumb" onerror="this.onerror=null;this.src='/t/${n.item_id}.webp';this.onerror=function(){this.style.display='none';}"></div>
|
||||
<div class="notif-content">
|
||||
<div>
|
||||
@@ -18761,7 +19003,7 @@ class NotificationSystem {
|
||||
if (n.type === 'report') {
|
||||
const link = '/mod/reports';
|
||||
return `
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}">
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}" data-item-id="${n.item_id || ''}" data-item-slug="${n.item_slug || n.slug || ''}">
|
||||
<div class="notif-thumb"${n.item_mode ? ` data-mode="${n.item_mode}"` : ''}><img src="/t/${n.item_id}.webp" alt="thumb" onerror="this.onerror=null;this.src='/mod/pending/t/${n.item_id}.webp';this.onerror=function(){this.onerror=null;this.src='/mod/deleted/t/${n.item_id}.webp';this.onerror=function(){this.style.display='none';};}"></div>
|
||||
<div class="notif-content">
|
||||
<div>
|
||||
@@ -18776,7 +19018,7 @@ class NotificationSystem {
|
||||
if (n.type === 'warning') {
|
||||
const link = `/notifications?tab=system#notif-${n.id}`;
|
||||
return `
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}" data-notif-nav="true">
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}" data-item-id="${n.item_id || ''}" data-item-slug="${n.item_slug || n.slug || ''}" data-notif-nav="true">
|
||||
<div class="notif-thumb" style="display:flex;align-items:center;justify-content:center;background:var(--bg-lighter);color:var(--danger);font-size:1.5em;"><i class="fa-solid fa-triangle-exclamation"></i></div>
|
||||
<div class="notif-content">
|
||||
<div>
|
||||
@@ -18800,7 +19042,7 @@ class NotificationSystem {
|
||||
|
||||
const thumb = n.item_id ? `<div class="notif-thumb"${n.item_mode ? ` data-mode="${n.item_mode}"` : ''}><img src="/t/${n.item_id}.webp" alt="thumb" onerror="this.style.display='none'"></div>` : '';
|
||||
return `
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}">
|
||||
<a href="${link}" class="notif-item ${n.is_read ? '' : 'unread'} notif-with-thumb" data-id="${n.id}" data-item-id="${n.item_id || ''}" data-item-slug="${n.item_slug || n.slug || ''}">
|
||||
${thumb}
|
||||
<div class="notif-content">
|
||||
<div>
|
||||
@@ -18812,6 +19054,113 @@ class NotificationSystem {
|
||||
`;
|
||||
}
|
||||
|
||||
markItemRead(itemId, slug = null) {
|
||||
if (!itemId && !slug) return;
|
||||
const strId = itemId ? String(itemId) : null;
|
||||
const strSlug = slug ? String(slug) : null;
|
||||
|
||||
const matchesItem = (n) => {
|
||||
if (!n) return false;
|
||||
if (strId && String(n.item_id) === strId) return true;
|
||||
if (strSlug && (String(n.item_slug) === strSlug || String(n.slug) === strSlug)) return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
[this._cachedUser, this._cachedSystem].forEach(list => {
|
||||
if (!Array.isArray(list)) return;
|
||||
list.forEach(n => {
|
||||
if (matchesItem(n) && !n.is_read) {
|
||||
n.is_read = true;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Remove matching .notif-item elements from dropdown
|
||||
if (this.list) {
|
||||
const items = this.list.querySelectorAll('.notif-item');
|
||||
items.forEach(el => {
|
||||
const notifItemId = el.dataset.itemId;
|
||||
const notifItemSlug = el.dataset.itemSlug;
|
||||
const notifHref = el.getAttribute('href') || '';
|
||||
const isMatch = (strId && notifItemId === strId) ||
|
||||
(strSlug && notifItemSlug === strSlug) ||
|
||||
(strId && (notifHref === `/${strId}` || notifHref.startsWith(`/${strId}#`) || notifHref.startsWith(`/${strId}?`))) ||
|
||||
(strSlug && (notifHref === `/${strSlug}` || notifHref.startsWith(`/${strSlug}#`) || notifHref.startsWith(`/${strSlug}?`)));
|
||||
if (isMatch) {
|
||||
el.remove();
|
||||
}
|
||||
});
|
||||
if (this.list.children.length === 0) {
|
||||
this.list.innerHTML = `<div class="notif-empty">${window.f0ckI18n?.no_notifications || 'No new notifications'}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
// Mark as read in full history page if open
|
||||
document.querySelectorAll('.notifications-list-full .notif-item.unread').forEach(el => {
|
||||
const notifItemId = el.dataset.itemId;
|
||||
const notifItemSlug = el.dataset.itemSlug;
|
||||
const notifHref = el.getAttribute('href') || '';
|
||||
const isMatch = (strId && notifItemId === strId) ||
|
||||
(strSlug && notifItemSlug === strSlug) ||
|
||||
(strId && (notifHref === `/${strId}` || notifHref.startsWith(`/${strId}#`) || notifHref.startsWith(`/${strId}?`))) ||
|
||||
(strSlug && (notifHref === `/${strSlug}` || notifHref.startsWith(`/${strSlug}#`) || notifHref.startsWith(`/${strSlug}?`)));
|
||||
if (isMatch) {
|
||||
el.classList.remove('unread');
|
||||
}
|
||||
});
|
||||
|
||||
// Recalculate unread counts
|
||||
const userUnread = (this._cachedUser || []).filter(n => !n.is_read).length;
|
||||
const systemUnread = (this._cachedSystem || []).filter(n => !n.is_read).length;
|
||||
const totalUnread = userUnread + systemUnread;
|
||||
|
||||
if (this.countBadge) {
|
||||
this.countBadge.textContent = totalUnread;
|
||||
this.countBadge.style.display = totalUnread > 0 ? 'block' : 'none';
|
||||
}
|
||||
const userBadge = document.getElementById('notif-tab-badge-user');
|
||||
const systemBadge = document.getElementById('notif-tab-badge-system');
|
||||
if (userBadge) {
|
||||
userBadge.textContent = userUnread;
|
||||
userBadge.style.display = userUnread > 0 ? '' : 'none';
|
||||
}
|
||||
if (systemBadge) {
|
||||
systemBadge.textContent = systemUnread;
|
||||
systemBadge.style.display = systemUnread > 0 ? '' : 'none';
|
||||
}
|
||||
if (typeof window._scrollerNotifHook === 'function') {
|
||||
window._scrollerNotifHook(totalUnread);
|
||||
}
|
||||
|
||||
// Remove .has-notif from matching thumbnails in DOM
|
||||
const removeHasNotif = (root = document) => {
|
||||
root.querySelectorAll('a.thumb.has-notif, a.lazy-thumb.has-notif').forEach(el => {
|
||||
const id = el.dataset.itemId || el.getAttribute('data-item-id') || el.getAttribute('href')?.match(/\/([a-zA-Z0-9_-]{11}|\d+)(?:[?#]|$)/)?.[1];
|
||||
if (id && (id === strId || id === strSlug)) {
|
||||
el.classList.remove('has-notif');
|
||||
}
|
||||
});
|
||||
};
|
||||
removeHasNotif(document);
|
||||
|
||||
// Also strip from any detached cached grids in gridCacheMap
|
||||
if (typeof gridCacheMap !== 'undefined' && gridCacheMap) {
|
||||
gridCacheMap.forEach(cacheEntry => {
|
||||
if (cacheEntry && cacheEntry.node) {
|
||||
removeHasNotif(cacheEntry.node);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Tell server in background (fire-and-forget with keepalive)
|
||||
const serverId = strId || strSlug;
|
||||
if (serverId) {
|
||||
fetch(`/api/notifications/item/${encodeURIComponent(serverId)}/read`, {
|
||||
method: 'POST',
|
||||
keepalive: true
|
||||
}).catch(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
async markAllRead() {
|
||||
try {
|
||||
@@ -18829,7 +19178,7 @@ class NotificationSystem {
|
||||
}
|
||||
|
||||
markAllReadUI() {
|
||||
this.countBadge.style.display = 'none';
|
||||
if (this.countBadge) this.countBadge.style.display = 'none';
|
||||
// Clear per-tab badges
|
||||
const userBadge = document.getElementById('notif-tab-badge-user');
|
||||
const systemBadge = document.getElementById('notif-tab-badge-system');
|
||||
@@ -18843,6 +19192,16 @@ class NotificationSystem {
|
||||
}
|
||||
// Also update History page items if present
|
||||
document.querySelectorAll('.notifications-list-full .notif-item.unread').forEach(el => el.classList.remove('unread'));
|
||||
// Remove .has-notif highlights
|
||||
document.querySelectorAll('a.thumb.has-notif, a.lazy-thumb.has-notif').forEach(el => el.classList.remove('has-notif'));
|
||||
if (typeof gridCacheMap !== 'undefined' && gridCacheMap) {
|
||||
gridCacheMap.forEach(cacheEntry => {
|
||||
if (cacheEntry?.node) cacheEntry.node.querySelectorAll('a.thumb.has-notif, a.lazy-thumb.has-notif').forEach(el => el.classList.remove('has-notif'));
|
||||
});
|
||||
}
|
||||
if (typeof window._scrollerNotifHook === 'function') {
|
||||
window._scrollerNotifHook(0);
|
||||
}
|
||||
}
|
||||
|
||||
handleTagsUpdate(data) {
|
||||
@@ -19053,6 +19412,8 @@ class NotificationSystem {
|
||||
return false;
|
||||
});
|
||||
favoBtns.forEach(favoBtn => {
|
||||
favoBtn.classList.remove('fa-spinner', 'fa-spin');
|
||||
favoBtn.classList.add('iconset', 'fa-heart');
|
||||
favoBtn.classList.toggle('fa-solid', isNowFav);
|
||||
favoBtn.classList.toggle('fa-regular', !isNowFav);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user