diff --git a/public/s/css/f0ckm.css b/public/s/css/f0ckm.css index c3e6e8f..13c75d7 100644 --- a/public/s/css/f0ckm.css +++ b/public/s/css/f0ckm.css @@ -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; +} + diff --git a/public/s/js/settings.js b/public/s/js/settings.js index df57235..f8fac07 100644 --- a/public/s/js/settings.js +++ b/public/s/js/settings.js @@ -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'; } }); diff --git a/views/settings.html b/views/settings.html index 04fbcc1..f05a89f 100644 --- a/views/settings.html +++ b/views/settings.html @@ -77,176 +77,118 @@
+ Click directly on your profile card below to edit your avatar, banner, name, color, or bio. +
- - - @if(enable_profile_description) - - @endif - - -