haufen sachen
This commit is contained in:
1 parent
416ca9e854
commit
e6243701a3
20 files changed
+1562
-116
No files matched your search
+91
-15
@@ -1,25 +1,101 @@
|
||||
// ── Theme picker ──
|
||||
// ── Theme + Settings ──
|
||||
|
||||
import { $ } from './util.js';
|
||||
import { $, api, getCsrf } from './util.js';
|
||||
import { state } from './state.js';
|
||||
import { renderSettingsPanel as renderNotifSettings } from './notifications.js';
|
||||
|
||||
const picker = $('theme-picker');
|
||||
const list = $('theme-list');
|
||||
const overlay = $('settings-overlay');
|
||||
const themeList = $('settings-theme-list');
|
||||
|
||||
if (list) {
|
||||
// Render theme list in settings
|
||||
function renderThemes() {
|
||||
if (!themeList) return;
|
||||
const current = localStorage.getItem('hyprcrd-theme') || 'slate';
|
||||
themeList.innerHTML = '';
|
||||
for (const [key, t] of Object.entries(window.themes)) {
|
||||
const btn = document.createElement('button');
|
||||
btn.className = 'flex items-center gap-2.5 w-full px-2 py-1.5 text-left text-xs text-t-muted hover:text-t-bright transition-colors rounded';
|
||||
btn.dataset.themeDot = key;
|
||||
btn.innerHTML = `<span class="w-3 h-3 rounded-full shrink-0 border border-t-border" style="background:${t.vars['--t-accent']}"></span>
|
||||
<span class="font-pixel text-[10px]">${t.label}</span>`;
|
||||
btn.onclick = () => { window.applyTheme(key); window._renderBoard?.(); };
|
||||
list.appendChild(btn);
|
||||
const active = key === current;
|
||||
btn.className = `flex items-center gap-3 px-3 py-2.5 text-left text-xs border transition-colors rounded ${active ? 'border-t-accent text-t-bright' : 'border-t-border text-t-muted hover:border-t-accent hover:text-t-bright'}`;
|
||||
btn.innerHTML = `<span class="w-4 h-4 rounded-full shrink-0" style="background:${t.vars['--t-accent']}"></span>
|
||||
<span class="font-pixel text-[10px] flex-1">${t.label}</span>
|
||||
${active ? '<i class="ph ph-check text-t-accent text-sm"></i>' : ''}`;
|
||||
btn.onclick = () => { window.applyTheme(key); renderThemes(); window._renderBoard?.(); };
|
||||
themeList.appendChild(btn);
|
||||
}
|
||||
}
|
||||
|
||||
window.applyTheme(localStorage.getItem('hyprcrd-theme') || 'slate');
|
||||
// Tab switching
|
||||
overlay?.querySelectorAll('.settings-tab').forEach(tab => {
|
||||
tab.addEventListener('click', () => {
|
||||
overlay.querySelectorAll('.settings-tab').forEach(t => t.classList.remove('active'));
|
||||
tab.classList.add('active');
|
||||
const panel = tab.dataset.tab;
|
||||
overlay.querySelectorAll('[id^="settings-panel-"]').forEach(p => p.classList.add('hidden'));
|
||||
$(`settings-panel-${panel}`)?.classList.remove('hidden');
|
||||
if (panel === 'sync') window._loadCaldavSettings?.();
|
||||
if (panel === 'notifications') renderNotifSettings();
|
||||
if (panel === 'behavior') initBehaviorSettings();
|
||||
});
|
||||
});
|
||||
|
||||
if (picker) {
|
||||
$('theme-toggle')?.addEventListener('click', () => picker.classList.toggle('open'));
|
||||
document.addEventListener('click', e => { if (!picker.contains(e.target)) picker.classList.remove('open'); });
|
||||
// Open/Close
|
||||
function updateStats() {
|
||||
const sc = $('stats-cards'); if (sc) sc.textContent = state.cards?.length || 0;
|
||||
const sb = $('stats-buckets'); if (sb) sb.textContent = state.buckets?.length || 0;
|
||||
const tags = new Set(); (state.cards || []).forEach(c => (c.tags || '').split(',').forEach(t => { if (t) tags.add(t); }));
|
||||
const st = $('stats-tags'); if (st) st.textContent = tags.size;
|
||||
}
|
||||
|
||||
$('settings-btn')?.addEventListener('click', () => {
|
||||
renderThemes();
|
||||
updateStats();
|
||||
overlay?.classList.add('open');
|
||||
});
|
||||
$('settings-close')?.addEventListener('click', () => overlay?.classList.remove('open'));
|
||||
overlay?.addEventListener('click', e => { if (e.target === overlay) overlay?.classList.remove('open'); });
|
||||
|
||||
// Password change
|
||||
$('settings-pw-save')?.addEventListener('click', async () => {
|
||||
const current = $('settings-pw-current')?.value;
|
||||
const newPw = $('settings-pw-new')?.value;
|
||||
const confirm = $('settings-pw-confirm')?.value;
|
||||
const status = $('settings-pw-status');
|
||||
|
||||
if (!current || !newPw) { if (status) { status.textContent = 'fill all fields'; status.style.color = 'var(--t-danger)'; } return; }
|
||||
if (newPw !== confirm) { if (status) { status.textContent = 'passwords do not match'; status.style.color = 'var(--t-danger)'; } return; }
|
||||
if (newPw.length < 4) { if (status) { status.textContent = 'min 4 characters'; status.style.color = 'var(--t-danger)'; } return; }
|
||||
|
||||
const res = await fetch('api/auth/password', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': getCsrf() },
|
||||
body: JSON.stringify({ current, new: newPw }),
|
||||
}).then(r => r.json()).catch(() => ({ error: 'network error' }));
|
||||
|
||||
if (res.ok) {
|
||||
if (status) { status.textContent = res.rekey ? 'password changed — re-encrypting notes...' : 'password changed'; status.style.color = 'var(--t-accent)'; }
|
||||
$('settings-pw-current').value = '';
|
||||
$('settings-pw-new').value = '';
|
||||
$('settings-pw-confirm').value = '';
|
||||
// Trigger sync to re-push notes with new encryption key
|
||||
if (res.rekey) {
|
||||
window._triggerSync?.();
|
||||
setTimeout(() => { if (status) status.textContent = 'password changed, notes re-encrypted'; }, 3000);
|
||||
}
|
||||
} else {
|
||||
if (status) { status.textContent = res.error || 'failed'; status.style.color = 'var(--t-danger)'; }
|
||||
}
|
||||
});
|
||||
|
||||
function initBehaviorSettings() {
|
||||
const sel = $('setting-current-days');
|
||||
if (sel) {
|
||||
sel.value = localStorage.getItem('hyprcrd-current-days') || '2';
|
||||
sel.onchange = () => {
|
||||
localStorage.setItem('hyprcrd-current-days', sel.value);
|
||||
window._renderBoard?.();
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Apply saved theme on load
|
||||
window.applyTheme(localStorage.getItem('hyprcrd-theme') || 'slate');
|
||||
Reference in new issue
Block a user