Merge pull request 'add option to also hide fav activity from public' (#40) from master into 98
Reviewed-on: #40
This commit is contained in:
5
migrations/add_hide_fav_badge.sql
Normal file
5
migrations/add_hide_fav_badge.sql
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
-- Add hide_fav_badge column to user_options table
|
||||||
|
ALTER TABLE user_options
|
||||||
|
ADD COLUMN IF NOT EXISTS hide_fav_badge boolean DEFAULT false;
|
||||||
|
|
||||||
|
COMMENT ON COLUMN public.user_options.favorites_private IS 'When true, the user''s favorite badge on item pages displays as a ghost icon without linking to their profile';
|
||||||
@@ -1499,7 +1499,8 @@ CREATE TABLE public.user_options (
|
|||||||
do_not_disturb boolean DEFAULT false,
|
do_not_disturb boolean DEFAULT false,
|
||||||
comment_display_mode integer DEFAULT 1,
|
comment_display_mode integer DEFAULT 1,
|
||||||
force_comment_display_mode integer DEFAULT 0,
|
force_comment_display_mode integer DEFAULT 0,
|
||||||
favorites_private boolean DEFAULT false
|
favorites_private boolean DEFAULT false,
|
||||||
|
hide_fav_badge boolean DEFAULT false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
5
public/s/img/ghost_fav.svg
Normal file
5
public/s/img/ghost_fav.svg
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
|
||||||
|
<rect width="100" height="100" fill="#242526"/>
|
||||||
|
<path d="M50 22 C37 22 28 32 28 45 L28 72 L35 66 L42 72 L50 66 L58 72 L65 66 L72 72 L72 45 C72 32 63 22 50 22 Z" fill="#666666" opacity="0.6"/>
|
||||||
|
<text x="50" y="58" font-family="system-ui, -apple-system, sans-serif" font-weight="bold" font-size="36" fill="#ffffff" text-anchor="middle">?</text>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 443 B |
@@ -8768,23 +8768,39 @@ class NotificationSystem {
|
|||||||
// Build DOM nodes imperatively (avoids Sanitizer stripping inline border-color)
|
// Build DOM nodes imperatively (avoids Sanitizer stripping inline border-color)
|
||||||
const fragment = document.createDocumentFragment();
|
const fragment = document.createDocumentFragment();
|
||||||
data.favs.forEach(fav => {
|
data.favs.forEach(fav => {
|
||||||
const avatarUrl = fav.avatar_file
|
if (fav.hide_fav_badge) {
|
||||||
? `/a/${fav.avatar_file}`
|
const a = document.createElement('a');
|
||||||
: (fav.avatar ? `/t/${fav.avatar}.webp` : '/a/default.png');
|
a.className = 'ghost-fav';
|
||||||
|
a.setAttribute('tooltip', 'Ghost Fav');
|
||||||
|
a.setAttribute('flow', 'up');
|
||||||
|
a.style.cursor = 'default';
|
||||||
|
|
||||||
const a = document.createElement('a');
|
const img = document.createElement('img');
|
||||||
a.href = `/user/${fav.user.toLowerCase()}`;
|
img.src = '/s/img/ghost_fav.svg';
|
||||||
a.setAttribute('tooltip', fav.display_name || fav.user);
|
img.style.height = '32px';
|
||||||
a.setAttribute('flow', 'up');
|
img.style.width = '32px';
|
||||||
|
|
||||||
const img = document.createElement('img');
|
a.appendChild(img);
|
||||||
img.src = avatarUrl;
|
fragment.appendChild(a);
|
||||||
img.style.height = '32px';
|
} else {
|
||||||
img.style.width = '32px';
|
const avatarUrl = fav.avatar_file
|
||||||
if (fav.username_color) img.style.borderColor = fav.username_color;
|
? `/a/${fav.avatar_file}`
|
||||||
|
: (fav.avatar ? `/t/${fav.avatar}.webp` : '/a/default.png');
|
||||||
|
|
||||||
a.appendChild(img);
|
const a = document.createElement('a');
|
||||||
fragment.appendChild(a);
|
a.href = `/user/${fav.user.toLowerCase()}`;
|
||||||
|
a.setAttribute('tooltip', fav.display_name || fav.user);
|
||||||
|
a.setAttribute('flow', 'up');
|
||||||
|
|
||||||
|
const img = document.createElement('img');
|
||||||
|
img.src = avatarUrl;
|
||||||
|
img.style.height = '32px';
|
||||||
|
img.style.width = '32px';
|
||||||
|
if (fav.username_color) img.style.borderColor = fav.username_color;
|
||||||
|
|
||||||
|
a.appendChild(img);
|
||||||
|
fragment.appendChild(a);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
favsContainer.innerHTML = '';
|
favsContainer.innerHTML = '';
|
||||||
|
|||||||
@@ -1150,6 +1150,37 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hideFavBadgeToggle = document.getElementById('hide_fav_badge_toggle');
|
||||||
|
if (hideFavBadgeToggle) {
|
||||||
|
hideFavBadgeToggle.addEventListener('change', async function() {
|
||||||
|
const hide_fav_badge = hideFavBadgeToggle.checked;
|
||||||
|
try {
|
||||||
|
const res = await fetch('/api/v2/settings/hide_fav_badge', {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/x-www-form-urlencoded',
|
||||||
|
'X-CSRF-Token': window.f0ckSession ? window.f0ckSession.csrf_token : ''
|
||||||
|
},
|
||||||
|
body: new URLSearchParams({ hide_fav_badge })
|
||||||
|
});
|
||||||
|
const data = await res.json();
|
||||||
|
if (data.success) {
|
||||||
|
showStatus('Hide favorite badge preference updated!', 'success');
|
||||||
|
if (window.f0ckSession) {
|
||||||
|
window.f0ckSession.hide_fav_badge = hide_fav_badge;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
alert(data.msg || 'Error saving preference');
|
||||||
|
hideFavBadgeToggle.checked = !hide_fav_badge;
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Update Hide Fav Badge error:', err);
|
||||||
|
alert('Connection error');
|
||||||
|
hideFavBadgeToggle.checked = !hide_fav_badge;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// New Dual Column Layout Toggle
|
// New Dual Column Layout Toggle
|
||||||
const layoutToggle = document.getElementById('use_new_layout_toggle');
|
const layoutToggle = document.getElementById('use_new_layout_toggle');
|
||||||
if (layoutToggle) {
|
if (layoutToggle) {
|
||||||
|
|||||||
@@ -167,6 +167,8 @@
|
|||||||
"disable_swiping_hint": "Navigation per Wischen auf Mobilgeräten deaktivieren",
|
"disable_swiping_hint": "Navigation per Wischen auf Mobilgeräten deaktivieren",
|
||||||
"favorites_private": "Private Favoriten",
|
"favorites_private": "Private Favoriten",
|
||||||
"favorites_private_hint": "Nur du und Administratoren können deine Favoritenliste sehen.",
|
"favorites_private_hint": "Nur du und Administratoren können deine Favoritenliste sehen.",
|
||||||
|
"hide_fav_badge": "Favoriten-Badge-Avatar verbergen",
|
||||||
|
"hide_fav_badge_hint": "Zeigt auf Beitragsseiten stattdessen ein Geist-Icon ohne Profilverlinkung an",
|
||||||
"image_expand_on_click": "Bilder beim Klicken inline erweitern",
|
"image_expand_on_click": "Bilder beim Klicken inline erweitern",
|
||||||
"image_expand_on_click_hint": "Anstatt das Scroll-Zoom-Modal zu öffnen, wird ein Bild beim Klicken innerhalb der Seite auf volle Größe erweitert.",
|
"image_expand_on_click_hint": "Anstatt das Scroll-Zoom-Modal zu öffnen, wird ein Bild beim Klicken innerhalb der Seite auf volle Größe erweitert.",
|
||||||
"enable_bg_blur": "Hintergrundunschärfe aktivieren",
|
"enable_bg_blur": "Hintergrundunschärfe aktivieren",
|
||||||
|
|||||||
@@ -167,6 +167,8 @@
|
|||||||
"disable_swiping_hint": "Disable swipe-to-navigate on mobile devices",
|
"disable_swiping_hint": "Disable swipe-to-navigate on mobile devices",
|
||||||
"favorites_private": "Private Favorites",
|
"favorites_private": "Private Favorites",
|
||||||
"favorites_private_hint": "Only you and administrators can view your favorites list.",
|
"favorites_private_hint": "Only you and administrators can view your favorites list.",
|
||||||
|
"hide_fav_badge": "Hide Favorite Badge Avatar",
|
||||||
|
"hide_fav_badge_hint": "Display as a ghost icon on post detail pages without linking to your profile",
|
||||||
"image_expand_on_click": "Expand images inline on click",
|
"image_expand_on_click": "Expand images inline on click",
|
||||||
"image_expand_on_click_hint": "Instead of opening the scroll zoom modal, clicking an image will expand it to full size within the page.",
|
"image_expand_on_click_hint": "Instead of opening the scroll zoom modal, clicking an image will expand it to full size within the page.",
|
||||||
"enable_bg_blur": "Enable Background blur",
|
"enable_bg_blur": "Enable Background blur",
|
||||||
|
|||||||
@@ -167,6 +167,8 @@
|
|||||||
"disable_swiping_hint": "Swipe-to-navigate uitschakelen op mobiele apparaten",
|
"disable_swiping_hint": "Swipe-to-navigate uitschakelen op mobiele apparaten",
|
||||||
"favorites_private": "Privé favorieten",
|
"favorites_private": "Privé favorieten",
|
||||||
"favorites_private_hint": "Alleen jij en beheerders kunnen je favorietenlijst bekijken.",
|
"favorites_private_hint": "Alleen jij en beheerders kunnen je favorietenlijst bekijken.",
|
||||||
|
"hide_fav_badge": "Favoriet-badge avatar verbergen",
|
||||||
|
"hide_fav_badge_hint": "Toon als een spook-icoon op berichtpagina's zonder koppeling naar je profiel",
|
||||||
"image_expand_on_click": "Afbeeldingen inline vergroten bij klikken",
|
"image_expand_on_click": "Afbeeldingen inline vergroten bij klikken",
|
||||||
"image_expand_on_click_hint": "In plaats van de scroll-zoom-modal te openen, wordt een afbeelding bij klikken vergroot tot volledige grootte binnen de pagina.",
|
"image_expand_on_click_hint": "In plaats van de scroll-zoom-modal te openen, wordt een afbeelding bij klikken vergroot tot volledige grootte binnen de pagina.",
|
||||||
"enable_bg_blur": "Achtergrondvervaging inschakelen",
|
"enable_bg_blur": "Achtergrondvervaging inschakelen",
|
||||||
|
|||||||
@@ -167,6 +167,8 @@
|
|||||||
"disable_swiping_hint": "Deaktivieren der Wisch-Navigation auf Mobilgeräten",
|
"disable_swiping_hint": "Deaktivieren der Wisch-Navigation auf Mobilgeräten",
|
||||||
"favorites_private": "Private Favoriten",
|
"favorites_private": "Private Favoriten",
|
||||||
"favorites_private_hint": "Nur du und Administratoren können deine Favoritenliste sehen.",
|
"favorites_private_hint": "Nur du und Administratoren können deine Favoritenliste sehen.",
|
||||||
|
"hide_fav_badge": "Herzi-Badge-Avatar versteckeln",
|
||||||
|
"hide_fav_badge_hint": "Zeigt auf Beitragsseiten 1 geiles Geist-Icon an vong Anonymität her",
|
||||||
"image_expand_on_click": "Bildli beim Klickle inline uffblähe",
|
"image_expand_on_click": "Bildli beim Klickle inline uffblähe",
|
||||||
"image_expand_on_click_hint": "Anstatt dat Scroll-Zoom-Moped aufzumache, wird n Bild beim Klickle uff volle Größ im Bereich uffgepumpt.",
|
"image_expand_on_click_hint": "Anstatt dat Scroll-Zoom-Moped aufzumache, wird n Bild beim Klickle uff volle Größ im Bereich uffgepumpt.",
|
||||||
"enable_bg_blur": "Hintergrundunschärfe aktivieren",
|
"enable_bg_blur": "Hintergrundunschärfe aktivieren",
|
||||||
|
|||||||
@@ -768,7 +768,7 @@ export default {
|
|||||||
link.suffix = '';
|
link.suffix = '';
|
||||||
}
|
}
|
||||||
const favorites = await db`
|
const favorites = await db`
|
||||||
select "user".user, "user_options".avatar, "user_options".avatar_file, "user_options".username_color, "user_options".display_name
|
select "user".user, "user_options".avatar, "user_options".avatar_file, "user_options".username_color, "user_options".display_name, "user_options".hide_fav_badge
|
||||||
from "favorites"
|
from "favorites"
|
||||||
left join "user" on "user".id = "favorites".user_id
|
left join "user" on "user".id = "favorites".user_id
|
||||||
left join "user_options" on "user_options".user_id = "favorites".user_id
|
left join "user_options" on "user_options".user_id = "favorites".user_id
|
||||||
|
|||||||
@@ -1066,7 +1066,7 @@ export default router => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const favs = await db`
|
const favs = await db`
|
||||||
select "user".user, "user_options".avatar, "user_options".avatar_file, "user_options".display_name, "user_options".username_color
|
select "user".user, "user_options".avatar, "user_options".avatar_file, "user_options".display_name, "user_options".username_color, "user_options".hide_fav_badge
|
||||||
from "favorites"
|
from "favorites"
|
||||||
left join "user" on "user".id = "favorites".user_id
|
left join "user" on "user".id = "favorites".user_id
|
||||||
left join "user_options" on "user_options".user_id = "favorites".user_id
|
left join "user_options" on "user_options".user_id = "favorites".user_id
|
||||||
|
|||||||
@@ -334,6 +334,25 @@ export default router => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Update Hide Fav Badge preference
|
||||||
|
group.put(/\/hide_fav_badge/, lib.loggedin, async (req, res) => {
|
||||||
|
const hide_fav_badge = req.post.hide_fav_badge === true || req.post.hide_fav_badge === 'true';
|
||||||
|
|
||||||
|
try {
|
||||||
|
await db`
|
||||||
|
update user_options
|
||||||
|
set hide_fav_badge = ${hide_fav_badge}
|
||||||
|
where user_id = ${+req.session.id}
|
||||||
|
`;
|
||||||
|
// Sync session immediately
|
||||||
|
if (req.session) req.session.hide_fav_badge = hide_fav_badge;
|
||||||
|
return res.json({ success: true, hide_fav_badge }, 200);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Update Hide Fav Badge pref error:', e);
|
||||||
|
return res.json({ success: false, msg: 'Error updating preference' }, 500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Update Username Color preference
|
// Update Username Color preference
|
||||||
group.put(/\/username_color/, lib.loggedin, async (req, res) => {
|
group.put(/\/username_color/, lib.loggedin, async (req, res) => {
|
||||||
const { color } = req.post;
|
const { color } = req.post;
|
||||||
|
|||||||
@@ -672,7 +672,7 @@ process.on('uncaughtException', err => {
|
|||||||
user = [_cachedRow];
|
user = [_cachedRow];
|
||||||
} else {
|
} else {
|
||||||
user = await db`
|
user = await db`
|
||||||
select "user".id, "user".login, "user".user, "user".admin, "user".is_moderator, "user".banned, "user".ban_reason, "user".ban_expires, "user".force_password_change, "user_sessions".id as sess_id, "user_sessions".csrf_token, "user_options".mode, "user_options".theme, "user_options".fullscreen, "user_options".excluded_tags, "user_options".avatar, "user_options".avatar_file, "user_options".show_motd, "user_options".strict_mode, "user_options".show_background, "user_options".use_new_layout, "user_options".username_color, "user_options".font, "user_options".disable_autoplay, "user_options".disable_swiping, "user_options".favorites_private, "user_options".description, "user_options".display_name, COALESCE("user_options".min_xd_score, 0) as min_xd_score, "user_options".ruffle_volume, "user_options".ruffle_background, "user_options".quote_emojis, "user_options".embed_youtube_in_comments, "user_options".hide_koepfe, "user_options".language, "user_options".use_alternative_infobox, "user_options".use_alternative_steuerung, "user_options".receive_system_notifications, "user_options".receive_user_notifications, "user_options".do_not_disturb, "user_options".comment_display_mode, "user_options".force_comment_display_mode
|
select "user".id, "user".login, "user".user, "user".admin, "user".is_moderator, "user".banned, "user".ban_reason, "user".ban_expires, "user".force_password_change, "user_sessions".id as sess_id, "user_sessions".csrf_token, "user_options".mode, "user_options".theme, "user_options".fullscreen, "user_options".excluded_tags, "user_options".avatar, "user_options".avatar_file, "user_options".show_motd, "user_options".strict_mode, "user_options".show_background, "user_options".use_new_layout, "user_options".username_color, "user_options".font, "user_options".disable_autoplay, "user_options".disable_swiping, "user_options".favorites_private, "user_options".hide_fav_badge, "user_options".description, "user_options".display_name, COALESCE("user_options".min_xd_score, 0) as min_xd_score, "user_options".ruffle_volume, "user_options".ruffle_background, "user_options".quote_emojis, "user_options".embed_youtube_in_comments, "user_options".hide_koepfe, "user_options".language, "user_options".use_alternative_infobox, "user_options".use_alternative_steuerung, "user_options".receive_system_notifications, "user_options".receive_user_notifications, "user_options".do_not_disturb, "user_options".comment_display_mode, "user_options".force_comment_display_mode
|
||||||
from "user_sessions"
|
from "user_sessions"
|
||||||
left join "user" on "user".id = "user_sessions".user_id
|
left join "user" on "user".id = "user_sessions".user_id
|
||||||
left join "user_options" on "user_options".user_id = "user_sessions".user_id
|
left join "user_options" on "user_options".user_id = "user_sessions".user_id
|
||||||
|
|||||||
@@ -197,7 +197,11 @@
|
|||||||
</span>
|
</span>
|
||||||
<span class="badge" id="favs" @if(!item.favorites.length) hidden@endif>
|
<span class="badge" id="favs" @if(!item.favorites.length) hidden@endif>
|
||||||
@each(item.favorites as fav)
|
@each(item.favorites as fav)
|
||||||
|
@if(fav.hide_fav_badge)
|
||||||
|
<a class="ghost-fav" tooltip="?" flow="up" style="cursor: default;"><img src="/s/img/ghost_fav.svg" style="height: 32px; width: 32px;" loading="lazy" /></a>
|
||||||
|
@else
|
||||||
<a href="/user/{{ fav.user.toLowerCase() }}" tooltip="{!! fav.display_name || fav.user !!}" flow="up"><img src="@if(fav.avatar_file)/a/{{ fav.avatar_file }}@elseif(fav.avatar)/t/{{ fav.avatar }}.webp@else/a/default.png@endif" style="height: 32px; width: 32px@if(fav.username_color); border-color: {{ fav.username_color }}@endif" loading="lazy" /></a>
|
<a href="/user/{{ fav.user.toLowerCase() }}" tooltip="{!! fav.display_name || fav.user !!}" flow="up"><img src="@if(fav.avatar_file)/a/{{ fav.avatar_file }}@elseif(fav.avatar)/t/{{ fav.avatar }}.webp@else/a/default.png@endif" style="height: 32px; width: 32px@if(fav.username_color); border-color: {{ fav.username_color }}@endif" loading="lazy" /></a>
|
||||||
|
@endif
|
||||||
@endeach
|
@endeach
|
||||||
</span>
|
</span>
|
||||||
@if(enable_xd_score && item.xd_score > 0)
|
@if(enable_xd_score && item.xd_score > 0)
|
||||||
|
|||||||
@@ -157,7 +157,11 @@
|
|||||||
</div>
|
</div>
|
||||||
<span id="favs" @if(!item.favorites.length) hidden@endif style="margin-top: 5px;">
|
<span id="favs" @if(!item.favorites.length) hidden@endif style="margin-top: 5px;">
|
||||||
@each(item.favorites as fav)
|
@each(item.favorites as fav)
|
||||||
|
@if(fav.hide_fav_badge)
|
||||||
|
<a class="ghost-fav" tooltip="?" flow="up" style="cursor: default;"><img src="/s/img/ghost_fav.svg" style="height: 32px; width: 32px;" loading="lazy" /></a>
|
||||||
|
@else
|
||||||
<a href="/user/{{ fav.user.toLowerCase() }}" tooltip="{!! fav.display_name || fav.user !!}" flow="up"><img src="@if(fav.avatar_file)/a/{{ fav.avatar_file }}@elseif(fav.avatar)/t/{{ fav.avatar }}.webp@else/a/default.png@endif" style="height: 32px; width: 32px@if(fav.username_color); border-color: {{ fav.username_color }}@endif" loading="lazy" /></a>
|
<a href="/user/{{ fav.user.toLowerCase() }}" tooltip="{!! fav.display_name || fav.user !!}" flow="up"><img src="@if(fav.avatar_file)/a/{{ fav.avatar_file }}@elseif(fav.avatar)/t/{{ fav.avatar }}.webp@else/a/default.png@endif" style="height: 32px; width: 32px@if(fav.username_color); border-color: {{ fav.username_color }}@endif" loading="lazy" /></a>
|
||||||
|
@endif
|
||||||
@endeach
|
@endeach
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
|||||||
@@ -326,6 +326,13 @@
|
|||||||
<span>{{ t('settings.favorites_private') }}</span>
|
<span>{{ t('settings.favorites_private') }}</span>
|
||||||
</label>
|
</label>
|
||||||
<small class="text-muted" style="margin-left: 25px;">{{ t('settings.favorites_private_hint') }}</small>
|
<small class="text-muted" style="margin-left: 25px;">{{ t('settings.favorites_private_hint') }}</small>
|
||||||
|
<div class="sub-setting-item" style="margin-left: 25px; margin-top: 10px;">
|
||||||
|
<label for="hide_fav_badge_toggle" style="cursor: pointer; display: flex; align-items: center; gap: 10px;">
|
||||||
|
<input type="checkbox" id="hide_fav_badge_toggle" @if(session.hide_fav_badge===true) checked @endif>
|
||||||
|
<span>{{ t('settings.hide_fav_badge') }}</span>
|
||||||
|
</label>
|
||||||
|
<small class="text-muted" style="margin-left: 25px;">{{ t('settings.hide_fav_badge_hint') }}</small>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="setting-item" style="margin-top: 15px;">
|
<div class="setting-item" style="margin-top: 15px;">
|
||||||
<label for="show_background_toggle" style="cursor: pointer; display: flex; align-items: center; gap: 10px;">
|
<label for="show_background_toggle" style="cursor: pointer; display: flex; align-items: center; gap: 10px;">
|
||||||
|
|||||||
Reference in New Issue
Block a user