diff --git a/ui/app.css b/ui/app.css index 8948b71..5024b4b 100644 --- a/ui/app.css +++ b/ui/app.css @@ -497,5 +497,6 @@ a.brand:hover > span:first-of-type { color: var(--accent); } .share-link input { flex: 1; min-width: 0; font-size: 0.75rem; padding: 0.3125rem 0.5rem; } .share-sep { height: 1px; background: var(--border); margin: 0.25rem 0; } .share-menu button[role=menuitem] { display: flex; align-items: center; gap: 0.625rem; width: 100%; } -.share-ic { width: 1.125rem; text-align: center; color: var(--muted); } +.share-ic { width: 1.125rem; display: inline-grid; place-items: center; color: var(--muted); } +.share-ic svg { width: 1rem; height: 1rem; } .share-note { margin: 0.375rem 0.5rem 0.125rem; } diff --git a/ui/app.js b/ui/app.js index a2d0891..daa6690 100644 --- a/ui/app.js +++ b/ui/app.js @@ -1392,6 +1392,19 @@ const ICONS = { download: '', share: '', }; +// Brand marks for the share menu (24x24 paths), drawn in each brand's colour. +const BRAND = { + x: ['currentColor', 'M18.901 1.153h3.68l-8.04 9.19L24 22.846h-7.406l-5.8-7.584-6.638 7.584H.474l8.6-9.83L0 1.154h7.594l5.243 6.932ZM17.61 20.644h2.039L6.486 3.24H4.298Z'], + telegram: ['#26A5E4', 'M11.944 0A12 12 0 0 0 0 12a12 12 0 0 0 12 12 12 12 0 0 0 12-12A12 12 0 0 0 12 0a12 12 0 0 0-.056 0zm4.962 7.224c.1-.002.321.023.465.14a.506.506 0 0 1 .171.325c.016.093.036.306.02.472-.18 1.898-.962 6.502-1.36 8.627-.168.9-.499 1.201-.82 1.23-.696.065-1.225-.46-1.9-.902-1.056-.693-1.653-1.124-2.678-1.8-1.185-.78-.417-1.21.258-1.91.177-.184 3.247-2.977 3.307-3.23.007-.032.014-.15-.056-.212s-.174-.041-.249-.024c-.106.024-1.793 1.14-5.061 3.345-.48.33-.913.49-1.302.48-.428-.008-1.252-.241-1.865-.44-.752-.245-1.349-.374-1.297-.789.027-.216.325-.437.893-.663 3.498-1.524 5.83-2.529 6.998-3.014 3.332-1.386 4.025-1.627 4.476-1.635z'], + whatsapp: ['#25D366', 'M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 0 1-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 0 1-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 0 1 2.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0 0 12.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 0 0 5.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 0 0-3.48-8.413Z'], +}; +function brandIcon(name) { + const [fill, d] = BRAND[name]; + const span = h('span', { class: 'share-ic', 'aria-hidden': 'true' }); + span.innerHTML = ``; // fixed markup above + return span; +} + function iconButton(name, label, run) { const b = h('button', { type: 'button', class: 'btn small icon', title: label, 'aria-label': label, onclick: (e) => { e.stopPropagation(); run(e); } }); b.innerHTML = ICONS[name]; // fixed markup above, never user data @@ -2119,14 +2132,21 @@ function objectBrowser(head, body, user, bucket, prefix, userSel) { catch { field.focus(); field.select(); } } }, 'Copy'); const send = (href) => () => { pop.done(); openLink(href); }; - const row = (icon, label, run) => h('button', { type: 'button', role: 'menuitem', onclick: run }, h('span', { class: 'share-ic', 'aria-hidden': 'true' }, icon), label); + const row = (icon, label, run) => h('button', { type: 'button', role: 'menuitem', onclick: run }, typeof icon === 'string' ? h('span', { class: 'share-ic', 'aria-hidden': 'true' }, icon) : icon, label); + // In Theseus, Telegram and WhatsApp open in its own sidebar apps (where + // the user is signed in) at their share screens; elsewhere, the apps' + // own share links, which hand over to the installed app. + const inTheseus = !!bridge || state.status?.host === 'theseus'; + const tgShare = `tg://msg_url?url=${enc(url)}&text=${enc(text)}`; + const telegram = inTheseus ? `https://web.telegram.org/k/#?tgaddr=${enc(tgShare)}` : `https://t.me/share/url?url=${enc(url)}&text=${enc(text)}`; + const whatsapp = inTheseus ? `https://web.whatsapp.com/send?text=${enc(`${text}: ${url}`)}` : `https://wa.me/?text=${enc(`${text}: ${url}`)}`; put(pop.menu, h('div', { class: 'share-link' }, field, copyBtn), h('div', { class: 'share-sep', role: 'separator' }), row('↗', 'Open link', send(url)), - row('𝕏', 'Post on X', send(`https://x.com/intent/post?text=${enc(text)}&url=${enc(url)}`)), - row('✈', 'Send on Telegram', send(`https://t.me/share/url?url=${enc(url)}&text=${enc(text)}`)), - row('✆', 'Send on WhatsApp', send(`https://wa.me/?text=${enc(`${text}: ${url}`)}`)), + row(brandIcon('telegram'), 'Send on Telegram', send(telegram)), + row(brandIcon('whatsapp'), 'Send on WhatsApp', send(whatsapp)), + row(brandIcon('x'), 'Post on X', send(`https://x.com/intent/post?text=${enc(text)}&url=${enc(url)}`)), h('div', { class: 'share-sep', role: 'separator' }), row('⚙', folder ? 'Manage public links…' : 'Link options…', options), h('p', { class: 'small muted share-note' }, 'Anyone with the link can open it, for 10 years unless you switch it off.')); @@ -2792,9 +2812,7 @@ function addSidebarControls() { const btn = h('button', { class: 'btn small', title: 'Open Pithos in a tab and close this panel', onclick: async () => { try { await bridge.invoke('open-in-tab', { path: hashToPath(location.hash || '#/overview') }); await bridge.sidebar?.close?.(); } catch (e) { fail(e); } } }, '⤢ Full page'); - hostControls().prepend(btn); - addMenuAction('⤢ Open as full page', () => btn.click()); - addBarButton('⤢', 'Open as full page', () => btn.click()); + addMenuAction('⤢ Open in a tab', () => btn.click()); } // A one-click icon in the compact top bar, beside ☰ (narrow layouts only).