kingkont 0.17.4 → 0.17.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/renderer/board.js +15 -0
- package/renderer/notifyPanel.js +21 -3
package/package.json
CHANGED
package/renderer/board.js
CHANGED
|
@@ -454,7 +454,22 @@ function fmtRelativeTime(ts) {
|
|
|
454
454
|
return new Date(ts).toLocaleDateString();
|
|
455
455
|
}
|
|
456
456
|
|
|
457
|
+
// Дедуп: на Cmd+R / WS-event burst несколько вызовов могли race'иться
|
|
458
|
+
// (clear grid → await getRecents → append → второй call в это же время →
|
|
459
|
+
// дубли карточек / наезжают). Если уже рендерим — отметим что нужен
|
|
460
|
+
// follow-up render и выйдем; запустим его после текущего.
|
|
461
|
+
let _wrInFlight = false;
|
|
462
|
+
let _wrPending = false;
|
|
457
463
|
async function renderWelcomeRecents() {
|
|
464
|
+
if (_wrInFlight) { _wrPending = true; return; }
|
|
465
|
+
_wrInFlight = true;
|
|
466
|
+
try { await _renderWelcomeRecentsInner(); }
|
|
467
|
+
finally {
|
|
468
|
+
_wrInFlight = false;
|
|
469
|
+
if (_wrPending) { _wrPending = false; renderWelcomeRecents().catch(() => {}); }
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
async function _renderWelcomeRecentsInner() {
|
|
458
473
|
const grid = $('welcomeRecentGrid');
|
|
459
474
|
const wrap = $('welcomeRecent');
|
|
460
475
|
const titleEl = $('welcomeRecentTitle');
|
package/renderer/notifyPanel.js
CHANGED
|
@@ -89,18 +89,36 @@
|
|
|
89
89
|
const dt = new Date(e.ts);
|
|
90
90
|
const time = `${String(dt.getHours()).padStart(2,'0')}:${String(dt.getMinutes()).padStart(2,'0')}:${String(dt.getSeconds()).padStart(2,'0')}`;
|
|
91
91
|
const clickable = !!e.target;
|
|
92
|
-
row.style.cssText = `padding:8px 10px; border-radius:4px; margin-bottom:4px; background:${c}22; border-left:3px solid ${c}; cursor:${clickable ? 'pointer' : 'default'}; transition:background 0.1s;`;
|
|
92
|
+
row.style.cssText = `position:relative; padding:8px 10px 8px 10px; border-radius:4px; margin-bottom:4px; background:${c}22; border-left:3px solid ${c}; cursor:${clickable ? 'pointer' : 'default'}; transition:background 0.1s;`;
|
|
93
93
|
if (clickable) row.title = 'Перейти к объекту';
|
|
94
94
|
const targetHint = clickable ? `<span style="color:#9ab; font-size:10px; margin-left:6px;">↗</span>` : '';
|
|
95
|
-
row.innerHTML = `<div style="display:flex; justify-content:space-between; gap:8px; align-items:flex-start;">
|
|
95
|
+
row.innerHTML = `<div style="display:flex; justify-content:space-between; gap:8px; align-items:flex-start; padding-right:18px;">
|
|
96
96
|
<div style="color:#e0e0e0; font-size:12px; line-height:1.4; word-break:break-word; flex:1;"></div>
|
|
97
97
|
<span style="color:#777; font-size:10px; font-family:ui-monospace,monospace; flex-shrink:0;">${time}${targetHint}</span>
|
|
98
98
|
</div>`;
|
|
99
99
|
row.querySelector('div > div').textContent = e.text;
|
|
100
|
+
// Кнопка × для удаления конкретного event'a (не блокирует клик по row).
|
|
101
|
+
const delBtn = document.createElement('button');
|
|
102
|
+
delBtn.textContent = '×';
|
|
103
|
+
delBtn.title = 'Удалить';
|
|
104
|
+
delBtn.style.cssText = 'position:absolute; top:2px; right:4px; background:transparent; border:none; color:#888; cursor:pointer; font-size:14px; line-height:1; padding:2px 6px; opacity:0.5; transition:opacity 0.1s;';
|
|
105
|
+
delBtn.addEventListener('mouseenter', () => delBtn.style.opacity = '1');
|
|
106
|
+
delBtn.addEventListener('mouseleave', () => delBtn.style.opacity = '0.5');
|
|
107
|
+
delBtn.addEventListener('click', (ev) => {
|
|
108
|
+
ev.stopPropagation();
|
|
109
|
+
// Find by ts (events shifted by render, индекс i может измениться к click'у).
|
|
110
|
+
const idx = events.findIndex(x => x.ts === e.ts && x.text === e.text);
|
|
111
|
+
if (idx >= 0) events.splice(idx, 1);
|
|
112
|
+
render();
|
|
113
|
+
});
|
|
114
|
+
row.appendChild(delBtn);
|
|
100
115
|
if (clickable) {
|
|
101
116
|
row.addEventListener('mouseenter', () => row.style.background = `${c}44`);
|
|
102
117
|
row.addEventListener('mouseleave', () => row.style.background = `${c}22`);
|
|
103
|
-
row.addEventListener('click', () =>
|
|
118
|
+
row.addEventListener('click', (ev) => {
|
|
119
|
+
if (ev.target === delBtn) return;
|
|
120
|
+
navigateToTarget(e.target);
|
|
121
|
+
});
|
|
104
122
|
}
|
|
105
123
|
list.appendChild(row);
|
|
106
124
|
}
|