An ATproto social media client -- with an independent Appview.

add video to embed (#5145)

authored by samuel.fm and committed by

GitHub 5dcb5201 fcf27f05

+48 -11
+1
bskyembed/assets/play_filled_corner2_rounded.svg
··· 1 + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><path fill="#fff" d="M9.576 2.534C7.578 1.299 5 2.737 5 5.086v13.828c0 2.35 2.578 3.787 4.576 2.552l11.194-6.914c1.899-1.172 1.899-3.932 0-5.104L9.576 2.534Z"/></svg>
+1 -1
bskyembed/package.json
··· 9 9 "lint": "eslint --cache --ext .js,.jsx,.ts,.tsx src" 10 10 }, 11 11 "dependencies": { 12 - "@atproto/api": "0.13.1", 12 + "@atproto/api": "0.13.6", 13 13 "@preact/preset-vite": "^2.8.2", 14 14 "@vitejs/plugin-legacy": "^5.3.2", 15 15 "preact": "^10.4.8",
+37 -1
bskyembed/src/components/embed.tsx
··· 3 3 AppBskyEmbedImages, 4 4 AppBskyEmbedRecord, 5 5 AppBskyEmbedRecordWithMedia, 6 + AppBskyEmbedVideo, 6 7 AppBskyFeedDefs, 7 8 AppBskyFeedPost, 8 9 AppBskyGraphDefs, ··· 14 15 import {useMemo} from 'preact/hooks' 15 16 16 17 import infoIcon from '../../assets/circleInfo_stroke2_corner0_rounded.svg' 18 + import playIcon from '../../assets/play_filled_corner2_rounded.svg' 17 19 import starterPackIcon from '../../assets/starterPack.svg' 18 20 import {CONTENT_LABELS, labelsToInfo} from '../labels' 19 21 import {getRkey} from '../utils' ··· 160 162 return null 161 163 } 162 164 163 - // Case 4: Record with media 165 + // Case 4: Video 166 + if (AppBskyEmbedVideo.isView(content)) { 167 + return <VideoEmbed content={content} /> 168 + } 169 + 170 + // Case 5: Record with media 164 171 if ( 165 172 AppBskyEmbedRecordWithMedia.isView(content) && 166 173 AppBskyEmbedRecord.isViewRecord(content.record.record) ··· 354 361 ) 355 362 } 356 363 364 + // just the thumbnail and a play button 365 + function VideoEmbed({content}: {content: AppBskyEmbedVideo.View}) { 366 + let aspectRatio = 1 367 + 368 + if (content.aspectRatio) { 369 + const {width, height} = content.aspectRatio 370 + aspectRatio = clamp(width / height, 1 / 1, 3 / 1) 371 + } 372 + 373 + return ( 374 + <div 375 + className="w-full overflow-hidden rounded-lg aspect-square" 376 + style={{aspectRatio: `${aspectRatio} / 1`}}> 377 + <img 378 + src={content.thumbnail} 379 + alt={content.alt} 380 + className="object-cover size-full" 381 + /> 382 + <div className="size-24 absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 rounded-full bg-black/50 flex items-center justify-center"> 383 + <img src={playIcon} className="object-cover size-3/5" /> 384 + </div> 385 + </div> 386 + ) 387 + } 388 + 357 389 function StarterPackEmbed({ 358 390 content, 359 391 }: { ··· 410 442 const handleOrDid = starterPack.creator.handle || starterPack.creator.did 411 443 return `/starter-pack/${handleOrDid}/${rkey}` 412 444 } 445 + 446 + function clamp(num: number, min: number, max: number) { 447 + return Math.max(min, Math.min(num, max)) 448 + }
+9 -9
bskyembed/yarn.lock
··· 20 20 "@jridgewell/gen-mapping" "^0.3.5" 21 21 "@jridgewell/trace-mapping" "^0.3.24" 22 22 23 - "@atproto/api@0.13.1": 24 - version "0.13.1" 25 - resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.1.tgz#fbf4306e4465d5467aaf031308c1b47dcc8039d0" 26 - integrity sha512-DL3iBfavn8Nnl48FmnAreQB0k0cIkW531DJ5JAHUCQZo10Nq0ZLk2/WFxcs0KuBG5wuLnGUdo+Y6/GQPVq8dYw== 23 + "@atproto/api@0.13.6": 24 + version "0.13.6" 25 + resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.6.tgz#2500e9d7143e6718089632300c42ce50149f8cd5" 26 + integrity sha512-58emFFZhqY8nVWD3xFWK0yYqAmJ2un+NaTtZxBbRo00mGq1rz9VXTpVmfoHFcuXL1hoDQN3WyJfsub8r6xGOgg== 27 27 dependencies: 28 28 "@atproto/common-web" "^0.3.0" 29 29 "@atproto/lexicon" "^0.4.1" 30 30 "@atproto/syntax" "^0.3.0" 31 - "@atproto/xrpc" "^0.6.0" 31 + "@atproto/xrpc" "^0.6.1" 32 32 await-lock "^2.2.2" 33 33 multiformats "^9.9.0" 34 34 tlds "^1.234.0" ··· 59 59 resolved "https://registry.yarnpkg.com/@atproto/syntax/-/syntax-0.3.0.tgz#fafa2dbea9add37253005cb663e7373e05e618b3" 60 60 integrity sha512-Weq0ZBxffGHDXHl9U7BQc2BFJi/e23AL+k+i5+D9hUq/bzT4yjGsrCejkjq0xt82xXDjmhhvQSZ0LqxyZ5woxA== 61 61 62 - "@atproto/xrpc@^0.6.0": 63 - version "0.6.0" 64 - resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.6.0.tgz#668c3262e67e2afa65951ea79a03bfe3720ddf5c" 65 - integrity sha512-5BbhBTv5j6MC3iIQ4+vYxQE7nLy2dDGQ+LYJrH8PptOCUdq0Pwg6aRccQ3y52kUZlhE/mzOTZ8Ngiy9pSAyfVQ== 62 + "@atproto/xrpc@^0.6.1": 63 + version "0.6.1" 64 + resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.6.1.tgz#dcd1315c8c60eef5af2db7fa4e35a38ebc6d79d5" 65 + integrity sha512-Zy5ydXEdk6sY7FDUZcEVfCL1jvbL4tXu5CcdPqbEaW6LQtk9GLds/DK1bCX9kswTGaBC88EMuqQMfkxOhp2t4A== 66 66 dependencies: 67 67 "@atproto/lexicon" "^0.4.1" 68 68 zod "^3.23.8"