diff --git a/__tests__/lib/string.test.ts b/__tests__/lib/string.test.ts index f003e5ac..eeb5ae15 100644 --- a/__tests__/lib/string.test.ts +++ b/__tests__/lib/string.test.ts @@ -1,17 +1,18 @@ import {RichText} from '@atproto/api' + +import {parseEmbedPlayerFromUrl} from 'lib/strings/embed-player' +import {cleanError} from '../../src/lib/strings/errors' +import {createFullHandle, makeValidHandle} from '../../src/lib/strings/handles' +import {enforceLen, pluralize} from '../../src/lib/strings/helpers' +import {detectLinkables} from '../../src/lib/strings/rich-text-detection' +import {shortenLinks} from '../../src/lib/strings/rich-text-manip' +import {ago} from '../../src/lib/strings/time' import { makeRecordUri, toNiceDomain, - toShortUrl, toShareUrl, + toShortUrl, } from '../../src/lib/strings/url-helpers' -import {pluralize, enforceLen} from '../../src/lib/strings/helpers' -import {ago} from '../../src/lib/strings/time' -import {detectLinkables} from '../../src/lib/strings/rich-text-detection' -import {shortenLinks} from '../../src/lib/strings/rich-text-manip' -import {makeValidHandle, createFullHandle} from '../../src/lib/strings/handles' -import {cleanError} from '../../src/lib/strings/errors' -import {parseEmbedPlayerFromUrl} from 'lib/strings/embed-player' describe('detectLinkables', () => { const inputs = [ @@ -434,6 +435,8 @@ describe('parseEmbedPlayerFromUrl', () => { 'https://giphy.com/gif/some-random-gif-name-gifId', 'https://giphy.com/gifs/', + 'https://giphy.com/gifs/39248209509382934029?hh=100&ww=100', + 'https://media.giphy.com/media/gifId/giphy.webp', 'https://media0.giphy.com/media/gifId/giphy.webp', 'https://media1.giphy.com/media/gifId/giphy.gif', @@ -621,18 +624,31 @@ describe('parseEmbedPlayerFromUrl', () => { isGif: true, hideDetails: true, metaUri: 'https://giphy.com/gifs/gifId', - playerUri: 'https://i.giphy.com/media/gifId/giphy.webp', + playerUri: 'https://i.giphy.com/media/gifId/200.webp', }, undefined, undefined, + { + type: 'giphy_gif', + source: 'giphy', + isGif: true, + hideDetails: true, + metaUri: 'https://giphy.com/gifs/39248209509382934029', + playerUri: 'https://i.giphy.com/media/39248209509382934029/200.mp4', + dimensions: { + width: 100, + height: 100, + }, + }, + { type: 'giphy_gif', source: 'giphy', isGif: true, hideDetails: true, metaUri: 'https://giphy.com/gifs/gifId', - playerUri: 'https://i.giphy.com/media/gifId/giphy.webp', + playerUri: 'https://i.giphy.com/media/gifId/200.webp', }, { type: 'giphy_gif', @@ -640,7 +656,7 @@ describe('parseEmbedPlayerFromUrl', () => { isGif: true, hideDetails: true, metaUri: 'https://giphy.com/gifs/gifId', - playerUri: 'https://i.giphy.com/media/gifId/giphy.webp', + playerUri: 'https://i.giphy.com/media/gifId/200.webp', }, { type: 'giphy_gif', @@ -648,7 +664,7 @@ describe('parseEmbedPlayerFromUrl', () => { isGif: true, hideDetails: true, metaUri: 'https://giphy.com/gifs/gifId', - playerUri: 'https://i.giphy.com/media/gifId/giphy.webp', + playerUri: 'https://i.giphy.com/media/gifId/200.webp', }, { type: 'giphy_gif', @@ -656,7 +672,7 @@ describe('parseEmbedPlayerFromUrl', () => { isGif: true, hideDetails: true, metaUri: 'https://giphy.com/gifs/gifId', - playerUri: 'https://i.giphy.com/media/gifId/giphy.webp', + playerUri: 'https://i.giphy.com/media/gifId/200.webp', }, { type: 'giphy_gif', @@ -664,7 +680,7 @@ describe('parseEmbedPlayerFromUrl', () => { isGif: true, hideDetails: true, metaUri: 'https://giphy.com/gifs/gifId', - playerUri: 'https://i.giphy.com/media/gifId/giphy.webp', + playerUri: 'https://i.giphy.com/media/gifId/200.webp', }, { type: 'giphy_gif', @@ -672,7 +688,7 @@ describe('parseEmbedPlayerFromUrl', () => { isGif: true, hideDetails: true, metaUri: 'https://giphy.com/gifs/gifId', - playerUri: 'https://i.giphy.com/media/gifId/giphy.webp', + playerUri: 'https://i.giphy.com/media/gifId/200.webp', }, undefined, undefined, @@ -684,7 +700,7 @@ describe('parseEmbedPlayerFromUrl', () => { isGif: true, hideDetails: true, metaUri: 'https://giphy.com/gifs/gifId', - playerUri: 'https://i.giphy.com/media/gifId/giphy.webp', + playerUri: 'https://i.giphy.com/media/gifId/200.webp', }, { @@ -693,7 +709,7 @@ describe('parseEmbedPlayerFromUrl', () => { isGif: true, hideDetails: true, metaUri: 'https://giphy.com/gifs/gifId', - playerUri: 'https://i.giphy.com/media/gifId/giphy.webp', + playerUri: 'https://i.giphy.com/media/gifId/200.webp', }, { type: 'giphy_gif', @@ -701,7 +717,7 @@ describe('parseEmbedPlayerFromUrl', () => { isGif: true, hideDetails: true, metaUri: 'https://giphy.com/gifs/gifId', - playerUri: 'https://i.giphy.com/media/gifId/giphy.webp', + playerUri: 'https://i.giphy.com/media/gifId/200.webp', }, { type: 'giphy_gif', @@ -709,7 +725,7 @@ describe('parseEmbedPlayerFromUrl', () => { isGif: true, hideDetails: true, metaUri: 'https://giphy.com/gifs/gifId', - playerUri: 'https://i.giphy.com/media/gifId/giphy.webp', + playerUri: 'https://i.giphy.com/media/gifId/200.webp', }, { type: 'giphy_gif', @@ -717,7 +733,7 @@ describe('parseEmbedPlayerFromUrl', () => { isGif: true, hideDetails: true, metaUri: 'https://giphy.com/gifs/gifId', - playerUri: 'https://i.giphy.com/media/gifId/giphy.webp', + playerUri: 'https://i.giphy.com/media/gifId/200.webp', }, { diff --git a/src/lib/statsig/gates.ts b/src/lib/statsig/gates.ts index 301746fb..e42e9efe 100644 --- a/src/lib/statsig/gates.ts +++ b/src/lib/statsig/gates.ts @@ -4,6 +4,7 @@ export type Gate = | 'disable_min_shell_on_foregrounding_v2' | 'disable_poll_on_discover_v2' | 'hide_vertical_scroll_indicators' + | 'new_gif_player' | 'new_profile_scroll_component' | 'receive_updates' | 'show_follow_back_label_v2' diff --git a/src/lib/strings/embed-player.ts b/src/lib/strings/embed-player.ts index ee732847..bbc58a20 100644 --- a/src/lib/strings/embed-player.ts +++ b/src/lib/strings/embed-player.ts @@ -1,4 +1,5 @@ import {Dimensions} from 'react-native' + import {isWeb} from 'platform/detection' const {height: SCREEN_HEIGHT} = Dimensions.get('window') @@ -60,6 +61,10 @@ export interface EmbedPlayerParams { source: EmbedPlayerSource metaUri?: string hideDetails?: boolean + dimensions?: { + height: number + width: number + } } const giphyRegex = /media(?:[0-4]\.giphy\.com|\.giphy\.com)/i @@ -250,6 +255,16 @@ export function parseEmbedPlayerFromUrl( if (urlp.hostname === 'giphy.com' || urlp.hostname === 'www.giphy.com') { const [_, gifs, nameAndId] = urlp.pathname.split('/') + const h = urlp.searchParams.get('hh') + const w = urlp.searchParams.get('ww') + let dimensions + if (h && w) { + dimensions = { + height: Number(h), + width: Number(w), + } + } + /* * nameAndId is a string that consists of the name (dash separated) and the id of the gif (the last part of the name) * We want to get the id of the gif, then direct to media.giphy.com/media/{id}/giphy.webp so we can @@ -266,7 +281,10 @@ export function parseEmbedPlayerFromUrl( isGif: true, hideDetails: true, metaUri: `https://giphy.com/gifs/${gifId}`, - playerUri: `https://i.giphy.com/media/${gifId}/giphy.webp`, + playerUri: `https://i.giphy.com/media/${gifId}/${ + dimensions ? '200.mp4' : '200.webp' + }`, + dimensions, } } } @@ -287,7 +305,7 @@ export function parseEmbedPlayerFromUrl( isGif: true, hideDetails: true, metaUri: `https://giphy.com/gifs/${trackingOrId}`, - playerUri: `https://i.giphy.com/media/${trackingOrId}/giphy.webp`, + playerUri: `https://i.giphy.com/media/${trackingOrId}/200.webp`, } } else if (filename && gifFilenameRegex.test(filename)) { return { @@ -296,7 +314,7 @@ export function parseEmbedPlayerFromUrl( isGif: true, hideDetails: true, metaUri: `https://giphy.com/gifs/${idOrFilename}`, - playerUri: `https://i.giphy.com/media/${idOrFilename}/giphy.webp`, + playerUri: `https://i.giphy.com/media/${idOrFilename}/200.webp`, } } } @@ -315,7 +333,7 @@ export function parseEmbedPlayerFromUrl( isGif: true, hideDetails: true, metaUri: `https://giphy.com/gifs/${gifId}`, - playerUri: `https://i.giphy.com/media/${gifId}/giphy.webp`, + playerUri: `https://i.giphy.com/media/${gifId}/200.webp`, } } else if (mediaOrFilename) { const gifId = mediaOrFilename.split('.')[0] @@ -327,7 +345,7 @@ export function parseEmbedPlayerFromUrl( metaUri: `https://giphy.com/gifs/${gifId}`, playerUri: `https://i.giphy.com/media/${ mediaOrFilename.split('.')[0] - }/giphy.webp`, + }/200.webp`, } } } diff --git a/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx b/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx index aaa98a41..ff7c643f 100644 --- a/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx +++ b/src/view/com/util/post-embeds/ExternalLinkEmbed.tsx @@ -1,15 +1,17 @@ import React from 'react' -import {Image} from 'expo-image' -import {Text} from '../text/Text' import {StyleSheet, View} from 'react-native' +import {Image} from 'expo-image' +import {AppBskyEmbedExternal} from '@atproto/api' + import {usePalette} from 'lib/hooks/usePalette' import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries' -import {AppBskyEmbedExternal} from '@atproto/api' -import {toNiceDomain} from 'lib/strings/url-helpers' +import {useGate} from 'lib/statsig/statsig' import {parseEmbedPlayerFromUrl} from 'lib/strings/embed-player' -import {ExternalPlayer} from 'view/com/util/post-embeds/ExternalPlayerEmbed' -import {ExternalGifEmbed} from 'view/com/util/post-embeds/ExternalGifEmbed' +import {toNiceDomain} from 'lib/strings/url-helpers' import {useExternalEmbedsPrefs} from 'state/preferences' +import {ExternalGifEmbed} from 'view/com/util/post-embeds/ExternalGifEmbed' +import {ExternalPlayer} from 'view/com/util/post-embeds/ExternalPlayerEmbed' +import {Text} from '../text/Text' export const ExternalLinkEmbed = ({ link, @@ -19,6 +21,7 @@ export const ExternalLinkEmbed = ({ const pal = usePalette('default') const {isMobile} = useWebMediaQueries() const externalEmbedPrefs = useExternalEmbedsPrefs() + const gate = useGate() const embedPlayerParams = React.useMemo(() => { const params = parseEmbedPlayerFromUrl(link.uri) @@ -27,6 +30,10 @@ export const ExternalLinkEmbed = ({ return params } }, [link.uri, externalEmbedPrefs]) + const isCompatibleGiphy = + embedPlayerParams?.source === 'giphy' && + embedPlayerParams.dimensions && + gate('new_gif_player') return ( @@ -37,20 +44,24 @@ export const ExternalLinkEmbed = ({ accessibilityIgnoresInvertColors /> ) : undefined} - {(embedPlayerParams?.isGif && ( + {isCompatibleGiphy ? ( + + ) : embedPlayerParams?.isGif ? ( - )) || - (embedPlayerParams && ( - - ))} + ) : embedPlayerParams ? ( + + ) : undefined} - - {toNiceDomain(link.uri)} - - {!embedPlayerParams?.isGif && ( + {!isCompatibleGiphy && ( + + {toNiceDomain(link.uri)} + + )} + + {!embedPlayerParams?.isGif && !embedPlayerParams?.dimensions && ( {link.title || link.uri}