Merge branch 'app-2066' into app-2067

# Conflicts:
#	src/state/queries/klipy.ts
This commit is contained in:
vineyardbovines
2026-04-14 15:03:11 -04:00
8 changed files with 28 additions and 107 deletions
+1 -1
View File
@@ -186,7 +186,7 @@ function LandingPage() {
function Skeleton() { function Skeleton() {
return ( return (
<Container> <Container>
<div className="flex-1 flex-col flex gap-2 pb-8"> <div className="flex-1 flex-col flex gap-2 p-5 pb-8">
<div className="flex gap-2.5 items-center"> <div className="flex gap-2.5 items-center">
<div className="w-10 h-10 overflow-hidden rounded-full bg-neutral-100 dark:bg-slate-700 shrink-0 animate-pulse" /> <div className="w-10 h-10 overflow-hidden rounded-full bg-neutral-100 dark:bg-slate-700 shrink-0 animate-pulse" />
<div className="flex-1"> <div className="flex-1">
+1 -1
View File
@@ -2,7 +2,7 @@
<html> <html>
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, viewport-fit=cover"> <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, viewport-fit=cover">
<meta name="referrer" content="origin-when-cross-origin"> <meta name="referrer" content="origin-when-cross-origin">
<!-- <!--
Preconnect to essential domains Preconnect to essential domains
+3 -9
View File
@@ -109,7 +109,7 @@ function EmbedDialogInner({
<Trans>Embed post</Trans> <Trans>Embed post</Trans>
</Text> </Text>
<Text <Text
style={[a.text_md, t.atoms.text_contrast_medium, a.leading_normal]}> style={[a.text_md, t.atoms.text_contrast_medium, a.leading_snug]}>
<Trans> <Trans>
Embed this post in your website. Simply copy the following snippet Embed this post in your website. Simply copy the following snippet
and paste it into the HTML code of your website. and paste it into the HTML code of your website.
@@ -117,12 +117,7 @@ function EmbedDialogInner({
</Text> </Text>
</View> </View>
<View <View
style={[ style={[a.border, t.atoms.border_contrast_low, {borderRadius: 18}]}>
a.border,
t.atoms.border_contrast_low,
a.rounded_sm,
a.overflow_hidden,
]}>
<Button <Button
label={ label={
showCustomisation showCustomisation
@@ -190,10 +185,9 @@ function EmbedDialogInner({
<Button <Button
label={_(msg`Copy code`)} label={_(msg`Copy code`)}
color="primary" color="primary"
variant="solid"
size="large" size="large"
onPress={() => { onPress={() => {
navigator.clipboard.writeText(snippet) void navigator.clipboard.writeText(snippet)
setCopied(true) setCopied(true)
}}> }}>
{copied ? ( {copied ? (
+15 -15
View File
@@ -2399,12 +2399,12 @@ msgstr ""
msgid "Collapses list of users for a given notification" msgid "Collapses list of users for a given notification"
msgstr "" msgstr ""
#: src/components/dialogs/Embed.tsx:155 #: src/components/dialogs/Embed.tsx:150
#: src/screens/Settings/AppearanceSettings.tsx:81 #: src/screens/Settings/AppearanceSettings.tsx:81
msgid "Color mode" msgid "Color mode"
msgstr "" msgstr ""
#: src/components/dialogs/Embed.tsx:152 #: src/components/dialogs/Embed.tsx:147
msgid "Color theme" msgid "Color theme"
msgstr "" msgstr ""
@@ -2646,7 +2646,7 @@ msgstr ""
msgid "Copied to clipboard" msgid "Copied to clipboard"
msgstr "" msgstr ""
#: src/components/dialogs/Embed.tsx:203 #: src/components/dialogs/Embed.tsx:197
#: src/screens/Settings/components/CopyButton.tsx:66 #: src/screens/Settings/components/CopyButton.tsx:66
msgid "Copied!" msgid "Copied!"
msgstr "" msgstr ""
@@ -2673,8 +2673,8 @@ msgstr ""
msgid "Copy author DID" msgid "Copy author DID"
msgstr "" msgstr ""
#: src/components/dialogs/Embed.tsx:191 #: src/components/dialogs/Embed.tsx:186
#: src/components/dialogs/Embed.tsx:208 #: src/components/dialogs/Embed.tsx:202
msgid "Copy code" msgid "Copy code"
msgstr "" msgstr ""
@@ -2948,7 +2948,7 @@ msgstr ""
msgid "Custom" msgid "Custom"
msgstr "" msgstr ""
#: src/components/dialogs/Embed.tsx:145 #: src/components/dialogs/Embed.tsx:140
msgid "Customization options" msgid "Customization options"
msgstr "" msgstr ""
@@ -2964,8 +2964,8 @@ msgstr ""
msgid "Dangerous substances or drug abuse" msgid "Dangerous substances or drug abuse"
msgstr "" msgstr ""
#: src/components/dialogs/Embed.tsx:169 #: src/components/dialogs/Embed.tsx:164
#: src/components/dialogs/Embed.tsx:171 #: src/components/dialogs/Embed.tsx:166
#: src/screens/Settings/AppearanceSettings.tsx:93 #: src/screens/Settings/AppearanceSettings.tsx:93
#: src/screens/Settings/AppearanceSettings.tsx:114 #: src/screens/Settings/AppearanceSettings.tsx:114
msgid "Dark" msgid "Dark"
@@ -3613,7 +3613,7 @@ msgstr ""
msgid "Email Verified" msgid "Email Verified"
msgstr "" msgstr ""
#: src/components/dialogs/Embed.tsx:183 #: src/components/dialogs/Embed.tsx:178
msgid "Embed HTML code" msgid "Embed HTML code"
msgstr "" msgstr ""
@@ -5004,7 +5004,7 @@ msgstr ""
msgid "Hide all events" msgid "Hide all events"
msgstr "" msgstr ""
#: src/components/dialogs/Embed.tsx:129 #: src/components/dialogs/Embed.tsx:124
msgid "Hide customization options" msgid "Hide customization options"
msgstr "" msgstr ""
@@ -5701,8 +5701,8 @@ msgstr ""
msgid "Let's go!" msgid "Let's go!"
msgstr "" msgstr ""
#: src/components/dialogs/Embed.tsx:164 #: src/components/dialogs/Embed.tsx:159
#: src/components/dialogs/Embed.tsx:166 #: src/components/dialogs/Embed.tsx:161
#: src/screens/Settings/AppearanceSettings.tsx:89 #: src/screens/Settings/AppearanceSettings.tsx:89
msgid "Light" msgid "Light"
msgstr "" msgstr ""
@@ -9359,7 +9359,7 @@ msgstr ""
msgid "Show badge and filter from feeds" msgid "Show badge and filter from feeds"
msgstr "" msgstr ""
#: src/components/dialogs/Embed.tsx:130 #: src/components/dialogs/Embed.tsx:125
msgid "Show customization options" msgid "Show customization options"
msgstr "" msgstr ""
@@ -9910,8 +9910,8 @@ msgstr ""
msgid "Switch to {0}" msgid "Switch to {0}"
msgstr "" msgstr ""
#: src/components/dialogs/Embed.tsx:159 #: src/components/dialogs/Embed.tsx:154
#: src/components/dialogs/Embed.tsx:161 #: src/components/dialogs/Embed.tsx:156
#: src/screens/Settings/AppearanceSettings.tsx:85 #: src/screens/Settings/AppearanceSettings.tsx:85
#: src/screens/Settings/AppearanceSettings.tsx:135 #: src/screens/Settings/AppearanceSettings.tsx:135
msgid "System" msgid "System"
+1 -1
View File
@@ -277,7 +277,7 @@ export async function compressImage(
async function moveIfNecessary(from: string) { async function moveIfNecessary(from: string) {
const cacheDir = IS_NATIVE && getImageCacheDirectory() const cacheDir = IS_NATIVE && getImageCacheDirectory()
if (cacheDir && from.startsWith(cacheDir)) { if (cacheDir && !from.startsWith(cacheDir)) {
const to = joinPath(cacheDir, nanoid(36)) const to = joinPath(cacheDir, nanoid(36))
await makeDirectoryAsync(cacheDir, {intermediates: true}) await makeDirectoryAsync(cacheDir, {intermediates: true})
+4 -76
View File
@@ -141,18 +141,18 @@ function createKlipyApi<Input extends object>(
if (!res.ok) { if (!res.ok) {
throw new Error('Failed to fetch KLIPY API') throw new Error('Failed to fetch KLIPY API')
} }
const body: KlipyResponse = await res.json() const body: {next: string; results: Gif[]} = await res.json()
return { return {
next: body.next, next: body.next,
results: body.data.map(normalizeKlipyGif), results: body.results,
} }
} }
} }
/** /**
* Returns the static URL for a KLIPY GIF preview image. * Returns the static URL for a KLIPY GIF preview image.
* Currently a pass-through; will route through the bsky proxy once the * KLIPY images are served directly from their CDN (static.klipy.com),
* backend proxy PR (tango) is deployed. * unlike Tenor which routes through t.gifs.bsky.app.
*/ */
export function klipyStaticUrl(gifUrl: string) { export function klipyStaticUrl(gifUrl: string) {
try { try {
@@ -164,78 +164,6 @@ export function klipyStaticUrl(gifUrl: string) {
} }
} }
/**
* Maps a native KLIPY gif object onto the Tenor-shaped `Gif` type so
* downstream consumers (resolveGif, composer drafts, ExternalEmbed, etc.)
* continue to work unchanged.
*
* NOTE: the exact KLIPY response shape needs to be verified against the
* backend proxy once the tango PR is deployed — some fields here are
* best-effort based on what's documented today.
*/
function normalizeKlipyGif(k: KlipyGif): Gif {
const toMediaObject = (v: KlipyFileVariant) => ({
url: v.url,
dims: [v.width, v.height] as [number, number],
duration: 0,
size: 0,
})
return {
id: k.slug,
title: k.title ?? '',
content_description: k.content_description ?? k.title ?? '',
tags: k.tags ?? [],
media_formats: {
gif: toMediaObject(k.file.hd.gif),
tinygif: toMediaObject(k.file.sm.gif),
preview: toMediaObject(k.file.sm.gif),
},
// Tenor-only fields; stub sensibly for KLIPY.
created: 0,
hasaudio: false,
hascaption: false,
flags: '',
itemurl: k.url ?? '',
url: k.url ?? '',
}
}
type KlipyFileVariant = {
url: string
width: number
height: number
}
type KlipyFileFormats = {
gif: KlipyFileVariant
webp?: KlipyFileVariant
mp4?: KlipyFileVariant
}
type KlipyFile = {
/** Small/thumbnail size, used in the picker grid */
sm: KlipyFileFormats
/** Medium size */
md: KlipyFileFormats
/** Full/large size, used when posting */
hd: KlipyFileFormats
}
type KlipyGif = {
slug: string
title?: string
content_description?: string
tags?: string[]
url?: string
file: KlipyFile
}
type KlipyResponse = {
next: string
data: KlipyGif[]
}
type KlipyAutocompleteResponse = { type KlipyAutocompleteResponse = {
locale: string locale: string
results: string[] results: string[]
+2 -3
View File
@@ -105,9 +105,8 @@ export function tenorUrlToBskyGifUrl(tenorUrl: string) {
/** /**
* Returns the appropriate URL for a GIF preview image. * Returns the appropriate URL for a GIF preview image.
* Rewrites Tenor URLs through the bsky proxy; KLIPY URLs pass through * Rewrites Tenor URLs through the bsky proxy (t.gifs.bsky.app);
* directly (will route through the bsky proxy once the tango backend-proxy * KLIPY URLs pass through directly to their CDN.
* PR is deployed).
*/ */
export function gifPreviewUrl(gifUrl: string) { export function gifPreviewUrl(gifUrl: string) {
try { try {
+1 -1
View File
@@ -9,7 +9,7 @@
--> -->
<meta <meta
name="viewport" name="viewport"
content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1.00001, viewport-fit=cover" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, viewport-fit=cover"
/> />
<!-- <!--
Preconnect to essential domains Preconnect to essential domains