Merge remote-tracking branch 'origin/main' into samuel/value-prop-pager

* origin/main: (28 commits)
  fix android admonition flex collapse issue (#9120)
  Keep the screen awake on the video feed (#9146)
  Add accessibilityRole to single images (#9148)
  Fix chat request buttons not moving with swipe gesture (#9155)
  fix hider alignment in thread (#9168)
  move aspect ratio to atom (#9171)
  fix background colors (#9174)
  Placeholder style tweaks (#9107)
  Tweak greens (#9177)
  add 10% sample rate to sentry (#9182)
  Ship activation experiments (#9170)
  Add validation to threadgate records, check for max hidden replies (#9178)
  Nightly source-language update
  reply button in feeds opens thread (#9143)
  Fix language prompt text wrap issue (#9175)
  Auto-select search results tab (#9159)
  fix: copy-paste mistake and more idiomatic structured data format
  fix: show both DisplayName and Handle in google structured data (or only Handle if DisplayName not set)
  [16KB] use 16kb-compatible fork of react-native-mmkv (#9150)
  nit
  ...
This commit is contained in:
Eric Bailey
2025-10-10 13:43:37 -05:00
74 changed files with 2774 additions and 588 deletions
+26
View File
@@ -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
+2
View File
@@ -4,6 +4,7 @@
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite",
"dev-snippet": "tsc --project tsconfig.snippet.json && serve -s dist -p 3000 -n",
"build": "tsc && vite build", "build": "tsc && vite build",
"build-snippet": "tsc --project tsconfig.snippet.json", "build-snippet": "tsc --project tsconfig.snippet.json",
"lint": "eslint --cache --ext .js,.jsx,.ts,.tsx src", "lint": "eslint --cache --ext .js,.jsx,.ts,.tsx src",
@@ -21,6 +22,7 @@
"eslint-config-preact": "^1.3.0", "eslint-config-preact": "^1.3.0",
"eslint-plugin-simple-import-sort": "^12.0.0", "eslint-plugin-simple-import-sort": "^12.0.0",
"postcss": "^8.4.38", "postcss": "^8.4.38",
"serve": "^14.2.5",
"tailwindcss": "^3.4.3", "tailwindcss": "^3.4.3",
"terser": "^5.43.1", "terser": "^5.43.1",
"typescript": "^5.8.3", "typescript": "^5.8.3",
+11 -1
View File
@@ -3,9 +3,19 @@ interface Window {
bluesky: { bluesky: {
scan: (element?: Pick<Element, 'querySelectorAll'>) => void scan: (element?: Pick<Element, 'querySelectorAll'>) => 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 || { window.bluesky = window.bluesky || {
scan, scan,
+2 -2
View File
@@ -330,7 +330,7 @@ function ExternalEmbed({
{content.external.thumb && ( {content.external.thumb && (
<img <img
src={content.external.thumb} src={content.external.thumb}
className="aspect-[1.91/1] object-cover" className="aspect-[1200/630] object-cover"
/> />
)} )}
<div className="py-3 px-4"> <div className="py-3 px-4">
@@ -435,7 +435,7 @@ function StarterPackEmbed({
<Link <Link
href={starterPackHref} href={starterPackHref}
className="w-full rounded-xl overflow-hidden border dark:border-slate-600 flex flex-col items-stretch"> className="w-full rounded-xl overflow-hidden border dark:border-slate-600 flex flex-col items-stretch">
<img src={imageUri} className="aspect-[1.91/1] object-cover" /> <img src={imageUri} className="aspect-[1200/630] object-cover" />
<div className="py-3 px-4"> <div className="py-3 px-4">
<div className="flex space-x-2 items-center"> <div className="flex space-x-2 items-center">
<img src={starterPackIcon} className="w-10 h-10" /> <img src={starterPackIcon} className="w-10 h-10" />
+1054
View File
File diff suppressed because it is too large Load Diff
+32 -1
View File
@@ -1,10 +1,40 @@
import fs from 'node:fs'
import {resolve} from 'node:path' import {resolve} from 'node:path'
import preact from '@preact/preset-vite' import preact from '@preact/preset-vite'
import legacy from '@vitejs/plugin-legacy' import legacy from '@vitejs/plugin-legacy'
import type {UserConfig} from 'vite' import type {Plugin, UserConfig} from 'vite'
import paths from 'vite-tsconfig-paths' 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 = { const config: UserConfig = {
plugins: [ plugins: [
preact(), preact(),
@@ -12,6 +42,7 @@ const config: UserConfig = {
legacy({ legacy({
targets: ['defaults', 'not IE 11'], targets: ['defaults', 'not IE 11'],
}), }),
devOnlyRouter(),
], ],
build: { build: {
assetsDir: 'static', assetsDir: 'static',
+376 -5
View File
@@ -1447,6 +1447,11 @@
regenerator-runtime "^0.14.1" regenerator-runtime "^0.14.1"
systemjs "^6.15.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: acorn-jsx@^5.3.2:
version "5.3.2" version "5.3.2"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" 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" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg== 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: ajv@^6.12.4:
version "6.12.6" version "6.12.6"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" 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" json-schema-traverse "^0.4.1"
uri-js "^4.2.2" 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: ansi-regex@^5.0.1:
version "5.0.1" version "5.0.1"
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" 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" normalize-path "^3.0.0"
picomatch "^2.0.4" 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" version "5.0.2"
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c" resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
integrity sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg== 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" resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e"
integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== 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: brace-expansion@^1.1.7:
version "1.1.11" version "1.1.11"
resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 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" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== 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: call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7:
version "1.0.7" version "1.0.7"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" 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" resolved "https://registry.yarnpkg.com/camelcase-css/-/camelcase-css-2.0.1.tgz#ee978f6947914cc30c6b44741b6ed1df7f043fd5"
integrity sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA== 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: caniuse-lite@^1.0.30001524:
version "1.0.30001606" version "1.0.30001606"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001606.tgz#b4d5f67ab0746a3b8b5b6d1f06e39c51beb39a9e" 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" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001727.tgz#22e9706422ad37aa50556af8c10e40e2d93a8b85"
integrity sha512-pB68nIHmbN6L/4C6MH1DokyR3bYqFwjaSs/sWDHGj4CTcFtQUQMuJftVwWkXq7mNWOybD3KhUv3oWHoGxgP14Q== 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" version "4.1.2"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01"
integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==
@@ -1777,6 +1845,11 @@ chalk@^4.0.0:
ansi-styles "^4.1.0" ansi-styles "^4.1.0"
supports-color "^7.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: chokidar@^3.5.3:
version "3.6.0" version "3.6.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
@@ -1792,6 +1865,20 @@ chokidar@^3.5.3:
optionalDependencies: optionalDependencies:
fsevents "~2.3.2" 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: color-convert@^2.0.1:
version "2.0.1" version "2.0.1"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" 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" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068"
integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== 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: concat-map@0.0.1:
version "0.0.1" version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== 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: convert-source-map@^2.0.0:
version "2.0.0" version "2.0.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" 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" shebang-command "^2.0.0"
which "^2.0.1" 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: css-select@^5.1.0:
version "5.2.2" version "5.2.2"
resolved "https://registry.yarnpkg.com/css-select/-/css-select-5.2.2.tgz#01b6e8d163637bb2dd6c982ca4ed65863682786e" 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" es-errors "^1.3.0"
is-data-view "^1.0.1" 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: debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.4, debug@^4.4.1:
version "4.4.1" version "4.4.1"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b"
@@ -1907,6 +2035,11 @@ debug@^4.3.2:
dependencies: dependencies:
ms "2.1.2" 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: deep-is@^0.1.3:
version "0.1.4" version "0.1.4"
resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" 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" resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== 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: fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
version "3.1.3" version "3.1.3"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" 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" has-symbols "^1.0.3"
hasown "^2.0.0" 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: get-symbol-description@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" 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" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== 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: ignore@^5.2.0:
version "5.3.1" version "5.3.1"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" 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" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 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: internal-slot@^1.0.7:
version "1.0.7" version "1.0.7"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" 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: dependencies:
has-tostringtag "^1.0.0" 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: is-extglob@^2.1.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" 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" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283"
integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== 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: is-regex@^1.1.4:
version "1.1.4" version "1.1.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" 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: dependencies:
call-bind "^1.0.7" 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: is-string@^1.0.5, is-string@^1.0.7:
version "1.0.7" version "1.0.7"
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" 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" call-bind "^1.0.7"
get-intrinsic "^1.2.4" 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: isarray@^2.0.5:
version "2.0.5" version "2.0.5"
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" 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" resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 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: json-stable-stringify-without-jsonify@^1.0.1:
version "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" 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" resolved "https://registry.yarnpkg.com/meow/-/meow-13.2.0.tgz#6b7d63f913f984063b3cc261b6e8800c4cd3474f"
integrity sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA== 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: merge2@^1.3.0, merge2@^1.4.1:
version "1.4.1" version "1.4.1"
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" 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" braces "^3.0.2"
picomatch "^2.3.1" 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" version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
@@ -3074,11 +3291,21 @@ minimatch@^9.0.1:
dependencies: dependencies:
brace-expansion "^2.0.1" 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: "minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4:
version "7.0.4" version "7.0.4"
resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c"
integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== 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: ms@2.1.2:
version "2.1.2" version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" 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" resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== 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: node-html-parser@^6.1.12:
version "6.1.13" version "6.1.13"
resolved "https://registry.yarnpkg.com/node-html-parser/-/node-html-parser-6.1.13.tgz#a1df799b83df5c6743fcd92740ba14682083b7e4" 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" resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA== 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: nth-check@^2.0.1:
version "2.1.1" version "2.1.1"
resolved "https://registry.yarnpkg.com/nth-check/-/nth-check-2.1.1.tgz#c9eab428effce36cd6b92c924bdb000ef1f1ed1d" 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" define-properties "^1.2.1"
es-object-atoms "^1.0.0" 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: once@^1.3.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@@ -3222,6 +3466,13 @@ once@^1.3.0:
dependencies: dependencies:
wrappy "1" 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: optionator@^0.9.3:
version "0.9.3" version "0.9.3"
resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" 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" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== 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" version "3.1.1"
resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
@@ -3283,6 +3539,11 @@ path-scurry@^1.10.2:
lru-cache "^10.2.0" lru-cache "^10.2.0"
minipass "^5.0.0 || ^6.0.2 || ^7.0.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: path-type@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" 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" resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== 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: react-is@^16.13.1:
version "16.13.1" version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" 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-ecmascript "^2.0.0"
unicode-match-property-value-ecmascript "^2.1.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: regjsgen@^0.8.0:
version "0.8.0" version "0.8.0"
resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.8.0.tgz#df23ff26e0c5b300a6470cad160a9d090c3a37ab" resolved "https://registry.yarnpkg.com/regjsgen/-/regjsgen-0.8.0.tgz#df23ff26e0c5b300a6470cad160a9d090c3a37ab"
@@ -3492,6 +3783,11 @@ regjsparser@^0.12.0:
dependencies: dependencies:
jsesc "~3.0.2" 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: resolve-from@^4.0.0:
version "4.0.0" version "4.0.0"
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" 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" has-symbols "^1.0.3"
isarray "^2.0.5" 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: safe-regex-test@^1.0.3:
version "1.0.3" version "1.0.3"
resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" 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: dependencies:
lru-cache "^6.0.0" 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: set-function-length@^1.2.1:
version "1.2.2" version "1.2.2"
resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" 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" get-intrinsic "^1.2.4"
object-inspect "^1.13.1" 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: signal-exit@^4.0.1:
version "4.1.0" version "4.1.0"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
@@ -3791,11 +4127,21 @@ strip-ansi@^7.0.1:
dependencies: dependencies:
ansi-regex "^6.0.1" 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: strip-json-comments@^3.1.1:
version "3.1.1" version "3.1.1"
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== 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: sucrase@^3.32.0:
version "3.35.0" version "3.35.0"
resolved "https://registry.yarnpkg.com/sucrase/-/sucrase-3.35.0.tgz#57f17a3d7e19b36d8995f06679d121be914ae263" 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" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4"
integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== 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: typed-array-buffer@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" 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" escalade "^3.2.0"
picocolors "^1.1.1" 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: uri-js@^4.2.2:
version "4.4.1" version "4.4.1"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" 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" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf"
integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== 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: vite-prerender-plugin@^0.5.3:
version "0.5.11" version "0.5.11"
resolved "https://registry.yarnpkg.com/vite-prerender-plugin/-/vite-prerender-plugin-0.5.11.tgz#83e4f29e03269dceb763fb5ec2376dcc502aa79f" 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: dependencies:
isexe "^2.0.0" 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": "wrap-ansi-cjs@npm:wrap-ansi@^7.0.0":
version "7.0.0" version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" 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" string-width "^4.1.0"
strip-ansi "^6.0.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" version "8.1.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"
integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==
+49 -13
View File
@@ -458,6 +458,18 @@ func (srv *Server) WebHome(c echo.Context) error {
return c.Render(http.StatusOK, "home.html", data) 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 { func (srv *Server) WebPost(c echo.Context) error {
ctx := c.Request().Context() ctx := c.Request().Context()
data := srv.NewTemplateContext() data := srv.NewTemplateContext()
@@ -512,19 +524,15 @@ func (srv *Server) WebPost(c echo.Context) error {
postView := tpv.Thread.FeedDefs_ThreadViewPost.Post postView := tpv.Thread.FeedDefs_ThreadViewPost.Post
data["postView"] = postView data["postView"] = postView
data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path) data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
if postView.Embed != nil {
if postView.Embed.EmbedImages_View != nil { // If any undesirable labels are set, the embed will not be included in
var thumbUrls []string // metadata
for i := range postView.Embed.EmbedImages_View.Images { isEmbedHidden := false
thumbUrls = append(thumbUrls, postView.Embed.EmbedImages_View.Images[i].Thumb) for _, label := range postView.Labels {
} isNeg := label.Neg != nil && *label.Neg
data["imgThumbUrls"] = thumbUrls if hideEmbedLabels[label.Val] && !isNeg {
} else if postView.Embed.EmbedRecordWithMedia_View != nil && postView.Embed.EmbedRecordWithMedia_View.Media != nil && postView.Embed.EmbedRecordWithMedia_View.Media.EmbedImages_View != nil { isEmbedHidden = true
var thumbUrls []string break
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
} }
} }
@@ -532,6 +540,34 @@ func (srv *Server) WebPost(c echo.Context) error {
postRecord, ok := postView.Record.Val.(*appbsky.FeedPost) postRecord, ok := postView.Record.Val.(*appbsky.FeedPost)
if ok { if ok {
data["postText"] = ExpandPostText(postRecord) 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
} }
} }
+5
View File
@@ -62,7 +62,12 @@
"@type": "DiscussionForumPosting", "@type": "DiscussionForumPosting",
"author": { "author": {
"@type": "Person", "@type": "Person",
{%- if postView.Author.DisplayName %}
"name": "{{ 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 }}" "url": "https://bsky.app/profile/{{ postView.Author.Handle }}"
}, },
{%- if postText %} {%- if postText %}
+4
View File
@@ -59,8 +59,12 @@
"dateCreated": "{{ profileView.CreatedAt }}", "dateCreated": "{{ profileView.CreatedAt }}",
"mainEntity": { "mainEntity": {
"@type": "Person", "@type": "Person",
{%- if profileView.DisplayName %}
"name": "{{ profileView.DisplayName }}", "name": "{{ profileView.DisplayName }}",
"alternateName": "@{{ profileView.Handle }}", "alternateName": "@{{ profileView.Handle }}",
{% else %}
"name": "@{{ profileView.Handle }}",
{% endif -%}
"identifier": "{{ profileView.Did }}", "identifier": "{{ profileView.Did }}",
"description": "{{ profileView.Description }}", "description": "{{ profileView.Description }}",
"image": "{{ profileView.Avatar }}", "image": "{{ profileView.Avatar }}",
+2 -1
View File
@@ -145,6 +145,7 @@
"expo-image-manipulator": "~14.0.7", "expo-image-manipulator": "~14.0.7",
"expo-image-picker": "~17.0.8", "expo-image-picker": "~17.0.8",
"expo-intent-launcher": "~13.0.7", "expo-intent-launcher": "~13.0.7",
"expo-keep-awake": "^15.0.7",
"expo-linear-gradient": "~15.0.7", "expo-linear-gradient": "~15.0.7",
"expo-linking": "~8.0.8", "expo-linking": "~8.0.8",
"expo-localization": "~17.0.7", "expo-localization": "~17.0.7",
@@ -192,7 +193,7 @@
"react-native-gesture-handler": "~2.28.0", "react-native-gesture-handler": "~2.28.0",
"react-native-get-random-values": "~1.11.0", "react-native-get-random-values": "~1.11.0",
"react-native-keyboard-controller": "1.18.5", "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-pager-view": "6.8.0",
"react-native-progress": "bluesky-social/react-native-progress", "react-native-progress": "bluesky-social/react-native-progress",
"react-native-qrcode-styled": "^0.3.3", "react-native-qrcode-styled": "^0.3.3",
@@ -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<Int, Int>(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",
@@ -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.
+22
View File
@@ -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, {
+3
View File
@@ -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.
+12 -1
View File
@@ -1,6 +1,7 @@
import {type StyleProp, type ViewStyle} from 'react-native' import {type StyleProp, type ViewStyle} from 'react-native'
import {atoms as baseAtoms} from '@bsky.app/alf' import {atoms as baseAtoms} from '@bsky.app/alf'
import {CARD_ASPECT_RATIO} from '#/lib/constants'
import {native, platform, web} from '#/alf/util/platform' import {native, platform, web} from '#/alf/util/platform'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
@@ -31,6 +32,16 @@ export const atoms = {
backgroundColor: 'transparent', backgroundColor: 'transparent',
}, },
/**
* Aspect ratios
*/
aspect_square: {
aspectRatio: 1,
},
aspect_card: {
aspectRatio: CARD_ASPECT_RATIO,
},
/* /*
* Transition * Transition
*/ */
@@ -67,7 +78,7 @@ export const atoms = {
}), }),
/* /*
* Animaations * Animations
*/ */
fade_in: web({ fade_in: web({
animation: 'fadeIn ease-out 0.15s', animation: 'fadeIn ease-out 0.15s',
+1 -1
View File
@@ -172,7 +172,7 @@ function AccountItem({
</View> </View>
{isCurrentAccount ? ( {isCurrentAccount ? (
<Check size="sm" style={[{color: t.palette.positive_600}]} /> <Check size="sm" style={[{color: t.palette.positive_500}]} />
) : ( ) : (
<Chevron size="sm" style={[t.atoms.text]} /> <Chevron size="sm" style={[t.atoms.text]} />
)} )}
+1 -1
View File
@@ -87,7 +87,7 @@ export function Row({
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
}) { }) {
return ( return (
<View style={[a.flex_1, a.flex_row, a.align_start, a.gap_sm, style]}> <View style={[a.w_full, a.flex_row, a.align_start, a.gap_sm, style]}>
{children} {children}
</View> </View>
) )
+2 -2
View File
@@ -258,7 +258,7 @@ export function InterestTabs({
t.atoms.border_contrast_low, t.atoms.border_contrast_low,
t.atoms.bg, t.atoms.bg,
a.h_full, a.h_full,
{aspectRatio: 1}, a.aspect_square,
a.rounded_full, a.rounded_full,
]}> ]}>
<ButtonIcon icon={ArrowLeft} /> <ButtonIcon icon={ArrowLeft} />
@@ -292,7 +292,7 @@ export function InterestTabs({
t.atoms.border_contrast_low, t.atoms.border_contrast_low,
t.atoms.bg, t.atoms.bg,
a.h_full, a.h_full,
{aspectRatio: 1}, a.aspect_square,
a.rounded_full, a.rounded_full,
]}> ]}>
<ButtonIcon icon={ArrowRight} /> <ButtonIcon icon={ArrowRight} />
+28
View File
@@ -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 <KeepAwakeInner />
} 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
}
+3
View File
@@ -0,0 +1,3 @@
export function KeepAwake() {
return null
}
-82
View File
@@ -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 (
<View style={[a.pb_md, style]}>
<View
style={[
a.flex_row,
a.align_center,
a.justify_between,
a.px_lg,
a.py_md,
a.rounded_md,
a.mb_xs,
t.atoms.bg_contrast_25,
]}>
<View style={[a.flex_row, a.align_center, a.flex_1, a.pr_md]}>
<Logo width={30} style={[a.mr_md]} />
<View style={[a.flex_1]}>
<Text style={[a.text_lg, a.font_semi_bold, a.leading_snug]}>
<Trans>Join Bluesky</Trans>
</Text>
<Text
style={[
a.text_md,
a.font_medium,
a.leading_snug,
t.atoms.text_contrast_medium,
]}>
<Trans>The open social network.</Trans>
</Text>
</View>
</View>
<Button
onPress={() => {
requestSwitchToAccount({requestedAccount: 'new'})
}}
label={_(msg`Create account`)}
size="small"
variant="solid"
color="primary">
<ButtonText>
<Trans>Create account</Trans>
</ButtonText>
</Button>
</View>
</View>
)
}
+3 -2
View File
@@ -87,7 +87,7 @@ export function ImageItem({
}) { }) {
const t = useTheme() const t = useTheme()
return ( return (
<View style={[a.relative, a.flex_1, {aspectRatio: 1, maxWidth: 100}]}> <View style={[a.relative, a.flex_1, a.aspect_square, {maxWidth: 100}]}>
<Image <Image
key={thumbnail} key={thumbnail}
source={{uri: thumbnail}} source={{uri: thumbnail}}
@@ -131,7 +131,8 @@ export function VideoItem({
style={[ style={[
{backgroundColor: 'black'}, {backgroundColor: 'black'},
a.flex_1, a.flex_1,
{aspectRatio: 1, maxWidth: 100}, a.aspect_square,
{maxWidth: 100},
a.justify_center, a.justify_center,
a.align_center, a.align_center,
]}> ]}>
@@ -97,9 +97,7 @@ export const ExternalEmbed = ({
]}> ]}>
{imageUri && !embedPlayerParams ? ( {imageUri && !embedPlayerParams ? (
<Image <Image
style={{ style={[a.aspect_card]}
aspectRatio: 1.91,
}}
source={{uri: imageUri}} source={{uri: imageUri}}
accessibilityIgnoresInvertColors accessibilityIgnoresInvertColors
/> />
@@ -46,7 +46,12 @@ import {
useProfileBlockMutationQueue, useProfileBlockMutationQueue,
useProfileMuteMutationQueue, useProfileMuteMutationQueue,
} from '#/state/queries/profile' } 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 {useRequireAuth, useSession} from '#/state/session'
import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies' import {useMergedThreadgateHiddenReplies} from '#/state/threadgate-hidden-replies'
import * as Toast from '#/view/com/util/Toast' import * as Toast from '#/view/com/util/Toast'
@@ -339,12 +344,32 @@ let PostMenuItems = ({
: _(msg({message: 'Reply visibility updated', context: 'toast'})), : _(msg({message: 'Reply visibility updated', context: 'toast'})),
) )
} catch (e: any) { } catch (e: any) {
if (e instanceof MaxHiddenRepliesError) {
Toast.show( Toast.show(
_(msg({message: 'Updating reply visibility failed', context: 'toast'})), _(
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}) logger.error(`Failed to ${action} reply`, {safeMessage: e.message})
} }
} }
}
const onPressPin = () => { const onPressPin = () => {
logEvent(isPinned ? 'post:unpin' : 'post:pin', {}) logEvent(isPinned ? 'post:unpin' : 'post:pin', {})
+1 -1
View File
@@ -57,7 +57,7 @@ let RepostButton = ({
<PostControlButton <PostControlButton
testID="repostBtn" testID="repostBtn"
active={isReposted} active={isReposted}
activeColor={t.palette.positive_600} activeColor={t.palette.positive_500}
big={big} big={big}
onPress={onPress} onPress={onPress}
onLongPress={onLongPress} onLongPress={onLongPress}
@@ -47,7 +47,7 @@ export const RepostButton = ({
<PostControlButton <PostControlButton
testID="repostBtn" testID="repostBtn"
active={isReposted} active={isReposted}
activeColor={t.palette.positive_600} activeColor={t.palette.positive_500}
label={props.accessibilityLabel} label={props.accessibilityLabel}
big={big} big={big}
{...props}> {...props}>
@@ -100,7 +100,7 @@ export const RepostButton = ({
<PostControlButton <PostControlButton
onPress={() => requireAuth(() => {})} onPress={() => requireAuth(() => {})}
active={isReposted} active={isReposted}
activeColor={t.palette.positive_600} activeColor={t.palette.positive_500}
label={_(msg`Repost or quote post`)} label={_(msg`Repost or quote post`)}
big={big}> big={big}>
<PostControlButtonIcon icon={Repost} /> <PostControlButtonIcon icon={Repost} />
@@ -136,7 +136,9 @@ let ShareMenuItems = ({
{hideInPWI && ( {hideInPWI && (
<Menu.Group> <Menu.Group>
<Menu.ContainerItem> <Menu.ContainerItem>
<Admonition type="warning" style={[a.flex_1, a.border_0, a.p_0]}> <Admonition
type="warning"
style={[a.flex_1, a.border_0, a.p_0, a.bg_transparent]}>
<Trans>This post is only visible to logged-in users.</Trans> <Trans>This post is only visible to logged-in users.</Trans>
</Admonition> </Admonition>
</Menu.ContainerItem> </Menu.ContainerItem>
+1 -1
View File
@@ -210,7 +210,7 @@ let PostControls = ({
a.flex_1, a.flex_1,
a.align_start, a.align_start,
{marginLeft: big ? -2 : -6}, {marginLeft: big ? -2 : -6},
replyDisabled ? {opacity: 0.5} : undefined, replyDisabled ? {opacity: 0.6} : undefined,
]}> ]}>
<PostControlButton <PostControlButton
testID="replyBtn" testID="replyBtn"
+3 -3
View File
@@ -32,7 +32,7 @@ export function Text({blend, style}: TextStyleProp & SkeletonProps) {
<View <View
style={[ style={[
a.rounded_md, a.rounded_md,
t.atoms.bg_contrast_25, t.atoms.bg_contrast_50,
{ {
height: lineHeight * 0.7, height: lineHeight * 0.7,
opacity: blend ? 0.6 : 1, opacity: blend ? 0.6 : 1,
@@ -57,7 +57,7 @@ export function Circle({
a.justify_center, a.justify_center,
a.align_center, a.align_center,
a.rounded_full, a.rounded_full,
t.atoms.bg_contrast_25, t.atoms.bg_contrast_50,
{ {
width: size, width: size,
height: size, height: size,
@@ -80,7 +80,7 @@ export function Pill({
<View <View
style={[ style={[
a.rounded_full, a.rounded_full,
t.atoms.bg_contrast_25, t.atoms.bg_contrast_50,
{ {
width: size * 1.618, width: size * 1.618,
height: size, height: size,
+1 -1
View File
@@ -91,8 +91,8 @@ function ShareDialogInner({
source={{uri: imageUrl}} source={{uri: imageUrl}}
style={[ style={[
a.rounded_sm, a.rounded_sm,
a.aspect_card,
{ {
aspectRatio: 1200 / 630,
transform: [{scale: gtMobile ? 0.85 : 1}], transform: [{scale: gtMobile ? 0.85 : 1}],
marginTop: gtMobile ? -20 : 0, marginTop: gtMobile ? -20 : 0,
}, },
@@ -191,7 +191,7 @@ export function Embed({
<Link starterPack={starterPack}> <Link starterPack={starterPack}>
<Image <Image
source={imageUri} source={imageUri}
style={[a.w_full, {aspectRatio: 1.91}]} style={[a.w_full, a.aspect_card]}
accessibilityIgnoresInvertColors={true} accessibilityIgnoresInvertColors={true}
/> />
<View style={[a.px_sm, a.py_md]}> <View style={[a.px_sm, a.py_md]}>
@@ -159,7 +159,7 @@ export function Inner({}: {optimisticState?: AgeAssuranceRedirectDialogState}) {
a.pt_lg, a.pt_lg,
a.pb_md, a.pb_md,
]}> ]}>
<SuccessIcon size="sm" fill={t.palette.positive_600} /> <SuccessIcon size="sm" fill={t.palette.positive_500} />
<Text style={[a.text_xl, a.font_bold]}> <Text style={[a.text_xl, a.font_bold]}>
<Trans>Success</Trans> <Trans>Success</Trans>
</Text> </Text>
@@ -281,7 +281,7 @@ export function Update(_props: ScreenProps<ScreenID.Update>) {
<Divider /> <Divider />
<View style={[a.gap_sm]}> <View style={[a.gap_sm]}>
<View style={[a.flex_row, a.gap_sm, a.align_center]}> <View style={[a.flex_row, a.gap_sm, a.align_center]}>
<Check fill={t.palette.positive_600} size="xs" /> <Check fill={t.palette.positive_500} size="xs" />
<Text style={[a.text_md, a.font_bold]}> <Text style={[a.text_md, a.font_bold]}>
<Trans>Success!</Trans> <Trans>Success!</Trans>
</Text> </Text>
@@ -176,7 +176,7 @@ export function Verify({config, showScreen}: ScreenProps<ScreenID.Verify>) {
<View style={[a.gap_sm]}> <View style={[a.gap_sm]}>
<Text style={[a.text_xl, a.font_bold]}> <Text style={[a.text_xl, a.font_bold]}>
<Span style={{top: 1}}> <Span style={{top: 1}}>
<Check size="sm" fill={t.palette.positive_600} /> <Check size="sm" fill={t.palette.positive_500} />
</Span> </Span>
{' '} {' '}
<Trans>Email verification complete!</Trans> <Trans>Email verification complete!</Trans>
@@ -202,7 +202,7 @@ export function Verify({config, showScreen}: ScreenProps<ScreenID.Verify>) {
state.mutationStatus === 'success' ? ( state.mutationStatus === 'success' ? (
<> <>
<Span style={{top: 1}}> <Span style={{top: 1}}>
<Check size="sm" fill={t.palette.positive_600} /> <Check size="sm" fill={t.palette.positive_500} />
</Span> </Span>
{' '} {' '}
<Trans>Email sent!</Trans> <Trans>Email sent!</Trans>
+2 -1
View File
@@ -300,7 +300,8 @@ export function GifPreview({
a.flex_1, a.flex_1,
a.mb_sm, a.mb_sm,
a.rounded_sm, a.rounded_sm,
{aspectRatio: 1, opacity: pressed ? 0.8 : 1}, a.aspect_card,
{opacity: pressed ? 0.8 : 1},
t.atoms.bg_contrast_25, t.atoms.bg_contrast_25,
]} ]}
source={{ source={{
+1 -1
View File
@@ -102,7 +102,7 @@ export function LiveStatus({
style={[ style={[
t.atoms.bg_contrast_25, t.atoms.bg_contrast_25,
a.w_full, a.w_full,
{aspectRatio: 1.91}, a.aspect_card,
android([ android([
a.overflow_hidden, a.overflow_hidden,
{ {
+3
View File
@@ -34,6 +34,7 @@ interface Props extends ComponentProps<typeof Link> {
modui: ModerationUI modui: ModerationUI
profile: AppBskyActorDefs.ProfileViewBasic profile: AppBskyActorDefs.ProfileViewBasic
interpretFilterAsBlur?: boolean interpretFilterAsBlur?: boolean
hiderStyle?: StyleProp<ViewStyle>
} }
export function PostHider({ export function PostHider({
@@ -42,6 +43,7 @@ export function PostHider({
disabled, disabled,
modui, modui,
style, style,
hiderStyle,
children, children,
iconSize, iconSize,
iconStyles, iconStyles,
@@ -100,6 +102,7 @@ export function PostHider({
}, },
override ? {paddingBottom: 0} : undefined, override ? {paddingBottom: 0} : undefined,
t.atoms.bg, t.atoms.bg,
hiderStyle,
]}> ]}>
<ModerationDetailsDialog control={control} modcause={blur} /> <ModerationDetailsDialog control={control} modcause={blur} />
<Pressable <Pressable
+2 -2
View File
@@ -21,12 +21,12 @@ export const ENV: string = process.env.EXPO_PUBLIC_ENV
export const IS_TESTFLIGHT = ENV === 'testflight' export const IS_TESTFLIGHT = ENV === 'testflight'
/** /**
* Indicates whether the app is __DEV__ * Indicates whether the app is `__DEV__`
*/ */
export const IS_DEV = __DEV__ export const IS_DEV = __DEV__
/** /**
* Indicates whether the app is __DEV__ or TestFlight * Indicates whether the app is `__DEV__` or TestFlight
*/ */
export const IS_INTERNAL = IS_DEV || IS_TESTFLIGHT export const IS_INTERNAL = IS_DEV || IS_TESTFLIGHT
+1
View File
@@ -17,6 +17,7 @@ export const EMBED_SERVICE = 'https://embed.bsky.app'
export const EMBED_SCRIPT = `${EMBED_SERVICE}/static/embed.js` export const EMBED_SCRIPT = `${EMBED_SERVICE}/static/embed.js`
export const BSKY_DOWNLOAD_URL = 'https://bsky.app/download' export const BSKY_DOWNLOAD_URL = 'https://bsky.app/download'
export const STARTER_PACK_MAX_SIZE = 150 export const STARTER_PACK_MAX_SIZE = 150
export const CARD_ASPECT_RATIO = 1200 / 630
// HACK // HACK
// Yes, this is exactly what it looks like. It's a hard-coded constant // Yes, this is exactly what it looks like. It's a hard-coded constant
+4 -1
View File
@@ -62,7 +62,10 @@ export async function getLinkMeta(
likelyType, likelyType,
url, url,
} }
if (likelyType !== LikelyType.HTML) { const htmlExemptedHostnames: string[] = ['storage.courtlistener.com']
const isExemptedFromHtmlCheck = htmlExemptedHostnames.includes(urlp.hostname)
// Skip early return only for hosts exempted from the HTML check
if (likelyType !== LikelyType.HTML && !isExemptedFromHtmlCheck) {
return meta return meta
} }
+4 -4
View File
@@ -67,7 +67,7 @@ export type CommonNavigatorParams = {
InterestsSettings: undefined InterestsSettings: undefined
AboutSettings: undefined AboutSettings: undefined
AppIconSettings: undefined AppIconSettings: undefined
Search: {q?: string} Search: {q?: string; tab?: 'user' | 'profile' | 'feed'}
Hashtag: {tag: string; author?: string} Hashtag: {tag: string; author?: string}
Topic: {topic: string} Topic: {topic: string}
MessagesConversation: {conversation: string; embed?: string; accept?: true} MessagesConversation: {conversation: string; embed?: string; accept?: true}
@@ -102,7 +102,7 @@ export type HomeTabNavigatorParams = CommonNavigatorParams & {
} }
export type SearchTabNavigatorParams = CommonNavigatorParams & { export type SearchTabNavigatorParams = CommonNavigatorParams & {
Search: {q?: string} Search: {q?: string; tab?: 'user' | 'profile' | 'feed'}
} }
export type NotificationsTabNavigatorParams = CommonNavigatorParams & { export type NotificationsTabNavigatorParams = CommonNavigatorParams & {
@@ -119,7 +119,7 @@ export type MessagesTabNavigatorParams = CommonNavigatorParams & {
export type FlatNavigatorParams = CommonNavigatorParams & { export type FlatNavigatorParams = CommonNavigatorParams & {
Home: undefined Home: undefined
Search: {q?: string} Search: {q?: string; tab?: 'user' | 'profile' | 'feed'}
Feeds: undefined Feeds: undefined
Notifications: undefined Notifications: undefined
Messages: {pushToConversation?: string; animation?: 'push' | 'pop'} Messages: {pushToConversation?: string; animation?: 'push' | 'pop'}
@@ -129,7 +129,7 @@ export type AllNavigatorParams = CommonNavigatorParams & {
HomeTab: undefined HomeTab: undefined
Home: undefined Home: undefined
SearchTab: undefined SearchTab: undefined
Search: {q?: string} Search: {q?: string; tab?: 'user' | 'profile' | 'feed'}
Feeds: undefined Feeds: undefined
NotificationsTab: undefined NotificationsTab: undefined
Notifications: undefined Notifications: undefined
+1 -5
View File
@@ -1,18 +1,14 @@
export type Gate = export type Gate =
// Keep this alphabetic please. // Keep this alphabetic please.
| 'alt_share_icon' | 'alt_share_icon'
| 'cta_above_post_heading'
| 'cta_above_post_replies'
| 'debug_show_feedcontext' | 'debug_show_feedcontext'
| 'debug_subscriptions' | 'debug_subscriptions'
| 'disable_onboarding_policy_update_notice' | 'disable_onboarding_policy_update_notice'
| 'explore_show_suggested_feeds' | 'explore_show_suggested_feeds'
| 'feed_reply_button_open_thread'
| 'old_postonboarding' | 'old_postonboarding'
| 'onboarding_add_video_feed' | 'onboarding_add_video_feed'
| 'onboarding_suggested_accounts'
| 'onboarding_value_prop'
| 'post_follow_profile_suggested_accounts' | 'post_follow_profile_suggested_accounts'
| 'remove_show_latest_button' | 'remove_show_latest_button'
| 'test_gate_1' | 'test_gate_1'
| 'test_gate_2' | 'test_gate_2'
| 'welcome_modal'
+121 -121
View File
@@ -124,7 +124,7 @@ msgstr ""
msgid "{0, plural, other {# people have}} used this starter pack!" msgid "{0, plural, other {# people have}} used this starter pack!"
msgstr "" msgstr ""
#: src/components/dialogs/StarterPackDialog.tsx:356 #: src/components/dialogs/StarterPackDialog.tsx:360
msgid "{0, plural, other {+# more}}" msgid "{0, plural, other {+# more}}"
msgstr "" msgstr ""
@@ -493,7 +493,7 @@ msgstr ""
msgid "<0>{date}</0> at {time}" msgid "<0>{date}</0> at {time}"
msgstr "" msgstr ""
#: src/screens/Search/SearchResults.tsx:255 #: src/screens/Search/SearchResults.tsx:257
msgid "<0>Sign in</0><1> or </1><2>create an account</2><3> </3><4>to search for news, sports, politics, and everything else happening on Bluesky.</4>" msgid "<0>Sign in</0><1> or </1><2>create an account</2><3> </3><4>to search for news, sports, politics, and everything else happening on Bluesky.</4>"
msgstr "" msgstr ""
@@ -568,7 +568,7 @@ msgstr ""
msgid "Accept Request" msgid "Accept Request"
msgstr "" msgstr ""
#: src/view/com/composer/select-language/SuggestedLanguage.tsx:179 #: src/view/com/composer/select-language/SuggestedLanguage.tsx:178
msgid "Accept this language suggestion" msgid "Accept this language suggestion"
msgstr "" msgstr ""
@@ -592,18 +592,18 @@ msgstr ""
#: src/components/PostControls/PostMenu/PostMenuItems.tsx:361 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:361
#: src/screens/Messages/components/RequestButtons.tsx:91 #: src/screens/Messages/components/RequestButtons.tsx:91
#: src/view/com/profile/ProfileMenu.tsx:161 #: src/view/com/profile/ProfileMenu.tsx:166
msgctxt "toast" msgctxt "toast"
msgid "Account blocked" msgid "Account blocked"
msgstr "" msgstr ""
#: src/view/com/profile/ProfileMenu.tsx:174 #: src/view/com/profile/ProfileMenu.tsx:179
msgctxt "toast" msgctxt "toast"
msgid "Account followed" msgid "Account followed"
msgstr "" msgstr ""
#: src/components/PostControls/PostMenu/PostMenuItems.tsx:384 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:384
#: src/view/com/profile/ProfileMenu.tsx:137 #: src/view/com/profile/ProfileMenu.tsx:142
msgctxt "toast" msgctxt "toast"
msgid "Account muted" msgid "Account muted"
msgstr "" msgstr ""
@@ -626,18 +626,18 @@ msgid "Account removed from quick access"
msgstr "" msgstr ""
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:132 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:132
#: src/view/com/profile/ProfileMenu.tsx:151 #: src/view/com/profile/ProfileMenu.tsx:156
msgctxt "toast" msgctxt "toast"
msgid "Account unblocked" msgid "Account unblocked"
msgstr "" msgstr ""
#: src/view/com/profile/ProfileMenu.tsx:186 #: src/view/com/profile/ProfileMenu.tsx:191
msgctxt "toast" msgctxt "toast"
msgid "Account unfollowed" msgid "Account unfollowed"
msgstr "" msgstr ""
#: src/components/PostControls/PostMenu/PostMenuItems.tsx:374 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:374
#: src/view/com/profile/ProfileMenu.tsx:127 #: src/view/com/profile/ProfileMenu.tsx:132
msgctxt "toast" msgctxt "toast"
msgid "Account unmuted" msgid "Account unmuted"
msgstr "" msgstr ""
@@ -658,8 +658,8 @@ msgstr ""
#: src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx:169 #: src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx:169
#: src/components/dialogs/MutedWords.tsx:333 #: src/components/dialogs/MutedWords.tsx:333
#: src/components/dialogs/StarterPackDialog.tsx:370 #: src/components/dialogs/StarterPackDialog.tsx:374
#: src/components/dialogs/StarterPackDialog.tsx:376 #: src/components/dialogs/StarterPackDialog.tsx:380
#: src/view/com/modals/UserAddRemoveLists.tsx:235 #: src/view/com/modals/UserAddRemoveLists.tsx:235
msgid "Add" msgid "Add"
msgstr "" msgstr ""
@@ -668,7 +668,7 @@ msgstr ""
msgid "Add {0} more to continue" msgid "Add {0} more to continue"
msgstr "" msgstr ""
#: src/components/StarterPack/Wizard/WizardListCard.tsx:61 #: src/components/StarterPack/Wizard/WizardListCard.tsx:62
msgid "Add {displayName} to starter pack" msgid "Add {displayName} to starter pack"
msgstr "" msgstr ""
@@ -785,8 +785,8 @@ msgstr ""
msgid "Add this feed to your feeds" msgid "Add this feed to your feeds"
msgstr "" msgstr ""
#: src/view/com/profile/ProfileMenu.tsx:317 #: src/view/com/profile/ProfileMenu.tsx:322
#: src/view/com/profile/ProfileMenu.tsx:320 #: src/view/com/profile/ProfileMenu.tsx:325
msgid "Add to lists" msgid "Add to lists"
msgstr "" msgstr ""
@@ -794,9 +794,9 @@ msgstr ""
msgid "Add to saved posts" msgid "Add to saved posts"
msgstr "" msgstr ""
#: src/components/dialogs/StarterPackDialog.tsx:175 #: src/components/dialogs/StarterPackDialog.tsx:176
#: src/view/com/profile/ProfileMenu.tsx:308 #: src/view/com/profile/ProfileMenu.tsx:313
#: src/view/com/profile/ProfileMenu.tsx:311 #: src/view/com/profile/ProfileMenu.tsx:316
msgid "Add to starter packs" msgid "Add to starter packs"
msgstr "" msgstr ""
@@ -809,7 +809,7 @@ msgstr ""
msgid "Added to list" msgid "Added to list"
msgstr "" msgstr ""
#: src/components/dialogs/StarterPackDialog.tsx:257 #: src/components/dialogs/StarterPackDialog.tsx:258
msgid "Added to starter pack" msgid "Added to starter pack"
msgstr "" msgstr ""
@@ -1311,7 +1311,7 @@ msgstr ""
msgid "Before creating a post or replying, you must first verify your email." msgid "Before creating a post or replying, you must first verify your email."
msgstr "" msgstr ""
#: src/components/dialogs/StarterPackDialog.tsx:70 #: src/components/dialogs/StarterPackDialog.tsx:71
#: src/components/StarterPack/ProfileStarterPacks.tsx:231 #: src/components/StarterPack/ProfileStarterPacks.tsx:231
#: src/components/StarterPack/ProfileStarterPacks.tsx:241 #: src/components/StarterPack/ProfileStarterPacks.tsx:241
msgid "Before creating a starter pack, you must first verify your email." 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/components/PostControls/PostMenu/PostMenuItems.tsx:760
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:328 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:328
#: src/view/com/profile/ProfileMenu.tsx:490 #: src/view/com/profile/ProfileMenu.tsx:495
msgid "Block" msgid "Block"
msgstr "" msgstr ""
@@ -1361,13 +1361,13 @@ msgstr ""
#: src/components/PostControls/PostMenu/PostMenuItems.tsx:647 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:647
#: src/screens/Messages/components/RequestButtons.tsx:144 #: src/screens/Messages/components/RequestButtons.tsx:144
#: src/screens/Messages/components/RequestButtons.tsx:146 #: src/screens/Messages/components/RequestButtons.tsx:146
#: src/view/com/profile/ProfileMenu.tsx:396 #: src/view/com/profile/ProfileMenu.tsx:401
#: src/view/com/profile/ProfileMenu.tsx:403 #: src/view/com/profile/ProfileMenu.tsx:408
msgid "Block account" msgid "Block account"
msgstr "" msgstr ""
#: src/components/PostControls/PostMenu/PostMenuItems.tsx:755 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:755
#: src/view/com/profile/ProfileMenu.tsx:473 #: src/view/com/profile/ProfileMenu.tsx:478
msgid "Block Account?" msgid "Block Account?"
msgstr "" msgstr ""
@@ -1419,7 +1419,7 @@ msgid "Blocked Accounts"
msgstr "" msgstr ""
#: src/components/PostControls/PostMenu/PostMenuItems.tsx:757 #: 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." msgid "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you."
msgstr "" msgstr ""
@@ -1435,7 +1435,7 @@ msgstr ""
msgid "Blocking is public. Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you." msgid "Blocking is public. Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you."
msgstr "" 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." 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 "" msgstr ""
@@ -1564,7 +1564,7 @@ msgstr ""
#: src/components/LabelingServiceCard/index.tsx:62 #: src/components/LabelingServiceCard/index.tsx:62
#: src/components/moderation/ReportDialog/index.tsx:686 #: src/components/moderation/ReportDialog/index.tsx:686
#: src/screens/Search/components/StarterPackCard.tsx:106 #: src/screens/Search/components/StarterPackCard.tsx:106
#: src/screens/Search/Explore.tsx:930 #: src/screens/Search/Explore.tsx:940
msgid "By {0}" msgid "By {0}"
msgstr "" msgstr ""
@@ -1620,7 +1620,7 @@ msgstr ""
#: src/screens/Deactivated.tsx:158 #: src/screens/Deactivated.tsx:158
#: src/screens/Profile/Header/EditProfileDialog.tsx:218 #: src/screens/Profile/Header/EditProfileDialog.tsx:218
#: src/screens/Profile/Header/EditProfileDialog.tsx:226 #: 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:44
#: src/screens/Settings/AppIconSettings/index.tsx:230 #: src/screens/Settings/AppIconSettings/index.tsx:230
#: src/screens/Settings/components/ChangeHandleDialog.tsx:78 #: src/screens/Settings/components/ChangeHandleDialog.tsx:78
@@ -1657,7 +1657,7 @@ msgstr ""
msgid "Cancel reactivation and sign out" msgid "Cancel reactivation and sign out"
msgstr "" msgstr ""
#: src/screens/Search/Shell.tsx:341 #: src/screens/Search/Shell.tsx:361
msgid "Cancel search" msgid "Cancel search"
msgstr "" msgstr ""
@@ -1920,7 +1920,7 @@ msgstr ""
#: src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx:178 #: src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx:178
#: src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx:187 #: src/components/dialogs/nuxs/InitialVerificationAnnouncement.tsx:187
#: src/components/dialogs/SearchablePeopleList.tsx:295 #: 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/EmojiPopup.android.tsx:58
#: src/components/dms/ReportDialog.tsx:387 #: src/components/dms/ReportDialog.tsx:387
#: src/components/dms/ReportDialog.tsx:396 #: src/components/dms/ReportDialog.tsx:396
@@ -1968,7 +1968,7 @@ msgstr ""
msgid "Close dialog" msgid "Close dialog"
msgstr "" msgstr ""
#: src/view/shell/index.web.tsx:110 #: src/view/shell/index.web.tsx:107
msgid "Close drawer menu" msgid "Close drawer menu"
msgstr "" msgstr ""
@@ -2281,8 +2281,8 @@ msgstr ""
msgid "Copy App Password" msgid "Copy App Password"
msgstr "" msgstr ""
#: src/view/com/profile/ProfileMenu.tsx:433 #: src/view/com/profile/ProfileMenu.tsx:438
#: src/view/com/profile/ProfileMenu.tsx:436 #: src/view/com/profile/ProfileMenu.tsx:441
msgid "Copy at:// URI" msgid "Copy at:// URI"
msgstr "" msgstr ""
@@ -2297,8 +2297,8 @@ msgid "Copy code"
msgstr "" msgstr ""
#: src/screens/Settings/components/ChangeHandleDialog.tsx:501 #: src/screens/Settings/components/ChangeHandleDialog.tsx:501
#: src/view/com/profile/ProfileMenu.tsx:442 #: src/view/com/profile/ProfileMenu.tsx:447
#: src/view/com/profile/ProfileMenu.tsx:445 #: src/view/com/profile/ProfileMenu.tsx:450
msgid "Copy DID" msgid "Copy DID"
msgstr "" msgstr ""
@@ -2327,8 +2327,8 @@ msgstr ""
msgid "Copy link to post" msgid "Copy link to post"
msgstr "" msgstr ""
#: src/view/com/profile/ProfileMenu.tsx:246 #: src/view/com/profile/ProfileMenu.tsx:251
#: src/view/com/profile/ProfileMenu.tsx:257 #: src/view/com/profile/ProfileMenu.tsx:262
msgid "Copy link to profile" msgid "Copy link to profile"
msgstr "" msgstr ""
@@ -2411,8 +2411,8 @@ msgstr ""
#. Text on button to create a new starter pack #. Text on button to create a new starter pack
#. 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:112
#: src/components/dialogs/StarterPackDialog.tsx:200 #: src/components/dialogs/StarterPackDialog.tsx:201
#: src/components/StarterPack/ProfileStarterPacks.tsx:296 #: src/components/StarterPack/ProfileStarterPacks.tsx:296
msgid "Create" msgid "Create"
msgstr "" msgstr ""
@@ -2452,7 +2452,7 @@ msgstr ""
#: src/components/dialogs/Signin.tsx:86 #: src/components/dialogs/Signin.tsx:86
#: src/components/dialogs/Signin.tsx:88 #: src/components/dialogs/Signin.tsx:88
#: src/screens/Search/SearchResults.tsx:266 #: src/screens/Search/SearchResults.tsx:268
msgid "Create an account" msgid "Create an account"
msgstr "" msgstr ""
@@ -2483,8 +2483,8 @@ msgstr ""
msgid "Create report for {0}" msgid "Create report for {0}"
msgstr "" msgstr ""
#: src/components/dialogs/StarterPackDialog.tsx:106 #: src/components/dialogs/StarterPackDialog.tsx:107
#: src/components/dialogs/StarterPackDialog.tsx:195 #: src/components/dialogs/StarterPackDialog.tsx:196
msgid "Create starter pack" msgid "Create starter pack"
msgstr "" msgstr ""
@@ -2518,7 +2518,7 @@ msgstr ""
msgid "Customize who can interact with this post." msgid "Customize who can interact with this post."
msgstr "" msgstr ""
#: src/screens/Onboarding/Layout.tsx:60 #: src/screens/Onboarding/Layout.tsx:61
msgid "Customizes your Bluesky experience" msgid "Customizes your Bluesky experience"
msgstr "" msgstr ""
@@ -2981,8 +2981,8 @@ msgstr ""
msgid "Edit list details" msgid "Edit list details"
msgstr "" msgstr ""
#: src/view/com/profile/ProfileMenu.tsx:329 #: src/view/com/profile/ProfileMenu.tsx:334
#: src/view/com/profile/ProfileMenu.tsx:335 #: src/view/com/profile/ProfileMenu.tsx:340
msgid "Edit live status" msgid "Edit live status"
msgstr "" msgstr ""
@@ -3252,7 +3252,7 @@ msgstr ""
msgid "Error:" msgid "Error:"
msgstr "" msgstr ""
#: src/screens/Search/SearchResults.tsx:144 #: src/screens/Search/SearchResults.tsx:146
msgid "Error: {error}" msgid "Error: {error}"
msgstr "" msgstr ""
@@ -3365,7 +3365,7 @@ msgid "Explicit sexual images."
msgstr "" msgstr ""
#: src/Navigation.tsx:759 #: 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/desktop/LeftNav.tsx:690
#: src/view/shell/Drawer.tsx:414 #: src/view/shell/Drawer.tsx:414
msgid "Explore" msgid "Explore"
@@ -3415,7 +3415,7 @@ msgstr ""
msgid "Failed to add emoji reaction" msgid "Failed to add emoji reaction"
msgstr "" msgstr ""
#: src/components/dialogs/StarterPackDialog.tsx:269 #: src/components/dialogs/StarterPackDialog.tsx:270
msgid "Failed to add to starter pack" msgid "Failed to add to starter pack"
msgstr "" msgstr ""
@@ -3521,7 +3521,7 @@ msgstr ""
msgid "Failed to remove emoji reaction" msgid "Failed to remove emoji reaction"
msgstr "" msgstr ""
#: src/components/dialogs/StarterPackDialog.tsx:288 #: src/components/dialogs/StarterPackDialog.tsx:289
msgid "Failed to remove from starter pack" msgid "Failed to remove from starter pack"
msgstr "" msgstr ""
@@ -3625,7 +3625,7 @@ msgstr ""
msgid "Feed menu" msgid "Feed menu"
msgstr "" msgstr ""
#: src/components/StarterPack/Wizard/WizardListCard.tsx:57 #: src/components/StarterPack/Wizard/WizardListCard.tsx:58
msgid "Feed toggle" msgid "Feed toggle"
msgstr "" msgstr ""
@@ -3647,7 +3647,7 @@ msgstr ""
#: src/Navigation.tsx:574 #: src/Navigation.tsx:574
#: src/screens/SavedFeeds.tsx:108 #: src/screens/SavedFeeds.tsx:108
#: src/screens/Search/SearchResults.tsx:73 #: src/screens/Search/SearchResults.tsx:75
#: src/screens/StarterPack/StarterPackScreen.tsx:190 #: src/screens/StarterPack/StarterPackScreen.tsx:190
#: src/view/screens/Feeds.tsx:511 #: src/view/screens/Feeds.tsx:511
#: src/view/screens/Profile.tsx:230 #: src/view/screens/Profile.tsx:230
@@ -3719,7 +3719,7 @@ msgstr ""
msgid "Find people to follow" msgid "Find people to follow"
msgstr "" msgstr ""
#: src/screens/Search/Shell.tsx:475 #: src/screens/Search/Shell.tsx:525
msgid "Find posts, users, and feeds on Bluesky" msgid "Find posts, users, and feeds on Bluesky"
msgstr "" msgstr ""
@@ -3787,8 +3787,8 @@ msgstr ""
msgid "Follow 7 accounts" msgid "Follow 7 accounts"
msgstr "" msgstr ""
#: src/view/com/profile/ProfileMenu.tsx:287 #: src/view/com/profile/ProfileMenu.tsx:292
#: src/view/com/profile/ProfileMenu.tsx:298 #: src/view/com/profile/ProfileMenu.tsx:303
msgid "Follow account" msgid "Follow account"
msgstr "" msgstr ""
@@ -3958,7 +3958,7 @@ msgstr ""
msgid "From @{sanitizedAuthor}" msgid "From @{sanitizedAuthor}"
msgstr "" msgstr ""
#: src/view/com/posts/PostFeedItem.tsx:327 #: src/view/com/posts/PostFeedItem.tsx:345
msgctxt "from-feed" msgctxt "from-feed"
msgid "From <0/>" msgid "From <0/>"
msgstr "" msgstr ""
@@ -4079,8 +4079,8 @@ msgstr ""
#: src/components/dms/ReportDialog.tsx:197 #: src/components/dms/ReportDialog.tsx:197
#: src/components/ReportDialog/SelectReportOptionView.tsx:81 #: src/components/ReportDialog/SelectReportOptionView.tsx:81
#: src/components/ReportDialog/SubmitView.tsx:110 #: src/components/ReportDialog/SubmitView.tsx:110
#: src/screens/Onboarding/Layout.tsx:120 #: src/screens/Onboarding/Layout.tsx:121
#: src/screens/Onboarding/Layout.tsx:213 #: src/screens/Onboarding/Layout.tsx:214
#: src/screens/Signup/BackNextButtons.tsx:35 #: src/screens/Signup/BackNextButtons.tsx:35
msgid "Go back to previous step" msgid "Go back to previous step"
msgstr "" msgstr ""
@@ -4099,8 +4099,8 @@ msgstr ""
msgid "Go Home" msgid "Go Home"
msgstr "" msgstr ""
#: src/view/com/profile/ProfileMenu.tsx:330 #: src/view/com/profile/ProfileMenu.tsx:335
#: src/view/com/profile/ProfileMenu.tsx:337 #: src/view/com/profile/ProfileMenu.tsx:342
msgid "Go live" msgid "Go live"
msgstr "" msgstr ""
@@ -4693,7 +4693,7 @@ msgid "Last initiated just now"
msgstr "" msgstr ""
#: src/screens/Hashtag.tsx:95 #: src/screens/Hashtag.tsx:95
#: src/screens/Search/SearchResults.tsx:57 #: src/screens/Search/SearchResults.tsx:59
#: src/screens/Topic.tsx:77 #: src/screens/Topic.tsx:77
msgid "Latest" msgid "Latest"
msgstr "" msgstr ""
@@ -5272,8 +5272,8 @@ msgid "More languages..."
msgstr "" msgstr ""
#: src/screens/ProfileList/components/MoreOptionsMenu.tsx:149 #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:149
#: src/view/com/profile/ProfileMenu.tsx:223 #: src/view/com/profile/ProfileMenu.tsx:228
#: src/view/com/profile/ProfileMenu.tsx:229 #: src/view/com/profile/ProfileMenu.tsx:234
msgid "More options" msgid "More options"
msgstr "" msgstr ""
@@ -5306,8 +5306,8 @@ msgstr ""
#: src/components/PostControls/PostMenu/PostMenuItems.tsx:628 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:628
#: src/components/PostControls/PostMenu/PostMenuItems.tsx:634 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:634
#: src/view/com/profile/ProfileMenu.tsx:375 #: src/view/com/profile/ProfileMenu.tsx:380
#: src/view/com/profile/ProfileMenu.tsx:382 #: src/view/com/profile/ProfileMenu.tsx:387
msgid "Mute account" msgid "Mute account"
msgstr "" msgstr ""
@@ -5548,7 +5548,7 @@ msgstr ""
msgid "New posts from {firstAuthorName} and {additionalAuthorsCount, plural, one {{formattedAuthorsCount} other} other {{formattedAuthorsCount} others}}" msgid "New posts from {firstAuthorName} and {additionalAuthorsCount, plural, one {{formattedAuthorsCount} other} other {{formattedAuthorsCount} others}}"
msgstr "" msgstr ""
#: src/components/dialogs/StarterPackDialog.tsx:192 #: src/components/dialogs/StarterPackDialog.tsx:193
msgid "New starter pack" msgid "New starter pack"
msgstr "" msgstr ""
@@ -5685,7 +5685,7 @@ msgstr ""
msgid "No results" msgid "No results"
msgstr "" msgstr ""
#: src/screens/Search/Explore.tsx:787 #: src/screens/Search/Explore.tsx:797
msgid "No results for \"{0}\"." msgid "No results for \"{0}\"."
msgstr "" msgstr ""
@@ -5697,13 +5697,13 @@ msgstr ""
msgid "No results found for \"{query}\"" msgid "No results found for \"{query}\""
msgstr "" msgstr ""
#: src/screens/Search/SearchResults.tsx:311 #: src/screens/Search/SearchResults.tsx:313
#: src/screens/Search/SearchResults.tsx:347 #: src/screens/Search/SearchResults.tsx:349
#: src/screens/Search/SearchResults.tsx:392 #: src/screens/Search/SearchResults.tsx:394
msgid "No results found for {query}" msgid "No results found for {query}"
msgstr "" msgstr ""
#: src/screens/Search/Explore.tsx:791 #: src/screens/Search/Explore.tsx:801
msgid "No results." msgid "No results."
msgstr "" msgstr ""
@@ -5758,7 +5758,7 @@ msgstr ""
msgid "Not in Mississippi?" msgid "Not in Mississippi?"
msgstr "" msgstr ""
#: src/view/com/profile/ProfileMenu.tsx:497 #: src/view/com/profile/ProfileMenu.tsx:502
msgid "Note about sharing" msgid "Note about sharing"
msgstr "" msgstr ""
@@ -6200,7 +6200,7 @@ msgid "Pause video"
msgstr "" msgstr ""
#: src/screens/ProfileList/index.tsx:166 #: src/screens/ProfileList/index.tsx:166
#: src/screens/Search/SearchResults.tsx:67 #: src/screens/Search/SearchResults.tsx:69
#: src/screens/StarterPack/StarterPackScreen.tsx:189 #: src/screens/StarterPack/StarterPackScreen.tsx:189
msgid "People" msgid "People"
msgstr "" msgstr ""
@@ -6222,7 +6222,7 @@ msgstr ""
msgid "Permission to access your photo library was denied. Please enable it in your system settings." msgid "Permission to access your photo library was denied. Please enable it in your system settings."
msgstr "" msgstr ""
#: src/components/StarterPack/Wizard/WizardListCard.tsx:57 #: src/components/StarterPack/Wizard/WizardListCard.tsx:58
msgid "Person toggle" msgid "Person toggle"
msgstr "" msgstr ""
@@ -6263,7 +6263,7 @@ msgstr ""
msgid "Pin to your profile" msgid "Pin to your profile"
msgstr "" msgstr ""
#: src/view/com/posts/PostFeedItem.tsx:408 #: src/view/com/posts/PostFeedItem.tsx:426
msgid "Pinned" msgid "Pinned"
msgstr "" msgstr ""
@@ -6881,11 +6881,11 @@ msgstr ""
#: src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx:171 #: src/components/dialogs/lists/ListAddRemoveUsersDialog.tsx:171
#: src/components/dialogs/MutedWords.tsx:443 #: src/components/dialogs/MutedWords.tsx:443
#: src/components/dialogs/StarterPackDialog.tsx:370 #: src/components/dialogs/StarterPackDialog.tsx:374
#: src/components/dialogs/StarterPackDialog.tsx:376 #: src/components/dialogs/StarterPackDialog.tsx:380
#: src/components/FeedCard.tsx:343 #: src/components/FeedCard.tsx:343
#: src/components/StarterPack/Wizard/WizardListCard.tsx:104 #: src/components/StarterPack/Wizard/WizardListCard.tsx:105
#: src/components/StarterPack/Wizard/WizardListCard.tsx:111 #: src/components/StarterPack/Wizard/WizardListCard.tsx:112
#: src/screens/Bookmarks/index.tsx:255 #: src/screens/Bookmarks/index.tsx:255
#: src/screens/Settings/Settings.tsx:664 #: src/screens/Settings/Settings.tsx:664
#: src/view/com/modals/UserAddRemoveLists.tsx:235 #: src/view/com/modals/UserAddRemoveLists.tsx:235
@@ -6893,7 +6893,7 @@ msgstr ""
msgid "Remove" msgid "Remove"
msgstr "" msgstr ""
#: src/components/StarterPack/Wizard/WizardListCard.tsx:60 #: src/components/StarterPack/Wizard/WizardListCard.tsx:61
msgid "Remove {displayName} from starter pack" msgid "Remove {displayName} from starter pack"
msgstr "" msgstr ""
@@ -6996,8 +6996,8 @@ msgstr ""
#: src/components/verification/VerificationRemovePrompt.tsx:46 #: src/components/verification/VerificationRemovePrompt.tsx:46
#: src/components/verification/VerificationsDialog.tsx:252 #: src/components/verification/VerificationsDialog.tsx:252
#: src/view/com/profile/ProfileMenu.tsx:348 #: src/view/com/profile/ProfileMenu.tsx:353
#: src/view/com/profile/ProfileMenu.tsx:351 #: src/view/com/profile/ProfileMenu.tsx:356
msgid "Remove verification" msgid "Remove verification"
msgstr "" msgstr ""
@@ -7027,7 +7027,7 @@ msgstr ""
msgid "Removed from saved posts" msgid "Removed from saved posts"
msgstr "" msgstr ""
#: src/components/dialogs/StarterPackDialog.tsx:276 #: src/components/dialogs/StarterPackDialog.tsx:277
msgid "Removed from starter pack" msgid "Removed from starter pack"
msgstr "" msgstr ""
@@ -7135,8 +7135,8 @@ msgstr ""
msgid "Report" msgid "Report"
msgstr "" msgstr ""
#: src/view/com/profile/ProfileMenu.tsx:415 #: src/view/com/profile/ProfileMenu.tsx:420
#: src/view/com/profile/ProfileMenu.tsx:418 #: src/view/com/profile/ProfileMenu.tsx:423
msgid "Report account" msgid "Report account"
msgstr "" msgstr ""
@@ -7246,16 +7246,16 @@ msgstr ""
msgid "Reposted By" msgid "Reposted By"
msgstr "" msgstr ""
#: src/view/com/posts/PostFeedItem.tsx:348 #: src/view/com/posts/PostFeedItem.tsx:366
msgid "Reposted by {0}" msgid "Reposted by {0}"
msgstr "" msgstr ""
#: src/view/com/posts/PostFeedItem.tsx:367 #: src/view/com/posts/PostFeedItem.tsx:385
msgid "Reposted by <0><1/></0>" msgid "Reposted by <0><1/></0>"
msgstr "" msgstr ""
#: src/view/com/posts/PostFeedItem.tsx:346 #: src/view/com/posts/PostFeedItem.tsx:364
#: src/view/com/posts/PostFeedItem.tsx:365 #: src/view/com/posts/PostFeedItem.tsx:383
msgid "Reposted by you" msgid "Reposted by you"
msgstr "" msgstr ""
@@ -7500,8 +7500,8 @@ msgstr ""
#: src/components/dialogs/SearchablePeopleList.tsx:514 #: src/components/dialogs/SearchablePeopleList.tsx:514
#: src/components/forms/SearchInput.tsx:34 #: src/components/forms/SearchInput.tsx:34
#: src/components/forms/SearchInput.tsx:36 #: src/components/forms/SearchInput.tsx:36
#: src/screens/Search/Shell.tsx:307 #: src/screens/Search/Shell.tsx:327
#: src/screens/Search/Shell.tsx:463 #: src/screens/Search/Shell.tsx:513
#: src/view/shell/bottom-bar/BottomBar.tsx:198 #: src/view/shell/bottom-bar/BottomBar.tsx:198
msgid "Search" msgid "Search"
msgstr "" msgstr ""
@@ -7549,7 +7549,7 @@ msgstr ""
msgid "Search for more feeds" msgid "Search for more feeds"
msgstr "" msgstr ""
#: src/screens/Search/Shell.tsx:334 #: src/screens/Search/Shell.tsx:354
msgid "Search for posts, users, or feeds" msgid "Search for posts, users, or feeds"
msgstr "" msgstr ""
@@ -7557,7 +7557,7 @@ msgstr ""
msgid "Search GIFs" msgid "Search GIFs"
msgstr "" msgstr ""
#: src/screens/Search/SearchResults.tsx:253 #: src/screens/Search/SearchResults.tsx:255
msgid "Search is currently unavailable when logged out" msgid "Search is currently unavailable when logged out"
msgstr "" msgstr ""
@@ -7570,8 +7570,8 @@ msgstr ""
msgid "Search my posts" msgid "Search my posts"
msgstr "" msgstr ""
#: src/view/com/profile/ProfileMenu.tsx:266 #: src/view/com/profile/ProfileMenu.tsx:271
#: src/view/com/profile/ProfileMenu.tsx:269 #: src/view/com/profile/ProfileMenu.tsx:274
msgid "Search posts" msgid "Search posts"
msgstr "" msgstr ""
@@ -7861,7 +7861,7 @@ msgstr ""
msgid "Set new password" msgid "Set new password"
msgstr "" msgstr ""
#: src/screens/Onboarding/Layout.tsx:49 #: src/screens/Onboarding/Layout.tsx:50
msgid "Set up your account" msgid "Set up your account"
msgstr "" msgstr ""
@@ -7953,7 +7953,7 @@ msgstr ""
msgid "Share a fun fact!" msgid "Share a fun fact!"
msgstr "" msgstr ""
#: src/view/com/profile/ProfileMenu.tsx:502 #: src/view/com/profile/ProfileMenu.tsx:507
msgid "Share anyway" msgid "Share anyway"
msgstr "" msgstr ""
@@ -8001,8 +8001,8 @@ msgstr ""
#: src/screens/ProfileList/components/MoreOptionsMenu.tsx:171 #: src/screens/ProfileList/components/MoreOptionsMenu.tsx:171
#: src/screens/StarterPack/StarterPackScreen.tsx:615 #: src/screens/StarterPack/StarterPackScreen.tsx:615
#: src/screens/StarterPack/StarterPackScreen.tsx:623 #: src/screens/StarterPack/StarterPackScreen.tsx:623
#: src/view/com/profile/ProfileMenu.tsx:246 #: src/view/com/profile/ProfileMenu.tsx:251
#: src/view/com/profile/ProfileMenu.tsx:259 #: src/view/com/profile/ProfileMenu.tsx:264
msgid "Share via..." msgid "Share via..."
msgstr "" msgstr ""
@@ -8132,7 +8132,7 @@ msgstr ""
#: src/screens/Login/index.tsx:136 #: src/screens/Login/index.tsx:136
#: src/screens/Login/index.tsx:157 #: src/screens/Login/index.tsx:157
#: src/screens/Login/LoginForm.tsx:181 #: 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:81
#: src/view/com/auth/SplashScreen.tsx:89 #: src/view/com/auth/SplashScreen.tsx:89
#: src/view/com/auth/SplashScreen.web.tsx:127 #: src/view/com/auth/SplashScreen.web.tsx:127
@@ -8684,7 +8684,7 @@ msgid "That's everything!"
msgstr "" msgstr ""
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:324 #: 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." msgid "The account will be able to interact with you after unblocking."
msgstr "" msgstr ""
@@ -8820,7 +8820,7 @@ msgstr ""
msgid "There was an issue fetching notifications. Tap here to try again." msgid "There was an issue fetching notifications. Tap here to try again."
msgstr "" msgstr ""
#: src/screens/Search/Explore.tsx:986 #: src/screens/Search/Explore.tsx:996
#: src/view/com/posts/PostFeed.tsx:709 #: src/view/com/posts/PostFeed.tsx:709
msgid "There was an issue fetching posts. Tap here to try again." msgid "There was an issue fetching posts. Tap here to try again."
msgstr "" msgstr ""
@@ -8865,12 +8865,12 @@ msgstr ""
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:101 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:101
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:123 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:123
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:136 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:136
#: src/view/com/profile/ProfileMenu.tsx:131 #: src/view/com/profile/ProfileMenu.tsx:136
#: src/view/com/profile/ProfileMenu.tsx:141 #: src/view/com/profile/ProfileMenu.tsx:146
#: src/view/com/profile/ProfileMenu.tsx:155 #: src/view/com/profile/ProfileMenu.tsx:160
#: src/view/com/profile/ProfileMenu.tsx:165 #: src/view/com/profile/ProfileMenu.tsx:170
#: src/view/com/profile/ProfileMenu.tsx:178 #: src/view/com/profile/ProfileMenu.tsx:183
#: src/view/com/profile/ProfileMenu.tsx:190 #: src/view/com/profile/ProfileMenu.tsx:195
msgid "There was an issue! {0}" msgid "There was an issue! {0}"
msgstr "" msgstr ""
@@ -9073,7 +9073,7 @@ msgstr ""
msgid "This post's author has disabled quote posts." msgid "This post's author has disabled quote posts."
msgstr "" 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." msgid "This profile is only visible to logged-in users. It won't be visible to people who aren't signed in."
msgstr "" msgstr ""
@@ -9199,7 +9199,7 @@ msgid "Toggles the sound"
msgstr "" msgstr ""
#: src/screens/Hashtag.tsx:84 #: src/screens/Hashtag.tsx:84
#: src/screens/Search/SearchResults.tsx:47 #: src/screens/Search/SearchResults.tsx:49
#: src/screens/Topic.tsx:71 #: src/screens/Topic.tsx:71
msgid "Top" msgid "Top"
msgstr "" msgstr ""
@@ -9312,7 +9312,7 @@ msgstr ""
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:328 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:328
#: src/screens/ProfileList/components/Header.tsx:171 #: src/screens/ProfileList/components/Header.tsx:171
#: src/screens/ProfileList/components/Header.tsx:178 #: src/screens/ProfileList/components/Header.tsx:178
#: src/view/com/profile/ProfileMenu.tsx:490 #: src/view/com/profile/ProfileMenu.tsx:495
msgid "Unblock" msgid "Unblock"
msgstr "" msgstr ""
@@ -9323,13 +9323,13 @@ msgstr ""
#: src/components/dms/ConvoMenu.tsx:247 #: src/components/dms/ConvoMenu.tsx:247
#: src/components/dms/ConvoMenu.tsx:250 #: src/components/dms/ConvoMenu.tsx:250
#: src/view/com/profile/ProfileMenu.tsx:395 #: src/view/com/profile/ProfileMenu.tsx:400
#: src/view/com/profile/ProfileMenu.tsx:401 #: src/view/com/profile/ProfileMenu.tsx:406
msgid "Unblock account" msgid "Unblock account"
msgstr "" msgstr ""
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:322 #: src/screens/Profile/Header/ProfileHeaderStandard.tsx:322
#: src/view/com/profile/ProfileMenu.tsx:472 #: src/view/com/profile/ProfileMenu.tsx:477
msgid "Unblock Account?" msgid "Unblock Account?"
msgstr "" msgstr ""
@@ -9362,8 +9362,8 @@ msgstr ""
msgid "Unfollow {0}" msgid "Unfollow {0}"
msgstr "" msgstr ""
#: src/view/com/profile/ProfileMenu.tsx:286 #: src/view/com/profile/ProfileMenu.tsx:291
#: src/view/com/profile/ProfileMenu.tsx:296 #: src/view/com/profile/ProfileMenu.tsx:301
msgid "Unfollow account" msgid "Unfollow account"
msgstr "" msgstr ""
@@ -9410,8 +9410,8 @@ msgstr ""
#: src/components/PostControls/PostMenu/PostMenuItems.tsx:627 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:627
#: src/components/PostControls/PostMenu/PostMenuItems.tsx:633 #: src/components/PostControls/PostMenu/PostMenuItems.tsx:633
#: src/view/com/profile/ProfileMenu.tsx:374 #: src/view/com/profile/ProfileMenu.tsx:379
#: src/view/com/profile/ProfileMenu.tsx:380 #: src/view/com/profile/ProfileMenu.tsx:385
msgid "Unmute account" msgid "Unmute account"
msgstr "" msgstr ""
@@ -9734,8 +9734,8 @@ msgstr ""
#: src/components/verification/VerificationCreatePrompt.tsx:84 #: src/components/verification/VerificationCreatePrompt.tsx:84
#: src/components/verification/VerificationCreatePrompt.tsx:86 #: src/components/verification/VerificationCreatePrompt.tsx:86
#: src/view/com/profile/ProfileMenu.tsx:358 #: src/view/com/profile/ProfileMenu.tsx:363
#: src/view/com/profile/ProfileMenu.tsx:361 #: src/view/com/profile/ProfileMenu.tsx:366
msgid "Verify account" msgid "Verify account"
msgstr "" 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." msgid "We're sorry, but we weren't able to load your muted words at this time. Please try again."
msgstr "" 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." msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
msgstr "" msgstr ""
@@ -10299,7 +10299,7 @@ msgstr ""
msgid "www.mylivestream.tv" msgid "www.mylivestream.tv"
msgstr "" msgstr ""
#: src/view/com/composer/select-language/SuggestedLanguage.tsx:181 #: src/view/com/composer/select-language/SuggestedLanguage.tsx:180
msgid "Yes" msgid "Yes"
msgstr "" msgstr ""
@@ -10512,7 +10512,7 @@ msgstr ""
msgid "You have no lists." msgid "You have no lists."
msgstr "" msgstr ""
#: src/components/dialogs/StarterPackDialog.tsx:100 #: src/components/dialogs/StarterPackDialog.tsx:101
msgid "You have no starter packs." msgid "You have no starter packs."
msgstr "" msgstr ""
+1
View File
@@ -29,4 +29,5 @@ init({
* @see https://docs.sentry.io/platforms/react-native/configuration/options/#attach-stacktrace * @see https://docs.sentry.io/platforms/react-native/configuration/options/#attach-stacktrace
*/ */
attachStacktrace: false, attachStacktrace: false,
sampleRate: env.IS_INTERNAL ? 1.0 : 0.1,
}) })
@@ -42,11 +42,14 @@ import {Trash_Stroke2_Corner0_Rounded} from '#/components/icons/Trash'
import {Link} from '#/components/Link' import {Link} from '#/components/Link'
import {useMenuControl} from '#/components/Menu' import {useMenuControl} from '#/components/Menu'
import {PostAlerts} from '#/components/moderation/PostAlerts' import {PostAlerts} from '#/components/moderation/PostAlerts'
import {createPortalGroup} from '#/components/Portal'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {useSimpleVerificationState} from '#/components/verification' import {useSimpleVerificationState} from '#/components/verification'
import {VerificationCheck} from '#/components/verification/VerificationCheck' import {VerificationCheck} from '#/components/verification/VerificationCheck'
import type * as bsky from '#/types/bsky' import type * as bsky from '#/types/bsky'
export const ChatListItemPortal = createPortalGroup()
export let ChatListItem = ({ export let ChatListItem = ({
convo, convo,
showMenu = true, showMenu = true,
@@ -331,6 +334,7 @@ function ChatListItemReady({
const hasUnread = convo.unreadCount > 0 && !isDeletedAccount const hasUnread = convo.unreadCount > 0 && !isDeletedAccount
return ( return (
<ChatListItemPortal.Provider>
<GestureActionView actions={actions}> <GestureActionView actions={actions}>
<View <View
onMouseEnter={onMouseEnter} onMouseEnter={onMouseEnter}
@@ -365,8 +369,14 @@ function ChatListItemReady({
accessibilityActions={ accessibilityActions={
isNative isNative
? [ ? [
{name: 'magicTap', label: _(msg`Open conversation options`)}, {
{name: 'longpress', label: _(msg`Open conversation options`)}, name: 'magicTap',
label: _(msg`Open conversation options`),
},
{
name: 'longpress',
label: _(msg`Open conversation options`),
},
] ]
: undefined : undefined
} }
@@ -450,7 +460,11 @@ function ChatListItemReady({
{!isDeletedAccount && ( {!isDeletedAccount && (
<Text <Text
numberOfLines={1} numberOfLines={1}
style={[a.text_sm, t.atoms.text_contrast_medium, a.pb_xs]}> style={[
a.text_sm,
t.atoms.text_contrast_medium,
a.pb_xs,
]}>
@{profile.handle} @{profile.handle}
</Text> </Text>
)} )}
@@ -497,6 +511,8 @@ function ChatListItemReady({
)} )}
</Link> </Link>
<ChatListItemPortal.Outlet />
{showMenu && ( {showMenu && (
<ConvoMenu <ConvoMenu
convo={convo} convo={convo}
@@ -513,7 +529,8 @@ function ChatListItemReady({
a.justify_center, a.justify_center,
{ {
right: tokens.space.lg, right: tokens.space.lg,
opacity: !gtMobile || showActions || menuControl.isOpen ? 1 : 0, opacity:
!gtMobile || showActions || menuControl.isOpen ? 1 : 0,
}, },
]} ]}
latestReportableMessage={latestReportableMessage} latestReportableMessage={latestReportableMessage}
@@ -526,5 +543,6 @@ function ChatListItemReady({
/> />
</View> </View>
</GestureActionView> </GestureActionView>
</ChatListItemPortal.Provider>
) )
} }
@@ -46,7 +46,7 @@ export function ChatStatusInfo({convoState}: {convoState: ActiveConvoStates}) {
label={_(msg`Block or report`)} label={_(msg`Block or report`)}
convo={convoState.convo} convo={convoState.convo}
profile={otherUser} profile={otherUser}
color="negative" color="negative_subtle"
size="small" size="small"
currentScreen="conversation" currentScreen="conversation"
/> />
@@ -70,8 +70,7 @@ export function ChatStatusInfo({convoState}: {convoState: ActiveConvoStates}) {
<AcceptChatButton <AcceptChatButton
onAcceptConvo={onAcceptChat} onAcceptConvo={onAcceptChat}
convo={convoState.convo} convo={convoState.convo}
color="primary" color="primary_subtle"
variant="outline"
size="small" size="small"
currentScreen="conversation" currentScreen="conversation"
/> />
@@ -36,7 +36,6 @@ export function RejectMenu({
convo, convo,
profile, profile,
size = 'tiny', size = 'tiny',
variant = 'outline',
color = 'secondary', color = 'secondary',
label, label,
showDeleteConvo, showDeleteConvo,
@@ -117,7 +116,6 @@ export function RejectMenu({
label={triggerProps.accessibilityLabel} label={triggerProps.accessibilityLabel}
style={[a.flex_1]} style={[a.flex_1]}
color={color} color={color}
variant={variant}
size={size}> size={size}>
<ButtonText> <ButtonText>
{label || ( {label || (
@@ -129,7 +127,7 @@ export function RejectMenu({
</Button> </Button>
)} )}
</Menu.Trigger> </Menu.Trigger>
<Menu.Outer> <Menu.Outer showCancel>
<Menu.Group> <Menu.Group>
{showDeleteConvo && ( {showDeleteConvo && (
<Menu.Item <Menu.Item
@@ -181,7 +179,6 @@ export function RejectMenu({
export function AcceptChatButton({ export function AcceptChatButton({
convo, convo,
size = 'tiny', size = 'tiny',
variant = 'solid',
color = 'secondary_inverted', color = 'secondary_inverted',
label, label,
currentScreen, currentScreen,
@@ -248,7 +245,6 @@ export function AcceptChatButton({
{...props} {...props}
label={label || _(msg`Accept chat request`)} label={label || _(msg`Accept chat request`)}
size={size} size={size}
variant={variant}
color={color} color={color}
style={a.flex_1} style={a.flex_1}
onPress={onPressAccept}> onPress={onPressAccept}>
@@ -266,7 +262,6 @@ export function AcceptChatButton({
export function DeleteChatButton({ export function DeleteChatButton({
convo, convo,
size = 'tiny', size = 'tiny',
variant = 'outline',
color = 'secondary', color = 'secondary',
label, label,
currentScreen, currentScreen,
@@ -315,7 +310,6 @@ export function DeleteChatButton({
<Button <Button
label={label || _(msg`Delete chat`)} label={label || _(msg`Delete chat`)}
size={size} size={size}
variant={variant}
color={color} color={color}
style={a.flex_1} style={a.flex_1}
onPress={onPressDelete} onPress={onPressDelete}
@@ -7,7 +7,7 @@ import {useSession} from '#/state/session'
import {atoms as a, tokens} from '#/alf' import {atoms as a, tokens} from '#/alf'
import {KnownFollowers} from '#/components/KnownFollowers' import {KnownFollowers} from '#/components/KnownFollowers'
import {Text} from '#/components/Typography' import {Text} from '#/components/Typography'
import {ChatListItem} from './ChatListItem' import {ChatListItem, ChatListItemPortal} from './ChatListItem'
import {AcceptChatButton, DeleteChatButton, RejectMenu} from './RequestButtons' import {AcceptChatButton, DeleteChatButton, RejectMenu} from './RequestButtons'
export function RequestListItem({convo}: {convo: ChatBskyConvoDefs.ConvoView}) { export function RequestListItem({convo}: {convo: ChatBskyConvoDefs.ConvoView}) {
@@ -42,7 +42,8 @@ export function RequestListItem({convo}: {convo: ChatBskyConvoDefs.ConvoView}) {
<Trans comment="Accept a chat request">Accept Request</Trans> <Trans comment="Accept a chat request">Accept Request</Trans>
</Text> </Text>
</View> </View>
</ChatListItem> {/* then, this gets absolutely positioned on top of the spacer */}
<ChatListItemPortal.Portal>
<View <View
style={[ style={[
a.absolute, a.absolute,
@@ -73,6 +74,8 @@ export function RequestListItem({convo}: {convo: ChatBskyConvoDefs.ConvoView}) {
</> </>
)} )}
</View> </View>
</ChatListItemPortal.Portal>
</ChatListItem>
</View> </View>
) )
} }
@@ -80,7 +80,7 @@ function Page({
]}> ]}>
<Image <Image
source={image} source={image}
style={[a.w_full, {aspectRatio: 1}]} style={[a.w_full, a.aspect_square]}
alt={alt} alt={alt}
accessibilityIgnoresInvertColors={false} // I guess we do need it to blend into the background accessibilityIgnoresInvertColors={false} // I guess we do need it to blend into the background
/> />
+6 -9
View File
@@ -2,7 +2,6 @@ import {useMemo, useReducer} from 'react'
import {msg} from '@lingui/macro' import {msg} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useGate} from '#/lib/statsig/statsig'
import { import {
Layout, Layout,
OnboardingControls, OnboardingControls,
@@ -13,21 +12,19 @@ import {StepFinished} from '#/screens/Onboarding/StepFinished'
import {StepInterests} from '#/screens/Onboarding/StepInterests' import {StepInterests} from '#/screens/Onboarding/StepInterests'
import {StepProfile} from '#/screens/Onboarding/StepProfile' import {StepProfile} from '#/screens/Onboarding/StepProfile'
import {Portal} from '#/components/Portal' import {Portal} from '#/components/Portal'
import {ENV} from '#/env'
import {StepSuggestedAccounts} from './StepSuggestedAccounts' import {StepSuggestedAccounts} from './StepSuggestedAccounts'
export function Onboarding() { export function Onboarding() {
const {_} = useLingui() const {_} = useLingui()
const gate = useGate()
const showValueProp = ENV !== 'e2e' && gate('onboarding_value_prop')
const showSuggestedAccounts =
ENV !== 'e2e' && gate('onboarding_suggested_accounts')
const [state, dispatch] = useReducer(reducer, { const [state, dispatch] = useReducer(reducer, {
...initialState, ...initialState,
totalSteps: showSuggestedAccounts ? 4 : 3, totalSteps: 4,
experiments: { experiments: {
onboarding_suggested_accounts: showSuggestedAccounts, // let's leave this flag logic in for now to avoid rebase churn
onboarding_value_prop: showValueProp, // TODO: remove this flag logic once we've finished with all experiments -sfn
onboarding_suggested_accounts: true,
onboarding_value_prop: true,
}, },
}) })
@@ -39,13 +39,12 @@ import {
OUTER_SPACE, OUTER_SPACE,
REPLY_LINE_WIDTH, REPLY_LINE_WIDTH,
} from '#/screens/PostThread/const' } from '#/screens/PostThread/const'
import {atoms as a, useBreakpoints, useTheme} from '#/alf' import {atoms as a, useTheme} from '#/alf'
import {colors} from '#/components/Admonition' import {colors} from '#/components/Admonition'
import {Button} from '#/components/Button' import {Button} from '#/components/Button'
import {CalendarClock_Stroke2_Corner0_Rounded as CalendarClockIcon} from '#/components/icons/CalendarClock' import {CalendarClock_Stroke2_Corner0_Rounded as CalendarClockIcon} from '#/components/icons/CalendarClock'
import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from '#/components/icons/Trash' import {Trash_Stroke2_Corner0_Rounded as TrashIcon} from '#/components/icons/Trash'
import {InlineLinkText, Link} from '#/components/Link' import {InlineLinkText, Link} from '#/components/Link'
import {LoggedOutCTA} from '#/components/LoggedOutCTA'
import {ContentHider} from '#/components/moderation/ContentHider' import {ContentHider} from '#/components/moderation/ContentHider'
import {LabelsOnMyPost} from '#/components/moderation/LabelsOnMe' import {LabelsOnMyPost} from '#/components/moderation/LabelsOnMe'
import {PostAlerts} from '#/components/moderation/PostAlerts' import {PostAlerts} from '#/components/moderation/PostAlerts'
@@ -180,7 +179,6 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({
const {_} = useLingui() const {_} = useLingui()
const {openComposer} = useOpenComposer() const {openComposer} = useOpenComposer()
const {currentAccount, hasSession} = useSession() const {currentAccount, hasSession} = useSession()
const {gtTablet} = useBreakpoints()
const feedFeedback = useFeedFeedback(postSource?.feedSourceInfo, hasSession) const feedFeedback = useFeedFeedback(postSource?.feedSourceInfo, hasSession)
const formatPostStatCount = useFormatPostStatCount() const formatPostStatCount = useFormatPostStatCount()
@@ -315,8 +313,6 @@ const ThreadItemAnchorInner = memo(function ThreadItemAnchorInner({
}, },
isRoot && [a.pt_lg], isRoot && [a.pt_lg],
]}> ]}>
{/* Show CTA for logged-out visitors - hide on desktop and check gate */}
{!gtTablet && <LoggedOutCTA gateName="cta_above_post_heading" />}
<View style={[a.flex_row, a.gap_md, a.pb_md]}> <View style={[a.flex_row, a.gap_md, a.pb_md]}>
<View collapsable={false}> <View collapsable={false}>
<PreviewableUserAvatar <PreviewableUserAvatar
@@ -132,9 +132,7 @@ const ThreadItemPostOuterWrapper = memo(function ThreadItemPostOuterWrapper({
<View <View
style={[ style={[
showTopBorder && [a.border_t, t.atoms.border_contrast_low], showTopBorder && [a.border_t, t.atoms.border_contrast_low],
{ {paddingHorizontal: OUTER_SPACE},
paddingHorizontal: OUTER_SPACE,
},
// If there's no next child, add a little padding to bottom // If there's no next child, add a little padding to bottom
!item.ui.showChildReplyLine && !item.ui.showChildReplyLine &&
!item.ui.precedesChildReadMore && { !item.ui.precedesChildReadMore && {
@@ -255,8 +253,9 @@ const ThreadItemPostInner = memo(function ThreadItemPostInner({
href={postHref} href={postHref}
disabled={overrides?.moderation === true} disabled={overrides?.moderation === true}
modui={moderation.ui('contentList')} modui={moderation.ui('contentList')}
hiderStyle={[a.pl_0, a.pr_2xs, a.bg_transparent]}
iconSize={LINEAR_AVI_WIDTH} iconSize={LINEAR_AVI_WIDTH}
iconStyles={{marginLeft: 2, marginRight: 2}} iconStyles={[a.mr_xs]}
profile={post.author} profile={post.author}
interpretFilterAsBlur> interpretFilterAsBlur>
<ThreadItemPostParentReplyLine item={item} /> <ThreadItemPostParentReplyLine item={item} />
-3
View File
@@ -38,7 +38,6 @@ import {
import {atoms as a, native, platform, useBreakpoints, web} from '#/alf' import {atoms as a, native, platform, useBreakpoints, web} from '#/alf'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
import {ListFooter} from '#/components/Lists' import {ListFooter} from '#/components/Lists'
import {LoggedOutCTA} from '#/components/LoggedOutCTA'
const PARENT_CHUNK_SIZE = 5 const PARENT_CHUNK_SIZE = 5
const CHILDREN_CHUNK_SIZE = 50 const CHILDREN_CHUNK_SIZE = 50
@@ -410,8 +409,6 @@ export function PostThread({uri}: {uri: string}) {
onPostSuccess={optimisticOnPostReply} onPostSuccess={optimisticOnPostReply}
postSource={anchorPostSource} postSource={anchorPostSource}
/> />
{/* Show CTA for logged-out visitors */}
<LoggedOutCTA style={a.px_lg} gateName="cta_above_post_replies" />
</View> </View>
) )
} else { } else {
+12 -2
View File
@@ -726,7 +726,12 @@ export function Explore({
<ModuleHeader.SearchButton <ModuleHeader.SearchButton
{...item.searchButton} {...item.searchButton}
onPress={() => onPress={() =>
focusSearchInput(item.searchButton?.tab || 'user') focusSearchInput(
(item.searchButton?.tab || 'user') as
| 'user'
| 'profile'
| 'feed',
)
} }
/> />
)} )}
@@ -743,7 +748,12 @@ export function Explore({
<ModuleHeader.SearchButton <ModuleHeader.SearchButton
{...item.searchButton} {...item.searchButton}
onPress={() => onPress={() =>
focusSearchInput(item.searchButton?.tab || 'user') focusSearchInput(
(item.searchButton?.tab || 'user') as
| 'user'
| 'profile'
| 'feed',
)
} }
/> />
)} )}
+3 -1
View File
@@ -30,12 +30,14 @@ let SearchResults = ({
activeTab, activeTab,
onPageSelected, onPageSelected,
headerHeight, headerHeight,
initialPage = 0,
}: { }: {
query: string query: string
queryWithParams: string queryWithParams: string
activeTab: number activeTab: number
onPageSelected: (page: number) => void onPageSelected: (page: number) => void
headerHeight: number headerHeight: number
initialPage?: number
}): React.ReactNode => { }): React.ReactNode => {
const {_} = useLingui() const {_} = useLingui()
@@ -89,7 +91,7 @@ let SearchResults = ({
<TabBar items={sections.map(section => section.title)} {...props} /> <TabBar items={sections.map(section => section.title)} {...props} />
</Layout.Center> </Layout.Center>
)} )}
initialPage={0}> initialPage={initialPage}>
{sections.map((section, i) => ( {sections.map((section, i) => (
<View key={i}>{section.component}</View> <View key={i}>{section.component}</View>
))} ))}
+60 -10
View File
@@ -190,15 +190,19 @@ export function SearchScreenShell({
setShowAutocomplete(false) setShowAutocomplete(false)
if (isWeb) { if (isWeb) {
// Empty params resets the URL to be /search rather than /search?q= // Empty params resets the URL to be /search rather than /search?q=
// Also clear the tab parameter
const {q: _q, ...parameters} = (route.params ?? {}) as { const {
q: _q,
tab: _tab,
...parameters
} = (route.params ?? {}) as {
[key: string]: string [key: string]: string
} }
// @ts-expect-error route is not typesafe // @ts-expect-error route is not typesafe
navigation.replace(route.name, parameters) navigation.replace(route.name, parameters)
} else { } else {
setSearchText('') setSearchText('')
navigation.setParams({q: ''}) navigation.setParams({q: '', tab: undefined})
} }
}, [setShowAutocomplete, setSearchText, navigation, route.params, route.name]) }, [setShowAutocomplete, setSearchText, navigation, route.params, route.name])
@@ -236,15 +240,19 @@ export function SearchScreenShell({
const onSoftReset = useCallback(() => { const onSoftReset = useCallback(() => {
if (isWeb) { if (isWeb) {
// Empty params resets the URL to be /search rather than /search?q= // Empty params resets the URL to be /search rather than /search?q=
// Also clear the tab parameter when soft resetting
const {q: _q, ...parameters} = (route.params ?? {}) as { const {
q: _q,
tab: _tab,
...parameters
} = (route.params ?? {}) as {
[key: string]: string [key: string]: string
} }
// @ts-expect-error route is not typesafe // @ts-expect-error route is not typesafe
navigation.replace(route.name, parameters) navigation.replace(route.name, parameters)
} else { } else {
setSearchText('') setSearchText('')
navigation.setParams({q: ''}) navigation.setParams({q: '', tab: undefined})
textInput.current?.focus() textInput.current?.focus()
} }
}, [navigation, route]) }, [navigation, route])
@@ -268,9 +276,21 @@ export function SearchScreenShell({
} }
}, [setShowAutocomplete]) }, [setShowAutocomplete])
const focusSearchInput = useCallback(() => { const focusSearchInput = useCallback(
(tab?: 'user' | 'profile' | 'feed') => {
textInput.current?.focus() textInput.current?.focus()
}, [])
// If a tab is specified, set the tab parameter
if (tab) {
if (isWeb) {
navigation.setParams({...route.params, tab})
} else {
navigation.setParams({tab})
}
}
},
[navigation, route],
)
const showHeader = !gtMobile || navButton !== 'menu' const showHeader = !gtMobile || navButton !== 'menu'
@@ -421,13 +441,42 @@ let SearchScreenInner = ({
query: string query: string
queryWithParams: string queryWithParams: string
headerHeight: number headerHeight: number
focusSearchInput: () => void focusSearchInput: (tab?: 'user' | 'profile' | 'feed') => void
}): React.ReactNode => { }): React.ReactNode => {
const t = useTheme() const t = useTheme()
const setMinimalShellMode = useSetMinimalShellMode() const setMinimalShellMode = useSetMinimalShellMode()
const {hasSession} = useSession() const {hasSession} = useSession()
const {gtTablet} = useBreakpoints() const {gtTablet} = useBreakpoints()
const [activeTab, setActiveTab] = useState(0) const route = useRoute()
// Get tab parameter from route params
const tabParam = (
route.params as {q?: string; tab?: 'user' | 'profile' | 'feed'}
)?.tab
// Map tab parameter to tab index
const getInitialTabIndex = useCallback(() => {
if (!tabParam) return 0
switch (tabParam) {
case 'user':
case 'profile':
return 2 // People tab
case 'feed':
return 3 // Feeds tab
default:
return 0
}
}, [tabParam])
const [activeTab, setActiveTab] = useState(getInitialTabIndex())
// Update activeTab when tabParam changes
useLayoutEffect(() => {
const newTabIndex = getInitialTabIndex()
if (newTabIndex !== activeTab) {
setActiveTab(newTabIndex)
}
}, [tabParam, activeTab, getInitialTabIndex])
const onPageSelected = useCallback( const onPageSelected = useCallback(
(index: number) => { (index: number) => {
@@ -444,6 +493,7 @@ let SearchScreenInner = ({
activeTab={activeTab} activeTab={activeTab}
headerHeight={headerHeight} headerHeight={headerHeight}
onPageSelected={onPageSelected} onPageSelected={onPageSelected}
initialPage={activeTab}
/> />
) : hasSession ? ( ) : hasSession ? (
<Explore focusSearchInput={focusSearchInput} headerHeight={headerHeight} /> <Explore focusSearchInput={focusSearchInput} headerHeight={headerHeight} />
@@ -194,7 +194,7 @@ function TrendingIndicator({type}: {type: TrendingIndicatorType | 'skeleton'}) {
case 'new': { case 'new': {
Icon = TrendingIcon Icon = TrendingIcon
text = _(msg`New`) text = _(msg`New`)
color = t.palette.positive_700 color = t.palette.positive_600
backgroundColor = t.palette.positive_50 backgroundColor = t.palette.positive_50
break break
} }
@@ -195,7 +195,6 @@ function CreateDialogInner({passwords}: {passwords: string[]}) {
value={data.password} value={data.password}
label={_(msg`Copy App Password`)} label={_(msg`Copy App Password`)}
size="large" size="large"
variant="solid"
color="secondary"> color="secondary">
<ButtonText>{data.password}</ButtonText> <ButtonText>{data.password}</ButtonText>
<ButtonIcon icon={CopyIcon} /> <ButtonIcon icon={CopyIcon} />
@@ -428,10 +428,10 @@ function OwnHandlePage({goToServiceHandle}: {goToServiceHandle: () => void}) {
</Text> </Text>
<View style={[a.py_xs]}> <View style={[a.py_xs]}>
<CopyButton <CopyButton
variant="solid"
color="secondary" color="secondary"
value="_atproto" value="_atproto"
label={_(msg`Copy host`)} label={_(msg`Copy host`)}
style={[a.bg_transparent]}
hoverStyle={[a.bg_transparent]} hoverStyle={[a.bg_transparent]}
hitSlop={HITSLOP_10}> hitSlop={HITSLOP_10}>
<Text style={[a.text_md, a.flex_1]}>_atproto</Text> <Text style={[a.text_md, a.flex_1]}>_atproto</Text>
@@ -449,10 +449,10 @@ function OwnHandlePage({goToServiceHandle}: {goToServiceHandle: () => void}) {
</Text> </Text>
<View style={[a.py_xs]}> <View style={[a.py_xs]}>
<CopyButton <CopyButton
variant="solid"
color="secondary" color="secondary"
value={'did=' + currentAccount?.did} value={'did=' + currentAccount?.did}
label={_(msg`Copy TXT record value`)} label={_(msg`Copy TXT record value`)}
style={[a.bg_transparent]}
hoverStyle={[a.bg_transparent]} hoverStyle={[a.bg_transparent]}
hitSlop={HITSLOP_10}> hitSlop={HITSLOP_10}>
<Text style={[a.text_md, a.flex_1]}> <Text style={[a.text_md, a.flex_1]}>
@@ -636,7 +636,7 @@ function SuccessMessage({text}: {text: string}) {
a.rounded_full, a.rounded_full,
a.align_center, a.align_center,
a.justify_center, a.justify_center,
{backgroundColor: t.palette.positive_600}, {backgroundColor: t.palette.positive_500},
]}> ]}>
<CheckIcon fill={t.palette.white} size="xs" /> <CheckIcon fill={t.palette.white} size="xs" />
</View> </View>
@@ -58,9 +58,9 @@ export function CopyButton({
pointerEvents="none"> pointerEvents="none">
<Text <Text
style={[ style={[
a.font_semi_bold, a.font_medium,
a.text_right, a.text_right,
a.text_md, a.text_sm,
t.atoms.text_contrast_high, t.atoms.text_contrast_high,
]}> ]}>
<Trans>Copied!</Trans> <Trans>Copied!</Trans>
+1 -1
View File
@@ -169,7 +169,7 @@ export function StepHandle() {
{isHandleAvailable?.available && ( {isHandleAvailable?.available && (
<CheckIcon <CheckIcon
testID="handleAvailableCheck" testID="handleAvailableCheck"
style={[{color: t.palette.positive_600}, a.z_20]} style={[{color: t.palette.positive_500}, a.z_20]}
/> />
)} )}
</TextField.Root> </TextField.Root>
+2
View File
@@ -93,6 +93,7 @@ import {ArrowLeft_Stroke2_Corner0_Rounded as ArrowLeftIcon} from '#/components/i
import {Check_Stroke2_Corner0_Rounded as CheckIcon} from '#/components/icons/Check' import {Check_Stroke2_Corner0_Rounded as CheckIcon} from '#/components/icons/Check'
import {EyeSlash_Stroke2_Corner0_Rounded as Eye} from '#/components/icons/EyeSlash' import {EyeSlash_Stroke2_Corner0_Rounded as Eye} from '#/components/icons/EyeSlash'
import {Leaf_Stroke2_Corner0_Rounded as LeafIcon} from '#/components/icons/Leaf' import {Leaf_Stroke2_Corner0_Rounded as LeafIcon} from '#/components/icons/Leaf'
import {KeepAwake} from '#/components/KeepAwake'
import * as Layout from '#/components/Layout' import * as Layout from '#/components/Layout'
import {Link} from '#/components/Link' import {Link} from '#/components/Link'
import {ListFooter} from '#/components/Lists' import {ListFooter} from '#/components/Lists'
@@ -150,6 +151,7 @@ export function VideoFeed({}: NativeStackScreenProps<
return ( return (
<ThemeProvider theme="dark"> <ThemeProvider theme="dark">
<Layout.Screen noInsetTop style={{backgroundColor: 'black'}}> <Layout.Screen noInsetTop style={{backgroundColor: 'black'}}>
<KeepAwake />
<SystemBars style={{statusBar: 'light', navigationBar: 'light'}} /> <SystemBars style={{statusBar: 'light', navigationBar: 'light'}} />
<View <View
style={[ style={[
+34
View File
@@ -25,6 +25,11 @@ import * as bsky from '#/types/bsky'
export * from '#/state/queries/threadgate/types' export * from '#/state/queries/threadgate/types'
export * from '#/state/queries/threadgate/util' export * from '#/state/queries/threadgate/util'
/**
* Must match the threadgate lexicon record definition.
*/
export const MAX_HIDDEN_REPLIES = 300
export const threadgateRecordQueryKeyRoot = 'threadgate-record' export const threadgateRecordQueryKeyRoot = 'threadgate-record'
export const createThreadgateRecordQueryKey = (uri: string) => [ export const createThreadgateRecordQueryKey = (uri: string) => [
threadgateRecordQueryKeyRoot, threadgateRecordQueryKeyRoot,
@@ -205,6 +210,7 @@ export async function upsertThreadgate(
}) })
const next = await callback(prev) const next = await callback(prev)
if (!next) return if (!next) return
validateThreadgateRecordOrThrow(next)
await writeThreadgateRecord({ await writeThreadgateRecord({
agent, agent,
postUri, postUri,
@@ -358,3 +364,31 @@ export function useToggleReplyVisibilityMutation() {
}, },
}) })
} }
export class MaxHiddenRepliesError extends Error {
constructor(message?: string) {
super(message || 'Maximum number of hidden replies reached')
this.name = 'MaxHiddenRepliesError'
}
}
export class InvalidInteractionSettingsError extends Error {
constructor(message?: string) {
super(message || 'Invalid interaction settings')
this.name = 'InvalidInteractionSettingsError'
}
}
export function validateThreadgateRecordOrThrow(
record: AppBskyFeedThreadgate.Record,
) {
const result = AppBskyFeedThreadgate.validateRecord(record)
if (result.success) {
if ((result.value.hiddenReplies?.length ?? 0) > MAX_HIDDEN_REPLIES) {
throw new MaxHiddenRepliesError()
}
} else {
throw new InvalidInteractionSettingsError()
}
}
+1 -1
View File
@@ -2,7 +2,7 @@ import {beforeEach, expect, jest, test} from '@jest/globals'
import {Storage} from '#/storage' import {Storage} from '#/storage'
jest.mock('react-native-mmkv', () => ({ jest.mock('@bsky.app/react-native-mmkv', () => ({
MMKV: class MMKVMock { MMKV: class MMKVMock {
_store = new Map() _store = new Map()
+1 -1
View File
@@ -1,5 +1,5 @@
import {useCallback, useEffect, useState} from 'react' import {useCallback, useEffect, useState} from 'react'
import {MMKV} from 'react-native-mmkv' import {MMKV} from '@bsky.app/react-native-mmkv'
import {type Account, type Device} from '#/storage/schema' import {type Account, type Device} from '#/storage/schema'
@@ -162,7 +162,6 @@ function LanguageSuggestionButton({
<View style={[a.flex_1]}> <View style={[a.flex_1]}>
<Text <Text
style={[ style={[
a.flex_1,
a.leading_snug, a.leading_snug,
{ {
maxWidth: 400, maxWidth: 400,
@@ -307,7 +307,7 @@ let NotificationFeedItem = ({
) : ( ) : (
<Trans>{firstAuthorLink} reposted your post</Trans> <Trans>{firstAuthorLink} reposted your post</Trans>
) )
icon = <RepostIcon size="xl" style={{color: t.palette.positive_600}} /> icon = <RepostIcon size="xl" style={{color: t.palette.positive_500}} />
} else if (item.type === 'follow') { } else if (item.type === 'follow') {
let isFollowBack = false let isFollowBack = false
@@ -519,7 +519,7 @@ let NotificationFeedItem = ({
) : ( ) : (
<Trans>{firstAuthorLink} reposted your repost</Trans> <Trans>{firstAuthorLink} reposted your repost</Trans>
) )
icon = <RepostIcon size="xl" style={{color: t.palette.positive_600}} /> icon = <RepostIcon size="xl" style={{color: t.palette.positive_500}} />
} else if (item.type === 'subscribed-post') { } else if (item.type === 'subscribed-post') {
const postsCount = 1 + (item.additional?.length || 0) const postsCount = 1 + (item.additional?.length || 0)
a11yLabel = hasMultipleAuthors a11yLabel = hasMultipleAuthors
+20 -2
View File
@@ -11,6 +11,7 @@ import {
} from '@atproto/api' } from '@atproto/api'
import {msg, Trans} from '@lingui/macro' import {msg, Trans} from '@lingui/macro'
import {useLingui} from '@lingui/react' import {useLingui} from '@lingui/react'
import {useNavigation} from '@react-navigation/native'
import {useQueryClient} from '@tanstack/react-query' import {useQueryClient} from '@tanstack/react-query'
import {useActorStatus} from '#/lib/actor-status' import {useActorStatus} from '#/lib/actor-status'
@@ -19,6 +20,8 @@ import {MAX_POST_LINES} from '#/lib/constants'
import {useOpenComposer} from '#/lib/hooks/useOpenComposer' import {useOpenComposer} from '#/lib/hooks/useOpenComposer'
import {usePalette} from '#/lib/hooks/usePalette' import {usePalette} from '#/lib/hooks/usePalette'
import {makeProfileLink} from '#/lib/routes/links' import {makeProfileLink} from '#/lib/routes/links'
import {type NavigationProp} from '#/lib/routes/types'
import {useGate} from '#/lib/statsig/statsig'
import {sanitizeDisplayName} from '#/lib/strings/display-names' import {sanitizeDisplayName} from '#/lib/strings/display-names'
import {sanitizeHandle} from '#/lib/strings/handles' import {sanitizeHandle} from '#/lib/strings/handles'
import {countLines} from '#/lib/strings/helpers' import {countLines} from '#/lib/strings/helpers'
@@ -167,18 +170,32 @@ let FeedItemInner = ({
}): React.ReactNode => { }): React.ReactNode => {
const queryClient = useQueryClient() const queryClient = useQueryClient()
const {openComposer} = useOpenComposer() const {openComposer} = useOpenComposer()
const navigation = useNavigation<NavigationProp>()
const pal = usePalette('default') const pal = usePalette('default')
const gate = useGate()
const {_} = useLingui() const {_} = useLingui()
const [hover, setHover] = useState(false) const [hover, setHover] = useState(false)
const href = useMemo(() => { const [href, rkey] = useMemo(() => {
const urip = new AtUri(post.uri) const urip = new AtUri(post.uri)
return makeProfileLink(post.author, 'post', urip.rkey) return [makeProfileLink(post.author, 'post', urip.rkey), urip.rkey]
}, [post.uri, post.author]) }, [post.uri, post.author])
const {sendInteraction, feedSourceInfo} = useFeedFeedbackContext() const {sendInteraction, feedSourceInfo} = useFeedFeedbackContext()
const onPressReply = () => { const onPressReply = () => {
if (gate('feed_reply_button_open_thread')) {
sendInteraction({
item: post.uri,
event: 'app.bsky.feed.defs#clickthroughItem',
feedContext,
reqId,
})
navigation.navigate('PostThread', {
name: post.author.did,
rkey,
})
} else {
sendInteraction({ sendInteraction({
item: post.uri, item: post.uri,
event: 'app.bsky.feed.defs#interactionReply', event: 'app.bsky.feed.defs#interactionReply',
@@ -197,6 +214,7 @@ let FeedItemInner = ({
}, },
}) })
} }
}
const onOpenAuthor = () => { const onOpenAuthor = () => {
sendInteraction({ sendInteraction({
+13 -20
View File
@@ -7,10 +7,8 @@ import {
type ViewStyle, type ViewStyle,
} from 'react-native' } from 'react-native'
import {usePalette} from '#/lib/hooks/usePalette'
import {s} from '#/lib/styles' import {s} from '#/lib/styles'
import {useTheme} from '#/lib/ThemeContext' import {atoms as a, useTheme} from '#/alf'
import {atoms as a, useTheme as useTheme_NEW} from '#/alf'
import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble' import {Bubble_Stroke2_Corner2_Rounded as Bubble} from '#/components/icons/Bubble'
import { import {
Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled, Heart2_Filled_Stroke2_Corner0_Rounded as HeartIconFilled,
@@ -27,7 +25,7 @@ export function LoadingPlaceholder({
height: DimensionValue | undefined height: DimensionValue | undefined
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
}) { }) {
const theme = useTheme() const t = useTheme()
return ( return (
<View <View
style={[ style={[
@@ -35,7 +33,7 @@ export function LoadingPlaceholder({
{ {
width, width,
height, height,
backgroundColor: theme.palette.default.backgroundLight, backgroundColor: t.palette.contrast_50,
}, },
style, style,
]} ]}
@@ -48,10 +46,9 @@ export function PostLoadingPlaceholder({
}: { }: {
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
}) { }) {
const t = useTheme_NEW() const t = useTheme()
const pal = usePalette('default')
return ( return (
<View style={[styles.post, pal.view, style]}> <View style={[styles.post, style]}>
<LoadingPlaceholder <LoadingPlaceholder
width={42} width={42}
height={42} height={42}
@@ -137,14 +134,11 @@ export function NotificationLoadingPlaceholder({
}: { }: {
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
}) { }) {
const pal = usePalette('default') const t = useTheme()
return ( return (
<View style={[styles.notification, pal.view, style]}> <View style={[styles.notification, style]}>
<View style={[{width: 60}, a.align_end, a.pr_sm, a.pt_2xs]}> <View style={[{width: 60}, a.align_end, a.pr_sm, a.pt_2xs]}>
<HeartIconFilled <HeartIconFilled size="xl" style={{color: t.palette.contrast_50}} />
size="xl"
style={{color: pal.colors.backgroundLight}}
/>
</View> </View>
<View style={{flex: 1}}> <View style={{flex: 1}}>
<View style={[a.flex_row, s.mb10]}> <View style={[a.flex_row, s.mb10]}>
@@ -184,9 +178,8 @@ export function ProfileCardLoadingPlaceholder({
}: { }: {
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
}) { }) {
const pal = usePalette('default')
return ( return (
<View style={[styles.profileCard, pal.view, style]}> <View style={[styles.profileCard, style]}>
<LoadingPlaceholder <LoadingPlaceholder
width={40} width={40}
height={40} height={40}
@@ -228,7 +221,7 @@ export function FeedLoadingPlaceholder({
showTopBorder?: boolean showTopBorder?: boolean
showLowerPlaceholder?: boolean showLowerPlaceholder?: boolean
}) { }) {
const pal = usePalette('default') const t = useTheme()
return ( return (
<View <View
style={[ style={[
@@ -236,10 +229,10 @@ export function FeedLoadingPlaceholder({
padding: 16, padding: 16,
borderTopWidth: showTopBorder ? StyleSheet.hairlineWidth : 0, borderTopWidth: showTopBorder ? StyleSheet.hairlineWidth : 0,
}, },
pal.border, t.atoms.border_contrast_low,
style, style,
]}> ]}>
<View style={[pal.view, {flexDirection: 'row'}]}> <View style={[{flexDirection: 'row'}]}>
<LoadingPlaceholder <LoadingPlaceholder
width={36} width={36}
height={36} height={36}
@@ -282,7 +275,7 @@ export function ChatListItemLoadingPlaceholder({
}: { }: {
style?: StyleProp<ViewStyle> style?: StyleProp<ViewStyle>
}) { }) {
const t = useTheme_NEW() const t = useTheme()
const random = useMemo(() => Math.random(), []) const random = useMemo(() => Math.random(), [])
return ( return (
<View style={[a.flex_row, a.gap_md, a.px_lg, a.mt_lg, t.atoms.bg, style]}> <View style={[a.flex_row, a.gap_md, a.px_lg, a.mt_lg, t.atoms.bg, style]}>
@@ -204,6 +204,7 @@ export function AutoSizedImage({
// alt here is what screen readers actually use // alt here is what screen readers actually use
accessibilityLabel={image.alt} accessibilityLabel={image.alt}
accessibilityHint={_(msg`Views full image`)} accessibilityHint={_(msg`Views full image`)}
accessibilityRole="button"
style={[ style={[
a.w_full, a.w_full,
a.rounded_md, a.rounded_md,
@@ -226,6 +227,7 @@ export function AutoSizedImage({
// alt here is what screen readers actually use // alt here is what screen readers actually use
accessibilityLabel={image.alt} accessibilityLabel={image.alt}
accessibilityHint={_(msg`Views full image`)} accessibilityHint={_(msg`Views full image`)}
accessibilityRole="button"
style={[a.h_full]}> style={[a.h_full]}>
{contents} {contents}
</Pressable> </Pressable>
+4 -4
View File
@@ -67,7 +67,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) {
const containerRefs = [containerRef1, containerRef2] const containerRefs = [containerRef1, containerRef2]
return ( return (
<View style={[a.flex_1, a.flex_row, gap]}> <View style={[a.flex_1, a.flex_row, gap]}>
<View style={[a.flex_1, {aspectRatio: 1}]}> <View style={[a.flex_1, a.aspect_square]}>
<GalleryItem <GalleryItem
{...props} {...props}
index={0} index={0}
@@ -76,7 +76,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) {
thumbDimsRef={thumbDimsRef} thumbDimsRef={thumbDimsRef}
/> />
</View> </View>
<View style={[a.flex_1, {aspectRatio: 1}]}> <View style={[a.flex_1, a.aspect_square]}>
<GalleryItem <GalleryItem
{...props} {...props}
index={1} index={1}
@@ -93,7 +93,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) {
const containerRefs = [containerRef1, containerRef2, containerRef3] const containerRefs = [containerRef1, containerRef2, containerRef3]
return ( return (
<View style={[a.flex_1, a.flex_row, gap]}> <View style={[a.flex_1, a.flex_row, gap]}>
<View style={[a.flex_1, {aspectRatio: 1}]}> <View style={[a.flex_1, a.aspect_square]}>
<GalleryItem <GalleryItem
{...props} {...props}
index={0} index={0}
@@ -102,7 +102,7 @@ function ImageLayoutGridInner(props: ImageLayoutGridInnerProps) {
thumbDimsRef={thumbDimsRef} thumbDimsRef={thumbDimsRef}
/> />
</View> </View>
<View style={[a.flex_1, {aspectRatio: 1}, gap]}> <View style={[a.flex_1, a.aspect_square, gap]}>
<View style={[a.flex_1]}> <View style={[a.flex_1]}>
<GalleryItem <GalleryItem
{...props} {...props}
+1 -4
View File
@@ -8,7 +8,6 @@ import {RemoveScrollBar} from 'react-remove-scroll-bar'
import {useIntentHandler} from '#/lib/hooks/useIntentHandler' import {useIntentHandler} from '#/lib/hooks/useIntentHandler'
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries' import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
import {type NavigationProp} from '#/lib/routes/types' import {type NavigationProp} from '#/lib/routes/types'
import {useGate} from '#/lib/statsig/statsig'
import {useGeolocationStatus} from '#/state/geolocation' import {useGeolocationStatus} from '#/state/geolocation'
import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell' import {useIsDrawerOpen, useSetDrawerOpen} from '#/state/shell'
import {useComposerKeyboardShortcut} from '#/state/shell/composer/useComposerKeyboardShortcut' import {useComposerKeyboardShortcut} from '#/state/shell/composer/useComposerKeyboardShortcut'
@@ -46,7 +45,6 @@ function ShellInner() {
const [showDrawerDelayedExit, setShowDrawerDelayedExit] = useState(showDrawer) const [showDrawerDelayedExit, setShowDrawerDelayedExit] = useState(showDrawer)
const {state: policyUpdateState} = usePolicyUpdateContext() const {state: policyUpdateState} = usePolicyUpdateContext()
const welcomeModalControl = useWelcomeModal() const welcomeModalControl = useWelcomeModal()
const gate = useGate()
useLayoutEffect(() => { useLayoutEffect(() => {
if (showDrawer !== showDrawerDelayedExit) { if (showDrawer !== showDrawerDelayedExit) {
@@ -85,8 +83,7 @@ function ShellInner() {
<LinkWarningDialog /> <LinkWarningDialog />
<Lightbox /> <Lightbox />
{/* Show welcome modal if the gate is enabled */} {welcomeModalControl.isOpen && (
{welcomeModalControl.isOpen && gate('welcome_modal') && (
<WelcomeModal control={welcomeModalControl} /> <WelcomeModal control={welcomeModalControl} />
)} )}
+6 -6
View File
@@ -3685,6 +3685,11 @@
dependencies: dependencies:
react-responsive "^10.0.1" react-responsive "^10.0.1"
"@bsky.app/react-native-mmkv@2.12.5":
version "2.12.5"
resolved "https://registry.yarnpkg.com/@bsky.app/react-native-mmkv/-/react-native-mmkv-2.12.5.tgz#eb17d31a6158c74393f617a1763ac223ff3f83a6"
integrity sha512-3vUz1nQY1DiKIPAWRkpp5ZGxH5f2G6Ui0UuQuEYjYv81xx1qFcSzS9KQ2sHcOKYdkOM9amWV2Q8TQCxt1lrAHg==
"@bufbuild/protobuf@^1.5.0": "@bufbuild/protobuf@^1.5.0":
version "1.7.0" version "1.7.0"
resolved "https://registry.yarnpkg.com/@bufbuild/protobuf/-/protobuf-1.7.0.tgz#cecddc8162a231642b410bc7b99309cd5969733c" resolved "https://registry.yarnpkg.com/@bufbuild/protobuf/-/protobuf-1.7.0.tgz#cecddc8162a231642b410bc7b99309cd5969733c"
@@ -11292,7 +11297,7 @@ expo-json-utils@~0.15.0:
resolved "https://registry.yarnpkg.com/expo-json-utils/-/expo-json-utils-0.15.0.tgz#6723574814b9e6b0a90e4e23662be76123ab6ae9" resolved "https://registry.yarnpkg.com/expo-json-utils/-/expo-json-utils-0.15.0.tgz#6723574814b9e6b0a90e4e23662be76123ab6ae9"
integrity sha512-duRT6oGl80IDzH2LD2yEFWNwGIC2WkozsB6HF3cDYNoNNdUvFk6uN3YiwsTsqVM/D0z6LEAQ01/SlYvN+Fw0JQ== integrity sha512-duRT6oGl80IDzH2LD2yEFWNwGIC2WkozsB6HF3cDYNoNNdUvFk6uN3YiwsTsqVM/D0z6LEAQ01/SlYvN+Fw0JQ==
expo-keep-awake@~15.0.7: expo-keep-awake@^15.0.7, expo-keep-awake@~15.0.7:
version "15.0.7" version "15.0.7"
resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-15.0.7.tgz#4eada556e1cca6c9c2e5aa39478fd01816cd0bc9" resolved "https://registry.yarnpkg.com/expo-keep-awake/-/expo-keep-awake-15.0.7.tgz#4eada556e1cca6c9c2e5aa39478fd01816cd0bc9"
integrity sha512-CgBNcWVPnrIVII5G54QDqoE125l+zmqR4HR8q+MQaCfHet+dYpS5vX5zii/RMayzGN4jPgA4XYIQ28ePKFjHoA== integrity sha512-CgBNcWVPnrIVII5G54QDqoE125l+zmqR4HR8q+MQaCfHet+dYpS5vX5zii/RMayzGN4jPgA4XYIQ28ePKFjHoA==
@@ -17065,11 +17070,6 @@ react-native-keyboard-controller@1.18.5:
dependencies: dependencies:
react-native-is-edge-to-edge "^1.2.1" react-native-is-edge-to-edge "^1.2.1"
react-native-mmkv@^2.12.2:
version "2.12.2"
resolved "https://registry.yarnpkg.com/react-native-mmkv/-/react-native-mmkv-2.12.2.tgz#4bba0f5f04e2cf222494cce3a9794ba6a4894dee"
integrity sha512-6058Aq0p57chPrUutLGe9fYoiDVDNMU2PKV+lLFUJ3GhoHvUrLdsS1PDSCLr00yqzL4WJQ7TTzH+V8cpyrNcfg==
react-native-pager-view@6.8.0: react-native-pager-view@6.8.0:
version "6.8.0" version "6.8.0"
resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-6.8.0.tgz#5bac05203d911bf9bf039d47db41b1313dbd1a7a" resolved "https://registry.yarnpkg.com/react-native-pager-view/-/react-native-pager-view-6.8.0.tgz#5bac05203d911bf9bf039d47db41b1313dbd1a7a"