hghdf
This commit is contained in:
@@ -17334,3 +17334,173 @@ a.lazy-thumb.filtered-upload-ghost:hover::after {
|
||||
filter: brightness(0.6);
|
||||
}
|
||||
.edit-mode-active #inline-banner-edit-wrapper { display: block !important; }
|
||||
|
||||
/* Settings Direct-Editable Profile Card */
|
||||
.editable-profile-card {
|
||||
position: relative;
|
||||
transition: box-shadow 0.2s ease, border-color 0.2s ease;
|
||||
border-radius: 8px;
|
||||
}
|
||||
.editable-profile-card:hover {
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.35);
|
||||
}
|
||||
|
||||
.card-banner-controls-overlay {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.card-overlay-btn {
|
||||
background: rgba(0, 0, 0, 0.7);
|
||||
color: #fff;
|
||||
border: 1px solid rgba(255, 255, 255, 0.2);
|
||||
backdrop-filter: blur(4px);
|
||||
font-size: 0.78rem;
|
||||
padding: 4px 10px;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.card-overlay-btn:hover {
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
border-color: var(--accent);
|
||||
color: var(--accent);
|
||||
}
|
||||
.card-overlay-btn.btn-danger:hover {
|
||||
border-color: #ff6b6b;
|
||||
color: #ff6b6b;
|
||||
}
|
||||
|
||||
.editable-avatar-container {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
}
|
||||
.avatar-hover-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.55);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
opacity: 0;
|
||||
transition: opacity 0.2s ease;
|
||||
border-radius: 50%;
|
||||
color: #fff;
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
.editable-avatar-container:hover .avatar-hover-overlay {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.avatar-quick-remove {
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
right: -4px;
|
||||
background: #ff4757;
|
||||
color: #fff;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
font-size: 0.72rem;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
z-index: 5;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.4);
|
||||
transition: transform 0.15s ease, background 0.15s ease;
|
||||
}
|
||||
.avatar-quick-remove:hover {
|
||||
transform: scale(1.15);
|
||||
background: #ff6b6b;
|
||||
}
|
||||
|
||||
.inline-edit-username-wrapper {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
position: relative;
|
||||
}
|
||||
.user-infobox-username[contenteditable="true"] {
|
||||
border-bottom: 1px dashed rgba(255, 255, 255, 0.3);
|
||||
padding: 1px 4px;
|
||||
border-radius: 3px;
|
||||
transition: all 0.2s ease;
|
||||
}
|
||||
.user-infobox-username[contenteditable="true"]:hover {
|
||||
border-bottom-color: var(--accent);
|
||||
background: rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
.user-infobox-username[contenteditable="true"]:focus {
|
||||
outline: none;
|
||||
border-bottom: 2px solid var(--accent);
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.color-picker-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid rgba(255, 255, 255, 0.8);
|
||||
cursor: pointer;
|
||||
font-size: 0.68rem;
|
||||
color: #fff;
|
||||
text-shadow: 0 0 2px rgba(0,0,0,0.8);
|
||||
flex-shrink: 0;
|
||||
transition: transform 0.2s ease, border-color 0.2s ease;
|
||||
box-shadow: 0 2px 5px rgba(0,0,0,0.3);
|
||||
}
|
||||
.color-picker-badge:hover {
|
||||
transform: scale(1.18);
|
||||
border-color: #fff;
|
||||
}
|
||||
|
||||
.user-infobox-description[contenteditable="true"] {
|
||||
min-height: 44px;
|
||||
padding: 6px 8px;
|
||||
border-radius: 4px;
|
||||
border: 1px dashed rgba(255, 255, 255, 0.2);
|
||||
transition: all 0.2s ease;
|
||||
position: relative;
|
||||
}
|
||||
.user-infobox-description[contenteditable="true"]:empty::before {
|
||||
content: attr(data-placeholder);
|
||||
color: var(--text-muted);
|
||||
font-style: italic;
|
||||
}
|
||||
.user-infobox-description[contenteditable="true"]:hover {
|
||||
border-color: var(--accent);
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
.user-infobox-description[contenteditable="true"]:focus {
|
||||
outline: none;
|
||||
border-style: solid;
|
||||
border-color: var(--accent);
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
|
||||
.inline-save-btn {
|
||||
background: var(--accent);
|
||||
color: #fff;
|
||||
border: none;
|
||||
padding: 3px 10px;
|
||||
font-size: 0.78rem;
|
||||
border-radius: 4px;
|
||||
cursor: pointer;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
.inline-save-btn:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
|
||||
@@ -137,10 +137,13 @@
|
||||
const statusDiv = document.getElementById('avatar-upload-status');
|
||||
const preview = document.getElementById('avatar-preview');
|
||||
|
||||
const showStatus = (msg, type) => {
|
||||
const showStatus = (msg, type = 'info') => {
|
||||
if (msg && window.flashMessage) {
|
||||
window.flashMessage(msg, 2500, type);
|
||||
}
|
||||
if (statusDiv) {
|
||||
statusDiv.textContent = msg;
|
||||
statusDiv.className = 'avatar-status ' + type;
|
||||
statusDiv.className = 'avatar-status ' + (type || '');
|
||||
}
|
||||
};
|
||||
|
||||
@@ -177,6 +180,7 @@
|
||||
filenameSpan.textContent = file.name;
|
||||
uploadBtn.disabled = false;
|
||||
showStatus('', '');
|
||||
uploadBtn.click();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1674,8 +1678,11 @@
|
||||
|
||||
// Two-way sync: swatch → text input
|
||||
if (colorPicker && colorHex) {
|
||||
const colorBadge = document.getElementById('color-picker-badge');
|
||||
|
||||
colorPicker.addEventListener('input', () => {
|
||||
colorHex.value = colorPicker.value;
|
||||
if (colorBadge) colorBadge.style.background = colorPicker.value;
|
||||
const liveBox = document.getElementById('live-profile-preview-box');
|
||||
if (liveBox) {
|
||||
liveBox.style.setProperty('--author-accent', colorPicker.value);
|
||||
@@ -1683,6 +1690,11 @@
|
||||
}
|
||||
});
|
||||
|
||||
colorPicker.addEventListener('change', () => {
|
||||
if (colorBadge) colorBadge.style.background = colorPicker.value;
|
||||
if (saveColorBtn) saveColorBtn.click();
|
||||
});
|
||||
|
||||
// Text input → swatch (validate on each keystroke)
|
||||
colorHex.addEventListener('input', () => {
|
||||
const val = colorHex.value.trim();
|
||||
@@ -1852,7 +1864,9 @@
|
||||
const data = await res.json();
|
||||
if (data.success) {
|
||||
await applyFontLive(font);
|
||||
showStatus('Website font updated!', 'success');
|
||||
if (window.flashMessage) {
|
||||
window.flashMessage('Website font updated!', 2500, 'success');
|
||||
}
|
||||
} else {
|
||||
alert(data.msg || 'Error saving font preference');
|
||||
}
|
||||
@@ -1868,6 +1882,35 @@
|
||||
const saveDescriptionBtn = document.getElementById('btn-save-description');
|
||||
const descriptionStatus = document.getElementById('description-status');
|
||||
|
||||
const liveDesc = document.getElementById('live-preview-description');
|
||||
const descControls = document.getElementById('desc-edit-controls');
|
||||
|
||||
if (liveDesc && descriptionTextarea) {
|
||||
liveDesc.addEventListener('focus', () => {
|
||||
if (descControls) descControls.style.display = 'flex';
|
||||
});
|
||||
|
||||
liveDesc.addEventListener('input', () => {
|
||||
descriptionTextarea.value = liveDesc.innerText.trim();
|
||||
});
|
||||
|
||||
liveDesc.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) {
|
||||
e.preventDefault();
|
||||
liveDesc.blur();
|
||||
if (saveDescriptionBtn) saveDescriptionBtn.click();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (descriptionTextarea) {
|
||||
descriptionTextarea.addEventListener('input', () => {
|
||||
if (liveDesc && document.activeElement !== liveDesc) {
|
||||
liveDesc.textContent = descriptionTextarea.value || '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (saveDescriptionBtn && descriptionTextarea) {
|
||||
saveDescriptionBtn.addEventListener('click', async () => {
|
||||
const description = descriptionTextarea.value;
|
||||
@@ -1948,10 +1991,13 @@
|
||||
const emailStatus = document.getElementById('email-status');
|
||||
const displayEmail = document.getElementById('display-email');
|
||||
|
||||
const showAccountStatus = (el, msg, type) => {
|
||||
const showAccountStatus = (el, msg, type = 'info') => {
|
||||
if (msg && window.flashMessage) {
|
||||
window.flashMessage(msg, 2500, type);
|
||||
}
|
||||
if (el) {
|
||||
el.textContent = msg;
|
||||
el.className = 'avatar-status ' + type;
|
||||
el.className = 'avatar-status ' + (type || '');
|
||||
if (type === 'success') {
|
||||
setTimeout(() => { el.textContent = ''; el.className = 'avatar-status'; }, 5000);
|
||||
}
|
||||
@@ -2037,11 +2083,36 @@
|
||||
const displayNameBtn = document.getElementById('btn-update-display-name');
|
||||
const displayNameInput = document.getElementById('display_name_input');
|
||||
const displayNameStatus = document.getElementById('display-name-status');
|
||||
const liveUsernameEl = document.getElementById('live-preview-username');
|
||||
|
||||
if (liveUsernameEl && displayNameInput && displayNameBtn) {
|
||||
liveUsernameEl.addEventListener('input', () => {
|
||||
displayNameInput.value = liveUsernameEl.textContent.trim();
|
||||
});
|
||||
|
||||
liveUsernameEl.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
liveUsernameEl.blur();
|
||||
}
|
||||
});
|
||||
|
||||
liveUsernameEl.addEventListener('blur', () => {
|
||||
const val = liveUsernameEl.textContent.trim();
|
||||
if (!val) {
|
||||
liveUsernameEl.textContent = window.f0ckSession?.user || 'Username';
|
||||
displayNameInput.value = window.f0ckSession?.user || '';
|
||||
} else {
|
||||
displayNameInput.value = val;
|
||||
}
|
||||
displayNameBtn.click();
|
||||
});
|
||||
}
|
||||
|
||||
if (displayNameBtn && displayNameInput) {
|
||||
displayNameInput.addEventListener('input', () => {
|
||||
const liveName = document.getElementById('live-preview-username');
|
||||
if (liveName) {
|
||||
liveName.textContent = displayNameInput.value.trim() || window.f0ckSession?.user || 'Username';
|
||||
if (liveUsernameEl && document.activeElement !== liveUsernameEl) {
|
||||
liveUsernameEl.textContent = displayNameInput.value.trim() || window.f0ckSession?.user || 'Username';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -77,176 +77,118 @@
|
||||
<!-- ═══════════════════════════════ PROFILE ═══════════════════════════════ -->
|
||||
<h2 id="profile"><i class="fa-solid fa-user-pen"></i> {{ t('settings.profile') }}</h2>
|
||||
|
||||
<!-- Identity & Display Settings -->
|
||||
<fieldset style="border: 1px solid var(--nav-border-color); padding: 12px 16px; border-radius: 6px; margin-bottom: 20px; background: rgba(0,0,0,0.06);">
|
||||
<legend style="width: auto; padding: 0 8px; font-size: 1.05em; font-weight: bold;"><i class="fa-solid fa-signature"></i> {{ t('settings.display_name') }}</legend>
|
||||
<div class="setting-item">
|
||||
<div style="display: flex; align-items: center; gap: 10px; flex-wrap: wrap;">
|
||||
<input type="text" id="display_name_input" class="input"
|
||||
placeholder="{{ t('settings.display_name_placeholder') }}" value="{!! session.display_name || '' !!}"
|
||||
maxlength="32" style="max-width: 240px; height: 32px; font-size: 0.9em;">
|
||||
<button type="button" id="btn-update-display-name" class="button"
|
||||
style="padding: 5px 14px; font-size: 0.85em;">{{ t('settings.save') }}</button>
|
||||
</div>
|
||||
<div id="display-name-status" class="avatar-status"></div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<p class="text-muted" style="margin-bottom: 16px; font-size: 0.9em; display: flex; align-items: center; gap: 8px;">
|
||||
<i class="fa-solid fa-wand-magic-sparkles" style="color: var(--accent);"></i> Click directly on your profile card below to edit your avatar, banner, name, color, or bio.
|
||||
</p>
|
||||
|
||||
<fieldset style="border: 1px solid var(--nav-border-color); padding: 12px 16px; border-radius: 6px; margin-bottom: 20px; background: rgba(0,0,0,0.06);">
|
||||
<legend style="width: auto; padding: 0 8px; font-size: 1.05em; font-weight: bold;"><i class="fa-solid fa-palette"></i> {{ t('settings.username_color') }}</legend>
|
||||
<div class="setting-item">
|
||||
<div style="display: flex; align-items: center; gap: 10px; flex-wrap: wrap;">
|
||||
<input type="color" id="username_color_picker" value="{{ session.username_color || '#ffffff' }}"
|
||||
style="width: 50px; height: 32px; padding: 0; border: 1px solid var(--nav-border-color); cursor: pointer; background: none; border-radius: 4px;">
|
||||
<input type="text" id="username_color_hex" value="{{ session.username_color || '#ffffff' }}" maxlength="7"
|
||||
placeholder="#ffffff" class="input"
|
||||
style="width: 95px; font-family: monospace; font-size: 0.9em; padding: 4px 8px; height: 32px;">
|
||||
<button type="button" id="btn-save-username-color" class="button"
|
||||
style="padding: 5px 14px; font-size: 0.85em;">{{ t('settings.save_color') }}</button>
|
||||
<button type="button" id="btn-reset-username-color" class="button button-secondary"
|
||||
style="padding: 5px 14px; font-size: 0.85em;">{{ t('settings.reset') }}</button>
|
||||
</div>
|
||||
<small class="text-muted" style="display: block; margin-top: 6px;">{{ t('settings.username_color_hint') }}</small>
|
||||
</div>
|
||||
</fieldset>
|
||||
<div class="direct-edit-profile-card-wrapper" style="position: relative; max-width: 750px; margin-bottom: 30px;">
|
||||
|
||||
@if(enable_profile_description)
|
||||
<fieldset style="border: 1px solid var(--nav-border-color); padding: 12px 16px; border-radius: 6px; margin-bottom: 20px; background: rgba(0,0,0,0.06);">
|
||||
<legend style="width: auto; padding: 0 8px; font-size: 1.05em; font-weight: bold;"><i class="fa-solid fa-align-left"></i> {{ t('settings.custom_description') }}</legend>
|
||||
<div class="setting-item">
|
||||
<textarea id="profile_description" class="input" placeholder="{{ t('settings.description_placeholder') }}"
|
||||
maxlength="2000" style="min-height: 80px;">{!! session.description || '' !!}</textarea>
|
||||
<div class="profile-settings-actions" style="margin-top: 10px;">
|
||||
<button type="button" id="btn-save-description" class="button">{{ t('settings.save_description') }}</button>
|
||||
<button type="button" id="btn-clear-description" class="button button-danger">{{ t('settings.clear') }}</button>
|
||||
</div>
|
||||
<div id="description-status" class="avatar-status"></div>
|
||||
</div>
|
||||
</fieldset>
|
||||
@endif
|
||||
<!-- Interactive User Card -->
|
||||
<div class="user-infobox-block editable-profile-card" id="live-profile-preview-box"
|
||||
style="--author-accent: {{ session.username_color || 'var(--accent)' }}; --author-border: {{ session.username_color || 'var(--accent)' }}; @if(banner_file && user_banner_enabled) --author-banner: url('/a/{{ banner_file }}?t={{ Date.now() }}'); --author-banner-position: {{ banner_position === 'center' ? 'center top' : (banner_position || 'center top') }}; --author-banner-size: {{ banner_size || 'cover' }}; @endif">
|
||||
|
||||
<!-- Avatar & Media Uploads -->
|
||||
<fieldset style="border: 1px solid var(--nav-border-color); padding: 12px 16px; border-radius: 6px; margin-bottom: 20px; background: rgba(0,0,0,0.06);">
|
||||
<legend style="width: auto; padding: 0 8px; font-size: 1.05em; font-weight: bold;"><i class="fa-solid fa-user-gear"></i> {{ t('settings.avatar') }}</legend>
|
||||
<div class="avatar-settings-wrapper">
|
||||
<div class="avatar-preview-container">
|
||||
<div class="avatar-preview-label">{{ t('settings.current_avatar') }}</div>
|
||||
<!-- Avatar with Hover Overlay -->
|
||||
<div class="user-infobox-avatar editable-avatar-container" id="avatar-choose-btn" title="Click to change avatar">
|
||||
<a href="#" onclick="event.preventDefault(); document.getElementById('avatar-file-input').click();" style="display:block; position:relative; width:100%; height:100%;">
|
||||
@if(avatar_file)
|
||||
<a href="/user/{!! session.user !!}" target="_blank">
|
||||
<img id="avatar-preview" class="avatar-preview-img" src="/a/{{ avatar_file }}">
|
||||
</a>
|
||||
<img id="live-preview-avatar" class="avatar-preview-img" src="/a/{{ avatar_file }}" />
|
||||
@elseif(session.avatar && session.avatar > 0)
|
||||
<a href="/user/{!! session.user !!}" target="_blank">
|
||||
<img id="avatar-preview" class="avatar-preview-img" src="/t/{{ session.avatar }}.webp">
|
||||
</a>
|
||||
<img id="live-preview-avatar" class="avatar-preview-img" src="/t/{{ session.avatar }}.webp" />
|
||||
@else
|
||||
<div id="avatar-preview" class="avatar-preview-img avatar-placeholder">?</div>
|
||||
<img id="live-preview-avatar" class="avatar-preview-img" src="/a/default.png" style="border-color: #444;" />
|
||||
@endif
|
||||
<div class="avatar-hover-overlay">
|
||||
<i class="fa-solid fa-camera"></i>
|
||||
</div>
|
||||
|
||||
<div class="avatar-upload-section">
|
||||
<p class="avatar-hint">{{ t('settings.avatar_hint') }}</p>
|
||||
|
||||
<div class="avatar-upload-wrapper">
|
||||
<input type="file" id="avatar-file-input" accept="image/gif,image/jpeg,image/png,image/webp" hidden>
|
||||
<button type="button" id="avatar-choose-btn" class="button">{{ t('settings.choose_file') }}</button>
|
||||
<span id="avatar-filename" class="avatar-filename">{{ t('settings.no_file_selected') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="avatar-progress-wrapper" id="avatar-progress-wrapper" style="display: none;">
|
||||
<div class="avatar-progress-bar">
|
||||
<div class="avatar-progress-fill" id="avatar-progress-fill"></div>
|
||||
</div>
|
||||
<span class="avatar-progress-text" id="avatar-progress-text">0%</span>
|
||||
</div>
|
||||
|
||||
<div class="avatar-upload-actions">
|
||||
<button type="button" id="avatar-upload-btn" class="button" disabled>{{ t('settings.upload_btn') }}</button>
|
||||
</a>
|
||||
@if(avatar_file)
|
||||
<button type="button" id="avatar-remove-btn" class="button button-danger">{{ t('settings.remove_custom') }}</button>
|
||||
@endif
|
||||
</div>
|
||||
<div id="avatar-upload-status" class="avatar-status"></div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
@if(user_banner_enabled)
|
||||
<fieldset style="border: 1px solid var(--nav-border-color); padding: 12px 16px; border-radius: 6px; margin-bottom: 20px; background: rgba(0,0,0,0.06);">
|
||||
<legend style="width: auto; padding: 0 8px; font-size: 1.05em; font-weight: bold;"><i class="fa-solid fa-image"></i> Profile Banner</legend>
|
||||
<div class="avatar-settings-wrapper">
|
||||
<div class="avatar-preview-container" style="width: 360px; max-width: 100%;">
|
||||
<div class="avatar-preview-label">{{ t('settings.current_banner') }}</div>
|
||||
@if(banner_file)
|
||||
<a href="/user/{!! session.user !!}" target="_blank" style="display:block; width: 100%;">
|
||||
<div id="banner-preview" class="banner-preview-img" style="width:100%;aspect-ratio:400/140;border-radius:4px;border:1px solid var(--nav-border-color);background-image:url('/a/{{ banner_file }}');background-size:{{ banner_size || 'cover' }};background-position:{{ banner_position === 'center' ? 'center top' : (banner_position || 'center top') }};background-repeat:no-repeat;"></div>
|
||||
</a>
|
||||
@else
|
||||
<div id="banner-preview" class="banner-preview-img banner-placeholder" style="width:100%;aspect-ratio:400/140;display:flex;align-items:center;justify-content:center;border:1px dashed var(--nav-border-color);border-radius:4px;color:var(--text-muted);font-size:0.85em;">{{ t('settings.no_banner_set') }}</div>
|
||||
<button type="button" class="avatar-quick-remove" id="avatar-remove-btn" title="Remove custom avatar">
|
||||
<i class="fa-solid fa-xmark"></i>
|
||||
</button>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="avatar-upload-section">
|
||||
<p class="avatar-hint">{{ t('settings.banner_hint') }}</p>
|
||||
<div class="avatar-upload-wrapper">
|
||||
<input type="file" id="banner-file-input" accept="image/gif,image/jpeg,image/png,image/webp" hidden>
|
||||
<button type="button" id="banner-choose-btn" class="button">{{ t('settings.choose_file') }}</button>
|
||||
<span id="banner-filename" class="avatar-filename">{{ t('settings.no_file_selected') }}</span>
|
||||
</div>
|
||||
|
||||
<div class="avatar-progress-wrapper" id="banner-progress-wrapper" style="display: none;">
|
||||
<div class="avatar-progress-bar">
|
||||
<div class="avatar-progress-fill" id="banner-progress-fill"></div>
|
||||
</div>
|
||||
<span class="avatar-progress-text" id="banner-progress-text">0%</span>
|
||||
</div>
|
||||
|
||||
<div class="avatar-upload-actions">
|
||||
<button type="button" id="banner-upload-btn" class="button" disabled>Upload Banner</button>
|
||||
@if(banner_file)
|
||||
<button type="button" id="banner-edit-btn" class="button">Edit Position</button>
|
||||
<button type="button" id="banner-remove-btn" class="button button-danger">Remove Banner</button>
|
||||
@endif
|
||||
</div>
|
||||
<div id="banner-upload-status" class="avatar-status"></div>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
@endif
|
||||
|
||||
<!-- Live Profile Preview -->
|
||||
<fieldset style="border: 1px solid var(--nav-border-color); padding: 12px 16px; border-radius: 6px; margin-bottom: 25px; background: rgba(0,0,0,0.06);">
|
||||
<legend style="width: auto; padding: 0 8px; font-size: 1.05em; font-weight: bold;"><i class="fa-solid fa-eye"></i> Live Profile Preview</legend>
|
||||
<div class="setting-item" style="max-width: 750px;">
|
||||
<div class="user-infobox-block" id="live-profile-preview-box" style="--author-accent: {{ session.username_color || 'var(--accent)' }}; --author-border: {{ session.username_color || 'var(--accent)' }}; @if(banner_file && user_banner_enabled) --author-banner: url('/a/{{ banner_file }}?t={{ Date.now() }}'); --author-banner-position: {{ banner_position === 'center' ? 'center top' : (banner_position || 'center top') }}; --author-banner-size: {{ banner_size || 'cover' }}; @endif">
|
||||
<div class="user-infobox-avatar">
|
||||
<a href="#">
|
||||
@if(avatar_file)
|
||||
<img id="live-preview-avatar" src="/a/{{ avatar_file }}" />
|
||||
@else
|
||||
<img id="live-preview-avatar" src="/a/default.png" style="border-color: #444;" />
|
||||
@endif
|
||||
</a>
|
||||
</div>
|
||||
<div class="user-infobox-info">
|
||||
<div class="user-infobox-header">
|
||||
<div class="user-infobox-username-container">
|
||||
<a id="live-preview-username" href="#" class="user-infobox-username">{!! session.display_name || session.user !!}</a>
|
||||
<div class="user-infobox-username-container" style="display: flex; align-items: center; gap: 8px; flex-wrap: wrap;">
|
||||
|
||||
<!-- Editable Display Name -->
|
||||
<div class="inline-edit-username-wrapper">
|
||||
<span id="live-preview-username" class="user-infobox-username" contenteditable="true" spellcheck="false" title="Click to edit display name">{!! session.display_name || session.user !!}</span>
|
||||
<i class="fa-solid fa-pen" style="font-size: 0.65em; opacity: 0.5; margin-left: 2px;" title="Editable"></i>
|
||||
</div>
|
||||
|
||||
<!-- Color Picker Badge -->
|
||||
<div class="inline-color-picker-wrapper" style="display: inline-flex; align-items: center;">
|
||||
<label for="username_color_picker" class="color-picker-badge" id="color-picker-badge" style="background: {{ session.username_color || 'var(--accent)' }};" title="Click to change username color">
|
||||
<i class="fa-solid fa-palette"></i>
|
||||
</label>
|
||||
<input type="color" id="username_color_picker" value="{{ session.username_color || '#ffffff' }}" style="position: absolute; opacity: 0; width: 0; height: 0; pointer-events: none;">
|
||||
<input type="text" id="username_color_hex" value="{{ session.username_color || '#ffffff' }}" style="display: none;">
|
||||
</div>
|
||||
|
||||
<!-- Hidden Backing Save Buttons for JS event trigger -->
|
||||
<button type="button" id="btn-update-display-name" class="inline-save-btn" style="display: none;"><i class="fa-solid fa-check"></i> Save Name</button>
|
||||
<button type="button" id="btn-save-username-color" style="display: none;">Save Color</button>
|
||||
<button type="button" id="btn-reset-username-color" style="display: none;">Reset</button>
|
||||
|
||||
</div>
|
||||
<span class="user-infobox-timestamp"><a href="#" class="timestamp-link"><time>just now</time></a></span>
|
||||
</div>
|
||||
|
||||
<div class="user-infobox-body">
|
||||
<div class="user-infobox-description">
|
||||
{!! session.description || 'Welcome to my profile! This is a live preview.' !!}
|
||||
|
||||
<!-- Editable Description -->
|
||||
<div class="inline-edit-description-wrapper">
|
||||
<div class="user-infobox-description" id="live-preview-description" contenteditable="true" spellcheck="false" title="Click to edit description" data-placeholder="Click to write a bio...">
|
||||
{!! session.description || '' !!}
|
||||
</div>
|
||||
<div class="description-edit-controls" id="desc-edit-controls" style="display: flex; margin-top: 10px; gap: 8px; align-items: center; flex-wrap: wrap;">
|
||||
<button type="button" id="btn-save-description" class="button button-sm" style="padding: 4px 10px; font-size: 0.8em;"><i class="fa-solid fa-floppy-disk"></i> {{ t('settings.save_description') }}</button>
|
||||
<button type="button" id="btn-clear-description" class="button button-danger button-sm" style="padding: 4px 10px; font-size: 0.8em;"><i class="fa-solid fa-trash"></i> {{ t('settings.clear') }}</button>
|
||||
@if(user_banner_enabled)
|
||||
<button type="button" id="banner-choose-btn" class="button button-sm" style="padding: 4px 10px; font-size: 0.8em;"><i class="fa-solid fa-camera"></i> Change Banner</button>
|
||||
@if(banner_file)
|
||||
<button type="button" id="banner-edit-btn" class="button button-sm" style="padding: 4px 10px; font-size: 0.8em;"><i class="fa-solid fa-arrows-up-down-left-right"></i> Reposition</button>
|
||||
<button type="button" id="banner-remove-btn" class="button button-danger button-sm" style="padding: 4px 10px; font-size: 0.8em;"><i class="fa-solid fa-trash"></i> Remove Banner</button>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="user-infobox-actions">
|
||||
<i class="iconset fa-solid fa-heart" title="Favorite"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Hidden Backing Elements for JavaScript compatibility -->
|
||||
<input type="file" id="avatar-file-input" accept="image/gif,image/jpeg,image/png,image/webp" style="display: none;">
|
||||
<span id="avatar-filename" style="display: none;"></span>
|
||||
<button type="button" id="avatar-upload-btn" style="display: none;"></button>
|
||||
<div id="avatar-progress-wrapper" style="display: none;">
|
||||
<div id="avatar-progress-fill"></div>
|
||||
<span id="avatar-progress-text"></span>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<input type="file" id="banner-file-input" accept="image/gif,image/jpeg,image/png,image/webp" style="display: none;">
|
||||
<span id="banner-filename" style="display: none;"></span>
|
||||
<button type="button" id="banner-upload-btn" style="display: none;"></button>
|
||||
<div id="banner-progress-wrapper" style="display: none;">
|
||||
<div id="banner-progress-fill"></div>
|
||||
<span id="banner-progress-text"></span>
|
||||
</div>
|
||||
|
||||
<input type="text" id="display_name_input" value="{!! session.display_name || '' !!}" style="display: none;">
|
||||
@if(enable_profile_description)
|
||||
<textarea id="profile_description" style="display: none;">{!! session.description || '' !!}</textarea>
|
||||
@endif
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<!-- ═══════════════════════════════ PREFERENCES ═══════════════════════════════ -->
|
||||
<h2 id="preferences"><i class="fa-solid fa-sliders"></i> {{ t('settings.preferences') }}</h2>
|
||||
|
||||
Reference in New Issue
Block a user