diff --git a/bskyembed/README.md b/bskyembed/README.md new file mode 100644 index 0000000000..fe81026f11 --- /dev/null +++ b/bskyembed/README.md @@ -0,0 +1,26 @@ +## Run / Test + +Install dependencies: + +```bash +cd bskyembed +yarn +``` + +Run the dev server: + +```bash +yarn dev +``` + +You can see the embed homepage at http://localhost:5173 + +### Testbed + +In another terminal window, run the snippet dev script: + +```bash +yarn dev-snippet +``` + +You can then see the testbed page at http://localhost:5173/test diff --git a/bskyembed/package.json b/bskyembed/package.json index c47c4218da..65bed99bae 100644 --- a/bskyembed/package.json +++ b/bskyembed/package.json @@ -4,6 +4,7 @@ "type": "module", "scripts": { "dev": "vite", + "dev-snippet": "tsc --project tsconfig.snippet.json && serve -s dist -p 3000 -n", "build": "tsc && vite build", "build-snippet": "tsc --project tsconfig.snippet.json", "lint": "eslint --cache --ext .js,.jsx,.ts,.tsx src", @@ -21,6 +22,7 @@ "eslint-config-preact": "^1.3.0", "eslint-plugin-simple-import-sort": "^12.0.0", "postcss": "^8.4.38", + "serve": "^14.2.5", "tailwindcss": "^3.4.3", "terser": "^5.43.1", "typescript": "^5.8.3", diff --git a/bskyembed/snippet/embed.ts b/bskyembed/snippet/embed.ts index 5cd86ed987..f863f59f38 100644 --- a/bskyembed/snippet/embed.ts +++ b/bskyembed/snippet/embed.ts @@ -3,9 +3,19 @@ interface Window { bluesky: { scan: (element?: Pick) => void } + BSKY_DEV_EMBED_URL?: string } -const EMBED_URL = 'https://embed.bsky.app' +/** + * Allow url to be overwritten during development + */ +const IS_DEV = + window.location.protocol === 'file:' || + window.location.hostname === 'localhost' +const EMBED_URL = + IS_DEV && window.BSKY_DEV_EMBED_URL + ? window.BSKY_DEV_EMBED_URL + : 'https://embed.bsky.app' window.bluesky = window.bluesky || { scan, diff --git a/bskyembed/src/components/embed.tsx b/bskyembed/src/components/embed.tsx index 52618a89da..ddaa7bf03e 100644 --- a/bskyembed/src/components/embed.tsx +++ b/bskyembed/src/components/embed.tsx @@ -330,7 +330,7 @@ function ExternalEmbed({ {content.external.thumb && ( )}
@@ -435,7 +435,7 @@ function StarterPackEmbed({ - +
diff --git a/bskyembed/test.html b/bskyembed/test.html new file mode 100644 index 0000000000..ed407ddcb0 --- /dev/null +++ b/bskyembed/test.html @@ -0,0 +1,1054 @@ + + + + + + + + + + +
+

Base embeds test

+
+
+
+

+

[image or embed] +

+ — test-all-embeds-b.bsky.social (@test-all-embeds-b.bsky.social) + Mar 13, 2025 at 6:58 PM +
+
Image
+
+ +
+
+

+ Test with self-label

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:24 PM +
+
Image w/ label
+
+ +
+
+

+

[image or embed] +

+ — test-all-embeds-b.bsky.social (@test-all-embeds-b.bsky.social) + Mar 13, 2025 at 6:59 PM +
+
Image
+
+ +
+
+

+ De Reclame, 11e Jaargang, No 8, 1932 + designreviewed.com/artefacts/de...

[image or embed] +

+ — Design Reviewed (@designreviewed.com) + Aug 19, 2025 at 2:45 PM +
+
Image x2
+
+ +
+
+

+ Test with 3 images

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 16, 2025 at 1:22 PM +
+
Image x3
+
+ +
+
+

+ Test with 4 images

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 16, 2025 at 1:23 PM +
+
Image x4
+
+ +
+
+

+

[image or embed] +

+ — test-all-embeds-b.bsky.social (@test-all-embeds-b.bsky.social) + Mar 13, 2025 at 6:58 PM +
+
Video
+
+ +
+
+

+ Test video with self-label

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:26 PM +
+
Video w/ label
+
+ +
+
+

+ Test gif

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:26 PM +
+
GIF
+
+ +
+
+

+ Test with list

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:27 PM +
+
List
+
+ +
+
+

+ Test list with self-label

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:28 PM +
+
List w/ label
+
+ +
+
+

+ Test with moderated list

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:28 PM +
+
List (takendown)
+
+ +
+
+

+ Test feed

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:29 PM +
+
Feed
+
+ +
+
+

+ Test adult content feed

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 16, 2025 at 1:32 PM +
+
Feed w/ label
+
+ +
+
+

+

[image or embed] +

+ — test-all-embeds-b.bsky.social (@test-all-embeds-b.bsky.social) + Mar 13, 2025 at 7:00 PM +
+
Link
+
+ +
+
+

+ Quote post of self-labeled moderated image

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:49 PM +
+
Link w/ label
+
+ +
+
+

+ Test starter pack

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:31 PM +
+
Starter pack
+
+ +
+
+

+ Test starter pack with self-label

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:32 PM +
+
Starter pack w/ self label
+
+ +
+
+

+ go.bsky.app/FVMZBTc test

[image or embed] +

+ — h 🪽 partner @ INTDEV (@hannah-final.bsky.social) + Aug 26, 2025 at 7:05 PM +
+
Starter pack w/ signups
+
+
+
+ + +
+

Quote posts

+
+
+
+

+ Quote post

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:32 PM +
+
Image
+
+ +
+
+

+ Quote post with moderated embed

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:32 PM +
+
Image w/ label
+
+ +
+
+

+ Quote post of video

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:33 PM +
+
Video
+
+ +
+
+

+ Quote post of moderated video

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:33 PM +
+
Moderated Video
+
+ +
+
+

+ Quote post of gif

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 16, 2025 at 1:39 PM +
+
GIF
+
+ +
+
+

+ Quote post of gif

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 16, 2025 at 1:39 PM +
+
List
+
+ +
+
+

+ Quote post of moderated list

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:33 PM +
+
List (takedown)
+
+ +
+
+

+ Quote post of feed

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:33 PM +
+
Feed
+
+ +
+
+

+ Quote post of link

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:33 PM +
+
Link
+
+ +
+
+

+ Quote post of moderated link

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:33 PM +
+
Link w/label
+
+ +
+
+

+ Quote post of starter pack

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:34 PM +
+
Starter pack
+
+
+
+ + +
+

Quote post states

+
+
+
+

+ Quoted post of deleted post

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:44 PM +
+
Deleted
+
+ +
+
+

+ Quoted post of detached post

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:44 PM +
+
Detached quoted post
+
+ +
+
+

+ Quoted post of user who blocks me

[image or embed] +

+ — Embed Tester (@test-all-embeds-a.bsky.social) + Mar 13, 2025 at 6:48 PM +
+
Blocked
+
+
+
+ + +
+

Default avatars

+
+
+
+

test

+ — test-all-embeds-b.bsky.social (@test-all-embeds-b.bsky.social) + Mar 13, 2025 at 6:54 PM +
+
Default avatar
+
+ +
+
+

+ quote

[image or embed] +

+ — beep boop 2 (@bleh-5.bsky.social) + Jun 9, 2025 at 9:00 AM +
+
Default avi quote
+
+ +
+
+

+ bsky.app/profile/did:...

[image or embed] +

+ — beep boop 2 (@bleh-5.bsky.social) + Jun 9, 2025 at 9:01 AM +
+
Default avi list
+
+ +
+
+

+ feed bsky.app/profile/why....

[image or embed] +

+ — beep boop 2 (@bleh-5.bsky.social) + Jun 9, 2025 at 9:04 AM +
+
Default avi feed
+
+
+
+ + +
+

Verification

+
+
+
+

+ Viewers in Africa, Asia, and Australia will be able to see the + blood moon in the sky—but those in the Americas will have to + settle for a live feed this time around. + www.wired.com/story/how-to...

[image or embed] +

+ — WIRED (@wired.com) + Aug 28, 2025 at 10:35 PM +
+
Trusted verifier
+
+ +
+
+

+ Wired is one of the few US media organisations which fully + appreciates what's happening.

[image or embed] +

+ — TJ McIntyre (@tjmcintyre.com) + Aug 25, 2025 at 12:46 AM +
+
Trusted verifier quoted
+
+ +
+
+

test

+ — Samuel (@samuel.bsky.team) + Aug 26, 2025 at 5:22 AM +
+
Verified
+
+ +
+
+

+ atproto in one post

[image or embed] +

+ — Samuel (@samuel.bsky.team) + Aug 26, 2025 at 1:30 PM +
+ +
Verified quoted
+
+
+
+ + diff --git a/bskyembed/vite.config.ts b/bskyembed/vite.config.ts index 9acc9d5ee4..7cd3ffce52 100644 --- a/bskyembed/vite.config.ts +++ b/bskyembed/vite.config.ts @@ -1,10 +1,40 @@ +import fs from 'node:fs' import {resolve} from 'node:path' import preact from '@preact/preset-vite' import legacy from '@vitejs/plugin-legacy' -import type {UserConfig} from 'vite' +import type {Plugin, UserConfig} from 'vite' import paths from 'vite-tsconfig-paths' +/** + * World's hackiest router, for dev only. Serves `/post.html` to requests that start with `/embed/` + */ +function devOnlyRouter(): Plugin { + return { + name: 'embed-to-post-html', + configureServer(server) { + server.middlewares.use((req, res, next) => { + const url = req.url || '' + if (!url.startsWith('/embed/')) return next() + + const html = fs.readFileSync( + resolve(process.cwd(), 'post.html'), + 'utf8', + ) + + server + .transformIndexHtml(url, html) + .then(transformed => { + res.statusCode = 200 + res.setHeader('Content-Type', 'text/html') + res.end(transformed) + }) + .catch(next) + }) + }, + } +} + const config: UserConfig = { plugins: [ preact(), @@ -12,6 +42,7 @@ const config: UserConfig = { legacy({ targets: ['defaults', 'not IE 11'], }), + devOnlyRouter(), ], build: { assetsDir: 'static', diff --git a/bskyembed/yarn.lock b/bskyembed/yarn.lock index 9cb6d73180..4a879bfe59 100644 --- a/bskyembed/yarn.lock +++ b/bskyembed/yarn.lock @@ -1447,6 +1447,11 @@ regenerator-runtime "^0.14.1" systemjs "^6.15.1" +"@zeit/schemas@2.36.0": + version "2.36.0" + resolved "https://registry.yarnpkg.com/@zeit/schemas/-/schemas-2.36.0.tgz#7a1b53f4091e18d0b404873ea3e3c83589c765f2" + integrity sha512-7kjMwcChYEzMKjeex9ZFXkt1AyNov9R5HZtjBKVsmVpw7pa7ZtlCGvCBC2vnnXctaYN+aRI61HjIqeetZW5ROg== + acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -1462,6 +1467,16 @@ acorn@^8.9.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a" integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== +ajv@8.12.0: + version "8.12.0" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1" + integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA== + dependencies: + fast-deep-equal "^3.1.1" + json-schema-traverse "^1.0.0" + require-from-string "^2.0.2" + uri-js "^4.2.2" + ajv@^6.12.4: version "6.12.6" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" @@ -1472,6 +1487,13 @@ ajv@^6.12.4: json-schema-traverse "^0.4.1" uri-js "^4.2.2" +ansi-align@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" @@ -1507,7 +1529,12 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" -arg@^5.0.2: +arch@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/arch/-/arch-2.2.0.tgz#1bc47818f305764f23ab3306b0bfc086c5a29d11" + integrity sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ== + +arg@5.0.2, arg@^5.0.2: version "5.0.2" resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== @@ -1684,6 +1711,20 @@ boolbase@^1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== +boxen@7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-7.0.0.tgz#9e5f8c26e716793fc96edcf7cf754cdf5e3fbf32" + integrity sha512-j//dBVuyacJbvW+tvZ9HuH03fZ46QcaKvvhZickZqtB271DxJ7SNRSNxrV/dZX0085m7hISRZWbzWlJvx/rHSg== + dependencies: + ansi-align "^3.0.1" + camelcase "^7.0.0" + chalk "^5.0.1" + cli-boxes "^3.0.0" + string-width "^5.1.2" + type-fest "^2.13.0" + widest-line "^4.0.1" + wrap-ansi "^8.0.1" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -1738,6 +1779,16 @@ buffer-from@^1.0.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +bytes@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.0.0.tgz#d32815404d689699f85a4ea4fa8755dd13a96048" + integrity sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw== + +bytes@3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" + integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== + call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" @@ -1759,6 +1810,11 @@ camelcase-css@^2.0.1: resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5" integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== +camelcase@^7.0.0: + version "7.0.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-7.0.1.tgz#f02e50af9fd7782bc8b88a3558c32fd3a388f048" + integrity sha512-xlx1yCK2Oc1APsPXDL2LdlNP6+uu8OCDdhOBSVT279M/S+y75O30C2VuD8T2ogdePBBl7PfPF4504tnLgX3zfw== + caniuse-lite@^1.0.30001524: version "1.0.30001606" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001606.tgz#b4d5f67ab0746a3b8b5b6d1f06e39c51beb39a9e" @@ -1769,7 +1825,19 @@ caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001702, caniuse-lite@^1.0.300017 resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz#22e9706422ad37aa50556af8c10e40e2d93a8b85" integrity sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q== -chalk@^4.0.0: +chalk-template@0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/chalk-template/-/chalk-template-0.4.0.tgz#692c034d0ed62436b9062c1707fadcd0f753204b" + integrity sha512-/ghrgmhfY8RaSdeo43hNXxpoHAtxdbskUHjPpfqUWGttFgycUhYPGx3YZBCnUCvOa7Doivn1IZec3DEGFoMgLg== + dependencies: + chalk "^4.1.2" + +chalk@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.0.1.tgz#ca57d71e82bb534a296df63bbacc4a1c22b2a4b6" + integrity sha512-Fo07WOYGqMfCWHOzSXOt2CxDbC6skS/jO9ynEcmpANMoPrD+W1r1K6Vx7iNm+AQmETU1Xr2t+n8nzkV9t6xh3w== + +chalk@^4.0.0, chalk@^4.1.2: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== @@ -1777,6 +1845,11 @@ chalk@^4.0.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +chalk@^5.0.1: + version "5.6.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-5.6.2.tgz#b1238b6e23ea337af71c7f8a295db5af0c158aea" + integrity sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA== + chokidar@^3.5.3: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" @@ -1792,6 +1865,20 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +cli-boxes@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-3.0.0.tgz#71a10c716feeba005e4504f36329ef0b17cf3145" + integrity sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g== + +clipboardy@3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/clipboardy/-/clipboardy-3.0.0.tgz#f3876247404d334c9ed01b6f269c11d09a5e3092" + integrity sha512-Su+uU5sr1jkUy1sGRpLKjKrvEOVXgSgiSInwa/qeID6aJ07yh+5NWc3h2QfjHjBnfX4LhtFcuAWKUsJ3r+fjbg== + dependencies: + arch "^2.2.0" + execa "^5.1.1" + is-wsl "^2.2.0" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -1814,11 +1901,36 @@ commander@^4.0.0: resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== +compressible@~2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/compressible/-/compressible-2.0.18.tgz#af53cca6b070d4c3c0750fbd77286a6d7cc46fba" + integrity sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg== + dependencies: + mime-db ">= 1.43.0 < 2" + +compression@1.8.1: + version "1.8.1" + resolved "https://registry.yarnpkg.com/compression/-/compression-1.8.1.tgz#4a45d909ac16509195a9a28bd91094889c180d79" + integrity sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w== + dependencies: + bytes "3.1.2" + compressible "~2.0.18" + debug "2.6.9" + negotiator "~0.6.4" + on-headers "~1.1.0" + safe-buffer "5.2.1" + vary "~1.1.2" + concat-map@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +content-disposition@0.5.2: + version "0.5.2" + resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.2.tgz#0cf68bb9ddf5f2be7961c3a85178cb85dba78cb4" + integrity sha512-kRGRZw3bLlFISDBgwTSA1TMBFN6J6GWDeubmDE3AF+3+yXL8hTWv8r5rkLbqYXY4RjPk/EzHnClI3zQf1cFmHA== + convert-source-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" @@ -1845,6 +1957,15 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.2: shebang-command "^2.0.0" which "^2.0.1" +cross-spawn@^7.0.3: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + css-select@^5.1.0: version "5.2.2" resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.2.2.tgz#01b6e8d163637bb2dd6c982ca4ed65863682786e" @@ -1893,6 +2014,13 @@ data-view-byte-offset@^1.0.0: es-errors "^1.3.0" is-data-view "^1.0.1" +debug@2.6.9: + version "2.6.9" + resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" + integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== + dependencies: + ms "2.0.0" + debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4, debug@^4.4.1: version "4.4.1" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" @@ -1907,6 +2035,11 @@ debug@^4.3.2: dependencies: ms "2.1.2" +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + deep-is@^0.1.3: version "0.1.4" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" @@ -2356,6 +2489,21 @@ esutils@^2.0.2: resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== +execa@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-5.1.1.tgz#f80ad9cbf4298f7bd1d4c9555c21e93741c411dd" + integrity sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg== + dependencies: + cross-spawn "^7.0.3" + get-stream "^6.0.0" + human-signals "^2.1.0" + is-stream "^2.0.0" + merge-stream "^2.0.0" + npm-run-path "^4.0.1" + onetime "^5.1.2" + signal-exit "^3.0.3" + strip-final-newline "^2.0.0" + fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: version "3.1.3" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" @@ -2496,6 +2644,11 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@ has-symbols "^1.0.3" hasown "^2.0.0" +get-stream@^6.0.0: + version "6.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" + integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== + get-symbol-description@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" @@ -2631,6 +2784,11 @@ he@1.2.0: resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +human-signals@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-2.1.0.tgz#dc91fcba42e4d06e4abaed33b3e7a3c02f514ea0" + integrity sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw== + ignore@^5.2.0: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" @@ -2662,6 +2820,11 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + internal-slot@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" @@ -2741,6 +2904,11 @@ is-date-object@^1.0.1, is-date-object@^1.0.5: dependencies: has-tostringtag "^1.0.0" +is-docker@^2.0.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" + integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -2799,6 +2967,11 @@ is-path-inside@^3.0.3: resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== +is-port-reachable@4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-port-reachable/-/is-port-reachable-4.0.0.tgz#dac044091ef15319c8ab2f34604d8794181f8c2d" + integrity sha512-9UoipoxYmSk6Xy7QFgRv2HDyaysmgSG75TFQs6S+3pDM7ZhKTF/bskZV+0UlABHzKjNVhPjYCLfeZUEg1wXxig== + is-regex@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" @@ -2819,6 +2992,11 @@ is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: dependencies: call-bind "^1.0.7" +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -2860,6 +3038,13 @@ is-weakset@^2.0.3: call-bind "^1.0.7" get-intrinsic "^1.2.4" +is-wsl@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" + integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== + dependencies: + is-docker "^2.0.0" + isarray@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" @@ -2932,6 +3117,11 @@ json-schema-traverse@^0.4.1: resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== +json-schema-traverse@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2" + integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug== + json-stable-stringify-without-jsonify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" @@ -3047,6 +3237,11 @@ meow@^13.0.0: resolved "https://registry.yarnpkg.com/meow/-/meow-13.2.0.tgz#6b7d63f913f984063b3cc261b6e8800c4cd3474f" integrity sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA== +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + merge2@^1.3.0, merge2@^1.4.1: version "1.4.1" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" @@ -3060,7 +3255,29 @@ micromatch@^4.0.4, micromatch@^4.0.5: braces "^3.0.2" picomatch "^2.3.1" -minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: +"mime-db@>= 1.43.0 < 2": + version "1.54.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.54.0.tgz#cddb3ee4f9c64530dff640236661d42cb6a314f5" + integrity sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ== + +mime-db@~1.33.0: + version "1.33.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.33.0.tgz#a3492050a5cb9b63450541e39d9788d2272783db" + integrity sha512-BHJ/EKruNIqJf/QahvxwQZXKygOQ256myeN/Ew+THcAa5q+PjyTTMMeNQC4DZw5AwfvelsUrA6B67NKMqXDbzQ== + +mime-types@2.1.18: + version "2.1.18" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.18.tgz#6f323f60a83d11146f831ff11fd66e2fe5503bb8" + integrity sha512-lc/aahn+t4/SWV/qcmumYjymLsWfN3ELhpmVuUFjgsORruuZPVSwAQryq+HHGvO/SI2KVX26bx+En+zhM8g8hQ== + dependencies: + mime-db "~1.33.0" + +mimic-fn@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" + integrity sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg== + +minimatch@3.1.2, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -3074,11 +3291,21 @@ minimatch@^9.0.1: dependencies: brace-expansion "^2.0.1" +minimist@^1.2.0: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + "minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4: version "7.0.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== +ms@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" + integrity sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A== + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -3118,6 +3345,11 @@ natural-compare@^1.4.0: resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== +negotiator@~0.6.4: + version "0.6.4" + resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.4.tgz#777948e2452651c570b712dd01c23e262713fff7" + integrity sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w== + node-html-parser@^6.1.12: version "6.1.13" resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-6.1.13.tgz#a1df799b83df5c6743fcd92740ba14682083b7e4" @@ -3141,6 +3373,13 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== +npm-run-path@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-4.0.1.tgz#b7ecd1e5ed53da8e37a55e1c2269e0b97ed748ea" + integrity sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw== + dependencies: + path-key "^3.0.0" + nth-check@^2.0.1: version "2.1.1" resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" @@ -3215,6 +3454,11 @@ object.values@^1.1.6, object.values@^1.1.7: define-properties "^1.2.1" es-object-atoms "^1.0.0" +on-headers@~1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/on-headers/-/on-headers-1.1.0.tgz#59da4f91c45f5f989c6e4bcedc5a3b0aed70ff65" + integrity sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A== + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -3222,6 +3466,13 @@ once@^1.3.0: dependencies: wrappy "1" +onetime@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-5.1.2.tgz#d0e96ebb56b07476df1dd9c4806e5237985ca45e" + integrity sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg== + dependencies: + mimic-fn "^2.1.0" + optionator@^0.9.3: version "0.9.3" resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" @@ -3265,7 +3516,12 @@ path-is-absolute@^1.0.0: resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== -path-key@^3.1.0: +path-is-inside@1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/path-is-inside/-/path-is-inside-1.0.2.tgz#365417dede44430d1c11af61027facf074bdfc53" + integrity sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w== + +path-key@^3.0.0, path-key@^3.1.0: version "3.1.1" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== @@ -3283,6 +3539,11 @@ path-scurry@^1.10.2: lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" +path-to-regexp@3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-3.3.0.tgz#f7f31d32e8518c2660862b644414b6d5c63a611b" + integrity sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" @@ -3409,6 +3670,21 @@ queue-microtask@^1.2.2: resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== +range-parser@1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.0.tgz#f49be6b487894ddc40dcc94a322f611092e00d5e" + integrity sha512-kA5WQoNVo4t9lNx2kQNFCxKeBl5IbbSNBl1M/tLkw9WCn+hxNBAW5Qh8gdhs63CJnhjJ2zQWFoqPJP2sK1AV5A== + +rc@^1.0.1, rc@^1.1.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + react-is@^16.13.1: version "16.13.1" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" @@ -3480,6 +3756,21 @@ regexpu-core@^6.2.0: unicode-match-property-ecmascript "^2.0.0" unicode-match-property-value-ecmascript "^2.1.0" +registry-auth-token@3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/registry-auth-token/-/registry-auth-token-3.3.2.tgz#851fd49038eecb586911115af845260eec983f20" + integrity sha512-JL39c60XlzCVgNrO+qq68FoNb56w/m7JYvGR2jT5iR1xBrUA3Mfx5Twk5rqTThPmQKMWydGmq8oFtDlxfrmxnQ== + dependencies: + rc "^1.1.6" + safe-buffer "^5.0.1" + +registry-url@3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/registry-url/-/registry-url-3.1.0.tgz#3d4ef870f73dde1d77f0cf9a381432444e174942" + integrity sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA== + dependencies: + rc "^1.0.1" + regjsgen@^0.8.0: version "0.8.0" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.8.0.tgz#df23ff26e0c5b300a6470cad160a9d090c3a37ab" @@ -3492,6 +3783,11 @@ regjsparser@^0.12.0: dependencies: jsesc "~3.0.2" +require-from-string@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" + integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== + resolve-from@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" @@ -3582,6 +3878,11 @@ safe-array-concat@^1.1.2: has-symbols "^1.0.3" isarray "^2.0.5" +safe-buffer@5.2.1, safe-buffer@^5.0.1: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + safe-regex-test@^1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" @@ -3603,6 +3904,36 @@ semver@^7.3.7, semver@^7.5.4: dependencies: lru-cache "^6.0.0" +serve-handler@6.1.6: + version "6.1.6" + resolved "https://registry.yarnpkg.com/serve-handler/-/serve-handler-6.1.6.tgz#50803c1d3e947cd4a341d617f8209b22bd76cfa1" + integrity sha512-x5RL9Y2p5+Sh3D38Fh9i/iQ5ZK+e4xuXRd/pGbM4D13tgo/MGwbttUk8emytcr1YYzBYs+apnUngBDFYfpjPuQ== + dependencies: + bytes "3.0.0" + content-disposition "0.5.2" + mime-types "2.1.18" + minimatch "3.1.2" + path-is-inside "1.0.2" + path-to-regexp "3.3.0" + range-parser "1.2.0" + +serve@^14.2.5: + version "14.2.5" + resolved "https://registry.yarnpkg.com/serve/-/serve-14.2.5.tgz#569e333b99a484b3a6d25acce4a569c8c4f96373" + integrity sha512-Qn/qMkzCcMFVPb60E/hQy+iRLpiU8PamOfOSYoAHmmF+fFFmpPpqa6Oci2iWYpTdOUM3VF+TINud7CfbQnsZbA== + dependencies: + "@zeit/schemas" "2.36.0" + ajv "8.12.0" + arg "5.0.2" + boxen "7.0.0" + chalk "5.0.1" + chalk-template "0.4.0" + clipboardy "3.0.0" + compression "1.8.1" + is-port-reachable "4.0.0" + serve-handler "6.1.6" + update-check "1.5.4" + set-function-length@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" @@ -3647,6 +3978,11 @@ side-channel@^1.0.4, side-channel@^1.0.6: get-intrinsic "^1.2.4" object-inspect "^1.13.1" +signal-exit@^3.0.3: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + signal-exit@^4.0.1: version "4.1.0" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" @@ -3791,11 +4127,21 @@ strip-ansi@^7.0.1: dependencies: ansi-regex "^6.0.1" +strip-final-newline@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" + integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== + strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + sucrase@^3.32.0: version "3.35.0" resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" @@ -3937,6 +4283,11 @@ type-fest@^0.20.2: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== +type-fest@^2.13.0: + version "2.19.0" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-2.19.0.tgz#88068015bb33036a598b952e55e9311a60fd3a9b" + integrity sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA== + typed-array-buffer@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" @@ -4034,6 +4385,14 @@ update-browserslist-db@^1.0.13, update-browserslist-db@^1.1.3: escalade "^3.2.0" picocolors "^1.1.1" +update-check@1.5.4: + version "1.5.4" + resolved "https://registry.yarnpkg.com/update-check/-/update-check-1.5.4.tgz#5b508e259558f1ad7dbc8b4b0457d4c9d28c8743" + integrity sha512-5YHsflzHP4t1G+8WGPlvKbJEbAJGCgw+Em+dGR1KmBUbr1J36SJBqlHLjR7oob7sco5hWHGQVcr9B2poIVDDTQ== + dependencies: + registry-auth-token "3.3.2" + registry-url "3.1.0" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -4046,6 +4405,11 @@ util-deprecate@^1.0.2: resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== +vary@~1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" + integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg== + vite-prerender-plugin@^0.5.3: version "0.5.11" resolved "https://registry.yarnpkg.com/vite-prerender-plugin/-/vite-prerender-plugin-0.5.11.tgz#83e4f29e03269dceb763fb5ec2376dcc502aa79f" @@ -4138,6 +4502,13 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +widest-line@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-4.0.1.tgz#a0fc673aaba1ea6f0a0d35b3c2795c9a9cc2ebf2" + integrity sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig== + dependencies: + string-width "^5.0.1" + "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" @@ -4147,7 +4518,7 @@ which@^2.0.1: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^8.1.0: +wrap-ansi@^8.0.1, wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== diff --git a/bskyweb/cmd/bskyweb/server.go b/bskyweb/cmd/bskyweb/server.go index f0cd72b153..c7350d37da 100644 --- a/bskyweb/cmd/bskyweb/server.go +++ b/bskyweb/cmd/bskyweb/server.go @@ -458,6 +458,18 @@ func (srv *Server) WebHome(c echo.Context) error { return c.Render(http.StatusOK, "home.html", data) } +// Posts that include these labels will not have embeds passed to the metadata +// template. +var hideEmbedLabels = map[string]bool{ + "nudity": true, + "porn": true, + "sexual": true, + "sexual-figurative": true, + "graphic-media": true, + "self-harm": true, + "sensitive": true, +} + func (srv *Server) WebPost(c echo.Context) error { ctx := c.Request().Context() data := srv.NewTemplateContext() @@ -512,19 +524,15 @@ func (srv *Server) WebPost(c echo.Context) error { postView := tpv.Thread.FeedDefs_ThreadViewPost.Post data["postView"] = postView data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path) - if postView.Embed != nil { - if postView.Embed.EmbedImages_View != nil { - var thumbUrls []string - for i := range postView.Embed.EmbedImages_View.Images { - thumbUrls = append(thumbUrls, postView.Embed.EmbedImages_View.Images[i].Thumb) - } - data["imgThumbUrls"] = thumbUrls - } else if postView.Embed.EmbedRecordWithMedia_View != nil && postView.Embed.EmbedRecordWithMedia_View.Media != nil && postView.Embed.EmbedRecordWithMedia_View.Media.EmbedImages_View != nil { - var thumbUrls []string - for i := range postView.Embed.EmbedRecordWithMedia_View.Media.EmbedImages_View.Images { - thumbUrls = append(thumbUrls, postView.Embed.EmbedRecordWithMedia_View.Media.EmbedImages_View.Images[i].Thumb) - } - data["imgThumbUrls"] = thumbUrls + + // If any undesirable labels are set, the embed will not be included in + // metadata + isEmbedHidden := false + for _, label := range postView.Labels { + isNeg := label.Neg != nil && *label.Neg + if hideEmbedLabels[label.Val] && !isNeg { + isEmbedHidden = true + break } } @@ -532,6 +540,34 @@ func (srv *Server) WebPost(c echo.Context) error { postRecord, ok := postView.Record.Val.(*appbsky.FeedPost) if ok { data["postText"] = ExpandPostText(postRecord) + + if !isEmbedHidden && postRecord.Labels != nil && postRecord.Labels.LabelDefs_SelfLabels != nil { + for _, label := range postRecord.Labels.LabelDefs_SelfLabels.Values { + if hideEmbedLabels[label.Val] { + isEmbedHidden = true + break + } + } + } + } + } + + if postView.Embed != nil && !isEmbedHidden { + hasImages := postView.Embed.EmbedImages_View != nil + hasMedia := postView.Embed.EmbedRecordWithMedia_View != nil && postView.Embed.EmbedRecordWithMedia_View.Media != nil && postView.Embed.EmbedRecordWithMedia_View.Media.EmbedImages_View != nil + + if hasImages { + var thumbUrls []string + for i := range postView.Embed.EmbedImages_View.Images { + thumbUrls = append(thumbUrls, postView.Embed.EmbedImages_View.Images[i].Thumb) + } + data["imgThumbUrls"] = thumbUrls + } else if hasMedia { + var thumbUrls []string + for i := range postView.Embed.EmbedRecordWithMedia_View.Media.EmbedImages_View.Images { + thumbUrls = append(thumbUrls, postView.Embed.EmbedRecordWithMedia_View.Media.EmbedImages_View.Images[i].Thumb) + } + data["imgThumbUrls"] = thumbUrls } } diff --git a/bskyweb/templates/post.html b/bskyweb/templates/post.html index ff21aaca14..5c7c844e61 100644 --- a/bskyweb/templates/post.html +++ b/bskyweb/templates/post.html @@ -62,7 +62,12 @@ "@type": "DiscussionForumPosting", "author": { "@type": "Person", + {%- if postView.Author.DisplayName %} "name": "{{ postView.Author.DisplayName }}", + "alternateName": "@{{ postView.Author.Handle }}", + {% else %} + "name": "@{{ postView.Author.Handle }}", + {% endif -%} "url": "https://bsky.app/profile/{{ postView.Author.Handle }}" }, {%- if postText %} diff --git a/bskyweb/templates/profile.html b/bskyweb/templates/profile.html index bb552ef47d..b4be429289 100644 --- a/bskyweb/templates/profile.html +++ b/bskyweb/templates/profile.html @@ -59,8 +59,12 @@ "dateCreated": "{{ profileView.CreatedAt }}", "mainEntity": { "@type": "Person", + {%- if profileView.DisplayName %} "name": "{{ profileView.DisplayName }}", "alternateName": "@{{ profileView.Handle }}", + {% else %} + "name": "@{{ profileView.Handle }}", + {% endif -%} "identifier": "{{ profileView.Did }}", "description": "{{ profileView.Description }}", "image": "{{ profileView.Avatar }}", diff --git a/package.json b/package.json index 500edc4dc3..e110ae2699 100644 --- a/package.json +++ b/package.json @@ -145,6 +145,7 @@ "expo-image-manipulator": "~14.0.7", "expo-image-picker": "~17.0.8", "expo-intent-launcher": "~13.0.7", + "expo-keep-awake": "^15.0.7", "expo-linear-gradient": "~15.0.7", "expo-linking": "~8.0.8", "expo-localization": "~17.0.7", @@ -192,7 +193,7 @@ "react-native-gesture-handler": "~2.28.0", "react-native-get-random-values": "~1.11.0", "react-native-keyboard-controller": "1.18.5", - "react-native-mmkv": "^2.12.2", + "@bsky.app/react-native-mmkv": "2.12.5", "react-native-pager-view": "6.8.0", "react-native-progress": "bluesky-social/react-native-progress", "react-native-qrcode-styled": "^0.3.3", diff --git a/patches/react-native-compressor+1.13.0.patch b/patches/react-native-compressor+1.13.0.patch new file mode 100644 index 0000000000..4b6198ee05 --- /dev/null +++ b/patches/react-native-compressor+1.13.0.patch @@ -0,0 +1,516 @@ +diff --git a/node_modules/react-native-compressor/android/build.gradle b/node_modules/react-native-compressor/android/build.gradle +index 5071139..84bee34 100644 +--- a/node_modules/react-native-compressor/android/build.gradle ++++ b/node_modules/react-native-compressor/android/build.gradle +@@ -115,7 +115,6 @@ dependencies { + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4" + implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4" + implementation 'org.mp4parser:isoparser:1.9.56' +- implementation 'com.github.banketree:AndroidLame-kotlin:v0.0.1' + implementation 'javazoom:jlayer:1.0.1' + } + +diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt +deleted file mode 100644 +index 9292d3e..0000000 +--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioCompressor.kt ++++ /dev/null +@@ -1,264 +0,0 @@ +-package com.reactnativecompressor.Audio +- +- +-import android.annotation.SuppressLint +-import com.facebook.react.bridge.Promise +-import com.facebook.react.bridge.ReactApplicationContext +-import com.facebook.react.bridge.ReadableMap +-import com.naman14.androidlame.LameBuilder +-import com.naman14.androidlame.WaveReader +-import com.reactnativecompressor.Utils.MediaCache +-import com.reactnativecompressor.Utils.Utils +-import com.reactnativecompressor.Utils.Utils.addLog +-import javazoom.jl.converter.Converter +-import javazoom.jl.decoder.JavaLayerException +-import java.io.BufferedOutputStream +-import java.io.File +-import java.io.FileNotFoundException +-import java.io.FileOutputStream +-import java.io.IOException +- +-class AudioCompressor { +- companion object { +- val TAG="AudioMain" +- private const val OUTPUT_STREAM_BUFFER = 8192 +- +- var outputStream: BufferedOutputStream? = null +- var waveReader: WaveReader? = null +- @JvmStatic +- fun CompressAudio( +- fileUrl: String, +- optionMap: ReadableMap, +- context: ReactApplicationContext, +- promise: Promise, +- ) { +- val realPath = Utils.getRealPath(fileUrl, context) +- var _fileUrl=realPath +- val filePathWithoutFileUri = realPath!!.replace("file://", "") +- try { +- var wavPath=filePathWithoutFileUri; +- var isNonWav:Boolean=false +- if (fileUrl.endsWith(".mp4", ignoreCase = true)) +- { +- addLog("mp4 file found") +- val mp3Path= Utils.generateCacheFilePath("mp3", context) +- AudioExtractor().genVideoUsingMuxer(fileUrl, mp3Path, -1, -1, true, false) +- _fileUrl=Utils.slashifyFilePath(mp3Path) +- wavPath= Utils.generateCacheFilePath("wav", context) +- try { +- val converter = Converter() +- converter.convert(mp3Path, wavPath) +- } catch (e: JavaLayerException) { +- addLog("JavaLayerException error"+e.localizedMessage) +- e.printStackTrace(); +- } +- isNonWav=true +- } +- else if (!fileUrl.endsWith(".wav", ignoreCase = true)) +- { +- addLog("non wav file found") +- wavPath= Utils.generateCacheFilePath("wav", context) +- try { +- val converter = Converter() +- converter.convert(filePathWithoutFileUri, wavPath) +- } catch (e: JavaLayerException) { +- addLog("JavaLayerException error"+e.localizedMessage) +- e.printStackTrace(); +- } +- isNonWav=true +- } +- +- +- autoCompressHelper(wavPath,filePathWithoutFileUri, optionMap,context) { mp3Path, finished -> +- if (finished) { +- val returnableFilePath:String="file://$mp3Path" +- addLog("finished: " + returnableFilePath) +- MediaCache.removeCompletedImagePath(fileUrl) +- if(isNonWav) +- { +- File(wavPath).delete() +- } +- promise.resolve(returnableFilePath) +- } else { +- addLog("error: "+mp3Path) +- promise.resolve(_fileUrl) +- } +- } +- } catch (e: Exception) { +- promise.resolve(_fileUrl) +- } +- } +- +- @SuppressLint("WrongConstant") +- private fun autoCompressHelper( +- fileUrl: String, +- actualFileUrl: String, +- optionMap: ReadableMap, +- context: ReactApplicationContext, +- completeCallback: (String, Boolean) -> Unit +- ) { +- +- val options = AudioHelper.fromMap(optionMap) +- val quality = options.quality +- +- var isCompletedCallbackTriggered:Boolean=false +- try { +- var mp3Path = Utils.generateCacheFilePath("mp3", context) +- val input = File(fileUrl) +- val output = File(mp3Path) +- +- val CHUNK_SIZE = 8192 +- addLog("Initialising wav reader") +- +- waveReader = WaveReader(input) +- +- try { +- waveReader!!.openWave() +- } catch (e: IOException) { +- e.printStackTrace() +- } +- +- addLog("Intitialising encoder") +- +- +- // for bitrate +- var audioBitrate:Int +- if(options.bitrate != -1) +- { +- audioBitrate= options.bitrate/1000 +- } +- else +- { +- audioBitrate=AudioHelper.getDestinationBitrateByQuality(actualFileUrl, quality!!) +- Utils.addLog("dest bitrate: $audioBitrate") +- } +- +- var androidLame = LameBuilder(); +- androidLame.setOutBitrate(audioBitrate) +- +- // for channels +- var audioChannels:Int +- if(options.channels != -1){ +- audioChannels= options.channels!! +- } +- else +- { +- audioChannels=waveReader!!.channels +- } +- androidLame.setOutChannels(audioChannels) +- +- // for sample rate +- androidLame.setInSampleRate(waveReader!!.sampleRate) +- var audioSampleRate:Int +- if(options.samplerate != -1){ +- audioSampleRate= options.samplerate!! +- } +- else +- { +- audioSampleRate=waveReader!!.sampleRate +- } +- androidLame.setOutSampleRate(audioSampleRate) +- val androidLameBuild=androidLame.build() +- +- try { +- outputStream = BufferedOutputStream(FileOutputStream(output), OUTPUT_STREAM_BUFFER) +- } catch (e: FileNotFoundException) { +- e.printStackTrace() +- } +- +- var bytesRead = 0 +- +- val buffer_l = ShortArray(CHUNK_SIZE) +- val buffer_r = ShortArray(CHUNK_SIZE) +- val mp3Buf = ByteArray(CHUNK_SIZE) +- +- val channels = waveReader!!.channels +- +- addLog("started encoding") +- while (true) { +- try { +- if (channels == 2) { +- +- bytesRead = waveReader!!.read(buffer_l, buffer_r, CHUNK_SIZE) +- addLog("bytes read=$bytesRead") +- +- if (bytesRead > 0) { +- +- var bytesEncoded = 0 +- bytesEncoded = androidLameBuild.encode(buffer_l, buffer_r, bytesRead, mp3Buf) +- addLog("bytes encoded=$bytesEncoded") +- +- if (bytesEncoded > 0) { +- try { +- addLog("writing mp3 buffer to outputstream with $bytesEncoded bytes") +- outputStream!!.write(mp3Buf, 0, bytesEncoded) +- } catch (e: IOException) { +- e.printStackTrace() +- } +- +- } +- +- } else +- break +- } else { +- +- bytesRead = waveReader!!.read(buffer_l, CHUNK_SIZE) +- addLog("bytes read=$bytesRead") +- +- if (bytesRead > 0) { +- var bytesEncoded = 0 +- +- bytesEncoded = androidLameBuild.encode(buffer_l, buffer_l, bytesRead, mp3Buf) +- addLog("bytes encoded=$bytesEncoded") +- +- if (bytesEncoded > 0) { +- try { +- addLog("writing mp3 buffer to outputstream with $bytesEncoded bytes") +- outputStream!!.write(mp3Buf, 0, bytesEncoded) +- } catch (e: IOException) { +- e.printStackTrace() +- } +- +- } +- +- } else +- break +- } +- +- +- } catch (e: IOException) { +- e.printStackTrace() +- } +- +- } +- +- addLog("flushing final mp3buffer") +- val outputMp3buf = androidLameBuild.flush(mp3Buf) +- addLog("flushed $outputMp3buf bytes") +- if (outputMp3buf > 0) { +- try { +- addLog("writing final mp3buffer to outputstream") +- outputStream!!.write(mp3Buf, 0, outputMp3buf) +- addLog("closing output stream") +- outputStream!!.close() +- completeCallback(output.absolutePath, true) +- isCompletedCallbackTriggered=true +- } catch (e: IOException) { +- completeCallback(e.localizedMessage, false) +- e.printStackTrace() +- } +- } +- +- } catch (e: IOException) { +- completeCallback(e.localizedMessage, false) +- } +- if(!isCompletedCallbackTriggered) +- { +- completeCallback("something went wrong", false) +- } +- } +- +- +- +- } +-} +diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioExtractor.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioExtractor.kt +deleted file mode 100644 +index c655182..0000000 +--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioExtractor.kt ++++ /dev/null +@@ -1,112 +0,0 @@ +-package com.reactnativecompressor.Audio +- +-import android.annotation.SuppressLint +-import android.media.MediaCodec +-import android.media.MediaExtractor +-import android.media.MediaFormat +-import android.media.MediaMetadataRetriever +-import android.media.MediaMuxer +-import android.util.Log +-import java.io.IOException +-import java.nio.ByteBuffer +- +- +-class AudioExtractor { +- /** +- * @param srcPath the path of source video file. +- * @param dstPath the path of destination video file. +- * @param startMs starting time in milliseconds for trimming. Set to +- * negative if starting from beginning. +- * @param endMs end time for trimming in milliseconds. Set to negative if +- * no trimming at the end. +- * @param useAudio true if keep the audio track from the source. +- * @param useVideo true if keep the video track from the source. +- * @throws IOException +- */ +- @SuppressLint("NewApi", "WrongConstant") +- @Throws(IOException::class) +- fun genVideoUsingMuxer(srcPath: String?, dstPath: String?, startMs: Int, endMs: Int, useAudio: Boolean, useVideo: Boolean) { +- // Set up MediaExtractor to read from the source. +- val extractor = MediaExtractor() +- extractor.setDataSource(srcPath!!) +- val trackCount = extractor.trackCount +- // Set up MediaMuxer for the destination. +- val muxer: MediaMuxer +- muxer = MediaMuxer(dstPath!!, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4) +- // Set up the tracks and retrieve the max buffer size for selected +- // tracks. +- val indexMap = HashMap(trackCount) +- var bufferSize = -1 +- for (i in 0 until trackCount) { +- val format = extractor.getTrackFormat(i) +- val mime = format.getString(MediaFormat.KEY_MIME) +- var selectCurrentTrack = false +- if (mime!!.startsWith("audio/") && useAudio) { +- selectCurrentTrack = true +- } else if (mime.startsWith("video/") && useVideo) { +- selectCurrentTrack = true +- } +- if (selectCurrentTrack) { +- extractor.selectTrack(i) +- val dstIndex = muxer.addTrack(format) +- indexMap[i] = dstIndex +- if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) { +- val newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE) +- bufferSize = if (newSize > bufferSize) newSize else bufferSize +- } +- } +- } +- if (bufferSize < 0) { +- bufferSize = DEFAULT_BUFFER_SIZE +- } +- // Set up the orientation and starting time for extractor. +- val retrieverSrc = MediaMetadataRetriever() +- retrieverSrc.setDataSource(srcPath) +- val degreesString = retrieverSrc.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION) +- if (degreesString != null) { +- val degrees = degreesString.toInt() +- if (degrees >= 0) { +- muxer.setOrientationHint(degrees) +- } +- } +- if (startMs > 0) { +- extractor.seekTo((startMs * 1000).toLong(), MediaExtractor.SEEK_TO_CLOSEST_SYNC) +- } +- // Copy the samples from MediaExtractor to MediaMuxer. We will loop +- // for copying each sample and stop when we get to the end of the source +- // file or exceed the end time of the trimming. +- val offset = 0 +- var trackIndex = -1 +- val dstBuf = ByteBuffer.allocate(bufferSize) +- val bufferInfo = MediaCodec.BufferInfo() +- muxer.start() +- while (true) { +- bufferInfo.offset = offset +- bufferInfo.size = extractor.readSampleData(dstBuf, offset) +- if (bufferInfo.size < 0) { +- Log.d(TAG, "Saw input EOS.") +- bufferInfo.size = 0 +- break +- } else { +- bufferInfo.presentationTimeUs = extractor.sampleTime +- if (endMs > 0 && bufferInfo.presentationTimeUs > endMs * 1000) { +- Log.d(TAG, "The current sample is over the trim end time.") +- break +- } else { +- bufferInfo.flags = extractor.sampleFlags +- trackIndex = extractor.sampleTrackIndex +- muxer.writeSampleData(indexMap[trackIndex]!!, dstBuf, bufferInfo) +- extractor.advance() +- } +- } +- } +- muxer.stop() +- muxer.release() +- return +- } +- +- companion object { +- private const val DEFAULT_BUFFER_SIZE = 1 * 1024 * 1024 +- private const val TAG = "AudioExtractorDecoder" +- } +-} +diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioHelper.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioHelper.kt +deleted file mode 100644 +index 42040b4..0000000 +--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioHelper.kt ++++ /dev/null +@@ -1,72 +0,0 @@ +-package com.reactnativecompressor.Audio +- +-import android.media.MediaExtractor +-import android.media.MediaFormat +-import com.facebook.react.bridge.ReadableMap +-import com.reactnativecompressor.Utils.Utils +-import java.io.File +-import java.io.IOException +- +- +-class AudioHelper { +- +- var quality: String? = "medium" +- var bitrate: Int = -1 +- var samplerate: Int = -1 +- var channels: Int = -1 +- var progressDivider: Int? = 0 +- +- companion object { +- fun fromMap(map: ReadableMap): AudioHelper { +- val options = AudioHelper() +- val iterator = map.keySetIterator() +- while (iterator.hasNextKey()) { +- val key = iterator.nextKey() +- when (key) { +- "quality" -> options.quality = map.getString(key) +- "bitrate" -> { +- val bitrate = map.getInt(key) +- options.bitrate = if (bitrate > 320000 || bitrate < 64000) 64000 else bitrate +- } +- "samplerate" -> options.samplerate = map.getInt(key) +- "channels" -> options.channels = map.getInt(key) +- } +- } +- return options +- } +- +- +- fun getAudioBitrate(path: String): Int { +- val file = File(path) +- val fileSize = file.length() * 8 // size in bits +- +- val mex = MediaExtractor() +- try { +- mex.setDataSource(path) +- } catch (e: IOException) { +- e.printStackTrace() +- } +- +- val mf = mex.getTrackFormat(0) +- val durationUs = mf.getLong(MediaFormat.KEY_DURATION) +- val durationSec = durationUs / 1_000_000.0 // convert duration to seconds +- +- return (fileSize / durationSec).toInt()/1000 // bitrate in bits per second +- } +- fun getDestinationBitrateByQuality(path: String, quality: String): Int { +- val originalBitrate = getAudioBitrate(path) +- var destinationBitrate = originalBitrate +- Utils.addLog("source bitrate: $originalBitrate") +- +- when (quality.lowercase()) { +- "low" -> destinationBitrate = maxOf(64, (originalBitrate * 0.3).toInt()) +- "medium" -> destinationBitrate = (originalBitrate * 0.5).toInt() +- "high" -> destinationBitrate = minOf(320, (originalBitrate * 0.7).toInt()) +- else -> Utils.addLog("Invalid quality level. Please enter 'low', 'medium', or 'high'.") +- } +- +- return destinationBitrate +- } +- +- } +-} +diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt +index 446d4fb..f021909 100644 +--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt ++++ b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Audio/AudioMain.kt +@@ -11,7 +11,9 @@ class AudioMain(private val reactContext: ReactApplicationContext) { + promise: Promise) { + try { + +- AudioCompressor.CompressAudio(fileUrl,optionMap,reactContext,promise) ++ // Skip compression on Android to avoid libandroidlame dependency ++ // Return the original file URL without compression ++ promise.resolve(fileUrl) + } catch (ex: Exception) { + promise.reject(ex) + } +diff --git a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt +index c14b727..1198908 100644 +--- a/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt ++++ b/node_modules/react-native-compressor/android/src/main/java/com/reactnativecompressor/Utils/Utils.kt +@@ -7,7 +7,6 @@ import android.provider.OpenableColumns + import android.util.Log + import com.facebook.react.bridge.Promise + import com.facebook.react.bridge.ReactApplicationContext +-import com.reactnativecompressor.Audio.AudioCompressor + import com.reactnativecompressor.Video.VideoCompressor.CompressionListener + import com.reactnativecompressor.Video.VideoCompressor.VideoCompressorClass + import java.io.FileNotFoundException +@@ -152,10 +151,6 @@ object Utils { + } + } + +- fun addLog(log: String) { +- Log.d(AudioCompressor.TAG, log) +- } +- + val exifAttributes = arrayOf( + "FNumber", + "ApertureValue", diff --git a/patches/react-native-compressor+1.13.0.patch.md b/patches/react-native-compressor+1.13.0.patch.md new file mode 100644 index 0000000000..de59e55244 --- /dev/null +++ b/patches/react-native-compressor+1.13.0.patch.md @@ -0,0 +1,5 @@ +# react-native-compressor + +Patch file taken from https://github.com/numandev1/react-native-compressor/pull/355#issuecomment-3180870738 + +This patch removes the audio compression feature on Android from the library. This is because `libandroidlame.so`, the native dependency, does not support 16kb page sizes, and the Play Store has made this mandatory as of 1st Nov 2025. diff --git a/patches/sonner-native+0.21.0.patch b/patches/sonner-native+0.21.0.patch new file mode 100644 index 0000000000..3fe7cc0aab --- /dev/null +++ b/patches/sonner-native+0.21.0.patch @@ -0,0 +1,22 @@ +diff --git a/node_modules/sonner-native/lib/commonjs/toast.js b/node_modules/sonner-native/lib/commonjs/toast.js +index 121816a..0c3c7bd 100644 +--- a/node_modules/sonner-native/lib/commonjs/toast.js ++++ b/node_modules/sonner-native/lib/commonjs/toast.js +@@ -264,7 +264,7 @@ const Toast = exports.Toast = /*#__PURE__*/React.forwardRef(({ + ...toastSwipeHandlerProps, + children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, { + entering: entering, +- exiting: exiting, ++ exiting: _reactNative.Platform.OS === 'android' ? undefined : exiting, + children: jsx + }) + }); +@@ -274,7 +274,7 @@ const Toast = exports.Toast = /*#__PURE__*/React.forwardRef(({ + children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, { + style: [unstyled ? undefined : elevationStyle, defaultStyles.toast, toastStyleCtx, styles?.toast, style, wiggleAnimationStyle], + entering: entering, +- exiting: exiting, ++ exiting: _reactNative.Platform.OS === 'android' ? undefined : exiting, + children: /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, { + style: [defaultStyles.toastContent, toastContentStyleCtx, styles?.toastContent], + children: [promiseOptions || variant === 'loading' ? 'loading' in icons ? icons.loading : /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.ActivityIndicator, {}) : icon ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, { diff --git a/patches/sonner-native+0.21.0.patch.md b/patches/sonner-native+0.21.0.patch.md new file mode 100644 index 0000000000..0a7fbafcc4 --- /dev/null +++ b/patches/sonner-native+0.21.0.patch.md @@ -0,0 +1,3 @@ +# sonner-native+0.21.0.patch + +Removes Reanimated exit layout animations from the toasts. This was causing crashes if the toast was hidden while you were scrolling a flatlist. diff --git a/src/alf/atoms.ts b/src/alf/atoms.ts index 3168b1da18..6d40962e01 100644 --- a/src/alf/atoms.ts +++ b/src/alf/atoms.ts @@ -1,6 +1,7 @@ import {type StyleProp, type ViewStyle} from 'react-native' import {atoms as baseAtoms} from '@bsky.app/alf' +import {CARD_ASPECT_RATIO} from '#/lib/constants' import {native, platform, web} from '#/alf/util/platform' import * as Layout from '#/components/Layout' @@ -31,6 +32,16 @@ export const atoms = { backgroundColor: 'transparent', }, + /** + * Aspect ratios + */ + aspect_square: { + aspectRatio: 1, + }, + aspect_card: { + aspectRatio: CARD_ASPECT_RATIO, + }, + /* * Transition */ @@ -67,7 +78,7 @@ export const atoms = { }), /* - * Animaations + * Animations */ fade_in: web({ animation: 'fadeIn ease-out 0.15s', diff --git a/src/components/AccountList.tsx b/src/components/AccountList.tsx index e3b2b7d129..e01ca31d2c 100644 --- a/src/components/AccountList.tsx +++ b/src/components/AccountList.tsx @@ -172,7 +172,7 @@ function AccountItem({ {isCurrentAccount ? ( - + ) : ( )} diff --git a/src/components/Admonition.tsx b/src/components/Admonition.tsx index 961d94b37e..8846bb208d 100644 --- a/src/components/Admonition.tsx +++ b/src/components/Admonition.tsx @@ -87,7 +87,7 @@ export function Row({ style?: StyleProp }) { return ( - + {children} ) diff --git a/src/components/InterestTabs.tsx b/src/components/InterestTabs.tsx index aec4217681..6b4a46837f 100644 --- a/src/components/InterestTabs.tsx +++ b/src/components/InterestTabs.tsx @@ -258,7 +258,7 @@ export function InterestTabs({ t.atoms.border_contrast_low, t.atoms.bg, a.h_full, - {aspectRatio: 1}, + a.aspect_square, a.rounded_full, ]}> @@ -292,7 +292,7 @@ export function InterestTabs({ t.atoms.border_contrast_low, t.atoms.bg, a.h_full, - {aspectRatio: 1}, + a.aspect_square, a.rounded_full, ]}> diff --git a/src/components/KeepAwake.tsx b/src/components/KeepAwake.tsx new file mode 100644 index 0000000000..d423656216 --- /dev/null +++ b/src/components/KeepAwake.tsx @@ -0,0 +1,28 @@ +import {useId} from 'react' +import {useKeepAwake} from 'expo-keep-awake' +import {useIsFocused} from '@react-navigation/native' + +/** + * Stops the screen from sleeping. Only applies to the current screen. + * + * Note: Expo keeps the screen permanently awake when in dev mode, so + * you'll only see this do anything when in production. + * + * @platform ios, android + */ +export function KeepAwake({enabled = true}) { + const isFocused = useIsFocused() + if (enabled && isFocused) { + return + } else { + return null + } +} + +function KeepAwakeInner() { + const id = useId() + // if you don't pass an explicit ID, any `useKeepAwake` hook unmounting disables them all. + // very strange behaviour, but easily fixed by passing a unique ID -sfn + useKeepAwake(id) + return null +} diff --git a/src/components/KeepAwake.web.tsx b/src/components/KeepAwake.web.tsx new file mode 100644 index 0000000000..06eb3112ae --- /dev/null +++ b/src/components/KeepAwake.web.tsx @@ -0,0 +1,3 @@ +export function KeepAwake() { + return null +} diff --git a/src/components/LoggedOutCTA.tsx b/src/components/LoggedOutCTA.tsx deleted file mode 100644 index de0e23dc96..0000000000 --- a/src/components/LoggedOutCTA.tsx +++ /dev/null @@ -1,82 +0,0 @@ -import {View, type ViewStyle} from 'react-native' -import {msg, Trans} from '@lingui/macro' -import {useLingui} from '@lingui/react' - -import {type Gate} from '#/lib/statsig/gates' -import {useGate} from '#/lib/statsig/statsig' -import {isWeb} from '#/platform/detection' -import {useSession} from '#/state/session' -import {useLoggedOutViewControls} from '#/state/shell/logged-out' -import {Logo} from '#/view/icons/Logo' -import {atoms as a, useTheme} from '#/alf' -import {Button, ButtonText} from '#/components/Button' -import {Text} from '#/components/Typography' - -interface LoggedOutCTAProps { - style?: ViewStyle - gateName: Gate -} - -export function LoggedOutCTA({style, gateName}: LoggedOutCTAProps) { - const {hasSession} = useSession() - const {requestSwitchToAccount} = useLoggedOutViewControls() - const gate = useGate() - const t = useTheme() - const {_} = useLingui() - - // Only show for logged-out users on web - if (hasSession || !isWeb) { - return null - } - - // Check gate at the last possible moment to avoid counting users as exposed when they won't see the element - if (!gate(gateName)) { - return null - } - - return ( - - - - - - - Join Bluesky - - - The open social network. - - - - - - - ) -} diff --git a/src/components/MediaPreview.tsx b/src/components/MediaPreview.tsx index c2603a4d78..d8d2e430f2 100644 --- a/src/components/MediaPreview.tsx +++ b/src/components/MediaPreview.tsx @@ -87,7 +87,7 @@ export function ImageItem({ }) { const t = useTheme() return ( - + diff --git a/src/components/Post/Embed/ExternalEmbed/index.tsx b/src/components/Post/Embed/ExternalEmbed/index.tsx index 7911df726b..4e970ad7f8 100644 --- a/src/components/Post/Embed/ExternalEmbed/index.tsx +++ b/src/components/Post/Embed/ExternalEmbed/index.tsx @@ -97,9 +97,7 @@ export const ExternalEmbed = ({ ]}> {imageUri && !embedPlayerParams ? ( diff --git a/src/components/PostControls/PostMenu/PostMenuItems.tsx b/src/components/PostControls/PostMenu/PostMenuItems.tsx index 2ec0c6a4cd..63501c5952 100644 --- a/src/components/PostControls/PostMenu/PostMenuItems.tsx +++ b/src/components/PostControls/PostMenu/PostMenuItems.tsx @@ -46,7 +46,12 @@ import { useProfileBlockMutationQueue, useProfileMuteMutationQueue, } from '#/state/queries/profile' -import {useToggleReplyVisibilityMutation} from '#/state/queries/threadgate' +import { + InvalidInteractionSettingsError, + MAX_HIDDEN_REPLIES, + MaxHiddenRepliesError, + useToggleReplyVisibilityMutation, +} from '#/state/queries/threadgate' import {useRequireAuth, useSession} from '#/state/session' import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies' import * as Toast from '#/view/com/util/Toast' @@ -339,10 +344,30 @@ let PostMenuItems = ({ : _(msg({message: 'Reply visibility updated', context: 'toast'})), ) } catch (e: any) { - Toast.show( - _(msg({message: 'Updating reply visibility failed', context: 'toast'})), - ) - logger.error(`Failed to ${action} reply`, {safeMessage: e.message}) + if (e instanceof MaxHiddenRepliesError) { + Toast.show( + _( + msg({ + message: `You can hide a maximum of ${MAX_HIDDEN_REPLIES} replies.`, + context: 'toast', + }), + ), + ) + } else if (e instanceof InvalidInteractionSettingsError) { + Toast.show( + _(msg({message: 'Invalid interaction settings.', context: 'toast'})), + ) + } else { + Toast.show( + _( + msg({ + message: 'Updating reply visibility failed', + context: 'toast', + }), + ), + ) + logger.error(`Failed to ${action} reply`, {safeMessage: e.message}) + } } } diff --git a/src/components/PostControls/RepostButton.tsx b/src/components/PostControls/RepostButton.tsx index f34e37c29c..d759f94575 100644 --- a/src/components/PostControls/RepostButton.tsx +++ b/src/components/PostControls/RepostButton.tsx @@ -57,7 +57,7 @@ let RepostButton = ({ @@ -100,7 +100,7 @@ export const RepostButton = ({ requireAuth(() => {})} active={isReposted} - activeColor={t.palette.positive_600} + activeColor={t.palette.positive_500} label={_(msg`Repost or quote post`)} big={big}> diff --git a/src/components/PostControls/ShareMenu/ShareMenuItems.tsx b/src/components/PostControls/ShareMenu/ShareMenuItems.tsx index 03b1137088..2a70a248e5 100644 --- a/src/components/PostControls/ShareMenu/ShareMenuItems.tsx +++ b/src/components/PostControls/ShareMenu/ShareMenuItems.tsx @@ -136,7 +136,9 @@ let ShareMenuItems = ({ {hideInPWI && ( - + This post is only visible to logged-in users. diff --git a/src/components/PostControls/index.tsx b/src/components/PostControls/index.tsx index f91bcd8a5d..c516c2477d 100644 --- a/src/components/PostControls/index.tsx +++ b/src/components/PostControls/index.tsx @@ -210,7 +210,7 @@ let PostControls = ({ a.flex_1, a.align_start, {marginLeft: big ? -2 : -6}, - replyDisabled ? {opacity: 0.5} : undefined, + replyDisabled ? {opacity: 0.6} : undefined, ]}> diff --git a/src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx b/src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx index c45bc3a2c8..3146ddc80e 100644 --- a/src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx +++ b/src/components/ageAssurance/AgeAssuranceRedirectDialog.tsx @@ -159,7 +159,7 @@ export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) { a.pt_lg, a.pb_md, ]}> - + Success diff --git a/src/components/dialogs/EmailDialog/screens/Update.tsx b/src/components/dialogs/EmailDialog/screens/Update.tsx index a0ec69c859..f92e764767 100644 --- a/src/components/dialogs/EmailDialog/screens/Update.tsx +++ b/src/components/dialogs/EmailDialog/screens/Update.tsx @@ -281,7 +281,7 @@ export function Update(_props: ScreenProps) { - + Success! diff --git a/src/components/dialogs/EmailDialog/screens/Verify.tsx b/src/components/dialogs/EmailDialog/screens/Verify.tsx index 74ff9c96be..6116acf2f7 100644 --- a/src/components/dialogs/EmailDialog/screens/Verify.tsx +++ b/src/components/dialogs/EmailDialog/screens/Verify.tsx @@ -176,7 +176,7 @@ export function Verify({config, showScreen}: ScreenProps) { - + {' '} Email verification complete! @@ -202,7 +202,7 @@ export function Verify({config, showScreen}: ScreenProps) { state.mutationStatus === 'success' ? ( <> - + {' '} Email sent! diff --git a/src/components/dialogs/GifSelect.tsx b/src/components/dialogs/GifSelect.tsx index d26cec2c6d..6ac87f4e02 100644 --- a/src/components/dialogs/GifSelect.tsx +++ b/src/components/dialogs/GifSelect.tsx @@ -300,7 +300,8 @@ export function GifPreview({ a.flex_1, a.mb_sm, a.rounded_sm, - {aspectRatio: 1, opacity: pressed ? 0.8 : 1}, + a.aspect_card, + {opacity: pressed ? 0.8 : 1}, t.atoms.bg_contrast_25, ]} source={{ diff --git a/src/components/live/LiveStatusDialog.tsx b/src/components/live/LiveStatusDialog.tsx index 835b69e286..f15650e485 100644 --- a/src/components/live/LiveStatusDialog.tsx +++ b/src/components/live/LiveStatusDialog.tsx @@ -102,7 +102,7 @@ export function LiveStatus({ style={[ t.atoms.bg_contrast_25, a.w_full, - {aspectRatio: 1.91}, + a.aspect_card, android([ a.overflow_hidden, { diff --git a/src/components/moderation/PostHider.tsx b/src/components/moderation/PostHider.tsx index 057c77023a..77910ec1a7 100644 --- a/src/components/moderation/PostHider.tsx +++ b/src/components/moderation/PostHider.tsx @@ -34,6 +34,7 @@ interface Props extends ComponentProps { modui: ModerationUI profile: AppBskyActorDefs.ProfileViewBasic interpretFilterAsBlur?: boolean + hiderStyle?: StyleProp } export function PostHider({ @@ -42,6 +43,7 @@ export function PostHider({ disabled, modui, style, + hiderStyle, children, iconSize, iconStyles, @@ -100,6 +102,7 @@ export function PostHider({ }, override ? {paddingBottom: 0} : undefined, t.atoms.bg, + hiderStyle, ]}> {date} at {time}" msgstr "" -#: src/screens/Search/SearchResults.tsx:255 +#: src/screens/Search/SearchResults.tsx:257 msgid "<0>Sign in<1> or <2>create an account<3> <4>to search for news, sports, politics, and everything else happening on Bluesky." msgstr "" @@ -568,7 +568,7 @@ msgstr "" msgid "Accept Request" msgstr "" -#: src/view/com/composer/select-language/SuggestedLanguage.tsx:179 +#: src/view/com/composer/select-language/SuggestedLanguage.tsx:178 msgid "Accept this language suggestion" msgstr "" @@ -592,18 +592,18 @@ msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:361 #: src/screens/Messages/components/RequestButtons.tsx:91 -#: src/view/com/profile/ProfileMenu.tsx:161 +#: src/view/com/profile/ProfileMenu.tsx:166 msgctxt "toast" msgid "Account blocked" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:174 +#: src/view/com/profile/ProfileMenu.tsx:179 msgctxt "toast" msgid "Account followed" msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:384 -#: src/view/com/profile/ProfileMenu.tsx:137 +#: src/view/com/profile/ProfileMenu.tsx:142 msgctxt "toast" msgid "Account muted" msgstr "" @@ -626,18 +626,18 @@ msgid "Account removed from quick access" msgstr "" #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:132 -#: src/view/com/profile/ProfileMenu.tsx:151 +#: src/view/com/profile/ProfileMenu.tsx:156 msgctxt "toast" msgid "Account unblocked" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:186 +#: src/view/com/profile/ProfileMenu.tsx:191 msgctxt "toast" msgid "Account unfollowed" msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:374 -#: src/view/com/profile/ProfileMenu.tsx:127 +#: src/view/com/profile/ProfileMenu.tsx:132 msgctxt "toast" msgid "Account unmuted" msgstr "" @@ -658,8 +658,8 @@ msgstr "" #: src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx:169 #: src/components/dialogs/MutedWords.tsx:333 -#: src/components/dialogs/StarterPackDialog.tsx:370 -#: src/components/dialogs/StarterPackDialog.tsx:376 +#: src/components/dialogs/StarterPackDialog.tsx:374 +#: src/components/dialogs/StarterPackDialog.tsx:380 #: src/view/com/modals/UserAddRemoveLists.tsx:235 msgid "Add" msgstr "" @@ -668,7 +668,7 @@ msgstr "" msgid "Add {0} more to continue" msgstr "" -#: src/components/StarterPack/Wizard/WizardListCard.tsx:61 +#: src/components/StarterPack/Wizard/WizardListCard.tsx:62 msgid "Add {displayName} to starter pack" msgstr "" @@ -785,8 +785,8 @@ msgstr "" msgid "Add this feed to your feeds" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:317 -#: src/view/com/profile/ProfileMenu.tsx:320 +#: src/view/com/profile/ProfileMenu.tsx:322 +#: src/view/com/profile/ProfileMenu.tsx:325 msgid "Add to lists" msgstr "" @@ -794,9 +794,9 @@ msgstr "" msgid "Add to saved posts" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:175 -#: src/view/com/profile/ProfileMenu.tsx:308 -#: src/view/com/profile/ProfileMenu.tsx:311 +#: src/components/dialogs/StarterPackDialog.tsx:176 +#: src/view/com/profile/ProfileMenu.tsx:313 +#: src/view/com/profile/ProfileMenu.tsx:316 msgid "Add to starter packs" msgstr "" @@ -809,7 +809,7 @@ msgstr "" msgid "Added to list" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:257 +#: src/components/dialogs/StarterPackDialog.tsx:258 msgid "Added to starter pack" msgstr "" @@ -1311,7 +1311,7 @@ msgstr "" msgid "Before creating a post or replying, you must first verify your email." msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:70 +#: src/components/dialogs/StarterPackDialog.tsx:71 #: src/components/StarterPack/ProfileStarterPacks.tsx:231 #: src/components/StarterPack/ProfileStarterPacks.tsx:241 msgid "Before creating a starter pack, you must first verify your email." @@ -1351,7 +1351,7 @@ msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:760 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:328 -#: src/view/com/profile/ProfileMenu.tsx:490 +#: src/view/com/profile/ProfileMenu.tsx:495 msgid "Block" msgstr "" @@ -1361,13 +1361,13 @@ msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:647 #: src/screens/Messages/components/RequestButtons.tsx:144 #: src/screens/Messages/components/RequestButtons.tsx:146 -#: src/view/com/profile/ProfileMenu.tsx:396 -#: src/view/com/profile/ProfileMenu.tsx:403 +#: src/view/com/profile/ProfileMenu.tsx:401 +#: src/view/com/profile/ProfileMenu.tsx:408 msgid "Block account" msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:755 -#: src/view/com/profile/ProfileMenu.tsx:473 +#: src/view/com/profile/ProfileMenu.tsx:478 msgid "Block Account?" msgstr "" @@ -1419,7 +1419,7 @@ msgid "Blocked Accounts" msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:757 -#: src/view/com/profile/ProfileMenu.tsx:485 +#: src/view/com/profile/ProfileMenu.tsx:490 msgid "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you." msgstr "" @@ -1435,7 +1435,7 @@ msgstr "" msgid "Blocking is public. Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you." msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:482 +#: src/view/com/profile/ProfileMenu.tsx:487 msgid "Blocking will not prevent labels from being applied on your account, but it will stop this account from replying in your threads or interacting with you." msgstr "" @@ -1564,7 +1564,7 @@ msgstr "" #: src/components/LabelingServiceCard/index.tsx:62 #: src/components/moderation/ReportDialog/index.tsx:686 #: src/screens/Search/components/StarterPackCard.tsx:106 -#: src/screens/Search/Explore.tsx:930 +#: src/screens/Search/Explore.tsx:940 msgid "By {0}" msgstr "" @@ -1620,7 +1620,7 @@ msgstr "" #: src/screens/Deactivated.tsx:158 #: src/screens/Profile/Header/EditProfileDialog.tsx:218 #: src/screens/Profile/Header/EditProfileDialog.tsx:226 -#: src/screens/Search/Shell.tsx:349 +#: src/screens/Search/Shell.tsx:369 #: src/screens/Settings/AppIconSettings/index.tsx:44 #: src/screens/Settings/AppIconSettings/index.tsx:230 #: src/screens/Settings/components/ChangeHandleDialog.tsx:78 @@ -1657,7 +1657,7 @@ msgstr "" msgid "Cancel reactivation and sign out" msgstr "" -#: src/screens/Search/Shell.tsx:341 +#: src/screens/Search/Shell.tsx:361 msgid "Cancel search" msgstr "" @@ -1920,7 +1920,7 @@ msgstr "" #: src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx:178 #: src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx:187 #: src/components/dialogs/SearchablePeopleList.tsx:295 -#: src/components/dialogs/StarterPackDialog.tsx:178 +#: src/components/dialogs/StarterPackDialog.tsx:179 #: src/components/dms/EmojiPopup.android.tsx:58 #: src/components/dms/ReportDialog.tsx:387 #: src/components/dms/ReportDialog.tsx:396 @@ -1968,7 +1968,7 @@ msgstr "" msgid "Close dialog" msgstr "" -#: src/view/shell/index.web.tsx:110 +#: src/view/shell/index.web.tsx:107 msgid "Close drawer menu" msgstr "" @@ -2281,8 +2281,8 @@ msgstr "" msgid "Copy App Password" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:433 -#: src/view/com/profile/ProfileMenu.tsx:436 +#: src/view/com/profile/ProfileMenu.tsx:438 +#: src/view/com/profile/ProfileMenu.tsx:441 msgid "Copy at:// URI" msgstr "" @@ -2297,8 +2297,8 @@ msgid "Copy code" msgstr "" #: src/screens/Settings/components/ChangeHandleDialog.tsx:501 -#: src/view/com/profile/ProfileMenu.tsx:442 -#: src/view/com/profile/ProfileMenu.tsx:445 +#: src/view/com/profile/ProfileMenu.tsx:447 +#: src/view/com/profile/ProfileMenu.tsx:450 msgid "Copy DID" msgstr "" @@ -2327,8 +2327,8 @@ msgstr "" msgid "Copy link to post" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:246 -#: src/view/com/profile/ProfileMenu.tsx:257 +#: src/view/com/profile/ProfileMenu.tsx:251 +#: src/view/com/profile/ProfileMenu.tsx:262 msgid "Copy link to profile" msgstr "" @@ -2411,8 +2411,8 @@ msgstr "" #. Text on button to create a new starter pack #. Text on button to create a new starter pack -#: src/components/dialogs/StarterPackDialog.tsx:111 -#: src/components/dialogs/StarterPackDialog.tsx:200 +#: src/components/dialogs/StarterPackDialog.tsx:112 +#: src/components/dialogs/StarterPackDialog.tsx:201 #: src/components/StarterPack/ProfileStarterPacks.tsx:296 msgid "Create" msgstr "" @@ -2452,7 +2452,7 @@ msgstr "" #: src/components/dialogs/Signin.tsx:86 #: src/components/dialogs/Signin.tsx:88 -#: src/screens/Search/SearchResults.tsx:266 +#: src/screens/Search/SearchResults.tsx:268 msgid "Create an account" msgstr "" @@ -2483,8 +2483,8 @@ msgstr "" msgid "Create report for {0}" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:106 -#: src/components/dialogs/StarterPackDialog.tsx:195 +#: src/components/dialogs/StarterPackDialog.tsx:107 +#: src/components/dialogs/StarterPackDialog.tsx:196 msgid "Create starter pack" msgstr "" @@ -2518,7 +2518,7 @@ msgstr "" msgid "Customize who can interact with this post." msgstr "" -#: src/screens/Onboarding/Layout.tsx:60 +#: src/screens/Onboarding/Layout.tsx:61 msgid "Customizes your Bluesky experience" msgstr "" @@ -2981,8 +2981,8 @@ msgstr "" msgid "Edit list details" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:329 -#: src/view/com/profile/ProfileMenu.tsx:335 +#: src/view/com/profile/ProfileMenu.tsx:334 +#: src/view/com/profile/ProfileMenu.tsx:340 msgid "Edit live status" msgstr "" @@ -3252,7 +3252,7 @@ msgstr "" msgid "Error:" msgstr "" -#: src/screens/Search/SearchResults.tsx:144 +#: src/screens/Search/SearchResults.tsx:146 msgid "Error: {error}" msgstr "" @@ -3365,7 +3365,7 @@ msgid "Explicit sexual images." msgstr "" #: src/Navigation.tsx:759 -#: src/screens/Search/Shell.tsx:307 +#: src/screens/Search/Shell.tsx:327 #: src/view/shell/desktop/LeftNav.tsx:690 #: src/view/shell/Drawer.tsx:414 msgid "Explore" @@ -3415,7 +3415,7 @@ msgstr "" msgid "Failed to add emoji reaction" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:269 +#: src/components/dialogs/StarterPackDialog.tsx:270 msgid "Failed to add to starter pack" msgstr "" @@ -3521,7 +3521,7 @@ msgstr "" msgid "Failed to remove emoji reaction" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:288 +#: src/components/dialogs/StarterPackDialog.tsx:289 msgid "Failed to remove from starter pack" msgstr "" @@ -3625,7 +3625,7 @@ msgstr "" msgid "Feed menu" msgstr "" -#: src/components/StarterPack/Wizard/WizardListCard.tsx:57 +#: src/components/StarterPack/Wizard/WizardListCard.tsx:58 msgid "Feed toggle" msgstr "" @@ -3647,7 +3647,7 @@ msgstr "" #: src/Navigation.tsx:574 #: src/screens/SavedFeeds.tsx:108 -#: src/screens/Search/SearchResults.tsx:73 +#: src/screens/Search/SearchResults.tsx:75 #: src/screens/StarterPack/StarterPackScreen.tsx:190 #: src/view/screens/Feeds.tsx:511 #: src/view/screens/Profile.tsx:230 @@ -3719,7 +3719,7 @@ msgstr "" msgid "Find people to follow" msgstr "" -#: src/screens/Search/Shell.tsx:475 +#: src/screens/Search/Shell.tsx:525 msgid "Find posts, users, and feeds on Bluesky" msgstr "" @@ -3787,8 +3787,8 @@ msgstr "" msgid "Follow 7 accounts" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:287 -#: src/view/com/profile/ProfileMenu.tsx:298 +#: src/view/com/profile/ProfileMenu.tsx:292 +#: src/view/com/profile/ProfileMenu.tsx:303 msgid "Follow account" msgstr "" @@ -3958,7 +3958,7 @@ msgstr "" msgid "From @{sanitizedAuthor}" msgstr "" -#: src/view/com/posts/PostFeedItem.tsx:327 +#: src/view/com/posts/PostFeedItem.tsx:345 msgctxt "from-feed" msgid "From <0/>" msgstr "" @@ -4079,8 +4079,8 @@ msgstr "" #: src/components/dms/ReportDialog.tsx:197 #: src/components/ReportDialog/SelectReportOptionView.tsx:81 #: src/components/ReportDialog/SubmitView.tsx:110 -#: src/screens/Onboarding/Layout.tsx:120 -#: src/screens/Onboarding/Layout.tsx:213 +#: src/screens/Onboarding/Layout.tsx:121 +#: src/screens/Onboarding/Layout.tsx:214 #: src/screens/Signup/BackNextButtons.tsx:35 msgid "Go back to previous step" msgstr "" @@ -4099,8 +4099,8 @@ msgstr "" msgid "Go Home" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:330 -#: src/view/com/profile/ProfileMenu.tsx:337 +#: src/view/com/profile/ProfileMenu.tsx:335 +#: src/view/com/profile/ProfileMenu.tsx:342 msgid "Go live" msgstr "" @@ -4693,7 +4693,7 @@ msgid "Last initiated just now" msgstr "" #: src/screens/Hashtag.tsx:95 -#: src/screens/Search/SearchResults.tsx:57 +#: src/screens/Search/SearchResults.tsx:59 #: src/screens/Topic.tsx:77 msgid "Latest" msgstr "" @@ -5272,8 +5272,8 @@ msgid "More languages..." msgstr "" #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:149 -#: src/view/com/profile/ProfileMenu.tsx:223 -#: src/view/com/profile/ProfileMenu.tsx:229 +#: src/view/com/profile/ProfileMenu.tsx:228 +#: src/view/com/profile/ProfileMenu.tsx:234 msgid "More options" msgstr "" @@ -5306,8 +5306,8 @@ msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:628 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:634 -#: src/view/com/profile/ProfileMenu.tsx:375 -#: src/view/com/profile/ProfileMenu.tsx:382 +#: src/view/com/profile/ProfileMenu.tsx:380 +#: src/view/com/profile/ProfileMenu.tsx:387 msgid "Mute account" msgstr "" @@ -5548,7 +5548,7 @@ msgstr "" msgid "New posts from {firstAuthorName} and {additionalAuthorsCount, plural, one {{formattedAuthorsCount} other} other {{formattedAuthorsCount} others}}" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:192 +#: src/components/dialogs/StarterPackDialog.tsx:193 msgid "New starter pack" msgstr "" @@ -5685,7 +5685,7 @@ msgstr "" msgid "No results" msgstr "" -#: src/screens/Search/Explore.tsx:787 +#: src/screens/Search/Explore.tsx:797 msgid "No results for \"{0}\"." msgstr "" @@ -5697,13 +5697,13 @@ msgstr "" msgid "No results found for \"{query}\"" msgstr "" -#: src/screens/Search/SearchResults.tsx:311 -#: src/screens/Search/SearchResults.tsx:347 -#: src/screens/Search/SearchResults.tsx:392 +#: src/screens/Search/SearchResults.tsx:313 +#: src/screens/Search/SearchResults.tsx:349 +#: src/screens/Search/SearchResults.tsx:394 msgid "No results found for {query}" msgstr "" -#: src/screens/Search/Explore.tsx:791 +#: src/screens/Search/Explore.tsx:801 msgid "No results." msgstr "" @@ -5758,7 +5758,7 @@ msgstr "" msgid "Not in Mississippi?" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:497 +#: src/view/com/profile/ProfileMenu.tsx:502 msgid "Note about sharing" msgstr "" @@ -6200,7 +6200,7 @@ msgid "Pause video" msgstr "" #: src/screens/ProfileList/index.tsx:166 -#: src/screens/Search/SearchResults.tsx:67 +#: src/screens/Search/SearchResults.tsx:69 #: src/screens/StarterPack/StarterPackScreen.tsx:189 msgid "People" msgstr "" @@ -6222,7 +6222,7 @@ msgstr "" msgid "Permission to access your photo library was denied. Please enable it in your system settings." msgstr "" -#: src/components/StarterPack/Wizard/WizardListCard.tsx:57 +#: src/components/StarterPack/Wizard/WizardListCard.tsx:58 msgid "Person toggle" msgstr "" @@ -6263,7 +6263,7 @@ msgstr "" msgid "Pin to your profile" msgstr "" -#: src/view/com/posts/PostFeedItem.tsx:408 +#: src/view/com/posts/PostFeedItem.tsx:426 msgid "Pinned" msgstr "" @@ -6881,11 +6881,11 @@ msgstr "" #: src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx:171 #: src/components/dialogs/MutedWords.tsx:443 -#: src/components/dialogs/StarterPackDialog.tsx:370 -#: src/components/dialogs/StarterPackDialog.tsx:376 +#: src/components/dialogs/StarterPackDialog.tsx:374 +#: src/components/dialogs/StarterPackDialog.tsx:380 #: src/components/FeedCard.tsx:343 -#: src/components/StarterPack/Wizard/WizardListCard.tsx:104 -#: src/components/StarterPack/Wizard/WizardListCard.tsx:111 +#: src/components/StarterPack/Wizard/WizardListCard.tsx:105 +#: src/components/StarterPack/Wizard/WizardListCard.tsx:112 #: src/screens/Bookmarks/index.tsx:255 #: src/screens/Settings/Settings.tsx:664 #: src/view/com/modals/UserAddRemoveLists.tsx:235 @@ -6893,7 +6893,7 @@ msgstr "" msgid "Remove" msgstr "" -#: src/components/StarterPack/Wizard/WizardListCard.tsx:60 +#: src/components/StarterPack/Wizard/WizardListCard.tsx:61 msgid "Remove {displayName} from starter pack" msgstr "" @@ -6996,8 +6996,8 @@ msgstr "" #: src/components/verification/VerificationRemovePrompt.tsx:46 #: src/components/verification/VerificationsDialog.tsx:252 -#: src/view/com/profile/ProfileMenu.tsx:348 -#: src/view/com/profile/ProfileMenu.tsx:351 +#: src/view/com/profile/ProfileMenu.tsx:353 +#: src/view/com/profile/ProfileMenu.tsx:356 msgid "Remove verification" msgstr "" @@ -7027,7 +7027,7 @@ msgstr "" msgid "Removed from saved posts" msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:276 +#: src/components/dialogs/StarterPackDialog.tsx:277 msgid "Removed from starter pack" msgstr "" @@ -7135,8 +7135,8 @@ msgstr "" msgid "Report" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:415 -#: src/view/com/profile/ProfileMenu.tsx:418 +#: src/view/com/profile/ProfileMenu.tsx:420 +#: src/view/com/profile/ProfileMenu.tsx:423 msgid "Report account" msgstr "" @@ -7246,16 +7246,16 @@ msgstr "" msgid "Reposted By" msgstr "" -#: src/view/com/posts/PostFeedItem.tsx:348 +#: src/view/com/posts/PostFeedItem.tsx:366 msgid "Reposted by {0}" msgstr "" -#: src/view/com/posts/PostFeedItem.tsx:367 +#: src/view/com/posts/PostFeedItem.tsx:385 msgid "Reposted by <0><1/>" msgstr "" -#: src/view/com/posts/PostFeedItem.tsx:346 -#: src/view/com/posts/PostFeedItem.tsx:365 +#: src/view/com/posts/PostFeedItem.tsx:364 +#: src/view/com/posts/PostFeedItem.tsx:383 msgid "Reposted by you" msgstr "" @@ -7500,8 +7500,8 @@ msgstr "" #: src/components/dialogs/SearchablePeopleList.tsx:514 #: src/components/forms/SearchInput.tsx:34 #: src/components/forms/SearchInput.tsx:36 -#: src/screens/Search/Shell.tsx:307 -#: src/screens/Search/Shell.tsx:463 +#: src/screens/Search/Shell.tsx:327 +#: src/screens/Search/Shell.tsx:513 #: src/view/shell/bottom-bar/BottomBar.tsx:198 msgid "Search" msgstr "" @@ -7549,7 +7549,7 @@ msgstr "" msgid "Search for more feeds" msgstr "" -#: src/screens/Search/Shell.tsx:334 +#: src/screens/Search/Shell.tsx:354 msgid "Search for posts, users, or feeds" msgstr "" @@ -7557,7 +7557,7 @@ msgstr "" msgid "Search GIFs" msgstr "" -#: src/screens/Search/SearchResults.tsx:253 +#: src/screens/Search/SearchResults.tsx:255 msgid "Search is currently unavailable when logged out" msgstr "" @@ -7570,8 +7570,8 @@ msgstr "" msgid "Search my posts" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:266 -#: src/view/com/profile/ProfileMenu.tsx:269 +#: src/view/com/profile/ProfileMenu.tsx:271 +#: src/view/com/profile/ProfileMenu.tsx:274 msgid "Search posts" msgstr "" @@ -7861,7 +7861,7 @@ msgstr "" msgid "Set new password" msgstr "" -#: src/screens/Onboarding/Layout.tsx:49 +#: src/screens/Onboarding/Layout.tsx:50 msgid "Set up your account" msgstr "" @@ -7953,7 +7953,7 @@ msgstr "" msgid "Share a fun fact!" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:502 +#: src/view/com/profile/ProfileMenu.tsx:507 msgid "Share anyway" msgstr "" @@ -8001,8 +8001,8 @@ msgstr "" #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:171 #: src/screens/StarterPack/StarterPackScreen.tsx:615 #: src/screens/StarterPack/StarterPackScreen.tsx:623 -#: src/view/com/profile/ProfileMenu.tsx:246 -#: src/view/com/profile/ProfileMenu.tsx:259 +#: src/view/com/profile/ProfileMenu.tsx:251 +#: src/view/com/profile/ProfileMenu.tsx:264 msgid "Share via..." msgstr "" @@ -8132,7 +8132,7 @@ msgstr "" #: src/screens/Login/index.tsx:136 #: src/screens/Login/index.tsx:157 #: src/screens/Login/LoginForm.tsx:181 -#: src/screens/Search/SearchResults.tsx:258 +#: src/screens/Search/SearchResults.tsx:260 #: src/view/com/auth/SplashScreen.tsx:81 #: src/view/com/auth/SplashScreen.tsx:89 #: src/view/com/auth/SplashScreen.web.tsx:127 @@ -8684,7 +8684,7 @@ msgid "That's everything!" msgstr "" #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:324 -#: src/view/com/profile/ProfileMenu.tsx:478 +#: src/view/com/profile/ProfileMenu.tsx:483 msgid "The account will be able to interact with you after unblocking." msgstr "" @@ -8820,7 +8820,7 @@ msgstr "" msgid "There was an issue fetching notifications. Tap here to try again." msgstr "" -#: src/screens/Search/Explore.tsx:986 +#: src/screens/Search/Explore.tsx:996 #: src/view/com/posts/PostFeed.tsx:709 msgid "There was an issue fetching posts. Tap here to try again." msgstr "" @@ -8865,12 +8865,12 @@ msgstr "" #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:101 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:123 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:136 -#: src/view/com/profile/ProfileMenu.tsx:131 -#: src/view/com/profile/ProfileMenu.tsx:141 -#: src/view/com/profile/ProfileMenu.tsx:155 -#: src/view/com/profile/ProfileMenu.tsx:165 -#: src/view/com/profile/ProfileMenu.tsx:178 -#: src/view/com/profile/ProfileMenu.tsx:190 +#: src/view/com/profile/ProfileMenu.tsx:136 +#: src/view/com/profile/ProfileMenu.tsx:146 +#: src/view/com/profile/ProfileMenu.tsx:160 +#: src/view/com/profile/ProfileMenu.tsx:170 +#: src/view/com/profile/ProfileMenu.tsx:183 +#: src/view/com/profile/ProfileMenu.tsx:195 msgid "There was an issue! {0}" msgstr "" @@ -9073,7 +9073,7 @@ msgstr "" msgid "This post's author has disabled quote posts." msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:499 +#: src/view/com/profile/ProfileMenu.tsx:504 msgid "This profile is only visible to logged-in users. It won't be visible to people who aren't signed in." msgstr "" @@ -9199,7 +9199,7 @@ msgid "Toggles the sound" msgstr "" #: src/screens/Hashtag.tsx:84 -#: src/screens/Search/SearchResults.tsx:47 +#: src/screens/Search/SearchResults.tsx:49 #: src/screens/Topic.tsx:71 msgid "Top" msgstr "" @@ -9312,7 +9312,7 @@ msgstr "" #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:328 #: src/screens/ProfileList/components/Header.tsx:171 #: src/screens/ProfileList/components/Header.tsx:178 -#: src/view/com/profile/ProfileMenu.tsx:490 +#: src/view/com/profile/ProfileMenu.tsx:495 msgid "Unblock" msgstr "" @@ -9323,13 +9323,13 @@ msgstr "" #: src/components/dms/ConvoMenu.tsx:247 #: src/components/dms/ConvoMenu.tsx:250 -#: src/view/com/profile/ProfileMenu.tsx:395 -#: src/view/com/profile/ProfileMenu.tsx:401 +#: src/view/com/profile/ProfileMenu.tsx:400 +#: src/view/com/profile/ProfileMenu.tsx:406 msgid "Unblock account" msgstr "" #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:322 -#: src/view/com/profile/ProfileMenu.tsx:472 +#: src/view/com/profile/ProfileMenu.tsx:477 msgid "Unblock Account?" msgstr "" @@ -9362,8 +9362,8 @@ msgstr "" msgid "Unfollow {0}" msgstr "" -#: src/view/com/profile/ProfileMenu.tsx:286 -#: src/view/com/profile/ProfileMenu.tsx:296 +#: src/view/com/profile/ProfileMenu.tsx:291 +#: src/view/com/profile/ProfileMenu.tsx:301 msgid "Unfollow account" msgstr "" @@ -9410,8 +9410,8 @@ msgstr "" #: src/components/PostControls/PostMenu/PostMenuItems.tsx:627 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:633 -#: src/view/com/profile/ProfileMenu.tsx:374 -#: src/view/com/profile/ProfileMenu.tsx:380 +#: src/view/com/profile/ProfileMenu.tsx:379 +#: src/view/com/profile/ProfileMenu.tsx:385 msgid "Unmute account" msgstr "" @@ -9734,8 +9734,8 @@ msgstr "" #: src/components/verification/VerificationCreatePrompt.tsx:84 #: src/components/verification/VerificationCreatePrompt.tsx:86 -#: src/view/com/profile/ProfileMenu.tsx:358 -#: src/view/com/profile/ProfileMenu.tsx:361 +#: src/view/com/profile/ProfileMenu.tsx:363 +#: src/view/com/profile/ProfileMenu.tsx:366 msgid "Verify account" msgstr "" @@ -10143,7 +10143,7 @@ msgstr "" msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again." msgstr "" -#: src/screens/Search/SearchResults.tsx:285 +#: src/screens/Search/SearchResults.tsx:287 msgid "We're sorry, but your search could not be completed. Please try again in a few minutes." msgstr "" @@ -10299,7 +10299,7 @@ msgstr "" msgid "www.mylivestream.tv" msgstr "" -#: src/view/com/composer/select-language/SuggestedLanguage.tsx:181 +#: src/view/com/composer/select-language/SuggestedLanguage.tsx:180 msgid "Yes" msgstr "" @@ -10512,7 +10512,7 @@ msgstr "" msgid "You have no lists." msgstr "" -#: src/components/dialogs/StarterPackDialog.tsx:100 +#: src/components/dialogs/StarterPackDialog.tsx:101 msgid "You have no starter packs." msgstr "" diff --git a/src/logger/sentry/setup/index.ts b/src/logger/sentry/setup/index.ts index d062f05d2b..4fe07e97e2 100644 --- a/src/logger/sentry/setup/index.ts +++ b/src/logger/sentry/setup/index.ts @@ -29,4 +29,5 @@ init({ * @see https://docs.sentry.io/platforms/react-native/configuration/options/#attach-stacktrace */ attachStacktrace: false, + sampleRate: env.IS_INTERNAL ? 1.0 : 0.1, }) diff --git a/src/screens/Messages/components/ChatListItem.tsx b/src/screens/Messages/components/ChatListItem.tsx index cc21a2688a..f4e7863679 100644 --- a/src/screens/Messages/components/ChatListItem.tsx +++ b/src/screens/Messages/components/ChatListItem.tsx @@ -42,11 +42,14 @@ import {Trash_Stroke2_Corner0_Rounded} from '#/components/icons/Trash' import {Link} from '#/components/Link' import {useMenuControl} from '#/components/Menu' import {PostAlerts} from '#/components/moderation/PostAlerts' +import {createPortalGroup} from '#/components/Portal' import {Text} from '#/components/Typography' import {useSimpleVerificationState} from '#/components/verification' import {VerificationCheck} from '#/components/verification/VerificationCheck' import type * as bsky from '#/types/bsky' +export const ChatListItemPortal = createPortalGroup() + export let ChatListItem = ({ convo, showMenu = true, @@ -331,200 +334,215 @@ function ChatListItemReady({ const hasUnread = convo.unreadCount > 0 && !isDeletedAccount return ( - - + + - - - - - {({hovered, pressed, focused}) => ( - - {/* Avatar goes here */} - + onMouseEnter={onMouseEnter} + onMouseLeave={onMouseLeave} + // @ts-expect-error web only + onFocus={onFocus} + onBlur={onMouseLeave} + style={[a.relative, t.atoms.bg]}> + + + + + {({hovered, pressed, focused}) => ( - - + style={[ + a.flex_row, + isDeletedAccount ? a.align_center : a.align_start, + a.flex_1, + a.px_lg, + a.py_md, + a.gap_md, + (hovered || pressed || focused) && t.atoms.bg_contrast_25, + ]}> + {/* Avatar goes here */} + + + + + + + {displayName} + + + {verification.showBadge && ( + + + + )} + {lastMessageSentAt && ( + + + {({timeElapsed}) => ( + + · {timeElapsed} + + )} + + + )} + {(convo.muted || moderation.blocked) && ( + + {' '} + ·{' '} + + + )} + + + {!isDeletedAccount && ( - {displayName} - - - {verification.showBadge && ( - - - - )} - {lastMessageSentAt && ( - - - {({timeElapsed}) => ( - - · {timeElapsed} - - )} - - - )} - {(convo.muted || moderation.blocked) && ( - - {' '} - ·{' '} - + @{profile.handle} )} + + + {lastMessage} + + + + + {children} - {!isDeletedAccount && ( - - @{profile.handle} - + {hasUnread && ( + )} - - - {lastMessage} - - - - - {children} + )} + - {hasUnread && ( - - )} - + + + {showMenu && ( + 0} + hideTrigger={isNative} + blockInfo={blockInfo} + style={[ + a.absolute, + a.h_full, + a.self_end, + a.justify_center, + { + right: tokens.space.lg, + opacity: + !gtMobile || showActions || menuControl.isOpen ? 1 : 0, + }, + ]} + latestReportableMessage={latestReportableMessage} + /> )} - - - {showMenu && ( - 0} - hideTrigger={isNative} - blockInfo={blockInfo} - style={[ - a.absolute, - a.h_full, - a.self_end, - a.justify_center, - { - right: tokens.space.lg, - opacity: !gtMobile || showActions || menuControl.isOpen ? 1 : 0, - }, - ]} - latestReportableMessage={latestReportableMessage} /> - )} - - - + + + ) } diff --git a/src/screens/Messages/components/ChatStatusInfo.tsx b/src/screens/Messages/components/ChatStatusInfo.tsx index c02034ff32..0cebabfd11 100644 --- a/src/screens/Messages/components/ChatStatusInfo.tsx +++ b/src/screens/Messages/components/ChatStatusInfo.tsx @@ -46,7 +46,7 @@ export function ChatStatusInfo({convoState}: {convoState: ActiveConvoStates}) { label={_(msg`Block or report`)} convo={convoState.convo} profile={otherUser} - color="negative" + color="negative_subtle" size="small" currentScreen="conversation" /> @@ -70,8 +70,7 @@ export function ChatStatusInfo({convoState}: {convoState: ActiveConvoStates}) { diff --git a/src/screens/Messages/components/RequestButtons.tsx b/src/screens/Messages/components/RequestButtons.tsx index 560888552b..4437a9a43f 100644 --- a/src/screens/Messages/components/RequestButtons.tsx +++ b/src/screens/Messages/components/RequestButtons.tsx @@ -36,7 +36,6 @@ export function RejectMenu({ convo, profile, size = 'tiny', - variant = 'outline', color = 'secondary', label, showDeleteConvo, @@ -117,7 +116,6 @@ export function RejectMenu({ label={triggerProps.accessibilityLabel} style={[a.flex_1]} color={color} - variant={variant} size={size}> {label || ( @@ -129,7 +127,7 @@ export function RejectMenu({ )} - + {showDeleteConvo && ( @@ -266,7 +262,6 @@ export function AcceptChatButton({ export function DeleteChatButton({ convo, size = 'tiny', - variant = 'outline', color = 'secondary', label, currentScreen, @@ -315,7 +310,6 @@ export function DeleteChatButton({