* ios player autoplay after recycle remove all items from AVPlayer queue recurururururursion use managers in the view add prefetch make sure player items stay in order add controller and item managers start of the view create module, ios * android player smoother basic caching prep cache somewhat works backup other files android impl blegh lets go touchup add prefetch to js use caching * bogus testing commit * add dims to type * save * add the dimensions to the embed info * add a new case * add a new case * limit this case to giphy * use gate * Revert "bogus testing commit" This reverts commit b3c8751b71f7108de9aa843b22ded4e0249fa854. * add web player base * flip mp4/webp * basic mp4 player for web * move some stuff into `ExternalLinkEmbed` instead * use a class component for web * remove extra component * add `onPlayerStateChange` event type on web * layer properly * fix tests * add new test * about ready. native portions done, a few touch ups on web needed show placeholder on ios fix type rm log display thumbnail until video is ready to play add oncanplay, playsinline remove unused method add `isLoaded` change event release player when finished apply gc to the view cleanup logs android gc rm log automatic gc for assets make `nativeRef` private remove unnecessary `await` cleanup rev log only play on prepare whenever needed rm unused perfperfperf rm var comment + android width native height calculations rm pressable add event dispatcher on android add event dispatcher on ios * ready to test ios fix autoplay ios clean oops * autoplay on web * normalize across all platforms add check for `ALT:` separate gif embed logic to another file handle permissions requests flatten web styles normalize styles normalize styles prefetch functions pause animatable on foreground android nits one more oops idk where that code went lint rethink the usage wrap up android clear bg update gradle more android rename dir update android namespace web ios add deps use webp rm unused update types use webp on mobile * rm gate from types * remove unused event param * only start placeholder op if doesn't exist in disk cache * fix gifs animating on app resume android * remove comment * add `isLoaded` for ios * add `isLoaded` to Android * onload for web * add visual loading state * rm a log * implement isloaded for android * dialogs * replace `webpSource` with `source` * update prop name * Move to Tenor for GIFs (#3654) * update some urls * right order for dimensions * add GIF coder for ios * remove giphy check * rewrite tenor urls * remove all the unnecessary stuff for consent * rm print * rm log * check if id and filename are strings * full size playback controls * pass tests * add accessibility to gifs * use `onPlay` and `onPause` * rm unused logic for description * add accessibility label to the controls * add gif into to external embed in composer * make it optional * gif dimensions * make the jsx look nicer --------- Co-authored-by: Dan Abramov <dan.abramov@gmail.com> Co-authored-by: Samuel Newman <mozzius@protonmail.com>
772 lines
22 KiB
TypeScript
772 lines
22 KiB
TypeScript
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,
|
|
toShareUrl,
|
|
toShortUrl,
|
|
} from '../../src/lib/strings/url-helpers'
|
|
|
|
describe('detectLinkables', () => {
|
|
const inputs = [
|
|
'no linkable',
|
|
'@start middle end',
|
|
'start @middle end',
|
|
'start middle @end',
|
|
'@start @middle @end',
|
|
'@full123.test-of-chars',
|
|
'not@right',
|
|
'@bad!@#$chars',
|
|
'@newline1\n@newline2',
|
|
'parenthetical (@handle)',
|
|
'start https://middle.com end',
|
|
'start https://middle.com/foo/bar end',
|
|
'start https://middle.com/foo/bar?baz=bux end',
|
|
'start https://middle.com/foo/bar?baz=bux#hash end',
|
|
'https://start.com/foo/bar?baz=bux#hash middle end',
|
|
'start middle https://end.com/foo/bar?baz=bux#hash',
|
|
'https://newline1.com\nhttps://newline2.com',
|
|
'start middle.com end',
|
|
'start middle.com/foo/bar end',
|
|
'start middle.com/foo/bar?baz=bux end',
|
|
'start middle.com/foo/bar?baz=bux#hash end',
|
|
'start.com/foo/bar?baz=bux#hash middle end',
|
|
'start middle end.com/foo/bar?baz=bux#hash',
|
|
'newline1.com\nnewline2.com',
|
|
'not.. a..url ..here',
|
|
'e.g.',
|
|
'e.g. real.com fake.notreal',
|
|
'something-cool.jpg',
|
|
'website.com.jpg',
|
|
'e.g./foo',
|
|
'website.com.jpg/foo',
|
|
'Classic article https://socket3.wordpress.com/2018/02/03/designing-windows-95s-user-interface/',
|
|
'Classic article https://socket3.wordpress.com/2018/02/03/designing-windows-95s-user-interface/ ',
|
|
'https://foo.com https://bar.com/whatever https://baz.com',
|
|
'punctuation https://foo.com, https://bar.com/whatever; https://baz.com.',
|
|
'parenthetical (https://foo.com)',
|
|
'except for https://foo.com/thing_(cool)',
|
|
]
|
|
const outputs = [
|
|
['no linkable'],
|
|
[{link: '@start'}, ' middle end'],
|
|
['start ', {link: '@middle'}, ' end'],
|
|
['start middle ', {link: '@end'}],
|
|
[{link: '@start'}, ' ', {link: '@middle'}, ' ', {link: '@end'}],
|
|
[{link: '@full123.test-of-chars'}],
|
|
['not@right'],
|
|
[{link: '@bad'}, '!@#$chars'],
|
|
[{link: '@newline1'}, '\n', {link: '@newline2'}],
|
|
['parenthetical (', {link: '@handle'}, ')'],
|
|
['start ', {link: 'https://middle.com'}, ' end'],
|
|
['start ', {link: 'https://middle.com/foo/bar'}, ' end'],
|
|
['start ', {link: 'https://middle.com/foo/bar?baz=bux'}, ' end'],
|
|
['start ', {link: 'https://middle.com/foo/bar?baz=bux#hash'}, ' end'],
|
|
[{link: 'https://start.com/foo/bar?baz=bux#hash'}, ' middle end'],
|
|
['start middle ', {link: 'https://end.com/foo/bar?baz=bux#hash'}],
|
|
[{link: 'https://newline1.com'}, '\n', {link: 'https://newline2.com'}],
|
|
['start ', {link: 'middle.com'}, ' end'],
|
|
['start ', {link: 'middle.com/foo/bar'}, ' end'],
|
|
['start ', {link: 'middle.com/foo/bar?baz=bux'}, ' end'],
|
|
['start ', {link: 'middle.com/foo/bar?baz=bux#hash'}, ' end'],
|
|
[{link: 'start.com/foo/bar?baz=bux#hash'}, ' middle end'],
|
|
['start middle ', {link: 'end.com/foo/bar?baz=bux#hash'}],
|
|
[{link: 'newline1.com'}, '\n', {link: 'newline2.com'}],
|
|
['not.. a..url ..here'],
|
|
['e.g.'],
|
|
['e.g. ', {link: 'real.com'}, ' fake.notreal'],
|
|
['something-cool.jpg'],
|
|
['website.com.jpg'],
|
|
['e.g./foo'],
|
|
['website.com.jpg/foo'],
|
|
[
|
|
'Classic article ',
|
|
{
|
|
link: 'https://socket3.wordpress.com/2018/02/03/designing-windows-95s-user-interface/',
|
|
},
|
|
],
|
|
[
|
|
'Classic article ',
|
|
{
|
|
link: 'https://socket3.wordpress.com/2018/02/03/designing-windows-95s-user-interface/',
|
|
},
|
|
' ',
|
|
],
|
|
[
|
|
{link: 'https://foo.com'},
|
|
' ',
|
|
{link: 'https://bar.com/whatever'},
|
|
' ',
|
|
{link: 'https://baz.com'},
|
|
],
|
|
[
|
|
'punctuation ',
|
|
{link: 'https://foo.com'},
|
|
', ',
|
|
{link: 'https://bar.com/whatever'},
|
|
'; ',
|
|
{link: 'https://baz.com'},
|
|
'.',
|
|
],
|
|
['parenthetical (', {link: 'https://foo.com'}, ')'],
|
|
['except for ', {link: 'https://foo.com/thing_(cool)'}],
|
|
]
|
|
it('correctly handles a set of text inputs', () => {
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
const input = inputs[i]
|
|
const output = detectLinkables(input)
|
|
expect(output).toEqual(outputs[i])
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('pluralize', () => {
|
|
const inputs: [number, string, string?][] = [
|
|
[1, 'follower'],
|
|
[1, 'member'],
|
|
[100, 'post'],
|
|
[1000, 'repost'],
|
|
[10000, 'upvote'],
|
|
[100000, 'other'],
|
|
[2, 'man', 'men'],
|
|
]
|
|
const outputs = [
|
|
'follower',
|
|
'member',
|
|
'posts',
|
|
'reposts',
|
|
'upvotes',
|
|
'others',
|
|
'men',
|
|
]
|
|
|
|
it('correctly pluralizes a set of words', () => {
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
const input = inputs[i]
|
|
const output = pluralize(...input)
|
|
expect(output).toEqual(outputs[i])
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('makeRecordUri', () => {
|
|
const inputs: [string, string, string][] = [
|
|
['alice.test', 'app.bsky.feed.post', '3jk7x4irgv52r'],
|
|
]
|
|
const outputs = ['at://alice.test/app.bsky.feed.post/3jk7x4irgv52r']
|
|
|
|
it('correctly builds a record URI', () => {
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
const input = inputs[i]
|
|
const result = makeRecordUri(...input)
|
|
expect(result).toEqual(outputs[i])
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('ago', () => {
|
|
const inputs = [
|
|
1671461038,
|
|
'04 Dec 1995 00:12:00 GMT',
|
|
new Date(),
|
|
new Date().setSeconds(new Date().getSeconds() - 10),
|
|
new Date().setMinutes(new Date().getMinutes() - 10),
|
|
new Date().setHours(new Date().getHours() - 1),
|
|
new Date().setDate(new Date().getDate() - 1),
|
|
new Date().setMonth(new Date().getMonth() - 1),
|
|
]
|
|
const outputs = [
|
|
new Date(1671461038).toLocaleDateString(),
|
|
new Date('04 Dec 1995 00:12:00 GMT').toLocaleDateString(),
|
|
'now',
|
|
'10s',
|
|
'10m',
|
|
'1h',
|
|
'1d',
|
|
'1mo',
|
|
]
|
|
|
|
it('correctly calculates how much time passed, in a string', () => {
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
const result = ago(inputs[i])
|
|
expect(result).toEqual(outputs[i])
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('makeValidHandle', () => {
|
|
const inputs = [
|
|
'test-handle-123',
|
|
'test!"#$%&/()=?_',
|
|
'this-handle-should-be-too-big',
|
|
]
|
|
const outputs = ['test-handle-123', 'test', 'this-handle-should-b']
|
|
|
|
it('correctly parses and corrects handles', () => {
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
const result = makeValidHandle(inputs[i])
|
|
expect(result).toEqual(outputs[i])
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('createFullHandle', () => {
|
|
const inputs: [string, string][] = [
|
|
['test-handle-123', 'test'],
|
|
['.test.handle', 'test.test.'],
|
|
['test.handle.', '.test.test'],
|
|
]
|
|
const outputs = [
|
|
'test-handle-123.test',
|
|
'.test.handle.test.test.',
|
|
'test.handle.test.test',
|
|
]
|
|
|
|
it('correctly parses and corrects handles', () => {
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
const input = inputs[i]
|
|
const result = createFullHandle(...input)
|
|
expect(result).toEqual(outputs[i])
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('enforceLen', () => {
|
|
const inputs: [string, number][] = [
|
|
['Hello World!', 5],
|
|
['Hello World!', 20],
|
|
['', 5],
|
|
]
|
|
const outputs = ['Hello', 'Hello World!', '']
|
|
|
|
it('correctly enforces defined length on a given string', () => {
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
const input = inputs[i]
|
|
const result = enforceLen(...input)
|
|
expect(result).toEqual(outputs[i])
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('cleanError', () => {
|
|
const inputs = [
|
|
'TypeError: Network request failed',
|
|
'Error: Aborted',
|
|
'Error: TypeError "x" is not a function',
|
|
'Error: SyntaxError unexpected token "export"',
|
|
'Some other error',
|
|
]
|
|
const outputs = [
|
|
'Unable to connect. Please check your internet connection and try again.',
|
|
'Unable to connect. Please check your internet connection and try again.',
|
|
'TypeError "x" is not a function',
|
|
'SyntaxError unexpected token "export"',
|
|
'Some other error',
|
|
]
|
|
|
|
it('removes extra content from error message', () => {
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
const result = cleanError(inputs[i])
|
|
expect(result).toEqual(outputs[i])
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('toNiceDomain', () => {
|
|
const inputs = [
|
|
'https://example.com/index.html',
|
|
'https://bsky.app',
|
|
'https://bsky.social',
|
|
'#123123123',
|
|
]
|
|
const outputs = ['example.com', 'bsky.app', 'Bluesky Social', '#123123123']
|
|
|
|
it("displays the url's host in a easily readable manner", () => {
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
const result = toNiceDomain(inputs[i])
|
|
expect(result).toEqual(outputs[i])
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('toShortUrl', () => {
|
|
const inputs = [
|
|
'https://bsky.app',
|
|
'https://bsky.app/3jk7x4irgv52r',
|
|
'https://bsky.app/3jk7x4irgv52r2313y182h9',
|
|
'https://very-long-domain-name.com/foo',
|
|
'https://very-long-domain-name.com/foo?bar=baz#andsomemore',
|
|
]
|
|
const outputs = [
|
|
'bsky.app',
|
|
'bsky.app/3jk7x4irgv52r',
|
|
'bsky.app/3jk7x4irgv52...',
|
|
'very-long-domain-name.com/foo',
|
|
'very-long-domain-name.com/foo?bar=baz#...',
|
|
]
|
|
|
|
it('shortens the url', () => {
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
const result = toShortUrl(inputs[i])
|
|
expect(result).toEqual(outputs[i])
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('toShareUrl', () => {
|
|
const inputs = ['https://bsky.app', '/3jk7x4irgv52r', 'item/test/123']
|
|
const outputs = [
|
|
'https://bsky.app',
|
|
'https://bsky.app/3jk7x4irgv52r',
|
|
'https://bsky.app/item/test/123',
|
|
]
|
|
|
|
it('appends https, when not present', () => {
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
const result = toShareUrl(inputs[i])
|
|
expect(result).toEqual(outputs[i])
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('shortenLinks', () => {
|
|
const inputs = [
|
|
'start https://middle.com/foo/bar?baz=bux#hash end',
|
|
'https://start.com/foo/bar?baz=bux#hash middle end',
|
|
'start middle https://end.com/foo/bar?baz=bux#hash',
|
|
'https://newline1.com/very/long/url/here\nhttps://newline2.com/very/long/url/here',
|
|
'Classic article https://socket3.wordpress.com/2018/02/03/designing-windows-95s-user-interface/',
|
|
]
|
|
const outputs = [
|
|
[
|
|
'start middle.com/foo/bar?baz=... end',
|
|
['https://middle.com/foo/bar?baz=bux#hash'],
|
|
],
|
|
[
|
|
'start.com/foo/bar?baz=... middle end',
|
|
['https://start.com/foo/bar?baz=bux#hash'],
|
|
],
|
|
[
|
|
'start middle end.com/foo/bar?baz=...',
|
|
['https://end.com/foo/bar?baz=bux#hash'],
|
|
],
|
|
[
|
|
'newline1.com/very/long/ur...\nnewline2.com/very/long/ur...',
|
|
[
|
|
'https://newline1.com/very/long/url/here',
|
|
'https://newline2.com/very/long/url/here',
|
|
],
|
|
],
|
|
[
|
|
'Classic article socket3.wordpress.com/2018/02/03/d...',
|
|
[
|
|
'https://socket3.wordpress.com/2018/02/03/designing-windows-95s-user-interface/',
|
|
],
|
|
],
|
|
]
|
|
|
|
it('correctly shortens rich text while preserving facet URIs', () => {
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
const input = inputs[i]
|
|
const inputRT = new RichText({text: input})
|
|
inputRT.detectFacetsWithoutResolution()
|
|
const outputRT = shortenLinks(inputRT)
|
|
expect(outputRT.text).toEqual(outputs[i][0])
|
|
expect(outputRT.facets?.length).toEqual(outputs[i][1].length)
|
|
for (let j = 0; j < outputs[i][1].length; j++) {
|
|
expect(outputRT.facets![j].features[0].uri).toEqual(outputs[i][1][j])
|
|
}
|
|
}
|
|
})
|
|
})
|
|
|
|
describe('parseEmbedPlayerFromUrl', () => {
|
|
const inputs = [
|
|
'https://youtu.be/videoId',
|
|
'https://www.youtube.com/watch?v=videoId',
|
|
'https://www.youtube.com/watch?v=videoId&feature=share',
|
|
'https://youtube.com/watch?v=videoId',
|
|
'https://youtube.com/watch?v=videoId&feature=share',
|
|
'https://youtube.com/shorts/videoId',
|
|
'https://m.youtube.com/watch?v=videoId',
|
|
|
|
'https://youtube.com/shorts/',
|
|
'https://youtube.com/',
|
|
'https://youtube.com/random',
|
|
|
|
'https://twitch.tv/channelName',
|
|
'https://www.twitch.tv/channelName',
|
|
'https://m.twitch.tv/channelName',
|
|
|
|
'https://twitch.tv/channelName/clip/clipId',
|
|
'https://twitch.tv/videos/videoId',
|
|
|
|
'https://open.spotify.com/playlist/playlistId',
|
|
'https://open.spotify.com/playlist/playlistId?param=value',
|
|
'https://open.spotify.com/locale/playlist/playlistId',
|
|
|
|
'https://open.spotify.com/track/songId',
|
|
'https://open.spotify.com/track/songId?param=value',
|
|
'https://open.spotify.com/locale/track/songId',
|
|
|
|
'https://open.spotify.com/album/albumId',
|
|
'https://open.spotify.com/album/albumId?param=value',
|
|
'https://open.spotify.com/locale/album/albumId',
|
|
|
|
'https://soundcloud.com/user/track',
|
|
'https://soundcloud.com/user/sets/set',
|
|
'https://soundcloud.com/user/',
|
|
|
|
'https://music.apple.com/us/playlist/playlistName/playlistId',
|
|
'https://music.apple.com/us/album/albumName/albumId',
|
|
'https://music.apple.com/us/album/albumName/albumId?i=songId',
|
|
|
|
'https://vimeo.com/videoId',
|
|
'https://vimeo.com/videoId?autoplay=0',
|
|
|
|
'https://giphy.com/gifs/some-random-gif-name-gifId',
|
|
'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',
|
|
'https://media2.giphy.com/media/gifId/giphy.webp',
|
|
'https://media3.giphy.com/media/gifId/giphy.mp4',
|
|
'https://media4.giphy.com/media/gifId/giphy.webp',
|
|
'https://media5.giphy.com/media/gifId/giphy.mp4',
|
|
'https://media0.giphy.com/media/gifId/giphy.mp3',
|
|
'https://media1.google.com/media/gifId/giphy.webp',
|
|
|
|
'https://media.giphy.com/media/trackingId/gifId/giphy.webp',
|
|
|
|
'https://i.giphy.com/media/gifId/giphy.webp',
|
|
'https://i.giphy.com/media/gifId/giphy.webp',
|
|
'https://i.giphy.com/gifId.gif',
|
|
'https://i.giphy.com/gifId.gif',
|
|
|
|
'https://tenor.com/view/gifId',
|
|
'https://tenor.com/notView/gifId',
|
|
'https://tenor.com/view',
|
|
'https://tenor.com/view/gifId.gif',
|
|
'https://tenor.com/intl/view/gifId.gif',
|
|
|
|
'https://media.tenor.com/someID_AAAAC/someName.gif?hh=100&ww=100',
|
|
'https://media.tenor.com/someID_AAAAC/someName.gif',
|
|
'https://media.tenor.com/someID/someName.gif',
|
|
'https://media.tenor.com/someID',
|
|
'https://media.tenor.com',
|
|
]
|
|
|
|
const outputs = [
|
|
{
|
|
type: 'youtube_video',
|
|
source: 'youtube',
|
|
playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0',
|
|
},
|
|
{
|
|
type: 'youtube_video',
|
|
source: 'youtube',
|
|
playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0',
|
|
},
|
|
{
|
|
type: 'youtube_video',
|
|
source: 'youtube',
|
|
playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0',
|
|
},
|
|
{
|
|
type: 'youtube_video',
|
|
source: 'youtube',
|
|
playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0',
|
|
},
|
|
{
|
|
type: 'youtube_video',
|
|
source: 'youtube',
|
|
playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0',
|
|
},
|
|
{
|
|
type: 'youtube_short',
|
|
source: 'youtubeShorts',
|
|
hideDetails: true,
|
|
playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0',
|
|
},
|
|
{
|
|
type: 'youtube_video',
|
|
source: 'youtube',
|
|
playerUri: 'https://bsky.app/iframe/youtube.html?videoId=videoId&start=0',
|
|
},
|
|
|
|
undefined,
|
|
undefined,
|
|
undefined,
|
|
|
|
{
|
|
type: 'twitch_video',
|
|
source: 'twitch',
|
|
playerUri: `https://player.twitch.tv/?volume=0.5&!muted&autoplay&channel=channelName&parent=localhost`,
|
|
},
|
|
{
|
|
type: 'twitch_video',
|
|
source: 'twitch',
|
|
playerUri: `https://player.twitch.tv/?volume=0.5&!muted&autoplay&channel=channelName&parent=localhost`,
|
|
},
|
|
{
|
|
type: 'twitch_video',
|
|
source: 'twitch',
|
|
playerUri: `https://player.twitch.tv/?volume=0.5&!muted&autoplay&channel=channelName&parent=localhost`,
|
|
},
|
|
{
|
|
type: 'twitch_video',
|
|
source: 'twitch',
|
|
playerUri: `https://clips.twitch.tv/embed?volume=0.5&autoplay=true&clip=clipId&parent=localhost`,
|
|
},
|
|
{
|
|
type: 'twitch_video',
|
|
source: 'twitch',
|
|
playerUri: `https://player.twitch.tv/?volume=0.5&!muted&autoplay&video=videoId&parent=localhost`,
|
|
},
|
|
|
|
{
|
|
type: 'spotify_playlist',
|
|
source: 'spotify',
|
|
playerUri: `https://open.spotify.com/embed/playlist/playlistId`,
|
|
},
|
|
{
|
|
type: 'spotify_playlist',
|
|
source: 'spotify',
|
|
playerUri: `https://open.spotify.com/embed/playlist/playlistId`,
|
|
},
|
|
{
|
|
type: 'spotify_playlist',
|
|
source: 'spotify',
|
|
playerUri: `https://open.spotify.com/embed/playlist/playlistId`,
|
|
},
|
|
|
|
{
|
|
type: 'spotify_song',
|
|
source: 'spotify',
|
|
playerUri: `https://open.spotify.com/embed/track/songId`,
|
|
},
|
|
{
|
|
type: 'spotify_song',
|
|
source: 'spotify',
|
|
playerUri: `https://open.spotify.com/embed/track/songId`,
|
|
},
|
|
{
|
|
type: 'spotify_song',
|
|
source: 'spotify',
|
|
playerUri: `https://open.spotify.com/embed/track/songId`,
|
|
},
|
|
|
|
{
|
|
type: 'spotify_album',
|
|
source: 'spotify',
|
|
playerUri: `https://open.spotify.com/embed/album/albumId`,
|
|
},
|
|
{
|
|
type: 'spotify_album',
|
|
source: 'spotify',
|
|
playerUri: `https://open.spotify.com/embed/album/albumId`,
|
|
},
|
|
{
|
|
type: 'spotify_album',
|
|
source: 'spotify',
|
|
playerUri: `https://open.spotify.com/embed/album/albumId`,
|
|
},
|
|
|
|
{
|
|
type: 'soundcloud_track',
|
|
source: 'soundcloud',
|
|
playerUri: `https://w.soundcloud.com/player/?url=https://soundcloud.com/user/track&auto_play=true&visual=false&hide_related=true`,
|
|
},
|
|
{
|
|
type: 'soundcloud_set',
|
|
source: 'soundcloud',
|
|
playerUri: `https://w.soundcloud.com/player/?url=https://soundcloud.com/user/sets/set&auto_play=true&visual=false&hide_related=true`,
|
|
},
|
|
undefined,
|
|
|
|
{
|
|
type: 'apple_music_playlist',
|
|
source: 'appleMusic',
|
|
playerUri:
|
|
'https://embed.music.apple.com/us/playlist/playlistName/playlistId',
|
|
},
|
|
{
|
|
type: 'apple_music_album',
|
|
source: 'appleMusic',
|
|
playerUri: 'https://embed.music.apple.com/us/album/albumName/albumId',
|
|
},
|
|
{
|
|
type: 'apple_music_song',
|
|
source: 'appleMusic',
|
|
playerUri:
|
|
'https://embed.music.apple.com/us/album/albumName/albumId?i=songId',
|
|
},
|
|
|
|
{
|
|
type: 'vimeo_video',
|
|
source: 'vimeo',
|
|
playerUri: 'https://player.vimeo.com/video/videoId?autoplay=1',
|
|
},
|
|
{
|
|
type: 'vimeo_video',
|
|
source: 'vimeo',
|
|
playerUri: 'https://player.vimeo.com/video/videoId?autoplay=1',
|
|
},
|
|
|
|
{
|
|
type: 'giphy_gif',
|
|
source: 'giphy',
|
|
isGif: true,
|
|
hideDetails: true,
|
|
metaUri: 'https://giphy.com/gifs/gifId',
|
|
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.webp',
|
|
},
|
|
{
|
|
type: 'giphy_gif',
|
|
source: 'giphy',
|
|
isGif: true,
|
|
hideDetails: true,
|
|
metaUri: 'https://giphy.com/gifs/gifId',
|
|
playerUri: 'https://i.giphy.com/media/gifId/200.webp',
|
|
},
|
|
{
|
|
type: 'giphy_gif',
|
|
source: 'giphy',
|
|
isGif: true,
|
|
hideDetails: true,
|
|
metaUri: 'https://giphy.com/gifs/gifId',
|
|
playerUri: 'https://i.giphy.com/media/gifId/200.webp',
|
|
},
|
|
{
|
|
type: 'giphy_gif',
|
|
source: 'giphy',
|
|
isGif: true,
|
|
hideDetails: true,
|
|
metaUri: 'https://giphy.com/gifs/gifId',
|
|
playerUri: 'https://i.giphy.com/media/gifId/200.webp',
|
|
},
|
|
{
|
|
type: 'giphy_gif',
|
|
source: 'giphy',
|
|
isGif: true,
|
|
hideDetails: true,
|
|
metaUri: 'https://giphy.com/gifs/gifId',
|
|
playerUri: 'https://i.giphy.com/media/gifId/200.webp',
|
|
},
|
|
{
|
|
type: 'giphy_gif',
|
|
source: 'giphy',
|
|
isGif: true,
|
|
hideDetails: true,
|
|
metaUri: 'https://giphy.com/gifs/gifId',
|
|
playerUri: 'https://i.giphy.com/media/gifId/200.webp',
|
|
},
|
|
{
|
|
type: 'giphy_gif',
|
|
source: 'giphy',
|
|
isGif: true,
|
|
hideDetails: true,
|
|
metaUri: 'https://giphy.com/gifs/gifId',
|
|
playerUri: 'https://i.giphy.com/media/gifId/200.webp',
|
|
},
|
|
undefined,
|
|
undefined,
|
|
undefined,
|
|
|
|
{
|
|
type: 'giphy_gif',
|
|
source: 'giphy',
|
|
isGif: true,
|
|
hideDetails: true,
|
|
metaUri: 'https://giphy.com/gifs/gifId',
|
|
playerUri: 'https://i.giphy.com/media/gifId/200.webp',
|
|
},
|
|
|
|
{
|
|
type: 'giphy_gif',
|
|
source: 'giphy',
|
|
isGif: true,
|
|
hideDetails: true,
|
|
metaUri: 'https://giphy.com/gifs/gifId',
|
|
playerUri: 'https://i.giphy.com/media/gifId/200.webp',
|
|
},
|
|
{
|
|
type: 'giphy_gif',
|
|
source: 'giphy',
|
|
isGif: true,
|
|
hideDetails: true,
|
|
metaUri: 'https://giphy.com/gifs/gifId',
|
|
playerUri: 'https://i.giphy.com/media/gifId/200.webp',
|
|
},
|
|
{
|
|
type: 'giphy_gif',
|
|
source: 'giphy',
|
|
isGif: true,
|
|
hideDetails: true,
|
|
metaUri: 'https://giphy.com/gifs/gifId',
|
|
playerUri: 'https://i.giphy.com/media/gifId/200.webp',
|
|
},
|
|
{
|
|
type: 'giphy_gif',
|
|
source: 'giphy',
|
|
isGif: true,
|
|
hideDetails: true,
|
|
metaUri: 'https://giphy.com/gifs/gifId',
|
|
playerUri: 'https://i.giphy.com/media/gifId/200.webp',
|
|
},
|
|
|
|
undefined,
|
|
undefined,
|
|
undefined,
|
|
undefined,
|
|
undefined,
|
|
|
|
{
|
|
type: 'tenor_gif',
|
|
source: 'tenor',
|
|
isGif: true,
|
|
hideDetails: true,
|
|
playerUri: 'https://t.gifs.bsky.app/someID_AAAAM/someName.gif',
|
|
dimensions: {
|
|
width: 100,
|
|
height: 100,
|
|
},
|
|
},
|
|
undefined,
|
|
undefined,
|
|
undefined,
|
|
undefined,
|
|
]
|
|
|
|
it('correctly grabs the correct id from uri', () => {
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
const input = inputs[i]
|
|
const output = outputs[i]
|
|
|
|
const res = parseEmbedPlayerFromUrl(input)
|
|
|
|
expect(res).toEqual(output)
|
|
}
|
|
})
|
|
})
|