about summary refs log tree commit diff
path: root/bskyembed
diff options
context:
space:
mode:
authorSamuel Newman <mozzius@protonmail.com>2024-08-14 21:01:59 +0100
committerGitHub <noreply@github.com>2024-08-14 21:01:59 +0100
commitb6fa0d2d048b3c68d47d6fe502ca1b52096eb4c9 (patch)
treef9085702a4aa0f7bff0b568e2fef4c590f248289 /bskyembed
parent21e214c23579e5ca45fed3ec563d4010e37562a2 (diff)
downloadvoidsky-b6fa0d2d048b3c68d47d6fe502ca1b52096eb4c9.tar.zst
[Embed] Starter pack embed embed (#4935)
* update @atproto/api

* add starter pack embed

* update depreciated BskyAgent to AtpAgent

* unrelated, but avoid direct import of type

* nits

* rm commented out code

---------

Co-authored-by: Samuel Newman <10959775+mozzius@users.noreply.github.com>
Diffstat (limited to 'bskyembed')
-rw-r--r--bskyembed/.eslintrc5
-rw-r--r--bskyembed/assets/starterPack.svg1
-rw-r--r--bskyembed/package.json2
-rw-r--r--bskyembed/src/components/embed.tsx92
-rw-r--r--bskyembed/src/components/post.tsx5
-rw-r--r--bskyembed/src/screens/post.tsx4
-rw-r--r--bskyembed/yarn.lock66
7 files changed, 133 insertions, 42 deletions
diff --git a/bskyembed/.eslintrc b/bskyembed/.eslintrc
index e6e575a11..2b290d581 100644
--- a/bskyembed/.eslintrc
+++ b/bskyembed/.eslintrc
@@ -10,11 +10,12 @@
   ],
   "rules": {
     "simple-import-sort/imports": "warn",
-    "simple-import-sort/exports": "warn"
+    "simple-import-sort/exports": "warn",
+    'no-else-return': 'off'
   },
   "parserOptions": {
     "sourceType": "module",
     "ecmaVersion": "latest",
     "project": "./bskyembed/tsconfig.json"
   }
-}
\ No newline at end of file
+}
diff --git a/bskyembed/assets/starterPack.svg b/bskyembed/assets/starterPack.svg
new file mode 100644
index 000000000..eb8dd710f
--- /dev/null
+++ b/bskyembed/assets/starterPack.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24"><defs><linearGradient x1="0" y1="0" x2="100%" y2="0" gradientTransform="rotate(45)" id="sky_V5w1FF_xb91wVQ_1euhBX"><stop offset="0" stop-color="#0A7AFF"></stop><stop offset="1" stop-color="#59B9FF"></stop></linearGradient></defs><path fill="url(#sky_V5w1FF_xb91wVQ_1euhBX)" fill-rule="evenodd" clip-rule="evenodd" d="M11.26 5.227 5.02 6.899c-.734.197-1.17.95-.973 1.685l1.672 6.24c.197.734.951 1.17 1.685.973l6.24-1.672c.734-.197 1.17-.951.973-1.685L12.945 6.2a1.375 1.375 0 0 0-1.685-.973Zm-6.566.459a2.632 2.632 0 0 0-1.86 3.223l1.672 6.24a2.632 2.632 0 0 0 3.223 1.861l6.24-1.672a2.631 2.631 0 0 0 1.861-3.223l-1.672-6.24a2.632 2.632 0 0 0-3.223-1.861l-6.24 1.672Z"></path><path fill="url(#sky_V5w1FF_xb91wVQ_1euhBX)" fill-rule="evenodd" clip-rule="evenodd" d="M15.138 18.411a4.606 4.606 0 1 0 0-9.211 4.606 4.606 0 0 0 0 9.211Zm0 1.257a5.862 5.862 0 1 0 0-11.724 5.862 5.862 0 0 0 0 11.724Z"></path></svg>
diff --git a/bskyembed/package.json b/bskyembed/package.json
index f610e8c06..cb9a46213 100644
--- a/bskyembed/package.json
+++ b/bskyembed/package.json
@@ -9,7 +9,7 @@
     "lint": "eslint --cache --ext .js,.jsx,.ts,.tsx src"
   },
   "dependencies": {
-    "@atproto/api": "^0.12.2",
+    "@atproto/api": "0.13.1",
     "@preact/preset-vite": "^2.8.2",
     "@vitejs/plugin-legacy": "^5.3.2",
     "preact": "^10.4.8",
diff --git a/bskyembed/src/components/embed.tsx b/bskyembed/src/components/embed.tsx
index 1dadfee38..600c7c2c3 100644
--- a/bskyembed/src/components/embed.tsx
+++ b/bskyembed/src/components/embed.tsx
@@ -6,12 +6,15 @@ import {
   AppBskyFeedDefs,
   AppBskyFeedPost,
   AppBskyGraphDefs,
+  AppBskyGraphStarterpack,
   AppBskyLabelerDefs,
+  AtUri,
 } from '@atproto/api'
 import {ComponentChildren, h} from 'preact'
 import {useMemo} from 'preact/hooks'
 
 import infoIcon from '../../assets/circleInfo_stroke2_corner0_rounded.svg'
+import starterPackIcon from '../../assets/starterPack.svg'
 import {CONTENT_LABELS, labelsToInfo} from '../labels'
 import {getRkey} from '../utils'
 import {Link} from './link'
@@ -105,7 +108,7 @@ export function Embed({
       // Case 3.2: List
       if (AppBskyGraphDefs.isListView(record)) {
         return (
-          <GenericWithImage
+          <GenericWithImageEmbed
             image={record.avatar}
             title={record.name}
             href={`/profile/${record.creator.did}/lists/${getRkey(record)}`}
@@ -122,7 +125,7 @@ export function Embed({
       // Case 3.3: Feed
       if (AppBskyFeedDefs.isGeneratorView(record)) {
         return (
-          <GenericWithImage
+          <GenericWithImageEmbed
             image={record.avatar}
             title={record.displayName}
             href={`/profile/${record.creator.did}/feed/${getRkey(record)}`}
@@ -134,28 +137,27 @@ export function Embed({
 
       // Case 3.4: Labeler
       if (AppBskyLabelerDefs.isLabelerView(record)) {
-        return (
-          <GenericWithImage
-            image={record.creator.avatar}
-            title={record.creator.displayName || record.creator.handle}
-            href={`/profile/${record.creator.did}`}
-            subtitle="Labeler"
-            description={`Liked by ${record.likeCount ?? 0} users`}
-          />
-        )
+        // Embed type does not exist in the app, so show nothing
+        return null
+      }
+
+      // Case 3.5: Starter pack
+      if (AppBskyGraphDefs.isStarterPackViewBasic(record)) {
+        return <StarterPackEmbed content={record} />
       }
 
-      // Case 3.5: Post not found
+      // Case 3.6: Post not found
       if (AppBskyEmbedRecord.isViewNotFound(record)) {
         return <Info>Quoted post not found, it may have been deleted.</Info>
       }
 
-      // Case 3.6: Post blocked
+      // Case 3.7: Post blocked
       if (AppBskyEmbedRecord.isViewBlocked(record)) {
         return <Info>The quoted post is blocked.</Info>
       }
 
-      throw new Error('Unknown embed type')
+      // Unknown embed type
+      return null
     }
 
     // Case 4: Record with media
@@ -182,7 +184,8 @@ export function Embed({
       )
     }
 
-    throw new Error('Unsupported embed type')
+    // Unknown embed type
+    return null
   } catch (err) {
     return (
       <Info>{err instanceof Error ? err.message : 'An error occurred'}</Info>
@@ -314,7 +317,7 @@ function ExternalEmbed({
   )
 }
 
-function GenericWithImage({
+function GenericWithImageEmbed({
   title,
   subtitle,
   href,
@@ -350,3 +353,60 @@ function GenericWithImage({
     </Link>
   )
 }
+
+function StarterPackEmbed({
+  content,
+}: {
+  content: AppBskyGraphDefs.StarterPackViewBasic
+}) {
+  if (!AppBskyGraphStarterpack.isRecord(content.record)) {
+    return null
+  }
+
+  const starterPackHref = getStarterPackHref(content)
+  const imageUri = getStarterPackImage(content)
+
+  return (
+    <Link
+      href={starterPackHref}
+      className="w-full rounded-lg overflow-hidden border flex flex-col items-stretch">
+      <img src={imageUri} className="aspect-[1.91/1] object-cover" />
+      <div className="py-3 px-4">
+        <div className="flex space-x-2 items-center">
+          <img src={starterPackIcon} className="w-10 h-10" />
+          <div>
+            <p className="font-semibold leading-[21px]">
+              {content.record.name}
+            </p>
+            <p className="text-sm text-textLight line-clamp-2 leading-[18px]">
+              Starter pack by{' '}
+              {content.creator.displayName || `@${content.creator.handle}`}
+            </p>
+          </div>
+        </div>
+        {content.record.description && (
+          <p className="text-sm mt-1">{content.record.description}</p>
+        )}
+        {!!content.joinedAllTimeCount && content.joinedAllTimeCount > 50 && (
+          <p className="text-sm font-semibold text-textLight mt-1">
+            {content.joinedAllTimeCount} users have joined!
+          </p>
+        )}
+      </div>
+    </Link>
+  )
+}
+
+// from #/lib/strings/starter-pack.ts
+function getStarterPackImage(starterPack: AppBskyGraphDefs.StarterPackView) {
+  const rkey = new AtUri(starterPack.uri).rkey
+  return `https://ogcard.cdn.bsky.app/start/${starterPack.creator.did}/${rkey}`
+}
+
+function getStarterPackHref(
+  starterPack: AppBskyGraphDefs.StarterPackViewBasic,
+) {
+  const rkey = new AtUri(starterPack.uri).rkey
+  const handleOrDid = starterPack.creator.handle || starterPack.creator.did
+  return `/starter-pack/${handleOrDid}/${rkey}`
+}
diff --git a/bskyembed/src/components/post.tsx b/bskyembed/src/components/post.tsx
index d23c84cbf..1d1e8f4d8 100644
--- a/bskyembed/src/components/post.tsx
+++ b/bskyembed/src/components/post.tsx
@@ -132,7 +132,10 @@ function PostContent({record}: {record: AppBskyFeedPost.Record | null}) {
           key={counter}
           href={segment.link.uri}
           className="text-blue-400 hover:underline"
-          disableTracking={!segment.link.uri.startsWith('https://bsky.app')}>
+          disableTracking={
+            !segment.link.uri.startsWith('https://bsky.app') &&
+            !segment.link.uri.startsWith('https://go.bsky.app')
+          }>
           {segment.text}
         </Link>,
       )
diff --git a/bskyembed/src/screens/post.tsx b/bskyembed/src/screens/post.tsx
index 337bf0100..6ccf10a79 100644
--- a/bskyembed/src/screens/post.tsx
+++ b/bskyembed/src/screens/post.tsx
@@ -1,6 +1,6 @@
 import '../index.css'
 
-import {AppBskyFeedDefs, BskyAgent} from '@atproto/api'
+import {AppBskyFeedDefs, AtpAgent} from '@atproto/api'
 import {h, render} from 'preact'
 
 import logo from '../../assets/logo.svg'
@@ -12,7 +12,7 @@ import {getRkey} from '../utils'
 const root = document.getElementById('app')
 if (!root) throw new Error('No root element')
 
-const agent = new BskyAgent({
+const agent = new AtpAgent({
   service: 'https://public.api.bsky.app',
 })
 
diff --git a/bskyembed/yarn.lock b/bskyembed/yarn.lock
index 60efe3684..ca52dc074 100644
--- a/bskyembed/yarn.lock
+++ b/bskyembed/yarn.lock
@@ -20,15 +20,16 @@
     "@jridgewell/gen-mapping" "^0.3.5"
     "@jridgewell/trace-mapping" "^0.3.24"
 
-"@atproto/api@^0.12.2":
-  version "0.12.2"
-  resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.12.2.tgz#5df6d4f60dea0395c84fdebd9e81a7e853edf130"
-  integrity sha512-UVzCiDZH2j0wrr/O8nb1edD5cYLVqB5iujueXUCbHS3rAwIxgmyLtA3Hzm2QYsGPo/+xsIg1fNvpq9rNT6KWUA==
+"@atproto/api@0.13.1":
+  version "0.13.1"
+  resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.13.1.tgz#fbf4306e4465d5467aaf031308c1b47dcc8039d0"
+  integrity sha512-DL3iBfavn8Nnl48FmnAreQB0k0cIkW531DJ5JAHUCQZo10Nq0ZLk2/WFxcs0KuBG5wuLnGUdo+Y6/GQPVq8dYw==
   dependencies:
     "@atproto/common-web" "^0.3.0"
-    "@atproto/lexicon" "^0.4.0"
+    "@atproto/lexicon" "^0.4.1"
     "@atproto/syntax" "^0.3.0"
-    "@atproto/xrpc" "^0.5.0"
+    "@atproto/xrpc" "^0.6.0"
+    await-lock "^2.2.2"
     multiformats "^9.9.0"
     tlds "^1.234.0"
 
@@ -42,29 +43,29 @@
     uint8arrays "3.0.0"
     zod "^3.21.4"
 
-"@atproto/lexicon@^0.4.0":
-  version "0.4.0"
-  resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.0.tgz#63e8829945d80c25524882caa8ed27b1151cc576"
-  integrity sha512-RvCBKdSI4M8qWm5uTNz1z3R2yIvIhmOsMuleOj8YR6BwRD+QbtUBy3l+xQ7iXf4M5fdfJFxaUNa6Ty0iRwdKqQ==
+"@atproto/lexicon@^0.4.1":
+  version "0.4.1"
+  resolved "https://registry.yarnpkg.com/@atproto/lexicon/-/lexicon-0.4.1.tgz#19155210570a2fafbcc7d4f655d9b813948e72a0"
+  integrity sha512-bzyr+/VHXLQWbumViX5L7h1NKQObfs8Z+XZJl43OUK8nYFUI4e/sW1IZKRNfw7Wvi5YVNK+J+yP3DWIBZhkCYA==
   dependencies:
     "@atproto/common-web" "^0.3.0"
     "@atproto/syntax" "^0.3.0"
     iso-datestring-validator "^2.2.2"
     multiformats "^9.9.0"
-    zod "^3.21.4"
+    zod "^3.23.8"
 
 "@atproto/syntax@^0.3.0":
   version "0.3.0"
   resolved "https://registry.yarnpkg.com/@atproto/syntax/-/syntax-0.3.0.tgz#fafa2dbea9add37253005cb663e7373e05e618b3"
   integrity sha512-Weq0ZBxffGHDXHl9U7BQc2BFJi/e23AL+k+i5+D9hUq/bzT4yjGsrCejkjq0xt82xXDjmhhvQSZ0LqxyZ5woxA==
 
-"@atproto/xrpc@^0.5.0":
-  version "0.5.0"
-  resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.5.0.tgz#dacbfd8f7b13f0ab5bd56f8fdd4b460e132a6032"
-  integrity sha512-swu+wyOLvYW4l3n+VAuJbHcPcES+tin2Lsrp8Bw5aIXIICiuFn1YMFlwK9JwVUzTH21Py1s1nHEjr4CJeElJog==
+"@atproto/xrpc@^0.6.0":
+  version "0.6.0"
+  resolved "https://registry.yarnpkg.com/@atproto/xrpc/-/xrpc-0.6.0.tgz#668c3262e67e2afa65951ea79a03bfe3720ddf5c"
+  integrity sha512-5BbhBTv5j6MC3iIQ4+vYxQE7nLy2dDGQ+LYJrH8PptOCUdq0Pwg6aRccQ3y52kUZlhE/mzOTZ8Ngiy9pSAyfVQ==
   dependencies:
-    "@atproto/lexicon" "^0.4.0"
-    zod "^3.21.4"
+    "@atproto/lexicon" "^0.4.1"
+    zod "^3.23.8"
 
 "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2":
   version "7.24.2"
@@ -1710,6 +1711,11 @@ available-typed-arrays@^1.0.7:
   dependencies:
     possible-typed-array-names "^1.0.0"
 
+await-lock@^2.2.2:
+  version "2.2.2"
+  resolved "https://registry.yarnpkg.com/await-lock/-/await-lock-2.2.2.tgz#a95a9b269bfd2f69d22b17a321686f551152bcef"
+  integrity sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==
+
 babel-plugin-polyfill-corejs2@^0.4.10:
   version "0.4.10"
   resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz#276f41710b03a64f6467433cab72cbc2653c38b1"
@@ -3730,8 +3736,16 @@ stack-trace@^1.0.0-pre2:
   resolved "https://registry.yarnpkg.com/stack-trace/-/stack-trace-1.0.0-pre2.tgz#46a83a79f1b287807e9aaafc6a5dd8bcde626f9c"
   integrity sha512-2ztBJRek8IVofG9DBJqdy2N5kulaacX30Nz7xmkYF6ale9WBVmIy6mFBchvGX7Vx/MyjBhx+Rcxqrj+dbOnQ6A==
 
-"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0:
-  name string-width-cjs
+"string-width-cjs@npm:string-width@^4.2.0":
+  version "4.2.3"
+  resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
+  integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
+  dependencies:
+    emoji-regex "^8.0.0"
+    is-fullwidth-code-point "^3.0.0"
+    strip-ansi "^6.0.1"
+
+string-width@^4.1.0:
   version "4.2.3"
   resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010"
   integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -3795,7 +3809,14 @@ string.prototype.trimstart@^1.0.8:
     define-properties "^1.2.1"
     es-object-atoms "^1.0.0"
 
-"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1:
+"strip-ansi-cjs@npm:strip-ansi@^6.0.1":
+  version "6.0.1"
+  resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
+  integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
+  dependencies:
+    ansi-regex "^5.0.1"
+
+strip-ansi@^6.0.0, strip-ansi@^6.0.1:
   version "6.0.1"
   resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9"
   integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==
@@ -4192,3 +4213,8 @@ zod@^3.21.4:
   version "3.22.4"
   resolved "https://registry.yarnpkg.com/zod/-/zod-3.22.4.tgz#f31c3a9386f61b1f228af56faa9255e845cf3fff"
   integrity sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==
+
+zod@^3.23.8:
+  version "3.23.8"
+  resolved "https://registry.yarnpkg.com/zod/-/zod-3.23.8.tgz#e37b957b5d52079769fb8097099b592f0ef4067d"
+  integrity sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==