gfsd
This commit is contained in:
+103
-138
@@ -6526,7 +6526,7 @@ window.cancelAnimFrame = (function () {
|
||||
}
|
||||
};
|
||||
const initExcludedTagsModal = () => {
|
||||
if (window.f0ckSession && !window.f0ckSession.logged_in) return;
|
||||
const isLoggedIn = !!(window.f0ckSession && window.f0ckSession.logged_in);
|
||||
|
||||
const overlay = document.getElementById('excluded-tags-overlay');
|
||||
if (!overlay) return;
|
||||
@@ -6544,9 +6544,9 @@ window.cancelAnimFrame = (function () {
|
||||
overlay.offsetHeight;
|
||||
overlay.classList.add('visible');
|
||||
document.body.style.overflow = 'hidden';
|
||||
renderTags();
|
||||
if (isLoggedIn) renderTags();
|
||||
if (window.syncRatingButtonUI) window.syncRatingButtonUI();
|
||||
if (window.innerWidth > 768) input.focus();
|
||||
if (isLoggedIn && window.innerWidth > 768) input.focus();
|
||||
} else {
|
||||
overlay.classList.remove('visible');
|
||||
document.body.style.overflow = '';
|
||||
@@ -6611,149 +6611,105 @@ window.cancelAnimFrame = (function () {
|
||||
if (e.target === overlay) toggleModal(false);
|
||||
});
|
||||
|
||||
const addTag = async () => {
|
||||
const tagname = input.value.trim();
|
||||
if (!tagname) return;
|
||||
suggestions.style.display = 'none';
|
||||
try {
|
||||
const res = await fetch('/api/v2/settings/excluded_tags', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({
|
||||
tagname
|
||||
})
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
renderTags();
|
||||
input.value = '';
|
||||
} else {
|
||||
window.flashMessage(data.msg || 'Error adding tag', 3000, 'error');
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
if (window.innerWidth > 768) input.focus();
|
||||
}
|
||||
};
|
||||
input.addEventListener('keydown', e => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
// If a suggestion is highlighted, use it
|
||||
if (highlightIdx >= 0) {
|
||||
const items = suggestions.querySelectorAll('.tag-suggestion-item');
|
||||
if (items[highlightIdx]) {
|
||||
input.value = items[highlightIdx].querySelector('.tag-suggestion-name').textContent;
|
||||
}
|
||||
}
|
||||
if (isLoggedIn) {
|
||||
const addTag = async () => {
|
||||
const tagname = input.value.trim();
|
||||
if (!tagname) return;
|
||||
suggestions.style.display = 'none';
|
||||
addTag();
|
||||
}
|
||||
});
|
||||
|
||||
list.addEventListener('click', async e => {
|
||||
if (e.target.classList.contains('remove-excluded-tag')) {
|
||||
e.preventDefault();
|
||||
const tag = e.target.getAttribute('data-tag');
|
||||
try {
|
||||
const res = await fetch(`/api/v2/settings/excluded_tags/${encodeURIComponent(tag)}`, {
|
||||
method: 'DELETE'
|
||||
const res = await fetch('/api/v2/settings/excluded_tags', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ tagname })
|
||||
});
|
||||
const data = await res.json();
|
||||
if (data.success) renderTags();
|
||||
if (data.success) { renderTags(); input.value = ''; }
|
||||
else window.flashMessage(data.msg || 'Error adding tag', 3000, 'error');
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
} finally {
|
||||
if (window.innerWidth > 768) input.focus();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Autocomplete with dropdown suggestions
|
||||
let debounceTimer = null;
|
||||
let highlightIdx = -1;
|
||||
|
||||
const renderSuggestions = (items) => {
|
||||
suggestions.innerHTML = '';
|
||||
highlightIdx = -1;
|
||||
if (!items.length) {
|
||||
suggestions.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
items.forEach(s => {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'tag-suggestion-item';
|
||||
|
||||
const name = document.createElement('span');
|
||||
name.className = 'tag-suggestion-name';
|
||||
name.textContent = s.tag;
|
||||
|
||||
const meta = document.createElement('span');
|
||||
meta.className = 'tag-suggestion-meta';
|
||||
meta.textContent = `${s.tagged}× · ${s.score.toFixed(2)}`;
|
||||
|
||||
div.appendChild(name);
|
||||
div.appendChild(meta);
|
||||
|
||||
div.addEventListener('mousedown', (e) => {
|
||||
};
|
||||
input.addEventListener('keydown', e => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
input.value = s.tag;
|
||||
if (highlightIdx >= 0) {
|
||||
const items = suggestions.querySelectorAll('.tag-suggestion-item');
|
||||
if (items[highlightIdx]) input.value = items[highlightIdx].querySelector('.tag-suggestion-name').textContent;
|
||||
}
|
||||
suggestions.style.display = 'none';
|
||||
addTag();
|
||||
});
|
||||
suggestions.appendChild(div);
|
||||
});
|
||||
suggestions.style.display = 'block';
|
||||
};
|
||||
|
||||
input.addEventListener('input', () => {
|
||||
const q = input.value.trim();
|
||||
highlightIdx = -1;
|
||||
if (q.length < 1) {
|
||||
suggestions.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
if (debounceTimer) clearTimeout(debounceTimer);
|
||||
debounceTimer = setTimeout(async () => {
|
||||
try {
|
||||
const res = await fetch(`/api/v2/tags/suggest?q=${encodeURIComponent(q)}`);
|
||||
const json = await res.json();
|
||||
if (json.success && json.suggestions) {
|
||||
renderSuggestions(json.suggestions.slice(0, 8));
|
||||
} else {
|
||||
suggestions.style.display = 'none';
|
||||
}
|
||||
} catch (e) {
|
||||
suggestions.style.display = 'none';
|
||||
}
|
||||
}, 300);
|
||||
});
|
||||
});
|
||||
|
||||
input.addEventListener('keydown', e => {
|
||||
const items = suggestions.querySelectorAll('.tag-suggestion-item');
|
||||
if (!items.length || suggestions.style.display === 'none') return;
|
||||
list.addEventListener('click', async e => {
|
||||
if (e.target.classList.contains('remove-excluded-tag')) {
|
||||
e.preventDefault();
|
||||
const tag = e.target.getAttribute('data-tag');
|
||||
try {
|
||||
const res = await fetch(`/api/v2/settings/excluded_tags/${encodeURIComponent(tag)}`, { method: 'DELETE' });
|
||||
const data = await res.json();
|
||||
if (data.success) renderTags();
|
||||
} catch (e) { console.error(e); }
|
||||
}
|
||||
});
|
||||
|
||||
if (e.key === 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
if (highlightIdx >= 0 && highlightIdx < items.length) items[highlightIdx].classList.remove('active');
|
||||
highlightIdx = highlightIdx < items.length - 1 ? highlightIdx + 1 : 0;
|
||||
items[highlightIdx].classList.add('active');
|
||||
items[highlightIdx].scrollIntoView({ block: 'nearest' });
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
if (highlightIdx >= 0 && highlightIdx < items.length) items[highlightIdx].classList.remove('active');
|
||||
highlightIdx = highlightIdx > 0 ? highlightIdx - 1 : items.length - 1;
|
||||
items[highlightIdx].classList.add('active');
|
||||
items[highlightIdx].scrollIntoView({ block: 'nearest' });
|
||||
} else if (e.key === 'Escape') {
|
||||
suggestions.style.display = 'none';
|
||||
// Autocomplete with dropdown suggestions
|
||||
let debounceTimer = null;
|
||||
let highlightIdx = -1;
|
||||
|
||||
const renderSuggestions = (items) => {
|
||||
suggestions.innerHTML = '';
|
||||
highlightIdx = -1;
|
||||
}
|
||||
});
|
||||
if (!items.length) { suggestions.style.display = 'none'; return; }
|
||||
items.forEach(s => {
|
||||
const div = document.createElement('div');
|
||||
div.className = 'tag-suggestion-item';
|
||||
const name = document.createElement('span'); name.className = 'tag-suggestion-name'; name.textContent = s.tag;
|
||||
const meta = document.createElement('span'); meta.className = 'tag-suggestion-meta'; meta.textContent = `${s.tagged}× · ${s.score.toFixed(2)}`;
|
||||
div.appendChild(name); div.appendChild(meta);
|
||||
div.addEventListener('mousedown', (e) => { e.preventDefault(); input.value = s.tag; suggestions.style.display = 'none'; addTag(); });
|
||||
suggestions.appendChild(div);
|
||||
});
|
||||
suggestions.style.display = 'block';
|
||||
};
|
||||
|
||||
input.addEventListener('blur', () => {
|
||||
setTimeout(() => { suggestions.style.display = 'none'; }, 150);
|
||||
});
|
||||
input.addEventListener('input', () => {
|
||||
const q = input.value.trim();
|
||||
highlightIdx = -1;
|
||||
if (q.length < 1) { suggestions.style.display = 'none'; return; }
|
||||
if (debounceTimer) clearTimeout(debounceTimer);
|
||||
debounceTimer = setTimeout(async () => {
|
||||
try {
|
||||
const res = await fetch(`/api/v2/tags/suggest?q=${encodeURIComponent(q)}`);
|
||||
const json = await res.json();
|
||||
if (json.success && json.suggestions) renderSuggestions(json.suggestions.slice(0, 8));
|
||||
else suggestions.style.display = 'none';
|
||||
} catch (e) { suggestions.style.display = 'none'; }
|
||||
}, 300);
|
||||
});
|
||||
|
||||
input.addEventListener('keydown', e => {
|
||||
const items = suggestions.querySelectorAll('.tag-suggestion-item');
|
||||
if (!items.length || suggestions.style.display === 'none') return;
|
||||
if (e.key === 'ArrowDown') {
|
||||
e.preventDefault();
|
||||
if (highlightIdx >= 0 && highlightIdx < items.length) items[highlightIdx].classList.remove('active');
|
||||
highlightIdx = highlightIdx < items.length - 1 ? highlightIdx + 1 : 0;
|
||||
items[highlightIdx].classList.add('active'); items[highlightIdx].scrollIntoView({ block: 'nearest' });
|
||||
} else if (e.key === 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
if (highlightIdx >= 0 && highlightIdx < items.length) items[highlightIdx].classList.remove('active');
|
||||
highlightIdx = highlightIdx > 0 ? highlightIdx - 1 : items.length - 1;
|
||||
items[highlightIdx].classList.add('active'); items[highlightIdx].scrollIntoView({ block: 'nearest' });
|
||||
} else if (e.key === 'Escape') {
|
||||
suggestions.style.display = 'none'; highlightIdx = -1;
|
||||
}
|
||||
});
|
||||
|
||||
input.addEventListener('blur', () => { setTimeout(() => { suggestions.style.display = 'none'; }, 150); });
|
||||
} // end isLoggedIn tag block
|
||||
|
||||
// ESC to close, "e" to open
|
||||
document.addEventListener('keydown', (e) => {
|
||||
@@ -6922,30 +6878,39 @@ window.cancelAnimFrame = (function () {
|
||||
const THUMB_SIZES = ['s', 'm', 'l', 'xl'];
|
||||
const gridSizeBtns = overlay.querySelectorAll('.nav-grid-size-btn');
|
||||
|
||||
const applyNavThumbSize = (size) => {
|
||||
if (!THUMB_SIZES.includes(size)) size = 'm';
|
||||
const applyNavThumbSize = (size, persist = true) => {
|
||||
if (!THUMB_SIZES.includes(size)) size = window.f0ckDefaultThumbSize || 'm';
|
||||
document.documentElement.dataset.thumbSize = size;
|
||||
localStorage.setItem(THUMB_SIZE_KEY, size);
|
||||
if (persist) localStorage.setItem(THUMB_SIZE_KEY, size);
|
||||
gridSizeBtns.forEach(b => b.classList.toggle('active', b.dataset.thumbSize === size));
|
||||
};
|
||||
|
||||
// Sync active state each time the modal opens
|
||||
if (filterBtn) {
|
||||
filterBtn.addEventListener('click', () => {
|
||||
const cur = localStorage.getItem(THUMB_SIZE_KEY) || 'm';
|
||||
const cur = localStorage.getItem(THUMB_SIZE_KEY) || window.f0ckDefaultThumbSize || 'm';
|
||||
gridSizeBtns.forEach(b => b.classList.toggle('active', b.dataset.thumbSize === cur));
|
||||
});
|
||||
}
|
||||
|
||||
gridSizeBtns.forEach(btn => {
|
||||
btn.addEventListener('click', () => applyNavThumbSize(btn.dataset.thumbSize));
|
||||
btn.addEventListener('click', () => applyNavThumbSize(btn.dataset.thumbSize, true));
|
||||
});
|
||||
|
||||
// Apply persisted size immediately on init (every page load)
|
||||
applyNavThumbSize(localStorage.getItem(THUMB_SIZE_KEY) || 'm');
|
||||
// Apply on init — do NOT persist so config default stays effective until user chooses
|
||||
applyNavThumbSize(localStorage.getItem(THUMB_SIZE_KEY) || window.f0ckDefaultThumbSize || 'm', false);
|
||||
};
|
||||
|
||||
// ── Thumb size init (runs on every page, independently of the filter modal) ──
|
||||
const initThumbSize = () => {
|
||||
const THUMB_SIZE_KEY = 'scroller_thumb_size';
|
||||
const THUMB_SIZES = ['s', 'm', 'l', 'xl'];
|
||||
const size = localStorage.getItem(THUMB_SIZE_KEY) || window.f0ckDefaultThumbSize || 'm';
|
||||
document.documentElement.dataset.thumbSize = THUMB_SIZES.includes(size) ? size : (window.f0ckDefaultThumbSize || 'm');
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
initThumbSize(); // always runs — applies data-thumb-size to <html>
|
||||
initSearch();
|
||||
initExcludedTagsModal();
|
||||
if (window.updateFilterBadge) window.updateFilterBadge();
|
||||
|
||||
Reference in New Issue
Block a user