Merge remote-tracking branch 'origin/main' into eric/nova
* origin/main: (22 commits) basic public RSS feed for profiles (#2229) use `s.likeColor` everywhere (#2234) Add credits to localization doc (#2233) Fix `Logotype` fill for dark mode (#2230) Hide label appeal on self-labeled posts (#2232) Fix & Add: Japanese Translation (3) (#2226) tweak social card meta yet again (#2228) bskyweb: update golang indigo dep (from May!), and some small devex tweaks (#2227) Fix: Some display issues (#2219) Update splash screen tagline, update translations, bump ios build number Bump ios build number Tweaks (#2225) 1.60 Traffic reduction and tuned caching strats (#2215) Super secret changes don't look (#2218) Fix android icon dims (#2213) Log post creation failures (#2205) Some brand, some pwi (#2212) 🤫 (#2211) PWI behavior updates (#2207) ...
@@ -10,6 +10,7 @@ help: ## Print info about all commands
|
||||
|
||||
.PHONY: build-web
|
||||
build-web: ## Compile web bundle, copy to bskyweb directory
|
||||
yarn intl:build
|
||||
yarn build-web
|
||||
|
||||
.PHONY: test
|
||||
|
||||
@@ -9,12 +9,12 @@ module.exports = function () {
|
||||
/**
|
||||
* iOS build number. Must be incremented for each TestFlight version.
|
||||
*/
|
||||
const IOS_BUILD_NUMBER = '2'
|
||||
const IOS_BUILD_NUMBER = '4'
|
||||
|
||||
/**
|
||||
* Android build number. Must be incremented for each release.
|
||||
*/
|
||||
const ANDROID_VERSION_CODE = 49
|
||||
const ANDROID_VERSION_CODE = 50
|
||||
|
||||
/**
|
||||
* Uses built-in Expo env vars
|
||||
@@ -43,7 +43,7 @@ module.exports = function () {
|
||||
icon: './assets/icon.png',
|
||||
userInterfaceStyle: 'automatic',
|
||||
splash: {
|
||||
image: './assets/cloud-splash.png',
|
||||
image: './assets/splash.png',
|
||||
resizeMode: 'cover',
|
||||
backgroundColor: '#ffffff',
|
||||
},
|
||||
@@ -73,9 +73,12 @@ module.exports = function () {
|
||||
},
|
||||
android: {
|
||||
versionCode: ANDROID_VERSION_CODE,
|
||||
icon: './assets/icon.png',
|
||||
adaptiveIcon: {
|
||||
foregroundImage: './assets/adaptive-icon.png',
|
||||
backgroundColor: '#ffffff',
|
||||
foregroundImage: './assets/icon-android-foreground.png',
|
||||
monochromeImage: './assets/icon-android-foreground.png',
|
||||
backgroundImage: './assets/icon-android-background.png',
|
||||
backgroundColor: '#1185FE',
|
||||
},
|
||||
googleServicesFile: './google-services.json',
|
||||
package: 'xyz.blueskyweb.app',
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 MiB |
|
Before Width: | Height: | Size: 696 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 223 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 1.1 MiB After Width: | Height: | Size: 452 KiB |
|
After Width: | Height: | Size: 1.4 MiB |
|
Before Width: | Height: | Size: 78 KiB |
@@ -42,4 +42,4 @@ check: ## Compile everything, checking syntax (does not output binaries)
|
||||
|
||||
.PHONY: run-dev-bskyweb
|
||||
run-dev-bskyweb: .env ## Runs 'bskyweb' for local dev
|
||||
GOLOG_LOG_LEVEL=info go run ./cmd/bskyweb serve --debug
|
||||
GOLOG_LOG_LEVEL=info go run ./cmd/bskyweb serve
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
appbsky "github.com/bluesky-social/indigo/api/bsky"
|
||||
"github.com/bluesky-social/indigo/atproto/syntax"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// We don't actually populate the title for "posts".
|
||||
// Some background: https://book.micro.blog/rss-for-microblogs/
|
||||
type Item struct {
|
||||
Title string `xml:"title,omitempty"`
|
||||
Link string `xml:"link,omitempty"`
|
||||
Description string `xml:"description,omitempty"`
|
||||
PubDate string `xml:"pubDate,omitempty"`
|
||||
Author string `xml:"author,omitempty"`
|
||||
GUID string `xml:"guid,omitempty"`
|
||||
}
|
||||
|
||||
type rss struct {
|
||||
Version string `xml:"version,attr"`
|
||||
Description string `xml:"channel>description,omitempty"`
|
||||
Link string `xml:"channel>link"`
|
||||
Title string `xml:"channel>title"`
|
||||
|
||||
Item []Item `xml:"channel>item"`
|
||||
}
|
||||
|
||||
func (srv *Server) WebProfileRSS(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
|
||||
didParam := c.Param("did")
|
||||
did, err := syntax.ParseDID(didParam)
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(400, fmt.Sprintf("not a valid DID: %s", didParam))
|
||||
}
|
||||
|
||||
// check that public view is Ok
|
||||
pv, err := appbsky.ActorGetProfile(ctx, srv.xrpcc, did.String())
|
||||
if err != nil {
|
||||
return echo.NewHTTPError(404, fmt.Sprintf("account not found: %s", did))
|
||||
}
|
||||
for _, label := range pv.Labels {
|
||||
if label.Src == pv.Did && label.Val == "!no-unauthenticated" {
|
||||
return echo.NewHTTPError(403, fmt.Sprintf("account does not allow public views: %s", did))
|
||||
}
|
||||
}
|
||||
|
||||
af, err := appbsky.FeedGetAuthorFeed(ctx, srv.xrpcc, did.String(), "", "", 30)
|
||||
if err != nil {
|
||||
log.Warn("failed to fetch author feed", "did", did, "err", err)
|
||||
return err
|
||||
}
|
||||
|
||||
posts := []Item{}
|
||||
for _, p := range af.Feed {
|
||||
// only include author's own posts in RSS
|
||||
if p.Post.Author.Did != pv.Did {
|
||||
continue
|
||||
}
|
||||
aturi, err := syntax.ParseATURI(p.Post.Uri)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rec := p.Post.Record.Val.(*appbsky.FeedPost)
|
||||
// only top-level posts in RSS (no replies)
|
||||
if rec.Reply != nil {
|
||||
continue
|
||||
}
|
||||
posts = append(posts, Item{
|
||||
Link: fmt.Sprintf("https://bsky.app/profile/%s/post/%s", pv.Handle, aturi.RecordKey().String()),
|
||||
Description: rec.Text,
|
||||
PubDate: rec.CreatedAt,
|
||||
Author: "@" + pv.Handle,
|
||||
GUID: aturi.String(),
|
||||
})
|
||||
}
|
||||
|
||||
title := "@" + pv.Handle
|
||||
if pv.DisplayName != nil {
|
||||
title = title + " - " + *pv.DisplayName
|
||||
}
|
||||
desc := ""
|
||||
if pv.Description != nil {
|
||||
desc = *pv.Description
|
||||
}
|
||||
feed := &rss{
|
||||
Version: "2.0",
|
||||
Description: desc,
|
||||
Link: fmt.Sprintf("https://bsky.app/profile/%s", pv.Handle),
|
||||
Title: title,
|
||||
Item: posts,
|
||||
}
|
||||
return c.XML(http.StatusOK, feed)
|
||||
}
|
||||
@@ -15,7 +15,8 @@ import (
|
||||
"time"
|
||||
|
||||
appbsky "github.com/bluesky-social/indigo/api/bsky"
|
||||
cliutil "github.com/bluesky-social/indigo/cmd/gosky/util"
|
||||
"github.com/bluesky-social/indigo/atproto/syntax"
|
||||
"github.com/bluesky-social/indigo/util/cliutil"
|
||||
"github.com/bluesky-social/indigo/xrpc"
|
||||
"github.com/bluesky-social/social-app/bskyweb"
|
||||
|
||||
@@ -208,6 +209,9 @@ func serve(cctx *cli.Context) error {
|
||||
e.GET("/profile/:handle/feed/:rkey", server.WebGeneric)
|
||||
e.GET("/profile/:handle/feed/:rkey/liked-by", server.WebGeneric)
|
||||
|
||||
// profile RSS feed (DID not handle)
|
||||
e.GET("/profile/:did/rss", server.WebProfileRSS)
|
||||
|
||||
// post endpoints; only first populates info
|
||||
e.GET("/profile/:handle/post/:rkey", server.WebPost)
|
||||
e.GET("/profile/:handle/post/:rkey/liked-by", server.WebGeneric)
|
||||
@@ -285,73 +289,87 @@ func (srv *Server) WebHome(c echo.Context) error {
|
||||
}
|
||||
|
||||
func (srv *Server) WebPost(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
data := pongo2.Context{}
|
||||
handle := c.Param("handle")
|
||||
rkey := c.Param("rkey")
|
||||
// sanity check argument
|
||||
if len(handle) > 4 && len(handle) < 128 && len(rkey) > 0 {
|
||||
ctx := c.Request().Context()
|
||||
// requires two fetches: first fetch profile (!)
|
||||
pv, err := appbsky.ActorGetProfile(ctx, srv.xrpcc, handle)
|
||||
if err != nil {
|
||||
log.Warnf("failed to fetch handle: %s\t%v", handle, err)
|
||||
} else {
|
||||
unauthedViewingOkay := true
|
||||
for _, label := range pv.Labels {
|
||||
if label.Src == pv.Did && label.Val == "!no-unauthenticated" {
|
||||
unauthedViewingOkay = false
|
||||
}
|
||||
}
|
||||
|
||||
if unauthedViewingOkay {
|
||||
did := pv.Did
|
||||
data["did"] = did
|
||||
// sanity check arguments. don't 4xx, just let app handle if not expected format
|
||||
rkeyParam := c.Param("rkey")
|
||||
rkey, err := syntax.ParseRecordKey(rkeyParam)
|
||||
if err != nil {
|
||||
return c.Render(http.StatusOK, "post.html", data)
|
||||
}
|
||||
handleParam := c.Param("handle")
|
||||
handle, err := syntax.ParseHandle(handleParam)
|
||||
if err != nil {
|
||||
return c.Render(http.StatusOK, "post.html", data)
|
||||
}
|
||||
handle = handle.Normalize()
|
||||
|
||||
// then fetch the post thread (with extra context)
|
||||
uri := fmt.Sprintf("at://%s/app.bsky.feed.post/%s", did, rkey)
|
||||
tpv, err := appbsky.FeedGetPostThread(ctx, srv.xrpcc, 1, uri)
|
||||
if err != nil {
|
||||
log.Warnf("failed to fetch post: %s\t%v", uri, err)
|
||||
} else {
|
||||
req := c.Request()
|
||||
postView := tpv.Thread.FeedDefs_ThreadViewPost.Post
|
||||
data["postView"] = postView
|
||||
data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
|
||||
if postView.Embed != nil && postView.Embed.EmbedImages_View != nil {
|
||||
data["imgThumbUrl"] = postView.Embed.EmbedImages_View.Images[0].Thumb
|
||||
}
|
||||
}
|
||||
}
|
||||
// requires two fetches: first fetch profile (!)
|
||||
pv, err := appbsky.ActorGetProfile(ctx, srv.xrpcc, handle.String())
|
||||
if err != nil {
|
||||
log.Warnf("failed to fetch handle: %s\t%v", handle, err)
|
||||
return c.Render(http.StatusOK, "post.html", data)
|
||||
}
|
||||
unauthedViewingOkay := true
|
||||
for _, label := range pv.Labels {
|
||||
if label.Src == pv.Did && label.Val == "!no-unauthenticated" {
|
||||
unauthedViewingOkay = false
|
||||
}
|
||||
}
|
||||
|
||||
if !unauthedViewingOkay {
|
||||
return c.Render(http.StatusOK, "post.html", data)
|
||||
}
|
||||
did := pv.Did
|
||||
data["did"] = did
|
||||
|
||||
// then fetch the post thread (with extra context)
|
||||
uri := fmt.Sprintf("at://%s/app.bsky.feed.post/%s", did, rkey)
|
||||
tpv, err := appbsky.FeedGetPostThread(ctx, srv.xrpcc, 1, 0, uri)
|
||||
if err != nil {
|
||||
log.Warnf("failed to fetch post: %s\t%v", uri, err)
|
||||
return c.Render(http.StatusOK, "post.html", data)
|
||||
}
|
||||
req := c.Request()
|
||||
postView := tpv.Thread.FeedDefs_ThreadViewPost.Post
|
||||
data["postView"] = postView
|
||||
data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
|
||||
if postView.Embed != nil && postView.Embed.EmbedImages_View != nil {
|
||||
data["imgThumbUrl"] = postView.Embed.EmbedImages_View.Images[0].Thumb
|
||||
}
|
||||
return c.Render(http.StatusOK, "post.html", data)
|
||||
}
|
||||
|
||||
func (srv *Server) WebProfile(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
data := pongo2.Context{}
|
||||
handle := c.Param("handle")
|
||||
// sanity check argument
|
||||
if len(handle) > 4 && len(handle) < 128 {
|
||||
ctx := c.Request().Context()
|
||||
pv, err := appbsky.ActorGetProfile(ctx, srv.xrpcc, handle)
|
||||
if err != nil {
|
||||
log.Warnf("failed to fetch handle: %s\t%v", handle, err)
|
||||
} else {
|
||||
unauthedViewingOkay := true
|
||||
for _, label := range pv.Labels {
|
||||
if label.Src == pv.Did && label.Val == "!no-unauthenticated" {
|
||||
unauthedViewingOkay = false
|
||||
}
|
||||
}
|
||||
if unauthedViewingOkay {
|
||||
req := c.Request()
|
||||
data["profileView"] = pv
|
||||
data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
|
||||
}
|
||||
|
||||
// sanity check arguments. don't 4xx, just let app handle if not expected format
|
||||
handleParam := c.Param("handle")
|
||||
handle, err := syntax.ParseHandle(handleParam)
|
||||
if err != nil {
|
||||
return c.Render(http.StatusOK, "profile.html", data)
|
||||
}
|
||||
handle = handle.Normalize()
|
||||
|
||||
pv, err := appbsky.ActorGetProfile(ctx, srv.xrpcc, handle.String())
|
||||
if err != nil {
|
||||
log.Warnf("failed to fetch handle: %s\t%v", handle, err)
|
||||
return c.Render(http.StatusOK, "profile.html", data)
|
||||
}
|
||||
unauthedViewingOkay := true
|
||||
for _, label := range pv.Labels {
|
||||
if label.Src == pv.Did && label.Val == "!no-unauthenticated" {
|
||||
unauthedViewingOkay = false
|
||||
}
|
||||
}
|
||||
|
||||
if !unauthedViewingOkay {
|
||||
return c.Render(http.StatusOK, "profile.html", data)
|
||||
}
|
||||
req := c.Request()
|
||||
data["profileView"] = pv
|
||||
data["requestURI"] = fmt.Sprintf("https://%s%s", req.Host, req.URL.Path)
|
||||
return c.Render(http.StatusOK, "profile.html", data)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
GOLOG_LOG_LEVEL=info
|
||||
ATP_APPVIEW_HOST=https://api.bsky.app
|
||||
ATP_APPVIEW_HOST=https://public.api.bsky.app
|
||||
|
||||
@@ -3,88 +3,104 @@ module github.com/bluesky-social/social-app/bskyweb
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/bluesky-social/indigo v0.0.0-20230504025040-8915cccc3319
|
||||
github.com/bluesky-social/indigo v0.0.0-20231216010655-ad730a7da4f5
|
||||
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.16.5
|
||||
github.com/labstack/echo/v4 v4.10.2
|
||||
github.com/urfave/cli/v2 v2.25.3
|
||||
github.com/klauspost/compress v1.17.3
|
||||
github.com/labstack/echo/v4 v4.11.3
|
||||
github.com/urfave/cli/v2 v2.25.7
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/benbjohnson/clock v1.3.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/carlmjohnson/versioninfo v0.22.5 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.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/go-logr/logr v1.2.4 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
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.3.0 // 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.2 // indirect
|
||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
|
||||
github.com/hashicorp/golang-lru v1.0.2 // indirect
|
||||
github.com/hashicorp/golang-lru/arc/v2 v2.0.6 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/ipfs/bbloom v0.0.4 // indirect
|
||||
github.com/ipfs/go-block-format v0.1.2 // indirect
|
||||
github.com/ipfs/go-block-format v0.2.0 // indirect
|
||||
github.com/ipfs/go-cid v0.4.1 // indirect
|
||||
github.com/ipfs/go-datastore v0.6.0 // indirect
|
||||
github.com/ipfs/go-ipfs-blockstore v1.3.0 // indirect
|
||||
github.com/ipfs/go-ipfs-ds-help v1.1.0 // indirect
|
||||
github.com/ipfs/go-ipfs-util v0.0.2 // indirect
|
||||
github.com/ipfs/go-ipld-cbor v0.0.7-0.20230126201833-a73d038d90bc // indirect
|
||||
github.com/ipfs/go-ipld-format v0.4.0 // indirect
|
||||
github.com/ipfs/go-ipfs-blockstore v1.3.1 // indirect
|
||||
github.com/ipfs/go-ipfs-ds-help v1.1.1 // indirect
|
||||
github.com/ipfs/go-ipfs-util v0.0.3 // indirect
|
||||
github.com/ipfs/go-ipld-cbor v0.1.0 // indirect
|
||||
github.com/ipfs/go-ipld-format v0.6.0 // indirect
|
||||
github.com/ipfs/go-log/v2 v2.5.1 // indirect
|
||||
github.com/ipfs/go-metrics-interface v0.0.1 // indirect
|
||||
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgx/v5 v5.3.1 // indirect
|
||||
github.com/jackc/pgx/v5 v5.5.0 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/jbenet/goprocess v0.1.4 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||
github.com/labstack/gommon v0.4.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||
github.com/labstack/gommon v0.4.1 // 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.9 // 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-isatty v0.0.18 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.16 // indirect
|
||||
github.com/minio/sha256-simd v1.0.0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-sqlite3 v1.14.18 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
||||
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mr-tron/base58 v1.2.0 // indirect
|
||||
github.com/multiformats/go-base32 v0.1.0 // indirect
|
||||
github.com/multiformats/go-base36 v0.2.0 // indirect
|
||||
github.com/multiformats/go-multibase v0.2.0 // indirect
|
||||
github.com/multiformats/go-multihash v0.2.1 // indirect
|
||||
github.com/multiformats/go-multihash v0.2.3 // indirect
|
||||
github.com/multiformats/go-varint v0.0.7 // indirect
|
||||
github.com/opentracing/opentracing-go v1.2.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // 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/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
github.com/spaolacci/murmur3 v1.1.0 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20230418232409-daab9ece03a0 // indirect
|
||||
github.com/whyrusleeping/go-did v0.0.0-20230301193428-2146016fc220 // indirect
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20230923211252-36a87e1ba72f // indirect
|
||||
github.com/whyrusleeping/go-did v0.0.0-20230824162731-404d1707d5d6 // indirect
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||
go.opentelemetry.io/otel v1.15.1 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.15.1 // indirect
|
||||
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b // indirect
|
||||
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 // indirect
|
||||
go.opentelemetry.io/otel v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.21.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.24.0 // indirect
|
||||
golang.org/x/crypto v0.8.0 // indirect
|
||||
golang.org/x/net v0.9.0 // indirect
|
||||
golang.org/x/sys v0.7.0 // indirect
|
||||
golang.org/x/text v0.9.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
golang.org/x/crypto v0.15.0 // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sync v0.5.0 // indirect
|
||||
golang.org/x/sys v0.14.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.3.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect
|
||||
google.golang.org/protobuf v1.31.0 // indirect
|
||||
gorm.io/driver/postgres v1.5.0 // indirect
|
||||
gorm.io/driver/sqlite v1.5.0 // indirect
|
||||
gorm.io/gorm v1.25.0 // indirect
|
||||
lukechampine.com/blake3 v1.1.7 // indirect
|
||||
gorm.io/driver/sqlite v1.5.4 // indirect
|
||||
gorm.io/gorm v1.25.5 // indirect
|
||||
lukechampine.com/blake3 v1.2.1 // indirect
|
||||
)
|
||||
|
||||
@@ -1,25 +1,30 @@
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
||||
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||
github.com/bluesky-social/indigo v0.0.0-20230504025040-8915cccc3319 h1:VCNXRXpgyK3xkaQ8fzL5WzswerwLycke4B9ggLs1uOA=
|
||||
github.com/bluesky-social/indigo v0.0.0-20230504025040-8915cccc3319/go.mod h1:Hc09SUJXAIujaAvq7JXxi8ZQQI887grzPkHgn4JyE1Q=
|
||||
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-20231216010655-ad730a7da4f5 h1:Zk1c+mxCYH6G/vLL0+9lO2Eci4OT3AFy73qPWa9auDM=
|
||||
github.com/bluesky-social/indigo v0.0.0-20231216010655-ad730a7da4f5/go.mod h1:a8cPbqDkRX+aPwJnXF7kAi3PF26hYiR4w5H8624MB7k=
|
||||
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/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.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
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=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc=
|
||||
github.com/decred/dcrd/crypto/blake256 v1.0.1/go.mod h1:2OfgNZ5wDpcsFmHmCK5gZTPcCXqlm2ArzUIkw9czNJo=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0 h1:8UrgZ3GkP4i/CLijOJx79Yu+etlyjdBU4sfcs2WYQMs=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.2.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
|
||||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/flosch/pongo2/v6 v6.0.0 h1:lsGru8IAzHgIAw6H2m4PCyleO58I40ow6apih0WprMU=
|
||||
github.com/flosch/pongo2/v6 v6.0.0/go.mod h1:CuDpFm47R0uGGE7z13/tTlt1Y6zdxvr2RLT5LJhsHEU=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible/go.mod h1:w2MrLa16VYP0jy6N7M5kHaCkaLENm+P+Tv+MfurjSw0=
|
||||
@@ -29,53 +34,49 @@ 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/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
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/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
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=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gxed/hashland/keccakpg v0.0.1/go.mod h1:kRzw3HkwxFU1mpmPP8v1WyQzwdGfmKFJ6tItnhQ67kU=
|
||||
github.com/gxed/hashland/murmur3 v0.0.1/go.mod h1:KjXop02n4/ckmZSnY2+HKcLud/tcmvhST0bie/0lS48=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 h1:035FKYIWjmULyFRBKPs8TBQoi0x6d9G4xc9neXJWAZQ=
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
|
||||
github.com/hashicorp/go-hclog v0.9.2 h1:CG6TE5H9/JXsFWJCfoIVpKFIkFe6ysEuHirp4DxCsHI=
|
||||
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.2 h1:AcYqCvkpalPnPF2pn0KamgwamS42TqUDDYFRKq/RAd0=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.2/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
|
||||
github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c=
|
||||
github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/hashicorp/golang-lru/arc/v2 v2.0.6 h1:4NU7uP5vSoK6TbaMj3NtY478TTAWLso/vL1gpNrInHg=
|
||||
github.com/hashicorp/golang-lru/arc/v2 v2.0.6/go.mod h1:cfdDIX05DWvYV6/shsxDfa/OVcRieOt+q4FnM8x+Xno=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/ipfs/bbloom v0.0.4 h1:Gi+8EGJ2y5qiD5FbsbpX/TMNcJw8gSqr7eyjHa4Fhvs=
|
||||
github.com/ipfs/bbloom v0.0.4/go.mod h1:cS9YprKXpoZ9lT0n/Mw/a6/aFV6DTjTLYHeA+gyqMG0=
|
||||
github.com/ipfs/go-block-format v0.0.2/go.mod h1:AWR46JfpcObNfg3ok2JHDUfdiHRgWhJgCQF+KIgOPJY=
|
||||
github.com/ipfs/go-block-format v0.1.2 h1:GAjkfhVx1f4YTODS6Esrj1wt2HhrtwTnhEr+DyPUaJo=
|
||||
github.com/ipfs/go-block-format v0.1.2/go.mod h1:mACVcrxarQKstUU3Yf/RdwbC4DzPV6++rO2a3d+a/KE=
|
||||
github.com/ipfs/go-cid v0.0.1/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
|
||||
github.com/ipfs/go-cid v0.0.2/go.mod h1:GHWU/WuQdMPmIosc4Yn1bcCT7dSeX4lBafM7iqUPQvM=
|
||||
github.com/ipfs/go-cid v0.0.5/go.mod h1:plgt+Y5MnOey4vO4UlUazGqdbEXuFYitED67FexhXog=
|
||||
github.com/ipfs/go-block-format v0.2.0 h1:ZqrkxBA2ICbDRbK8KJs/u0O3dlp6gmAuuXUJNiW1Ycs=
|
||||
github.com/ipfs/go-block-format v0.2.0/go.mod h1:+jpL11nFx5A/SPpsoBn6Bzkra/zaArfSmsknbPMYgzM=
|
||||
github.com/ipfs/go-cid v0.0.6/go.mod h1:6Ux9z5e+HpkQdckYoX1PG/6xqKspzlEIR5SDmgqgC/I=
|
||||
github.com/ipfs/go-cid v0.4.1 h1:A/T3qGvxi4kpKWWcPC/PgbvDA2bjVLO7n4UeVwnbs/s=
|
||||
github.com/ipfs/go-cid v0.4.1/go.mod h1:uQHwDeX4c6CtyrFwdqyhpNcxVewur1M7l7fNU7LKwZk=
|
||||
github.com/ipfs/go-datastore v0.5.0/go.mod h1:9zhEApYMTl17C8YDp7JmU7sQZi2/wqiYh73hakZ90Bk=
|
||||
github.com/ipfs/go-datastore v0.6.0 h1:JKyz+Gvz1QEZw0LsX1IBn+JFCJQH4SJVFtM4uWU0Myk=
|
||||
github.com/ipfs/go-datastore v0.6.0/go.mod h1:rt5M3nNbSO/8q1t4LNkLyUwRs8HupMeN/8O4Vn9YAT8=
|
||||
github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
|
||||
github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
|
||||
github.com/ipfs/go-ipfs-blockstore v1.3.0 h1:m2EXaWgwTzAfsmt5UdJ7Is6l4gJcaM/A12XwJyvYvMM=
|
||||
github.com/ipfs/go-ipfs-blockstore v1.3.0/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE=
|
||||
github.com/ipfs/go-ipfs-delay v0.0.0-20181109222059-70721b86a9a8/go.mod h1:8SP1YXK1M1kXuc4KJZINY3TQQ03J2rwBG9QfXmbRPrw=
|
||||
github.com/ipfs/go-ipfs-ds-help v1.1.0 h1:yLE2w9RAsl31LtfMt91tRZcrx+e61O5mDxFRR994w4Q=
|
||||
github.com/ipfs/go-ipfs-ds-help v1.1.0/go.mod h1:YR5+6EaebOhfcqVCyqemItCLthrpVNot+rsOU/5IatU=
|
||||
github.com/ipfs/go-ipfs-util v0.0.1/go.mod h1:spsl5z8KUnrve+73pOhSVZND1SIxPW5RyBCNzQxlJBc=
|
||||
github.com/ipfs/go-ipfs-util v0.0.2 h1:59Sswnk1MFaiq+VcaknX7aYEyGyGDAA73ilhEK2POp8=
|
||||
github.com/ipfs/go-ipfs-util v0.0.2/go.mod h1:CbPtkWJzjLdEcezDns2XYaehFVNXG9zrdrtMecczcsQ=
|
||||
github.com/ipfs/go-ipld-cbor v0.0.7-0.20230126201833-a73d038d90bc h1:eUEo764smNy0EVRuMTSmirmuh552Mf2aBjfpDcLnDa8=
|
||||
github.com/ipfs/go-ipld-cbor v0.0.7-0.20230126201833-a73d038d90bc/go.mod h1:X7SgEIwC4COC5OWfcepZBWafO5kA1Rmt9ZsLLbhihQk=
|
||||
github.com/ipfs/go-ipld-format v0.4.0 h1:yqJSaJftjmjc9jEOFYlpkwOLVKv68OD27jFLlSghBlQ=
|
||||
github.com/ipfs/go-ipld-format v0.4.0/go.mod h1:co/SdBE8h99968X0hViiw1MNlh6fvxxnHpvVLnH7jSM=
|
||||
github.com/ipfs/go-ipfs-blockstore v1.3.1 h1:cEI9ci7V0sRNivqaOr0elDsamxXFxJMMMy7PTTDQNsQ=
|
||||
github.com/ipfs/go-ipfs-blockstore v1.3.1/go.mod h1:KgtZyc9fq+P2xJUiCAzbRdhhqJHvsw8u2Dlqy2MyRTE=
|
||||
github.com/ipfs/go-ipfs-ds-help v1.1.1 h1:B5UJOH52IbcfS56+Ul+sv8jnIV10lbjLF5eOO0C66Nw=
|
||||
github.com/ipfs/go-ipfs-ds-help v1.1.1/go.mod h1:75vrVCkSdSFidJscs8n4W+77AtTpCIAdDGAwjitJMIo=
|
||||
github.com/ipfs/go-ipfs-util v0.0.3 h1:2RFdGez6bu2ZlZdI+rWfIdbQb1KudQp3VGwPtdNCmE0=
|
||||
github.com/ipfs/go-ipfs-util v0.0.3/go.mod h1:LHzG1a0Ig4G+iZ26UUOMjHd+lfM84LZCrn17xAKWBvs=
|
||||
github.com/ipfs/go-ipld-cbor v0.1.0 h1:dx0nS0kILVivGhfWuB6dUpMa/LAwElHPw1yOGYopoYs=
|
||||
github.com/ipfs/go-ipld-cbor v0.1.0/go.mod h1:U2aYlmVrJr2wsUBU67K4KgepApSZddGRDWBYR0H4sCk=
|
||||
github.com/ipfs/go-ipld-format v0.6.0 h1:VEJlA2kQ3LqFSIm5Vu6eIlSxD/Ze90xtc4Meten1F5U=
|
||||
github.com/ipfs/go-ipld-format v0.6.0/go.mod h1:g4QVMTn3marU3qXchwjpKPKgJv+zF+OlaKMyhJ4LHPg=
|
||||
github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
|
||||
github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
|
||||
github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
|
||||
@@ -83,16 +84,16 @@ github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
|
||||
github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
|
||||
github.com/ipfs/go-metrics-interface v0.0.1 h1:j+cpbjYvu4R8zbleSs36gvB7jR+wsL2fGD6n0jO4kdg=
|
||||
github.com/ipfs/go-metrics-interface v0.0.1/go.mod h1:6s6euYU4zowdslK0GKHmqaIZ3j/b/tL7HTWtJ4VPgWY=
|
||||
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52 h1:QG4CGBqCeuBo6aZlGAamSkxWdgWfZGeE49eUOWJPA4c=
|
||||
github.com/ipsn/go-secp256k1 v0.0.0-20180726113642-9d62b9f0bc52/go.mod h1:fdg+/X9Gg4AsAIzWpEHwnqd+QY3b7lajxyjE1m4hkq4=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.3.0/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
|
||||
github.com/jackc/pgx/v5 v5.3.1 h1:Fcr8QJ1ZeLi5zsPZqQeUZhNhxfkkKBOgJuYkJHoBOtU=
|
||||
github.com/jackc/pgx/v5 v5.3.1/go.mod h1:t3JDKnCBlYIc0ewLF0Q7B8MXmoIaBOZj/ic7iHozM/8=
|
||||
github.com/jackc/pgx/v5 v5.5.0 h1:NxstgwndsTRy7eq9/kqYc/BZh5w2hHJV86wjvO+1xPw=
|
||||
github.com/jackc/pgx/v5 v5.5.0/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
|
||||
github.com/jackc/puddle/v2 v2.2.0/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
|
||||
github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jbenet/go-cienv v0.1.0/go.mod h1:TqNnHUmJgXau0nCzC7kXWeotg3J9W34CUv5Djy1+FlA=
|
||||
github.com/jbenet/goprocess v0.1.4 h1:DRGOFReOMqqDNXwW70QkacFW0YN9QnwLV0Vqk+3oU0o=
|
||||
github.com/jbenet/goprocess v0.1.4/go.mod h1:5yspPrukOVuOLORacaBi858NqyClJPQxYZlqdZVfqY4=
|
||||
@@ -106,25 +107,23 @@ 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.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
|
||||
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
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/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
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=
|
||||
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
|
||||
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
|
||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
||||
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/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=
|
||||
@@ -133,26 +132,25 @@ github.com/lestrrat-go/httprc v1.0.4 h1:bAZymwoZQb+Oq8MEbyipag7iSq6YIga8Wj6GOiJG
|
||||
github.com/lestrrat-go/httprc v1.0.4/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
|
||||
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
|
||||
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.9 h1:TRX4Q630UXxPVLvP5vGaqVJO7S+0PE6msRZUsFSBoC8=
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.9/go.mod h1:K68euYaR95FnL0hIQB8VvzL70vB7pSifbJUydCTPmgM=
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.12 h1:3d589+5w/b9b7S3DneICPW16AqTyYXB7VRjgluSDWeA=
|
||||
github.com/lestrrat-go/jwx/v2 v2.0.12/go.mod h1:Mq4KN1mM7bp+5z/W5HS8aCNs5RKZ911G/0y2qUjAQuQ=
|
||||
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.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
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-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.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
|
||||
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
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.18 h1:JL0eqdCOq6DJVNPSvArO/bIV9/P7fbGrV00LZHc+5aI=
|
||||
github.com/mattn/go-sqlite3 v1.14.18/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
||||
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/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
|
||||
github.com/minio/sha256-simd v0.0.0-20190131020904-2d45a736cd16/go.mod h1:2FMWW+8GMoPweT6+pI63m9YE3Lmw4J71hV56Chs1E/U=
|
||||
github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
|
||||
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
|
||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
|
||||
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/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mr-tron/base58 v1.1.0/go.mod h1:xcD2VGqlgYjBdcBLw+TuYLr8afG+Hj8g2eTVqeSzSU8=
|
||||
@@ -165,32 +163,39 @@ github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYg
|
||||
github.com/multiformats/go-base36 v0.1.0/go.mod h1:kFGE83c6s80PklsHO9sRn2NCoffoRdUUOENyW/Vv6sM=
|
||||
github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
|
||||
github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
|
||||
github.com/multiformats/go-multibase v0.0.1/go.mod h1:bja2MqRZ3ggyXtZSEDKpl0uO/gviWFaSteVbWT51qgs=
|
||||
github.com/multiformats/go-multibase v0.0.3/go.mod h1:5+1R4eQrT3PkYZ24C3W2Ue2tPwIdYQD509ZjSb5y9Oc=
|
||||
github.com/multiformats/go-multibase v0.2.0 h1:isdYCVLvksgWlMW9OZRYJEa9pZETFivncJHmHnnd87g=
|
||||
github.com/multiformats/go-multibase v0.2.0/go.mod h1:bFBZX4lKCA/2lyOFSAoKH5SS6oPyjtnzK/XTFDPkNuk=
|
||||
github.com/multiformats/go-multihash v0.0.1/go.mod h1:w/5tugSrLEbWqlcgJabL3oHFKTwfvkofsjW2Qa1ct4U=
|
||||
github.com/multiformats/go-multihash v0.0.13/go.mod h1:VdAWLKTwram9oKAatUcLxBNUjdtcVwxObEQBtRfuyjc=
|
||||
github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108=
|
||||
github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc=
|
||||
github.com/multiformats/go-multihash v0.2.3 h1:7Lyc8XfX/IY2jWb/gI7JP+o7JEq9hOa7BFvVU9RSh+U=
|
||||
github.com/multiformats/go-multihash v0.2.3/go.mod h1:dXgKXCXjBzdscBLk9JkjINiEsCKRVch90MdaGiKsvSM=
|
||||
github.com/multiformats/go-varint v0.0.5/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
|
||||
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/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/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
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/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
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=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||
github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/smartystreets/assertions v1.2.0 h1:42S6lae5dvLc7BrLu/0ugRtcFVjoJNMC/N3yZFZkDFs=
|
||||
github.com/smartystreets/assertions v1.2.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
@@ -209,39 +214,46 @@ 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.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/urfave/cli v1.22.10/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||
github.com/urfave/cli/v2 v2.25.3 h1:VJkt6wvEBOoSjPFQvOkv6iWIrsJyCrKGtCtxXWwmGeY=
|
||||
github.com/urfave/cli/v2 v2.25.3/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc=
|
||||
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=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0 h1:GDDkbFiaK8jsSDJfjId/PEGEShv6ugrt4kYsC5UIDaQ=
|
||||
github.com/warpfork/go-wish v0.0.0-20220906213052-39a1cc7a02d0/go.mod h1:x6AKhvSSexNrVSrViXSHUEbICjmGXhtgABaHIySUSGw=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20230418232409-daab9ece03a0 h1:XYEgH2nJgsrcrj32p+SAbx6T3s/6QknOXezXtz7kzbg=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20230418232409-daab9ece03a0/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
|
||||
github.com/whyrusleeping/go-did v0.0.0-20230301193428-2146016fc220 h1:EO/9z3yDvx1van1/0esdcqhalZZQGRj3I1BPTWr5k3A=
|
||||
github.com/whyrusleeping/go-did v0.0.0-20230301193428-2146016fc220/go.mod h1:qPtRyexGM5XMHFIfjH+EiA/A/1n2JakWEdMPC53pJAE=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20230923211252-36a87e1ba72f h1:SBuSxXJL0/ZJMtTxbXZgHZkThl9dNrzyaNhlyaqscRo=
|
||||
github.com/whyrusleeping/cbor-gen v0.0.0-20230923211252-36a87e1ba72f/go.mod h1:fgkXqYy7bV2cFeIEOkVTZS/WjXARfBqSH6Q2qHL33hQ=
|
||||
github.com/whyrusleeping/go-did v0.0.0-20230824162731-404d1707d5d6 h1:yJ9/LwIGIk/c0CdoavpC9RNSGSruIspSZtxG3Nnldic=
|
||||
github.com/whyrusleeping/go-did v0.0.0-20230824162731-404d1707d5d6/go.mod h1:39U9RRVr4CKbXpXYopWn+FSH5s+vWu6+RmguSPWAq5s=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
go.opentelemetry.io/otel v1.15.1 h1:3Iwq3lfRByPaws0f6bU3naAqOR1n5IeDWd9390kWHa8=
|
||||
go.opentelemetry.io/otel v1.15.1/go.mod h1:mHHGEHVDLal6YrKMmk9LqC4a3sF5g+fHfrttQIB1NTc=
|
||||
go.opentelemetry.io/otel/trace v1.15.1 h1:uXLo6iHJEzDfrNC0L0mNjItIp06SyaBQxu5t3xMlngY=
|
||||
go.opentelemetry.io/otel/trace v1.15.1/go.mod h1:IWdQG/5N1x7f6YUlmdLeJvH9yxtuJAfc4VW5Agv9r/8=
|
||||
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b h1:CzigHMRySiX3drau9C6Q5CAbNIApmLdat5jPMqChvDA=
|
||||
gitlab.com/yawning/secp256k1-voi v0.0.0-20230925100816-f2616030848b/go.mod h1:/y/V339mxv2sZmYYR64O07VuCpdNZqCTwO8ZcouTMI8=
|
||||
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02 h1:qwDnMxjkyLmAFgcfgTnfJrmYKWhHnci3GjDqcZp1M3Q=
|
||||
gitlab.com/yawning/tuplehash v0.0.0-20230713102510-df83abbf9a02/go.mod h1:JTnUj0mpYiAsuZLmKjTx/ex3AtMowcCgnE7YNyCEP0I=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0 h1:pginetY7+onl4qN1vl0xW/V/v6OBZ0vVdH+esuJgvmM=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.42.0/go.mod h1:XiYsayHc36K3EByOO6nbAXnAWbrUxdjUROCEeeROOH8=
|
||||
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
|
||||
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
|
||||
go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4=
|
||||
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
|
||||
go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc=
|
||||
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
|
||||
go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
|
||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
||||
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
|
||||
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
|
||||
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
@@ -249,9 +261,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
|
||||
go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
|
||||
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
|
||||
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
||||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
||||
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
|
||||
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
@@ -259,9 +270,9 @@ 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.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
|
||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
||||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||
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=
|
||||
@@ -278,17 +289,18 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
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.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
|
||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
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.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190219092855-153ac476189d/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=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -296,27 +308,29 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
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-20220704084225-05e143d24a9e/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.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
|
||||
golang.org/x/sys v0.7.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.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
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=
|
||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.11.0/go.mod h1:zC9APTIj3jG3FdV/Ons+XE1riIZXG4aZ4GTHiPZJPIU=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
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.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
||||
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
@@ -335,11 +349,13 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
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.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
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-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
@@ -351,11 +367,11 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U=
|
||||
gorm.io/driver/postgres v1.5.0/go.mod h1:FUZXzO+5Uqg5zzwzv4KK49R8lvGIyscBOqYrtI1Ce9A=
|
||||
gorm.io/driver/sqlite v1.5.0 h1:zKYbzRCpBrT1bNijRnxLDJWPjVfImGEn0lSnUY5gZ+c=
|
||||
gorm.io/driver/sqlite v1.5.0/go.mod h1:kDMDfntV9u/vuMmz8APHtHF0b4nyBB7sfCieC6G8k8I=
|
||||
gorm.io/driver/sqlite v1.5.4 h1:IqXwXi8M/ZlPzH/947tn5uik3aYQslP9BVveoax0nV0=
|
||||
gorm.io/driver/sqlite v1.5.4/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4=
|
||||
gorm.io/gorm v1.24.7-0.20230306060331-85eaf9eeda11/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.0 h1:+KtYtb2roDz14EQe4bla8CbQlmb9dN3VejSai3lprfU=
|
||||
gorm.io/gorm v1.25.0/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||
gorm.io/gorm v1.25.5 h1:zR9lOiiYf09VNh5Q1gphfyia1JpiClIWG9hQaxB/mls=
|
||||
gorm.io/gorm v1.25.5/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
|
||||
lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
|
||||
lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
|
||||
lukechampine.com/blake3 v1.2.1 h1:YuqqRuaqsGV71BV/nm9xlI0MKUv4QC54jQnBChWbGnI=
|
||||
lukechampine.com/blake3 v1.2.1/go.mod h1:0OFRp7fBtAylGVCO40o87sbupkyIGgbpv1+M1k1LM6k=
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
<meta property="og:title" content="Bluesky Social">
|
||||
<meta property="og:description" content="See what's next.">
|
||||
<meta property="og:image" content="/static/social-card-default.png">
|
||||
<meta property="og:site_name" content="Bluesky Social">
|
||||
<meta name="twitter:card" content="summary">
|
||||
<meta name="twitter:site" content="@bluesky">
|
||||
{%- endblock %}
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
|
||||
{% block html_head_extra -%}
|
||||
{%- if postView -%}
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:site_name" content="Bluesky Social">
|
||||
<meta property="og:type" content="article">
|
||||
<meta property="profile:username" content="{{ profileView.Handle }}">
|
||||
{%- if requestURI %}
|
||||
<meta property="og:url" content="{{ requestURI }}">
|
||||
{% endif -%}
|
||||
@@ -32,17 +33,20 @@
|
||||
<meta name="twitter:card" content="summary">
|
||||
{% endif %}
|
||||
<meta name="twitter:label1" content="Posted At">
|
||||
<meta name="twitter:value1" content="{{ postView.CreatedAt }}">
|
||||
<meta name="twitter:site" content="@bluesky">
|
||||
<meta name="twitter:value1" content="{{ postView.IndexedAt }}">
|
||||
<meta name="article:published_time" content="{{ postView.IndexedAt }}">
|
||||
{% endif -%}
|
||||
{%- endblock %}
|
||||
|
||||
{% block noscript_extra -%}
|
||||
{%- if postView -%}
|
||||
<div id="bsky_post_summary">
|
||||
<h3>Post</h3>
|
||||
<p id="bsky_display_name">{{ postView.Author.DisplayName }}</p>
|
||||
<p id="bsky_handle">{{ postView.Author.Handle }}</p>
|
||||
<p id="bsky_did">{{ postView.Author.Did }}</p>
|
||||
<p id="bsky_post_text">{{ postView.Record.Val.Text }}</p>
|
||||
<p id="bsky_post_indexedat">{{ postView.IndexedAt }}</p>
|
||||
</div>
|
||||
{% endif -%}
|
||||
{%- endblock %}
|
||||
|
||||
@@ -10,8 +10,9 @@
|
||||
|
||||
{% block html_head_extra -%}
|
||||
{%- if profileView -%}
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:site_name" content="Bluesky Social">
|
||||
<meta property="og:type" content="profile">
|
||||
<meta property="profile:username" content="{{ profileView.Handle }}">
|
||||
{%- if requestURI %}
|
||||
<meta property="og:url" content="{{ requestURI }}">
|
||||
{% endif -%}
|
||||
@@ -33,11 +34,12 @@
|
||||
{% endif %}
|
||||
<meta name="twitter:label1" content="Account DID">
|
||||
<meta name="twitter:value1" content="{{ profileView.Did }}">
|
||||
<meta name="twitter:site" content="@bluesky">
|
||||
<link rel="alternate" type="application/rss+xml" href="/profile/{{ profileView.Did }}/rss">
|
||||
{% endif -%}
|
||||
{%- endblock %}
|
||||
|
||||
{% block noscript_extra -%}
|
||||
{%- if profileView -%}
|
||||
<div id="bsky_profile_summary">
|
||||
<h3>Profile</h3>
|
||||
<p id="bsky_display_name">{{ profileView.DisplayName }}</p>
|
||||
@@ -45,4 +47,5 @@
|
||||
<p id="bsky_did">{{ profileView.Did }}</p>
|
||||
<p id="bsky_profile_description">{{ profileView.Description }}</p>
|
||||
</div>
|
||||
{% endif -%}
|
||||
{%- endblock %}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
- After initial setup:
|
||||
- Copy `google-services.json.example` to `google-services.json` or provide your own `google-services.json`. (A real firebase project is NOT required)
|
||||
- `npx expo prebuild` -> you will also need to run this anytime `app.json` or native `package.json` deps change
|
||||
- `yarn intl:build` -> you will also need to run this anytime `./src/locale/{locale}/messages.po` change
|
||||
- Start the dev servers
|
||||
- `git clone git@github.com:bluesky-social/atproto.git`
|
||||
- `cd atproto`
|
||||
|
||||
@@ -110,4 +110,10 @@ export function Welcome() {
|
||||
|
||||
return <div>{welcome}</div>;
|
||||
}
|
||||
```
|
||||
```
|
||||
|
||||
|
||||
### Credits
|
||||
Please check each individual `messages.po` file for the credits of the translators. We are very grateful for their help!
|
||||
|
||||
If you would like to translate the Bluesky app into your language, please open a PR or issue on this repo.
|
||||
@@ -78,7 +78,7 @@ export async function createServer(
|
||||
})
|
||||
|
||||
const pic = fs.readFileSync(
|
||||
path.join(__dirname, '..', 'assets', 'default-avatar.jpg'),
|
||||
path.join(__dirname, '..', 'assets', 'default-avatar.png'),
|
||||
)
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "bsky.app",
|
||||
"version": "1.59.0",
|
||||
"version": "1.60.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"prepare": "is-ci || husky install",
|
||||
@@ -35,7 +35,7 @@
|
||||
"intl:compile": "lingui compile"
|
||||
},
|
||||
"dependencies": {
|
||||
"@atproto/api": "^0.7.3",
|
||||
"@atproto/api": "^0.7.4",
|
||||
"@bam.tech/react-native-image-resizer": "^3.0.4",
|
||||
"@braintree/sanitize-url": "^6.0.2",
|
||||
"@emoji-mart/react": "^1.1.1",
|
||||
@@ -54,6 +54,7 @@
|
||||
"@react-native-clipboard/clipboard": "^1.10.0",
|
||||
"@react-native-community/blur": "^4.3.0",
|
||||
"@react-native-community/datetimepicker": "7.2.0",
|
||||
"@react-native-masked-view/masked-view": "^0.3.1",
|
||||
"@react-native-menu/menu": "^0.8.0",
|
||||
"@react-native-picker/picker": "2.4.10",
|
||||
"@react-navigation/bottom-tabs": "^6.5.7",
|
||||
|
||||
@@ -6,6 +6,10 @@ import {RootSiblingParent} from 'react-native-root-siblings'
|
||||
import * as SplashScreen from 'expo-splash-screen'
|
||||
import {GestureHandlerRootView} from 'react-native-gesture-handler'
|
||||
import {QueryClientProvider} from '@tanstack/react-query'
|
||||
import {
|
||||
SafeAreaProvider,
|
||||
initialWindowMetrics,
|
||||
} from 'react-native-safe-area-context'
|
||||
|
||||
import 'view/icons'
|
||||
|
||||
@@ -34,6 +38,7 @@ import {
|
||||
} from 'state/session'
|
||||
import {Provider as UnreadNotifsProvider} from 'state/queries/notifications/unread'
|
||||
import * as persisted from '#/state/persisted'
|
||||
import {Splash} from '#/Splash'
|
||||
|
||||
SplashScreen.preventAutoHideAsync()
|
||||
|
||||
@@ -53,27 +58,28 @@ function InnerApp() {
|
||||
resumeSession(account)
|
||||
}, [resumeSession])
|
||||
|
||||
// wait for session to resume
|
||||
if (isInitialLoad) return null
|
||||
|
||||
return (
|
||||
<React.Fragment
|
||||
// Resets the entire tree below when it changes:
|
||||
key={currentAccount?.did}>
|
||||
<LoggedOutViewProvider>
|
||||
<UnreadNotifsProvider>
|
||||
<ThemeProvider theme={colorMode}>
|
||||
{/* All components should be within this provider */}
|
||||
<RootSiblingParent>
|
||||
<GestureHandlerRootView style={s.h100pct}>
|
||||
<TestCtrls />
|
||||
<Shell />
|
||||
</GestureHandlerRootView>
|
||||
</RootSiblingParent>
|
||||
</ThemeProvider>
|
||||
</UnreadNotifsProvider>
|
||||
</LoggedOutViewProvider>
|
||||
</React.Fragment>
|
||||
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
|
||||
<Splash isReady={!isInitialLoad}>
|
||||
<React.Fragment
|
||||
// Resets the entire tree below when it changes:
|
||||
key={currentAccount?.did}>
|
||||
<LoggedOutViewProvider>
|
||||
<UnreadNotifsProvider>
|
||||
<ThemeProvider theme={colorMode}>
|
||||
{/* All components should be within this provider */}
|
||||
<RootSiblingParent>
|
||||
<GestureHandlerRootView style={s.h100pct}>
|
||||
<TestCtrls />
|
||||
<Shell />
|
||||
</GestureHandlerRootView>
|
||||
</RootSiblingParent>
|
||||
</ThemeProvider>
|
||||
</UnreadNotifsProvider>
|
||||
</LoggedOutViewProvider>
|
||||
</React.Fragment>
|
||||
</Splash>
|
||||
</SafeAreaProvider>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import * as React from 'react'
|
||||
import {StyleSheet} from 'react-native'
|
||||
import * as SplashScreen from 'expo-splash-screen'
|
||||
import {
|
||||
NavigationContainer,
|
||||
createNavigationContainerRef,
|
||||
@@ -182,7 +181,7 @@ function commonScreens(Stack: typeof HomeTab, unreadCountLabel?: string) {
|
||||
<Stack.Screen
|
||||
name="ProfileFeed"
|
||||
getComponent={() => ProfileFeedScreen}
|
||||
options={{title: title('Feed')}}
|
||||
options={{title: title('Feed'), requireAuth: true}}
|
||||
/>
|
||||
<Stack.Screen
|
||||
name="ProfileFeedLikedBy"
|
||||
@@ -293,7 +292,11 @@ function HomeTabNavigator() {
|
||||
animationDuration: 250,
|
||||
contentStyle,
|
||||
}}>
|
||||
<HomeTab.Screen name="Home" getComponent={() => HomeScreen} />
|
||||
<HomeTab.Screen
|
||||
name="Home"
|
||||
getComponent={() => HomeScreen}
|
||||
options={{requireAuth: true}}
|
||||
/>
|
||||
{commonScreens(HomeTab)}
|
||||
</HomeTab.Navigator>
|
||||
)
|
||||
@@ -327,7 +330,11 @@ function FeedsTabNavigator() {
|
||||
animationDuration: 250,
|
||||
contentStyle,
|
||||
}}>
|
||||
<FeedsTab.Screen name="Feeds" getComponent={() => FeedsScreen} />
|
||||
<FeedsTab.Screen
|
||||
name="Feeds"
|
||||
getComponent={() => FeedsScreen}
|
||||
options={{requireAuth: true}}
|
||||
/>
|
||||
{commonScreens(FeedsTab as typeof HomeTab)}
|
||||
</FeedsTab.Navigator>
|
||||
)
|
||||
@@ -399,7 +406,7 @@ const FlatNavigator = () => {
|
||||
<Flat.Screen
|
||||
name="Home"
|
||||
getComponent={() => HomeScreen}
|
||||
options={{title: title('Home')}}
|
||||
options={{title: title('Home'), requireAuth: true}}
|
||||
/>
|
||||
<Flat.Screen
|
||||
name="Search"
|
||||
@@ -409,7 +416,7 @@ const FlatNavigator = () => {
|
||||
<Flat.Screen
|
||||
name="Feeds"
|
||||
getComponent={() => FeedsScreen}
|
||||
options={{title: title('Feeds')}}
|
||||
options={{title: title('Feeds'), requireAuth: true}}
|
||||
/>
|
||||
<Flat.Screen
|
||||
name="Notifications"
|
||||
@@ -489,7 +496,6 @@ function RoutesContainer({children}: React.PropsWithChildren<{}>) {
|
||||
linking={LINKING}
|
||||
theme={theme}
|
||||
onReady={() => {
|
||||
SplashScreen.hideAsync()
|
||||
logModuleInitTime()
|
||||
onReady()
|
||||
}}>
|
||||
|
||||
@@ -0,0 +1,164 @@
|
||||
import React, {useCallback, useEffect} from 'react'
|
||||
import {View, StyleSheet, Image as RNImage} from 'react-native'
|
||||
import * as SplashScreen from 'expo-splash-screen'
|
||||
import {Image} from 'expo-image'
|
||||
import Animated, {
|
||||
interpolate,
|
||||
runOnJS,
|
||||
useAnimatedStyle,
|
||||
useSharedValue,
|
||||
withTiming,
|
||||
Easing,
|
||||
} from 'react-native-reanimated'
|
||||
import MaskedView from '@react-native-masked-view/masked-view'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
import Svg, {Path, SvgProps} from 'react-native-svg'
|
||||
|
||||
// @ts-ignore
|
||||
import splashImagePointer from '../assets/splash.png'
|
||||
const splashImageUri = RNImage.resolveAssetSource(splashImagePointer).uri
|
||||
|
||||
export const Logo = React.forwardRef(function LogoImpl(props: SvgProps, ref) {
|
||||
const width = 1000
|
||||
const height = width * (67 / 64)
|
||||
return (
|
||||
<Svg
|
||||
fill="none"
|
||||
// @ts-ignore it's fiiiiine
|
||||
ref={ref}
|
||||
viewBox="0 0 64 66"
|
||||
style={{width, height}}>
|
||||
<Path
|
||||
fill="#fff"
|
||||
d="M13.873 3.77C21.21 9.243 29.103 20.342 32 26.3v15.732c0-.335-.13.043-.41.858-1.512 4.414-7.418 21.642-20.923 7.87-7.111-7.252-3.819-14.503 9.125-16.692-7.405 1.252-15.73-.817-18.014-8.93C1.12 22.804 0 8.431 0 6.488 0-3.237 8.579-.18 13.873 3.77ZM50.127 3.77C42.79 9.243 34.897 20.342 32 26.3v15.732c0-.335.13.043.41.858 1.512 4.414 7.418 21.642 20.923 7.87 7.111-7.252 3.819-14.503-9.125-16.692 7.405 1.252 15.73-.817 18.014-8.93C62.88 22.804 64 8.431 64 6.488 64-3.237 55.422-.18 50.127 3.77Z"
|
||||
/>
|
||||
</Svg>
|
||||
)
|
||||
})
|
||||
|
||||
type Props = {
|
||||
isReady: boolean
|
||||
}
|
||||
|
||||
SplashScreen.preventAutoHideAsync().catch(() => {})
|
||||
|
||||
const AnimatedLogo = Animated.createAnimatedComponent(Logo)
|
||||
|
||||
export function Splash(props: React.PropsWithChildren<Props>) {
|
||||
const insets = useSafeAreaInsets()
|
||||
const intro = useSharedValue(0)
|
||||
const outroLogo = useSharedValue(0)
|
||||
const outroApp = useSharedValue(0)
|
||||
const [isAnimationComplete, setIsAnimationComplete] = React.useState(false)
|
||||
const [isImageLoaded, setIsImageLoaded] = React.useState(false)
|
||||
const isReady = props.isReady && isImageLoaded
|
||||
|
||||
const logoAnimations = useAnimatedStyle(() => {
|
||||
return {
|
||||
transform: [
|
||||
{
|
||||
scale: interpolate(intro.value, [0, 1], [0.8, 1], 'clamp'),
|
||||
},
|
||||
{
|
||||
scale: interpolate(
|
||||
outroLogo.value,
|
||||
[0, 0.06, 0.08, 1],
|
||||
[1, 0.8, 0.8, 400],
|
||||
'clamp',
|
||||
),
|
||||
},
|
||||
],
|
||||
opacity: interpolate(intro.value, [0, 1], [0, 1], 'clamp'),
|
||||
}
|
||||
})
|
||||
|
||||
const appAnimation = useAnimatedStyle(() => {
|
||||
return {
|
||||
transform: [
|
||||
{
|
||||
scale: interpolate(outroApp.value, [0, 1], [1.1, 1], 'clamp'),
|
||||
},
|
||||
],
|
||||
opacity: interpolate(outroApp.value, [0, 0.9, 1], [0, 1, 1], 'clamp'),
|
||||
}
|
||||
})
|
||||
|
||||
const onFinish = useCallback(() => setIsAnimationComplete(true), [])
|
||||
|
||||
useEffect(() => {
|
||||
if (isReady) {
|
||||
// hide on mount
|
||||
SplashScreen.hideAsync().catch(() => {})
|
||||
|
||||
intro.value = withTiming(
|
||||
1,
|
||||
{duration: 200, easing: Easing.out(Easing.cubic)},
|
||||
async () => {
|
||||
// set these values to check animation at specific point
|
||||
// outroLogo.value = 0.1
|
||||
// outroApp.value = 0.1
|
||||
outroLogo.value = withTiming(
|
||||
1,
|
||||
{duration: 1000, easing: Easing.in(Easing.cubic)},
|
||||
() => {
|
||||
runOnJS(onFinish)()
|
||||
},
|
||||
)
|
||||
outroApp.value = withTiming(
|
||||
1,
|
||||
{duration: 1000, easing: Easing.inOut(Easing.cubic)},
|
||||
() => {
|
||||
runOnJS(onFinish)()
|
||||
},
|
||||
)
|
||||
},
|
||||
)
|
||||
}
|
||||
}, [onFinish, intro, outroLogo, outroApp, isReady])
|
||||
|
||||
const onLoadEnd = useCallback(() => {
|
||||
setIsImageLoaded(true)
|
||||
}, [setIsImageLoaded])
|
||||
|
||||
return (
|
||||
<View style={{flex: 1}}>
|
||||
{!isAnimationComplete && (
|
||||
<Image
|
||||
accessibilityIgnoresInvertColors
|
||||
onLoadEnd={onLoadEnd}
|
||||
source={{uri: splashImageUri}}
|
||||
style={StyleSheet.absoluteFillObject}
|
||||
/>
|
||||
)}
|
||||
|
||||
<MaskedView
|
||||
style={[StyleSheet.absoluteFillObject]}
|
||||
maskElement={
|
||||
<Animated.View
|
||||
style={[
|
||||
StyleSheet.absoluteFillObject,
|
||||
{
|
||||
// Transparent background because mask is based off alpha channel.
|
||||
backgroundColor: 'transparent',
|
||||
flex: 1,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
transform: [{translateY: -(insets.top / 2)}, {scale: 0.1}], // scale from 1000px to 100px
|
||||
},
|
||||
]}>
|
||||
<AnimatedLogo style={[logoAnimations]} />
|
||||
</Animated.View>
|
||||
}>
|
||||
{!isAnimationComplete && (
|
||||
<View
|
||||
style={[StyleSheet.absoluteFillObject, {backgroundColor: 'white'}]}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Animated.View style={[{flex: 1}, appAnimation]}>
|
||||
{props.children}
|
||||
</Animated.View>
|
||||
</MaskedView>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
import React, {createContext, useContext, useMemo} from 'react'
|
||||
import {ScrollHandlers} from 'react-native-reanimated'
|
||||
|
||||
const ScrollContext = createContext<ScrollHandlers<any>>({
|
||||
onBeginDrag: undefined,
|
||||
onEndDrag: undefined,
|
||||
onScroll: undefined,
|
||||
})
|
||||
|
||||
export function useScrollHandlers(): ScrollHandlers<any> {
|
||||
return useContext(ScrollContext)
|
||||
}
|
||||
|
||||
type ProviderProps = {children: React.ReactNode} & ScrollHandlers<any>
|
||||
|
||||
// Note: this completely *overrides* the parent handlers.
|
||||
// It's up to you to compose them with the parent ones via useScrollHandlers() if needed.
|
||||
export function ScrollProvider({
|
||||
children,
|
||||
onBeginDrag,
|
||||
onEndDrag,
|
||||
onScroll,
|
||||
}: ProviderProps) {
|
||||
const handlers = useMemo(
|
||||
() => ({
|
||||
onBeginDrag,
|
||||
onEndDrag,
|
||||
onScroll,
|
||||
}),
|
||||
[onBeginDrag, onEndDrag, onScroll],
|
||||
)
|
||||
return (
|
||||
<ScrollContext.Provider value={handlers}>{children}</ScrollContext.Provider>
|
||||
)
|
||||
}
|
||||
@@ -104,12 +104,18 @@ export async function post(agent: BskyAgent, opts: PostOpts) {
|
||||
|
||||
// add image embed if present
|
||||
if (opts.images?.length) {
|
||||
logger.info(`Uploading images`, {
|
||||
count: opts.images.length,
|
||||
})
|
||||
|
||||
const images: AppBskyEmbedImages.Image[] = []
|
||||
for (const image of opts.images) {
|
||||
opts.onStateChange?.(`Uploading image #${images.length + 1}...`)
|
||||
logger.info(`Compressing image`)
|
||||
await image.compress()
|
||||
const path = image.compressed?.path ?? image.path
|
||||
const {width, height} = image.compressed || image
|
||||
logger.info(`Uploading image`)
|
||||
const res = await uploadBlob(agent, path, 'image/jpeg')
|
||||
images.push({
|
||||
image: res.data.blob,
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import {ImageRequireSource} from 'react-native'
|
||||
|
||||
export const DEF_AVATAR: ImageRequireSource = require('../../assets/default-avatar.jpg')
|
||||
export const TABS_EXPLAINER: ImageRequireSource = require('../../assets/tabs-explainer.jpg')
|
||||
export const CLOUD_SPLASH: ImageRequireSource = require('../../assets/cloud-splash.png')
|
||||
export const DEF_AVATAR: ImageRequireSource = require('../../assets/default-avatar.png')
|
||||
export const CLOUD_SPLASH: ImageRequireSource = require('../../assets/splash.png')
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import {ImageRequireSource} from 'react-native'
|
||||
|
||||
// @ts-ignore we need to pretend -prf
|
||||
export const DEF_AVATAR: ImageRequireSource = {uri: '/img/default-avatar.jpg'}
|
||||
export const DEF_AVATAR: ImageRequireSource = {uri: '/img/default-avatar.png'}
|
||||
// @ts-ignore we need to pretend -prf
|
||||
export const TABS_EXPLAINER: ImageRequireSource = {
|
||||
uri: '/img/tabs-explainer.jpg',
|
||||
}
|
||||
// @ts-ignore we need to pretend -prf
|
||||
export const CLOUD_SPLASH: ImageRequireSource = {uri: '/img/cloud-splash.png'}
|
||||
export const CLOUD_SPLASH: ImageRequireSource = {uri: '/img/splash.png'}
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
export const LOGIN_INCLUDE_DEV_SERVERS = true
|
||||
export const PWI_ENABLED = false
|
||||
export const PWI_ENABLED = true
|
||||
|
||||
@@ -47,7 +47,7 @@ msgstr ""
|
||||
msgid "{invitesAvailable} invite codes available"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:87
|
||||
#: src/view/screens/Search/Search.tsx:88
|
||||
msgid "{message}"
|
||||
msgstr ""
|
||||
|
||||
@@ -95,7 +95,7 @@ msgstr ""
|
||||
|
||||
#: src/view/com/modals/ListAddRemoveUsers.tsx:264
|
||||
#: src/view/com/modals/UserAddRemoveLists.tsx:193
|
||||
#: src/view/screens/ProfileList.tsx:783
|
||||
#: src/view/screens/ProfileList.tsx:754
|
||||
msgid "Add"
|
||||
msgstr ""
|
||||
|
||||
@@ -103,7 +103,7 @@ msgstr ""
|
||||
msgid "Add a content warning"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:773
|
||||
#: src/view/screens/ProfileList.tsx:744
|
||||
msgid "Add a user to this list"
|
||||
msgstr ""
|
||||
|
||||
@@ -126,11 +126,11 @@ msgstr ""
|
||||
msgid "Add details to report"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:432
|
||||
#: src/view/com/composer/Composer.tsx:438
|
||||
msgid "Add link card"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:435
|
||||
#: src/view/com/composer/Composer.tsx:441
|
||||
msgid "Add link card:"
|
||||
msgstr ""
|
||||
|
||||
@@ -142,7 +142,7 @@ msgstr ""
|
||||
msgid "Add to Lists"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:280
|
||||
#: src/view/screens/ProfileFeed.tsx:270
|
||||
msgid "Add to my feeds"
|
||||
msgstr ""
|
||||
|
||||
@@ -224,11 +224,11 @@ msgstr ""
|
||||
msgid "Are you sure you want to delete the app password \"{name}\"?"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:141
|
||||
#: src/view/com/composer/Composer.tsx:142
|
||||
msgid "Are you sure you'd like to discard this draft?"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:375
|
||||
#: src/view/screens/ProfileList.tsx:352
|
||||
msgid "Are you sure?"
|
||||
msgstr ""
|
||||
|
||||
@@ -250,9 +250,9 @@ msgstr ""
|
||||
#: src/view/com/auth/login/LoginForm.tsx:249
|
||||
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
|
||||
#: src/view/com/modals/report/InputIssueDetails.tsx:45
|
||||
#: src/view/com/post-thread/PostThread.tsx:392
|
||||
#: src/view/com/post-thread/PostThread.tsx:442
|
||||
#: src/view/com/post-thread/PostThread.tsx:450
|
||||
#: src/view/com/post-thread/PostThread.tsx:395
|
||||
#: src/view/com/post-thread/PostThread.tsx:445
|
||||
#: src/view/com/post-thread/PostThread.tsx:453
|
||||
#: src/view/com/profile/ProfileHeader.tsx:672
|
||||
msgid "Back"
|
||||
msgstr ""
|
||||
@@ -275,15 +275,15 @@ msgstr ""
|
||||
msgid "Block Account"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:545
|
||||
#: src/view/screens/ProfileList.tsx:522
|
||||
msgid "Block accounts"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:495
|
||||
#: src/view/screens/ProfileList.tsx:472
|
||||
msgid "Block list"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:330
|
||||
#: src/view/screens/ProfileList.tsx:307
|
||||
msgid "Block these accounts?"
|
||||
msgstr ""
|
||||
|
||||
@@ -303,15 +303,19 @@ msgstr ""
|
||||
msgid "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you. You will not see their content and they will be prevented from seeing yours."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:248
|
||||
#: src/view/com/post-thread/PostThread.tsx:251
|
||||
msgid "Blocked post."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:332
|
||||
#: src/view/screens/ProfileList.tsx:309
|
||||
msgid "Blocking is public. Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/SplashScreen.tsx:26
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:93
|
||||
msgid "Blog"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:31
|
||||
msgid "Bluesky"
|
||||
msgstr ""
|
||||
|
||||
@@ -343,6 +347,10 @@ msgstr ""
|
||||
msgid "Build version {0} {1}"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:87
|
||||
msgid "Business"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/photos/OpenCameraBtn.tsx:60
|
||||
#: src/view/com/util/UserAvatar.tsx:221
|
||||
#: src/view/com/util/UserBanner.tsx:38
|
||||
@@ -353,8 +361,8 @@ msgstr ""
|
||||
msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:279
|
||||
#: src/view/com/composer/Composer.tsx:282
|
||||
#: src/view/com/composer/Composer.tsx:285
|
||||
#: src/view/com/composer/Composer.tsx:288
|
||||
#: src/view/com/modals/AltImage.tsx:127
|
||||
#: src/view/com/modals/ChangeEmail.tsx:218
|
||||
#: src/view/com/modals/ChangeEmail.tsx:220
|
||||
@@ -368,7 +376,7 @@ msgstr ""
|
||||
#: src/view/com/modals/LinkWarning.tsx:85
|
||||
#: src/view/com/modals/Repost.tsx:73
|
||||
#: src/view/com/modals/Waitlist.tsx:136
|
||||
#: src/view/screens/Search/Search.tsx:558
|
||||
#: src/view/screens/Search/Search.tsx:592
|
||||
#: src/view/shell/desktop/Search.tsx:182
|
||||
msgid "Cancel"
|
||||
msgstr ""
|
||||
@@ -473,7 +481,7 @@ msgid "Clear all storage data (restart after this)"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/util/forms/SearchInput.tsx:73
|
||||
#: src/view/screens/Search/Search.tsx:543
|
||||
#: src/view/screens/Search/Search.tsx:577
|
||||
msgid "Clear search query"
|
||||
msgstr ""
|
||||
|
||||
@@ -551,7 +559,7 @@ msgstr ""
|
||||
msgid "Content Languages"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:69
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:78
|
||||
msgid "Content Warning"
|
||||
msgstr ""
|
||||
|
||||
@@ -573,7 +581,7 @@ msgstr ""
|
||||
msgid "Copy"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:407
|
||||
#: src/view/screens/ProfileList.tsx:384
|
||||
msgid "Copy link to list"
|
||||
msgstr ""
|
||||
|
||||
@@ -593,15 +601,16 @@ msgstr ""
|
||||
msgid "Copyright Policy"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:103
|
||||
#: src/view/screens/ProfileFeed.tsx:94
|
||||
msgid "Could not load feed"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:860
|
||||
#: src/view/screens/ProfileList.tsx:830
|
||||
msgid "Could not load list"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/SplashScreen.tsx:41
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:62
|
||||
#: src/view/com/auth/SplashScreen.tsx:46
|
||||
msgid "Create a new account"
|
||||
msgstr ""
|
||||
|
||||
@@ -609,7 +618,8 @@ msgstr ""
|
||||
msgid "Create Account"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/SplashScreen.tsx:38
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:54
|
||||
#: src/view/com/auth/SplashScreen.tsx:43
|
||||
msgid "Create new account"
|
||||
msgstr ""
|
||||
|
||||
@@ -643,8 +653,8 @@ msgstr ""
|
||||
msgid "Delete app password"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:374
|
||||
#: src/view/screens/ProfileList.tsx:434
|
||||
#: src/view/screens/ProfileList.tsx:351
|
||||
#: src/view/screens/ProfileList.tsx:411
|
||||
msgid "Delete List"
|
||||
msgstr ""
|
||||
|
||||
@@ -664,7 +674,7 @@ msgstr ""
|
||||
msgid "Delete this post?"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:240
|
||||
#: src/view/com/post-thread/PostThread.tsx:243
|
||||
msgid "Deleted post."
|
||||
msgstr ""
|
||||
|
||||
@@ -683,11 +693,11 @@ msgstr ""
|
||||
msgid "Developer Tools"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:142
|
||||
#: src/view/com/composer/Composer.tsx:143
|
||||
msgid "Discard"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:136
|
||||
#: src/view/com/composer/Composer.tsx:137
|
||||
msgid "Discard draft"
|
||||
msgstr ""
|
||||
|
||||
@@ -739,7 +749,7 @@ msgstr ""
|
||||
msgid "Edit image"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:422
|
||||
#: src/view/screens/ProfileList.tsx:399
|
||||
msgid "Edit list details"
|
||||
msgstr ""
|
||||
|
||||
@@ -787,7 +797,7 @@ msgstr ""
|
||||
msgid "Enable this setting to only see replies between people you follow."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Profile.tsx:471
|
||||
#: src/view/screens/Profile.tsx:425
|
||||
msgid "End of feed"
|
||||
msgstr ""
|
||||
|
||||
@@ -815,7 +825,7 @@ msgstr ""
|
||||
msgid "Enter your username and password"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:105
|
||||
#: src/view/screens/Search/Search.tsx:106
|
||||
msgid "Error:"
|
||||
msgstr ""
|
||||
|
||||
@@ -836,7 +846,7 @@ msgstr ""
|
||||
msgid "Feed offline"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/feeds/FeedPage.tsx:140
|
||||
#: src/view/com/feeds/FeedPage.tsx:143
|
||||
msgid "Feed Preferences"
|
||||
msgstr ""
|
||||
|
||||
@@ -847,8 +857,8 @@ msgstr ""
|
||||
|
||||
#: src/view/screens/Feeds.tsx:475
|
||||
#: src/view/screens/Profile.tsx:164
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:160
|
||||
#: src/view/shell/desktop/LeftNav.tsx:333
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:181
|
||||
#: src/view/shell/desktop/LeftNav.tsx:339
|
||||
#: src/view/shell/Drawer.tsx:455
|
||||
#: src/view/shell/Drawer.tsx:456
|
||||
msgid "Feeds"
|
||||
@@ -862,6 +872,14 @@ msgstr ""
|
||||
msgid "Feeds are custom algorithms that users build with a little coding expertise. <0/> for more information."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:422
|
||||
msgid "Find users on Bluesky"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:420
|
||||
msgid "Find users with the search tool on the right"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/onboarding/RecommendedFollowsItem.tsx:150
|
||||
msgid "Finding similar accounts..."
|
||||
msgstr ""
|
||||
@@ -940,17 +958,17 @@ msgstr ""
|
||||
msgid "Get Started"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/LoggedOut.tsx:68
|
||||
#: src/view/com/auth/LoggedOut.tsx:69
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:105
|
||||
#: src/view/com/auth/LoggedOut.tsx:70
|
||||
#: src/view/com/auth/LoggedOut.tsx:71
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:123
|
||||
#: src/view/shell/desktop/LeftNav.tsx:103
|
||||
msgid "Go back"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:112
|
||||
#: src/view/screens/ProfileFeed.tsx:117
|
||||
#: src/view/screens/ProfileList.tsx:869
|
||||
#: src/view/screens/ProfileList.tsx:874
|
||||
#: src/view/screens/ProfileFeed.tsx:103
|
||||
#: src/view/screens/ProfileFeed.tsx:108
|
||||
#: src/view/screens/ProfileList.tsx:839
|
||||
#: src/view/screens/ProfileList.tsx:844
|
||||
msgid "Go Back"
|
||||
msgstr ""
|
||||
|
||||
@@ -974,6 +992,7 @@ msgid "Here is your app password."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/notifications/FeedItem.tsx:316
|
||||
#: src/view/com/util/moderation/ContentHider.tsx:103
|
||||
msgid "Hide"
|
||||
msgstr ""
|
||||
|
||||
@@ -1009,14 +1028,14 @@ msgstr ""
|
||||
#~ msgid "Hmmm, we're having trouble finding this feed. It may have been deleted."
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:116
|
||||
#: src/view/shell/desktop/LeftNav.tsx:297
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:137
|
||||
#: src/view/shell/desktop/LeftNav.tsx:303
|
||||
#: src/view/shell/Drawer.tsx:379
|
||||
#: src/view/shell/Drawer.tsx:380
|
||||
msgid "Home"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:99
|
||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:96
|
||||
#: src/view/screens/PreferencesHomeFeed.tsx:95
|
||||
#: src/view/screens/Settings.tsx:481
|
||||
msgid "Home Feed Preferences"
|
||||
@@ -1082,6 +1101,10 @@ msgstr ""
|
||||
msgid "Invite codes: {invitesAvailable} available"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:99
|
||||
msgid "Jobs"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/modals/Waitlist.tsx:67
|
||||
msgid "Join the waitlist"
|
||||
msgstr ""
|
||||
@@ -1107,9 +1130,13 @@ msgstr ""
|
||||
msgid "Languages"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/util/moderation/ContentHider.tsx:101
|
||||
msgid "Learn more"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/util/moderation/PostAlerts.tsx:47
|
||||
#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:65
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:88
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:104
|
||||
msgid "Learn More"
|
||||
msgstr ""
|
||||
|
||||
@@ -1117,7 +1144,7 @@ msgstr ""
|
||||
#: src/view/com/util/moderation/PostAlerts.tsx:40
|
||||
#: src/view/com/util/moderation/PostHider.tsx:76
|
||||
#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:49
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:85
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:101
|
||||
msgid "Learn more about this warning"
|
||||
msgstr ""
|
||||
|
||||
@@ -1147,7 +1174,7 @@ msgstr ""
|
||||
#~ msgid "Light"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:643
|
||||
#: src/view/screens/ProfileFeed.tsx:577
|
||||
msgid "Like this feed"
|
||||
msgstr ""
|
||||
|
||||
@@ -1177,22 +1204,22 @@ msgid "List Name"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Profile.tsx:165
|
||||
#: src/view/shell/desktop/LeftNav.tsx:373
|
||||
#: src/view/shell/desktop/LeftNav.tsx:376
|
||||
#: src/view/shell/Drawer.tsx:471
|
||||
#: src/view/shell/Drawer.tsx:472
|
||||
msgid "Lists"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:257
|
||||
#: src/view/com/post-thread/PostThread.tsx:265
|
||||
#: src/view/com/post-thread/PostThread.tsx:260
|
||||
#: src/view/com/post-thread/PostThread.tsx:268
|
||||
msgid "Load more posts"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Notifications.tsx:141
|
||||
#: src/view/screens/Notifications.tsx:144
|
||||
msgid "Load new notifications"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/feeds/FeedPage.tsx:185
|
||||
#: src/view/com/feeds/FeedPage.tsx:189
|
||||
msgid "Load new posts"
|
||||
msgstr ""
|
||||
|
||||
@@ -1216,9 +1243,9 @@ msgstr ""
|
||||
msgid "Login to account that is not listed"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:482
|
||||
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
||||
msgstr ""
|
||||
#: src/view/screens/ProfileFeed.tsx:472
|
||||
#~ msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/view/com/modals/LinkWarning.tsx:63
|
||||
msgid "Make sure this is where you intend to go!"
|
||||
@@ -1236,18 +1263,17 @@ msgstr ""
|
||||
msgid "Mentioned users"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:503
|
||||
#: src/view/screens/Search/Search.tsx:537
|
||||
msgid "Menu"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/posts/FeedErrorMessage.tsx:194
|
||||
#: src/view/screens/ProfileFeed.tsx:490
|
||||
msgid "Message from server"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Moderation.tsx:64
|
||||
#: src/view/screens/Settings.tsx:563
|
||||
#: src/view/shell/desktop/LeftNav.tsx:391
|
||||
#: src/view/shell/desktop/LeftNav.tsx:394
|
||||
#: src/view/shell/Drawer.tsx:490
|
||||
#: src/view/shell/Drawer.tsx:491
|
||||
msgid "Moderation"
|
||||
@@ -1266,8 +1292,8 @@ msgid "More feeds"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/profile/ProfileHeader.tsx:548
|
||||
#: src/view/screens/ProfileFeed.tsx:370
|
||||
#: src/view/screens/ProfileList.tsx:606
|
||||
#: src/view/screens/ProfileFeed.tsx:360
|
||||
#: src/view/screens/ProfileList.tsx:583
|
||||
msgid "More options"
|
||||
msgstr ""
|
||||
|
||||
@@ -1279,15 +1305,15 @@ msgstr ""
|
||||
msgid "Mute Account"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:533
|
||||
#: src/view/screens/ProfileList.tsx:510
|
||||
msgid "Mute accounts"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:480
|
||||
#: src/view/screens/ProfileList.tsx:457
|
||||
msgid "Mute list"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:293
|
||||
#: src/view/screens/ProfileList.tsx:270
|
||||
msgid "Mute these accounts?"
|
||||
msgstr ""
|
||||
|
||||
@@ -1307,7 +1333,7 @@ msgstr ""
|
||||
msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:295
|
||||
#: src/view/screens/ProfileList.tsx:272
|
||||
msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them."
|
||||
msgstr ""
|
||||
|
||||
@@ -1345,12 +1371,12 @@ msgstr ""
|
||||
msgid "New"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/feeds/FeedPage.tsx:196
|
||||
#: src/view/com/feeds/FeedPage.tsx:200
|
||||
#: src/view/screens/Feeds.tsx:510
|
||||
#: src/view/screens/Profile.tsx:389
|
||||
#: src/view/screens/ProfileFeed.tsx:451
|
||||
#: src/view/screens/ProfileList.tsx:212
|
||||
#: src/view/screens/ProfileList.tsx:244
|
||||
#: src/view/screens/Profile.tsx:353
|
||||
#: src/view/screens/ProfileFeed.tsx:430
|
||||
#: src/view/screens/ProfileList.tsx:193
|
||||
#: src/view/screens/ProfileList.tsx:221
|
||||
#: src/view/shell/desktop/LeftNav.tsx:246
|
||||
msgid "New post"
|
||||
msgstr ""
|
||||
@@ -1379,8 +1405,8 @@ msgstr ""
|
||||
msgid "No"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:636
|
||||
#: src/view/screens/ProfileList.tsx:740
|
||||
#: src/view/screens/ProfileFeed.tsx:570
|
||||
#: src/view/screens/ProfileList.tsx:711
|
||||
msgid "No description"
|
||||
msgstr ""
|
||||
|
||||
@@ -1398,9 +1424,9 @@ msgstr ""
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/view/com/modals/ListAddRemoveUsers.tsx:127
|
||||
#: src/view/screens/Search/Search.tsx:270
|
||||
#: src/view/screens/Search/Search.tsx:298
|
||||
#: src/view/screens/Search/Search.tsx:581
|
||||
#: src/view/screens/Search/Search.tsx:271
|
||||
#: src/view/screens/Search/Search.tsx:299
|
||||
#: src/view/screens/Search/Search.tsx:615
|
||||
#: src/view/shell/desktop/Search.tsx:210
|
||||
msgid "No results found for {query}"
|
||||
msgstr ""
|
||||
@@ -1429,10 +1455,10 @@ msgstr ""
|
||||
#~ msgid "Note: Third-party apps that display Bluesky content may not respect this setting."
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/view/screens/Notifications.tsx:108
|
||||
#: src/view/screens/Notifications.tsx:132
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:187
|
||||
#: src/view/shell/desktop/LeftNav.tsx:355
|
||||
#: src/view/screens/Notifications.tsx:109
|
||||
#: src/view/screens/Notifications.tsx:133
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:205
|
||||
#: src/view/shell/desktop/LeftNav.tsx:358
|
||||
#: src/view/shell/Drawer.tsx:416
|
||||
#: src/view/shell/Drawer.tsx:417
|
||||
msgid "Notifications"
|
||||
@@ -1446,7 +1472,7 @@ msgstr ""
|
||||
msgid "Okay"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:348
|
||||
#: src/view/com/composer/Composer.tsx:354
|
||||
msgid "One or more images is missing alt text."
|
||||
msgstr ""
|
||||
|
||||
@@ -1454,7 +1480,7 @@ msgstr ""
|
||||
msgid "Only {0} can reply."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:79
|
||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:76
|
||||
msgid "Open navigation"
|
||||
msgstr ""
|
||||
|
||||
@@ -1569,13 +1595,13 @@ msgstr ""
|
||||
msgid "Please tell us why you think this decision was incorrect."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:331
|
||||
#: src/view/com/post-thread/PostThread.tsx:223
|
||||
#: src/view/screens/PostThread.tsx:78
|
||||
#: src/view/com/composer/Composer.tsx:337
|
||||
#: src/view/com/post-thread/PostThread.tsx:226
|
||||
#: src/view/screens/PostThread.tsx:80
|
||||
msgid "Post"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:382
|
||||
#: src/view/com/post-thread/PostThread.tsx:385
|
||||
msgid "Post hidden"
|
||||
msgstr ""
|
||||
|
||||
@@ -1587,7 +1613,7 @@ msgstr ""
|
||||
msgid "Post Languages"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:434
|
||||
#: src/view/com/post-thread/PostThread.tsx:437
|
||||
msgid "Post not found"
|
||||
msgstr ""
|
||||
|
||||
@@ -1623,7 +1649,8 @@ msgstr ""
|
||||
msgid "Processing..."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:229
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:247
|
||||
#: src/view/shell/desktop/LeftNav.tsx:412
|
||||
#: src/view/shell/Drawer.tsx:69
|
||||
#: src/view/shell/Drawer.tsx:525
|
||||
#: src/view/shell/Drawer.tsx:526
|
||||
@@ -1690,7 +1717,7 @@ msgstr ""
|
||||
|
||||
#: src/view/com/feeds/FeedSourceCard.tsx:105
|
||||
#: src/view/com/feeds/FeedSourceCard.tsx:172
|
||||
#: src/view/screens/ProfileFeed.tsx:280
|
||||
#: src/view/screens/ProfileFeed.tsx:270
|
||||
msgid "Remove from my feeds"
|
||||
msgstr ""
|
||||
|
||||
@@ -1735,11 +1762,11 @@ msgstr ""
|
||||
msgid "Report Account"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:300
|
||||
#: src/view/screens/ProfileFeed.tsx:290
|
||||
msgid "Report feed"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:448
|
||||
#: src/view/screens/ProfileList.tsx:425
|
||||
msgid "Report List"
|
||||
msgstr ""
|
||||
|
||||
@@ -1851,10 +1878,10 @@ msgstr ""
|
||||
|
||||
#: src/view/com/modals/ListAddRemoveUsers.tsx:75
|
||||
#: src/view/com/util/forms/SearchInput.tsx:64
|
||||
#: src/view/screens/Search/Search.tsx:381
|
||||
#: src/view/screens/Search/Search.tsx:533
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:138
|
||||
#: src/view/shell/desktop/LeftNav.tsx:315
|
||||
#: src/view/screens/Search/Search.tsx:401
|
||||
#: src/view/screens/Search/Search.tsx:567
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:159
|
||||
#: src/view/shell/desktop/LeftNav.tsx:321
|
||||
#: src/view/shell/desktop/Search.tsx:161
|
||||
#: src/view/shell/desktop/Search.tsx:170
|
||||
#: src/view/shell/Drawer.tsx:343
|
||||
@@ -1863,14 +1890,14 @@ msgid "Search"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:390
|
||||
msgid "Search for posts and users."
|
||||
msgstr ""
|
||||
#~ msgid "Search for posts and users."
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/view/com/modals/ChangeEmail.tsx:110
|
||||
msgid "Security Step Required"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/SplashScreen.tsx:29
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:39
|
||||
msgid "See what's next"
|
||||
msgstr ""
|
||||
|
||||
@@ -1944,7 +1971,7 @@ msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your f
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Settings.tsx:277
|
||||
#: src/view/shell/desktop/LeftNav.tsx:427
|
||||
#: src/view/shell/desktop/LeftNav.tsx:430
|
||||
#: src/view/shell/Drawer.tsx:546
|
||||
#: src/view/shell/Drawer.tsx:547
|
||||
msgid "Settings"
|
||||
@@ -1956,11 +1983,11 @@ msgstr ""
|
||||
|
||||
#: src/view/com/profile/ProfileHeader.tsx:338
|
||||
#: src/view/com/util/forms/PostDropdownBtn.tsx:129
|
||||
#: src/view/screens/ProfileList.tsx:407
|
||||
#: src/view/screens/ProfileList.tsx:384
|
||||
msgid "Share"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:312
|
||||
#: src/view/screens/ProfileFeed.tsx:302
|
||||
msgid "Share feed"
|
||||
msgstr ""
|
||||
|
||||
@@ -1968,11 +1995,12 @@ msgstr ""
|
||||
#~ msgid "Share link"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/view/com/util/moderation/ContentHider.tsx:105
|
||||
#: src/view/screens/Settings.tsx:316
|
||||
msgid "Show"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:114
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:132
|
||||
msgid "Show anyway"
|
||||
msgstr ""
|
||||
|
||||
@@ -2000,15 +2028,23 @@ msgstr ""
|
||||
msgid "Show users"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:70
|
||||
#: src/view/com/auth/login/Login.tsx:98
|
||||
#: src/view/com/auth/SplashScreen.tsx:49
|
||||
#: src/view/shell/NavSignupCard.tsx:52
|
||||
#: src/view/shell/NavSignupCard.tsx:53
|
||||
#: src/view/com/auth/SplashScreen.tsx:54
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:285
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:286
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:288
|
||||
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:177
|
||||
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:178
|
||||
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:180
|
||||
#: src/view/shell/NavSignupCard.tsx:58
|
||||
#: src/view/shell/NavSignupCard.tsx:59
|
||||
msgid "Sign in"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/SplashScreen.tsx:52
|
||||
#: src/view/com/auth/SplashScreen.web.tsx:84
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:78
|
||||
#: src/view/com/auth/SplashScreen.tsx:57
|
||||
#: src/view/com/auth/SplashScreen.web.tsx:87
|
||||
msgid "Sign In"
|
||||
msgstr ""
|
||||
|
||||
@@ -2030,16 +2066,26 @@ msgstr ""
|
||||
msgid "Sign out"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/shell/NavSignupCard.tsx:43
|
||||
#: src/view/shell/NavSignupCard.tsx:44
|
||||
#: src/view/shell/NavSignupCard.tsx:46
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:275
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:276
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:278
|
||||
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:167
|
||||
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:168
|
||||
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:170
|
||||
#: src/view/shell/NavSignupCard.tsx:49
|
||||
#: src/view/shell/NavSignupCard.tsx:50
|
||||
#: src/view/shell/NavSignupCard.tsx:52
|
||||
msgid "Sign up"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/shell/NavSignupCard.tsx:36
|
||||
#: src/view/shell/NavSignupCard.tsx:42
|
||||
msgid "Sign up or sign in to join the conversation"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:76
|
||||
msgid "Sign-in Required"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Settings.tsx:327
|
||||
msgid "Signed in as"
|
||||
msgstr ""
|
||||
@@ -2077,15 +2123,15 @@ msgstr ""
|
||||
msgid "Submit"
|
||||
msgstr "Submit"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:597
|
||||
#: src/view/screens/ProfileList.tsx:574
|
||||
msgid "Subscribe"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:593
|
||||
#: src/view/screens/ProfileList.tsx:570
|
||||
msgid "Subscribe to this list"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:354
|
||||
#: src/view/screens/Search/Search.tsx:357
|
||||
msgid "Suggested Follows"
|
||||
msgstr ""
|
||||
|
||||
@@ -2135,7 +2181,7 @@ msgstr ""
|
||||
msgid "The Copyright Policy has been moved to <0/>"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:437
|
||||
#: src/view/com/post-thread/PostThread.tsx:440
|
||||
msgid "The post may have been deleted."
|
||||
msgstr ""
|
||||
|
||||
@@ -2159,10 +2205,14 @@ msgstr ""
|
||||
msgid "This {0} has been labeled."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:72
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:88
|
||||
msgid "This {screenDescription} has been flagged:"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:83
|
||||
msgid "This account has requested that users sign in to view their profile."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/posts/FeedErrorMessage.tsx:107
|
||||
msgid "This content is not viewable without a Bluesky account."
|
||||
msgstr ""
|
||||
@@ -2222,11 +2272,11 @@ msgstr ""
|
||||
msgid "Try again"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:495
|
||||
#: src/view/screens/ProfileList.tsx:472
|
||||
msgid "Un-block list"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:480
|
||||
#: src/view/screens/ProfileList.tsx:457
|
||||
msgid "Un-mute list"
|
||||
msgstr ""
|
||||
|
||||
@@ -2262,7 +2312,7 @@ msgstr ""
|
||||
msgid "Unmute thread"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:463
|
||||
#: src/view/screens/ProfileList.tsx:440
|
||||
msgid "Unpin moderation list"
|
||||
msgstr ""
|
||||
|
||||
@@ -2311,7 +2361,7 @@ msgstr ""
|
||||
msgid "Username or email address"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:767
|
||||
#: src/view/screens/ProfileList.tsx:738
|
||||
msgid "Users"
|
||||
msgstr ""
|
||||
|
||||
@@ -2368,7 +2418,7 @@ msgstr ""
|
||||
#~ msgid "We're sorry, but this feed is currently receiving high traffic and is temporarily unavailable. Please try again later."
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:237
|
||||
#: src/view/screens/Search/Search.tsx:238
|
||||
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
||||
msgstr ""
|
||||
|
||||
@@ -2384,6 +2434,10 @@ msgstr ""
|
||||
msgid "What is the issue with this {collectionName}?"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/SplashScreen.tsx:34
|
||||
msgid "What's up?"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:78
|
||||
msgid "Which languages are used in this post?"
|
||||
msgstr ""
|
||||
@@ -2405,7 +2459,7 @@ msgstr ""
|
||||
msgid "Wide"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:403
|
||||
#: src/view/com/composer/Composer.tsx:409
|
||||
msgid "Write post"
|
||||
msgstr ""
|
||||
|
||||
@@ -2444,16 +2498,16 @@ msgstr ""
|
||||
msgid "You don't have any saved feeds."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:385
|
||||
#: src/view/com/post-thread/PostThread.tsx:388
|
||||
msgid "You have blocked the author or you have been blocked by the author."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/feeds/ProfileFeedgens.tsx:154
|
||||
#: src/view/com/feeds/ProfileFeedgens.tsx:141
|
||||
msgid "You have no feeds."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/lists/MyLists.tsx:89
|
||||
#: src/view/com/lists/ProfileLists.tsx:158
|
||||
#: src/view/com/lists/ProfileLists.tsx:145
|
||||
msgid "You have no lists."
|
||||
msgstr ""
|
||||
|
||||
|
||||
@@ -47,7 +47,7 @@ msgstr ""
|
||||
msgid "{invitesAvailable} invite codes available"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:87
|
||||
#: src/view/screens/Search/Search.tsx:88
|
||||
msgid "{message}"
|
||||
msgstr ""
|
||||
|
||||
@@ -95,7 +95,7 @@ msgstr "अकाउंट के विकल्प"
|
||||
|
||||
#: src/view/com/modals/ListAddRemoveUsers.tsx:264
|
||||
#: src/view/com/modals/UserAddRemoveLists.tsx:193
|
||||
#: src/view/screens/ProfileList.tsx:783
|
||||
#: src/view/screens/ProfileList.tsx:754
|
||||
msgid "Add"
|
||||
msgstr "ऐड करो"
|
||||
|
||||
@@ -103,7 +103,7 @@ msgstr "ऐड करो"
|
||||
msgid "Add a content warning"
|
||||
msgstr "सामग्री चेतावनी जोड़ें"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:773
|
||||
#: src/view/screens/ProfileList.tsx:744
|
||||
msgid "Add a user to this list"
|
||||
msgstr "इस सूची में किसी को जोड़ें"
|
||||
|
||||
@@ -126,11 +126,11 @@ msgstr "विवरण जोड़ें"
|
||||
msgid "Add details to report"
|
||||
msgstr "रिपोर्ट करने के लिए विवरण जोड़ें"
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:432
|
||||
#: src/view/com/composer/Composer.tsx:438
|
||||
msgid "Add link card"
|
||||
msgstr "लिंक कार्ड जोड़ें"
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:435
|
||||
#: src/view/com/composer/Composer.tsx:441
|
||||
msgid "Add link card:"
|
||||
msgstr "लिंक कार्ड जोड़ें:"
|
||||
|
||||
@@ -142,7 +142,7 @@ msgstr "अपने डोमेन में निम्नलिखित DN
|
||||
msgid "Add to Lists"
|
||||
msgstr "सूचियों में जोड़ें"
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:280
|
||||
#: src/view/screens/ProfileFeed.tsx:270
|
||||
msgid "Add to my feeds"
|
||||
msgstr "इस फ़ीड को सहेजें"
|
||||
|
||||
@@ -224,11 +224,11 @@ msgstr "दिखावट"
|
||||
msgid "Are you sure you want to delete the app password \"{name}\"?"
|
||||
msgstr "क्या आप वाकई ऐप पासवर्ड \"{name}\" हटाना चाहते हैं?"
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:141
|
||||
#: src/view/com/composer/Composer.tsx:142
|
||||
msgid "Are you sure you'd like to discard this draft?"
|
||||
msgstr "क्या आप वाकई इस ड्राफ्ट को हटाना करना चाहेंगे?"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:375
|
||||
#: src/view/screens/ProfileList.tsx:352
|
||||
msgid "Are you sure?"
|
||||
msgstr "क्या आप वास्तव में इसे करना चाहते हैं?"
|
||||
|
||||
@@ -250,9 +250,9 @@ msgstr "कलात्मक या गैर-कामुक नग्नत
|
||||
#: src/view/com/auth/login/LoginForm.tsx:249
|
||||
#: src/view/com/auth/login/SetNewPasswordForm.tsx:148
|
||||
#: src/view/com/modals/report/InputIssueDetails.tsx:45
|
||||
#: src/view/com/post-thread/PostThread.tsx:392
|
||||
#: src/view/com/post-thread/PostThread.tsx:442
|
||||
#: src/view/com/post-thread/PostThread.tsx:450
|
||||
#: src/view/com/post-thread/PostThread.tsx:395
|
||||
#: src/view/com/post-thread/PostThread.tsx:445
|
||||
#: src/view/com/post-thread/PostThread.tsx:453
|
||||
#: src/view/com/profile/ProfileHeader.tsx:672
|
||||
msgid "Back"
|
||||
msgstr "वापस"
|
||||
@@ -275,15 +275,15 @@ msgstr "जन्मदिन:"
|
||||
msgid "Block Account"
|
||||
msgstr "खाता ब्लॉक करें"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:545
|
||||
#: src/view/screens/ProfileList.tsx:522
|
||||
msgid "Block accounts"
|
||||
msgstr "खाता ब्लॉक करें"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:495
|
||||
#: src/view/screens/ProfileList.tsx:472
|
||||
msgid "Block list"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:330
|
||||
#: src/view/screens/ProfileList.tsx:307
|
||||
msgid "Block these accounts?"
|
||||
msgstr "खाता ब्लॉक करें?"
|
||||
|
||||
@@ -303,15 +303,19 @@ msgstr "अवरुद्ध खाते आपके थ्रेड्स
|
||||
msgid "Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you. You will not see their content and they will be prevented from seeing yours."
|
||||
msgstr "अवरुद्ध खाते आपके थ्रेड्स में उत्तर नहीं दे सकते, आपका उल्लेख नहीं कर सकते, या अन्यथा आपके साथ बातचीत नहीं कर सकते। आप उनकी सामग्री नहीं देख पाएंगे और उन्हें आपकी सामग्री देखने से रोका जाएगा।"
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:248
|
||||
#: src/view/com/post-thread/PostThread.tsx:251
|
||||
msgid "Blocked post."
|
||||
msgstr "ब्लॉक पोस्ट।"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:332
|
||||
#: src/view/screens/ProfileList.tsx:309
|
||||
msgid "Blocking is public. Blocked accounts cannot reply in your threads, mention you, or otherwise interact with you."
|
||||
msgstr "अवरोधन सार्वजनिक है. अवरुद्ध खाते आपके थ्रेड्स में उत्तर नहीं दे सकते, आपका उल्लेख नहीं कर सकते, या अन्यथा आपके साथ बातचीत नहीं कर सकते।"
|
||||
|
||||
#: src/view/com/auth/SplashScreen.tsx:26
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:93
|
||||
msgid "Blog"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:31
|
||||
msgid "Bluesky"
|
||||
msgstr "Bluesky"
|
||||
|
||||
@@ -343,6 +347,10 @@ msgstr "Bluesky.Social"
|
||||
msgid "Build version {0} {1}"
|
||||
msgstr "Build version {0} {1}"
|
||||
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:87
|
||||
msgid "Business"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/photos/OpenCameraBtn.tsx:60
|
||||
#: src/view/com/util/UserAvatar.tsx:221
|
||||
#: src/view/com/util/UserBanner.tsx:38
|
||||
@@ -353,8 +361,8 @@ msgstr "कैमरा"
|
||||
msgid "Can only contain letters, numbers, spaces, dashes, and underscores. Must be at least 4 characters long, but no more than 32 characters long."
|
||||
msgstr "केवल अक्षर, संख्या, रिक्त स्थान, डैश और अंडरस्कोर हो सकते हैं। कम से कम 4 अक्षर लंबा होना चाहिए, लेकिन 32 अक्षरों से अधिक लंबा नहीं होना चाहिए।।"
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:279
|
||||
#: src/view/com/composer/Composer.tsx:282
|
||||
#: src/view/com/composer/Composer.tsx:285
|
||||
#: src/view/com/composer/Composer.tsx:288
|
||||
#: src/view/com/modals/AltImage.tsx:127
|
||||
#: src/view/com/modals/ChangeEmail.tsx:218
|
||||
#: src/view/com/modals/ChangeEmail.tsx:220
|
||||
@@ -368,7 +376,7 @@ msgstr "केवल अक्षर, संख्या, रिक्त स्
|
||||
#: src/view/com/modals/LinkWarning.tsx:85
|
||||
#: src/view/com/modals/Repost.tsx:73
|
||||
#: src/view/com/modals/Waitlist.tsx:136
|
||||
#: src/view/screens/Search/Search.tsx:558
|
||||
#: src/view/screens/Search/Search.tsx:592
|
||||
#: src/view/shell/desktop/Search.tsx:182
|
||||
msgid "Cancel"
|
||||
msgstr "कैंसिल"
|
||||
@@ -469,7 +477,7 @@ msgid "Clear all storage data (restart after this)"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/util/forms/SearchInput.tsx:73
|
||||
#: src/view/screens/Search/Search.tsx:543
|
||||
#: src/view/screens/Search/Search.tsx:577
|
||||
msgid "Clear search query"
|
||||
msgstr "खोज क्वेरी साफ़ करें"
|
||||
|
||||
@@ -547,7 +555,7 @@ msgstr "सामग्री फ़िल्टरिंग"
|
||||
msgid "Content Languages"
|
||||
msgstr "सामग्री भाषा"
|
||||
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:69
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:78
|
||||
msgid "Content Warning"
|
||||
msgstr "सामग्री चेतावनी"
|
||||
|
||||
@@ -569,7 +577,7 @@ msgstr "कॉपी कर ली"
|
||||
msgid "Copy"
|
||||
msgstr "कॉपी"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:407
|
||||
#: src/view/screens/ProfileList.tsx:384
|
||||
msgid "Copy link to list"
|
||||
msgstr ""
|
||||
|
||||
@@ -589,15 +597,16 @@ msgstr "पोस्ट टेक्स्ट कॉपी करें"
|
||||
msgid "Copyright Policy"
|
||||
msgstr "कॉपीराइट नीति"
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:103
|
||||
#: src/view/screens/ProfileFeed.tsx:94
|
||||
msgid "Could not load feed"
|
||||
msgstr "फ़ीड लोड नहीं कर सकता"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:860
|
||||
#: src/view/screens/ProfileList.tsx:830
|
||||
msgid "Could not load list"
|
||||
msgstr "सूची लोड नहीं कर सकता"
|
||||
|
||||
#: src/view/com/auth/SplashScreen.tsx:41
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:62
|
||||
#: src/view/com/auth/SplashScreen.tsx:46
|
||||
msgid "Create a new account"
|
||||
msgstr "नया खाता बनाएं"
|
||||
|
||||
@@ -605,7 +614,8 @@ msgstr "नया खाता बनाएं"
|
||||
msgid "Create Account"
|
||||
msgstr "खाता बनाएँ"
|
||||
|
||||
#: src/view/com/auth/SplashScreen.tsx:38
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:54
|
||||
#: src/view/com/auth/SplashScreen.tsx:43
|
||||
msgid "Create new account"
|
||||
msgstr "नया खाता बनाएं"
|
||||
|
||||
@@ -639,8 +649,8 @@ msgstr "खाता हटाएं"
|
||||
msgid "Delete app password"
|
||||
msgstr "अप्प पासवर्ड हटाएं"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:374
|
||||
#: src/view/screens/ProfileList.tsx:434
|
||||
#: src/view/screens/ProfileList.tsx:351
|
||||
#: src/view/screens/ProfileList.tsx:411
|
||||
msgid "Delete List"
|
||||
msgstr "सूची हटाएँ"
|
||||
|
||||
@@ -660,7 +670,7 @@ msgstr "पोस्ट को हटाएं"
|
||||
msgid "Delete this post?"
|
||||
msgstr "इस पोस्ट को डीलीट करें?"
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:240
|
||||
#: src/view/com/post-thread/PostThread.tsx:243
|
||||
msgid "Deleted post."
|
||||
msgstr "यह पोस्ट मिटाई जा चुकी है"
|
||||
|
||||
@@ -679,11 +689,11 @@ msgstr "देव सर्वर"
|
||||
msgid "Developer Tools"
|
||||
msgstr "डेवलपर उपकरण"
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:142
|
||||
#: src/view/com/composer/Composer.tsx:143
|
||||
msgid "Discard"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:136
|
||||
#: src/view/com/composer/Composer.tsx:137
|
||||
msgid "Discard draft"
|
||||
msgstr "ड्राफ्ट हटाएं"
|
||||
|
||||
@@ -735,7 +745,7 @@ msgstr "प्रत्येक कोड एक बार काम करत
|
||||
msgid "Edit image"
|
||||
msgstr "छवि संपादित करें"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:422
|
||||
#: src/view/screens/ProfileList.tsx:399
|
||||
msgid "Edit list details"
|
||||
msgstr "सूची विवरण संपादित करें"
|
||||
|
||||
@@ -783,7 +793,7 @@ msgstr "ईमेल:"
|
||||
msgid "Enable this setting to only see replies between people you follow."
|
||||
msgstr "इस सेटिंग को केवल उन लोगों के बीच जवाब देखने में सक्षम करें जिन्हें आप फॉलो करते हैं।।"
|
||||
|
||||
#: src/view/screens/Profile.tsx:471
|
||||
#: src/view/screens/Profile.tsx:425
|
||||
msgid "End of feed"
|
||||
msgstr ""
|
||||
|
||||
@@ -811,7 +821,7 @@ msgstr "नीचे अपना नया ईमेल पता दर्ज
|
||||
msgid "Enter your username and password"
|
||||
msgstr "अपने यूज़रनेम और पासवर्ड दर्ज करें"
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:105
|
||||
#: src/view/screens/Search/Search.tsx:106
|
||||
msgid "Error:"
|
||||
msgstr ""
|
||||
|
||||
@@ -832,7 +842,7 @@ msgstr "अनुशंसित फ़ीड लोड करने में
|
||||
msgid "Feed offline"
|
||||
msgstr "फ़ीड ऑफ़लाइन है"
|
||||
|
||||
#: src/view/com/feeds/FeedPage.tsx:140
|
||||
#: src/view/com/feeds/FeedPage.tsx:143
|
||||
msgid "Feed Preferences"
|
||||
msgstr "फ़ीड प्राथमिकता"
|
||||
|
||||
@@ -843,8 +853,8 @@ msgstr "प्रतिक्रिया"
|
||||
|
||||
#: src/view/screens/Feeds.tsx:475
|
||||
#: src/view/screens/Profile.tsx:164
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:160
|
||||
#: src/view/shell/desktop/LeftNav.tsx:333
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:181
|
||||
#: src/view/shell/desktop/LeftNav.tsx:339
|
||||
#: src/view/shell/Drawer.tsx:455
|
||||
#: src/view/shell/Drawer.tsx:456
|
||||
msgid "Feeds"
|
||||
@@ -858,6 +868,14 @@ msgstr "सामग्री को व्यवस्थित करने
|
||||
msgid "Feeds are custom algorithms that users build with a little coding expertise. <0/> for more information."
|
||||
msgstr "फ़ीड कस्टम एल्गोरिदम हैं जिन्हें उपयोगकर्ता थोड़ी कोडिंग विशेषज्ञता के साथ बनाते हैं। <0/> अधिक जानकारी के लिए."
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:422
|
||||
msgid "Find users on Bluesky"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:420
|
||||
msgid "Find users with the search tool on the right"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/onboarding/RecommendedFollowsItem.tsx:150
|
||||
msgid "Finding similar accounts..."
|
||||
msgstr "मिलते-जुलते खाते ढूँढना"
|
||||
@@ -932,17 +950,17 @@ msgstr "गैलरी"
|
||||
msgid "Get Started"
|
||||
msgstr "प्रारंभ करें"
|
||||
|
||||
#: src/view/com/auth/LoggedOut.tsx:68
|
||||
#: src/view/com/auth/LoggedOut.tsx:69
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:105
|
||||
#: src/view/com/auth/LoggedOut.tsx:70
|
||||
#: src/view/com/auth/LoggedOut.tsx:71
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:123
|
||||
#: src/view/shell/desktop/LeftNav.tsx:103
|
||||
msgid "Go back"
|
||||
msgstr "वापस जाओ"
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:112
|
||||
#: src/view/screens/ProfileFeed.tsx:117
|
||||
#: src/view/screens/ProfileList.tsx:869
|
||||
#: src/view/screens/ProfileList.tsx:874
|
||||
#: src/view/screens/ProfileFeed.tsx:103
|
||||
#: src/view/screens/ProfileFeed.tsx:108
|
||||
#: src/view/screens/ProfileList.tsx:839
|
||||
#: src/view/screens/ProfileList.tsx:844
|
||||
msgid "Go Back"
|
||||
msgstr "वापस जाओ"
|
||||
|
||||
@@ -966,6 +984,7 @@ msgid "Here is your app password."
|
||||
msgstr "यहां आपका ऐप पासवर्ड है."
|
||||
|
||||
#: src/view/com/notifications/FeedItem.tsx:316
|
||||
#: src/view/com/util/moderation/ContentHider.tsx:103
|
||||
msgid "Hide"
|
||||
msgstr "इसे छिपाएं"
|
||||
|
||||
@@ -1001,14 +1020,14 @@ msgstr ""
|
||||
#~ msgid "Hmmm, we're having trouble finding this feed. It may have been deleted."
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:116
|
||||
#: src/view/shell/desktop/LeftNav.tsx:297
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:137
|
||||
#: src/view/shell/desktop/LeftNav.tsx:303
|
||||
#: src/view/shell/Drawer.tsx:379
|
||||
#: src/view/shell/Drawer.tsx:380
|
||||
msgid "Home"
|
||||
msgstr "होम फीड"
|
||||
|
||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:99
|
||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:96
|
||||
#: src/view/screens/PreferencesHomeFeed.tsx:95
|
||||
#: src/view/screens/Settings.tsx:481
|
||||
msgid "Home Feed Preferences"
|
||||
@@ -1074,6 +1093,10 @@ msgstr ""
|
||||
msgid "Invite codes: {invitesAvailable} available"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:99
|
||||
msgid "Jobs"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/modals/Waitlist.tsx:67
|
||||
msgid "Join the waitlist"
|
||||
msgstr "प्रतीक्षा सूची में शामिल हों"
|
||||
@@ -1099,9 +1122,13 @@ msgstr "भाषा सेटिंग्स"
|
||||
msgid "Languages"
|
||||
msgstr "भाषा"
|
||||
|
||||
#: src/view/com/util/moderation/ContentHider.tsx:101
|
||||
msgid "Learn more"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/util/moderation/PostAlerts.tsx:47
|
||||
#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:65
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:88
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:104
|
||||
msgid "Learn More"
|
||||
msgstr "अधिक जानें"
|
||||
|
||||
@@ -1109,7 +1136,7 @@ msgstr "अधिक जानें"
|
||||
#: src/view/com/util/moderation/PostAlerts.tsx:40
|
||||
#: src/view/com/util/moderation/PostHider.tsx:76
|
||||
#: src/view/com/util/moderation/ProfileHeaderAlerts.tsx:49
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:85
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:101
|
||||
msgid "Learn more about this warning"
|
||||
msgstr "इस चेतावनी के बारे में अधिक जानें"
|
||||
|
||||
@@ -1139,7 +1166,7 @@ msgstr "चित्र पुस्तकालय"
|
||||
#~ msgid "Light"
|
||||
#~ msgstr "लाइट मोड"
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:643
|
||||
#: src/view/screens/ProfileFeed.tsx:577
|
||||
msgid "Like this feed"
|
||||
msgstr "इस फ़ीड को लाइक करो"
|
||||
|
||||
@@ -1169,22 +1196,22 @@ msgid "List Name"
|
||||
msgstr "सूची का नाम"
|
||||
|
||||
#: src/view/screens/Profile.tsx:165
|
||||
#: src/view/shell/desktop/LeftNav.tsx:373
|
||||
#: src/view/shell/desktop/LeftNav.tsx:376
|
||||
#: src/view/shell/Drawer.tsx:471
|
||||
#: src/view/shell/Drawer.tsx:472
|
||||
msgid "Lists"
|
||||
msgstr "सूची"
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:257
|
||||
#: src/view/com/post-thread/PostThread.tsx:265
|
||||
#: src/view/com/post-thread/PostThread.tsx:260
|
||||
#: src/view/com/post-thread/PostThread.tsx:268
|
||||
msgid "Load more posts"
|
||||
msgstr "अधिक पोस्ट लोड करें"
|
||||
|
||||
#: src/view/screens/Notifications.tsx:141
|
||||
#: src/view/screens/Notifications.tsx:144
|
||||
msgid "Load new notifications"
|
||||
msgstr "नई सूचनाएं लोड करें"
|
||||
|
||||
#: src/view/com/feeds/FeedPage.tsx:185
|
||||
#: src/view/com/feeds/FeedPage.tsx:189
|
||||
msgid "Load new posts"
|
||||
msgstr "नई पोस्ट लोड करें"
|
||||
|
||||
@@ -1208,9 +1235,9 @@ msgstr ""
|
||||
msgid "Login to account that is not listed"
|
||||
msgstr "उस खाते में लॉग इन करें जो सूचीबद्ध नहीं है"
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:482
|
||||
msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
||||
msgstr ""
|
||||
#: src/view/screens/ProfileFeed.tsx:472
|
||||
#~ msgid "Looks like this feed is only available to users with a Bluesky account. Please sign up or sign in to view this feed!"
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/view/com/modals/LinkWarning.tsx:63
|
||||
msgid "Make sure this is where you intend to go!"
|
||||
@@ -1228,18 +1255,17 @@ msgstr ""
|
||||
msgid "Mentioned users"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:503
|
||||
#: src/view/screens/Search/Search.tsx:537
|
||||
msgid "Menu"
|
||||
msgstr "मेनू"
|
||||
|
||||
#: src/view/com/posts/FeedErrorMessage.tsx:194
|
||||
#: src/view/screens/ProfileFeed.tsx:490
|
||||
msgid "Message from server"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Moderation.tsx:64
|
||||
#: src/view/screens/Settings.tsx:563
|
||||
#: src/view/shell/desktop/LeftNav.tsx:391
|
||||
#: src/view/shell/desktop/LeftNav.tsx:394
|
||||
#: src/view/shell/Drawer.tsx:490
|
||||
#: src/view/shell/Drawer.tsx:491
|
||||
msgid "Moderation"
|
||||
@@ -1258,8 +1284,8 @@ msgid "More feeds"
|
||||
msgstr "अधिक फ़ीड"
|
||||
|
||||
#: src/view/com/profile/ProfileHeader.tsx:548
|
||||
#: src/view/screens/ProfileFeed.tsx:370
|
||||
#: src/view/screens/ProfileList.tsx:606
|
||||
#: src/view/screens/ProfileFeed.tsx:360
|
||||
#: src/view/screens/ProfileList.tsx:583
|
||||
msgid "More options"
|
||||
msgstr "अधिक विकल्प"
|
||||
|
||||
@@ -1271,15 +1297,15 @@ msgstr "अधिक विकल्प"
|
||||
msgid "Mute Account"
|
||||
msgstr "खाता म्यूट करें"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:533
|
||||
#: src/view/screens/ProfileList.tsx:510
|
||||
msgid "Mute accounts"
|
||||
msgstr "खातों को म्यूट करें"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:480
|
||||
#: src/view/screens/ProfileList.tsx:457
|
||||
msgid "Mute list"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:293
|
||||
#: src/view/screens/ProfileList.tsx:270
|
||||
msgid "Mute these accounts?"
|
||||
msgstr "इन खातों को म्यूट करें?"
|
||||
|
||||
@@ -1299,7 +1325,7 @@ msgstr "म्यूट किए गए खाते"
|
||||
msgid "Muted accounts have their posts removed from your feed and from your notifications. Mutes are completely private."
|
||||
msgstr "म्यूट किए गए खातों की पोस्ट आपके फ़ीड और आपकी सूचनाओं से हटा दी जाती हैं। म्यूट पूरी तरह से निजी हैं."
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:295
|
||||
#: src/view/screens/ProfileList.tsx:272
|
||||
msgid "Muting is private. Muted accounts can interact with you, but you will not see their posts or receive notifications from them."
|
||||
msgstr "म्यूट करना निजी है. म्यूट किए गए खाते आपके साथ इंटरैक्ट कर सकते हैं, लेकिन आप उनकी पोस्ट नहीं देखेंगे या उनसे सूचनाएं प्राप्त नहीं करेंगे।"
|
||||
|
||||
@@ -1337,12 +1363,12 @@ msgstr "अपने फ़ॉलोअर्स और डेटा तक प
|
||||
msgid "New"
|
||||
msgstr "नया"
|
||||
|
||||
#: src/view/com/feeds/FeedPage.tsx:196
|
||||
#: src/view/com/feeds/FeedPage.tsx:200
|
||||
#: src/view/screens/Feeds.tsx:510
|
||||
#: src/view/screens/Profile.tsx:389
|
||||
#: src/view/screens/ProfileFeed.tsx:451
|
||||
#: src/view/screens/ProfileList.tsx:212
|
||||
#: src/view/screens/ProfileList.tsx:244
|
||||
#: src/view/screens/Profile.tsx:353
|
||||
#: src/view/screens/ProfileFeed.tsx:430
|
||||
#: src/view/screens/ProfileList.tsx:193
|
||||
#: src/view/screens/ProfileList.tsx:221
|
||||
#: src/view/shell/desktop/LeftNav.tsx:246
|
||||
msgid "New post"
|
||||
msgstr "नई पोस्ट"
|
||||
@@ -1371,8 +1397,8 @@ msgstr "अगली फोटो"
|
||||
msgid "No"
|
||||
msgstr "नहीं"
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:636
|
||||
#: src/view/screens/ProfileList.tsx:740
|
||||
#: src/view/screens/ProfileFeed.tsx:570
|
||||
#: src/view/screens/ProfileList.tsx:711
|
||||
msgid "No description"
|
||||
msgstr "कोई विवरण नहीं"
|
||||
|
||||
@@ -1390,9 +1416,9 @@ msgstr "\"{query}\" के लिए कोई परिणाम नहीं
|
||||
#~ msgstr "{0} के लिए कोई परिणाम नहीं मिला"
|
||||
|
||||
#: src/view/com/modals/ListAddRemoveUsers.tsx:127
|
||||
#: src/view/screens/Search/Search.tsx:270
|
||||
#: src/view/screens/Search/Search.tsx:298
|
||||
#: src/view/screens/Search/Search.tsx:581
|
||||
#: src/view/screens/Search/Search.tsx:271
|
||||
#: src/view/screens/Search/Search.tsx:299
|
||||
#: src/view/screens/Search/Search.tsx:615
|
||||
#: src/view/shell/desktop/Search.tsx:210
|
||||
msgid "No results found for {query}"
|
||||
msgstr ""
|
||||
@@ -1421,10 +1447,10 @@ msgstr ""
|
||||
#~ msgid "Note: Third-party apps that display Bluesky content may not respect this setting."
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/view/screens/Notifications.tsx:108
|
||||
#: src/view/screens/Notifications.tsx:132
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:187
|
||||
#: src/view/shell/desktop/LeftNav.tsx:355
|
||||
#: src/view/screens/Notifications.tsx:109
|
||||
#: src/view/screens/Notifications.tsx:133
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:205
|
||||
#: src/view/shell/desktop/LeftNav.tsx:358
|
||||
#: src/view/shell/Drawer.tsx:416
|
||||
#: src/view/shell/Drawer.tsx:417
|
||||
msgid "Notifications"
|
||||
@@ -1438,7 +1464,7 @@ msgstr "अरे नहीं!"
|
||||
msgid "Okay"
|
||||
msgstr "ठीक है"
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:348
|
||||
#: src/view/com/composer/Composer.tsx:354
|
||||
msgid "One or more images is missing alt text."
|
||||
msgstr "एक या अधिक छवियाँ alt पाठ याद आती हैं।।"
|
||||
|
||||
@@ -1446,7 +1472,7 @@ msgstr "एक या अधिक छवियाँ alt पाठ याद
|
||||
msgid "Only {0} can reply."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:79
|
||||
#: src/view/com/pager/FeedsTabBarMobile.tsx:76
|
||||
msgid "Open navigation"
|
||||
msgstr "ओपन नेविगेशन"
|
||||
|
||||
@@ -1561,13 +1587,13 @@ msgstr "कृपया अपना पासवर्ड भी दर्ज
|
||||
msgid "Please tell us why you think this decision was incorrect."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:331
|
||||
#: src/view/com/post-thread/PostThread.tsx:223
|
||||
#: src/view/screens/PostThread.tsx:78
|
||||
#: src/view/com/composer/Composer.tsx:337
|
||||
#: src/view/com/post-thread/PostThread.tsx:226
|
||||
#: src/view/screens/PostThread.tsx:80
|
||||
msgid "Post"
|
||||
msgstr "पोस्ट"
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:382
|
||||
#: src/view/com/post-thread/PostThread.tsx:385
|
||||
msgid "Post hidden"
|
||||
msgstr "छुपा पोस्ट"
|
||||
|
||||
@@ -1579,7 +1605,7 @@ msgstr "पोस्ट भाषा"
|
||||
msgid "Post Languages"
|
||||
msgstr "पोस्ट भाषा"
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:434
|
||||
#: src/view/com/post-thread/PostThread.tsx:437
|
||||
msgid "Post not found"
|
||||
msgstr "पोस्ट नहीं मिला"
|
||||
|
||||
@@ -1615,7 +1641,8 @@ msgstr "गोपनीयता नीति"
|
||||
msgid "Processing..."
|
||||
msgstr "प्रसंस्करण..."
|
||||
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:229
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:247
|
||||
#: src/view/shell/desktop/LeftNav.tsx:412
|
||||
#: src/view/shell/Drawer.tsx:69
|
||||
#: src/view/shell/Drawer.tsx:525
|
||||
#: src/view/shell/Drawer.tsx:526
|
||||
@@ -1682,7 +1709,7 @@ msgstr "फ़ीड हटाएँ"
|
||||
|
||||
#: src/view/com/feeds/FeedSourceCard.tsx:105
|
||||
#: src/view/com/feeds/FeedSourceCard.tsx:172
|
||||
#: src/view/screens/ProfileFeed.tsx:280
|
||||
#: src/view/screens/ProfileFeed.tsx:270
|
||||
msgid "Remove from my feeds"
|
||||
msgstr "मेरे फ़ीड से हटाएँ"
|
||||
|
||||
@@ -1727,11 +1754,11 @@ msgstr "रिपोर्ट {collectionName}"
|
||||
msgid "Report Account"
|
||||
msgstr "रिपोर्ट"
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:300
|
||||
#: src/view/screens/ProfileFeed.tsx:290
|
||||
msgid "Report feed"
|
||||
msgstr "रिपोर्ट फ़ीड"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:448
|
||||
#: src/view/screens/ProfileList.tsx:425
|
||||
msgid "Report List"
|
||||
msgstr "रिपोर्ट सूची"
|
||||
|
||||
@@ -1843,10 +1870,10 @@ msgstr "सहेजे गए फ़ीड"
|
||||
|
||||
#: src/view/com/modals/ListAddRemoveUsers.tsx:75
|
||||
#: src/view/com/util/forms/SearchInput.tsx:64
|
||||
#: src/view/screens/Search/Search.tsx:381
|
||||
#: src/view/screens/Search/Search.tsx:533
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:138
|
||||
#: src/view/shell/desktop/LeftNav.tsx:315
|
||||
#: src/view/screens/Search/Search.tsx:401
|
||||
#: src/view/screens/Search/Search.tsx:567
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:159
|
||||
#: src/view/shell/desktop/LeftNav.tsx:321
|
||||
#: src/view/shell/desktop/Search.tsx:161
|
||||
#: src/view/shell/desktop/Search.tsx:170
|
||||
#: src/view/shell/Drawer.tsx:343
|
||||
@@ -1855,14 +1882,14 @@ msgid "Search"
|
||||
msgstr "खोज"
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:390
|
||||
msgid "Search for posts and users."
|
||||
msgstr ""
|
||||
#~ msgid "Search for posts and users."
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/view/com/modals/ChangeEmail.tsx:110
|
||||
msgid "Security Step Required"
|
||||
msgstr "सुरक्षा चरण आवश्यक"
|
||||
|
||||
#: src/view/com/auth/SplashScreen.tsx:29
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:39
|
||||
msgid "See what's next"
|
||||
msgstr "आगे क्या है"
|
||||
|
||||
@@ -1936,7 +1963,7 @@ msgid "Set this setting to \"Yes\" to show samples of your saved feeds in your f
|
||||
msgstr "इस सेटिंग को अपने निम्नलिखित फ़ीड में अपने सहेजे गए फ़ीड के नमूने दिखाने के लिए \"हाँ\" पर सेट करें। यह एक प्रयोगात्मक विशेषता है।।"
|
||||
|
||||
#: src/view/screens/Settings.tsx:277
|
||||
#: src/view/shell/desktop/LeftNav.tsx:427
|
||||
#: src/view/shell/desktop/LeftNav.tsx:430
|
||||
#: src/view/shell/Drawer.tsx:546
|
||||
#: src/view/shell/Drawer.tsx:547
|
||||
msgid "Settings"
|
||||
@@ -1948,11 +1975,11 @@ msgstr "यौन गतिविधि या कामुक नग्नत
|
||||
|
||||
#: src/view/com/profile/ProfileHeader.tsx:338
|
||||
#: src/view/com/util/forms/PostDropdownBtn.tsx:129
|
||||
#: src/view/screens/ProfileList.tsx:407
|
||||
#: src/view/screens/ProfileList.tsx:384
|
||||
msgid "Share"
|
||||
msgstr "शेयर"
|
||||
|
||||
#: src/view/screens/ProfileFeed.tsx:312
|
||||
#: src/view/screens/ProfileFeed.tsx:302
|
||||
msgid "Share feed"
|
||||
msgstr ""
|
||||
|
||||
@@ -1960,11 +1987,12 @@ msgstr ""
|
||||
#~ msgid "Share link"
|
||||
#~ msgstr "लिंक शेयर करें"
|
||||
|
||||
#: src/view/com/util/moderation/ContentHider.tsx:105
|
||||
#: src/view/screens/Settings.tsx:316
|
||||
msgid "Show"
|
||||
msgstr "दिखाओ"
|
||||
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:114
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:132
|
||||
msgid "Show anyway"
|
||||
msgstr "दिखाओ"
|
||||
|
||||
@@ -1992,15 +2020,23 @@ msgstr "रीपोस्ट दिखाएँ"
|
||||
msgid "Show users"
|
||||
msgstr "लोग दिखाएँ"
|
||||
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:70
|
||||
#: src/view/com/auth/login/Login.tsx:98
|
||||
#: src/view/com/auth/SplashScreen.tsx:49
|
||||
#: src/view/shell/NavSignupCard.tsx:52
|
||||
#: src/view/shell/NavSignupCard.tsx:53
|
||||
#: src/view/com/auth/SplashScreen.tsx:54
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:285
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:286
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:288
|
||||
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:177
|
||||
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:178
|
||||
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:180
|
||||
#: src/view/shell/NavSignupCard.tsx:58
|
||||
#: src/view/shell/NavSignupCard.tsx:59
|
||||
msgid "Sign in"
|
||||
msgstr "साइन इन करें"
|
||||
|
||||
#: src/view/com/auth/SplashScreen.tsx:52
|
||||
#: src/view/com/auth/SplashScreen.web.tsx:84
|
||||
#: src/view/com/auth/HomeLoggedOutCTA.tsx:78
|
||||
#: src/view/com/auth/SplashScreen.tsx:57
|
||||
#: src/view/com/auth/SplashScreen.web.tsx:87
|
||||
msgid "Sign In"
|
||||
msgstr "साइन इन करें"
|
||||
|
||||
@@ -2022,16 +2058,26 @@ msgstr "साइन इन करें"
|
||||
msgid "Sign out"
|
||||
msgstr "साइन आउट"
|
||||
|
||||
#: src/view/shell/NavSignupCard.tsx:43
|
||||
#: src/view/shell/NavSignupCard.tsx:44
|
||||
#: src/view/shell/NavSignupCard.tsx:46
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:275
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:276
|
||||
#: src/view/shell/bottom-bar/BottomBar.tsx:278
|
||||
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:167
|
||||
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:168
|
||||
#: src/view/shell/bottom-bar/BottomBarWeb.tsx:170
|
||||
#: src/view/shell/NavSignupCard.tsx:49
|
||||
#: src/view/shell/NavSignupCard.tsx:50
|
||||
#: src/view/shell/NavSignupCard.tsx:52
|
||||
msgid "Sign up"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/shell/NavSignupCard.tsx:36
|
||||
#: src/view/shell/NavSignupCard.tsx:42
|
||||
msgid "Sign up or sign in to join the conversation"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:76
|
||||
msgid "Sign-in Required"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/Settings.tsx:327
|
||||
msgid "Signed in as"
|
||||
msgstr "आपने इस रूप में साइन इन करा है:"
|
||||
@@ -2069,15 +2115,15 @@ msgstr "Storybook"
|
||||
msgid "Submit"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:597
|
||||
#: src/view/screens/ProfileList.tsx:574
|
||||
msgid "Subscribe"
|
||||
msgstr "सब्सक्राइब"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:593
|
||||
#: src/view/screens/ProfileList.tsx:570
|
||||
msgid "Subscribe to this list"
|
||||
msgstr "इस सूची को सब्सक्राइब करें"
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:354
|
||||
#: src/view/screens/Search/Search.tsx:357
|
||||
msgid "Suggested Follows"
|
||||
msgstr "अनुशंसित लोग"
|
||||
|
||||
@@ -2127,7 +2173,7 @@ msgstr "सामुदायिक दिशानिर्देशों क
|
||||
msgid "The Copyright Policy has been moved to <0/>"
|
||||
msgstr "कॉपीराइट नीति को <0/> पर स्थानांतरित कर दिया गया है"
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:437
|
||||
#: src/view/com/post-thread/PostThread.tsx:440
|
||||
msgid "The post may have been deleted."
|
||||
msgstr "हो सकता है कि यह पोस्ट हटा दी गई हो।"
|
||||
|
||||
@@ -2151,10 +2197,14 @@ msgstr "एप्लिकेशन में एक अप्रत्याश
|
||||
msgid "This {0} has been labeled."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:72
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:88
|
||||
msgid "This {screenDescription} has been flagged:"
|
||||
msgstr "यह {screenDescription} फ्लैग किया गया है:"
|
||||
|
||||
#: src/view/com/util/moderation/ScreenHider.tsx:83
|
||||
msgid "This account has requested that users sign in to view their profile."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/posts/FeedErrorMessage.tsx:107
|
||||
msgid "This content is not viewable without a Bluesky account."
|
||||
msgstr ""
|
||||
@@ -2214,11 +2264,11 @@ msgstr "अनुवाद"
|
||||
msgid "Try again"
|
||||
msgstr "फिर से कोशिश करो"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:495
|
||||
#: src/view/screens/ProfileList.tsx:472
|
||||
msgid "Un-block list"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:480
|
||||
#: src/view/screens/ProfileList.tsx:457
|
||||
msgid "Un-mute list"
|
||||
msgstr ""
|
||||
|
||||
@@ -2254,7 +2304,7 @@ msgstr "अनम्यूट खाता"
|
||||
msgid "Unmute thread"
|
||||
msgstr "थ्रेड को अनम्यूट करें"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:463
|
||||
#: src/view/screens/ProfileList.tsx:440
|
||||
msgid "Unpin moderation list"
|
||||
msgstr ""
|
||||
|
||||
@@ -2303,7 +2353,7 @@ msgstr "लोग सूचियाँ"
|
||||
msgid "Username or email address"
|
||||
msgstr "यूजर नाम या ईमेल पता"
|
||||
|
||||
#: src/view/screens/ProfileList.tsx:767
|
||||
#: src/view/screens/ProfileList.tsx:738
|
||||
msgid "Users"
|
||||
msgstr "यूजर लोग"
|
||||
|
||||
@@ -2360,7 +2410,7 @@ msgstr "हम आपके हमारी सेवा में शामि
|
||||
#~ msgid "We're sorry, but this feed is currently receiving high traffic and is temporarily unavailable. Please try again later."
|
||||
#~ msgstr ""
|
||||
|
||||
#: src/view/screens/Search/Search.tsx:237
|
||||
#: src/view/screens/Search/Search.tsx:238
|
||||
msgid "We're sorry, but your search could not be completed. Please try again in a few minutes."
|
||||
msgstr ""
|
||||
|
||||
@@ -2376,6 +2426,10 @@ msgstr "<0>Bluesky</0> में आपका स्वागत है"
|
||||
msgid "What is the issue with this {collectionName}?"
|
||||
msgstr "इस {collectionName} के साथ क्या मुद्दा है?"
|
||||
|
||||
#: src/view/com/auth/SplashScreen.tsx:34
|
||||
msgid "What's up?"
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/modals/lang-settings/PostLanguagesSettings.tsx:78
|
||||
msgid "Which languages are used in this post?"
|
||||
msgstr "इस पोस्ट में किस भाषा का उपयोग किया जाता है?"
|
||||
@@ -2397,7 +2451,7 @@ msgstr ""
|
||||
msgid "Wide"
|
||||
msgstr "चौड़ा"
|
||||
|
||||
#: src/view/com/composer/Composer.tsx:403
|
||||
#: src/view/com/composer/Composer.tsx:409
|
||||
msgid "Write post"
|
||||
msgstr "पोस्ट लिखो"
|
||||
|
||||
@@ -2436,16 +2490,16 @@ msgstr ""
|
||||
msgid "You don't have any saved feeds."
|
||||
msgstr "आपके पास कोई सहेजी गई फ़ीड नहीं है."
|
||||
|
||||
#: src/view/com/post-thread/PostThread.tsx:385
|
||||
#: src/view/com/post-thread/PostThread.tsx:388
|
||||
msgid "You have blocked the author or you have been blocked by the author."
|
||||
msgstr "आपने लेखक को अवरुद्ध किया है या आपने लेखक द्वारा अवरुद्ध किया है।।"
|
||||
|
||||
#: src/view/com/feeds/ProfileFeedgens.tsx:154
|
||||
#: src/view/com/feeds/ProfileFeedgens.tsx:141
|
||||
msgid "You have no feeds."
|
||||
msgstr ""
|
||||
|
||||
#: src/view/com/lists/MyLists.tsx:89
|
||||
#: src/view/com/lists/ProfileLists.tsx:158
|
||||
#: src/view/com/lists/ProfileLists.tsx:145
|
||||
msgid "You have no lists."
|
||||
msgstr "आपके पास कोई सूची नहीं है।।"
|
||||
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
import React from 'react'
|
||||
import {AppBskyActorDefs} from '@atproto/api'
|
||||
import {AppBskyActorDefs, ModerationOpts, moderateProfile} from '@atproto/api'
|
||||
import {useQuery, useQueryClient} from '@tanstack/react-query'
|
||||
|
||||
import {logger} from '#/logger'
|
||||
import {getAgent} from '#/state/session'
|
||||
import {useMyFollowsQuery} from '#/state/queries/my-follows'
|
||||
import {STALE} from '#/state/queries'
|
||||
import {
|
||||
DEFAULT_LOGGED_OUT_PREFERENCES,
|
||||
getModerationOpts,
|
||||
useModerationOpts,
|
||||
} from './preferences'
|
||||
|
||||
const DEFAULT_MOD_OPTS = getModerationOpts({
|
||||
userDid: '',
|
||||
preferences: DEFAULT_LOGGED_OUT_PREFERENCES,
|
||||
})
|
||||
|
||||
export const RQKEY = (prefix: string) => ['actor-autocomplete', prefix]
|
||||
|
||||
export function useActorAutocompleteQuery(prefix: string) {
|
||||
const {data: follows, isFetching} = useMyFollowsQuery()
|
||||
const moderationOpts = useModerationOpts()
|
||||
|
||||
return useQuery<AppBskyActorDefs.ProfileViewBasic[]>({
|
||||
staleTime: STALE.MINUTES.ONE,
|
||||
@@ -22,9 +33,20 @@ export function useActorAutocompleteQuery(prefix: string) {
|
||||
limit: 8,
|
||||
})
|
||||
: undefined
|
||||
return computeSuggestions(prefix, follows, res?.data.actors)
|
||||
return res?.data.actors || []
|
||||
},
|
||||
enabled: !isFetching,
|
||||
select: React.useCallback(
|
||||
(data: AppBskyActorDefs.ProfileViewBasic[]) => {
|
||||
return computeSuggestions(
|
||||
prefix,
|
||||
follows,
|
||||
data,
|
||||
moderationOpts || DEFAULT_MOD_OPTS,
|
||||
)
|
||||
},
|
||||
[prefix, follows, moderationOpts],
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -32,6 +54,7 @@ export type ActorAutocompleteFn = ReturnType<typeof useActorAutocompleteFn>
|
||||
export function useActorAutocompleteFn() {
|
||||
const queryClient = useQueryClient()
|
||||
const {data: follows} = useMyFollowsQuery()
|
||||
const moderationOpts = useModerationOpts()
|
||||
|
||||
return React.useCallback(
|
||||
async ({query, limit = 8}: {query: string; limit?: number}) => {
|
||||
@@ -54,9 +77,14 @@ export function useActorAutocompleteFn() {
|
||||
}
|
||||
}
|
||||
|
||||
return computeSuggestions(query, follows, res?.data.actors)
|
||||
return computeSuggestions(
|
||||
query,
|
||||
follows,
|
||||
res?.data.actors,
|
||||
moderationOpts || DEFAULT_MOD_OPTS,
|
||||
)
|
||||
},
|
||||
[follows, queryClient],
|
||||
[follows, queryClient, moderationOpts],
|
||||
)
|
||||
}
|
||||
|
||||
@@ -64,6 +92,7 @@ function computeSuggestions(
|
||||
prefix: string,
|
||||
follows: AppBskyActorDefs.ProfileViewBasic[] | undefined,
|
||||
searched: AppBskyActorDefs.ProfileViewBasic[] = [],
|
||||
moderationOpts: ModerationOpts,
|
||||
) {
|
||||
let items: AppBskyActorDefs.ProfileViewBasic[] = []
|
||||
if (follows) {
|
||||
@@ -76,10 +105,14 @@ function computeSuggestions(
|
||||
handle: item.handle,
|
||||
displayName: item.displayName,
|
||||
avatar: item.avatar,
|
||||
labels: item.labels,
|
||||
})
|
||||
}
|
||||
}
|
||||
return items
|
||||
return items.filter(profile => {
|
||||
const mod = moderateProfile(profile, moderationOpts)
|
||||
return !mod.account.filter
|
||||
})
|
||||
}
|
||||
|
||||
function prefixMatch(
|
||||
|
||||
@@ -161,51 +161,6 @@ export function useFeedSourceInfoQuery({uri}: {uri: string}) {
|
||||
})
|
||||
}
|
||||
|
||||
export const isFeedPublicQueryKey = ({uri}: {uri: string}) => [
|
||||
'isFeedPublic',
|
||||
uri,
|
||||
]
|
||||
|
||||
export function useIsFeedPublicQuery({uri}: {uri: string}) {
|
||||
return useQuery({
|
||||
queryKey: isFeedPublicQueryKey({uri}),
|
||||
queryFn: async ({queryKey}) => {
|
||||
const [, uri] = queryKey
|
||||
try {
|
||||
const res = await getAgent().app.bsky.feed.getFeed({
|
||||
feed: uri,
|
||||
limit: 1,
|
||||
})
|
||||
return {
|
||||
isPublic: Boolean(res.data.feed),
|
||||
error: undefined,
|
||||
}
|
||||
} catch (e: any) {
|
||||
/**
|
||||
* This should be an `XRPCError`, but I can't safely import from
|
||||
* `@atproto/xrpc` due to a depdency on node's `crypto` module.
|
||||
*
|
||||
* @see https://github.com/bluesky-social/atproto/blob/c17971a2d8e424cc7f10c071d97c07c08aa319cf/packages/xrpc/src/client.ts#L126
|
||||
*/
|
||||
if (e?.status === 401) {
|
||||
return {
|
||||
isPublic: false,
|
||||
error: e,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Non-401 response means something else went wrong on the server
|
||||
*/
|
||||
return {
|
||||
isPublic: true,
|
||||
error: e,
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export const useGetPopularFeedsQueryKey = ['getPopularFeeds']
|
||||
|
||||
export function useGetPopularFeedsQuery() {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* 3. Don't call this query's `refetch()` if you're trying to sync latest; call `checkUnread()` instead.
|
||||
*/
|
||||
|
||||
import {useEffect} from 'react'
|
||||
import {useEffect, useRef} from 'react'
|
||||
import {AppBskyFeedDefs} from '@atproto/api'
|
||||
import {
|
||||
useInfiniteQuery,
|
||||
@@ -49,6 +49,7 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
|
||||
const threadMutes = useMutedThreads()
|
||||
const unreads = useUnreadNotificationsApi()
|
||||
const enabled = opts?.enabled !== false
|
||||
const lastPageCountRef = useRef(0)
|
||||
|
||||
const query = useInfiniteQuery<
|
||||
FeedPage,
|
||||
@@ -104,24 +105,26 @@ export function useNotificationFeedQuery(opts?: {enabled?: boolean}) {
|
||||
|
||||
useEffect(() => {
|
||||
const {isFetching, hasNextPage, data} = query
|
||||
|
||||
let count = 0
|
||||
let numEmpties = 0
|
||||
for (const page of data?.pages || []) {
|
||||
if (!page.items.length) {
|
||||
numEmpties++
|
||||
}
|
||||
count += page.items.length
|
||||
if (isFetching || !hasNextPage) {
|
||||
return
|
||||
}
|
||||
|
||||
// avoid double-fires of fetchNextPage()
|
||||
if (
|
||||
!isFetching &&
|
||||
hasNextPage &&
|
||||
count < PAGE_SIZE &&
|
||||
numEmpties < 3 &&
|
||||
(data?.pages.length || 0) < 6
|
||||
lastPageCountRef.current !== 0 &&
|
||||
lastPageCountRef.current === data?.pages?.length
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
// fetch next page if we haven't gotten a full page of content
|
||||
let count = 0
|
||||
for (const page of data?.pages || []) {
|
||||
count += page.items.length
|
||||
}
|
||||
if (count < PAGE_SIZE && (data?.pages.length || 0) < 6) {
|
||||
query.fetchNextPage()
|
||||
lastPageCountRef.current = data?.pages?.length || 0
|
||||
}
|
||||
}, [query])
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {useCallback, useEffect} from 'react'
|
||||
import React, {useCallback, useEffect, useRef} from 'react'
|
||||
import {
|
||||
AppBskyFeedDefs,
|
||||
AppBskyFeedPost,
|
||||
@@ -78,6 +78,7 @@ export interface FeedPageUnselected {
|
||||
api: FeedAPI
|
||||
cursor: string | undefined
|
||||
feed: AppBskyFeedDefs.FeedViewPost[]
|
||||
fetchedAt: number
|
||||
}
|
||||
|
||||
export interface FeedPage {
|
||||
@@ -85,6 +86,7 @@ export interface FeedPage {
|
||||
tuner: FeedTuner | NoopFeedTuner
|
||||
cursor: string | undefined
|
||||
slices: FeedPostSlice[]
|
||||
fetchedAt: number
|
||||
}
|
||||
|
||||
const PAGE_SIZE = 30
|
||||
@@ -98,11 +100,12 @@ export function usePostFeedQuery(
|
||||
const feedTuners = useFeedTuners(feedDesc)
|
||||
const moderationOpts = useModerationOpts()
|
||||
const enabled = opts?.enabled !== false && Boolean(moderationOpts)
|
||||
const lastRun = React.useRef<{
|
||||
const lastRun = useRef<{
|
||||
data: InfiniteData<FeedPageUnselected>
|
||||
args: typeof selectArgs
|
||||
result: InfiniteData<FeedPage>
|
||||
} | null>(null)
|
||||
const lastPageCountRef = useRef(0)
|
||||
|
||||
// Make sure this doesn't invalidate unless really needed.
|
||||
const selectArgs = React.useMemo(
|
||||
@@ -152,6 +155,7 @@ export function usePostFeedQuery(
|
||||
api,
|
||||
cursor: res.cursor,
|
||||
feed: res.feed,
|
||||
fetchedAt: Date.now(),
|
||||
}
|
||||
},
|
||||
initialPageParam: undefined,
|
||||
@@ -214,6 +218,7 @@ export function usePostFeedQuery(
|
||||
api: page.api,
|
||||
tuner,
|
||||
cursor: page.cursor,
|
||||
fetchedAt: page.fetchedAt,
|
||||
slices: tuner
|
||||
.tune(page.feed)
|
||||
.map(slice => {
|
||||
@@ -279,26 +284,28 @@ export function usePostFeedQuery(
|
||||
|
||||
useEffect(() => {
|
||||
const {isFetching, hasNextPage, data} = query
|
||||
if (isFetching || !hasNextPage) {
|
||||
return
|
||||
}
|
||||
|
||||
// avoid double-fires of fetchNextPage()
|
||||
if (
|
||||
lastPageCountRef.current !== 0 &&
|
||||
lastPageCountRef.current === data?.pages?.length
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
// fetch next page if we haven't gotten a full page of content
|
||||
let count = 0
|
||||
let numEmpties = 0
|
||||
for (const page of data?.pages || []) {
|
||||
if (page.slices.length === 0) {
|
||||
numEmpties++
|
||||
}
|
||||
for (const slice of page.slices) {
|
||||
count += slice.items.length
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
!isFetching &&
|
||||
hasNextPage &&
|
||||
count < PAGE_SIZE &&
|
||||
numEmpties < 3 &&
|
||||
(data?.pages.length || 0) < 6
|
||||
) {
|
||||
if (count < PAGE_SIZE && (data?.pages.length || 0) < 6) {
|
||||
query.fetchNextPage()
|
||||
lastPageCountRef.current = data?.pages?.length || 0
|
||||
}
|
||||
}, [query])
|
||||
|
||||
@@ -409,6 +416,9 @@ export function* findAllPostsInQueryData(
|
||||
}
|
||||
|
||||
function assertSomePostsPassModeration(feed: AppBskyFeedDefs.FeedViewPost[]) {
|
||||
// no posts in this feed
|
||||
if (feed.length === 0) return true
|
||||
|
||||
// assume false
|
||||
let somePostsPassModeration = false
|
||||
|
||||
|
||||
@@ -35,9 +35,7 @@ export function useProfileQuery({did}: {did: string | undefined}) {
|
||||
// if you remove it, the UI infinite-loops
|
||||
// -prf
|
||||
staleTime: isCurrentAccount ? STALE.SECONDS.THIRTY : STALE.MINUTES.FIVE,
|
||||
refetchInterval: isCurrentAccount
|
||||
? STALE.SECONDS.THIRTY
|
||||
: STALE.MINUTES.FIVE,
|
||||
refetchInterval: STALE.MINUTES.FIVE,
|
||||
queryKey: RQKEY(did || ''),
|
||||
queryFn: async () => {
|
||||
const res = await getAgent().getProfile({actor: did || ''})
|
||||
|
||||
@@ -22,7 +22,7 @@ type Controls = {
|
||||
/**
|
||||
* The did of the account to populate the login form with.
|
||||
*/
|
||||
requestedAccount?: string
|
||||
requestedAccount?: string | 'none' | 'new'
|
||||
}) => void
|
||||
/**
|
||||
* Clears the requested account so that next time the logged out view is
|
||||
|
||||
@@ -0,0 +1,165 @@
|
||||
import React from 'react'
|
||||
import {StyleSheet, TouchableOpacity, View} from 'react-native'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {ScrollView} from '../util/Views'
|
||||
import {Text} from '../util/text/Text'
|
||||
import {usePalette} from '#/lib/hooks/usePalette'
|
||||
import {colors, s} from '#/lib/styles'
|
||||
import {TextLink} from '../util/Link'
|
||||
import {useWebMediaQueries} from '#/lib/hooks/useWebMediaQueries'
|
||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||
|
||||
export function HomeLoggedOutCTA() {
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const {requestSwitchToAccount} = useLoggedOutViewControls()
|
||||
|
||||
const showCreateAccount = React.useCallback(() => {
|
||||
requestSwitchToAccount({requestedAccount: 'new'})
|
||||
}, [requestSwitchToAccount])
|
||||
|
||||
const showSignIn = React.useCallback(() => {
|
||||
requestSwitchToAccount({requestedAccount: 'none'})
|
||||
}, [requestSwitchToAccount])
|
||||
|
||||
return (
|
||||
<ScrollView style={styles.container} testID="loggedOutCTA">
|
||||
<View style={[styles.hero, isMobile && styles.heroMobile]}>
|
||||
<Text style={[styles.title, pal.link]}>
|
||||
<Trans>Bluesky</Trans>
|
||||
</Text>
|
||||
<Text
|
||||
style={[
|
||||
styles.subtitle,
|
||||
isMobile && styles.subtitleMobile,
|
||||
pal.textLight,
|
||||
]}>
|
||||
<Trans>See what's next</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
<View
|
||||
testID="signinOrCreateAccount"
|
||||
style={isMobile ? undefined : styles.btnsDesktop}>
|
||||
<TouchableOpacity
|
||||
testID="createAccountButton"
|
||||
style={[
|
||||
styles.btn,
|
||||
isMobile && styles.btnMobile,
|
||||
{backgroundColor: colors.blue3},
|
||||
]}
|
||||
onPress={showCreateAccount}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={_(msg`Create new account`)}
|
||||
accessibilityHint="Opens flow to create a new Bluesky account">
|
||||
<Text
|
||||
style={[
|
||||
s.white,
|
||||
styles.btnLabel,
|
||||
isMobile && styles.btnLabelMobile,
|
||||
]}>
|
||||
<Trans>Create a new account</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity
|
||||
testID="signInButton"
|
||||
style={[styles.btn, isMobile && styles.btnMobile, pal.btn]}
|
||||
onPress={showSignIn}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={_(msg`Sign in`)}
|
||||
accessibilityHint="Opens flow to sign into your existing Bluesky account">
|
||||
<Text
|
||||
style={[
|
||||
pal.text,
|
||||
styles.btnLabel,
|
||||
isMobile && styles.btnLabelMobile,
|
||||
]}>
|
||||
<Trans>Sign In</Trans>
|
||||
</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
|
||||
<View style={[styles.footer, pal.view, pal.border]}>
|
||||
<TextLink
|
||||
type="2xl"
|
||||
href="https://blueskyweb.xyz"
|
||||
text={_(msg`Business`)}
|
||||
style={[styles.footerLink, pal.link]}
|
||||
/>
|
||||
<TextLink
|
||||
type="2xl"
|
||||
href="https://blueskyweb.xyz/blog"
|
||||
text={_(msg`Blog`)}
|
||||
style={[styles.footerLink, pal.link]}
|
||||
/>
|
||||
<TextLink
|
||||
type="2xl"
|
||||
href="https://blueskyweb.xyz/join"
|
||||
text={_(msg`Jobs`)}
|
||||
style={[styles.footerLink, pal.link]}
|
||||
/>
|
||||
</View>
|
||||
</ScrollView>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
height: '100%',
|
||||
},
|
||||
hero: {
|
||||
justifyContent: 'center',
|
||||
paddingTop: 100,
|
||||
paddingBottom: 30,
|
||||
},
|
||||
heroMobile: {
|
||||
paddingBottom: 50,
|
||||
},
|
||||
title: {
|
||||
textAlign: 'center',
|
||||
fontSize: 68,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
subtitle: {
|
||||
textAlign: 'center',
|
||||
fontSize: 48,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
subtitleMobile: {
|
||||
fontSize: 42,
|
||||
},
|
||||
btnsDesktop: {
|
||||
flexDirection: 'row',
|
||||
justifyContent: 'center',
|
||||
gap: 20,
|
||||
marginHorizontal: 20,
|
||||
},
|
||||
btn: {
|
||||
borderRadius: 32,
|
||||
width: 230,
|
||||
paddingVertical: 12,
|
||||
marginBottom: 20,
|
||||
},
|
||||
btnMobile: {
|
||||
flex: 1,
|
||||
width: 'auto',
|
||||
marginHorizontal: 20,
|
||||
paddingVertical: 16,
|
||||
},
|
||||
btnLabel: {
|
||||
textAlign: 'center',
|
||||
fontSize: 18,
|
||||
},
|
||||
btnLabelMobile: {
|
||||
textAlign: 'center',
|
||||
fontSize: 21,
|
||||
},
|
||||
|
||||
footer: {
|
||||
flexDirection: 'row',
|
||||
gap: 20,
|
||||
justifyContent: 'center',
|
||||
},
|
||||
footerLink: {},
|
||||
})
|
||||
@@ -33,7 +33,9 @@ export function LoggedOut({onDismiss}: {onDismiss?: () => void}) {
|
||||
const {requestedAccountSwitchTo} = useLoggedOutView()
|
||||
const [screenState, setScreenState] = React.useState<ScreenState>(
|
||||
requestedAccountSwitchTo
|
||||
? ScreenState.S_Login
|
||||
? requestedAccountSwitchTo === 'new'
|
||||
? ScreenState.S_CreateAccount
|
||||
: ScreenState.S_Login
|
||||
: ScreenState.S_LoginOrCreateAccount,
|
||||
)
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
|
||||
@@ -7,6 +7,8 @@ import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {CenteredView} from '../util/Views'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
import {Logotype} from '#/view/icons/Logotype'
|
||||
|
||||
export const SplashScreen = ({
|
||||
onPressSignin,
|
||||
@@ -22,11 +24,14 @@ export const SplashScreen = ({
|
||||
<CenteredView style={[styles.container, pal.view]}>
|
||||
<ErrorBoundary>
|
||||
<View style={styles.hero}>
|
||||
<Text style={[styles.title, pal.link]}>
|
||||
<Trans>Bluesky</Trans>
|
||||
</Text>
|
||||
<Text style={[styles.subtitle, pal.textLight]}>
|
||||
<Trans>See what's next</Trans>
|
||||
<Logo width={92} fill="sky" />
|
||||
|
||||
<View style={{paddingTop: 40, paddingBottom: 6}}>
|
||||
<Logotype width={161} fill={pal.text.color} />
|
||||
</View>
|
||||
|
||||
<Text type="lg-medium" style={[pal.textLight]}>
|
||||
<Trans>What's up?</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
<View testID="signinOrCreateAccount" style={styles.btns}>
|
||||
@@ -65,6 +70,7 @@ const styles = StyleSheet.create({
|
||||
hero: {
|
||||
flex: 2,
|
||||
justifyContent: 'center',
|
||||
alignItems: 'center',
|
||||
},
|
||||
btns: {
|
||||
paddingBottom: 40,
|
||||
|
||||
@@ -10,6 +10,8 @@ import {CenteredView} from '../util/Views'
|
||||
import {isWeb} from 'platform/detection'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {Trans} from '@lingui/macro'
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
import {Logotype} from '#/view/icons/Logotype'
|
||||
|
||||
export const SplashScreen = ({
|
||||
onDismiss,
|
||||
@@ -55,14 +57,15 @@ export const SplashScreen = ({
|
||||
styles.containerInner,
|
||||
isMobileWeb && styles.containerInnerMobile,
|
||||
pal.border,
|
||||
{alignItems: 'center'},
|
||||
]}>
|
||||
<ErrorBoundary>
|
||||
<Text style={isMobileWeb ? styles.titleMobile : styles.title}>
|
||||
Bluesky
|
||||
</Text>
|
||||
<Text style={isMobileWeb ? styles.subtitleMobile : styles.subtitle}>
|
||||
See what's next
|
||||
</Text>
|
||||
<Logo width={92} fill="sky" />
|
||||
|
||||
<View style={{paddingTop: 40, paddingBottom: 20}}>
|
||||
<Logotype width={161} fill={pal.text.color} />
|
||||
</View>
|
||||
|
||||
<View testID="signinOrCreateAccount" style={styles.btns}>
|
||||
<TouchableOpacity
|
||||
testID="createAccountButton"
|
||||
@@ -117,8 +120,6 @@ function Footer({styles}: {styles: ReturnType<typeof useStyles>}) {
|
||||
)
|
||||
}
|
||||
const useStyles = () => {
|
||||
const {isTabletOrMobile} = useWebMediaQueries()
|
||||
const isMobileWeb = isWeb && isTabletOrMobile
|
||||
return StyleSheet.create({
|
||||
container: {
|
||||
height: '100%',
|
||||
@@ -161,8 +162,7 @@ const useStyles = () => {
|
||||
paddingBottom: 30,
|
||||
},
|
||||
btns: {
|
||||
flexDirection: isMobileWeb ? 'column' : 'row',
|
||||
gap: 20,
|
||||
gap: 10,
|
||||
justifyContent: 'center',
|
||||
paddingBottom: 40,
|
||||
},
|
||||
|
||||
@@ -62,6 +62,7 @@ import {useProfileQuery} from '#/state/queries/profile'
|
||||
import {useComposerControls} from '#/state/shell/composer'
|
||||
import {emitPostCreated} from '#/state/events'
|
||||
import {ThreadgateSetting} from '#/state/queries/threadgate'
|
||||
import {logger} from '#/logger'
|
||||
|
||||
type Props = ComposerOpts
|
||||
export const ComposePost = observer(function ComposePost({
|
||||
@@ -228,6 +229,11 @@ export const ComposePost = observer(function ComposePost({
|
||||
})
|
||||
).uri
|
||||
} catch (e: any) {
|
||||
logger.error(e, {
|
||||
message: `Composer: create post failed`,
|
||||
hasImages: gallery.size > 0,
|
||||
})
|
||||
|
||||
if (extLink) {
|
||||
setExtLink({
|
||||
...extLink,
|
||||
|
||||
@@ -7,13 +7,15 @@ import {useNavigation} from '@react-navigation/native'
|
||||
import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed'
|
||||
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
|
||||
import {MainScrollProvider} from '../util/MainScrollProvider'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {useSetMinimalShellMode} from '#/state/shell'
|
||||
import {FeedDescriptor, FeedParams} from '#/state/queries/post-feed'
|
||||
import {ComposeIcon2} from 'lib/icons'
|
||||
import {colors, s} from 'lib/styles'
|
||||
import {FlatList, View, useWindowDimensions} from 'react-native'
|
||||
import {View, useWindowDimensions} from 'react-native'
|
||||
import {ListMethods} from '../util/List'
|
||||
import {Feed} from '../posts/Feed'
|
||||
import {TextLink} from '../util/Link'
|
||||
import {FAB} from '../util/fab/FAB'
|
||||
@@ -27,7 +29,7 @@ import {truncateAndInvalidate} from '#/state/queries/util'
|
||||
import {TabState, getTabState, getRootNavigation} from '#/lib/routes/helpers'
|
||||
import {isNative} from '#/platform/detection'
|
||||
|
||||
const POLL_FREQ = 30e3 // 30sec
|
||||
const POLL_FREQ = 60e3 // 60sec
|
||||
|
||||
export function FeedPage({
|
||||
testID,
|
||||
@@ -51,10 +53,11 @@ export function FeedPage({
|
||||
const {isDesktop} = useWebMediaQueries()
|
||||
const queryClient = useQueryClient()
|
||||
const {openComposer} = useComposerControls()
|
||||
const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll()
|
||||
const [isScrolledDown, setIsScrolledDown] = React.useState(false)
|
||||
const setMinimalShellMode = useSetMinimalShellMode()
|
||||
const {screen, track} = useAnalytics()
|
||||
const headerOffset = useHeaderOffset()
|
||||
const scrollElRef = React.useRef<FlatList>(null)
|
||||
const scrollElRef = React.useRef<ListMethods>(null)
|
||||
const [hasNew, setHasNew] = React.useState(false)
|
||||
|
||||
const scrollToTop = React.useCallback(() => {
|
||||
@@ -62,8 +65,8 @@ export function FeedPage({
|
||||
animated: isNative,
|
||||
offset: -headerOffset,
|
||||
})
|
||||
resetMainScroll()
|
||||
}, [headerOffset, resetMainScroll])
|
||||
setMinimalShellMode(false)
|
||||
}, [headerOffset, setMinimalShellMode])
|
||||
|
||||
const onSoftReset = React.useCallback(() => {
|
||||
const isScreenFocused =
|
||||
@@ -164,21 +167,22 @@ export function FeedPage({
|
||||
|
||||
return (
|
||||
<View testID={testID} style={s.h100pct}>
|
||||
<Feed
|
||||
testID={testID ? `${testID}-feed` : undefined}
|
||||
enabled={isPageFocused}
|
||||
feed={feed}
|
||||
feedParams={feedParams}
|
||||
pollInterval={POLL_FREQ}
|
||||
scrollElRef={scrollElRef}
|
||||
onScroll={onMainScroll}
|
||||
onHasNew={setHasNew}
|
||||
scrollEventThrottle={1}
|
||||
renderEmptyState={renderEmptyState}
|
||||
renderEndOfFeed={renderEndOfFeed}
|
||||
ListHeaderComponent={ListHeaderComponent}
|
||||
headerOffset={headerOffset}
|
||||
/>
|
||||
<MainScrollProvider>
|
||||
<Feed
|
||||
testID={testID ? `${testID}-feed` : undefined}
|
||||
enabled={isPageFocused}
|
||||
feed={feed}
|
||||
feedParams={feedParams}
|
||||
pollInterval={POLL_FREQ}
|
||||
scrollElRef={scrollElRef}
|
||||
onScrolledDownChange={setIsScrolledDown}
|
||||
onHasNew={setHasNew}
|
||||
renderEmptyState={renderEmptyState}
|
||||
renderEndOfFeed={renderEndOfFeed}
|
||||
ListHeaderComponent={ListHeaderComponent}
|
||||
headerOffset={headerOffset}
|
||||
/>
|
||||
</MainScrollProvider>
|
||||
{(isScrolledDown || hasNew) && (
|
||||
<LoadLatestBtn
|
||||
onPress={onPressLoadLatest}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {MutableRefObject} from 'react'
|
||||
import React from 'react'
|
||||
import {
|
||||
Dimensions,
|
||||
RefreshControl,
|
||||
@@ -8,18 +8,16 @@ import {
|
||||
ViewStyle,
|
||||
} from 'react-native'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
import {FlatList} from '../util/Views'
|
||||
import {List, ListRef} from '../util/List'
|
||||
import {FeedSourceCardLoaded} from './FeedSourceCard'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
|
||||
import {Text} from '../util/text/Text'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useProfileFeedgensQuery, RQKEY} from '#/state/queries/profile-feedgens'
|
||||
import {OnScrollHandler} from '#/lib/hooks/useOnMainScroll'
|
||||
import {logger} from '#/logger'
|
||||
import {Trans} from '@lingui/macro'
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
||||
import {useTheme} from '#/lib/ThemeContext'
|
||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||
import {hydrateFeedGenerator} from '#/state/queries/feed'
|
||||
@@ -37,9 +35,7 @@ interface SectionRef {
|
||||
|
||||
interface ProfileFeedgensProps {
|
||||
did: string
|
||||
scrollElRef: MutableRefObject<FlatList<any> | null>
|
||||
onScroll?: OnScrollHandler
|
||||
scrollEventThrottle?: number
|
||||
scrollElRef: ListRef
|
||||
headerOffset: number
|
||||
enabled?: boolean
|
||||
style?: StyleProp<ViewStyle>
|
||||
@@ -50,16 +46,7 @@ export const ProfileFeedgens = React.forwardRef<
|
||||
SectionRef,
|
||||
ProfileFeedgensProps
|
||||
>(function ProfileFeedgensImpl(
|
||||
{
|
||||
did,
|
||||
scrollElRef,
|
||||
onScroll,
|
||||
scrollEventThrottle,
|
||||
headerOffset,
|
||||
enabled,
|
||||
style,
|
||||
testID,
|
||||
},
|
||||
{did, scrollElRef, headerOffset, enabled, style, testID},
|
||||
ref,
|
||||
) {
|
||||
const pal = usePalette('default')
|
||||
@@ -185,10 +172,9 @@ export const ProfileFeedgens = React.forwardRef<
|
||||
[error, refetch, onPressRetryLoadMore, pal, preferences],
|
||||
)
|
||||
|
||||
const scrollHandler = useAnimatedScrollHandler(onScroll || {})
|
||||
return (
|
||||
<View testID={testID} style={style}>
|
||||
<FlatList
|
||||
<List
|
||||
testID={testID ? `${testID}-flatlist` : undefined}
|
||||
ref={scrollElRef}
|
||||
data={items}
|
||||
@@ -207,8 +193,6 @@ export const ProfileFeedgens = React.forwardRef<
|
||||
minHeight: Dimensions.get('window').height * 1.5,
|
||||
}}
|
||||
style={{paddingTop: headerOffset}}
|
||||
onScroll={onScroll != null ? scrollHandler : undefined}
|
||||
scrollEventThrottle={scrollEventThrottle}
|
||||
indicatorStyle={theme.colorScheme === 'dark' ? 'white' : 'black'}
|
||||
removeClippedSubviews={true}
|
||||
contentOffset={{x: 0, y: headerOffset * -1}}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {MutableRefObject} from 'react'
|
||||
import React from 'react'
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Dimensions,
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
ViewStyle,
|
||||
} from 'react-native'
|
||||
import {AppBskyActorDefs, AppBskyGraphDefs} from '@atproto/api'
|
||||
import {FlatList} from '../util/Views'
|
||||
import {List, ListRef} from '../util/List'
|
||||
import {ProfileCardFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
|
||||
@@ -18,10 +18,8 @@ import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {useListMembersQuery} from '#/state/queries/list-members'
|
||||
import {OnScrollHandler} from 'lib/hooks/useOnMainScroll'
|
||||
import {logger} from '#/logger'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
||||
import {useSession} from '#/state/session'
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
|
||||
@@ -34,24 +32,22 @@ export function ListMembers({
|
||||
list,
|
||||
style,
|
||||
scrollElRef,
|
||||
onScroll,
|
||||
onScrolledDownChange,
|
||||
onPressTryAgain,
|
||||
renderHeader,
|
||||
renderEmptyState,
|
||||
testID,
|
||||
scrollEventThrottle,
|
||||
headerOffset = 0,
|
||||
desktopFixedHeightOffset,
|
||||
}: {
|
||||
list: string
|
||||
style?: StyleProp<ViewStyle>
|
||||
scrollElRef?: MutableRefObject<FlatList<any> | null>
|
||||
onScroll: OnScrollHandler
|
||||
scrollElRef?: ListRef
|
||||
onScrolledDownChange: (isScrolledDown: boolean) => void
|
||||
onPressTryAgain?: () => void
|
||||
renderHeader: () => JSX.Element
|
||||
renderEmptyState: () => JSX.Element
|
||||
testID?: string
|
||||
scrollEventThrottle?: number
|
||||
headerOffset?: number
|
||||
desktopFixedHeightOffset?: number
|
||||
}) {
|
||||
@@ -209,10 +205,9 @@ export function ListMembers({
|
||||
[isFetching],
|
||||
)
|
||||
|
||||
const scrollHandler = useAnimatedScrollHandler(onScroll)
|
||||
return (
|
||||
<View testID={testID} style={style}>
|
||||
<FlatList
|
||||
<List
|
||||
testID={testID ? `${testID}-flatlist` : undefined}
|
||||
ref={scrollElRef}
|
||||
data={items}
|
||||
@@ -233,10 +228,9 @@ export function ListMembers({
|
||||
minHeight: Dimensions.get('window').height * 1.5,
|
||||
}}
|
||||
style={{paddingTop: headerOffset}}
|
||||
onScroll={scrollHandler}
|
||||
onScrolledDownChange={onScrolledDownChange}
|
||||
onEndReached={onEndReached}
|
||||
onEndReachedThreshold={0.6}
|
||||
scrollEventThrottle={scrollEventThrottle}
|
||||
removeClippedSubviews={true}
|
||||
contentOffset={{x: 0, y: headerOffset * -1}}
|
||||
// @ts-ignore our .web version only -prf
|
||||
|
||||
@@ -15,7 +15,7 @@ import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {Text} from '../util/text/Text'
|
||||
import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {FlatList} from '../util/Views'
|
||||
import {List} from '../util/List'
|
||||
import {s} from 'lib/styles'
|
||||
import {logger} from '#/logger'
|
||||
import {Trans} from '@lingui/macro'
|
||||
@@ -119,7 +119,7 @@ export function MyLists({
|
||||
[error, onRefresh, renderItem, pal],
|
||||
)
|
||||
|
||||
const FlatListCom = inline ? RNFlatList : FlatList
|
||||
const FlatListCom = inline ? RNFlatList : List
|
||||
return (
|
||||
<View testID={testID} style={style}>
|
||||
{items.length > 0 && (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {MutableRefObject} from 'react'
|
||||
import React from 'react'
|
||||
import {
|
||||
Dimensions,
|
||||
RefreshControl,
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
ViewStyle,
|
||||
} from 'react-native'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
import {FlatList} from '../util/Views'
|
||||
import {List, ListRef} from '../util/List'
|
||||
import {ListCard} from './ListCard'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
|
||||
@@ -16,11 +16,9 @@ import {Text} from '../util/text/Text'
|
||||
import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useProfileListsQuery, RQKEY} from '#/state/queries/profile-lists'
|
||||
import {OnScrollHandler} from '#/lib/hooks/useOnMainScroll'
|
||||
import {logger} from '#/logger'
|
||||
import {Trans} from '@lingui/macro'
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
||||
import {useTheme} from '#/lib/ThemeContext'
|
||||
import {FeedLoadingPlaceholder} from '#/view/com/util/LoadingPlaceholder'
|
||||
import {isNative} from '#/platform/detection'
|
||||
@@ -36,9 +34,7 @@ interface SectionRef {
|
||||
|
||||
interface ProfileListsProps {
|
||||
did: string
|
||||
scrollElRef: MutableRefObject<FlatList<any> | null>
|
||||
onScroll?: OnScrollHandler
|
||||
scrollEventThrottle?: number
|
||||
scrollElRef: ListRef
|
||||
headerOffset: number
|
||||
enabled?: boolean
|
||||
style?: StyleProp<ViewStyle>
|
||||
@@ -47,16 +43,7 @@ interface ProfileListsProps {
|
||||
|
||||
export const ProfileLists = React.forwardRef<SectionRef, ProfileListsProps>(
|
||||
function ProfileListsImpl(
|
||||
{
|
||||
did,
|
||||
scrollElRef,
|
||||
onScroll,
|
||||
scrollEventThrottle,
|
||||
headerOffset,
|
||||
enabled,
|
||||
style,
|
||||
testID,
|
||||
},
|
||||
{did, scrollElRef, headerOffset, enabled, style, testID},
|
||||
ref,
|
||||
) {
|
||||
const pal = usePalette('default')
|
||||
@@ -187,10 +174,9 @@ export const ProfileLists = React.forwardRef<SectionRef, ProfileListsProps>(
|
||||
[error, refetch, onPressRetryLoadMore, pal],
|
||||
)
|
||||
|
||||
const scrollHandler = useAnimatedScrollHandler(onScroll || {})
|
||||
return (
|
||||
<View testID={testID} style={style}>
|
||||
<FlatList
|
||||
<List
|
||||
testID={testID ? `${testID}-flatlist` : undefined}
|
||||
ref={scrollElRef}
|
||||
data={items}
|
||||
@@ -209,8 +195,6 @@ export const ProfileLists = React.forwardRef<SectionRef, ProfileListsProps>(
|
||||
minHeight: Dimensions.get('window').height * 1.5,
|
||||
}}
|
||||
style={{paddingTop: headerOffset}}
|
||||
onScroll={onScroll != null ? scrollHandler : undefined}
|
||||
scrollEventThrottle={scrollEventThrottle}
|
||||
indicatorStyle={theme.colorScheme === 'dark' ? 'white' : 'black'}
|
||||
removeClippedSubviews={true}
|
||||
contentOffset={{x: 0, y: headerOffset * -1}}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import React, {MutableRefObject} from 'react'
|
||||
import {CenteredView, FlatList} from '../util/Views'
|
||||
import React from 'react'
|
||||
import {CenteredView} from '../util/Views'
|
||||
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native'
|
||||
import {FeedItem} from './FeedItem'
|
||||
import {NotificationFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
|
||||
import {EmptyState} from '../util/EmptyState'
|
||||
import {OnScrollHandler} from 'lib/hooks/useOnMainScroll'
|
||||
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
||||
import {s} from 'lib/styles'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useNotificationFeedQuery} from '#/state/queries/notifications/feed'
|
||||
@@ -15,6 +13,7 @@ import {useUnreadNotificationsApi} from '#/state/queries/notifications/unread'
|
||||
import {logger} from '#/logger'
|
||||
import {cleanError} from '#/lib/strings/errors'
|
||||
import {useModerationOpts} from '#/state/queries/preferences'
|
||||
import {List, ListRef} from '../util/List'
|
||||
|
||||
const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
|
||||
const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'}
|
||||
@@ -23,12 +22,12 @@ const LOADING_ITEM = {_reactKey: '__loading__'}
|
||||
export function Feed({
|
||||
scrollElRef,
|
||||
onPressTryAgain,
|
||||
onScroll,
|
||||
onScrolledDownChange,
|
||||
ListHeaderComponent,
|
||||
}: {
|
||||
scrollElRef?: MutableRefObject<FlatList<any> | null>
|
||||
scrollElRef?: ListRef
|
||||
onPressTryAgain?: () => void
|
||||
onScroll?: OnScrollHandler
|
||||
onScrolledDownChange: (isScrolledDown: boolean) => void
|
||||
ListHeaderComponent?: () => JSX.Element
|
||||
}) {
|
||||
const pal = usePalette('default')
|
||||
@@ -135,7 +134,6 @@ export function Feed({
|
||||
[isFetchingNextPage],
|
||||
)
|
||||
|
||||
const scrollHandler = useAnimatedScrollHandler(onScroll || {})
|
||||
return (
|
||||
<View style={s.hContentRegion}>
|
||||
{error && (
|
||||
@@ -146,7 +144,7 @@ export function Feed({
|
||||
/>
|
||||
</CenteredView>
|
||||
)}
|
||||
<FlatList
|
||||
<List
|
||||
testID="notifsFeed"
|
||||
ref={scrollElRef}
|
||||
data={items}
|
||||
@@ -164,8 +162,7 @@ export function Feed({
|
||||
}
|
||||
onEndReached={onEndReached}
|
||||
onEndReachedThreshold={0.6}
|
||||
onScroll={scrollHandler}
|
||||
scrollEventThrottle={1}
|
||||
onScrolledDownChange={onScrolledDownChange}
|
||||
contentContainerStyle={s.contentContainer}
|
||||
// @ts-ignore our .web version only -prf
|
||||
desktopFixedHeight
|
||||
|
||||
@@ -3,12 +3,9 @@ import {StyleSheet, TouchableOpacity, View} from 'react-native'
|
||||
import {TabBar} from 'view/com/pager/TabBar'
|
||||
import {RenderTabBarFnProps} from 'view/com/pager/Pager'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
|
||||
import {Link} from '../util/Link'
|
||||
import {Text} from '../util/text/Text'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import {FontAwesomeIconStyle} from '@fortawesome/react-native-fontawesome'
|
||||
import {s} from 'lib/styles'
|
||||
import {HITSLOP_10} from 'lib/constants'
|
||||
import Animated from 'react-native-reanimated'
|
||||
import {msg} from '@lingui/macro'
|
||||
@@ -21,17 +18,17 @@ import {usePinnedFeedsInfos} from '#/state/queries/feed'
|
||||
import {isWeb} from 'platform/detection'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
import {NavigationProp} from 'lib/routes/types'
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
|
||||
export function FeedsTabBar(
|
||||
props: RenderTabBarFnProps & {testID?: string; onPressSelected: () => void},
|
||||
) {
|
||||
const pal = usePalette('default')
|
||||
const {isSandbox, hasSession} = useSession()
|
||||
const {hasSession} = useSession()
|
||||
const {_} = useLingui()
|
||||
const setDrawerOpen = useSetDrawerOpen()
|
||||
const navigation = useNavigation<NavigationProp>()
|
||||
const {feeds, hasPinnedCustom} = usePinnedFeedsInfos()
|
||||
const brandBlue = useColorSchemeStyle(s.brandBlue, s.blue3)
|
||||
const {headerHeight} = useShellLayout()
|
||||
const {headerMinimalShellTransform} = useMinimalShellMode()
|
||||
const pinnedDisplayNames = hasSession ? feeds.map(f => f.displayName) : []
|
||||
@@ -86,9 +83,9 @@ export function FeedsTabBar(
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
<Text style={[brandBlue, s.bold, styles.title]}>
|
||||
{isSandbox ? 'SANDBOX' : 'Bluesky'}
|
||||
</Text>
|
||||
<View>
|
||||
<Logo width={30} />
|
||||
</View>
|
||||
<View style={[pal.view, {width: 18}]}>
|
||||
{hasSession && (
|
||||
<Link
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import * as React from 'react'
|
||||
import {
|
||||
LayoutChangeEvent,
|
||||
FlatList,
|
||||
ScrollView,
|
||||
StyleSheet,
|
||||
View,
|
||||
@@ -20,17 +19,14 @@ import Animated, {
|
||||
import {Pager, PagerRef, RenderTabBarFnProps} from 'view/com/pager/Pager'
|
||||
import {TabBar} from './TabBar'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {OnScrollHandler} from 'lib/hooks/useOnMainScroll'
|
||||
import {useNonReactiveCallback} from '#/lib/hooks/useNonReactiveCallback'
|
||||
|
||||
const SCROLLED_DOWN_LIMIT = 200
|
||||
import {ListMethods} from '../util/List'
|
||||
import {ScrollProvider} from '#/lib/ScrollContext'
|
||||
|
||||
export interface PagerWithHeaderChildParams {
|
||||
headerHeight: number
|
||||
isFocused: boolean
|
||||
onScroll: OnScrollHandler
|
||||
isScrolledDown: boolean
|
||||
scrollElRef: React.MutableRefObject<FlatList<any> | ScrollView | null>
|
||||
scrollElRef: React.MutableRefObject<ListMethods | ScrollView | null>
|
||||
}
|
||||
|
||||
export interface PagerWithHeaderProps {
|
||||
@@ -62,7 +58,6 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
|
||||
const [currentPage, setCurrentPage] = React.useState(0)
|
||||
const [tabBarHeight, setTabBarHeight] = React.useState(0)
|
||||
const [headerOnlyHeight, setHeaderOnlyHeight] = React.useState(0)
|
||||
const [isScrolledDown, setIsScrolledDown] = React.useState(false)
|
||||
const scrollY = useSharedValue(0)
|
||||
const headerHeight = headerOnlyHeight + tabBarHeight
|
||||
|
||||
@@ -155,15 +150,7 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
|
||||
if (!throttleTimeout.current) {
|
||||
throttleTimeout.current = setTimeout(() => {
|
||||
throttleTimeout.current = null
|
||||
|
||||
runOnUI(adjustScrollForOtherPages)()
|
||||
|
||||
const nextIsScrolledDown = scrollY.value > SCROLLED_DOWN_LIMIT
|
||||
if (isScrolledDown !== nextIsScrolledDown) {
|
||||
React.startTransition(() => {
|
||||
setIsScrolledDown(nextIsScrolledDown)
|
||||
})
|
||||
}
|
||||
}, 80 /* Sync often enough you're unlikely to catch it unsynced */)
|
||||
}
|
||||
})
|
||||
@@ -211,7 +198,6 @@ export const PagerWithHeader = React.forwardRef<PagerRef, PagerWithHeaderProps>(
|
||||
index={i}
|
||||
isReady={isReady}
|
||||
isFocused={i === currentPage}
|
||||
isScrolledDown={isScrolledDown}
|
||||
onScrollWorklet={i === currentPage ? onScrollWorklet : noop}
|
||||
registerRef={registerRef}
|
||||
renderTab={child}
|
||||
@@ -293,7 +279,6 @@ function PagerItem({
|
||||
index,
|
||||
isReady,
|
||||
isFocused,
|
||||
isScrolledDown,
|
||||
onScrollWorklet,
|
||||
renderTab,
|
||||
registerRef,
|
||||
@@ -302,7 +287,6 @@ function PagerItem({
|
||||
index: number
|
||||
isFocused: boolean
|
||||
isReady: boolean
|
||||
isScrolledDown: boolean
|
||||
registerRef: (scrollRef: AnimatedRef<any> | null, atIndex: number) => void
|
||||
onScrollWorklet: (e: NativeScrollEvent) => void
|
||||
renderTab: ((props: PagerWithHeaderChildParams) => JSX.Element) | null
|
||||
@@ -316,24 +300,21 @@ function PagerItem({
|
||||
}
|
||||
}, [scrollElRef, registerRef, index])
|
||||
|
||||
const scrollHandler = React.useMemo(
|
||||
() => ({onScroll: onScrollWorklet}),
|
||||
[onScrollWorklet],
|
||||
)
|
||||
|
||||
if (!isReady || renderTab == null) {
|
||||
return null
|
||||
}
|
||||
|
||||
return renderTab({
|
||||
headerHeight,
|
||||
isFocused,
|
||||
isScrolledDown,
|
||||
onScroll: scrollHandler,
|
||||
scrollElRef: scrollElRef as React.MutableRefObject<
|
||||
FlatList<any> | ScrollView | null
|
||||
>,
|
||||
})
|
||||
return (
|
||||
<ScrollProvider onScroll={onScrollWorklet}>
|
||||
{renderTab({
|
||||
headerHeight,
|
||||
isFocused,
|
||||
scrollElRef: scrollElRef as React.MutableRefObject<
|
||||
ListMethods | ScrollView | null
|
||||
>,
|
||||
})}
|
||||
</ScrollProvider>
|
||||
)
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React, {useCallback, useMemo, useState} from 'react'
|
||||
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native'
|
||||
import {AppBskyFeedGetLikes as GetLikes} from '@atproto/api'
|
||||
import {CenteredView, FlatList} from '../util/Views'
|
||||
import {CenteredView} from '../util/Views'
|
||||
import {List} from '../util/List'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
@@ -84,7 +85,7 @@ export function PostLikedBy({uri}: {uri: string}) {
|
||||
// loaded
|
||||
// =
|
||||
return (
|
||||
<FlatList
|
||||
<List
|
||||
data={likes}
|
||||
keyExtractor={item => item.actor.did}
|
||||
refreshControl={
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React, {useMemo, useCallback, useState} from 'react'
|
||||
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native'
|
||||
import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
|
||||
import {CenteredView, FlatList} from '../util/Views'
|
||||
import {CenteredView} from '../util/Views'
|
||||
import {List} from '../util/List'
|
||||
import {ProfileCardWithFollowBtn} from '../profile/ProfileCard'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
@@ -85,7 +86,7 @@ export function PostRepostedBy({uri}: {uri: string}) {
|
||||
// loaded
|
||||
// =
|
||||
return (
|
||||
<FlatList
|
||||
<List
|
||||
data={repostedBy}
|
||||
keyExtractor={item => item.did}
|
||||
refreshControl={
|
||||
|
||||
@@ -8,7 +8,8 @@ import {
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {AppBskyFeedDefs} from '@atproto/api'
|
||||
import {CenteredView, FlatList} from '../util/Views'
|
||||
import {CenteredView} from '../util/Views'
|
||||
import {List, ListMethods} from '../util/List'
|
||||
import {
|
||||
FontAwesomeIcon,
|
||||
FontAwesomeIconStyle,
|
||||
@@ -140,7 +141,7 @@ function PostThreadLoaded({
|
||||
const {_} = useLingui()
|
||||
const pal = usePalette('default')
|
||||
const {isTablet, isDesktop} = useWebMediaQueries()
|
||||
const ref = useRef<FlatList>(null)
|
||||
const ref = useRef<ListMethods>(null)
|
||||
const highlightedPostRef = useRef<View | null>(null)
|
||||
const needsScrollAdjustment = useRef<boolean>(
|
||||
!isNative || // web always uses scroll adjustment
|
||||
@@ -156,7 +157,9 @@ function PostThreadLoaded({
|
||||
// construct content
|
||||
const posts = React.useMemo(() => {
|
||||
let arr = [TOP_COMPONENT].concat(
|
||||
Array.from(flattenThreadSkeleton(sortThread(thread, threadViewPrefs))),
|
||||
Array.from(
|
||||
flattenThreadSkeleton(sortThread(thread, threadViewPrefs), hasSession),
|
||||
),
|
||||
)
|
||||
if (arr.length > maxVisible) {
|
||||
arr = arr.slice(0, maxVisible).concat([LOAD_MORE])
|
||||
@@ -165,7 +168,7 @@ function PostThreadLoaded({
|
||||
arr.push(BOTTOM_COMPONENT)
|
||||
}
|
||||
return arr
|
||||
}, [thread, maxVisible, threadViewPrefs])
|
||||
}, [thread, maxVisible, threadViewPrefs, hasSession])
|
||||
|
||||
/**
|
||||
* NOTE
|
||||
@@ -335,7 +338,7 @@ function PostThreadLoaded({
|
||||
)
|
||||
|
||||
return (
|
||||
<FlatList
|
||||
<List
|
||||
ref={ref}
|
||||
data={posts}
|
||||
initialNumToRender={!isNative ? posts.length : undefined}
|
||||
@@ -467,20 +470,24 @@ function isThreadPost(v: unknown): v is ThreadPost {
|
||||
|
||||
function* flattenThreadSkeleton(
|
||||
node: ThreadNode,
|
||||
hasSession: boolean,
|
||||
): Generator<YieldedItem, void> {
|
||||
if (node.type === 'post') {
|
||||
if (node.parent) {
|
||||
yield* flattenThreadSkeleton(node.parent)
|
||||
yield* flattenThreadSkeleton(node.parent, hasSession)
|
||||
} else if (node.ctx.isParentLoading) {
|
||||
yield PARENT_SPINNER
|
||||
}
|
||||
if (!hasSession && node.ctx.depth > 0 && hasPwiOptOut(node)) {
|
||||
return
|
||||
}
|
||||
yield node
|
||||
if (node.ctx.isHighlightedPost && !node.post.viewer?.replyDisabled) {
|
||||
yield REPLY_PROMPT
|
||||
}
|
||||
if (node.replies?.length) {
|
||||
for (const reply of node.replies) {
|
||||
yield* flattenThreadSkeleton(reply)
|
||||
yield* flattenThreadSkeleton(reply, hasSession)
|
||||
}
|
||||
} else if (node.ctx.isChildLoading) {
|
||||
yield CHILD_SPINNER
|
||||
@@ -492,6 +499,10 @@ function* flattenThreadSkeleton(
|
||||
}
|
||||
}
|
||||
|
||||
function hasPwiOptOut(node: ThreadPost) {
|
||||
return !!node.post.author.labels?.find(l => l.val === '!no-unauthenticated')
|
||||
}
|
||||
|
||||
function hasBranchingReplies(node: ThreadNode) {
|
||||
if (node.type !== 'post') {
|
||||
return false
|
||||
|
||||
@@ -187,6 +187,9 @@ let PostThreadItemLoaded = ({
|
||||
return makeProfileLink(post.author, 'post', urip.rkey, 'reposted-by')
|
||||
}, [post.uri, post.author])
|
||||
const repostsTitle = 'Reposts of this post'
|
||||
const isSelfLabeledPost =
|
||||
moderation.decisions.post.cause?.type === 'label' &&
|
||||
moderation.decisions.post.cause.label.src === currentAccount?.did
|
||||
|
||||
const translatorUrl = getTranslatorLink(
|
||||
record?.text || '',
|
||||
@@ -351,7 +354,7 @@ let PostThreadItemLoaded = ({
|
||||
includeMute
|
||||
style={styles.alert}
|
||||
/>
|
||||
{post.author.did === currentAccount?.did ? (
|
||||
{post.author.did === currentAccount?.did && !isSelfLabeledPost ? (
|
||||
<LabelInfo
|
||||
details={{uri: post.uri, cid: post.cid}}
|
||||
labels={post.labels}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, {memo, MutableRefObject} from 'react'
|
||||
import React, {memo} from 'react'
|
||||
import {
|
||||
ActivityIndicator,
|
||||
AppState,
|
||||
@@ -10,15 +10,13 @@ import {
|
||||
ViewStyle,
|
||||
} from 'react-native'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
import {FlatList} from '../util/Views'
|
||||
import {List, ListRef} from '../util/List'
|
||||
import {PostFeedLoadingPlaceholder} from '../util/LoadingPlaceholder'
|
||||
import {FeedErrorMessage} from './FeedErrorMessage'
|
||||
import {FeedSlice} from './FeedSlice'
|
||||
import {LoadMoreRetryBtn} from '../util/LoadMoreRetryBtn'
|
||||
import {OnScrollHandler} from 'lib/hooks/useOnMainScroll'
|
||||
import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
||||
import {useTheme} from 'lib/ThemeContext'
|
||||
import {logger} from '#/logger'
|
||||
import {
|
||||
@@ -31,12 +29,16 @@ import {
|
||||
import {isWeb} from '#/platform/detection'
|
||||
import {listenPostCreated} from '#/state/events'
|
||||
import {useSession} from '#/state/session'
|
||||
import {STALE} from '#/state/queries'
|
||||
|
||||
const LOADING_ITEM = {_reactKey: '__loading__'}
|
||||
const EMPTY_FEED_ITEM = {_reactKey: '__empty__'}
|
||||
const ERROR_ITEM = {_reactKey: '__error__'}
|
||||
const LOAD_MORE_ERROR_ITEM = {_reactKey: '__load_more_error__'}
|
||||
|
||||
const REFRESH_AFTER = STALE.HOURS.ONE
|
||||
const CHECK_LATEST_AFTER = STALE.SECONDS.THIRTY
|
||||
|
||||
let Feed = ({
|
||||
feed,
|
||||
feedParams,
|
||||
@@ -45,9 +47,8 @@ let Feed = ({
|
||||
enabled,
|
||||
pollInterval,
|
||||
scrollElRef,
|
||||
onScroll,
|
||||
onScrolledDownChange,
|
||||
onHasNew,
|
||||
scrollEventThrottle,
|
||||
renderEmptyState,
|
||||
renderEndOfFeed,
|
||||
testID,
|
||||
@@ -62,10 +63,9 @@ let Feed = ({
|
||||
style?: StyleProp<ViewStyle>
|
||||
enabled?: boolean
|
||||
pollInterval?: number
|
||||
scrollElRef?: MutableRefObject<FlatList<any> | null>
|
||||
scrollElRef?: ListRef
|
||||
onHasNew?: (v: boolean) => void
|
||||
onScroll?: OnScrollHandler
|
||||
scrollEventThrottle?: number
|
||||
onScrolledDownChange?: (isScrolledDown: boolean) => void
|
||||
renderEmptyState: () => JSX.Element
|
||||
renderEndOfFeed?: () => JSX.Element
|
||||
testID?: string
|
||||
@@ -81,6 +81,7 @@ let Feed = ({
|
||||
const {currentAccount} = useSession()
|
||||
const [isPTRing, setIsPTRing] = React.useState(false)
|
||||
const checkForNewRef = React.useRef<(() => void) | null>(null)
|
||||
const lastFetchRef = React.useRef<number>(Date.now())
|
||||
|
||||
const opts = React.useMemo(
|
||||
() => ({enabled, ignoreFilterFor}),
|
||||
@@ -98,6 +99,9 @@ let Feed = ({
|
||||
fetchNextPage,
|
||||
} = usePostFeedQuery(feed, feedParams, opts)
|
||||
const isEmpty = !isFetching && !data?.pages[0]?.slices.length
|
||||
if (data?.pages[0]) {
|
||||
lastFetchRef.current = data?.pages[0].fetchedAt
|
||||
}
|
||||
|
||||
const checkForNew = React.useCallback(async () => {
|
||||
if (!data?.pages[0] || isFetching || !onHasNew || !enabled) {
|
||||
@@ -137,11 +141,21 @@ let Feed = ({
|
||||
checkForNewRef.current = checkForNew
|
||||
}, [checkForNew])
|
||||
React.useEffect(() => {
|
||||
if (enabled && checkForNewRef.current) {
|
||||
// check for new on enable (aka on focus)
|
||||
checkForNewRef.current()
|
||||
if (enabled) {
|
||||
const timeSinceFirstLoad = Date.now() - lastFetchRef.current
|
||||
if (timeSinceFirstLoad > REFRESH_AFTER) {
|
||||
// do a full refresh
|
||||
scrollElRef?.current?.scrollToOffset({offset: 0, animated: false})
|
||||
queryClient.resetQueries({queryKey: RQKEY(feed)})
|
||||
} else if (
|
||||
timeSinceFirstLoad > CHECK_LATEST_AFTER &&
|
||||
checkForNewRef.current
|
||||
) {
|
||||
// check for new on enable (aka on focus)
|
||||
checkForNewRef.current()
|
||||
}
|
||||
}
|
||||
}, [enabled])
|
||||
}, [enabled, feed, queryClient, scrollElRef])
|
||||
React.useEffect(() => {
|
||||
let cleanup1: () => void | undefined, cleanup2: () => void | undefined
|
||||
const subscription = AppState.addEventListener('change', nextAppState => {
|
||||
@@ -270,10 +284,9 @@ let Feed = ({
|
||||
)
|
||||
}, [isFetchingNextPage, shouldRenderEndOfFeed, renderEndOfFeed, headerOffset])
|
||||
|
||||
const scrollHandler = useAnimatedScrollHandler(onScroll || {})
|
||||
return (
|
||||
<View testID={testID} style={style}>
|
||||
<FlatList
|
||||
<List
|
||||
testID={testID ? `${testID}-flatlist` : undefined}
|
||||
ref={scrollElRef}
|
||||
data={feedItems}
|
||||
@@ -294,8 +307,7 @@ let Feed = ({
|
||||
minHeight: Dimensions.get('window').height * 1.5,
|
||||
}}
|
||||
style={{paddingTop: headerOffset}}
|
||||
onScroll={onScroll != null ? scrollHandler : undefined}
|
||||
scrollEventThrottle={scrollEventThrottle}
|
||||
onScrolledDownChange={onScrolledDownChange}
|
||||
indicatorStyle={theme.colorScheme === 'dark' ? 'white' : 'black'}
|
||||
onEndReached={onEndReached}
|
||||
onEndReachedThreshold={2} // number of posts left to trigger load more
|
||||
|
||||
@@ -50,6 +50,9 @@ export function ProfileCard({
|
||||
return null
|
||||
}
|
||||
const moderation = moderateProfile(profile, moderationOpts)
|
||||
if (moderation.account.filter) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<Link
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React from 'react'
|
||||
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native'
|
||||
import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
|
||||
import {CenteredView, FlatList} from '../util/Views'
|
||||
import {CenteredView} from '../util/Views'
|
||||
import {List} from '../util/List'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {ProfileCardWithFollowBtn} from './ProfileCard'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
@@ -86,7 +87,7 @@ export function ProfileFollowers({name}: {name: string}) {
|
||||
// loaded
|
||||
// =
|
||||
return (
|
||||
<FlatList
|
||||
<List
|
||||
data={followers}
|
||||
keyExtractor={item => item.did}
|
||||
refreshControl={
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import React from 'react'
|
||||
import {ActivityIndicator, RefreshControl, StyleSheet, View} from 'react-native'
|
||||
import {AppBskyActorDefs as ActorDefs} from '@atproto/api'
|
||||
import {CenteredView, FlatList} from '../util/Views'
|
||||
import {CenteredView} from '../util/Views'
|
||||
import {List} from '../util/List'
|
||||
import {ErrorMessage} from '../util/error/ErrorMessage'
|
||||
import {ProfileCardWithFollowBtn} from './ProfileCard'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
@@ -86,7 +87,7 @@ export function ProfileFollows({name}: {name: string}) {
|
||||
// loaded
|
||||
// =
|
||||
return (
|
||||
<FlatList
|
||||
<List
|
||||
data={follows}
|
||||
keyExtractor={item => item.did}
|
||||
refreshControl={
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
import React, {memo, startTransition} from 'react'
|
||||
import {FlatListProps} from 'react-native'
|
||||
import {FlatList_INTERNAL} from './Views'
|
||||
import {useScrollHandlers} from '#/lib/ScrollContext'
|
||||
import {runOnJS, useSharedValue} from 'react-native-reanimated'
|
||||
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
||||
|
||||
export type ListMethods = FlatList_INTERNAL
|
||||
export type ListProps<ItemT> = Omit<
|
||||
FlatListProps<ItemT>,
|
||||
'onScroll' // Use ScrollContext instead.
|
||||
> & {
|
||||
onScrolledDownChange?: (isScrolledDown: boolean) => void
|
||||
}
|
||||
export type ListRef = React.MutableRefObject<FlatList_INTERNAL | null>
|
||||
|
||||
const SCROLLED_DOWN_LIMIT = 200
|
||||
|
||||
function ListImpl<ItemT>(
|
||||
{onScrolledDownChange, ...props}: ListProps<ItemT>,
|
||||
ref: React.Ref<ListMethods>,
|
||||
) {
|
||||
const isScrolledDown = useSharedValue(false)
|
||||
const contextScrollHandlers = useScrollHandlers()
|
||||
|
||||
function handleScrolledDownChange(didScrollDown: boolean) {
|
||||
startTransition(() => {
|
||||
onScrolledDownChange?.(didScrollDown)
|
||||
})
|
||||
}
|
||||
|
||||
const scrollHandler = useAnimatedScrollHandler({
|
||||
onBeginDrag(e, ctx) {
|
||||
contextScrollHandlers.onBeginDrag?.(e, ctx)
|
||||
},
|
||||
onEndDrag(e, ctx) {
|
||||
contextScrollHandlers.onEndDrag?.(e, ctx)
|
||||
},
|
||||
onScroll(e, ctx) {
|
||||
contextScrollHandlers.onScroll?.(e, ctx)
|
||||
|
||||
const didScrollDown = e.contentOffset.y > SCROLLED_DOWN_LIMIT
|
||||
if (isScrolledDown.value !== didScrollDown) {
|
||||
isScrolledDown.value = didScrollDown
|
||||
if (onScrolledDownChange != null) {
|
||||
runOnJS(handleScrolledDownChange)(didScrollDown)
|
||||
}
|
||||
}
|
||||
},
|
||||
})
|
||||
|
||||
return (
|
||||
<FlatList_INTERNAL
|
||||
{...props}
|
||||
onScroll={scrollHandler}
|
||||
scrollEventThrottle={1}
|
||||
ref={ref}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export const List = memo(React.forwardRef(ListImpl)) as <ItemT>(
|
||||
props: ListProps<ItemT> & {ref?: React.Ref<ListMethods>},
|
||||
) => React.ReactElement
|
||||
@@ -1,30 +1,18 @@
|
||||
import {useState, useCallback, useMemo} from 'react'
|
||||
import {NativeSyntheticEvent, NativeScrollEvent} from 'react-native'
|
||||
import React, {useCallback} from 'react'
|
||||
import {ScrollProvider} from '#/lib/ScrollContext'
|
||||
import {NativeScrollEvent} from 'react-native'
|
||||
import {useSetMinimalShellMode, useMinimalShellMode} from '#/state/shell'
|
||||
import {useShellLayout} from '#/state/shell/shell-layout'
|
||||
import {s} from 'lib/styles'
|
||||
import {isWeb} from 'platform/detection'
|
||||
import {
|
||||
useSharedValue,
|
||||
interpolate,
|
||||
runOnJS,
|
||||
ScrollHandlers,
|
||||
} from 'react-native-reanimated'
|
||||
import {useSharedValue, interpolate} from 'react-native-reanimated'
|
||||
|
||||
function clamp(num: number, min: number, max: number) {
|
||||
'worklet'
|
||||
return Math.min(Math.max(num, min), max)
|
||||
}
|
||||
|
||||
export type OnScrollCb = (
|
||||
event: NativeSyntheticEvent<NativeScrollEvent>,
|
||||
) => void
|
||||
export type OnScrollHandler = ScrollHandlers<any>
|
||||
export type ResetCb = () => void
|
||||
|
||||
export function useOnMainScroll(): [OnScrollHandler, boolean, ResetCb] {
|
||||
export function MainScrollProvider({children}: {children: React.ReactNode}) {
|
||||
const {headerHeight} = useShellLayout()
|
||||
const [isScrolledDown, setIsScrolledDown] = useState(false)
|
||||
const mode = useMinimalShellMode()
|
||||
const setMode = useSetMinimalShellMode()
|
||||
const startDragOffset = useSharedValue<number | null>(null)
|
||||
@@ -58,13 +46,6 @@ export function useOnMainScroll(): [OnScrollHandler, boolean, ResetCb] {
|
||||
const onScroll = useCallback(
|
||||
(e: NativeScrollEvent) => {
|
||||
'worklet'
|
||||
// Keep track of whether we want to show "scroll to top".
|
||||
if (!isScrolledDown && e.contentOffset.y > s.window.height) {
|
||||
runOnJS(setIsScrolledDown)(true)
|
||||
} else if (isScrolledDown && e.contentOffset.y < s.window.height) {
|
||||
runOnJS(setIsScrolledDown)(false)
|
||||
}
|
||||
|
||||
if (startDragOffset.value === null || startMode.value === null) {
|
||||
if (mode.value !== 0 && e.contentOffset.y < headerHeight.value) {
|
||||
// If we're close enough to the top, always show the shell.
|
||||
@@ -102,24 +83,15 @@ export function useOnMainScroll(): [OnScrollHandler, boolean, ResetCb] {
|
||||
startMode.value = mode.value
|
||||
}
|
||||
},
|
||||
[headerHeight, mode, setMode, isScrolledDown, startDragOffset, startMode],
|
||||
[headerHeight, mode, setMode, startDragOffset, startMode],
|
||||
)
|
||||
|
||||
const scrollHandler: ScrollHandlers<any> = useMemo(
|
||||
() => ({
|
||||
onBeginDrag,
|
||||
onEndDrag,
|
||||
onScroll,
|
||||
}),
|
||||
[onBeginDrag, onEndDrag, onScroll],
|
||||
return (
|
||||
<ScrollProvider
|
||||
onBeginDrag={onBeginDrag}
|
||||
onEndDrag={onEndDrag}
|
||||
onScroll={onScroll}>
|
||||
{children}
|
||||
</ScrollProvider>
|
||||
)
|
||||
|
||||
return [
|
||||
scrollHandler,
|
||||
isScrolledDown,
|
||||
useCallback(() => {
|
||||
setIsScrolledDown(false)
|
||||
setMode(false)
|
||||
}, [setMode]),
|
||||
]
|
||||
}
|
||||
@@ -1,13 +1,14 @@
|
||||
import React, {useEffect, useState} from 'react'
|
||||
import {
|
||||
NativeSyntheticEvent,
|
||||
NativeScrollEvent,
|
||||
Pressable,
|
||||
RefreshControl,
|
||||
StyleSheet,
|
||||
View,
|
||||
ScrollView,
|
||||
} from 'react-native'
|
||||
import {FlatList} from './Views'
|
||||
import {OnScrollCb} from 'lib/hooks/useOnMainScroll'
|
||||
import {FlatList_INTERNAL} from './Views'
|
||||
import {useColorSchemeStyle} from 'lib/hooks/useColorSchemeStyle'
|
||||
import {Text} from './text/Text'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
@@ -38,7 +39,7 @@ export const ViewSelector = React.forwardRef<
|
||||
| null
|
||||
| undefined
|
||||
onSelectView?: (viewIndex: number) => void
|
||||
onScroll?: OnScrollCb
|
||||
onScroll?: (event: NativeSyntheticEvent<NativeScrollEvent>) => void
|
||||
onRefresh?: () => void
|
||||
onEndReached?: (info: {distanceFromEnd: number}) => void
|
||||
}
|
||||
@@ -59,7 +60,7 @@ export const ViewSelector = React.forwardRef<
|
||||
) {
|
||||
const pal = usePalette('default')
|
||||
const [selectedIndex, setSelectedIndex] = useState<number>(0)
|
||||
const flatListRef = React.useRef<FlatList>(null)
|
||||
const flatListRef = React.useRef<FlatList_INTERNAL>(null)
|
||||
|
||||
// events
|
||||
// =
|
||||
@@ -110,7 +111,7 @@ export const ViewSelector = React.forwardRef<
|
||||
[items],
|
||||
)
|
||||
return (
|
||||
<FlatList
|
||||
<FlatList_INTERNAL
|
||||
ref={flatListRef}
|
||||
data={data}
|
||||
keyExtractor={keyExtractor}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import React from 'react'
|
||||
import {ViewProps} from 'react-native'
|
||||
export {FlatList, ScrollView} from 'react-native'
|
||||
export {FlatList as FlatList_INTERNAL, ScrollView} from 'react-native'
|
||||
export function CenteredView({
|
||||
style,
|
||||
sideBorders,
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from 'react'
|
||||
import {View} from 'react-native'
|
||||
import Animated from 'react-native-reanimated'
|
||||
|
||||
export const FlatList = Animated.FlatList
|
||||
export const FlatList_INTERNAL = Animated.FlatList
|
||||
export const ScrollView = Animated.ScrollView
|
||||
export function CenteredView(props) {
|
||||
return <View {...props} />
|
||||
|
||||
@@ -49,7 +49,7 @@ export function CenteredView({
|
||||
return <View style={style} {...props} />
|
||||
}
|
||||
|
||||
export const FlatList = React.forwardRef(function FlatListImpl<ItemT>(
|
||||
export const FlatList_INTERNAL = React.forwardRef(function FlatListImpl<ItemT>(
|
||||
{
|
||||
contentContainerStyle,
|
||||
style,
|
||||
|
||||
@@ -7,7 +7,7 @@ import {Text} from '../text/Text'
|
||||
import {ShieldExclamation} from 'lib/icons'
|
||||
import {describeModerationCause} from 'lib/moderation'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {isPostMediaBlurred} from 'lib/moderation'
|
||||
|
||||
@@ -95,13 +95,17 @@ export function ContentHider({
|
||||
<Text type="md" style={pal.text}>
|
||||
{desc.name}
|
||||
</Text>
|
||||
{!moderation.noOverride && (
|
||||
<View style={styles.showBtn}>
|
||||
<Text type="lg" style={pal.link}>
|
||||
{override ? 'Hide' : 'Show'}
|
||||
</Text>
|
||||
</View>
|
||||
)}
|
||||
<View style={styles.showBtn}>
|
||||
<Text type="lg" style={pal.link}>
|
||||
{moderation.noOverride ? (
|
||||
<Trans>Learn more</Trans>
|
||||
) : override ? (
|
||||
<Trans>Hide</Trans>
|
||||
) : (
|
||||
<Trans>Show</Trans>
|
||||
)}
|
||||
</Text>
|
||||
</View>
|
||||
</Pressable>
|
||||
{override && <View style={childContainerStyle}>{children}</View>}
|
||||
</View>
|
||||
|
||||
@@ -43,7 +43,8 @@ export function LabelInfo({
|
||||
]}>
|
||||
<Text type="sm" style={pal.text}>
|
||||
<Trans>
|
||||
This {'did' in details ? 'account' : 'post'} has been labeled.
|
||||
A content warning has been applied to this{' '}
|
||||
{'did' in details ? 'account' : 'post'}.
|
||||
</Trans>{' '}
|
||||
</Text>
|
||||
<Pressable
|
||||
|
||||
@@ -22,6 +22,7 @@ import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {s} from '#/lib/styles'
|
||||
import {CenteredView} from '../Views'
|
||||
|
||||
export function ScreenHider({
|
||||
testID,
|
||||
@@ -53,41 +54,58 @@ export function ScreenHider({
|
||||
)
|
||||
}
|
||||
|
||||
const isNoPwi =
|
||||
moderation.cause?.type === 'label' &&
|
||||
moderation.cause?.labelDef.id === '!no-unauthenticated'
|
||||
const desc = describeModerationCause(moderation.cause, 'account')
|
||||
return (
|
||||
<View style={[styles.container, pal.view, containerStyle]}>
|
||||
<CenteredView
|
||||
style={[styles.container, pal.view, containerStyle]}
|
||||
sideBorders>
|
||||
<View style={styles.iconContainer}>
|
||||
<View style={[styles.icon, palInverted.view]}>
|
||||
<FontAwesomeIcon
|
||||
icon="exclamation"
|
||||
icon={isNoPwi ? ['far', 'eye-slash'] : 'exclamation'}
|
||||
style={pal.textInverted as FontAwesomeIconStyle}
|
||||
size={24}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<Text type="title-2xl" style={[styles.title, pal.text]}>
|
||||
<Trans>Content Warning</Trans>
|
||||
{isNoPwi ? (
|
||||
<Trans>Sign-in Required</Trans>
|
||||
) : (
|
||||
<Trans>Content Warning</Trans>
|
||||
)}
|
||||
</Text>
|
||||
<Text type="2xl" style={[styles.description, pal.textLight]}>
|
||||
<Trans>This {screenDescription} has been flagged:</Trans>
|
||||
<Text type="2xl-medium" style={[pal.text, s.ml5]}>
|
||||
{desc.name}.
|
||||
</Text>
|
||||
<TouchableWithoutFeedback
|
||||
onPress={() => {
|
||||
openModal({
|
||||
name: 'moderation-details',
|
||||
context: 'account',
|
||||
moderation,
|
||||
})
|
||||
}}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={_(msg`Learn more about this warning`)}
|
||||
accessibilityHint="">
|
||||
<Text type="2xl" style={pal.link}>
|
||||
<Trans>Learn More</Trans>
|
||||
</Text>
|
||||
</TouchableWithoutFeedback>
|
||||
{isNoPwi ? (
|
||||
<Trans>
|
||||
This account has requested that users sign in to view their profile.
|
||||
</Trans>
|
||||
) : (
|
||||
<>
|
||||
<Trans>This {screenDescription} has been flagged:</Trans>
|
||||
<Text type="2xl-medium" style={[pal.text, s.ml5]}>
|
||||
{desc.name}.
|
||||
</Text>
|
||||
<TouchableWithoutFeedback
|
||||
onPress={() => {
|
||||
openModal({
|
||||
name: 'moderation-details',
|
||||
context: 'account',
|
||||
moderation,
|
||||
})
|
||||
}}
|
||||
accessibilityRole="button"
|
||||
accessibilityLabel={_(msg`Learn more about this warning`)}
|
||||
accessibilityHint="">
|
||||
<Text type="2xl" style={pal.link}>
|
||||
<Trans>Learn More</Trans>
|
||||
</Text>
|
||||
</TouchableWithoutFeedback>
|
||||
</>
|
||||
)}{' '}
|
||||
</Text>
|
||||
{isMobile && <View style={styles.spacer} />}
|
||||
<View style={styles.btnContainer}>
|
||||
@@ -116,7 +134,7 @@ export function ScreenHider({
|
||||
</Button>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
</CenteredView>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import {AppBskyFeedDefs, AppBskyFeedPost} from '@atproto/api'
|
||||
import {Text} from '../text/Text'
|
||||
import {PostDropdownBtn} from '../forms/PostDropdownBtn'
|
||||
import {HeartIcon, HeartIconSolid, CommentBottomArrow} from 'lib/icons'
|
||||
import {s, colors} from 'lib/styles'
|
||||
import {s} from 'lib/styles'
|
||||
import {pluralize} from 'lib/strings/helpers'
|
||||
import {useTheme} from 'lib/ThemeContext'
|
||||
import {RepostButton} from './RepostButton'
|
||||
@@ -180,7 +180,7 @@ let PostCtrls = ({
|
||||
accessibilityHint=""
|
||||
hitSlop={big ? HITSLOP_20 : HITSLOP_10}>
|
||||
{post.viewer?.like ? (
|
||||
<HeartIconSolid style={styles.ctrlIconLiked} size={big ? 22 : 16} />
|
||||
<HeartIconSolid style={s.likeColor} size={big ? 22 : 16} />
|
||||
) : (
|
||||
<HeartIcon
|
||||
style={[defaultCtrlColor, big ? styles.mt1 : undefined]}
|
||||
@@ -193,7 +193,7 @@ let PostCtrls = ({
|
||||
testID="likeCount"
|
||||
style={
|
||||
post.viewer?.like
|
||||
? [s.bold, s.red3, s.f15, s.ml5]
|
||||
? [s.bold, s.likeColor, s.f15, s.ml5]
|
||||
: [defaultCtrlColor, s.f15, s.ml5]
|
||||
}>
|
||||
{post.likeCount}
|
||||
@@ -233,9 +233,6 @@ const styles = StyleSheet.create({
|
||||
paddingLeft: 5,
|
||||
paddingRight: 5,
|
||||
},
|
||||
ctrlIconLiked: {
|
||||
color: colors.like,
|
||||
},
|
||||
mt1: {
|
||||
marginTop: 1,
|
||||
},
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import React from 'react'
|
||||
import Svg, {
|
||||
Path,
|
||||
Defs,
|
||||
LinearGradient,
|
||||
Stop,
|
||||
SvgProps,
|
||||
PathProps,
|
||||
} from 'react-native-svg'
|
||||
|
||||
import {colors} from '#/lib/styles'
|
||||
|
||||
const ratio = 57 / 64
|
||||
|
||||
type Props = {
|
||||
fill?: PathProps['fill']
|
||||
} & SvgProps
|
||||
|
||||
export const Logo = React.forwardRef(function LogoImpl(props: Props, ref) {
|
||||
const {fill, ...rest} = props
|
||||
const gradient = fill === 'sky'
|
||||
const _fill = gradient ? 'url(#sky)' : fill || colors.blue3
|
||||
// @ts-ignore it's fiiiiine
|
||||
const size = parseInt(rest.width || 32)
|
||||
return (
|
||||
<Svg
|
||||
fill="none"
|
||||
// @ts-ignore it's fiiiiine
|
||||
ref={ref}
|
||||
viewBox="0 0 64 57"
|
||||
{...rest}
|
||||
style={{width: size, height: size * ratio}}>
|
||||
{gradient && (
|
||||
<Defs>
|
||||
<LinearGradient id="sky" x1="0" y1="0" x2="0" y2="1">
|
||||
<Stop offset="0" stopColor="#0A7AFF" stopOpacity="1" />
|
||||
<Stop offset="1" stopColor="#59B9FF" stopOpacity="1" />
|
||||
</LinearGradient>
|
||||
</Defs>
|
||||
)}
|
||||
|
||||
<Path
|
||||
fill={_fill}
|
||||
d="M13.873 3.805C21.21 9.332 29.103 20.537 32 26.55v15.882c0-.338-.13.044-.41.867-1.512 4.456-7.418 21.847-20.923 7.944-7.111-7.32-3.819-14.64 9.125-16.85-7.405 1.264-15.73-.825-18.014-9.015C1.12 23.022 0 8.51 0 6.55 0-3.268 8.579-.182 13.873 3.805ZM50.127 3.805C42.79 9.332 34.897 20.537 32 26.55v15.882c0-.338.13.044.41.867 1.512 4.456 7.418 21.847 20.923 7.944 7.111-7.32 3.819-14.64-9.125-16.85 7.405 1.264 15.73-.825 18.014-9.015C62.88 23.022 64 8.51 64 6.55c0-9.818-8.578-6.732-13.873-2.745Z"
|
||||
/>
|
||||
</Svg>
|
||||
)
|
||||
})
|
||||
@@ -0,0 +1,29 @@
|
||||
import React from 'react'
|
||||
import Svg, {Path, SvgProps, PathProps} from 'react-native-svg'
|
||||
|
||||
import {usePalette} from '#/lib/hooks/usePalette'
|
||||
|
||||
const ratio = 17 / 64
|
||||
|
||||
export function Logotype({
|
||||
fill,
|
||||
...rest
|
||||
}: {fill?: PathProps['fill']} & SvgProps) {
|
||||
const pal = usePalette('default')
|
||||
// @ts-ignore it's fiiiiine
|
||||
const size = parseInt(rest.width || 32)
|
||||
|
||||
return (
|
||||
<Svg
|
||||
fill="none"
|
||||
viewBox="0 0 64 17"
|
||||
{...rest}
|
||||
width={size}
|
||||
height={Number(size) * ratio}>
|
||||
<Path
|
||||
fill={fill || pal.text.color}
|
||||
d="M8.478 6.252c1.503.538 2.3 1.78 2.3 3.172 0 2.356-1.576 3.785-4.6 3.785H0V0h5.974c2.875 0 4.267 1.466 4.267 3.413 0 1.3-.594 2.245-1.763 2.839Zm-2.69-4.193H2.504v3.45h3.284c1.28 0 1.967-.667 1.967-1.78 0-1.02-.705-1.67-1.967-1.67Zm-3.284 9.072h3.544c1.41 0 2.17-.65 2.17-1.818 0-1.224-.723-1.837-2.17-1.837H2.504v3.655ZM14.251 13.209h-2.337V0h2.337v13.209ZM22.001 8.998V3.636h2.338v9.573h-2.263v-1.392c-.724 1.076-1.726 1.614-3.006 1.614-2.022 0-3.34-1.224-3.34-3.45V3.636h2.338v5.955c0 1.206.594 1.818 1.8 1.818 1.132 0 2.133-.835 2.133-2.411ZM34.979 8.59v.556h-7.161c.167 1.651 1.076 2.467 2.486 2.467 1.076 0 1.8-.463 2.189-1.372h2.244c-.5 1.947-2.17 3.19-4.452 3.19-1.428 0-2.579-.463-3.45-1.372-.872-.91-1.318-2.115-1.318-3.637 0-1.502.427-2.708 1.299-3.636.872-.909 2.004-1.372 3.432-1.372 1.447 0 2.597.482 3.45 1.428.854.946 1.28 2.208 1.28 3.747Zm-4.75-3.358c-1.28 0-2.17.742-2.393 2.281h4.805c-.204-1.391-1.057-2.281-2.411-2.281ZM40.16 13.469c-2.783 0-4.249-1.095-4.379-3.303h2.282c.13 1.188.724 1.633 2.134 1.633 1.261 0 1.892-.39 1.892-1.15 0-.687-.445-1.02-1.874-1.262l-1.094-.185c-2.097-.353-3.136-1.318-3.136-2.894 0-1.8 1.429-2.894 3.97-2.894 2.728 0 4.138 1.075 4.23 3.246h-2.207c-.056-1.169-.742-1.577-2.023-1.577-1.113 0-1.67.371-1.67 1.113 0 .668.483.965 1.596 1.169l1.206.186c2.32.426 3.32 1.28 3.32 2.912 0 1.93-1.557 3.006-4.247 3.006ZM54.667 13.209h-2.671l-2.783-4.453-1.447 1.447v3.006h-2.3V0h2.3v7.606l3.896-3.97h2.783l-3.618 3.618 3.84 5.955ZM60.772 6.048l.78-2.412H64l-3.692 10.352c-.39 1.057-.872 1.818-1.484 2.245-.612.426-1.484.63-2.634.63-.39 0-.724-.018-1.02-.055V14.97h.89c1.057 0 1.577-.65 1.577-1.54 0-.445-.149-1.094-.446-1.929l-2.746-7.866h2.487l.779 2.393c.575 1.8 1.076 3.58 1.521 5.343.408-1.521.928-3.302 1.54-5.324Z"
|
||||
/>
|
||||
</Svg>
|
||||
)
|
||||
}
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
import {ErrorMessage} from 'view/com/util/error/ErrorMessage'
|
||||
import debounce from 'lodash.debounce'
|
||||
import {Text} from 'view/com/util/text/Text'
|
||||
import {FlatList} from 'view/com/util/Views'
|
||||
import {List} from 'view/com/util/List'
|
||||
import {useFocusEffect} from '@react-navigation/native'
|
||||
import {FeedSourceCard} from 'view/com/feeds/FeedSourceCard'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
@@ -481,7 +481,7 @@ export function FeedsScreen(_props: Props) {
|
||||
|
||||
{preferences ? <View /> : <ActivityIndicator />}
|
||||
|
||||
<FlatList
|
||||
<List
|
||||
style={[!isTabletOrDesktop && s.flex1, styles.list]}
|
||||
data={items}
|
||||
keyExtractor={item => item.key}
|
||||
|
||||
@@ -9,6 +9,7 @@ import {CustomFeedEmptyState} from 'view/com/posts/CustomFeedEmptyState'
|
||||
import {FeedsTabBar} from '../com/pager/FeedsTabBar'
|
||||
import {Pager, RenderTabBarFnProps} from 'view/com/pager/Pager'
|
||||
import {FeedPage} from 'view/com/feeds/FeedPage'
|
||||
import {HomeLoggedOutCTA} from '../com/auth/HomeLoggedOutCTA'
|
||||
import {useSetMinimalShellMode, useSetDrawerSwipeDisabled} from '#/state/shell'
|
||||
import {usePreferencesQuery} from '#/state/queries/preferences'
|
||||
import {UsePreferencesQueryResponse} from '#/state/queries/preferences/types'
|
||||
@@ -199,12 +200,7 @@ function HomeScreenReady({
|
||||
onPageScrollStateChanged={onPageScrollStateChanged}
|
||||
renderTabBar={renderTabBar}
|
||||
tabBarPosition="top">
|
||||
<FeedPage
|
||||
testID="customFeedPage"
|
||||
isPageFocused={true}
|
||||
feed={`feedgen|at://did:plc:z72i7hdynmk6r22z27h6tvur/app.bsky.feed.generator/whats-hot`}
|
||||
renderEmptyState={renderCustomFeedEmptyState}
|
||||
/>
|
||||
<HomeLoggedOutCTA />
|
||||
</Pager>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from 'react'
|
||||
import {FlatList, View} from 'react-native'
|
||||
import {View} from 'react-native'
|
||||
import {useFocusEffect} from '@react-navigation/native'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
import {
|
||||
@@ -9,8 +9,9 @@ import {
|
||||
import {ViewHeader} from '../com/util/ViewHeader'
|
||||
import {Feed} from '../com/notifications/Feed'
|
||||
import {TextLink} from 'view/com/util/Link'
|
||||
import {ListMethods} from 'view/com/util/List'
|
||||
import {LoadLatestBtn} from 'view/com/util/load-latest/LoadLatestBtn'
|
||||
import {useOnMainScroll} from 'lib/hooks/useOnMainScroll'
|
||||
import {MainScrollProvider} from '../com/util/MainScrollProvider'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {s, colors} from 'lib/styles'
|
||||
@@ -35,8 +36,8 @@ type Props = NativeStackScreenProps<
|
||||
export function NotificationsScreen({}: Props) {
|
||||
const {_} = useLingui()
|
||||
const setMinimalShellMode = useSetMinimalShellMode()
|
||||
const [onMainScroll, isScrolledDown, resetMainScroll] = useOnMainScroll()
|
||||
const scrollElRef = React.useRef<FlatList>(null)
|
||||
const [isScrolledDown, setIsScrolledDown] = React.useState(false)
|
||||
const scrollElRef = React.useRef<ListMethods>(null)
|
||||
const checkLatestRef = React.useRef<() => void | null>()
|
||||
const {screen} = useAnalytics()
|
||||
const pal = usePalette('default')
|
||||
@@ -50,8 +51,8 @@ export function NotificationsScreen({}: Props) {
|
||||
// =
|
||||
const scrollToTop = React.useCallback(() => {
|
||||
scrollElRef.current?.scrollToOffset({animated: isNative, offset: 0})
|
||||
resetMainScroll()
|
||||
}, [scrollElRef, resetMainScroll])
|
||||
setMinimalShellMode(false)
|
||||
}, [scrollElRef, setMinimalShellMode])
|
||||
|
||||
const onPressLoadLatest = React.useCallback(() => {
|
||||
scrollToTop()
|
||||
@@ -130,11 +131,13 @@ export function NotificationsScreen({}: Props) {
|
||||
return (
|
||||
<View testID="notificationsScreen" style={s.hContentRegion}>
|
||||
<ViewHeader title={_(msg`Notifications`)} canGoBack={false} />
|
||||
<Feed
|
||||
onScroll={onMainScroll}
|
||||
scrollElRef={scrollElRef}
|
||||
ListHeaderComponent={ListHeaderComponent}
|
||||
/>
|
||||
<MainScrollProvider>
|
||||
<Feed
|
||||
onScrolledDownChange={setIsScrolledDown}
|
||||
scrollElRef={scrollElRef}
|
||||
ListHeaderComponent={ListHeaderComponent}
|
||||
/>
|
||||
</MainScrollProvider>
|
||||
{(isScrolledDown || hasNew) && (
|
||||
<LoadLatestBtn
|
||||
onPress={onPressLoadLatest}
|
||||
|
||||
@@ -24,11 +24,13 @@ import {useResolveUriQuery} from '#/state/queries/resolve-uri'
|
||||
import {ErrorMessage} from '../com/util/error/ErrorMessage'
|
||||
import {CenteredView} from '../com/util/Views'
|
||||
import {useComposerControls} from '#/state/shell/composer'
|
||||
import {useSession} from '#/state/session'
|
||||
|
||||
type Props = NativeStackScreenProps<CommonNavigatorParams, 'PostThread'>
|
||||
export function PostThreadScreen({route}: Props) {
|
||||
const queryClient = useQueryClient()
|
||||
const {_} = useLingui()
|
||||
const {hasSession} = useSession()
|
||||
const {fabMinimalShellTransform} = useMinimalShellMode()
|
||||
const setMinimalShellMode = useSetMinimalShellMode()
|
||||
const {openComposer} = useComposerControls()
|
||||
@@ -89,7 +91,7 @@ export function PostThreadScreen({route}: Props) {
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
{isMobile && canReply && (
|
||||
{isMobile && canReply && hasSession && (
|
||||
<Animated.View
|
||||
style={[
|
||||
styles.prompt,
|
||||
|
||||
@@ -5,7 +5,8 @@ import {AppBskyActorDefs, moderateProfile, ModerationOpts} from '@atproto/api'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
|
||||
import {CenteredView, FlatList} from '../com/util/Views'
|
||||
import {CenteredView} from '../com/util/Views'
|
||||
import {ListRef} from '../com/util/List'
|
||||
import {ScreenHider} from 'view/com/util/moderation/ScreenHider'
|
||||
import {Feed} from 'view/com/posts/Feed'
|
||||
import {ProfileLists} from '../com/lists/ProfileLists'
|
||||
@@ -20,7 +21,6 @@ import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {ComposeIcon2} from 'lib/icons'
|
||||
import {useSetTitle} from 'lib/hooks/useSetTitle'
|
||||
import {combinedDisplayName} from 'lib/strings/display-names'
|
||||
import {OnScrollHandler} from '#/lib/hooks/useOnMainScroll'
|
||||
import {FeedDescriptor} from '#/state/queries/post-feed'
|
||||
import {useResolveDidQuery} from '#/state/queries/resolve-uri'
|
||||
import {useProfileQuery} from '#/state/queries/profile'
|
||||
@@ -153,7 +153,7 @@ function ProfileScreenLoaded({
|
||||
const isMe = profile.did === currentAccount?.did
|
||||
const showRepliesTab = hasSession
|
||||
const showLikesTab = isMe
|
||||
const showFeedsTab = isMe || extraInfoQuery.data?.hasFeedgens
|
||||
const showFeedsTab = hasSession && (isMe || extraInfoQuery.data?.hasFeedgens)
|
||||
const showListsTab = hasSession && (isMe || extraInfoQuery.data?.hasLists)
|
||||
const sectionTitles = useMemo<string[]>(() => {
|
||||
return [
|
||||
@@ -277,103 +277,67 @@ function ProfileScreenLoaded({
|
||||
onPageSelected={onPageSelected}
|
||||
onCurrentPageSelected={onCurrentPageSelected}
|
||||
renderHeader={renderHeader}>
|
||||
{({onScroll, headerHeight, isFocused, isScrolledDown, scrollElRef}) => (
|
||||
{({headerHeight, isFocused, scrollElRef}) => (
|
||||
<FeedSection
|
||||
ref={postsSectionRef}
|
||||
feed={`author|${profile.did}|posts_and_author_threads`}
|
||||
onScroll={onScroll}
|
||||
headerHeight={headerHeight}
|
||||
isFocused={isFocused}
|
||||
isScrolledDown={isScrolledDown}
|
||||
scrollElRef={
|
||||
scrollElRef as React.MutableRefObject<FlatList<any> | null>
|
||||
}
|
||||
scrollElRef={scrollElRef as ListRef}
|
||||
ignoreFilterFor={profile.did}
|
||||
/>
|
||||
)}
|
||||
{showRepliesTab
|
||||
? ({
|
||||
onScroll,
|
||||
headerHeight,
|
||||
isFocused,
|
||||
isScrolledDown,
|
||||
scrollElRef,
|
||||
}) => (
|
||||
? ({headerHeight, isFocused, scrollElRef}) => (
|
||||
<FeedSection
|
||||
ref={repliesSectionRef}
|
||||
feed={`author|${profile.did}|posts_with_replies`}
|
||||
onScroll={onScroll}
|
||||
headerHeight={headerHeight}
|
||||
isFocused={isFocused}
|
||||
isScrolledDown={isScrolledDown}
|
||||
scrollElRef={
|
||||
scrollElRef as React.MutableRefObject<FlatList<any> | null>
|
||||
}
|
||||
scrollElRef={scrollElRef as ListRef}
|
||||
ignoreFilterFor={profile.did}
|
||||
/>
|
||||
)
|
||||
: null}
|
||||
{({onScroll, headerHeight, isFocused, isScrolledDown, scrollElRef}) => (
|
||||
{({headerHeight, isFocused, scrollElRef}) => (
|
||||
<FeedSection
|
||||
ref={mediaSectionRef}
|
||||
feed={`author|${profile.did}|posts_with_media`}
|
||||
onScroll={onScroll}
|
||||
headerHeight={headerHeight}
|
||||
isFocused={isFocused}
|
||||
isScrolledDown={isScrolledDown}
|
||||
scrollElRef={
|
||||
scrollElRef as React.MutableRefObject<FlatList<any> | null>
|
||||
}
|
||||
scrollElRef={scrollElRef as ListRef}
|
||||
ignoreFilterFor={profile.did}
|
||||
/>
|
||||
)}
|
||||
{showLikesTab
|
||||
? ({
|
||||
onScroll,
|
||||
headerHeight,
|
||||
isFocused,
|
||||
isScrolledDown,
|
||||
scrollElRef,
|
||||
}) => (
|
||||
? ({headerHeight, isFocused, scrollElRef}) => (
|
||||
<FeedSection
|
||||
ref={likesSectionRef}
|
||||
feed={`likes|${profile.did}`}
|
||||
onScroll={onScroll}
|
||||
headerHeight={headerHeight}
|
||||
isFocused={isFocused}
|
||||
isScrolledDown={isScrolledDown}
|
||||
scrollElRef={
|
||||
scrollElRef as React.MutableRefObject<FlatList<any> | null>
|
||||
}
|
||||
scrollElRef={scrollElRef as ListRef}
|
||||
ignoreFilterFor={profile.did}
|
||||
/>
|
||||
)
|
||||
: null}
|
||||
{showFeedsTab
|
||||
? ({onScroll, headerHeight, isFocused, scrollElRef}) => (
|
||||
? ({headerHeight, isFocused, scrollElRef}) => (
|
||||
<ProfileFeedgens
|
||||
ref={feedsSectionRef}
|
||||
did={profile.did}
|
||||
scrollElRef={
|
||||
scrollElRef as React.MutableRefObject<FlatList<any> | null>
|
||||
}
|
||||
onScroll={onScroll}
|
||||
scrollEventThrottle={1}
|
||||
scrollElRef={scrollElRef as ListRef}
|
||||
headerOffset={headerHeight}
|
||||
enabled={isFocused}
|
||||
/>
|
||||
)
|
||||
: null}
|
||||
{showListsTab
|
||||
? ({onScroll, headerHeight, isFocused, scrollElRef}) => (
|
||||
? ({headerHeight, isFocused, scrollElRef}) => (
|
||||
<ProfileLists
|
||||
ref={listsSectionRef}
|
||||
did={profile.did}
|
||||
scrollElRef={
|
||||
scrollElRef as React.MutableRefObject<FlatList<any> | null>
|
||||
}
|
||||
onScroll={onScroll}
|
||||
scrollEventThrottle={1}
|
||||
scrollElRef={scrollElRef as ListRef}
|
||||
headerOffset={headerHeight}
|
||||
enabled={isFocused}
|
||||
/>
|
||||
@@ -396,28 +360,19 @@ function ProfileScreenLoaded({
|
||||
|
||||
interface FeedSectionProps {
|
||||
feed: FeedDescriptor
|
||||
onScroll: OnScrollHandler
|
||||
headerHeight: number
|
||||
isFocused: boolean
|
||||
isScrolledDown: boolean
|
||||
scrollElRef: React.MutableRefObject<FlatList<any> | null>
|
||||
scrollElRef: ListRef
|
||||
ignoreFilterFor?: string
|
||||
}
|
||||
const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
|
||||
function FeedSectionImpl(
|
||||
{
|
||||
feed,
|
||||
onScroll,
|
||||
headerHeight,
|
||||
isFocused,
|
||||
isScrolledDown,
|
||||
scrollElRef,
|
||||
ignoreFilterFor,
|
||||
},
|
||||
{feed, headerHeight, isFocused, scrollElRef, ignoreFilterFor},
|
||||
ref,
|
||||
) {
|
||||
const queryClient = useQueryClient()
|
||||
const [hasNew, setHasNew] = React.useState(false)
|
||||
const [isScrolledDown, setIsScrolledDown] = React.useState(false)
|
||||
|
||||
const onScrollToTop = React.useCallback(() => {
|
||||
scrollElRef.current?.scrollToOffset({
|
||||
@@ -443,8 +398,7 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
|
||||
feed={feed}
|
||||
scrollElRef={scrollElRef}
|
||||
onHasNew={setHasNew}
|
||||
onScroll={onScroll}
|
||||
scrollEventThrottle={1}
|
||||
onScrolledDownChange={setIsScrolledDown}
|
||||
renderEmptyState={renderPostsEmpty}
|
||||
headerOffset={headerHeight}
|
||||
renderEndOfFeed={ProfileEndOfFeed}
|
||||
|
||||
@@ -1,25 +1,20 @@
|
||||
import React, {useMemo, useCallback} from 'react'
|
||||
import {
|
||||
Dimensions,
|
||||
StyleSheet,
|
||||
View,
|
||||
ActivityIndicator,
|
||||
FlatList,
|
||||
} from 'react-native'
|
||||
import {Dimensions, StyleSheet, View, ActivityIndicator} from 'react-native'
|
||||
import {NativeStackScreenProps} from '@react-navigation/native-stack'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
import {useIsFocused, useNavigation} from '@react-navigation/native'
|
||||
import {useQueryClient} from '@tanstack/react-query'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {HeartIcon, HeartIconSolid} from 'lib/icons'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
import {CommonNavigatorParams} from 'lib/routes/types'
|
||||
import {makeRecordUri} from 'lib/strings/url-helpers'
|
||||
import {colors, s} from 'lib/styles'
|
||||
import {s} from 'lib/styles'
|
||||
import {FeedDescriptor} from '#/state/queries/post-feed'
|
||||
import {PagerWithHeader} from 'view/com/pager/PagerWithHeader'
|
||||
import {ProfileSubpageHeader} from 'view/com/profile/ProfileSubpageHeader'
|
||||
import {Feed} from 'view/com/posts/Feed'
|
||||
import {TextLink} from 'view/com/util/Link'
|
||||
import {ListRef} from 'view/com/util/List'
|
||||
import {Button} from 'view/com/util/forms/Button'
|
||||
import {Text} from 'view/com/util/text/Text'
|
||||
import {RichText} from 'view/com/util/text/RichText'
|
||||
@@ -29,12 +24,13 @@ import {EmptyState} from 'view/com/util/EmptyState'
|
||||
import * as Toast from 'view/com/util/Toast'
|
||||
import {useSetTitle} from 'lib/hooks/useSetTitle'
|
||||
import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed'
|
||||
import {OnScrollHandler} from 'lib/hooks/useOnMainScroll'
|
||||
import {shareUrl} from 'lib/sharing'
|
||||
import {toShareUrl} from 'lib/strings/url-helpers'
|
||||
import {Haptics} from 'lib/haptics'
|
||||
import {useAnalytics} from 'lib/analytics/analytics'
|
||||
import {NativeDropdown, DropdownItem} from 'view/com/util/forms/NativeDropdown'
|
||||
import {useScrollHandlers} from '#/lib/ScrollContext'
|
||||
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
||||
import {makeCustomFeedLink} from 'lib/routes/links'
|
||||
import {pluralize} from 'lib/strings/helpers'
|
||||
import {CenteredView, ScrollView} from 'view/com/util/Views'
|
||||
@@ -46,12 +42,7 @@ import {logger} from '#/logger'
|
||||
import {Trans, msg} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {useAnimatedScrollHandler} from '#/lib/hooks/useAnimatedScrollHandler_FIXED'
|
||||
import {
|
||||
useFeedSourceInfoQuery,
|
||||
FeedSourceFeedInfo,
|
||||
useIsFeedPublicQuery,
|
||||
} from '#/state/queries/feed'
|
||||
import {useFeedSourceInfoQuery, FeedSourceFeedInfo} from '#/state/queries/feed'
|
||||
import {useResolveUriQuery} from '#/state/queries/resolve-uri'
|
||||
import {
|
||||
UsePreferencesQueryResponse,
|
||||
@@ -137,10 +128,8 @@ export function ProfileFeedScreen(props: Props) {
|
||||
function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) {
|
||||
const {data: preferences} = usePreferencesQuery()
|
||||
const {data: info} = useFeedSourceInfoQuery({uri: feedUri})
|
||||
const {isLoading: isPublicStatusLoading, data: isPublicResponse} =
|
||||
useIsFeedPublicQuery({uri: feedUri})
|
||||
|
||||
if (!preferences || !info || isPublicStatusLoading) {
|
||||
if (!preferences || !info) {
|
||||
return (
|
||||
<CenteredView>
|
||||
<View style={s.p20}>
|
||||
@@ -154,7 +143,6 @@ function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) {
|
||||
<ProfileFeedScreenInner
|
||||
preferences={preferences}
|
||||
feedInfo={info as FeedSourceFeedInfo}
|
||||
isPublicResponse={isPublicResponse}
|
||||
/>
|
||||
)
|
||||
}
|
||||
@@ -162,11 +150,9 @@ function ProfileFeedScreenIntermediate({feedUri}: {feedUri: string}) {
|
||||
export function ProfileFeedScreenInner({
|
||||
preferences,
|
||||
feedInfo,
|
||||
isPublicResponse,
|
||||
}: {
|
||||
preferences: UsePreferencesQueryResponse
|
||||
feedInfo: FeedSourceFeedInfo
|
||||
isPublicResponse: ReturnType<typeof useIsFeedPublicQuery>['data']
|
||||
}) {
|
||||
const {_} = useLingui()
|
||||
const pal = usePalette('default')
|
||||
@@ -175,6 +161,7 @@ export function ProfileFeedScreenInner({
|
||||
const {openComposer} = useComposerControls()
|
||||
const {track} = useAnalytics()
|
||||
const feedSectionRef = React.useRef<SectionRef>(null)
|
||||
const isScreenFocused = useIsFocused()
|
||||
|
||||
const {
|
||||
mutateAsync: saveFeed,
|
||||
@@ -210,6 +197,9 @@ export function ProfileFeedScreenInner({
|
||||
|
||||
useSetTitle(feedInfo?.displayName)
|
||||
|
||||
// event handlers
|
||||
//
|
||||
|
||||
const onToggleSaved = React.useCallback(async () => {
|
||||
try {
|
||||
Haptics.default()
|
||||
@@ -403,32 +393,21 @@ export function ProfileFeedScreenInner({
|
||||
isHeaderReady={true}
|
||||
renderHeader={renderHeader}
|
||||
onCurrentPageSelected={onCurrentPageSelected}>
|
||||
{({onScroll, headerHeight, isScrolledDown, scrollElRef, isFocused}) =>
|
||||
isPublicResponse?.isPublic ? (
|
||||
<FeedSection
|
||||
ref={feedSectionRef}
|
||||
feed={`feedgen|${feedInfo.uri}`}
|
||||
onScroll={onScroll}
|
||||
headerHeight={headerHeight}
|
||||
isScrolledDown={isScrolledDown}
|
||||
scrollElRef={
|
||||
scrollElRef as React.MutableRefObject<FlatList<any> | null>
|
||||
}
|
||||
isFocused={isFocused}
|
||||
/>
|
||||
) : (
|
||||
<CenteredView sideBorders style={[{paddingTop: headerHeight}]}>
|
||||
<NonPublicFeedMessage rawError={isPublicResponse?.error} />
|
||||
</CenteredView>
|
||||
)
|
||||
}
|
||||
{({onScroll, headerHeight, scrollElRef}) => (
|
||||
{({headerHeight, scrollElRef, isFocused}) => (
|
||||
<FeedSection
|
||||
ref={feedSectionRef}
|
||||
feed={`feedgen|${feedInfo.uri}`}
|
||||
headerHeight={headerHeight}
|
||||
scrollElRef={scrollElRef as ListRef}
|
||||
isFocused={isScreenFocused && isFocused}
|
||||
/>
|
||||
)}
|
||||
{({headerHeight, scrollElRef}) => (
|
||||
<AboutSection
|
||||
feedOwnerDid={feedInfo.creatorDid}
|
||||
feedRkey={feedInfo.route.params.rkey}
|
||||
feedInfo={feedInfo}
|
||||
headerHeight={headerHeight}
|
||||
onScroll={onScroll}
|
||||
scrollElRef={
|
||||
scrollElRef as React.MutableRefObject<ScrollView | null>
|
||||
}
|
||||
@@ -456,59 +435,16 @@ export function ProfileFeedScreenInner({
|
||||
)
|
||||
}
|
||||
|
||||
function NonPublicFeedMessage({rawError}: {rawError?: Error}) {
|
||||
const pal = usePalette('default')
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
pal.border,
|
||||
{
|
||||
padding: 18,
|
||||
borderTopWidth: 1,
|
||||
minHeight: Dimensions.get('window').height * 1.5,
|
||||
},
|
||||
]}>
|
||||
<View
|
||||
style={[
|
||||
pal.viewLight,
|
||||
{
|
||||
padding: 12,
|
||||
borderRadius: 8,
|
||||
gap: 12,
|
||||
},
|
||||
]}>
|
||||
<Text style={[pal.text]}>
|
||||
<Trans>
|
||||
Looks like this feed is only available to users with a Bluesky
|
||||
account. Please sign up or sign in to view this feed!
|
||||
</Trans>
|
||||
</Text>
|
||||
|
||||
{rawError?.message && (
|
||||
<Text style={pal.textLight}>
|
||||
<Trans>Message from server</Trans>: {rawError.message}
|
||||
</Text>
|
||||
)}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
interface FeedSectionProps {
|
||||
feed: FeedDescriptor
|
||||
onScroll: OnScrollHandler
|
||||
headerHeight: number
|
||||
isScrolledDown: boolean
|
||||
scrollElRef: React.MutableRefObject<FlatList<any> | null>
|
||||
scrollElRef: ListRef
|
||||
isFocused: boolean
|
||||
}
|
||||
const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
|
||||
function FeedSectionImpl(
|
||||
{feed, onScroll, headerHeight, isScrolledDown, scrollElRef, isFocused},
|
||||
ref,
|
||||
) {
|
||||
function FeedSectionImpl({feed, headerHeight, scrollElRef, isFocused}, ref) {
|
||||
const [hasNew, setHasNew] = React.useState(false)
|
||||
const [isScrolledDown, setIsScrolledDown] = React.useState(false)
|
||||
const queryClient = useQueryClient()
|
||||
|
||||
const onScrollToTop = useCallback(() => {
|
||||
@@ -533,11 +469,10 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
|
||||
<Feed
|
||||
enabled={isFocused}
|
||||
feed={feed}
|
||||
pollInterval={30e3}
|
||||
pollInterval={60e3}
|
||||
scrollElRef={scrollElRef}
|
||||
onHasNew={setHasNew}
|
||||
onScroll={onScroll}
|
||||
scrollEventThrottle={5}
|
||||
onScrolledDownChange={setIsScrolledDown}
|
||||
renderEmptyState={renderPostsEmpty}
|
||||
headerOffset={headerHeight}
|
||||
/>
|
||||
@@ -558,7 +493,6 @@ function AboutSection({
|
||||
feedRkey,
|
||||
feedInfo,
|
||||
headerHeight,
|
||||
onScroll,
|
||||
scrollElRef,
|
||||
isOwner,
|
||||
}: {
|
||||
@@ -566,13 +500,13 @@ function AboutSection({
|
||||
feedRkey: string
|
||||
feedInfo: FeedSourceFeedInfo
|
||||
headerHeight: number
|
||||
onScroll: OnScrollHandler
|
||||
scrollElRef: React.MutableRefObject<ScrollView | null>
|
||||
isOwner: boolean
|
||||
}) {
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const scrollHandler = useAnimatedScrollHandler(onScroll)
|
||||
const scrollHandlers = useScrollHandlers()
|
||||
const onScroll = useAnimatedScrollHandler(scrollHandlers)
|
||||
const [likeUri, setLikeUri] = React.useState(feedInfo.likeUri)
|
||||
const {hasSession} = useSession()
|
||||
const {track} = useAnalytics()
|
||||
@@ -608,12 +542,12 @@ function AboutSection({
|
||||
return (
|
||||
<ScrollView
|
||||
ref={scrollElRef}
|
||||
onScroll={onScroll}
|
||||
scrollEventThrottle={1}
|
||||
contentContainerStyle={{
|
||||
paddingTop: headerHeight,
|
||||
minHeight: Dimensions.get('window').height * 1.5,
|
||||
}}
|
||||
onScroll={scrollHandler}>
|
||||
}}>
|
||||
<View
|
||||
style={[
|
||||
{
|
||||
@@ -646,7 +580,7 @@ function AboutSection({
|
||||
onPress={onToggleLiked}
|
||||
style={{paddingHorizontal: 10}}>
|
||||
{isLiked ? (
|
||||
<HeartIconSolid size={19} style={styles.liked} />
|
||||
<HeartIconSolid size={19} style={s.likeColor} />
|
||||
) : (
|
||||
<HeartIcon strokeWidth={3} size={19} style={pal.textLight} />
|
||||
)}
|
||||
@@ -689,9 +623,6 @@ const styles = StyleSheet.create({
|
||||
borderRadius: 50,
|
||||
marginLeft: 6,
|
||||
},
|
||||
liked: {
|
||||
color: colors.red3,
|
||||
},
|
||||
notFoundContainer: {
|
||||
margin: 10,
|
||||
paddingHorizontal: 18,
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
import React, {useCallback, useMemo} from 'react'
|
||||
import {
|
||||
ActivityIndicator,
|
||||
FlatList,
|
||||
Pressable,
|
||||
StyleSheet,
|
||||
View,
|
||||
} from 'react-native'
|
||||
import {useFocusEffect} from '@react-navigation/native'
|
||||
import {ActivityIndicator, Pressable, StyleSheet, View} from 'react-native'
|
||||
import {useFocusEffect, useIsFocused} from '@react-navigation/native'
|
||||
import {NativeStackScreenProps, CommonNavigatorParams} from 'lib/routes/types'
|
||||
import {useNavigation} from '@react-navigation/native'
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-native-fontawesome'
|
||||
@@ -22,6 +16,7 @@ import {EmptyState} from 'view/com/util/EmptyState'
|
||||
import {RichText} from 'view/com/util/text/RichText'
|
||||
import {Button} from 'view/com/util/forms/Button'
|
||||
import {TextLink} from 'view/com/util/Link'
|
||||
import {ListRef} from 'view/com/util/List'
|
||||
import * as Toast from 'view/com/util/Toast'
|
||||
import {LoadLatestBtn} from 'view/com/util/load-latest/LoadLatestBtn'
|
||||
import {FAB} from 'view/com/util/fab/FAB'
|
||||
@@ -31,7 +26,6 @@ import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useSetTitle} from 'lib/hooks/useSetTitle'
|
||||
import {useWebMediaQueries} from 'lib/hooks/useWebMediaQueries'
|
||||
import {RQKEY as FEED_RQKEY} from '#/state/queries/post-feed'
|
||||
import {OnScrollHandler} from 'lib/hooks/useOnMainScroll'
|
||||
import {NavigationProp} from 'lib/routes/types'
|
||||
import {toShareUrl} from 'lib/strings/url-helpers'
|
||||
import {shareUrl} from 'lib/sharing'
|
||||
@@ -121,6 +115,7 @@ function ProfileListScreenLoaded({
|
||||
const aboutSectionRef = React.useRef<SectionRef>(null)
|
||||
const {openModal} = useModalControls()
|
||||
const isCurateList = list.purpose === 'app.bsky.graph.defs#curatelist'
|
||||
const isScreenFocused = useIsFocused()
|
||||
|
||||
useSetTitle(list.name)
|
||||
|
||||
@@ -165,36 +160,22 @@ function ProfileListScreenLoaded({
|
||||
isHeaderReady={true}
|
||||
renderHeader={renderHeader}
|
||||
onCurrentPageSelected={onCurrentPageSelected}>
|
||||
{({
|
||||
onScroll,
|
||||
headerHeight,
|
||||
isScrolledDown,
|
||||
scrollElRef,
|
||||
isFocused,
|
||||
}) => (
|
||||
{({headerHeight, scrollElRef, isFocused}) => (
|
||||
<FeedSection
|
||||
ref={feedSectionRef}
|
||||
feed={`list|${uri}`}
|
||||
scrollElRef={
|
||||
scrollElRef as React.MutableRefObject<FlatList<any> | null>
|
||||
}
|
||||
onScroll={onScroll}
|
||||
scrollElRef={scrollElRef as ListRef}
|
||||
headerHeight={headerHeight}
|
||||
isScrolledDown={isScrolledDown}
|
||||
isFocused={isFocused}
|
||||
isFocused={isScreenFocused && isFocused}
|
||||
/>
|
||||
)}
|
||||
{({onScroll, headerHeight, isScrolledDown, scrollElRef}) => (
|
||||
{({headerHeight, scrollElRef}) => (
|
||||
<AboutSection
|
||||
ref={aboutSectionRef}
|
||||
scrollElRef={
|
||||
scrollElRef as React.MutableRefObject<FlatList<any> | null>
|
||||
}
|
||||
scrollElRef={scrollElRef as ListRef}
|
||||
list={list}
|
||||
onPressAddUser={onPressAddUser}
|
||||
onScroll={onScroll}
|
||||
headerHeight={headerHeight}
|
||||
isScrolledDown={isScrolledDown}
|
||||
/>
|
||||
)}
|
||||
</PagerWithHeader>
|
||||
@@ -221,16 +202,12 @@ function ProfileListScreenLoaded({
|
||||
items={SECTION_TITLES_MOD}
|
||||
isHeaderReady={true}
|
||||
renderHeader={renderHeader}>
|
||||
{({onScroll, headerHeight, isScrolledDown, scrollElRef}) => (
|
||||
{({headerHeight, scrollElRef}) => (
|
||||
<AboutSection
|
||||
list={list}
|
||||
scrollElRef={
|
||||
scrollElRef as React.MutableRefObject<FlatList<any> | null>
|
||||
}
|
||||
scrollElRef={scrollElRef as ListRef}
|
||||
onPressAddUser={onPressAddUser}
|
||||
onScroll={onScroll}
|
||||
headerHeight={headerHeight}
|
||||
isScrolledDown={isScrolledDown}
|
||||
/>
|
||||
)}
|
||||
</PagerWithHeader>
|
||||
@@ -615,19 +592,15 @@ function Header({rkey, list}: {rkey: string; list: AppBskyGraphDefs.ListView}) {
|
||||
|
||||
interface FeedSectionProps {
|
||||
feed: FeedDescriptor
|
||||
onScroll: OnScrollHandler
|
||||
headerHeight: number
|
||||
isScrolledDown: boolean
|
||||
scrollElRef: React.MutableRefObject<FlatList<any> | null>
|
||||
scrollElRef: ListRef
|
||||
isFocused: boolean
|
||||
}
|
||||
const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
|
||||
function FeedSectionImpl(
|
||||
{feed, scrollElRef, onScroll, headerHeight, isScrolledDown, isFocused},
|
||||
ref,
|
||||
) {
|
||||
function FeedSectionImpl({feed, scrollElRef, headerHeight, isFocused}, ref) {
|
||||
const queryClient = useQueryClient()
|
||||
const [hasNew, setHasNew] = React.useState(false)
|
||||
const [isScrolledDown, setIsScrolledDown] = React.useState(false)
|
||||
|
||||
const onScrollToTop = useCallback(() => {
|
||||
scrollElRef.current?.scrollToOffset({
|
||||
@@ -651,11 +624,10 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
|
||||
testID="listFeed"
|
||||
enabled={isFocused}
|
||||
feed={feed}
|
||||
pollInterval={30e3}
|
||||
pollInterval={60e3}
|
||||
scrollElRef={scrollElRef}
|
||||
onHasNew={setHasNew}
|
||||
onScroll={onScroll}
|
||||
scrollEventThrottle={1}
|
||||
onScrolledDownChange={setIsScrolledDown}
|
||||
renderEmptyState={renderPostsEmpty}
|
||||
headerOffset={headerHeight}
|
||||
/>
|
||||
@@ -674,20 +646,19 @@ const FeedSection = React.forwardRef<SectionRef, FeedSectionProps>(
|
||||
interface AboutSectionProps {
|
||||
list: AppBskyGraphDefs.ListView
|
||||
onPressAddUser: () => void
|
||||
onScroll: OnScrollHandler
|
||||
headerHeight: number
|
||||
isScrolledDown: boolean
|
||||
scrollElRef: React.MutableRefObject<FlatList<any> | null>
|
||||
scrollElRef: ListRef
|
||||
}
|
||||
const AboutSection = React.forwardRef<SectionRef, AboutSectionProps>(
|
||||
function AboutSectionImpl(
|
||||
{list, onPressAddUser, onScroll, headerHeight, isScrolledDown, scrollElRef},
|
||||
{list, onPressAddUser, headerHeight, scrollElRef},
|
||||
ref,
|
||||
) {
|
||||
const pal = usePalette('default')
|
||||
const {_} = useLingui()
|
||||
const {isMobile} = useWebMediaQueries()
|
||||
const {currentAccount} = useSession()
|
||||
const [isScrolledDown, setIsScrolledDown] = React.useState(false)
|
||||
const isCurateList = list.purpose === 'app.bsky.graph.defs#curatelist'
|
||||
const isOwner = list.creator.did === currentAccount?.did
|
||||
|
||||
@@ -817,8 +788,7 @@ const AboutSection = React.forwardRef<SectionRef, AboutSectionProps>(
|
||||
renderHeader={renderHeader}
|
||||
renderEmptyState={renderEmptyState}
|
||||
headerOffset={headerHeight}
|
||||
onScroll={onScroll}
|
||||
scrollEventThrottle={1}
|
||||
onScrolledDownChange={setIsScrolledDown}
|
||||
/>
|
||||
{isScrolledDown && (
|
||||
<LoadLatestBtn
|
||||
|
||||
@@ -8,7 +8,8 @@ import {
|
||||
Pressable,
|
||||
Platform,
|
||||
} from 'react-native'
|
||||
import {FlatList, ScrollView, CenteredView} from '#/view/com/util/Views'
|
||||
import {ScrollView, CenteredView} from '#/view/com/util/Views'
|
||||
import {List} from '#/view/com/util/List'
|
||||
import {AppBskyActorDefs, AppBskyFeedDefs, moderateProfile} from '@atproto/api'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
@@ -155,7 +156,7 @@ function SearchScreenSuggestedFollows() {
|
||||
}, [currentAccount, setSuggestions, getSuggestedFollowsByActor])
|
||||
|
||||
return suggestions.length ? (
|
||||
<FlatList
|
||||
<List
|
||||
data={suggestions}
|
||||
renderItem={({item}) => <ProfileCardWithFollowBtn profile={item} noBg />}
|
||||
keyExtractor={item => item.did}
|
||||
@@ -243,7 +244,7 @@ function SearchScreenPostResults({query}: {query: string}) {
|
||||
{isFetched ? (
|
||||
<>
|
||||
{posts.length ? (
|
||||
<FlatList
|
||||
<List
|
||||
data={items}
|
||||
renderItem={({item}) => {
|
||||
if (item.type === 'post') {
|
||||
@@ -284,7 +285,7 @@ function SearchScreenUserResults({query}: {query: string}) {
|
||||
return isFetched && results ? (
|
||||
<>
|
||||
{results.length ? (
|
||||
<FlatList
|
||||
<List
|
||||
data={results}
|
||||
renderItem={({item}) => (
|
||||
<ProfileCardWithFollowBtn profile={item} noBg />
|
||||
@@ -303,7 +304,8 @@ function SearchScreenUserResults({query}: {query: string}) {
|
||||
)
|
||||
}
|
||||
|
||||
const SECTIONS = ['Posts', 'Users']
|
||||
const SECTIONS_LOGGEDOUT = ['Users']
|
||||
const SECTIONS_LOGGEDIN = ['Posts', 'Users']
|
||||
export function SearchScreenInner({query}: {query?: string}) {
|
||||
const pal = usePalette('default')
|
||||
const setMinimalShellMode = useSetMinimalShellMode()
|
||||
@@ -319,44 +321,62 @@ export function SearchScreenInner({query}: {query?: string}) {
|
||||
[setDrawerSwipeDisabled, setMinimalShellMode],
|
||||
)
|
||||
|
||||
if (hasSession) {
|
||||
return query ? (
|
||||
<Pager
|
||||
tabBarPosition="top"
|
||||
onPageSelected={onPageSelected}
|
||||
renderTabBar={props => (
|
||||
<CenteredView sideBorders style={pal.border}>
|
||||
<TabBar items={SECTIONS_LOGGEDIN} {...props} />
|
||||
</CenteredView>
|
||||
)}
|
||||
initialPage={0}>
|
||||
<View>
|
||||
<SearchScreenPostResults query={query} />
|
||||
</View>
|
||||
<View>
|
||||
<SearchScreenUserResults query={query} />
|
||||
</View>
|
||||
</Pager>
|
||||
) : (
|
||||
<View>
|
||||
<CenteredView sideBorders style={pal.border}>
|
||||
<Text
|
||||
type="title"
|
||||
style={[
|
||||
pal.text,
|
||||
pal.border,
|
||||
{
|
||||
display: 'flex',
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 18,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
]}>
|
||||
<Trans>Suggested Follows</Trans>
|
||||
</Text>
|
||||
</CenteredView>
|
||||
|
||||
<SearchScreenSuggestedFollows />
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
return query ? (
|
||||
<Pager
|
||||
tabBarPosition="top"
|
||||
onPageSelected={onPageSelected}
|
||||
renderTabBar={props => (
|
||||
<CenteredView sideBorders style={pal.border}>
|
||||
<TabBar items={SECTIONS} {...props} />
|
||||
<TabBar items={SECTIONS_LOGGEDOUT} {...props} />
|
||||
</CenteredView>
|
||||
)}
|
||||
initialPage={0}>
|
||||
<View>
|
||||
<SearchScreenPostResults query={query} />
|
||||
</View>
|
||||
<View>
|
||||
<SearchScreenUserResults query={query} />
|
||||
</View>
|
||||
</Pager>
|
||||
) : hasSession ? (
|
||||
<View>
|
||||
<CenteredView sideBorders style={pal.border}>
|
||||
<Text
|
||||
type="title"
|
||||
style={[
|
||||
pal.text,
|
||||
pal.border,
|
||||
{
|
||||
display: 'flex',
|
||||
paddingVertical: 12,
|
||||
paddingHorizontal: 18,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
]}>
|
||||
<Trans>Suggested Follows</Trans>
|
||||
</Text>
|
||||
</CenteredView>
|
||||
|
||||
<SearchScreenSuggestedFollows />
|
||||
</View>
|
||||
) : (
|
||||
<CenteredView sideBorders style={pal.border}>
|
||||
<View
|
||||
@@ -382,13 +402,27 @@ export function SearchScreenInner({query}: {query?: string}) {
|
||||
</Text>
|
||||
)}
|
||||
|
||||
<Text
|
||||
style={[
|
||||
pal.textLight,
|
||||
{textAlign: 'center', paddingVertical: 12, paddingHorizontal: 18},
|
||||
]}>
|
||||
<Trans>Search for posts and users.</Trans>
|
||||
</Text>
|
||||
<View
|
||||
style={{
|
||||
flexDirection: 'column',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
paddingVertical: 30,
|
||||
gap: 15,
|
||||
}}>
|
||||
<MagnifyingGlassIcon
|
||||
strokeWidth={3}
|
||||
size={isDesktop ? 60 : 60}
|
||||
style={pal.textLight}
|
||||
/>
|
||||
<Text type="xl" style={[pal.textLight, {paddingHorizontal: 18}]}>
|
||||
{isDesktop ? (
|
||||
<Trans>Find users with the search tool on the right</Trans>
|
||||
) : (
|
||||
<Trans>Find users on Bluesky</Trans>
|
||||
)}
|
||||
</Text>
|
||||
</View>
|
||||
</View>
|
||||
</CenteredView>
|
||||
)
|
||||
|
||||
@@ -221,19 +221,17 @@ let DrawerContent = ({}: {}): React.ReactNode => {
|
||||
<NavSignupCard />
|
||||
)}
|
||||
|
||||
{hasSession && <InviteCodes />}
|
||||
{hasSession && <View style={{height: 10}} />}
|
||||
<SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} />
|
||||
<HomeMenuItem isActive={isAtHome} onPress={onPressHome} />
|
||||
{hasSession && (
|
||||
<NotificationsMenuItem
|
||||
isActive={isAtNotifications}
|
||||
onPress={onPressNotifications}
|
||||
/>
|
||||
)}
|
||||
<FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} />
|
||||
{hasSession && (
|
||||
{hasSession ? (
|
||||
<>
|
||||
<InviteCodes />
|
||||
<View style={{height: 10}} />
|
||||
<SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} />
|
||||
<HomeMenuItem isActive={isAtHome} onPress={onPressHome} />
|
||||
<NotificationsMenuItem
|
||||
isActive={isAtNotifications}
|
||||
onPress={onPressNotifications}
|
||||
/>
|
||||
<FeedsMenuItem isActive={isAtFeeds} onPress={onPressMyFeeds} />
|
||||
<ListsMenuItem onPress={onPressLists} />
|
||||
<ModerationMenuItem onPress={onPressModeration} />
|
||||
<ProfileMenuItem
|
||||
@@ -242,6 +240,8 @@ let DrawerContent = ({}: {}): React.ReactNode => {
|
||||
/>
|
||||
<SettingsMenuItem onPress={onPressSettings} />
|
||||
</>
|
||||
) : (
|
||||
<SearchMenuItem isActive={isAtSearch} onPress={onPressSearch} />
|
||||
)}
|
||||
|
||||
<View style={styles.smallSpacer} />
|
||||
|
||||
@@ -5,22 +5,28 @@ import {useLingui} from '@lingui/react'
|
||||
|
||||
import {s} from 'lib/styles'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {DefaultAvatar} from '#/view/com/util/UserAvatar'
|
||||
import {Text} from '#/view/com/util/text/Text'
|
||||
import {Button} from '#/view/com/util/forms/Button'
|
||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||
import {useCloseAllActiveElements} from '#/state/util'
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
|
||||
let NavSignupCard = ({}: {}): React.ReactNode => {
|
||||
const {_} = useLingui()
|
||||
const pal = usePalette('default')
|
||||
const {setShowLoggedOut} = useLoggedOutViewControls()
|
||||
const {requestSwitchToAccount} = useLoggedOutViewControls()
|
||||
const closeAllActiveElements = useCloseAllActiveElements()
|
||||
|
||||
const showLoggedOut = React.useCallback(() => {
|
||||
const showSignIn = React.useCallback(() => {
|
||||
closeAllActiveElements()
|
||||
setShowLoggedOut(true)
|
||||
}, [setShowLoggedOut, closeAllActiveElements])
|
||||
requestSwitchToAccount({requestedAccount: 'none'})
|
||||
}, [requestSwitchToAccount, closeAllActiveElements])
|
||||
|
||||
const showCreateAccount = React.useCallback(() => {
|
||||
closeAllActiveElements()
|
||||
requestSwitchToAccount({requestedAccount: 'new'})
|
||||
// setShowLoggedOut(true)
|
||||
}, [requestSwitchToAccount, closeAllActiveElements])
|
||||
|
||||
return (
|
||||
<View
|
||||
@@ -29,17 +35,17 @@ let NavSignupCard = ({}: {}): React.ReactNode => {
|
||||
paddingTop: 6,
|
||||
marginBottom: 24,
|
||||
}}>
|
||||
<DefaultAvatar type="user" size={48} />
|
||||
<Logo width={48} />
|
||||
|
||||
<View style={{paddingTop: 12}}>
|
||||
<Text type="md" style={[pal.text, s.bold]}>
|
||||
<View style={{paddingTop: 18}}>
|
||||
<Text type="md-bold" style={[pal.text]}>
|
||||
<Trans>Sign up or sign in to join the conversation</Trans>
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={{flexDirection: 'row', paddingTop: 12, gap: 8}}>
|
||||
<Button
|
||||
onPress={showLoggedOut}
|
||||
onPress={showCreateAccount}
|
||||
accessibilityHint={_(msg`Sign up`)}
|
||||
accessibilityLabel={_(msg`Sign up`)}>
|
||||
<Text type="md" style={[{color: 'white'}, s.bold]}>
|
||||
@@ -48,7 +54,7 @@ let NavSignupCard = ({}: {}): React.ReactNode => {
|
||||
</Button>
|
||||
<Button
|
||||
type="default"
|
||||
onPress={showLoggedOut}
|
||||
onPress={showSignIn}
|
||||
accessibilityHint={_(msg`Sign in`)}
|
||||
accessibilityLabel={_(msg`Sign in`)}>
|
||||
<Text type="md" style={[pal.text, s.bold]}>
|
||||
|
||||
@@ -23,13 +23,19 @@ import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
|
||||
import {useNavigationTabState} from 'lib/hooks/useNavigationTabState'
|
||||
import {UserAvatar} from 'view/com/util/UserAvatar'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {msg} from '@lingui/macro'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useModalControls} from '#/state/modals'
|
||||
import {useShellLayout} from '#/state/shell/shell-layout'
|
||||
import {useUnreadNotifications} from '#/state/queries/notifications/unread'
|
||||
import {emitSoftReset} from '#/state/events'
|
||||
import {useSession} from '#/state/session'
|
||||
import {useProfileQuery} from '#/state/queries/profile'
|
||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||
import {useCloseAllActiveElements} from '#/state/util'
|
||||
import {Button} from '#/view/com/util/forms/Button'
|
||||
import {s} from 'lib/styles'
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
import {Logotype} from '#/view/icons/Logotype'
|
||||
|
||||
type TabOptions = 'Home' | 'Search' | 'Notifications' | 'MyProfile' | 'Feeds'
|
||||
|
||||
@@ -46,6 +52,19 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
||||
const numUnreadNotifications = useUnreadNotifications()
|
||||
const {footerMinimalShellTransform} = useMinimalShellMode()
|
||||
const {data: profile} = useProfileQuery({did: currentAccount?.did})
|
||||
const {requestSwitchToAccount} = useLoggedOutViewControls()
|
||||
const closeAllActiveElements = useCloseAllActiveElements()
|
||||
|
||||
const showSignIn = React.useCallback(() => {
|
||||
closeAllActiveElements()
|
||||
requestSwitchToAccount({requestedAccount: 'none'})
|
||||
}, [requestSwitchToAccount, closeAllActiveElements])
|
||||
|
||||
const showCreateAccount = React.useCallback(() => {
|
||||
closeAllActiveElements()
|
||||
requestSwitchToAccount({requestedAccount: 'new'})
|
||||
// setShowLoggedOut(true)
|
||||
}, [requestSwitchToAccount, closeAllActiveElements])
|
||||
|
||||
const onPressTab = React.useCallback(
|
||||
(tab: TabOptions) => {
|
||||
@@ -94,75 +113,74 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
||||
onLayout={e => {
|
||||
footerHeight.value = e.nativeEvent.layout.height
|
||||
}}>
|
||||
<Btn
|
||||
testID="bottomBarHomeBtn"
|
||||
icon={
|
||||
isAtHome ? (
|
||||
<HomeIconSolid
|
||||
strokeWidth={4}
|
||||
size={24}
|
||||
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
||||
/>
|
||||
) : (
|
||||
<HomeIcon
|
||||
strokeWidth={4}
|
||||
size={24}
|
||||
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
onPress={onPressHome}
|
||||
accessibilityRole="tab"
|
||||
accessibilityLabel={_(msg`Home`)}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
<Btn
|
||||
testID="bottomBarSearchBtn"
|
||||
icon={
|
||||
isAtSearch ? (
|
||||
<MagnifyingGlassIcon2Solid
|
||||
size={25}
|
||||
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
||||
strokeWidth={1.8}
|
||||
/>
|
||||
) : (
|
||||
<MagnifyingGlassIcon2
|
||||
size={25}
|
||||
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
||||
strokeWidth={1.8}
|
||||
/>
|
||||
)
|
||||
}
|
||||
onPress={onPressSearch}
|
||||
accessibilityRole="search"
|
||||
accessibilityLabel={_(msg`Search`)}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
<Btn
|
||||
testID="bottomBarFeedsBtn"
|
||||
icon={
|
||||
isAtFeeds ? (
|
||||
<HashtagIcon
|
||||
size={24}
|
||||
style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
|
||||
strokeWidth={4}
|
||||
/>
|
||||
) : (
|
||||
<HashtagIcon
|
||||
size={24}
|
||||
style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
|
||||
strokeWidth={2.25}
|
||||
/>
|
||||
)
|
||||
}
|
||||
onPress={onPressFeeds}
|
||||
accessibilityRole="tab"
|
||||
accessibilityLabel={_(msg`Feeds`)}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
|
||||
{hasSession && (
|
||||
{hasSession ? (
|
||||
<>
|
||||
<Btn
|
||||
testID="bottomBarHomeBtn"
|
||||
icon={
|
||||
isAtHome ? (
|
||||
<HomeIconSolid
|
||||
strokeWidth={4}
|
||||
size={24}
|
||||
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
||||
/>
|
||||
) : (
|
||||
<HomeIcon
|
||||
strokeWidth={4}
|
||||
size={24}
|
||||
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
||||
/>
|
||||
)
|
||||
}
|
||||
onPress={onPressHome}
|
||||
accessibilityRole="tab"
|
||||
accessibilityLabel={_(msg`Home`)}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
<Btn
|
||||
testID="bottomBarSearchBtn"
|
||||
icon={
|
||||
isAtSearch ? (
|
||||
<MagnifyingGlassIcon2Solid
|
||||
size={25}
|
||||
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
||||
strokeWidth={1.8}
|
||||
/>
|
||||
) : (
|
||||
<MagnifyingGlassIcon2
|
||||
size={25}
|
||||
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
||||
strokeWidth={1.8}
|
||||
/>
|
||||
)
|
||||
}
|
||||
onPress={onPressSearch}
|
||||
accessibilityRole="search"
|
||||
accessibilityLabel={_(msg`Search`)}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
<Btn
|
||||
testID="bottomBarFeedsBtn"
|
||||
icon={
|
||||
isAtFeeds ? (
|
||||
<HashtagIcon
|
||||
size={24}
|
||||
style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
|
||||
strokeWidth={4}
|
||||
/>
|
||||
) : (
|
||||
<HashtagIcon
|
||||
size={24}
|
||||
style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
|
||||
strokeWidth={2.25}
|
||||
/>
|
||||
)
|
||||
}
|
||||
onPress={onPressFeeds}
|
||||
accessibilityRole="tab"
|
||||
accessibilityLabel={_(msg`Feeds`)}
|
||||
accessibilityHint=""
|
||||
/>
|
||||
<Btn
|
||||
testID="bottomBarNotificationsBtn"
|
||||
icon={
|
||||
@@ -230,6 +248,49 @@ export function BottomBar({navigation}: BottomTabBarProps) {
|
||||
accessibilityHint=""
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<View
|
||||
style={{
|
||||
width: '100%',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingTop: 14,
|
||||
paddingBottom: 2,
|
||||
paddingLeft: 14,
|
||||
paddingRight: 6,
|
||||
gap: 8,
|
||||
}}>
|
||||
<View style={{flexDirection: 'row', alignItems: 'center', gap: 8}}>
|
||||
<Logo width={28} />
|
||||
<View style={{paddingTop: 4}}>
|
||||
<Logotype width={80} fill={pal.text.color} />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={{flexDirection: 'row', alignItems: 'center', gap: 4}}>
|
||||
<Button
|
||||
onPress={showCreateAccount}
|
||||
accessibilityHint={_(msg`Sign up`)}
|
||||
accessibilityLabel={_(msg`Sign up`)}>
|
||||
<Text type="md" style={[{color: 'white'}, s.bold]}>
|
||||
<Trans>Sign up</Trans>
|
||||
</Text>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="default"
|
||||
onPress={showSignIn}
|
||||
accessibilityHint={_(msg`Sign in`)}
|
||||
accessibilityLabel={_(msg`Sign in`)}>
|
||||
<Text type="md" style={[pal.text, s.bold]}>
|
||||
<Trans>Sign in</Trans>
|
||||
</Text>
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
</Animated.View>
|
||||
)
|
||||
|
||||
@@ -3,6 +3,9 @@ import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {useNavigationState} from '@react-navigation/native'
|
||||
import Animated from 'react-native-reanimated'
|
||||
import {useSafeAreaInsets} from 'react-native-safe-area-context'
|
||||
import {View} from 'react-native'
|
||||
import {msg, Trans} from '@lingui/macro'
|
||||
import {useLingui} from '@lingui/react'
|
||||
import {getCurrentRoute, isTab} from 'lib/routes/helpers'
|
||||
import {styles} from './BottomBarStyles'
|
||||
import {clamp} from 'lib/numbers'
|
||||
@@ -22,12 +25,33 @@ import {useMinimalShellMode} from 'lib/hooks/useMinimalShellMode'
|
||||
import {makeProfileLink} from 'lib/routes/links'
|
||||
import {CommonNavigatorParams} from 'lib/routes/types'
|
||||
import {useSession} from '#/state/session'
|
||||
import {useLoggedOutViewControls} from '#/state/shell/logged-out'
|
||||
import {useCloseAllActiveElements} from '#/state/util'
|
||||
import {Button} from '#/view/com/util/forms/Button'
|
||||
import {Text} from '#/view/com/util/text/Text'
|
||||
import {s} from 'lib/styles'
|
||||
import {Logo} from '#/view/icons/Logo'
|
||||
import {Logotype} from '#/view/icons/Logotype'
|
||||
|
||||
export function BottomBarWeb() {
|
||||
const {_} = useLingui()
|
||||
const {hasSession, currentAccount} = useSession()
|
||||
const pal = usePalette('default')
|
||||
const safeAreaInsets = useSafeAreaInsets()
|
||||
const {footerMinimalShellTransform} = useMinimalShellMode()
|
||||
const {requestSwitchToAccount} = useLoggedOutViewControls()
|
||||
const closeAllActiveElements = useCloseAllActiveElements()
|
||||
|
||||
const showSignIn = React.useCallback(() => {
|
||||
closeAllActiveElements()
|
||||
requestSwitchToAccount({requestedAccount: 'none'})
|
||||
}, [requestSwitchToAccount, closeAllActiveElements])
|
||||
|
||||
const showCreateAccount = React.useCallback(() => {
|
||||
closeAllActiveElements()
|
||||
requestSwitchToAccount({requestedAccount: 'new'})
|
||||
// setShowLoggedOut(true)
|
||||
}, [requestSwitchToAccount, closeAllActiveElements])
|
||||
|
||||
return (
|
||||
<Animated.View
|
||||
@@ -38,79 +62,126 @@ export function BottomBarWeb() {
|
||||
{paddingBottom: clamp(safeAreaInsets.bottom, 15, 30)},
|
||||
footerMinimalShellTransform,
|
||||
]}>
|
||||
<NavItem routeName="Home" href="/">
|
||||
{({isActive}) => {
|
||||
const Icon = isActive ? HomeIconSolid : HomeIcon
|
||||
return (
|
||||
<Icon
|
||||
strokeWidth={4}
|
||||
size={24}
|
||||
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
</NavItem>
|
||||
<NavItem routeName="Search" href="/search">
|
||||
{({isActive}) => {
|
||||
const Icon = isActive
|
||||
? MagnifyingGlassIcon2Solid
|
||||
: MagnifyingGlassIcon2
|
||||
return (
|
||||
<Icon
|
||||
size={25}
|
||||
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
||||
strokeWidth={1.8}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
</NavItem>
|
||||
<NavItem routeName="Feeds" href="/feeds">
|
||||
{({isActive}) => {
|
||||
return (
|
||||
<HashtagIcon
|
||||
size={22}
|
||||
style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
|
||||
strokeWidth={isActive ? 4 : 2.5}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
</NavItem>
|
||||
|
||||
{hasSession && (
|
||||
{hasSession ? (
|
||||
<>
|
||||
<NavItem routeName="Notifications" href="/notifications">
|
||||
<NavItem routeName="Home" href="/">
|
||||
{({isActive}) => {
|
||||
const Icon = isActive ? BellIconSolid : BellIcon
|
||||
const Icon = isActive ? HomeIconSolid : HomeIcon
|
||||
return (
|
||||
<Icon
|
||||
strokeWidth={4}
|
||||
size={24}
|
||||
strokeWidth={1.9}
|
||||
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
|
||||
style={[styles.ctrlIcon, pal.text, styles.homeIcon]}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
</NavItem>
|
||||
<NavItem
|
||||
routeName="Profile"
|
||||
href={
|
||||
currentAccount
|
||||
? makeProfileLink({
|
||||
did: currentAccount.did,
|
||||
handle: currentAccount.handle,
|
||||
})
|
||||
: '/'
|
||||
}>
|
||||
<NavItem routeName="Search" href="/search">
|
||||
{({isActive}) => {
|
||||
const Icon = isActive ? UserIconSolid : UserIcon
|
||||
const Icon = isActive
|
||||
? MagnifyingGlassIcon2Solid
|
||||
: MagnifyingGlassIcon2
|
||||
return (
|
||||
<Icon
|
||||
size={28}
|
||||
strokeWidth={1.5}
|
||||
style={[styles.ctrlIcon, pal.text, styles.profileIcon]}
|
||||
size={25}
|
||||
style={[styles.ctrlIcon, pal.text, styles.searchIcon]}
|
||||
strokeWidth={1.8}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
</NavItem>
|
||||
|
||||
{hasSession && (
|
||||
<>
|
||||
<NavItem routeName="Feeds" href="/feeds">
|
||||
{({isActive}) => {
|
||||
return (
|
||||
<HashtagIcon
|
||||
size={22}
|
||||
style={[styles.ctrlIcon, pal.text, styles.feedsIcon]}
|
||||
strokeWidth={isActive ? 4 : 2.5}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
</NavItem>
|
||||
<NavItem routeName="Notifications" href="/notifications">
|
||||
{({isActive}) => {
|
||||
const Icon = isActive ? BellIconSolid : BellIcon
|
||||
return (
|
||||
<Icon
|
||||
size={24}
|
||||
strokeWidth={1.9}
|
||||
style={[styles.ctrlIcon, pal.text, styles.bellIcon]}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
</NavItem>
|
||||
<NavItem
|
||||
routeName="Profile"
|
||||
href={
|
||||
currentAccount
|
||||
? makeProfileLink({
|
||||
did: currentAccount.did,
|
||||
handle: currentAccount.handle,
|
||||
})
|
||||
: '/'
|
||||
}>
|
||||
{({isActive}) => {
|
||||
const Icon = isActive ? UserIconSolid : UserIcon
|
||||
return (
|
||||
<Icon
|
||||
size={28}
|
||||
strokeWidth={1.5}
|
||||
style={[styles.ctrlIcon, pal.text, styles.profileIcon]}
|
||||
/>
|
||||
)
|
||||
}}
|
||||
</NavItem>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<View
|
||||
style={{
|
||||
width: '100%',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'space-between',
|
||||
paddingTop: 14,
|
||||
paddingBottom: 2,
|
||||
paddingLeft: 14,
|
||||
paddingRight: 6,
|
||||
gap: 8,
|
||||
}}>
|
||||
<View style={{flexDirection: 'row', alignItems: 'center', gap: 12}}>
|
||||
<Logo width={32} />
|
||||
<View style={{paddingTop: 4}}>
|
||||
<Logotype width={80} fill={pal.text.color} />
|
||||
</View>
|
||||
</View>
|
||||
|
||||
<View style={{flexDirection: 'row', alignItems: 'center', gap: 8}}>
|
||||
<Button
|
||||
onPress={showCreateAccount}
|
||||
accessibilityHint={_(msg`Sign up`)}
|
||||
accessibilityLabel={_(msg`Sign up`)}>
|
||||
<Text type="md" style={[{color: 'white'}, s.bold]}>
|
||||
<Trans>Sign up</Trans>
|
||||
</Text>
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
type="default"
|
||||
onPress={showSignIn}
|
||||
accessibilityHint={_(msg`Sign in`)}
|
||||
accessibilityLabel={_(msg`Sign in`)}>
|
||||
<Text type="md" style={[pal.text, s.bold]}>
|
||||
<Trans>Sign in</Trans>
|
||||
</Text>
|
||||
</Button>
|
||||
</View>
|
||||
</View>
|
||||
</>
|
||||
)}
|
||||
</Animated.View>
|
||||
|
||||
@@ -266,6 +266,10 @@ export function DesktopLeftNav() {
|
||||
const {isDesktop, isTablet} = useWebMediaQueries()
|
||||
const numUnread = useUnreadNotifications()
|
||||
|
||||
if (!hasSession && !isDesktop) {
|
||||
return null
|
||||
}
|
||||
|
||||
return (
|
||||
<View
|
||||
style={[
|
||||
@@ -282,59 +286,58 @@ export function DesktopLeftNav() {
|
||||
</View>
|
||||
) : null}
|
||||
|
||||
<BackBtn />
|
||||
|
||||
<NavItem
|
||||
href="/"
|
||||
icon={<HomeIcon size={isDesktop ? 24 : 28} style={pal.text} />}
|
||||
iconFilled={
|
||||
<HomeIconSolid
|
||||
strokeWidth={4}
|
||||
size={isDesktop ? 24 : 28}
|
||||
style={pal.text}
|
||||
/>
|
||||
}
|
||||
label={_(msg`Home`)}
|
||||
/>
|
||||
<NavItem
|
||||
href="/search"
|
||||
icon={
|
||||
<MagnifyingGlassIcon2
|
||||
strokeWidth={2}
|
||||
size={isDesktop ? 24 : 26}
|
||||
style={pal.text}
|
||||
/>
|
||||
}
|
||||
iconFilled={
|
||||
<MagnifyingGlassIcon2Solid
|
||||
strokeWidth={2}
|
||||
size={isDesktop ? 24 : 26}
|
||||
style={pal.text}
|
||||
/>
|
||||
}
|
||||
label={_(msg`Search`)}
|
||||
/>
|
||||
<NavItem
|
||||
href="/feeds"
|
||||
icon={
|
||||
<HashtagIcon
|
||||
strokeWidth={2.25}
|
||||
style={pal.text as FontAwesomeIconStyle}
|
||||
size={isDesktop ? 24 : 28}
|
||||
/>
|
||||
}
|
||||
iconFilled={
|
||||
<HashtagIcon
|
||||
strokeWidth={2.5}
|
||||
style={pal.text as FontAwesomeIconStyle}
|
||||
size={isDesktop ? 24 : 28}
|
||||
/>
|
||||
}
|
||||
label={_(msg`Feeds`)}
|
||||
/>
|
||||
|
||||
{hasSession && (
|
||||
<>
|
||||
<BackBtn />
|
||||
|
||||
<NavItem
|
||||
href="/"
|
||||
icon={<HomeIcon size={isDesktop ? 24 : 28} style={pal.text} />}
|
||||
iconFilled={
|
||||
<HomeIconSolid
|
||||
strokeWidth={4}
|
||||
size={isDesktop ? 24 : 28}
|
||||
style={pal.text}
|
||||
/>
|
||||
}
|
||||
label={_(msg`Home`)}
|
||||
/>
|
||||
<NavItem
|
||||
href="/search"
|
||||
icon={
|
||||
<MagnifyingGlassIcon2
|
||||
strokeWidth={2}
|
||||
size={isDesktop ? 24 : 26}
|
||||
style={pal.text}
|
||||
/>
|
||||
}
|
||||
iconFilled={
|
||||
<MagnifyingGlassIcon2Solid
|
||||
strokeWidth={2}
|
||||
size={isDesktop ? 24 : 26}
|
||||
style={pal.text}
|
||||
/>
|
||||
}
|
||||
label={_(msg`Search`)}
|
||||
/>
|
||||
<NavItem
|
||||
href="/feeds"
|
||||
icon={
|
||||
<HashtagIcon
|
||||
strokeWidth={2.25}
|
||||
style={pal.text as FontAwesomeIconStyle}
|
||||
size={isDesktop ? 24 : 28}
|
||||
/>
|
||||
}
|
||||
iconFilled={
|
||||
<HashtagIcon
|
||||
strokeWidth={2.5}
|
||||
style={pal.text as FontAwesomeIconStyle}
|
||||
size={isDesktop ? 24 : 28}
|
||||
/>
|
||||
}
|
||||
label={_(msg`Feeds`)}
|
||||
/>
|
||||
<NavItem
|
||||
href="/notifications"
|
||||
count={numUnread}
|
||||
@@ -406,7 +409,7 @@ export function DesktopLeftNav() {
|
||||
style={pal.text}
|
||||
/>
|
||||
}
|
||||
label="Profile"
|
||||
label={_(msg`Profile`)}
|
||||
/>
|
||||
<NavItem
|
||||
href="/settings"
|
||||
@@ -512,7 +515,6 @@ const styles = StyleSheet.create({
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
width: 140,
|
||||
borderRadius: 24,
|
||||
paddingTop: 10,
|
||||
paddingBottom: 12, // visually aligns the text vertically inside the button
|
||||
|
||||
@@ -52,7 +52,7 @@ export function DesktopRightNav() {
|
||||
</Text>
|
||||
</View>
|
||||
) : undefined}
|
||||
<View style={[s.flexRow]}>
|
||||
<View style={[{flexWrap: 'wrap'}, s.flexRow]}>
|
||||
{hasSession && (
|
||||
<>
|
||||
<TextLink
|
||||
|
||||
@@ -19,10 +19,6 @@ import {useTheme} from 'lib/ThemeContext'
|
||||
import {usePalette} from 'lib/hooks/usePalette'
|
||||
import {RoutesContainer, TabsNavigator} from '../../Navigation'
|
||||
import {isStateAtTabRoot} from 'lib/routes/helpers'
|
||||
import {
|
||||
SafeAreaProvider,
|
||||
initialWindowMetrics,
|
||||
} from 'react-native-safe-area-context'
|
||||
import {
|
||||
useIsDrawerOpen,
|
||||
useSetDrawerOpen,
|
||||
@@ -107,14 +103,12 @@ export const Shell: React.FC = function ShellImpl() {
|
||||
const pal = usePalette('default')
|
||||
const theme = useTheme()
|
||||
return (
|
||||
<SafeAreaProvider initialMetrics={initialWindowMetrics} style={pal.view}>
|
||||
<View testID="mobileShellView" style={[styles.outerContainer, pal.view]}>
|
||||
<StatusBar style={theme.colorScheme === 'dark' ? 'light' : 'dark'} />
|
||||
<RoutesContainer>
|
||||
<ShellInner />
|
||||
</RoutesContainer>
|
||||
</View>
|
||||
</SafeAreaProvider>
|
||||
<View testID="mobileShellView" style={[styles.outerContainer, pal.view]}>
|
||||
<StatusBar style={theme.colorScheme === 'dark' ? 'light' : 'dark'} />
|
||||
<RoutesContainer>
|
||||
<ShellInner />
|
||||
</RoutesContainer>
|
||||
</View>
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -48,10 +48,10 @@
|
||||
typed-emitter "^2.1.0"
|
||||
zod "^3.21.4"
|
||||
|
||||
"@atproto/api@^0.7.3":
|
||||
version "0.7.3"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.7.3.tgz#3224000353619970d5e397a157c6e189e195ef47"
|
||||
integrity sha512-fKU+W+S4kKxClE6IcPBHPZAjcyBYxG28S0FW/bv3T/ZYDkNxGzDV4xuoHOyEDGtB30slltl5U83njuuRZs5xtw==
|
||||
"@atproto/api@^0.7.4":
|
||||
version "0.7.4"
|
||||
resolved "https://registry.yarnpkg.com/@atproto/api/-/api-0.7.4.tgz#0dd6e725c88d1f941c57670dc82b60fde10f4ec6"
|
||||
integrity sha512-7DBy6/OcXemzCPzA0dx52LLYRABBs8bq9Docs3is+WRgEx5/Pd1kHSAlCHIaBhsym8fZ3/U4Fks/5FSHkSm4yQ==
|
||||
dependencies:
|
||||
"@atproto/common-web" "^0.2.3"
|
||||
"@atproto/lexicon" "^0.3.1"
|
||||
@@ -4448,6 +4448,11 @@
|
||||
resolved "https://registry.yarnpkg.com/@react-native-community/eslint-plugin/-/eslint-plugin-1.3.0.tgz#9e558170c106bbafaa1ef502bd8e6d4651012bf9"
|
||||
integrity sha512-+zDZ20NUnSWghj7Ku5aFphMzuM9JulqCW+aPXT6IfIXFbb8tzYTTOSeRFOtuekJ99ibW2fUCSsjuKNlwDIbHFg==
|
||||
|
||||
"@react-native-masked-view/masked-view@^0.3.1":
|
||||
version "0.3.1"
|
||||
resolved "https://registry.yarnpkg.com/@react-native-masked-view/masked-view/-/masked-view-0.3.1.tgz#5bd76f17004a6ccbcec03856893777ee91f23d29"
|
||||
integrity sha512-uVm8U6nwFIlUd1iDIB5cS+lDadApKR+l8k4k84d9hn+GN4lzAIJhUZ9syYX7c022MxNgAlbxoFLt0pqKoyaAGg==
|
||||
|
||||
"@react-native-menu/menu@^0.8.0":
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@react-native-menu/menu/-/menu-0.8.0.tgz#dbf227c2081e5ffd3d2073ee68ecc84cf8639727"
|
||||
|
||||