Compare commits
49 Commits
react-codemod
...
go-bump
| Author | SHA1 | Date | |
|---|---|---|---|
| 7e38da086f | |||
| dc9560cf93 | |||
| f8d3bdd796 | |||
| facb7a000e | |||
| b31cc46e17 | |||
| 5749efb996 | |||
| 82b2c214f1 | |||
| 2cd9733572 | |||
| 905f59bbc1 | |||
| 22c3a6cc90 | |||
| 803364869e | |||
| 0004d175c7 | |||
| d7cee2e154 | |||
| 92f0d07470 | |||
| dd2aa5294a | |||
| a9325ae973 | |||
| e4fa6d7209 | |||
| c80e5e3da5 | |||
| 9fe1b9cb57 | |||
| 0d1fb4ec06 | |||
| 27cbbea1f4 | |||
| 3342d587e1 | |||
| 573f602f4c | |||
| 4ba7453aa8 | |||
| d6c41e5b33 | |||
| 36a6eb2e62 | |||
| e592d54fe9 | |||
| 0046b00780 | |||
| 4a1c529ae9 | |||
| 52793a3b46 | |||
| a95e0976a6 | |||
| 66d7df1256 | |||
| f300b0525c | |||
| 66e5e174a4 | |||
| d338deeb2f | |||
| 7bc2f6fb05 | |||
| 40a560509b | |||
| c758bfc568 | |||
| 7f1798a6cb | |||
| 5b9357182f | |||
| 259c966f1c | |||
| bb824f152b | |||
| 490f9656d3 | |||
| 3c6f96bfc6 | |||
| 87885cdb80 | |||
| 4cd76a7135 | |||
| 9f44d16572 | |||
| 0af43d6fa8 | |||
| d66bf87a9c |
@@ -3,6 +3,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- go-bump
|
||||
|
||||
env:
|
||||
REGISTRY: ${{ secrets.AWS_ECR_REGISTRY_USEAST2_PACKAGES_REGISTRY }}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.23-bullseye AS build-env
|
||||
FROM golang:1.24-bullseye AS build-env
|
||||
|
||||
WORKDIR /usr/src/social-app
|
||||
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.23-bullseye AS build-env
|
||||
FROM golang:1.24-bullseye AS build-env
|
||||
|
||||
WORKDIR /usr/src/social-app
|
||||
|
||||
|
||||
@@ -13,6 +13,8 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
_ "net/http/pprof"
|
||||
|
||||
"github.com/bluesky-social/indigo/atproto/identity"
|
||||
"github.com/bluesky-social/indigo/util/cliutil"
|
||||
"github.com/bluesky-social/indigo/xrpc"
|
||||
@@ -70,7 +72,7 @@ func serve(cctx *cli.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
metricsMux := http.NewServeMux()
|
||||
metricsMux := http.DefaultServeMux
|
||||
metricsMux.Handle("/metrics", promhttp.Handler())
|
||||
|
||||
metricsHttpd := &http.Server{
|
||||
|
||||
+24
-19
@@ -1,24 +1,32 @@
|
||||
module github.com/bluesky-social/social-app/bskyweb
|
||||
|
||||
go 1.23
|
||||
go 1.24
|
||||
|
||||
toolchain go1.23.4
|
||||
toolchain go1.24.5
|
||||
|
||||
require (
|
||||
github.com/bluesky-social/indigo v0.0.0-20250605010711-db9bb60025dc
|
||||
github.com/bluesky-social/indigo v0.0.0-20250729223159-573ae927246a
|
||||
github.com/flosch/pongo2/v6 v6.0.0
|
||||
github.com/ipfs/go-log v1.0.5
|
||||
github.com/joho/godotenv v1.5.1
|
||||
github.com/klauspost/compress v1.17.3
|
||||
github.com/labstack/echo-contrib v0.15.0
|
||||
github.com/labstack/echo/v4 v4.11.3
|
||||
github.com/prometheus/client_golang v1.17.0
|
||||
github.com/klauspost/compress v1.18.0
|
||||
github.com/labstack/echo-contrib v0.17.4
|
||||
github.com/labstack/echo/v4 v4.13.3
|
||||
github.com/prometheus/client_golang v1.22.0
|
||||
github.com/urfave/cli/v2 v2.25.7
|
||||
)
|
||||
|
||||
require github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
|
||||
require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 // indirect
|
||||
github.com/carlmjohnson/versioninfo v0.22.5 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
@@ -26,7 +34,6 @@ require (
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/goccy/go-json v0.10.2 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
|
||||
@@ -52,17 +59,16 @@ require (
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/labstack/gommon v0.4.1 // indirect
|
||||
github.com/labstack/gommon v0.4.2 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.1 // indirect
|
||||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
||||
github.com/lestrrat-go/httprc v1.0.4 // indirect
|
||||
github.com/lestrrat-go/iter v1.0.2 // indirect
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.12 // indirect
|
||||
github.com/lestrrat-go/option v1.0.1 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.22 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
||||
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/multiformats/go-base32 v0.1.0 // indirect
|
||||
@@ -73,10 +79,9 @@ require (
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/orandin/slog-gorm v1.3.2 // indirect
|
||||
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f // indirect
|
||||
github.com/prometheus/client_golang v1.17.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.63.0 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
@@ -94,14 +99,14 @@ require (
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/net v0.23.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.22.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/crypto v0.38.0 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/sync v0.14.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
golang.org/x/time v0.11.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
google.golang.org/protobuf v1.33.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gorm.io/driver/postgres v1.5.7 // indirect
|
||||
gorm.io/driver/sqlite v1.5.5 // indirect
|
||||
gorm.io/gorm v1.25.9 // indirect
|
||||
|
||||
+54
-42
@@ -2,14 +2,14 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bluesky-social/indigo v0.0.0-20250605010711-db9bb60025dc h1:chbGD59Cn1mw07kbq9Uvb8WUFIr1dcoL5TOhT+I9bV4=
|
||||
github.com/bluesky-social/indigo v0.0.0-20250605010711-db9bb60025dc/go.mod h1:ovyxp8AMO1Hoe838vMJUbqHTZaAR8ABM3g3TXu+A5Ng=
|
||||
github.com/bluesky-social/indigo v0.0.0-20250729223159-573ae927246a h1:S12KN45uIkRglMHC8PqD/Vsz0+u3KbIaBF/6rit8/Pg=
|
||||
github.com/bluesky-social/indigo v0.0.0-20250729223159-573ae927246a/go.mod h1:0XUyOCRtL4/OiyeqMTmr6RlVHQMDgw3LS7CfibuZR5Q=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874 h1:N7oVaKyGp8bttX0bfZGmcGkjz7DLQXhAn3DNd3T0ous=
|
||||
github.com/bradfitz/gomemcache v0.0.0-20230905024940-24af94b03874/go.mod h1:r5xuitiExdLAJ09PR7vBVENGvp4ZuTBeWTGtxuX3K+c=
|
||||
github.com/carlmjohnson/versioninfo v0.22.5 h1:O00sjOLUAFxYQjlN/bzYTuZiS0y6fWDQjMRvwtKgwwc=
|
||||
github.com/carlmjohnson/versioninfo v0.22.5/go.mod h1:QT9mph3wcVfISUKd0i9sZfVrPviHuSF+cUtLjm2WSf8=
|
||||
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
@@ -33,10 +33,8 @@ github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
|
||||
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
@@ -102,8 +100,8 @@ github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.17.3 h1:qkRjuerhUU1EmXLYGkSH6EZL+vPSxIrYjLNAK4slzwA=
|
||||
github.com/klauspost/compress v1.17.3/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
@@ -113,10 +111,26 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
<<<<<<< HEAD
|
||||
<<<<<<< HEAD
|
||||
github.com/labstack/echo-contrib v0.15.0 h1:9K+oRU265y4Mu9zpRDv3X+DGTqUALY6oRHCSZZKCRVU=
|
||||
github.com/labstack/echo-contrib v0.15.0/go.mod h1:lei+qt5CLB4oa7VHTE0yEfQSEB9XTJI1LUqko9UWvo4=
|
||||
=======
|
||||
github.com/labstack/echo-contrib v0.17.4 h1:g5mfsrJfJTKv+F5uNKCyrjLK7js+ZW6HTjg4FnDxxgk=
|
||||
github.com/labstack/echo-contrib v0.17.4/go.mod h1:9O7ZPAHUeMGTOAfg80YqQduHzt0CzLak36PZRldYrZ0=
|
||||
>>>>>>> 2b92697e3 (switch to using DefaultServeMux, include go.mod and go.sum changes)
|
||||
github.com/labstack/echo/v4 v4.11.3 h1:Upyu3olaqSHkCjs1EJJwQ3WId8b8b1hxbogyommKktM=
|
||||
github.com/labstack/echo/v4 v4.11.3/go.mod h1:UcGuQ8V6ZNRmSweBIJkPvGfwCMIlFmiqrPqiEBfPYws=
|
||||
github.com/labstack/gommon v0.4.1 h1:gqEff0p/hTENGMABzezPoPSRtIh1Cvw0ueMOe0/dfOk=
|
||||
github.com/labstack/gommon v0.4.1/go.mod h1:TyTrpPqxR5KMk8LKVtLmfMjeQ5FEkBYdxLYPw/WfrOM=
|
||||
=======
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/labstack/echo-contrib v0.17.4 h1:g5mfsrJfJTKv+F5uNKCyrjLK7js+ZW6HTjg4FnDxxgk=
|
||||
github.com/labstack/echo-contrib v0.17.4/go.mod h1:9O7ZPAHUeMGTOAfg80YqQduHzt0CzLak36PZRldYrZ0=
|
||||
>>>>>>> 27c51401d (git tidy)
|
||||
github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
|
||||
github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
|
||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||
github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
|
||||
github.com/lestrrat-go/blackmagic v1.0.1 h1:lS5Zts+5HIC/8og6cGHb0uCcNCa3OUt1ygh3Qz2Fe80=
|
||||
github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
|
||||
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
|
||||
@@ -130,16 +144,13 @@ github.com/lestrrat-go/jwx/v2 v2.0.12/go.mod h1:Mq4KN1mM7bp+5z/W5HS8aCNs5RKZ911G
|
||||
github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
|
||||
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
|
||||
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
|
||||
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
|
||||
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
|
||||
@@ -154,6 +165,8 @@ github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7B
|
||||
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
|
||||
github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
|
||||
github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
|
||||
github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
|
||||
github.com/orandin/slog-gorm v1.3.2 h1:C0lKDQPAx/pF+8K2HL7bdShPwOEJpPM0Bn80zTzxU1g=
|
||||
@@ -163,14 +176,14 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f h1:VXTQfuJj9vKR4TCkEuWIckKvdHFeJH/huIFJ9/cXOB0=
|
||||
github.com/polydawn/refmt v0.89.1-0.20221221234430-40501e09de1f/go.mod h1:/zvteZs/GwLtCgZ4BL6CBsk9IKIlexP43ObX9AxTqTw=
|
||||
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
|
||||
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
|
||||
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
||||
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
@@ -197,8 +210,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
|
||||
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||
@@ -252,8 +265,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
@@ -271,16 +284,16 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -292,13 +305,12 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -310,10 +322,10 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
@@ -332,8 +344,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU=
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
||||
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
|
||||
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
|
||||
@@ -25,18 +25,17 @@ import {
|
||||
type ViewStyleProp,
|
||||
web,
|
||||
} from '#/alf'
|
||||
import {Button} from '#/components/Button'
|
||||
import {Button, ButtonText} from '#/components/Button'
|
||||
import * as FeedCard from '#/components/FeedCard'
|
||||
import {ArrowRight_Stroke2_Corner0_Rounded as Arrow} from '#/components/icons/Arrow'
|
||||
import {Hashtag_Stroke2_Corner0_Rounded as Hashtag} from '#/components/icons/Hashtag'
|
||||
import {PersonPlus_Stroke2_Corner0_Rounded as Person} from '#/components/icons/Person'
|
||||
import {InlineLinkText} from '#/components/Link'
|
||||
import * as ProfileCard from '#/components/ProfileCard'
|
||||
import {Text} from '#/components/Typography'
|
||||
import type * as bsky from '#/types/bsky'
|
||||
import {ProgressGuideList} from './ProgressGuide/List'
|
||||
|
||||
const MOBILE_CARD_WIDTH = 300
|
||||
const MOBILE_CARD_WIDTH = 165
|
||||
|
||||
function CardOuter({
|
||||
children,
|
||||
@@ -48,8 +47,8 @@ function CardOuter({
|
||||
<View
|
||||
style={[
|
||||
a.w_full,
|
||||
a.p_lg,
|
||||
a.rounded_md,
|
||||
a.p_md,
|
||||
a.rounded_lg,
|
||||
a.border,
|
||||
t.atoms.bg,
|
||||
t.atoms.border_contrast_low,
|
||||
@@ -65,14 +64,30 @@ function CardOuter({
|
||||
|
||||
export function SuggestedFollowPlaceholder() {
|
||||
const t = useTheme()
|
||||
return (
|
||||
<CardOuter style={[a.gap_md, t.atoms.border_contrast_low]}>
|
||||
<ProfileCard.Header>
|
||||
<ProfileCard.AvatarPlaceholder />
|
||||
<ProfileCard.NameAndHandlePlaceholder />
|
||||
</ProfileCard.Header>
|
||||
|
||||
<ProfileCard.DescriptionPlaceholder numberOfLines={2} />
|
||||
return (
|
||||
<CardOuter
|
||||
style={[a.gap_md, t.atoms.border_contrast_low, t.atoms.shadow_sm]}>
|
||||
<ProfileCard.Outer>
|
||||
<View
|
||||
style={[a.flex_col, a.align_center, a.gap_sm, a.pb_sm, a.mb_auto]}>
|
||||
<ProfileCard.AvatarPlaceholder size={88} />
|
||||
<ProfileCard.NamePlaceholder />
|
||||
<View style={[a.w_full]}>
|
||||
<ProfileCard.DescriptionPlaceholder numberOfLines={2} />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<Button
|
||||
label=""
|
||||
size="small"
|
||||
variant="solid"
|
||||
color="secondary"
|
||||
disabled
|
||||
style={[a.w_full, a.rounded_sm]}>
|
||||
<ButtonText>Follow</ButtonText>
|
||||
</Button>
|
||||
</ProfileCard.Outer>
|
||||
</CardOuter>
|
||||
)
|
||||
}
|
||||
@@ -243,10 +258,9 @@ export function ProfileGrid({
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
const moderationOpts = useModerationOpts()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {gtMobile} = useBreakpoints()
|
||||
const isLoading = isSuggestionsLoading || !moderationOpts
|
||||
const maxLength = gtMobile ? 4 : 6
|
||||
const maxLength = gtMobile ? 3 : 6
|
||||
|
||||
const content = isLoading ? (
|
||||
Array(maxLength)
|
||||
@@ -254,7 +268,14 @@ export function ProfileGrid({
|
||||
.map((_, i) => (
|
||||
<View
|
||||
key={i}
|
||||
style={[gtMobile && web([a.flex_0, {width: 'calc(50% - 6px)'}])]}>
|
||||
style={[
|
||||
gtMobile &&
|
||||
web([
|
||||
a.flex_0,
|
||||
a.flex_grow,
|
||||
{width: `calc(30% - ${a.gap_md.gap / 2}px)`},
|
||||
]),
|
||||
]}>
|
||||
<SuggestedFollowPlaceholder />
|
||||
</View>
|
||||
))
|
||||
@@ -276,44 +297,69 @@ export function ProfileGrid({
|
||||
}}
|
||||
style={[
|
||||
a.flex_1,
|
||||
gtMobile && web([a.flex_0, {width: 'calc(50% - 6px)'}]),
|
||||
gtMobile &&
|
||||
web([
|
||||
a.flex_0,
|
||||
a.flex_grow,
|
||||
{width: `calc(30% - ${a.gap_md.gap / 2}px)`},
|
||||
]),
|
||||
]}>
|
||||
{({hovered, pressed}) => (
|
||||
<CardOuter
|
||||
style={[
|
||||
a.flex_1,
|
||||
t.atoms.shadow_sm,
|
||||
(hovered || pressed) && t.atoms.border_contrast_high,
|
||||
]}>
|
||||
<ProfileCard.Outer>
|
||||
<ProfileCard.Header>
|
||||
<View
|
||||
style={[
|
||||
a.flex_col,
|
||||
a.align_center,
|
||||
a.gap_sm,
|
||||
a.pb_sm,
|
||||
a.mb_auto,
|
||||
]}>
|
||||
<ProfileCard.Avatar
|
||||
profile={profile}
|
||||
moderationOpts={moderationOpts}
|
||||
size={88}
|
||||
/>
|
||||
<ProfileCard.NameAndHandle
|
||||
profile={profile}
|
||||
moderationOpts={moderationOpts}
|
||||
/>
|
||||
<ProfileCard.FollowButton
|
||||
profile={profile}
|
||||
moderationOpts={moderationOpts}
|
||||
logContext="FeedInterstitial"
|
||||
shape="round"
|
||||
colorInverted
|
||||
onFollow={() => {
|
||||
logEvent('suggestedUser:follow', {
|
||||
logContext:
|
||||
viewContext === 'feed'
|
||||
? 'InterstitialDiscover'
|
||||
: 'InterstitialProfile',
|
||||
location: 'Card',
|
||||
recId,
|
||||
position: index,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</ProfileCard.Header>
|
||||
<ProfileCard.Description profile={profile} numberOfLines={2} />
|
||||
<View style={[a.flex_col, a.align_center, a.max_w_full]}>
|
||||
<ProfileCard.Name
|
||||
profile={profile}
|
||||
moderationOpts={moderationOpts}
|
||||
/>
|
||||
<ProfileCard.Description
|
||||
profile={profile}
|
||||
numberOfLines={2}
|
||||
style={[
|
||||
t.atoms.text_contrast_medium,
|
||||
a.text_center,
|
||||
a.text_xs,
|
||||
]}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<ProfileCard.FollowButton
|
||||
profile={profile}
|
||||
moderationOpts={moderationOpts}
|
||||
logContext="FeedInterstitial"
|
||||
withIcon={false}
|
||||
style={[a.rounded_sm]}
|
||||
onFollow={() => {
|
||||
logEvent('suggestedUser:follow', {
|
||||
logContext:
|
||||
viewContext === 'feed'
|
||||
? 'InterstitialDiscover'
|
||||
: 'InterstitialProfile',
|
||||
location: 'Card',
|
||||
recId,
|
||||
position: index,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</ProfileCard.Outer>
|
||||
</CardOuter>
|
||||
)}
|
||||
@@ -333,36 +379,30 @@ export function ProfileGrid({
|
||||
<View
|
||||
style={[
|
||||
a.p_lg,
|
||||
a.pb_xs,
|
||||
a.py_md,
|
||||
a.flex_row,
|
||||
a.align_center,
|
||||
a.justify_between,
|
||||
]}>
|
||||
<Text style={[a.text_sm, a.font_bold, t.atoms.text_contrast_medium]}>
|
||||
<Text style={[a.text_sm, a.font_bold, t.atoms.text]}>
|
||||
{viewContext === 'profile' ? (
|
||||
<Trans>Similar accounts</Trans>
|
||||
) : (
|
||||
<Trans>Suggested for you</Trans>
|
||||
)}
|
||||
</Text>
|
||||
<Person fill={t.atoms.text_contrast_low.color} size="sm" />
|
||||
<InlineLinkText
|
||||
label={_(msg`See more suggested profiles on the Explore page`)}
|
||||
to="/search">
|
||||
<Trans>See more</Trans>
|
||||
</InlineLinkText>
|
||||
</View>
|
||||
|
||||
{gtMobile ? (
|
||||
<View style={[a.flex_1, a.px_lg, a.pt_sm, a.pb_lg, a.gap_md]}>
|
||||
<View style={[a.flex_1, a.flex_row, a.flex_wrap, a.gap_sm]}>
|
||||
<View style={[a.px_lg, a.pb_lg]}>
|
||||
<View style={[a.flex_1, a.flex_row, a.flex_wrap, a.gap_md]}>
|
||||
{content}
|
||||
</View>
|
||||
|
||||
<View style={[a.flex_row, a.justify_end, a.align_center, a.gap_md]}>
|
||||
<InlineLinkText
|
||||
label={_(msg`Browse more suggestions`)}
|
||||
to="/search"
|
||||
style={[t.atoms.text_contrast_medium]}>
|
||||
<Trans>Browse more suggestions</Trans>
|
||||
</InlineLinkText>
|
||||
<Arrow size="sm" fill={t.atoms.text_contrast_medium.color} />
|
||||
</View>
|
||||
</View>
|
||||
) : (
|
||||
<BlockDrawerGesture>
|
||||
@@ -371,29 +411,12 @@ export function ProfileGrid({
|
||||
horizontal
|
||||
showsHorizontalScrollIndicator={false}
|
||||
snapToInterval={MOBILE_CARD_WIDTH + a.gap_md.gap}
|
||||
decelerationRate="fast">
|
||||
<View style={[a.px_lg, a.pt_sm, a.pb_lg, a.flex_row, a.gap_md]}>
|
||||
decelerationRate="fast"
|
||||
style={[a.overflow_visible]}>
|
||||
<View style={[a.px_lg, a.pb_lg, a.flex_row, a.gap_md]}>
|
||||
{content}
|
||||
|
||||
<Button
|
||||
label={_(msg`Browse more accounts on the Explore page`)}
|
||||
onPress={() => {
|
||||
navigation.navigate('SearchTab')
|
||||
}}>
|
||||
<CardOuter style={[a.flex_1, {borderWidth: 0}]}>
|
||||
<View style={[a.flex_1, a.justify_center]}>
|
||||
<View style={[a.flex_row, a.px_lg]}>
|
||||
<Text style={[a.pr_xl, a.flex_1, a.leading_snug]}>
|
||||
<Trans>
|
||||
Browse more suggestions on the Explore page
|
||||
</Trans>
|
||||
</Text>
|
||||
|
||||
<Arrow size="xl" />
|
||||
</View>
|
||||
</View>
|
||||
</CardOuter>
|
||||
</Button>
|
||||
<SeeMoreSuggestedProfilesCard />
|
||||
</View>
|
||||
</ScrollView>
|
||||
</View>
|
||||
@@ -403,6 +426,32 @@ export function ProfileGrid({
|
||||
)
|
||||
}
|
||||
|
||||
function SeeMoreSuggestedProfilesCard() {
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const t = useTheme()
|
||||
const {_} = useLingui()
|
||||
|
||||
return (
|
||||
<Button
|
||||
label={_(msg`Browse more accounts on the Explore page`)}
|
||||
onPress={() => {
|
||||
navigation.navigate('SearchTab')
|
||||
}}>
|
||||
<CardOuter style={[a.flex_1, t.atoms.shadow_sm]}>
|
||||
<View style={[a.flex_1, a.justify_center]}>
|
||||
<View style={[a.flex_col, a.align_center, a.gap_md]}>
|
||||
<Text style={[a.leading_snug, a.text_center]}>
|
||||
<Trans>See more accounts you might like</Trans>
|
||||
</Text>
|
||||
|
||||
<Arrow size="xl" />
|
||||
</View>
|
||||
</View>
|
||||
</CardOuter>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
export function SuggestedFeeds() {
|
||||
const numFeedsToDisplay = 3
|
||||
const t = useTheme()
|
||||
|
||||
@@ -20,7 +20,13 @@ import {useProfileFollowMutationQueue} from '#/state/queries/profile'
|
||||
import {useSession} from '#/state/session'
|
||||
import * as Toast from '#/view/com/util/Toast'
|
||||
import {PreviewableUserAvatar, UserAvatar} from '#/view/com/util/UserAvatar'
|
||||
import {atoms as a, platform, useTheme} from '#/alf'
|
||||
import {
|
||||
atoms as a,
|
||||
platform,
|
||||
type TextStyleProp,
|
||||
useTheme,
|
||||
type ViewStyleProp,
|
||||
} from '#/alf'
|
||||
import {
|
||||
Button,
|
||||
ButtonIcon,
|
||||
@@ -136,12 +142,14 @@ export function Avatar({
|
||||
onPress,
|
||||
disabledPreview,
|
||||
liveOverride,
|
||||
size = 40,
|
||||
}: {
|
||||
profile: bsky.profile.AnyProfileView
|
||||
moderationOpts: ModerationOpts
|
||||
onPress?: () => void
|
||||
disabledPreview?: boolean
|
||||
liveOverride?: boolean
|
||||
size?: number
|
||||
}) {
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
|
||||
@@ -149,7 +157,7 @@ export function Avatar({
|
||||
|
||||
return disabledPreview ? (
|
||||
<UserAvatar
|
||||
size={40}
|
||||
size={size}
|
||||
avatar={profile.avatar}
|
||||
type={profile.associated?.labeler ? 'labeler' : 'user'}
|
||||
moderation={moderation.ui('avatar')}
|
||||
@@ -157,7 +165,7 @@ export function Avatar({
|
||||
/>
|
||||
) : (
|
||||
<PreviewableUserAvatar
|
||||
size={40}
|
||||
size={size}
|
||||
profile={profile}
|
||||
moderation={moderation.ui('avatar')}
|
||||
onBeforePress={onPress}
|
||||
@@ -166,7 +174,7 @@ export function Avatar({
|
||||
)
|
||||
}
|
||||
|
||||
export function AvatarPlaceholder() {
|
||||
export function AvatarPlaceholder({size = 40}: {size?: number}) {
|
||||
const t = useTheme()
|
||||
return (
|
||||
<View
|
||||
@@ -174,8 +182,8 @@ export function AvatarPlaceholder() {
|
||||
a.rounded_full,
|
||||
t.atoms.bg_contrast_25,
|
||||
{
|
||||
width: 40,
|
||||
height: 40,
|
||||
width: size,
|
||||
height: size,
|
||||
},
|
||||
]}
|
||||
/>
|
||||
@@ -274,7 +282,7 @@ export function Name({
|
||||
)
|
||||
const verification = useSimpleVerificationState({profile})
|
||||
return (
|
||||
<View style={[a.flex_row, a.align_center]}>
|
||||
<View style={[a.flex_row, a.align_center, a.max_w_full]}>
|
||||
<Text
|
||||
emoji
|
||||
style={[
|
||||
@@ -343,13 +351,32 @@ export function NameAndHandlePlaceholder() {
|
||||
)
|
||||
}
|
||||
|
||||
export function NamePlaceholder({style}: ViewStyleProp) {
|
||||
const t = useTheme()
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
a.rounded_xs,
|
||||
t.atoms.bg_contrast_25,
|
||||
{
|
||||
width: '60%',
|
||||
height: 14,
|
||||
},
|
||||
style,
|
||||
]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export function Description({
|
||||
profile: profileUnshadowed,
|
||||
numberOfLines = 3,
|
||||
style,
|
||||
}: {
|
||||
profile: bsky.profile.AnyProfileView
|
||||
numberOfLines?: number
|
||||
}) {
|
||||
} & TextStyleProp) {
|
||||
const profile = useProfileShadow(profileUnshadowed)
|
||||
const rt = useMemo(() => {
|
||||
if (!('description' in profile)) return
|
||||
@@ -369,7 +396,7 @@ export function Description({
|
||||
<View style={[a.pt_xs]}>
|
||||
<RichText
|
||||
value={rt}
|
||||
style={[a.leading_snug]}
|
||||
style={[a.leading_snug, style]}
|
||||
numberOfLines={numberOfLines}
|
||||
disableLinks
|
||||
/>
|
||||
|
||||
@@ -966,8 +966,8 @@ msgstr ""
|
||||
|
||||
#: src/components/hooks/useFollowMethods.ts:35
|
||||
#: src/components/hooks/useFollowMethods.ts:50
|
||||
#: src/components/ProfileCard.tsx:457
|
||||
#: src/components/ProfileCard.tsx:478
|
||||
#: src/components/ProfileCard.tsx:484
|
||||
#: src/components/ProfileCard.tsx:505
|
||||
#: src/view/com/profile/FollowButton.tsx:38
|
||||
#: src/view/com/profile/FollowButton.tsx:48
|
||||
msgid "An issue occurred, please try again."
|
||||
@@ -1262,7 +1262,7 @@ msgid "Birthday"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/PostControls/PostMenu/PostMenuItems.tsx:757
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:319
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:320
|
||||
#: src/view/com/profile/ProfileMenu.tsx:473
|
||||
msgid "Block"
|
||||
msgstr ""
|
||||
@@ -1423,23 +1423,20 @@ msgstr ""
|
||||
msgid "Books"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/FeedInterstitials.tsx:379
|
||||
#: src/components/FeedInterstitials.tsx:436
|
||||
msgid "Browse more accounts on the Explore page"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/FeedInterstitials.tsx:517
|
||||
#: src/components/FeedInterstitials.tsx:566
|
||||
msgid "Browse more feeds on the Explore page"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/FeedInterstitials.tsx:359
|
||||
#: src/components/FeedInterstitials.tsx:362
|
||||
#: src/components/FeedInterstitials.tsx:498
|
||||
#: src/components/FeedInterstitials.tsx:501
|
||||
#: src/components/FeedInterstitials.tsx:547
|
||||
#: src/components/FeedInterstitials.tsx:550
|
||||
msgid "Browse more suggestions"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/FeedInterstitials.tsx:387
|
||||
#: src/components/FeedInterstitials.tsx:526
|
||||
#: src/components/FeedInterstitials.tsx:575
|
||||
msgid "Browse more suggestions on the Explore page"
|
||||
msgstr ""
|
||||
|
||||
@@ -3618,7 +3615,7 @@ msgid "Flexible"
|
||||
msgstr ""
|
||||
|
||||
#. User is not following this account, click to follow
|
||||
#: src/components/ProfileCard.tsx:490
|
||||
#: src/components/ProfileCard.tsx:517
|
||||
#: src/components/ProfileHoverCard/index.web.tsx:494
|
||||
#: src/components/ProfileHoverCard/index.web.tsx:505
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:245
|
||||
@@ -3696,7 +3693,7 @@ msgid "Followers you know"
|
||||
msgstr ""
|
||||
|
||||
#. User is following this account, click to unfollow
|
||||
#: src/components/ProfileCard.tsx:484
|
||||
#: src/components/ProfileCard.tsx:511
|
||||
#: src/components/ProfileHoverCard/index.web.tsx:493
|
||||
#: src/components/ProfileHoverCard/index.web.tsx:504
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:241
|
||||
@@ -3711,7 +3708,7 @@ msgctxt "feed-name"
|
||||
msgid "Following"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/ProfileCard.tsx:447
|
||||
#: src/components/ProfileCard.tsx:474
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:89
|
||||
msgid "Following {0}"
|
||||
msgstr ""
|
||||
@@ -5459,7 +5456,7 @@ msgstr ""
|
||||
msgid "No likes yet"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/ProfileCard.tsx:469
|
||||
#: src/components/ProfileCard.tsx:496
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:110
|
||||
msgid "No longer following {0}"
|
||||
msgstr ""
|
||||
@@ -7398,6 +7395,18 @@ msgstr ""
|
||||
msgid "See jobs at Bluesky"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/FeedInterstitials.tsx:397
|
||||
msgid "See more"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/FeedInterstitials.tsx:444
|
||||
msgid "See more accounts you might like"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/FeedInterstitials.tsx:395
|
||||
msgid "See more suggested profiles on the Explore page"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/SavedFeeds.tsx:213
|
||||
msgid "See this guide"
|
||||
msgstr ""
|
||||
@@ -7975,7 +7984,7 @@ msgstr ""
|
||||
msgid "Signed in as @{0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/FeedInterstitials.tsx:343
|
||||
#: src/components/FeedInterstitials.tsx:389
|
||||
msgid "Similar accounts"
|
||||
msgstr ""
|
||||
|
||||
@@ -8005,7 +8014,7 @@ msgstr ""
|
||||
msgid "Some of your verifications are invalid."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/FeedInterstitials.tsx:480
|
||||
#: src/components/FeedInterstitials.tsx:529
|
||||
msgid "Some other feeds you might like"
|
||||
msgstr ""
|
||||
|
||||
@@ -8237,7 +8246,7 @@ msgstr ""
|
||||
msgid "Suggested Accounts"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/FeedInterstitials.tsx:345
|
||||
#: src/components/FeedInterstitials.tsx:391
|
||||
msgid "Suggested for you"
|
||||
msgstr ""
|
||||
|
||||
@@ -8421,7 +8430,7 @@ msgstr ""
|
||||
msgid "That's everything!"
|
||||
msgstr ""
|
||||
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:315
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:316
|
||||
#: src/view/com/profile/ProfileMenu.tsx:461
|
||||
msgid "The account will be able to interact with you after unblocking."
|
||||
msgstr ""
|
||||
@@ -9046,7 +9055,7 @@ msgstr ""
|
||||
#: src/components/dms/MessagesListBlockedFooter.tsx:112
|
||||
#: src/components/dms/MessagesListBlockedFooter.tsx:119
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:203
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:319
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:320
|
||||
#: src/view/com/profile/ProfileMenu.tsx:473
|
||||
#: src/view/screens/ProfileList.tsx:723
|
||||
msgid "Unblock"
|
||||
@@ -9064,7 +9073,7 @@ msgstr ""
|
||||
msgid "Unblock account"
|
||||
msgstr ""
|
||||
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:313
|
||||
#: src/screens/Profile/Header/ProfileHeaderStandard.tsx:314
|
||||
#: src/view/com/profile/ProfileMenu.tsx:455
|
||||
msgid "Unblock Account?"
|
||||
msgstr ""
|
||||
@@ -9571,7 +9580,7 @@ msgstr ""
|
||||
msgid "View {0}'s avatar"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/ProfileCard.tsx:118
|
||||
#: src/components/ProfileCard.tsx:124
|
||||
#: src/screens/Profile/components/ProfileFeedHeader.tsx:454
|
||||
#: src/screens/Search/components/SearchProfileCard.tsx:36
|
||||
#: src/screens/VideoFeed/index.tsx:790
|
||||
|
||||
@@ -101,13 +101,9 @@ export const Link = memo(function Link({
|
||||
{name: 'activate', label: title},
|
||||
]
|
||||
|
||||
const dataSet = useMemo(() => {
|
||||
const ds = {...dataSetProp}
|
||||
if (anchorNoUnderline) {
|
||||
ds.noUnderline = 1
|
||||
}
|
||||
return ds
|
||||
}, [dataSetProp, anchorNoUnderline])
|
||||
const dataSet = anchorNoUnderline
|
||||
? {...dataSetProp, noUnderline: 1}
|
||||
: dataSetProp
|
||||
|
||||
if (noFeedback) {
|
||||
return (
|
||||
@@ -125,6 +121,8 @@ export const Link = memo(function Link({
|
||||
onAccessibilityAction?.(e)
|
||||
}
|
||||
}}
|
||||
// @ts-ignore web only -sfn
|
||||
dataSet={dataSet}
|
||||
{...props}
|
||||
android_ripple={{
|
||||
color: t.atoms.bg_contrast_25.backgroundColor,
|
||||
@@ -198,13 +196,9 @@ export const TextLink = memo(function TextLink({
|
||||
console.error('Unable to detect mismatching label')
|
||||
}
|
||||
|
||||
const dataSet = useMemo(() => {
|
||||
const ds = {...dataSetProp}
|
||||
if (anchorNoUnderline) {
|
||||
ds.noUnderline = 1
|
||||
}
|
||||
return ds
|
||||
}, [dataSetProp, anchorNoUnderline])
|
||||
const dataSet = anchorNoUnderline
|
||||
? {...dataSetProp, noUnderline: 1}
|
||||
: dataSetProp
|
||||
|
||||
const onPress = useCallback(
|
||||
(e?: Event) => {
|
||||
|
||||
@@ -0,0 +1,201 @@
|
||||
import {select, type Theme} from '#/alf'
|
||||
import {Check_Stroke2_Corner0_Rounded as SuccessIcon} from '#/components/icons/Check'
|
||||
import {CircleInfo_Stroke2_Corner0_Rounded as CircleInfo} from '#/components/icons/CircleInfo'
|
||||
import {CircleInfo_Stroke2_Corner0_Rounded as ErrorIcon} from '#/components/icons/CircleInfo'
|
||||
import {Warning_Stroke2_Corner0_Rounded as WarningIcon} from '#/components/icons/Warning'
|
||||
|
||||
export type ToastType = 'default' | 'success' | 'error' | 'warning' | 'info'
|
||||
|
||||
export type LegacyToastType =
|
||||
| 'xmark'
|
||||
| 'exclamation-circle'
|
||||
| 'check'
|
||||
| 'clipboard-check'
|
||||
| 'circle-exclamation'
|
||||
|
||||
export const convertLegacyToastType = (
|
||||
type: ToastType | LegacyToastType,
|
||||
): ToastType => {
|
||||
switch (type) {
|
||||
// these ones are fine
|
||||
case 'default':
|
||||
case 'success':
|
||||
case 'error':
|
||||
case 'warning':
|
||||
case 'info':
|
||||
return type
|
||||
// legacy ones need conversion
|
||||
case 'xmark':
|
||||
return 'error'
|
||||
case 'exclamation-circle':
|
||||
return 'warning'
|
||||
case 'check':
|
||||
return 'success'
|
||||
case 'clipboard-check':
|
||||
return 'success'
|
||||
case 'circle-exclamation':
|
||||
return 'warning'
|
||||
default:
|
||||
return 'default'
|
||||
}
|
||||
}
|
||||
|
||||
export const TOAST_ANIMATION_CONFIG = {
|
||||
duration: 300,
|
||||
damping: 15,
|
||||
stiffness: 150,
|
||||
mass: 0.8,
|
||||
overshootClamping: false,
|
||||
restSpeedThreshold: 0.01,
|
||||
restDisplacementThreshold: 0.01,
|
||||
}
|
||||
|
||||
export const TOAST_TYPE_TO_ICON = {
|
||||
default: SuccessIcon,
|
||||
success: SuccessIcon,
|
||||
error: ErrorIcon,
|
||||
warning: WarningIcon,
|
||||
info: CircleInfo,
|
||||
}
|
||||
|
||||
export const getToastTypeStyles = (t: Theme) => ({
|
||||
default: {
|
||||
backgroundColor: select(t.name, {
|
||||
light: t.atoms.bg_contrast_25.backgroundColor,
|
||||
dim: t.atoms.bg_contrast_100.backgroundColor,
|
||||
dark: t.atoms.bg_contrast_100.backgroundColor,
|
||||
}),
|
||||
borderColor: select(t.name, {
|
||||
light: t.atoms.border_contrast_low.borderColor,
|
||||
dim: t.atoms.border_contrast_high.borderColor,
|
||||
dark: t.atoms.border_contrast_high.borderColor,
|
||||
}),
|
||||
iconColor: select(t.name, {
|
||||
light: t.atoms.text_contrast_medium.color,
|
||||
dim: t.atoms.text_contrast_medium.color,
|
||||
dark: t.atoms.text_contrast_medium.color,
|
||||
}),
|
||||
textColor: select(t.name, {
|
||||
light: t.atoms.text_contrast_medium.color,
|
||||
dim: t.atoms.text_contrast_medium.color,
|
||||
dark: t.atoms.text_contrast_medium.color,
|
||||
}),
|
||||
},
|
||||
success: {
|
||||
backgroundColor: select(t.name, {
|
||||
light: t.palette.primary_100,
|
||||
dim: t.palette.primary_100,
|
||||
dark: t.palette.primary_50,
|
||||
}),
|
||||
borderColor: select(t.name, {
|
||||
light: t.palette.primary_500,
|
||||
dim: t.palette.primary_500,
|
||||
dark: t.palette.primary_500,
|
||||
}),
|
||||
iconColor: select(t.name, {
|
||||
light: t.palette.primary_500,
|
||||
dim: t.palette.primary_600,
|
||||
dark: t.palette.primary_600,
|
||||
}),
|
||||
textColor: select(t.name, {
|
||||
light: t.palette.primary_500,
|
||||
dim: t.palette.primary_600,
|
||||
dark: t.palette.primary_600,
|
||||
}),
|
||||
},
|
||||
error: {
|
||||
backgroundColor: select(t.name, {
|
||||
light: t.palette.negative_200,
|
||||
dim: t.palette.negative_25,
|
||||
dark: t.palette.negative_25,
|
||||
}),
|
||||
borderColor: select(t.name, {
|
||||
light: t.palette.negative_300,
|
||||
dim: t.palette.negative_300,
|
||||
dark: t.palette.negative_300,
|
||||
}),
|
||||
iconColor: select(t.name, {
|
||||
light: t.palette.negative_600,
|
||||
dim: t.palette.negative_600,
|
||||
dark: t.palette.negative_600,
|
||||
}),
|
||||
textColor: select(t.name, {
|
||||
light: t.palette.negative_600,
|
||||
dim: t.palette.negative_600,
|
||||
dark: t.palette.negative_600,
|
||||
}),
|
||||
},
|
||||
warning: {
|
||||
backgroundColor: select(t.name, {
|
||||
light: t.atoms.bg_contrast_25.backgroundColor,
|
||||
dim: t.atoms.bg_contrast_100.backgroundColor,
|
||||
dark: t.atoms.bg_contrast_100.backgroundColor,
|
||||
}),
|
||||
borderColor: select(t.name, {
|
||||
light: t.atoms.border_contrast_low.borderColor,
|
||||
dim: t.atoms.border_contrast_high.borderColor,
|
||||
dark: t.atoms.border_contrast_high.borderColor,
|
||||
}),
|
||||
iconColor: select(t.name, {
|
||||
light: t.atoms.text_contrast_medium.color,
|
||||
dim: t.atoms.text_contrast_medium.color,
|
||||
dark: t.atoms.text_contrast_medium.color,
|
||||
}),
|
||||
textColor: select(t.name, {
|
||||
light: t.atoms.text_contrast_medium.color,
|
||||
dim: t.atoms.text_contrast_medium.color,
|
||||
dark: t.atoms.text_contrast_medium.color,
|
||||
}),
|
||||
},
|
||||
info: {
|
||||
backgroundColor: select(t.name, {
|
||||
light: t.atoms.bg_contrast_25.backgroundColor,
|
||||
dim: t.atoms.bg_contrast_100.backgroundColor,
|
||||
dark: t.atoms.bg_contrast_100.backgroundColor,
|
||||
}),
|
||||
borderColor: select(t.name, {
|
||||
light: t.atoms.border_contrast_low.borderColor,
|
||||
dim: t.atoms.border_contrast_high.borderColor,
|
||||
dark: t.atoms.border_contrast_high.borderColor,
|
||||
}),
|
||||
iconColor: select(t.name, {
|
||||
light: t.atoms.text_contrast_medium.color,
|
||||
dim: t.atoms.text_contrast_medium.color,
|
||||
dark: t.atoms.text_contrast_medium.color,
|
||||
}),
|
||||
textColor: select(t.name, {
|
||||
light: t.atoms.text_contrast_medium.color,
|
||||
dim: t.atoms.text_contrast_medium.color,
|
||||
dark: t.atoms.text_contrast_medium.color,
|
||||
}),
|
||||
},
|
||||
})
|
||||
|
||||
export const getToastWebAnimationStyles = () => ({
|
||||
entering: {
|
||||
animation: 'toastFadeIn 0.3s ease-out forwards',
|
||||
},
|
||||
exiting: {
|
||||
animation: 'toastFadeOut 0.2s ease-in forwards',
|
||||
},
|
||||
})
|
||||
|
||||
export const TOAST_WEB_KEYFRAMES = `
|
||||
@keyframes toastFadeIn {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes toastFadeOut {
|
||||
from {
|
||||
opacity: 1;
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
`
|
||||
+78
-59
@@ -6,8 +6,8 @@ import {
|
||||
GestureHandlerRootView,
|
||||
} from 'react-native-gesture-handler'
|
||||
import Animated, {
|
||||
FadeInUp,
|
||||
FadeOutUp,
|
||||
FadeIn,
|
||||
FadeOut,
|
||||
runOnJS,
|
||||
useAnimatedReaction,
|
||||
useAnimatedStyle,
|
||||
@@ -17,37 +17,55 @@ import Animated, {
|
||||
} from 'react-native-reanimated'
|
||||
import RootSiblings from 'react-native-root-siblings'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
import {
|
||||
FontAwesomeIcon,
|
||||
type Props as FontAwesomeProps,
|
||||
} from '@fortawesome/react-native-fontawesome'
|
||||
|
||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||
import {
|
||||
convertLegacyToastType,
|
||||
getToastTypeStyles,
|
||||
type LegacyToastType,
|
||||
TOAST_ANIMATION_CONFIG,
|
||||
TOAST_TYPE_TO_ICON,
|
||||
type ToastType,
|
||||
} from '#/view/com/util/Toast.style'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {Text} from '#/components/Typography'
|
||||
|
||||
const TIMEOUT = 2e3
|
||||
|
||||
// Use type overloading to mark certain types as deprecated -sfn
|
||||
// https://stackoverflow.com/a/78325851/13325987
|
||||
export function show(message: string, type?: ToastType): void
|
||||
/**
|
||||
* @deprecated type is deprecated - use one of `'default' | 'success' | 'error' | 'warning' | 'info'`
|
||||
*/
|
||||
export function show(message: string, type?: LegacyToastType): void
|
||||
export function show(
|
||||
message: string,
|
||||
icon: FontAwesomeProps['icon'] = 'check',
|
||||
) {
|
||||
type: ToastType | LegacyToastType = 'default',
|
||||
): void {
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
return
|
||||
}
|
||||
|
||||
AccessibilityInfo.announceForAccessibility(message)
|
||||
const item = new RootSiblings(
|
||||
<Toast message={message} icon={icon} destroy={() => item.destroy()} />,
|
||||
(
|
||||
<Toast
|
||||
message={message}
|
||||
type={convertLegacyToastType(type)}
|
||||
destroy={() => item.destroy()}
|
||||
/>
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
function Toast({
|
||||
message,
|
||||
icon,
|
||||
type,
|
||||
destroy,
|
||||
}: {
|
||||
message: string
|
||||
icon: FontAwesomeProps['icon']
|
||||
type: ToastType
|
||||
destroy: () => void
|
||||
}) {
|
||||
const t = useTheme()
|
||||
@@ -56,6 +74,10 @@ function Toast({
|
||||
const dismissSwipeTranslateY = useSharedValue(0)
|
||||
const [cardHeight, setCardHeight] = useState(0)
|
||||
|
||||
const toastStyles = getToastTypeStyles(t)
|
||||
const colors = toastStyles[type]
|
||||
const IconComponent = TOAST_TYPE_TO_ICON[type]
|
||||
|
||||
// for the exit animation to work on iOS the animated component
|
||||
// must not be the root component
|
||||
// so we need to wrap it in a view and unmount the toast ahead of time
|
||||
@@ -159,55 +181,52 @@ function Toast({
|
||||
pointerEvents="box-none">
|
||||
{alive && (
|
||||
<Animated.View
|
||||
entering={FadeInUp}
|
||||
exiting={FadeOutUp}
|
||||
style={[a.flex_1]}>
|
||||
<Animated.View
|
||||
onLayout={evt => setCardHeight(evt.nativeEvent.layout.height)}
|
||||
accessibilityRole="alert"
|
||||
accessible={true}
|
||||
accessibilityLabel={message}
|
||||
accessibilityHint=""
|
||||
onAccessibilityEscape={hideAndDestroyImmediately}
|
||||
style={[
|
||||
a.flex_1,
|
||||
t.name === 'dark' ? t.atoms.bg_contrast_25 : t.atoms.bg,
|
||||
a.shadow_lg,
|
||||
t.atoms.border_contrast_medium,
|
||||
a.rounded_sm,
|
||||
a.border,
|
||||
animatedStyle,
|
||||
]}>
|
||||
<GestureDetector gesture={panGesture}>
|
||||
<View style={[a.flex_1, a.px_md, a.py_lg, a.flex_row, a.gap_md]}>
|
||||
<View
|
||||
style={[
|
||||
a.flex_shrink_0,
|
||||
a.rounded_full,
|
||||
{width: 32, height: 32},
|
||||
a.align_center,
|
||||
a.justify_center,
|
||||
{
|
||||
backgroundColor:
|
||||
t.name === 'dark'
|
||||
? t.palette.black
|
||||
: t.palette.primary_50,
|
||||
},
|
||||
]}>
|
||||
<FontAwesomeIcon
|
||||
icon={icon}
|
||||
size={16}
|
||||
style={t.atoms.text_contrast_medium}
|
||||
/>
|
||||
</View>
|
||||
<View style={[a.h_full, a.justify_center, a.flex_1]}>
|
||||
<Text style={a.text_md} emoji>
|
||||
{message}
|
||||
</Text>
|
||||
</View>
|
||||
entering={FadeIn.duration(TOAST_ANIMATION_CONFIG.duration)}
|
||||
exiting={FadeOut.duration(TOAST_ANIMATION_CONFIG.duration * 0.7)}
|
||||
onLayout={evt => setCardHeight(evt.nativeEvent.layout.height)}
|
||||
accessibilityRole="alert"
|
||||
accessible={true}
|
||||
accessibilityLabel={message}
|
||||
accessibilityHint=""
|
||||
onAccessibilityEscape={hideAndDestroyImmediately}
|
||||
style={[
|
||||
a.flex_1,
|
||||
{backgroundColor: colors.backgroundColor},
|
||||
a.shadow_sm,
|
||||
{borderColor: colors.borderColor, borderWidth: 1},
|
||||
a.rounded_sm,
|
||||
animatedStyle,
|
||||
]}>
|
||||
<GestureDetector gesture={panGesture}>
|
||||
<View style={[a.flex_1, a.px_md, a.py_lg, a.flex_row, a.gap_md]}>
|
||||
<View
|
||||
style={[
|
||||
a.flex_shrink_0,
|
||||
a.rounded_full,
|
||||
{width: 32, height: 32},
|
||||
a.align_center,
|
||||
a.justify_center,
|
||||
{
|
||||
backgroundColor: colors.backgroundColor,
|
||||
},
|
||||
]}>
|
||||
<IconComponent fill={colors.iconColor} size="sm" />
|
||||
</View>
|
||||
</GestureDetector>
|
||||
</Animated.View>
|
||||
<View
|
||||
style={[
|
||||
a.h_full,
|
||||
a.justify_center,
|
||||
a.flex_1,
|
||||
a.justify_center,
|
||||
]}>
|
||||
<Text
|
||||
style={[a.text_md, a.font_bold, {color: colors.textColor}]}
|
||||
emoji>
|
||||
{message}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</GestureDetector>
|
||||
</Animated.View>
|
||||
)}
|
||||
</GestureHandlerRootView>
|
||||
|
||||
@@ -4,17 +4,23 @@
|
||||
|
||||
import {useEffect, useState} from 'react'
|
||||
import {Pressable, StyleSheet, Text, View} from 'react-native'
|
||||
|
||||
import {
|
||||
FontAwesomeIcon,
|
||||
type FontAwesomeIconStyle,
|
||||
type Props as FontAwesomeProps,
|
||||
} from '@fortawesome/react-native-fontawesome'
|
||||
convertLegacyToastType,
|
||||
getToastTypeStyles,
|
||||
getToastWebAnimationStyles,
|
||||
type LegacyToastType,
|
||||
TOAST_TYPE_TO_ICON,
|
||||
TOAST_WEB_KEYFRAMES,
|
||||
type ToastType,
|
||||
} from '#/view/com/util/Toast.style'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
|
||||
const DURATION = 3500
|
||||
|
||||
interface ActiveToast {
|
||||
text: string
|
||||
icon: FontAwesomeProps['icon']
|
||||
type: ToastType
|
||||
}
|
||||
type GlobalSetActiveToast = (_activeToast: ActiveToast | undefined) => void
|
||||
|
||||
@@ -28,21 +34,82 @@ let toastTimeout: NodeJS.Timeout | undefined
|
||||
type ToastContainerProps = {}
|
||||
export const ToastContainer: React.FC<ToastContainerProps> = ({}) => {
|
||||
const [activeToast, setActiveToast] = useState<ActiveToast | undefined>()
|
||||
const [isExiting, setIsExiting] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
globalSetActiveToast = (t: ActiveToast | undefined) => {
|
||||
setActiveToast(t)
|
||||
if (!t && activeToast) {
|
||||
setIsExiting(true)
|
||||
setTimeout(() => {
|
||||
setActiveToast(t)
|
||||
setIsExiting(false)
|
||||
}, 200)
|
||||
} else {
|
||||
setActiveToast(t)
|
||||
setIsExiting(false)
|
||||
}
|
||||
}
|
||||
})
|
||||
}, [activeToast])
|
||||
|
||||
useEffect(() => {
|
||||
const styleId = 'toast-animations'
|
||||
if (!document.getElementById(styleId)) {
|
||||
const style = document.createElement('style')
|
||||
style.id = styleId
|
||||
style.textContent = TOAST_WEB_KEYFRAMES
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
}, [])
|
||||
|
||||
const t = useTheme()
|
||||
|
||||
const toastTypeStyles = getToastTypeStyles(t)
|
||||
const toastStyles = activeToast
|
||||
? toastTypeStyles[activeToast.type]
|
||||
: toastTypeStyles.default
|
||||
|
||||
const IconComponent = activeToast
|
||||
? TOAST_TYPE_TO_ICON[activeToast.type]
|
||||
: TOAST_TYPE_TO_ICON.default
|
||||
|
||||
const animationStyles = getToastWebAnimationStyles()
|
||||
|
||||
return (
|
||||
<>
|
||||
{activeToast && (
|
||||
<View style={styles.container}>
|
||||
<FontAwesomeIcon
|
||||
icon={activeToast.icon}
|
||||
size={20}
|
||||
style={styles.icon as FontAwesomeIconStyle}
|
||||
/>
|
||||
<Text style={styles.text}>{activeToast.text}</Text>
|
||||
<View
|
||||
style={[
|
||||
styles.container,
|
||||
{
|
||||
backgroundColor: toastStyles.backgroundColor,
|
||||
borderColor: toastStyles.borderColor,
|
||||
...(isExiting
|
||||
? animationStyles.exiting
|
||||
: animationStyles.entering),
|
||||
},
|
||||
]}>
|
||||
<View
|
||||
style={[
|
||||
styles.iconContainer,
|
||||
{
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
]}>
|
||||
<IconComponent
|
||||
fill={toastStyles.iconColor}
|
||||
size="sm"
|
||||
style={styles.icon}
|
||||
/>
|
||||
</View>
|
||||
<Text
|
||||
style={[
|
||||
styles.text,
|
||||
a.text_sm,
|
||||
a.font_bold,
|
||||
{color: toastStyles.textColor},
|
||||
]}>
|
||||
{activeToast.text}
|
||||
</Text>
|
||||
<Pressable
|
||||
style={styles.dismissBackdrop}
|
||||
accessibilityLabel="Dismiss"
|
||||
@@ -60,11 +127,15 @@ export const ToastContainer: React.FC<ToastContainerProps> = ({}) => {
|
||||
// methods
|
||||
// =
|
||||
|
||||
export function show(text: string, icon: FontAwesomeProps['icon'] = 'check') {
|
||||
export function show(
|
||||
text: string,
|
||||
type: ToastType | LegacyToastType = 'default',
|
||||
) {
|
||||
if (toastTimeout) {
|
||||
clearTimeout(toastTimeout)
|
||||
}
|
||||
globalSetActiveToast?.({text, icon})
|
||||
|
||||
globalSetActiveToast?.({text, type: convertLegacyToastType(type)})
|
||||
toastTimeout = setTimeout(() => {
|
||||
globalSetActiveToast?.(undefined)
|
||||
}, DURATION)
|
||||
@@ -78,12 +149,12 @@ const styles = StyleSheet.create({
|
||||
bottom: 20,
|
||||
// @ts-ignore web only
|
||||
width: 'calc(100% - 40px)',
|
||||
maxWidth: 350,
|
||||
maxWidth: 380,
|
||||
padding: 20,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
backgroundColor: '#000c',
|
||||
borderRadius: 10,
|
||||
borderWidth: 1,
|
||||
},
|
||||
dismissBackdrop: {
|
||||
position: 'absolute',
|
||||
@@ -92,13 +163,18 @@ const styles = StyleSheet.create({
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
},
|
||||
iconContainer: {
|
||||
width: 32,
|
||||
height: 32,
|
||||
borderRadius: 16,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
flexShrink: 0,
|
||||
},
|
||||
icon: {
|
||||
color: '#fff',
|
||||
flexShrink: 0,
|
||||
},
|
||||
text: {
|
||||
color: '#fff',
|
||||
fontSize: 18,
|
||||
marginLeft: 10,
|
||||
},
|
||||
})
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
import {Pressable, View} from 'react-native'
|
||||
|
||||
import * as Toast from '#/view/com/util/Toast'
|
||||
import {
|
||||
getToastTypeStyles,
|
||||
TOAST_TYPE_TO_ICON,
|
||||
type ToastType,
|
||||
} from '#/view/com/util/Toast.style'
|
||||
import {atoms as a, useTheme} from '#/alf'
|
||||
import {H1, Text} from '#/components/Typography'
|
||||
|
||||
function ToastPreview({message, type}: {message: string; type: ToastType}) {
|
||||
const t = useTheme()
|
||||
const toastStyles = getToastTypeStyles(t)
|
||||
const colors = toastStyles[type as keyof typeof toastStyles]
|
||||
const IconComponent =
|
||||
TOAST_TYPE_TO_ICON[type as keyof typeof TOAST_TYPE_TO_ICON]
|
||||
|
||||
return (
|
||||
<Pressable
|
||||
accessibilityRole="button"
|
||||
onPress={() => Toast.show(message, type)}
|
||||
style={[
|
||||
{backgroundColor: colors.backgroundColor},
|
||||
a.shadow_sm,
|
||||
{borderColor: colors.borderColor},
|
||||
a.rounded_sm,
|
||||
a.border,
|
||||
a.px_sm,
|
||||
a.py_sm,
|
||||
a.flex_row,
|
||||
a.gap_sm,
|
||||
a.align_center,
|
||||
]}>
|
||||
<View
|
||||
style={[
|
||||
a.flex_shrink_0,
|
||||
a.rounded_full,
|
||||
{width: 24, height: 24},
|
||||
a.align_center,
|
||||
a.justify_center,
|
||||
{
|
||||
backgroundColor: colors.backgroundColor,
|
||||
},
|
||||
]}>
|
||||
<IconComponent fill={colors.iconColor} size="xs" />
|
||||
</View>
|
||||
<View style={[a.flex_1]}>
|
||||
<Text
|
||||
style={[
|
||||
a.text_sm,
|
||||
a.font_bold,
|
||||
a.leading_snug,
|
||||
{color: colors.textColor},
|
||||
]}
|
||||
emoji>
|
||||
{message}
|
||||
</Text>
|
||||
</View>
|
||||
</Pressable>
|
||||
)
|
||||
}
|
||||
|
||||
export function Toasts() {
|
||||
return (
|
||||
<View style={[a.gap_md]}>
|
||||
<H1>Toast Examples</H1>
|
||||
|
||||
<View style={[a.gap_md]}>
|
||||
<View style={[a.gap_xs]}>
|
||||
<ToastPreview message="Default Toast" type="default" />
|
||||
</View>
|
||||
|
||||
<View style={[a.gap_xs]}>
|
||||
<ToastPreview
|
||||
message="Operation completed successfully!"
|
||||
type="success"
|
||||
/>
|
||||
</View>
|
||||
|
||||
<View style={[a.gap_xs]}>
|
||||
<ToastPreview message="Something went wrong!" type="error" />
|
||||
</View>
|
||||
|
||||
<View style={[a.gap_xs]}>
|
||||
<ToastPreview message="Please check your input" type="warning" />
|
||||
</View>
|
||||
|
||||
<View style={[a.gap_xs]}>
|
||||
<ToastPreview message="Here's some helpful information" type="info" />
|
||||
</View>
|
||||
|
||||
<View style={[a.gap_xs]}>
|
||||
<ToastPreview
|
||||
message="This is a longer message to test how the toast handles multiple lines of text content."
|
||||
type="info"
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import {Settings} from './Settings'
|
||||
import {Shadows} from './Shadows'
|
||||
import {Spacing} from './Spacing'
|
||||
import {Theming} from './Theming'
|
||||
import {Toasts} from './Toasts'
|
||||
import {Typography} from './Typography'
|
||||
|
||||
export function Storybook() {
|
||||
@@ -122,6 +123,7 @@ function StorybookInner() {
|
||||
<Breakpoints />
|
||||
<Dialogs />
|
||||
<Admonitions />
|
||||
<Toasts />
|
||||
<Settings />
|
||||
|
||||
<Button
|
||||
|
||||
Reference in New Issue
Block a user