live update banner udpates
This commit is contained in:
@@ -7306,8 +7306,11 @@ class NotificationSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (data.type === 'profile_update') {
|
} else if (data.type === 'profile_update') {
|
||||||
const { display_name, user } = data.data;
|
const { display_name, user, banner_file, banner_position, banner_size } = data.data;
|
||||||
this.applyDisplayNameUpdate(display_name, user);
|
if (display_name !== undefined) this.applyDisplayNameUpdate(display_name, user);
|
||||||
|
if (banner_file !== undefined || banner_position !== undefined || banner_size !== undefined) {
|
||||||
|
this.applyBannerUpdate(banner_file, banner_position, banner_size, user);
|
||||||
|
}
|
||||||
// Sync preferences to global session object for client-side gating (like DND)
|
// Sync preferences to global session object for client-side gating (like DND)
|
||||||
if (window.f0ckSession && data.data.user_id === window.f0ckSession.id) {
|
if (window.f0ckSession && data.data.user_id === window.f0ckSession.id) {
|
||||||
for (const key in data.data) {
|
for (const key in data.data) {
|
||||||
@@ -7366,6 +7369,34 @@ class NotificationSystem {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Helper: apply banner update to relevant DOM nodes
|
||||||
|
this.applyBannerUpdate = (banner_file, banner_position, banner_size, user) => {
|
||||||
|
const userName = user || window.f0ckSession?.user;
|
||||||
|
if (!userName) return;
|
||||||
|
|
||||||
|
const setBannerStyle = (el) => {
|
||||||
|
if (banner_file) {
|
||||||
|
el.style.setProperty('--author-banner', `url('/a/${banner_file}?t=${Date.now()}')`);
|
||||||
|
el.style.setProperty('--author-banner-position', banner_position || 'center');
|
||||||
|
el.style.setProperty('--author-banner-size', banner_size || 'cover');
|
||||||
|
} else {
|
||||||
|
el.style.removeProperty('--author-banner');
|
||||||
|
el.style.removeProperty('--author-banner-position');
|
||||||
|
el.style.removeProperty('--author-banner-size');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
document.querySelectorAll(`.profile_head[data-banner-user="${userName}"], .user-infobox-block[data-banner-user="${userName}"]`).forEach(el => {
|
||||||
|
setBannerStyle(el);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Special case for settings page preview block
|
||||||
|
if (window.f0ckSession && userName === window.f0ckSession.user) {
|
||||||
|
const previewBlock = document.getElementById('live-profile-preview-box');
|
||||||
|
if (previewBlock) setBannerStyle(previewBlock);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Poll fresh display_name from DB — used on tab focus to catch missed SSE events
|
// Poll fresh display_name from DB — used on tab focus to catch missed SSE events
|
||||||
this.syncDisplayName = async () => {
|
this.syncDisplayName = async () => {
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -193,6 +193,14 @@ export const handleBannerUpload = async (req, res) => {
|
|||||||
banner_size = ${parts.banner_size || 'cover'}
|
banner_size = ${parts.banner_size || 'cover'}
|
||||||
where user_id = ${+req.session.id}
|
where user_id = ${+req.session.id}
|
||||||
`;
|
`;
|
||||||
|
const payloadStr = JSON.stringify({
|
||||||
|
user_id: +req.session.id,
|
||||||
|
user: req.session.user,
|
||||||
|
banner_file: finalFilename,
|
||||||
|
banner_position: parts.banner_position || 'center',
|
||||||
|
banner_size: parts.banner_size || 'cover'
|
||||||
|
});
|
||||||
|
await db`select pg_notify('profile_update', ${payloadStr})`;
|
||||||
} catch (dbErr) {
|
} catch (dbErr) {
|
||||||
console.error('[BANNER HANDLER] DB update failed:', dbErr.message);
|
console.error('[BANNER HANDLER] DB update failed:', dbErr.message);
|
||||||
await fs.unlink(finalPath).catch(() => {});
|
await fs.unlink(finalPath).catch(() => {});
|
||||||
@@ -265,6 +273,12 @@ export const handleBannerDelete = async (req, res) => {
|
|||||||
set banner_file = null
|
set banner_file = null
|
||||||
where user_id = ${+req.session.id}
|
where user_id = ${+req.session.id}
|
||||||
`;
|
`;
|
||||||
|
const payloadStr = JSON.stringify({
|
||||||
|
user_id: +req.session.id,
|
||||||
|
user: req.session.user,
|
||||||
|
banner_file: null
|
||||||
|
});
|
||||||
|
await db`select pg_notify('profile_update', ${payloadStr})`;
|
||||||
|
|
||||||
console.log('[BANNER HANDLER] Delete complete');
|
console.log('[BANNER HANDLER] Delete complete');
|
||||||
return sendJson(res, { success: true, msg: 'Custom banner removed' }, 200);
|
return sendJson(res, { success: true, msg: 'Custom banner removed' }, 200);
|
||||||
|
|||||||
@@ -94,6 +94,17 @@ db.listen('profile_update', (payload) => {
|
|||||||
if (data.do_not_disturb !== undefined) client.do_not_disturb = data.do_not_disturb;
|
if (data.do_not_disturb !== undefined) client.do_not_disturb = data.do_not_disturb;
|
||||||
|
|
||||||
client.send({ type: 'profile_update', data });
|
client.send({ type: 'profile_update', data });
|
||||||
|
} else {
|
||||||
|
// For other users, only send public profile fields (so their DOM can live-update)
|
||||||
|
const publicData = {
|
||||||
|
user_id: data.user_id,
|
||||||
|
user: data.user,
|
||||||
|
display_name: data.display_name,
|
||||||
|
banner_file: data.banner_file,
|
||||||
|
banner_position: data.banner_position,
|
||||||
|
banner_size: data.banner_size
|
||||||
|
};
|
||||||
|
client.send({ type: 'profile_update', data: publicData });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="profile_head" style="@if(user.banner_file && user_banner_enabled) --author-banner: url('/a/{{ user.banner_file }}'); --author-banner-position: {{ user.banner_position || 'center' }}; --author-banner-size: {{ user.banner_size || 'cover' }}; @endif">
|
<div class="profile_head" data-banner-user="{{ user.user || '' }}" style="@if(user.banner_file && user_banner_enabled) --author-banner: url('/a/{{ user.banner_file }}'); --author-banner-position: {{ user.banner_position || 'center' }}; --author-banner-size: {{ user.banner_size || 'cover' }}; @endif">
|
||||||
@if(user.avatar_file)
|
@if(user.avatar_file)
|
||||||
<div class="profile_head_avatar">
|
<div class="profile_head_avatar">
|
||||||
<img src="/a/{{ user.avatar_file }}" style="display: grid;width: 55px" />
|
<img src="/a/{{ user.avatar_file }}" style="display: grid;width: 55px" />
|
||||||
|
|||||||
@@ -84,7 +84,7 @@
|
|||||||
|
|
||||||
<div class="blahlol">
|
<div class="blahlol">
|
||||||
@if(user_alternative_infobox)
|
@if(user_alternative_infobox)
|
||||||
<div class="user-infobox-block" style="--author-accent: @if(item.author_color){{ item.author_color }}@else var(--accent) @endif; --author-border: @if(item.author_color){{ item.author_color }}@else var(--accent) @endif;@if(item.author_banner_file && user_banner_enabled) --author-banner: url('/a/{{ item.author_banner_file }}'); --author-banner-position: {{ item.author_banner_position || 'center' }}; --author-banner-size: {{ item.author_banner_size || 'cover' }};@endif">
|
<div class="user-infobox-block" data-banner-user="{{ item.username || '' }}" style="--author-accent: @if(item.author_color){{ item.author_color }}@else var(--accent) @endif; --author-border: @if(item.author_color){{ item.author_color }}@else var(--accent) @endif;@if(item.author_banner_file && user_banner_enabled) --author-banner: url('/a/{{ item.author_banner_file }}'); --author-banner-position: {{ item.author_banner_position || 'center' }}; --author-banner-size: {{ item.author_banner_size || 'cover' }};@endif">
|
||||||
|
|
||||||
<div class="user-infobox-avatar">
|
<div class="user-infobox-avatar">
|
||||||
<a href="/user/{{ (item.username || '').toLowerCase() }}">
|
<a href="/user/{{ (item.username || '').toLowerCase() }}">
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<div class="profile_head" style="@if(user.banner_file && user_banner_enabled) --author-banner: url('/a/{{ user.banner_file }}'); --author-banner-position: {{ user.banner_position || 'center' }}; --author-banner-size: {{ user.banner_size || 'cover' }}; @endif">
|
<div class="profile_head" data-banner-user="{{ user.user || '' }}" style="@if(user.banner_file && user_banner_enabled) --author-banner: url('/a/{{ user.banner_file }}'); --author-banner-position: {{ user.banner_position || 'center' }}; --author-banner-size: {{ user.banner_size || 'cover' }}; @endif">
|
||||||
@if(user.is_ghost)
|
@if(user.is_ghost)
|
||||||
<div class="profile_head_avatar">
|
<div class="profile_head_avatar">
|
||||||
<div class="avatar-placeholder" style="background: #444; color: #888; width: 55px; height: 55px; display: flex; align-items: center; justify-content: center; font-size: 24px; font-weight: bold; border-radius: 4px;">?</div>
|
<div class="avatar-placeholder" style="background: #444; color: #888; width: 55px; height: 55px; display: flex; align-items: center; justify-content: center; font-size: 24px; font-weight: bold; border-radius: 4px;">?</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user