This commit is contained in:
th committed 2026-04-08 23:05:41 +02:00
1 parent e6243701a3
commit cd9dc3e5bc
6 files changed
+142 -31

No files matched your search

+15 -7
View File
@@ -317,8 +317,9 @@ $('sort-toggle')?.addEventListener('click', () => {
export function renderCardHtml(c, inGroup = false, recent = []) {
const loaded = c.body != null;
const coverImg = loaded ? leadingImage(c.body) : null;
const thumbImg = coverImg ? null : (loaded ? firstImage(c.body) : null);
const showThumbs = localStorage.getItem('hyprcrd-show-thumbnails') !== '0';
const coverImg = loaded && showThumbs ? leadingImage(c.body) : null;
const thumbImg = coverImg ? null : (loaded && showThumbs ? firstImage(c.body) : null);
const children = getChildren(c.id);
const isGroup = !inGroup && children.length > 0;
const todos = loaded ? getTodos(c.body) : null;
@@ -337,7 +338,7 @@ export function renderCardHtml(c, inGroup = false, recent = []) {
<div class="board-card ${isGroup ? 'card-group ' : ''}card-glow ${hasCover ? 'card-has-cover' : 'bg-t-surface'} border border-t-border cursor-pointer hover:border-t-muted transition-colors relative group"
style="--glow-color:${cardColor}22;${hasCover ? `background-image:url('${coverImg}')` : ''};${overdue ? 'border-bottom:3px solid var(--t-danger)' : recent.includes(String(c.id)) ? 'border-bottom:3px solid ' + cardColor : ''}" draggable="true" data-id="${c.id}">
${hasCover ? '<div class="card-cover-overlay"></div>' : ''}
${tags.includes('done') ? '<div class="card-done-badge"><i class="ph ph-check"></i></div>' : ''}
${tags.includes('done') && localStorage.getItem('hyprcrd-show-done-badge') !== '0' ? '<div class="card-done-badge"><i class="ph ph-check"></i></div>' : ''}
<div class="card-bar w-full card-layer ${overdue ? 'card-bar-pulse' : ''}" style="background:${barColor}"></div>
${isGroup ? `<div class="card-group-badge cursor-pointer hover:scale-110 transition-transform" style="background:${cardColor};color:#000" data-group="${c.id}">${children.length + 1}</div>` : ''}
${thumbImg ? `<div class="card-thumb" style="background-image:url('${thumbImg}')"></div>` : ''}
@@ -352,9 +353,9 @@ export function renderCardHtml(c, inGroup = false, recent = []) {
<div class="todo-progress">${Array.from({length: todos.total}, (_, i) => `<div class="todo-seg" style="background:${i < todos.done ? cardColor : 'var(--t-border)'}"></div>`).join('')}</div>
</div>` : ''}
${loaded
? `<p class="text-xs ${hasCover ? 'text-t-text' : 'text-t-muted'} leading-relaxed line-clamp-5 flex-1">${esc(stripMd(c.body))}</p>`
? (localStorage.getItem('hyprcrd-body-lines') === '0' ? '' : `<p class="text-xs ${hasCover ? 'text-t-text' : 'text-t-muted'} leading-relaxed flex-1" style="-webkit-line-clamp:var(--card-body-lines,5);display:-webkit-box;-webkit-box-orient:vertical;overflow:hidden;">${esc(stripMd(c.body))}</p>`)
: `<div class="flex-1 flex items-center justify-center py-2"><i class="ph ph-spinner card-spinner text-t-dim text-lg"></i></div>`}
${tags.length ? `<div class="flex flex-wrap gap-1 mt-1.5 card-layer">${tags.slice(0, 5).map(t => tagChipHtml(t)).join('')}${tags.length > 5 ? `<span class="tag-chip tag-chip-more">+${tags.length - 5}</span>` : ''}</div>` : ''}
${tags.length && localStorage.getItem('hyprcrd-show-tags') !== '0' ? `<div class="flex flex-wrap gap-1 mt-1.5 card-layer">${tags.slice(0, 5).map(t => tagChipHtml(t)).join('')}${tags.length > 5 ? `<span class="tag-chip tag-chip-more">+${tags.length - 5}</span>` : ''}</div>` : ''}
<div class="mt-auto pt-2 flex items-center gap-2 text-[10px] ${hasCover ? 'text-t-text' : 'text-t-dim'} font-pixel">
${c.due_date ? `<span class="due-pill" style="background:${overdue ? 'var(--t-danger)' : cardColor};"><i class="ph ph-clock-countdown" style="font-size:9px;"></i>${c.due_date}</span>` : `<span class="flex items-center gap-1"><i class="ph ph-clock text-xs"></i>${(c.updated_at || c.created_at || '').substring(0, 10)}</span>`}
${c.bucket_name ? `<span class="flex items-center gap-1"><i class="ph ph-folder text-xs"></i>${esc(c.bucket_name)}</span>` : ''}
@@ -384,8 +385,11 @@ export function renderBoard() {
if (recent.includes(String(c.id))) return true;
// Recently edited locally (not just synced — check synced_at vs updated_at)
const updated = new Date(c.updated_at || c.created_at || 0).getTime();
const synced = c.caldav_synced_at ? new Date(c.caldav_synced_at).getTime() : 0;
if (synced && Math.abs(updated - synced) < 3000) return false; // sync-only update
const includeSynced = localStorage.getItem('hyprcrd-current-include-synced') === '1';
if (!includeSynced) {
const synced = c.caldav_synced_at ? new Date(c.caldav_synced_at).getTime() : 0;
if (synced && Math.abs(updated - synced) < 3000) return false;
}
return (now - updated) < freshMs;
});
cards.sort((a, b) => (b.updated_at || b.created_at || '').localeCompare(a.updated_at || a.created_at || ''));
@@ -814,6 +818,10 @@ function bindCardEvents() {
clickTimer = setTimeout(() => {
clickTimer = null;
if (boardSplitOpen) { showBoardPreview(id); }
else if (localStorage.getItem('hyprcrd-click-action') === 'edit') {
const card = state.cards.find(c => c.id == id);
if (card) window._openModal(card);
}
else { window._openDetail(id); }
}, 200);
});
+1 -3
View File
@@ -147,10 +147,8 @@ function openOrphanLightbox(file) {
overlay.querySelector('.orphan-lb-create').addEventListener('click', async () => {
const name = file.url.split('/').pop().replace(/\.[^.]+$/, '');
await api('api/cards', { method: 'POST', body: { title: name, body: `![${name}](${file.url})`, color: '#38bdf8', position: -1 } });
await window._reloadAll();
close();
openGallery();
window._openModal({ id: null, title: name, body: `![${name}](${file.url})`, color: '#38bdf8', bucket_id: null });
});
overlay.querySelector('.orphan-lb-delete').addEventListener('click', async () => {
+49 -7
View File
@@ -87,15 +87,57 @@ $('settings-pw-save')?.addEventListener('click', async () => {
});
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?.();
};
const selects = {
'setting-current-days': { key: 'hyprcrd-current-days', def: '2' },
'setting-card-height': { key: 'hyprcrd-card-height', def: '180' },
'setting-card-width': { key: 'hyprcrd-card-width', def: '280' },
'setting-body-lines': { key: 'hyprcrd-body-lines', def: '5' },
'setting-click-action': { key: 'hyprcrd-click-action', def: 'preview' },
};
const toggles = {
'setting-current-include-synced': { key: 'hyprcrd-current-include-synced', def: '0' },
'setting-show-tags': { key: 'hyprcrd-show-tags', def: '1' },
'setting-show-thumbnails': { key: 'hyprcrd-show-thumbnails', def: '1' },
'setting-show-done-badge': { key: 'hyprcrd-show-done-badge', def: '1' },
'setting-confirm-delete': { key: 'hyprcrd-confirm-delete', def: '1' },
'setting-auto-save': { key: 'hyprcrd-auto-save', def: '0' },
};
for (const [id, cfg] of Object.entries(selects)) {
const el = $(id);
if (!el) continue;
el.value = localStorage.getItem(cfg.key) || cfg.def;
el.onchange = () => { localStorage.setItem(cfg.key, el.value); applyBehavior(); };
}
for (const [id, cfg] of Object.entries(toggles)) {
const el = $(id);
if (!el) continue;
const isOn = (localStorage.getItem(cfg.key) ?? cfg.def) === '1';
el.classList.toggle('on', isOn);
const row = el.closest('.toggle-row');
if (row) {
row.onclick = () => {
const nowOn = !el.classList.contains('on');
el.classList.toggle('on', nowOn);
localStorage.setItem(cfg.key, nowOn ? '1' : '0');
applyBehavior();
};
}
}
}
function applyBehavior() {
const board = $('board');
if (board) {
const w = localStorage.getItem('hyprcrd-card-width') || '280';
board.style.gridTemplateColumns = `repeat(auto-fill, minmax(${w}px, 1fr))`;
}
document.documentElement.style.setProperty('--card-min-h', (localStorage.getItem('hyprcrd-card-height') || '180') + 'px');
document.documentElement.style.setProperty('--card-body-lines', localStorage.getItem('hyprcrd-body-lines') || '5');
window._renderBoard?.();
}
// Apply on load
applyBehavior();
// Apply saved theme on load
window.applyTheme(localStorage.getItem('hyprcrd-theme') || 'slate');