forked from
jollywhoppers.com/witchsky.app
Bluesky app fork with some witchin' additions 馃挮
1// eslint-disable-next-line @typescript-eslint/no-unused-vars
2interface Window {
3 bluesky: {
4 scan: (element?: Pick<Element, 'querySelectorAll'>) => void
5 }
6 BSKY_DEV_EMBED_URL?: string
7}
8
9/**
10 * Allow url to be overwritten during development
11 */
12const IS_DEV =
13 window.location.protocol === 'file:' ||
14 window.location.hostname === 'localhost'
15const EMBED_URL =
16 IS_DEV && window.BSKY_DEV_EMBED_URL
17 ? window.BSKY_DEV_EMBED_URL
18 : 'https://embed.bsky.app'
19
20window.bluesky = window.bluesky || {
21 scan,
22}
23
24/**
25 * Listen for messages from the Bluesky embed iframe and adjust the height of
26 * the iframe accordingly.
27 */
28window.addEventListener('message', event => {
29 if (event.origin !== EMBED_URL) {
30 return
31 }
32
33 // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
34 const id = (event.data as {id: string}).id
35 if (!id) {
36 return
37 }
38
39 const embed = document.querySelector<HTMLIFrameElement>(
40 `[data-bluesky-id="${id}"]`,
41 )
42
43 if (!embed) {
44 return
45 }
46
47 // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
48 const height = (event.data as {height: number}).height
49 if (height) {
50 embed.style.height = `${height}px`
51 }
52})
53
54/**
55 * Scan the document for all elements with the data-bluesky-aturi attribute,
56 * and initialize them as Bluesky embeds.
57 *
58 * @param element Only scan this specific element @default document @optional
59 * @returns
60 */
61function scan(node = document) {
62 const embeds = node.querySelectorAll<HTMLIFrameElement>('[data-bluesky-uri]')
63
64 for (let i = 0; i < embeds.length; i++) {
65 const id = String(Math.random()).slice(2)
66
67 const embed = embeds[i]
68 const aturi = embed.getAttribute('data-bluesky-uri')
69
70 if (!aturi) {
71 continue
72 }
73
74 const ref_url = location.origin + location.pathname
75
76 const searchParams = new URLSearchParams()
77 searchParams.set('id', id)
78 if (ref_url.startsWith('http')) {
79 searchParams.set('ref_url', encodeURIComponent(ref_url))
80 }
81 if (embed.dataset.blueskyEmbedColorMode) {
82 searchParams.set('colorMode', embed.dataset.blueskyEmbedColorMode)
83 }
84
85 const iframe = document.createElement('iframe')
86 iframe.setAttribute('data-bluesky-id', id)
87 iframe.src = `${EMBED_URL}/embed/${aturi.slice(
88 'at://'.length,
89 )}?${searchParams.toString()}`
90 iframe.width = '100%'
91 iframe.style.border = 'none'
92 iframe.style.display = 'block'
93 iframe.style.flexGrow = '1'
94 iframe.frameBorder = '0'
95 iframe.scrolling = 'no'
96
97 const container = document.createElement('div')
98 container.style.maxWidth = '600px'
99 container.style.width = '100%'
100 container.style.marginTop = '10px'
101 container.style.marginBottom = '10px'
102 container.style.display = 'flex'
103 container.className = 'bluesky-embed'
104
105 container.appendChild(iframe)
106
107 embed.replaceWith(container)
108 }
109}
110
111if (['interactive', 'complete'].indexOf(document.readyState) !== -1) {
112 scan()
113} else {
114 document.addEventListener('DOMContentLoaded', () => scan())
115}