|
|
|
@@ -440,19 +440,11 @@
|
|
|
|
|
}
|
|
|
|
|
var url=b.src||'';if(url){
|
|
|
|
|
var src=url;
|
|
|
|
|
try{var h=window.location.href.split('/').slice(0,3).join('/');var urlNoProto=url.replace(/^https?:\\/\\//,'');if(/^(youtube\\.com|youtu\\.be|vimeo\\.com|loom\\.com|figma\\.com|google\\.com\\/maps|codepen\\.io|miro\\.com|open\\.spotify\\.com|soundcloud\\.com|twitch\\.tv|twitter\\.com|x\\.com|pinterest\\.)/.test(urlNoProto.split('/')[0])){src=url;}}catch(e){}
|
|
|
|
|
try{var h=window.location.href.split('/').slice(0,3).join('/');var urlNoProto=url.replace(/^https?:\/\//,'');if(/^(youtube\.com|youtu\.be|vimeo\.com|loom\.com|figma\.com|google\.com\/maps|codepen\.io|miro\.com|open\.spotify\.com|soundcloud\.com|twitch\.tv|twitter\.com|x\.com|pinterest\.)/.test(urlNoProto.split('/')[0])){src=url;}}catch(e){}
|
|
|
|
|
var height=b.height||520;
|
|
|
|
|
return `<div class="block-wrapper" data-id="${b.id}"><div class="block-content block-embed" style="position:relative;width:100%;height:${height}px;border-radius:8px;overflow:hidden;background:#0a0a0a;"><iframe src="${src}" loading="lazy" frameborder="0" style="position:absolute;inset:0;width:100%;height:100%;" allowfullscreen allow="autoplay; encrypted-media; picture-in-picture"></iframe></div></div>`;
|
|
|
|
|
}
|
|
|
|
|
return `<div class="block-wrapper" data-id="${b.id}"><div class="block-content block-embed" style="text-align:center;padding:60px 20px;background:var(--bg-secondary);border:1px dashed var(--border);border-radius:8px;cursor:pointer;" onclick="E.setEmbedUrl('${b.id}')"><div style="font-size:48px;margin-bottom:12px;">🔗</div><div style="font-size:14px;color:var(--text-dim);">Click to add embed URL</div></div></div>`;
|
|
|
|
|
}
|
|
|
|
|
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>`;
|
|
|
|
|
if(b.embed_type==='collection')return `<div class="block-wrapper" data-id="${b.id}"><div class="block-content block-embed-collection" id="inline-db-${b.collection_id}" style="padding:0;min-height:200px"><div style="padding:40px;text-align:center;color:var(--text-dim)">Loading database...</div></div><`+`script>setTimeout(function(){var el=document.getElementById('inline-db-${b.collection_id}');if(el&&window.FlowDeckDB)window.FlowDeckDB.renderInto(el,${b.collection_id},null);},50);<`+`/script></div>`;
|
|
|
|
|
if(b.embed_type==='pdf')return `<div class="block-wrapper" data-id="${b.id}"><div class="block-content block-embed" style="padding:0;"><iframe src="${b.src||''}" style="width:100%;height:80vh;border:none;border-radius:8px;" onerror="this.style.display='none';this.nextElementSibling.style.display='block';"></iframe><div style="display:none;text-align:center;padding:32px;color:var(--text-secondary);"><svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/></svg><p style="margin-top:8px;">Failed to load PDF</p><a href="${b.src||''}" target="_blank" style="color:var(--accent);">Open in new tab →</a></div></div></div>`;
|
|
|
|
|
if(b.embed_type==='download'){
|
|
|
|
|
var sz=b.file_size||0;var szStr=sz<1024?sz+' B':sz<1048576?(sz/1024).toFixed(1)+' KB':(sz/1048576).toFixed(1)+' MB';
|
|
|
|
|
return `<div class="block-wrapper" data-id="${b.id}"><div class="block-content block-embed" style="text-align:center;padding:60px 20px;"><div style="font-size:48px;margin-bottom:12px;">{{ fd_icon("paperclip",14) }}</div><div style="font-size:16px;font-weight:500;color:var(--text-primary);margin-bottom:4px;">${esc(b.file_name||'File')}</div><div style="font-size:12px;color:var(--text-tertiary);margin-bottom:16px;">${szStr} · ${esc(b.file_mime||'')}</div><a href="${b.src||''}" download style="display:inline-block;padding:8px 20px;background:var(--accent);color:#fff;text-decoration:none;border-radius:8px;font-size:13px;font-weight:500;">⬇ Download</a></div></div>`;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
const ph=b.type==='heading_1'?'Heading 1':b.type==='heading_2'?'Heading 2':b.type==='heading_3'?'Heading 3':b.type==='heading_4'?'Heading 4':b.type==='bulleted_list'?'List':b.type==='numbered_list'?'List':b.type==='to_do'?'To-do':b.type==='toggle'?'Toggle list':b.type==='quote'?'Empty quote':b.type==='code'?'Type code...':b.type==='callout'?'Type something...':(b.type==='paragraph'&&!b.content?'Press \'space\' for AI or \'/\' for commands':'Press \'/\' for commands...');
|
|
|
|
|
let inner='';
|
|
|
|
@@ -898,6 +890,18 @@
|
|
|
|
|
_commentSel:{range:null,bid:null,start:0,end:0},
|
|
|
|
|
_notifiedMentions:{},
|
|
|
|
|
undoStack:[],redoStack:[],_histCap:100,_histLock:false,
|
|
|
|
|
// ── Cover & icon (v5.10+) ──
|
|
|
|
|
coverUrl:'',
|
|
|
|
|
iconOpen:false,
|
|
|
|
|
iconValue:'',
|
|
|
|
|
// ── Import ──
|
|
|
|
|
importOpen:false,importText:'',importFile:null,
|
|
|
|
|
// ── DB Templates ──
|
|
|
|
|
dbTplOpen:false,dbTplLoading:false,dbTemplates:[],
|
|
|
|
|
// ── Version history ──
|
|
|
|
|
versionsOpen:false,versionsLoading:false,versionsList:[],
|
|
|
|
|
// ── Backlinks ──
|
|
|
|
|
backlinksOpen:false,backlinksLoading:false,backlinksList:[],
|
|
|
|
|
get timeAgo() {
|
|
|
|
|
if (!this.updatedAt) return 'just now';
|
|
|
|
|
var diff = Math.floor((Date.now() - new Date(this.updatedAt + 'Z').getTime()) / 1000);
|
|
|
|
@@ -1117,7 +1121,6 @@ replaceBlock(idx,type){const b=this.blocks[idx];if(!b)return;this.sync();this.pu
|
|
|
|
|
},
|
|
|
|
|
|
|
|
|
|
// ── v5.5.0: Cover & Icon ──
|
|
|
|
|
coverOpen:false,coverUrl:'',coverLoading:false,iconOpen:false,iconValue:'',
|
|
|
|
|
async loadCoverIcon(){
|
|
|
|
|
try{
|
|
|
|
|
const r=await fetch('/board/api/pages/'+this.pid);
|
|
|
|
|