Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhance(embed): add ability to pin color mode #7074

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions bskyembed/snippet/embed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ function scan(node = document) {
if (ref_url.startsWith('http')) {
searchParams.set('ref_url', encodeURIComponent(ref_url))
}
searchParams.set('colorMode', embed.dataset.blueskyColorMode || 'system')

const iframe = document.createElement('iframe')
iframe.setAttribute('data-bluesky-id', id)
Expand Down
6 changes: 6 additions & 0 deletions bskyembed/src/color-mode.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
export type ColorModeValues = 'system' | 'light' | 'dark'

export function assertColorModeValues(value: string): value is ColorModeValues {
return ['system', 'light', 'dark'].includes(value)
}

export function applyTheme(theme: 'light' | 'dark') {
document.documentElement.classList.remove('light', 'dark')
document.documentElement.classList.add(theme)
Expand Down
73 changes: 57 additions & 16 deletions bskyembed/src/screens/landing.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,11 @@ import {useEffect, useMemo, useRef, useState} from 'preact/hooks'

import arrowBottom from '../../assets/arrowBottom_stroke2_corner0_rounded.svg'
import logo from '../../assets/logo.svg'
import {initColorMode} from '../color-mode'
import {
assertColorModeValues,
ColorModeValues,
initColorMode,
} from '../color-mode'
import {Container} from '../components/container'
import {Link} from '../components/link'
import {Post} from '../components/post'
Expand All @@ -32,6 +36,7 @@ render(<LandingPage />, root)

function LandingPage() {
const [uri, setUri] = useState('')
const [colorMode, setColorMode] = useState<ColorModeValues>('system')
const [error, setError] = useState<string | null>(null)
const [loading, setLoading] = useState(false)
const [thread, setThread] = useState<AppBskyFeedDefs.ThreadViewPost | null>(
Expand Down Expand Up @@ -120,24 +125,52 @@ function LandingPage() {

<h1 className="text-4xl font-bold text-center">Embed a Bluesky Post</h1>

<input
type="text"
value={uri}
onInput={e => setUri(e.currentTarget.value)}
className="border rounded-lg py-3 w-full max-w-[600px] px-4 dark:bg-dimmedBg dark:border-slate-500"
placeholder={DEFAULT_POST}
/>
<div className="flex flex-col w-full max-w-[600px] gap-4">
<input
type="text"
value={uri}
onInput={e => setUri(e.currentTarget.value)}
className="border rounded-lg py-3 px-4 dark:bg-dimmedBg dark:border-slate-500"
placeholder={DEFAULT_POST}
/>

<div>
<label
className="block pb-1 text-sm font-medium"
for="colorModeSelect">
Theme
</label>
<select
value={colorMode}
onChange={e => {
const value = e.currentTarget.value
if (assertColorModeValues(value)) {
setColorMode(value)
}
}}
id="colorModeSelect"
className="block border w-full rounded-lg text-sm px-3 py-2 dark:bg-dimmedBg dark:border-slate-500">
<option value="system">System</option>
<option value="light">Light</option>
<option value="dark">Dark</option>
</select>
</div>
</div>

<img src={arrowBottom} className="w-6 dark:invert" />

{loading ? (
<div className="w-full max-w-[600px]">
<div className={`${colorMode} w-full max-w-[600px]`}>
<Skeleton />
</div>
) : (
<div className="w-full max-w-[600px] gap-8 flex flex-col">
{!error && thread && uri && <Snippet thread={thread} />}
{!error && thread && <Post thread={thread} key={thread.post.uri} />}
{!error && thread && uri && (
<Snippet thread={thread} colorMode={colorMode} />
)}
<div className={colorMode}>
{!error && thread && <Post thread={thread} key={thread.post.uri} />}
</div>
{error && (
<div className="w-full border border-red-500 bg-red-500/10 px-4 py-3 rounded-lg">
<p className="text-red-500 text-center">{error}</p>
Expand Down Expand Up @@ -168,7 +201,13 @@ function Skeleton() {
)
}

function Snippet({thread}: {thread: AppBskyFeedDefs.ThreadViewPost}) {
function Snippet({
thread,
colorMode,
}: {
thread: AppBskyFeedDefs.ThreadViewPost
colorMode: ColorModeValues
}) {
const ref = useRef<HTMLInputElement>(null)
const [copied, setCopied] = useState(false)

Expand Down Expand Up @@ -204,9 +243,11 @@ function Snippet({thread}: {thread: AppBskyFeedDefs.ThreadViewPost}) {
// x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x-x
return `<blockquote class="bluesky-embed" data-bluesky-uri="${escapeHtml(
thread.post.uri,
)}" data-bluesky-cid="${escapeHtml(thread.post.cid)}"><p lang="${escapeHtml(
lang,
)}">${escapeHtml(record.text)}${
)}" data-bluesky-cid="${escapeHtml(
thread.post.cid,
)}" data-bluesky-embed-color-mode="${escapeHtml(
colorMode,
)}"><p lang="${escapeHtml(lang)}">${escapeHtml(record.text)}${
record.embed
? `<br><br><a href="${escapeHtml(href)}">[image or embed]</a>`
: ''
Expand All @@ -217,7 +258,7 @@ function Snippet({thread}: {thread: AppBskyFeedDefs.ThreadViewPost}) {
)}</a>) <a href="${escapeHtml(href)}">${escapeHtml(
niceDate(thread.post.indexedAt),
)}</a></blockquote><script async src="${EMBED_SCRIPT}" charset="utf-8"></script>`
}, [thread])
}, [thread, colorMode])

return (
<div className="flex gap-2 w-full">
Expand Down
15 changes: 13 additions & 2 deletions bskyembed/src/screens/post.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {AppBskyFeedDefs, AtpAgent} from '@atproto/api'
import {h, render} from 'preact'

import logo from '../../assets/logo.svg'
import {initColorMode} from '../color-mode'
import {applyTheme, assertColorModeValues, initColorMode} from '../color-mode'
import {Container} from '../components/container'
import {Link} from '../components/link'
import {Post} from '../components/post'
Expand All @@ -22,7 +22,18 @@ if (!uri) {
throw new Error('No uri in path')
}

initColorMode()
const query = new URLSearchParams(window.location.search)
const colorMode = query.get('colorMode')

if (
colorMode != null &&
assertColorModeValues(colorMode) &&
colorMode !== 'system'
) {
applyTheme(colorMode)
} else {
initColorMode()
}

agent
.getPostThread({
Expand Down