about summary refs log tree commit diff
path: root/bskyembed/snippet/embed.ts
diff options
context:
space:
mode:
authorSamuel Newman <mozzius@protonmail.com>2024-04-13 03:58:40 +0100
committerGitHub <noreply@github.com>2024-04-13 03:58:40 +0100
commit4b3ec5573241b9c71504dfd0bd5f181cbde19a49 (patch)
tree698c2463b389cdf6e14536610e8f96f200ddaaa3 /bskyembed/snippet/embed.ts
parent8e29b1f63309ef9ac2da21f62e03b66d477244e9 (diff)
downloadvoidsky-4b3ec5573241b9c71504dfd0bd5f181cbde19a49.tar.zst
[Embeds] Embed subdomain landing page (#3501)
* add build output to web build

* simplify post-build step by copying everything at once

* make script that converts placeholder -> iframe

* dynamically resize iframe based on inner content

Requires the iframe content to `postMessage` its height back up to the parent

* add lang to embed

* svg explicit height -> viewBox

* add build output to web build

* simplify post-build step by copying everything at once

* attempt to fix go embed issue

* rm changes to bskyweb

* remove another bskyweb change

* embed landing page

* Drop xl breakpoint, too far down

* Remove pointer enter behavior

* Avoid button width jump

* Escape HTML

---------

Co-authored-by: Dan Abramov <dan.abramov@gmail.com>
Diffstat (limited to 'bskyembed/snippet/embed.ts')
-rw-r--r--bskyembed/snippet/embed.ts90
1 files changed, 90 insertions, 0 deletions
diff --git a/bskyembed/snippet/embed.ts b/bskyembed/snippet/embed.ts
new file mode 100644
index 000000000..f2b9b442e
--- /dev/null
+++ b/bskyembed/snippet/embed.ts
@@ -0,0 +1,90 @@
+// eslint-disable-next-line @typescript-eslint/no-unused-vars
+interface Window {
+  bluesky: {
+    scan: (element?: Pick<Element, 'querySelectorAll'>) => void
+  }
+}
+
+const EMBED_URL = 'https://embed.bsky.app'
+
+window.bluesky = window.bluesky || {
+  scan,
+}
+
+/**
+ * Listen for messages from the Bluesky embed iframe and adjust the height of
+ * the iframe accordingly.
+ */
+window.addEventListener('message', event => {
+  if (event.origin !== EMBED_URL) {
+    return
+  }
+
+  const id = (event.data as {id: string}).id
+  if (!id) {
+    return
+  }
+
+  const embed = document.querySelector<HTMLIFrameElement>(
+    `[data-bluesky-id="${id}"]`,
+  )
+
+  if (!embed) {
+    return
+  }
+
+  const height = (event.data as {height: number}).height
+  if (height) {
+    embed.style.height = `${height}px`
+  }
+})
+
+/**
+ * Scan the document for all elements with the data-bluesky-aturi attribute,
+ * and initialize them as Bluesky embeds.
+ *
+ * @param element Only scan this specific element @default document @optional
+ * @returns
+ */
+function scan(node = document) {
+  const embeds = node.querySelectorAll('[data-bluesky-uri]')
+
+  for (let i = 0; i < embeds.length; i++) {
+    const id = String(Math.random()).slice(2)
+
+    const embed = embeds[i]
+    const aturi = embed.getAttribute('data-bluesky-uri')
+
+    if (!aturi) {
+      continue
+    }
+
+    const iframe = document.createElement('iframe')
+    iframe.setAttribute('data-bluesky-id', id)
+    iframe.src = `${EMBED_URL}/embed/${aturi.slice('at://'.length)}?id=${id}`
+    iframe.width = '100%'
+    iframe.style.border = 'none'
+    iframe.style.display = 'block'
+    iframe.style.flexGrow = '1'
+    iframe.frameBorder = '0'
+    iframe.scrolling = 'no'
+
+    const container = document.createElement('div')
+    container.style.maxWidth = '600px'
+    container.style.width = '100%'
+    container.style.marginTop = '10px'
+    container.style.marginBottom = '10px'
+    container.style.display = 'flex'
+    container.className = 'bluesky-embed'
+
+    container.appendChild(iframe)
+
+    embed.replaceWith(container)
+  }
+}
+
+if (['interactive', 'complete'].indexOf(document.readyState) !== -1) {
+  scan()
+} else {
+  document.addEventListener('DOMContentLoaded', () => scan())
+}