9 Commits
98 ... f0ckv2

Author SHA1 Message Date
6856f4109e g 2026-07-18 12:31:05 +02:00
4fa0ed7e58 f0ckv2 specifics... 2026-07-18 12:27:52 +02:00
2a5f8288d2 f0ckv2 specifics 2026-07-18 12:22:51 +02:00
a8af6427eb Merge pull request 'master' (#18) from master into f0ckv2
Reviewed-on: #18
2026-07-17 23:34:12 +00:00
b26b7518cb Merge pull request 'pipi kaka' (#17) from master into f0ckv2
Reviewed-on: #17
2026-07-17 22:33:32 +00:00
ce03f9d17f Merge pull request 'master' (#16) from master into f0ckv2
Reviewed-on: #16
2026-07-17 22:23:15 +00:00
87905dd547 Merge pull request 'master' (#15) from master into f0ckv2
Reviewed-on: #15
2026-07-17 21:53:32 +00:00
18a871976c ffff 2026-07-17 22:59:53 +02:00
d09cb44fa7 f0ckv2 things 2026-07-17 22:06:56 +02:00
9 changed files with 48 additions and 12 deletions

View File

@@ -7178,7 +7178,7 @@ span#favs {
grid-column: 1/4;
padding: 5px;
background: var(--badge-bg);
border-top: 1px solid var(--nav-border-color);
border-bottom: 1px solid var(--nav-border-color);
}
span#favs[hidden] {
@@ -8351,7 +8351,7 @@ input#s_avatar {
.nav-user-menu a {
display: block;
padding: 10px 15px;
padding: 10px 10px;
color: var(--white);
text-decoration: none;
transition: background 0.2s;
@@ -8722,6 +8722,8 @@ video.autoplay-gif {
text-align: center;
background: var(--bg);
border-bottom: 1px solid var(--nav-link-hover-bg);
border-left: 1px solid var(--nav-border-color);
border-right: 1px solid var(--nav-border-color);
}
/* Markdown Styles */
@@ -9678,7 +9680,7 @@ html[theme="f0ck95d"] .badge-dark {
}
.steuerung {
font-size: large;
font-size: x-large;
font-family: monospace;
}
@@ -14036,7 +14038,7 @@ textarea#profile_description {
align-items: flex-start;
width: 100%;
max-width: 100%;
min-height: 120px;
min-height: 90px;
box-sizing: border-box;
margin-bottom: 10px;
}

View File

@@ -120,6 +120,8 @@ class CommentSystem {
if (!document.body.classList.contains('layout-legacy') && !document.body.classList.contains('legacy-view')) return;
const updateBtn = () => {
if (!this.initialLoadDone) return;
const btn = document.querySelector('.scroll-to-bottom');
if (!btn) return;
@@ -128,7 +130,9 @@ class CommentSystem {
const rect = container.getBoundingClientRect();
// Detect if we are at the bottom of the comments section
const isAtBottom = rect.bottom < window.innerHeight + 100;
// We also require window.scrollY > 50 to prevent flickering to 'scroll to top'
// when the page first loads and images haven't fully pushed the container down yet.
const isAtBottom = (rect.bottom < window.innerHeight + 100) && (window.scrollY > 50);
if (isAtBottom) {
btn.classList.add('is-at-bottom');
@@ -673,6 +677,7 @@ class CommentSystem {
this.render(comments, this.user, initialIsSubscribed);
this.initialLoadDone = true;
this.restoreState(state);
if (this.scrollHandler) this.scrollHandler();
this._loadDanmaku(comments);
if (scrollToId) {
@@ -743,6 +748,7 @@ class CommentSystem {
this.reconcile(data.comments, data.user_id, data.is_subscribed);
this.initialLoadDone = true;
this.restoreState(state);
if (this.scrollHandler) this.scrollHandler();
if (scrollToId) {
this.preservingScroll = false;
@@ -772,6 +778,7 @@ class CommentSystem {
this.render(data.comments, data.user_id, data.is_subscribed);
this.initialLoadDone = true;
this.restoreState(state);
if (this.scrollHandler) this.scrollHandler();
this._loadDanmaku(data.comments);
if (scrollToId) {

View File

@@ -252,6 +252,7 @@ export default {
${hallFilter}
${userHallFilter}
${!session && getGlobalfilter() ? db`and not exists (select 1 from tags_assign where item_id = items.id and (${db.unsafe(getGlobalfilter())}))` : db``}
${!session && cfg.websrv.public_untagged === false ? db`and exists (select 1 from tags_assign where item_id = items.id)` : db``}
${excludedTags.length > 0 ? db`and not exists (select 1 from tags_assign where item_id = items.id and tag_id = any(${excludedTags}::int[]))` : db``}
${newerThan ? db`and items.id > ${newerThan}` : db``}
${xdFilter}
@@ -294,6 +295,7 @@ export default {
${hallFilter}
${userHallFilter}
${!session && getGlobalfilter() ? db`and not exists (select 1 from tags_assign where item_id = items.id and (${db.unsafe(getGlobalfilter())}))` : db``}
${!session && cfg.websrv.public_untagged === false ? db`and exists (select 1 from tags_assign where item_id = items.id)` : db``}
${excludedTags.length > 0 ? db`and not exists (select 1 from tags_assign where item_id = items.id and tag_id = any(${excludedTags}::int[]))` : db``}
${newerThan ? db`and items.id > ${newerThan}` : db``}
${xdFilter}
@@ -516,6 +518,7 @@ export default {
${!fav && user ? db`and items.username ilike ${user}` : db``}
${mimeSQL}
${!session && getGlobalfilter() ? db`and not exists (select 1 from tags_assign where item_id = items.id and (${db.unsafe(getGlobalfilter())}))` : db``}
${!session && cfg.websrv.public_untagged === false ? db`and exists (select 1 from tags_assign where item_id = items.id)` : db``}
${excludedTags.length > 0 ? db`and not exists (select 1 from tags_assign where item_id = items.id and tag_id = any(${excludedTags}::int[]))` : db``}
`;
};
@@ -552,6 +555,7 @@ export default {
items.id = ${itemid} and
items.active = true
${!session && getGlobalfilter() ? db`and not exists (select 1 from tags_assign where item_id = items.id and (${db.unsafe(getGlobalfilter())}))` : db``}
${!session && cfg.websrv.public_untagged === false ? db`and exists (select 1 from tags_assign where item_id = items.id)` : db``}
limit 1
`;
@@ -569,7 +573,7 @@ export default {
if (!actitem) {
// Item not found or filtered out - check if it exists but was filtered (for OG meta tags)
if (!session && getGlobalfilter()) {
if (!session && (getGlobalfilter() || cfg.websrv.public_untagged === false)) {
const unfilteredItem = await db`
select id from items where id = ${itemid} and active = true limit 1
`;
@@ -925,6 +929,7 @@ export default {
AND items.title IS NOT NULL
${mimeSQL}
${!session && getGlobalfilter() ? db`and not exists (select 1 from tags_assign where item_id = items.id and (${db.unsafe(getGlobalfilter())}))` : db``}
${!session && cfg.websrv.public_untagged === false ? db`and exists (select 1 from tags_assign where item_id = items.id)` : db``}
${excludedTags.length > 0 ? db`and not exists (select 1 from tags_assign where item_id = items.id and tag_id = any(${excludedTags}::int[]))` : db``}
ORDER BY random()
LIMIT 1
@@ -945,6 +950,7 @@ export default {
and items.active = true
${mimeSQL}
${!session && getGlobalfilter() ? db`and not exists (select 1 from tags_assign where item_id = items.id and (${db.unsafe(getGlobalfilter())}))` : db``}
${!session && cfg.websrv.public_untagged === false ? db`and exists (select 1 from tags_assign where item_id = items.id)` : db``}
group by items.id
order by random()
limit 1
@@ -987,6 +993,7 @@ export default {
${hall ? db`and items.id in (select item_id from halls_assign ha join halls h on h.id = ha.hall_id where h.slug = ${hall})` : db``}
${mimeSQL}
${!session && getGlobalfilter() ? db`and not exists (select 1 from tags_assign where item_id = items.id and (${db.unsafe(getGlobalfilter())}))` : db``}
${!session && cfg.websrv.public_untagged === false ? db`and exists (select 1 from tags_assign where item_id = items.id)` : db``}
${excludedTags.length > 0 ? db`and not exists (select 1 from tags_assign where item_id = items.id and tag_id = any(${excludedTags}::int[]))` : db``}
group by items.id, tags.tag
order by random()
@@ -1006,6 +1013,7 @@ export default {
and items.active = true
${mimeSQL}
${!session && getGlobalfilter() ? db`and not exists (select 1 from tags_assign where item_id = items.id and (${db.unsafe(getGlobalfilter())}))` : db``}
${!session && cfg.websrv.public_untagged === false ? db`and exists (select 1 from tags_assign where item_id = items.id)` : db``}
${excludedTags.length > 0 ? db`and not exists (select 1 from tags_assign where item_id = items.id and tag_id = any(${excludedTags}::int[]))` : db``}
order by random()
limit 1
@@ -1021,6 +1029,8 @@ export default {
and uha.hall_id = ${userHallId}
and items.active = true
${mimeSQL}
${!session && getGlobalfilter() ? db`and not exists (select 1 from tags_assign where item_id = items.id and (${db.unsafe(getGlobalfilter())}))` : db``}
${!session && cfg.websrv.public_untagged === false ? db`and exists (select 1 from tags_assign where item_id = items.id)` : db``}
${excludedTags.length > 0 ? db`and not exists (select 1 from tags_assign where item_id = items.id and tag_id = any(${excludedTags}::int[]))` : db``}
order by random()
limit 1
@@ -1048,6 +1058,7 @@ export default {
WHERE items.active = true
${mimeSQL}
${checkFilter ? db`AND filter_ta.tag_id IS NULL` : db``}
${!session && cfg.websrv.public_untagged === false ? db`AND EXISTS (SELECT 1 FROM tags_assign WHERE item_id = items.id)` : db``}
${excludedTags.length > 0 ? db`AND NOT EXISTS (SELECT 1 FROM tags_assign WHERE item_id = items.id AND tag_id = ANY(${excludedTags}::int[]))` : db``}
${!useTagIdOpt ? db`AND ${db.unsafe(globalModeQuery)}` : db``}
ORDER BY random()

View File

@@ -972,6 +972,15 @@ export default (router, tpl) => {
// Recent Activity Page
router.get(/\/activity\/?/, async (req, res) => {
if (!req.session && cfg.main.hide_comments_from_public) {
if (req.url.qs?.json === 'true' || req.headers['x-requested-with'] === 'XMLHttpRequest') {
return res.reply({
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ success: true, comments: [], page: 1, hasMore: false, require_login: true })
});
}
return res.reply({ code: 403, body: "Forbidden" });
}
try {
const page = +(req.url.qs?.page || 1);
const limit = Math.min(+(req.url.qs?.limit || 50), 50);

View File

@@ -142,8 +142,9 @@ db.listen('activity', async (payload) => {
data.username = 'System';
}
// Broadcast to ALL connected clients
// Broadcast to ALL connected clients (except guests if comments are hidden)
for (const client of clients) {
if (!client.userId && cfg.main.hide_comments_from_public) continue;
client.send({ type: 'activity', data });
}
} catch (e) {

View File

@@ -1276,6 +1276,8 @@ process.on('uncaughtException', err => {
enable_danmaku: cfg.websrv.enable_danmaku !== false,
enable_item_title: cfg.websrv.enable_item_title !== false,
enable_global_chat: !!cfg.websrv.enable_global_chat,
enable_sidebar: cfg.websrv.enable_sidebar !== false,
sidebar_closed_default: cfg.websrv.sidebar_closed_default === true,
embed_youtube_in_comments: cfg.websrv.embed_youtube_in_comments !== false,
get koepfe_json() {
try {
@@ -1357,11 +1359,11 @@ process.on('uncaughtException', err => {
globals.lang = perRequestLang;
// Resolve per-request infobox preference
// Guests always get false — the alternative infobox is a logged-in user preference only
// Guests check the new config flag, whereas users use their session pref or default to the user flag
const useAltInfobox = (req && req.session && typeof req.session.use_alternative_infobox === 'boolean')
? req.session.use_alternative_infobox
: (req && !req.session
? false
? (cfg.websrv.guest_alternative_infobox === true)
: (data && typeof data.user_alternative_infobox === 'boolean'
? data.user_alternative_infobox
: (cfg.websrv.user_alternative_infobox !== false)));

View File

@@ -210,6 +210,7 @@
</div>
</div>
@if(session || !hide_comments_from_public)
<div id="comments-container"
data-item-id="{{ item.id }}"
@if(session) data-user="{{ session.user }}" @endif
@@ -221,6 +222,7 @@
</div>
@endif
</div>
@endif
<button class="mobile-scroll-to-top" title="Back to top" aria-label="Scroll to top"><i class="fa-solid fa-chevron-up"></i></button>
<script id="initial-subscription" type="application/json">{{ isSubscribed }}</script>

View File

@@ -102,7 +102,7 @@
@if(session)
@include(snippets/metadata-modal)
@endif
@if(!private_society || session)
@if(!private_society && enable_sidebar || session && enable_sidebar)
<div class="global-sidebar-right">
<div class="sidebar-activity">
<div id="sidebar-activity-container" class="sidebar-comments-list">
@@ -591,7 +591,9 @@
};
</script>
<script src="/s/js/f0ckm.js?v={{ ts }}"></script>
@if(enable_sidebar)
<script src="/s/js/sidebar-activity.js?v={{ ts }}"></script>
@endif
<script src="/s/js/flash_yank.js?v={{ ts }}"></script>
@if(show_koepfe && !(session && session.hide_koepfe))
<script>window.f0ckKoepfe = {{ koepfe_json }};</script>

View File

@@ -77,8 +77,8 @@
@endif
</head>
<body class="@if(session)@if(session.use_new_layout)layout-modern@else layout-legacy @endif@else @if(default_layout === 'legacy')layout-legacy@else layout-modern@endif @endif @if(private_society && !session)private-gate-active@endif">
<script>if(localStorage.getItem('sidebarRightHidden')==='true')document.body.classList.add('sidebar-right-hidden');if(localStorage.getItem('comments_hidden')==='true')document.body.classList.add('sidebar-left-hidden');(function(){var d=window.devicePixelRatio||1;console.log('[DPR] devicePixelRatio='+d);var t='dpr-1x';if(d>=1.55)t='dpr-high';else if(d>=1.39)t='dpr-150';else if(d>=1.26)t='dpr-130';else if(d>=1.20)t='dpr-120';else if(d>=1.05)t='dpr-110';document.documentElement.setAttribute('data-dpr',t);})();</script>
<body class="@if(session)@if(session.use_new_layout)layout-modern@else layout-legacy @endif@else @if(default_layout === 'legacy')layout-legacy@else layout-modern@endif @endif @if(private_society && !session)private-gate-active@endif @if(!enable_sidebar)sidebar-right-hidden@endif">
<script>if(localStorage.getItem('sidebarRightHidden')==='true' || (localStorage.getItem('sidebarRightHidden')===null && {{ sidebar_closed_default ? 'true' : 'false' }}))document.body.classList.add('sidebar-right-hidden');if(localStorage.getItem('comments_hidden')==='true')document.body.classList.add('sidebar-left-hidden');(function(){var d=window.devicePixelRatio||1;console.log('[DPR] devicePixelRatio='+d);var t='dpr-1x';if(d>=1.55)t='dpr-high';else if(d>=1.39)t='dpr-150';else if(d>=1.26)t='dpr-130';else if(d>=1.20)t='dpr-120';else if(d>=1.05)t='dpr-110';document.documentElement.setAttribute('data-dpr',t);})();</script>
@if(!private_society || session)
<canvas class="hidden-xs" id="bg"></canvas>
@endif