fix(web-clipper): bouton rond transparent draggable + toggle affichage + refresh auto sidebar + fix bloc bookmark (v6.2.1)
FlowDeck CI / lint (push) Successful in 1m14s
FlowDeck CI / test (push) Failing after 8m44s
FlowDeck CI / docker (push) Skipped

- bouton flottant rond (44px), semi-transparent blur, hover plus fonce, deplacable souris (pos persistee storage)
- option afficher/cacher dans popup extension (showButton)
- clipper: notification instantanee des onglets FlowDeck via tabs.sendMessage + polling 15s + BroadcastChannel + visibilitychange
- fix bookmark template literal '+title+' -> \/\/\/\/\ (_page_editor_scripts.html)
- sync static/extension + zip
This commit is contained in:
2026-09-20 11:02:49 -04:00
parent 7f998faf7b
commit ea19d1d050
14 changed files with 520 additions and 38 deletions
+3 -2
View File
@@ -548,10 +548,11 @@ window.__fdEditorScriptsLoaded = true;
}
if(b.type==='bookmark'){
var url=b.url||b.src||'';var title=esc(b.title||url);var desc=esc(b.description||'');var img=b.image||'';var site=esc(b.site_name||'');
var imgHtml=img?'<img src="'+img+'" alt="" style="width:120px;height:90px;object-fit:cover;border-radius:8px;flex-shrink:0;">':'';
var imgHtml=img?'<img src="'+img.replace(/"/g,'&quot;')+'" alt="" style="width:120px;height:90px;object-fit:cover;border-radius:8px;flex-shrink:0;">':'';
var descHtml=desc?'<div style="font-size:13px;color:var(--text-dim);margin-top:4px;">'+desc+'</div>':'';
var siteHtml=site?'<div style="font-size:11px;color:var(--text-tertiary);text-transform:uppercase;letter-spacing:.5px;margin-top:6px;">'+site+'</div>':'';
return url?`<div class="block-wrapper" data-id="${b.id}"><div class="block-content block-bookmark"><a href="'+url+'" target="_blank" rel="noopener noreferrer" style="text-decoration:none;color:inherit;"><div style="display:flex;gap:14px;align-items:center;border:1px solid var(--border);border-radius:10px;padding:14px 16px;margin:0;background:var(--bg-secondary);"><div style="flex:1;min-width:0;"><div style="font-weight:600;font-size:15px;">'+title+'</div>'+descHtml+siteHtml+'</div>'+imgHtml+'</div></a></div></div>`:`<div class="block-wrapper" data-id="${b.id}"><div class="block-content block-bookmark" style="text-align:center;padding:60px 20px;background:var(--bg-secondary);border:1px dashed var(--border);border-radius:8px;cursor:pointer;" onclick="E.setBookmarkUrl('${b.id}')"><div style="font-size:48px;margin-bottom:12px;">🔖</div><div style="font-size:14px;color:var(--text-dim);">Click to add bookmark URL</div></div></div>`;
var safeUrl=url.replace(/"/g,'&quot;');
return url?`<div class="block-wrapper" data-id="${b.id}"><div class="block-content block-bookmark"><a href="${safeUrl}" target="_blank" rel="noopener noreferrer" style="text-decoration:none;color:inherit;"><div style="display:flex;gap:14px;align-items:center;border:1px solid var(--border);border-radius:10px;padding:14px 16px;margin:0;background:var(--bg-secondary);"><div style="flex:1;min-width:0;"><div style="font-weight:600;font-size:15px;">${title}</div>${descHtml}${siteHtml}</div>${imgHtml}</div></a></div></div>`:`<div class="block-wrapper" data-id="${b.id}"><div class="block-content block-bookmark" style="text-align:center;padding:60px 20px;background:var(--bg-secondary);border:1px dashed var(--border);border-radius:8px;cursor:pointer;" onclick="E.setBookmarkUrl('${b.id}')"><div style="font-size:48px;margin-bottom:12px;">🔖</div><div style="font-size:14px;color:var(--text-dim);">Click to add bookmark URL</div></div></div>`;
}
if(b.type==='embed'){
if(b.embed_type==='inline_dbs')return `<div class="block-wrapper" data-id="${b.id}"><div class="block-content block-inline-dbs"><div style="padding:20px;text-align:center;color:var(--text-secondary);">📊 Inline Databases</div><div class="inline-dbs-grid">${(b.dbs||[]).map(db=>`<a href="/db/${db.id}/view/${db.view_type||'table'}" class="inline-db-card" target="_blank" style="display:block;padding:12px 16px;background:var(--bg-secondary);border-radius:8px;margin:8px 0;text-decoration:none;color:var(--text-primary);border:1px solid var(--border);"><span style="font-weight:500">📋 ${db.name}</span><span style="float:right;font-size:12px;color:var(--text-tertiary);">${db.view_type==='form'?'📝 Form':'📊 Table'} →</span></a>`).join('')}</div></div></div>`;
+41
View File
@@ -1100,6 +1100,47 @@
this.loadAgents();
this.initSidebarWidth();
document.addEventListener('fd-toggle-sidebar', () => this.toggleSidebar());
this.startClipAutoRefresh();
},
// ── Auto-refresh sidebar after a web clip (no manual reload) ──
_clipRefreshTimer: null,
_clipRefreshInterval: null,
startClipAutoRefresh() {
const self = this;
// Instant refresh when extension notifies (content script forwards event)
window.addEventListener('flowdeck:clip-created', () => {
clearTimeout(self._clipRefreshTimer);
self._clipRefreshTimer = setTimeout(() => self.refreshSidebarTree(), 400);
});
document.addEventListener('flowdeck:workspace-changed', () => {
clearTimeout(self._clipRefreshTimer);
self._clipRefreshTimer = setTimeout(() => self.refreshSidebarTree(), 400);
});
// Also refresh when tab becomes visible (user returns to FlowDeck after clipping)
document.addEventListener('visibilitychange', () => {
if (!document.hidden) self.refreshSidebarTree();
});
window.addEventListener('focus', () => self.refreshSidebarTree());
// Polling fallback every 15s while tab is visible (covers extension clip without message)
try {
self._clipRefreshInterval = setInterval(() => {
if (!document.hidden) self.refreshSidebarTree();
}, 15000);
} catch (_e) {}
// BroadcastChannel cross-tab sync (all FlowDeck tabs refresh together)
try {
if (window.BroadcastChannel) {
const bc = new BroadcastChannel('flowdeck');
bc.onmessage = (ev) => {
if (ev.data && ev.data.type === 'clip-created') self.refreshSidebarTree();
};
window._fdBC = bc;
// Bridge DOM event → BroadcastChannel for extension-triggered clips
window.addEventListener('flowdeck:clip-created', () => {
try { bc.postMessage({ type: 'clip-created', at: Date.now() }); } catch (_e) {}
});
}
} catch (_e) {}
},
agentList: [],
loadAgents() {