adding different layouts for testing

This commit is contained in:
2026-05-17 14:02:35 +02:00
parent 832f97970e
commit dbb8861aed
18 changed files with 238 additions and 41 deletions

View File

@@ -3628,6 +3628,83 @@ div.posts {
}
}
/* ── Feed Layout Variants ── */
/* Layout 0: Grid (compact) — default, no overrides needed */
div.posts.layout-0 {}
/* Layout 1: Modern (3-column wider grid) */
div.posts.layout-1 {
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}
@media (max-width: 600px) {
div.posts.layout-1 {
grid-template-columns: repeat(2, 1fr);
}
}
/* Layout 2: Feed (X / Instagram style — single-column cards) */
div.posts.layout-2 {
display: flex;
flex-direction: column;
gap: 18px;
max-width: 680px;
margin-left: auto;
margin-right: auto;
grid-template-columns: unset;
}
div.posts.layout-2 > a:not(.notif-item) {
width: 100%;
aspect-ratio: unset;
border-radius: 8px;
overflow: hidden;
}
div.posts.layout-2 > a:not(.notif-item)::before {
margin-top: 75%; /* ~4:3 portrait card */
}
@media (max-width: 600px) {
div.posts.layout-2 {
max-width: 100%;
gap: 12px;
}
}
/* Layout 3: YouTube style — 16:9 cards, 4-col desktop */
div.posts.layout-3 {
grid-template-columns: repeat(4, 1fr);
gap: 12px;
padding: 0 4px;
}
div.posts.layout-3 > a:not(.notif-item) {
border-radius: 6px;
overflow: hidden;
box-shadow: 0 2px 6px rgba(0,0,0,0.4);
transition: transform 0.15s ease, box-shadow 0.15s ease;
}
div.posts.layout-3 > a:not(.notif-item):hover,
div.posts.layout-3 > a:not(.notif-item).touch-active {
transform: translateY(-2px);
box-shadow: 0 5px 16px rgba(0,0,0,0.6);
outline: none;
}
/* No ::before override — preserves dynamic thumb aspect ratios (data-size spanning) */
/* Tablet: 3 columns */
@media (max-width: 960px) and (min-width: 601px) {
div.posts.layout-3 {
grid-template-columns: repeat(3, 1fr);
gap: 10px;
}
}
/* Mobile: 2 columns */
@media (max-width: 600px) {
div.posts.layout-3 {
grid-template-columns: repeat(2, 1fr);
gap: 8px;
padding: 0;
}
}
div.posts>a:not(.notif-item) {
display: inline-block;
position: relative;

View File

@@ -40,6 +40,24 @@ window.cancelAnimFrame = (function () {
if (ua.includes('Chrome')) htmlEl.classList.add('is-chrome');
if (ua.includes('Safari') && !ua.includes('Chrome')) htmlEl.classList.add('is-safari');
// Reload on back-forward cache restore so layout classes are always fresh from the server
window.addEventListener('pageshow', function(event) {
if (event.persisted) {
window.location.reload();
}
});
// Mirrors the server-side fallback logic in index.mjs:
// use the user's own feed_layout if they explicitly chose one (> 0),
// otherwise fall back to the site-wide default set via the admin dashboard.
window.getEffectiveFeedLayout = () => {
const s = window.f0ckSession;
if (!s) return 0;
const userLayout = (s.feed_layout !== undefined && s.feed_layout !== null) ? parseInt(s.feed_layout, 10) : 0;
const siteDefault = (s.default_feed_layout !== undefined && s.default_feed_layout !== null) ? parseInt(s.default_feed_layout, 10) : 0;
return (userLayout > 0) ? userLayout : siteDefault;
};
window.updateVisitIndicators = () => {
try {
// View indicators and counters have been permanently removed as requested.
@@ -1739,6 +1757,12 @@ window.cancelAnimFrame = (function () {
// Ensure loading state is reset just in case
if (restoredPosts._infiniteState) restoredPosts._infiniteState.loading = false;
}
// Re-apply layout class on the restored node — the cached node may have
// an outdated class if the user changed layout since it was cached.
if (restoredPosts) {
restoredPosts.className = restoredPosts.className.replace(/\blayout-\d\b/g, '').trim() + ' layout-' + window.getEffectiveFeedLayout();
}
}
// Restore Scroll Position
@@ -1806,7 +1830,8 @@ window.cancelAnimFrame = (function () {
// Clear entire main content and create fresh grid structure (with sidebar for index)
const indexWrapper = document.createElement('div');
indexWrapper.className = 'index-layout-wrapper';
indexWrapper.innerHTML = '<div class="index-container"><div class="posts grid-transition"></div></div>';
const layoutClass = 'layout-' + window.getEffectiveFeedLayout();
indexWrapper.innerHTML = `<div class="index-container"><div class="posts grid-transition ${layoutClass}"></div></div>`;
main.innerHTML = '';
main.appendChild(indexWrapper);
@@ -2305,6 +2330,8 @@ window.cancelAnimFrame = (function () {
if (replace) {
// Atomic replacement to prevent "jumping"
posts.innerHTML = data.html;
// Re-apply layout class (innerHTML wipe discards it; use effective layout = user pref or site default)
posts.className = posts.className.replace(/\blayout-\d\b/g, '').trim() + ' layout-' + window.getEffectiveFeedLayout();
window.updateVisitIndicators();
window.initLazyLoading();

View File

@@ -551,11 +551,13 @@
});
}
// New Dual Column Layout Toggle
const layoutToggle = document.getElementById('use_new_layout_toggle');
if (layoutToggle) {
layoutToggle.addEventListener('change', async () => {
const use_new_layout = layoutToggle.checked;
// Feed Layout Select
const feedLayoutSelect = document.getElementById('feed_layout_select');
if (feedLayoutSelect) {
feedLayoutSelect.addEventListener('change', async () => {
const feed_layout = parseInt(feedLayoutSelect.value, 10);
const prev = feedLayoutSelect.dataset.prev ?? feedLayoutSelect.value;
feedLayoutSelect.dataset.prev = feedLayoutSelect.value;
try {
const res = await fetch('/api/v2/settings/layout', {
method: 'PUT',
@@ -563,23 +565,24 @@
'Content-Type': 'application/json',
'X-CSRF-Token': window.f0ckSession?.csrf_token
},
body: JSON.stringify({ use_new_layout })
body: JSON.stringify({ feed_layout })
});
const data = await res.json();
if (data.success) {
window.location.reload();
} else {
alert(data.msg || 'Error saving preference');
layoutToggle.checked = !use_new_layout; // Revert
feedLayoutSelect.value = prev; // Revert
}
} catch (err) {
console.error(err);
alert('Failed to save Layout preference');
layoutToggle.checked = !use_new_layout; // Revert
alert('Failed to save layout preference');
feedLayoutSelect.value = prev; // Revert
}
});
}
// Disable Autoplay Toggle
const autoplayToggle = document.getElementById('disable_autoplay_toggle');
if (autoplayToggle) {