anproto personal data server
at master 127 lines 3.5 kB view raw
1const WIREDOVE_ORIGIN = 'http://localhost:8000' 2 3const applyWiredoveStyles = () => { 4 if (document.getElementById('anproto-wiredove-styles')) { return } 5 const style = document.createElement('style') 6 style.id = 'anproto-wiredove-styles' 7 style.textContent = ` 8 .wiredove-share { 9 --wiredove-purple: #ac8aff; 10 display: inline-flex; 11 align-items: center; 12 gap: 4px; 13 padding: 0 0 0 5px; 14 height: 22px; 15 border-radius: 999px; 16 border: 1px solid var(--wiredove-purple); 17 color: #fff; 18 background: var(--wiredove-purple); 19 font-weight: 600; 20 font-size: 12px; 21 line-height: 1; 22 letter-spacing: 0.02em; 23 cursor: pointer; 24 } 25 .wiredove-share img { 26 width: 18px; 27 height: 18px; 28 display: block; 29 } 30 .wiredove-share:hover { 31 filter: brightness(0.95); 32 } 33 .wiredove-share-icon { 34 display: inline-flex; 35 align-items: center; 36 justify-content: center; 37 width: 32px; 38 height: 32px; 39 padding: 0; 40 border-radius: 0; 41 border: none; 42 background: transparent; 43 cursor: pointer; 44 } 45 .wiredove-share-icon img { 46 width: 28px; 47 height: 28px; 48 display: block; 49 } 50 .wiredove-share-icon:hover { 51 filter: brightness(0.9); 52 } 53 ` 54 document.head.appendChild(style) 55} 56 57const ensureWiredoveLogo = (button, { createIfMissing = false } = {}) => { 58 let img = button.querySelector('img') 59 if (!img && createIfMissing) { 60 img = document.createElement('img') 61 button.appendChild(img) 62 } 63 if (!img) { return } 64 if (!img.getAttribute('alt')) { img.setAttribute('alt', 'Wiredove logo') } 65 if (!img.getAttribute('src')) { 66 img.src = new URL('./assets/dovepurple_sm.png', import.meta.url).href 67 } 68} 69 70const resolveValue = (value) => { 71 return typeof value === 'function' ? value() : value 72} 73 74const buildPayload = (value) => { 75 const base = { 76 title: document.title ? document.title.trim() : 'Shared link', 77 url: window.location.href 78 } 79 if (!value) { return base } 80 if (typeof value === 'string') { 81 const text = value.trim() 82 return text ? { ...base, text } : base 83 } 84 if (typeof value === 'object') { 85 return { ...base, ...value } 86 } 87 return base 88} 89 90const openWiredoveShare = (payload) => { 91 const encoded = encodeURIComponent(JSON.stringify(payload)) 92 const target = `${WIREDOVE_ORIGIN}/#share=${encoded}` 93 window.open(target, '_blank', 'noopener') 94} 95 96export const attachShareButton = (button, payload) => { 97 if (!button) { return } 98 button.addEventListener('click', () => { 99 const resolved = resolveValue(payload) 100 openWiredoveShare(buildPayload(resolved)) 101 }) 102} 103 104export const attachWiredoveShareButton = (button, payload) => { 105 if (!button) { return } 106 applyWiredoveStyles() 107 button.classList.add('wiredove-share') 108 if (!button.getAttribute('title')) { 109 button.setAttribute('title', 'Share with ANProto') 110 } 111 ensureWiredoveLogo(button) 112 attachShareButton(button, payload) 113} 114 115export const attachWiredoveIconShareButton = (button, payload) => { 116 if (!button) { return } 117 applyWiredoveStyles() 118 button.classList.add('wiredove-share-icon') 119 if (!button.getAttribute('title')) { 120 button.setAttribute('title', 'Share with ANProto') 121 } 122 if (!button.getAttribute('aria-label')) { 123 button.setAttribute('aria-label', 'Share on ANProto') 124 } 125 ensureWiredoveLogo(button, { createIfMissing: true }) 126 attachShareButton(button, payload) 127}